mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge branch 'release_24.2' into merge_24.2_into_dev
This commit is contained in:
@@ -260,9 +260,6 @@ function resetModal() {
|
||||
<BAlert v-else-if="!fromSelection && historyItemsError" variant="danger" show>
|
||||
{{ historyItemsError }}
|
||||
</BAlert>
|
||||
<BAlert v-else-if="!creatorItems?.length" variant="info" show>
|
||||
{{ localize("No items available to create a collection.") }}
|
||||
</BAlert>
|
||||
<BAlert v-else-if="creatingCollection" variant="info" show>
|
||||
<LoadingSpan :message="localize('Creating collection')" />
|
||||
</BAlert>
|
||||
@@ -289,7 +286,7 @@ function resetModal() {
|
||||
<ListCollectionCreator
|
||||
v-else-if="props.collectionType === 'list'"
|
||||
:history-id="props.historyId"
|
||||
:initial-elements="creatorItems"
|
||||
:initial-elements="creatorItems || []"
|
||||
:default-hide-source-items="props.defaultHideSourceItems"
|
||||
:from-selection="fromSelection"
|
||||
:extensions="props.extensions"
|
||||
@@ -298,7 +295,7 @@ function resetModal() {
|
||||
<PairedListCollectionCreator
|
||||
v-else-if="props.collectionType === 'list:paired'"
|
||||
:history-id="props.historyId"
|
||||
:initial-elements="creatorItems"
|
||||
:initial-elements="creatorItems || []"
|
||||
:default-hide-source-items="props.defaultHideSourceItems"
|
||||
:from-selection="fromSelection"
|
||||
:extensions="props.extensions"
|
||||
@@ -307,7 +304,7 @@ function resetModal() {
|
||||
<PairCollectionCreator
|
||||
v-else-if="props.collectionType === 'paired'"
|
||||
:history-id="props.historyId"
|
||||
:initial-elements="creatorItems"
|
||||
:initial-elements="creatorItems || []"
|
||||
:default-hide-source-items="props.defaultHideSourceItems"
|
||||
:from-selection="fromSelection"
|
||||
:extensions="props.extensions"
|
||||
|
||||
@@ -359,287 +359,273 @@ function renameElement(element: any, name: string) {
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="noInitialElements">
|
||||
<div v-if="fromSelection && returnInvalidElementsLength">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("No datasets were selected") }}
|
||||
{{ localize("At least one element is needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements.") }}
|
||||
</BAlert>
|
||||
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ localize("Cancel") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="allElementsAreInvalid">
|
||||
<BAlert v-if="!fromSelection" show variant="warning">
|
||||
{{
|
||||
localize(
|
||||
"No elements in your history are valid for this list. You may need to switch to a different history."
|
||||
)
|
||||
}}
|
||||
<span v-if="extensions?.length">
|
||||
{{ localize("The following extensions are required for this list: ") }}
|
||||
<ul>
|
||||
<li v-for="extension in extensions" :key="extension">
|
||||
{{ extension }}
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
</BAlert>
|
||||
<BAlert v-else show variant="warning" dismissible>
|
||||
{{ localize("The following selections could not be included due to problems:") }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ localize("At least one element is needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements.") }}
|
||||
</BAlert>
|
||||
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ localize("Cancel") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="fromSelection && returnInvalidElementsLength">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("The following selections could not be included due to problems:") }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
</BAlert>
|
||||
</div>
|
||||
|
||||
<div v-if="showDuplicateError">
|
||||
<BAlert show variant="danger">
|
||||
<div v-if="showDuplicateError">
|
||||
<BAlert show variant="danger">
|
||||
{{
|
||||
localize("Collections cannot have duplicated names. The following list names are duplicated: ")
|
||||
}}
|
||||
<ol>
|
||||
<li v-for="name in duplicateNames" :key="name">{{ name }}</li>
|
||||
</ol>
|
||||
{{ localize("Please fix these duplicates and try again.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
|
||||
<CollectionCreator
|
||||
:oncancel="() => emit('on-cancel')"
|
||||
:history-id="props.historyId"
|
||||
:hide-source-items="hideSourceItems"
|
||||
:extensions="extensions"
|
||||
:no-items="props.initialElements.length == 0 && !props.fromSelection"
|
||||
@add-uploaded-files="addUploadedFiles"
|
||||
@on-update-datatype-toggle="changeDatatypeFilter"
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate">
|
||||
<template v-slot:help-content>
|
||||
<!-- TODO: Update help content for case where `fromSelection` is false -->
|
||||
<p>
|
||||
{{
|
||||
localize(
|
||||
"Collections cannot have duplicated names. The following list names are duplicated: "
|
||||
[
|
||||
"Collections of datasets are permanent, ordered lists of datasets that can be passed to tools ",
|
||||
"and workflows in order to have analyses done on each member of the entire group. This interface allows ",
|
||||
"you to create a collection and re-order the final collection.",
|
||||
].join("")
|
||||
)
|
||||
}}
|
||||
<ol>
|
||||
<li v-for="name in duplicateNames" :key="name">{{ name }}</li>
|
||||
</ol>
|
||||
{{ localize("Please fix these duplicates and try again.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<CollectionCreator
|
||||
:oncancel="() => emit('on-cancel')"
|
||||
:history-id="props.historyId"
|
||||
:hide-source-items="hideSourceItems"
|
||||
:extensions="extensions"
|
||||
@add-uploaded-files="addUploadedFiles"
|
||||
@on-update-datatype-toggle="changeDatatypeFilter"
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate">
|
||||
<template v-slot:help-content>
|
||||
<!-- TODO: Update help content for case where `fromSelection` is false -->
|
||||
<p>
|
||||
{{
|
||||
localize(
|
||||
[
|
||||
"Collections of datasets are permanent, ordered lists of datasets that can be passed to tools ",
|
||||
"and workflows in order to have analyses done on each member of the entire group. This interface allows ",
|
||||
"you to create a collection and re-order the final collection.",
|
||||
].join("")
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
{{ localize("Rename elements in the list by clicking on") }}
|
||||
<i data-target=".collection-element .name">
|
||||
{{ localize("the existing name") }}
|
||||
</i>
|
||||
{{ localize(".") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Discard elements from the final created list by clicking on the ") }}
|
||||
<i data-target=".collection-element .discard">
|
||||
{{ localize("Discard") }}
|
||||
</i>
|
||||
{{ localize("button.") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{
|
||||
localize(
|
||||
"Reorder the list by clicking and dragging elements. Select multiple elements by clicking on"
|
||||
)
|
||||
}}
|
||||
<i data-target=".collection-element">
|
||||
{{ localize("them") }}
|
||||
</i>
|
||||
{{
|
||||
localize(
|
||||
"and you can then move those selected by dragging the entire group. Deselect them by clicking them again or by clicking the"
|
||||
)
|
||||
}}
|
||||
<i data-target=".clear-selected">
|
||||
{{ localize("Clear selected") }}
|
||||
</i>
|
||||
{{ localize("link.") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Click ") }}
|
||||
<i data-target=".reset">
|
||||
<FontAwesomeIcon :icon="faUndo" />
|
||||
</i>
|
||||
{{ localize("to begin again as if you had just opened the interface.") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Click ") }}
|
||||
<i data-target=".sort-items">
|
||||
<FontAwesomeIcon :icon="faSortAlphaDown" />
|
||||
</i>
|
||||
{{ localize("to sort datasets alphabetically.") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Click the") }}
|
||||
<i data-target=".cancel-create">
|
||||
{{ localize("Cancel") }}
|
||||
</i>
|
||||
{{ localize("button to exit the interface.") }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<p>
|
||||
{{ localize("Once your collection is complete, enter a ") }}
|
||||
<i data-target=".collection-name">
|
||||
{{ localize("name") }}
|
||||
</i>
|
||||
{{ localize("and click") }}
|
||||
<i data-target=".create-collection">
|
||||
{{ localize("Create list") }}
|
||||
<ul>
|
||||
<li>
|
||||
{{ localize("Rename elements in the list by clicking on") }}
|
||||
<i data-target=".collection-element .name">
|
||||
{{ localize("the existing name") }}
|
||||
</i>
|
||||
{{ localize(".") }}
|
||||
</p>
|
||||
</template>
|
||||
</li>
|
||||
|
||||
<template v-slot:middle-content>
|
||||
<div v-if="fromSelection">
|
||||
<div class="collection-elements-controls">
|
||||
<div>
|
||||
<BButton
|
||||
class="reset"
|
||||
:title="localize('Reset to original state')"
|
||||
size="sm"
|
||||
@click="reset">
|
||||
<FontAwesomeIcon :icon="faUndo" fixed-width />
|
||||
{{ localize("Reset") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
class="sort-items"
|
||||
:title="localize('Sort datasets by name')"
|
||||
size="sm"
|
||||
@click="sortByName">
|
||||
<FontAwesomeIcon :icon="faSortAlphaDown" />
|
||||
</BButton>
|
||||
</div>
|
||||
<li>
|
||||
{{ localize("Discard elements from the final created list by clicking on the ") }}
|
||||
<i data-target=".collection-element .discard">
|
||||
{{ localize("Discard") }}
|
||||
</i>
|
||||
{{ localize("button.") }}
|
||||
</li>
|
||||
|
||||
<div class="center-text">
|
||||
<u>{{ workingElements.length }}</u> {{ localize("elements in list") }}
|
||||
</div>
|
||||
<li>
|
||||
{{
|
||||
localize(
|
||||
"Reorder the list by clicking and dragging elements. Select multiple elements by clicking on"
|
||||
)
|
||||
}}
|
||||
<i data-target=".collection-element">
|
||||
{{ localize("them") }}
|
||||
</i>
|
||||
{{
|
||||
localize(
|
||||
"and you can then move those selected by dragging the entire group. Deselect them by clicking them again or by clicking the"
|
||||
)
|
||||
}}
|
||||
<i data-target=".clear-selected">
|
||||
{{ localize("Clear selected") }}
|
||||
</i>
|
||||
{{ localize("link.") }}
|
||||
</li>
|
||||
|
||||
<div>
|
||||
<span v-if="atLeastOneDatasetIsSelected"
|
||||
>{{ localize("For selection") }} ({{ selectedDatasetElements.length }}):</span
|
||||
>
|
||||
<BButtonGroup class="" size="sm">
|
||||
<BButton
|
||||
v-if="atLeastOneDatasetIsSelected"
|
||||
:title="localize('Remove selected datasets from the list')"
|
||||
@click="clickRemoveSelected">
|
||||
<FontAwesomeIcon :icon="faMinus" fixed-width />
|
||||
{{ localize("Remove") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
v-if="
|
||||
!atLeastOneDatasetIsSelected ||
|
||||
selectedDatasetElements.length < workingElements.length
|
||||
"
|
||||
:title="localize('Select all datasets')"
|
||||
size="sm"
|
||||
@click="clickSelectAll">
|
||||
<FontAwesomeIcon :icon="faSquare" fixed-width />
|
||||
{{ localize("Select all") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
v-if="atLeastOneDatasetIsSelected"
|
||||
class="clear-selected"
|
||||
:title="localize('De-select all selected datasets')"
|
||||
@click="clickClearAll">
|
||||
<FontAwesomeIcon :icon="faTimes" fixed-width />
|
||||
{{ localize("Clear") }}
|
||||
</BButton>
|
||||
</BButtonGroup>
|
||||
</div>
|
||||
<li>
|
||||
{{ localize("Click ") }}
|
||||
<i data-target=".reset">
|
||||
<FontAwesomeIcon :icon="faUndo" />
|
||||
</i>
|
||||
{{ localize("to begin again as if you had just opened the interface.") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Click ") }}
|
||||
<i data-target=".sort-items">
|
||||
<FontAwesomeIcon :icon="faSortAlphaDown" />
|
||||
</i>
|
||||
{{ localize("to sort datasets alphabetically.") }}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Click the") }}
|
||||
<i data-target=".cancel-create">
|
||||
{{ localize("Cancel") }}
|
||||
</i>
|
||||
{{ localize("button to exit the interface.") }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<p>
|
||||
{{ localize("Once your collection is complete, enter a ") }}
|
||||
<i data-target=".collection-name">
|
||||
{{ localize("name") }}
|
||||
</i>
|
||||
{{ localize("and click") }}
|
||||
<i data-target=".create-collection">
|
||||
{{ localize("Create list") }}
|
||||
</i>
|
||||
{{ localize(".") }}
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template v-slot:middle-content>
|
||||
<div v-if="noInitialElements">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("No datasets were selected") }}
|
||||
{{ localize("At least one element is needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements, or upload datasets.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else-if="allElementsAreInvalid">
|
||||
<BAlert v-if="!fromSelection" show variant="warning">
|
||||
{{
|
||||
localize(
|
||||
"No elements in your history are valid for this list. \
|
||||
You may need to switch to a different history or upload valid datasets."
|
||||
)
|
||||
}}
|
||||
<div v-if="extensions?.length">
|
||||
{{ localize("The following extensions are required for this list: ") }}
|
||||
<ul>
|
||||
<li v-for="extension in extensions" :key="extension">
|
||||
{{ extension }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</BAlert>
|
||||
<BAlert v-else show variant="warning" dismissible>
|
||||
{{ localize("The following selections could not be included due to problems:") }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ localize("At least one element is needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements, or upload valid datasets.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else-if="fromSelection">
|
||||
<div class="collection-elements-controls">
|
||||
<div>
|
||||
<BButton
|
||||
class="reset"
|
||||
:title="localize('Reset to original state')"
|
||||
size="sm"
|
||||
@click="reset">
|
||||
<FontAwesomeIcon :icon="faUndo" fixed-width />
|
||||
{{ localize("Reset") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
class="sort-items"
|
||||
:title="localize('Sort datasets by name')"
|
||||
size="sm"
|
||||
@click="sortByName">
|
||||
<FontAwesomeIcon :icon="faSortAlphaDown" />
|
||||
</BButton>
|
||||
</div>
|
||||
|
||||
<div v-if="noMoreValidDatasets">
|
||||
<BAlert show variant="warning">
|
||||
{{ localize("No elements left. Would you like to") }}
|
||||
<a class="reset-text" href="javascript:void(0)" role="button" @click="reset">
|
||||
{{ localize("start over") }}
|
||||
</a>
|
||||
?
|
||||
</BAlert>
|
||||
<div class="center-text">
|
||||
<u>{{ workingElements.length }}</u> {{ localize("elements in list") }}
|
||||
</div>
|
||||
|
||||
<draggable
|
||||
v-model="workingElements"
|
||||
class="collection-elements scroll-container flex-row drop-zone"
|
||||
chosen-class="bg-secondary">
|
||||
<DatasetCollectionElementView
|
||||
v-for="element in workingElements"
|
||||
:key="element.id"
|
||||
:class="{ selected: getSelectedDatasetElements.includes(element.id) }"
|
||||
:element="element"
|
||||
has-actions
|
||||
:selected="getSelectedDatasetElements.includes(element.id)"
|
||||
@element-is-selected="elementSelected"
|
||||
@element-is-discarded="elementDiscarded"
|
||||
@onRename="(name) => (element.name = name)" />
|
||||
</draggable>
|
||||
<div>
|
||||
<span v-if="atLeastOneDatasetIsSelected"
|
||||
>{{ localize("For selection") }} ({{ selectedDatasetElements.length }}):</span
|
||||
>
|
||||
<BButtonGroup class="" size="sm">
|
||||
<BButton
|
||||
v-if="atLeastOneDatasetIsSelected"
|
||||
:title="localize('Remove selected datasets from the list')"
|
||||
@click="clickRemoveSelected">
|
||||
<FontAwesomeIcon :icon="faMinus" fixed-width />
|
||||
{{ localize("Remove") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
v-if="
|
||||
!atLeastOneDatasetIsSelected ||
|
||||
selectedDatasetElements.length < workingElements.length
|
||||
"
|
||||
:title="localize('Select all datasets')"
|
||||
size="sm"
|
||||
@click="clickSelectAll">
|
||||
<FontAwesomeIcon :icon="faSquare" fixed-width />
|
||||
{{ localize("Select all") }}
|
||||
</BButton>
|
||||
<BButton
|
||||
v-if="atLeastOneDatasetIsSelected"
|
||||
class="clear-selected"
|
||||
:title="localize('De-select all selected datasets')"
|
||||
@click="clickClearAll">
|
||||
<FontAwesomeIcon :icon="faTimes" fixed-width />
|
||||
{{ localize("Clear") }}
|
||||
</BButton>
|
||||
</BButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FormSelectMany
|
||||
v-else
|
||||
v-model="inListElements"
|
||||
maintain-selection-order
|
||||
:placeholder="localize('Filter datasets by name')"
|
||||
:options="workingElements.map((e) => ({ label: e.name || '', value: e }))">
|
||||
<template v-slot:label-area="{ value }">
|
||||
<DatasetCollectionElementView
|
||||
class="w-100"
|
||||
:element="value"
|
||||
@onRename="(name) => renameElement(value, name)" />
|
||||
</template>
|
||||
</FormSelectMany>
|
||||
</template>
|
||||
</CollectionCreator>
|
||||
</div>
|
||||
<div v-if="noMoreValidDatasets">
|
||||
<BAlert show variant="warning">
|
||||
{{ localize("No elements left. Would you like to") }}
|
||||
<a class="reset-text" href="javascript:void(0)" role="button" @click="reset">
|
||||
{{ localize("start over") }}
|
||||
</a>
|
||||
?
|
||||
</BAlert>
|
||||
</div>
|
||||
|
||||
<draggable
|
||||
v-model="workingElements"
|
||||
class="collection-elements scroll-container flex-row drop-zone"
|
||||
chosen-class="bg-secondary">
|
||||
<DatasetCollectionElementView
|
||||
v-for="element in workingElements"
|
||||
:key="element.id"
|
||||
:class="{ selected: getSelectedDatasetElements.includes(element.id) }"
|
||||
:element="element"
|
||||
has-actions
|
||||
:selected="getSelectedDatasetElements.includes(element.id)"
|
||||
@element-is-selected="elementSelected"
|
||||
@element-is-discarded="elementDiscarded"
|
||||
@onRename="(name) => (element.name = name)" />
|
||||
</draggable>
|
||||
</div>
|
||||
|
||||
<FormSelectMany
|
||||
v-else
|
||||
v-model="inListElements"
|
||||
maintain-selection-order
|
||||
:placeholder="localize('Filter datasets by name')"
|
||||
:options="workingElements.map((e) => ({ label: e.name || '', value: e }))">
|
||||
<template v-slot:label-area="{ value }">
|
||||
<DatasetCollectionElementView
|
||||
class="w-100"
|
||||
:element="value"
|
||||
@onRename="(name) => renameElement(value, name)" />
|
||||
</template>
|
||||
</FormSelectMany>
|
||||
</template>
|
||||
</CollectionCreator>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -345,149 +345,133 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) {
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="noElementsSelected">
|
||||
<div v-if="fromSelection && invalidElements.length">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("No datasets were selected.") }}
|
||||
{{ localize("Exactly two elements needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements.") }}
|
||||
</BAlert>
|
||||
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ localize("Cancel") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="allElementsAreInvalid">
|
||||
<BAlert v-if="!fromSelection" show variant="warning">
|
||||
{{
|
||||
localize(
|
||||
"No elements in your history are valid for this pair. You may need to switch to a different history."
|
||||
)
|
||||
}}
|
||||
<span v-if="extensions?.length">
|
||||
{{ localize("The following extensions are required for this pair: ") }}
|
||||
<ul>
|
||||
<li v-for="extension in extensions" :key="extension">
|
||||
{{ extension }}
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
</BAlert>
|
||||
<BAlert v-else show variant="warning" dismissible>
|
||||
{{ localize("The following selections could not be included due to problems:") }}
|
||||
<ul>
|
||||
<li v-for="problem in invalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ localize("Exactly two elements needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements.") }}
|
||||
</BAlert>
|
||||
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ localize("Cancel") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="fromSelection && invalidElements.length">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("The following selections could not be included due to problems:") }}
|
||||
<ul>
|
||||
<li v-for="problem in invalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-if="!exactlyTwoValidElements">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("Exactly two elements are needed for the pair.") }}
|
||||
<span v-if="fromSelection">
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("Cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements.") }}
|
||||
</span>
|
||||
</BAlert>
|
||||
|
||||
<div v-if="fromSelection" class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
<div v-if="!exactlyTwoValidElements">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("Exactly two elements are needed for the pair.") }}
|
||||
<span v-if="fromSelection">
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("Cancel") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{{ localize("and reselect new elements.") }}
|
||||
</span>
|
||||
</BAlert>
|
||||
</div>
|
||||
|
||||
<CollectionCreator
|
||||
:oncancel="() => emit('on-cancel')"
|
||||
:history-id="props.historyId"
|
||||
:hide-source-items="hideSourceItems"
|
||||
:suggested-name="initialSuggestedName"
|
||||
:extensions="props.extensions"
|
||||
:extensions-toggle="removeExtensions"
|
||||
@add-uploaded-files="addUploadedFiles"
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate"
|
||||
@remove-extensions-toggle="removeExtensionsToggle">
|
||||
<template v-slot:help-content>
|
||||
<!-- TODO: Update help content for case where `fromSelection` is false -->
|
||||
<p>
|
||||
<CollectionCreator
|
||||
:oncancel="() => emit('on-cancel')"
|
||||
:history-id="props.historyId"
|
||||
:hide-source-items="hideSourceItems"
|
||||
:suggested-name="initialSuggestedName"
|
||||
:extensions="props.extensions"
|
||||
:extensions-toggle="removeExtensions"
|
||||
:no-items="props.initialElements.length == 0 && !props.fromSelection"
|
||||
@add-uploaded-files="addUploadedFiles"
|
||||
@onUpdateHideSourceItems="onUpdateHideSourceItems"
|
||||
@clicked-create="clickedCreate"
|
||||
@remove-extensions-toggle="removeExtensionsToggle">
|
||||
<template v-slot:help-content>
|
||||
<!-- TODO: Update help content for case where `fromSelection` is false -->
|
||||
<p>
|
||||
{{
|
||||
localize(
|
||||
[
|
||||
"Pair collections are permanent collections containing two datasets: one forward and one reverse. ",
|
||||
"Often these are forward and reverse reads. The pair collections can be passed to tools and workflows in ",
|
||||
"order to have analyses done on both datasets. This interface allows you to create a pair, name it, and ",
|
||||
"swap which is forward and which reverse.",
|
||||
].join("")
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
{{ localize("Click the ") }}
|
||||
<i data-target=".swap">
|
||||
{{ localize("Swap") }}
|
||||
</i>
|
||||
{{
|
||||
localize(
|
||||
[
|
||||
"Pair collections are permanent collections containing two datasets: one forward and one reverse. ",
|
||||
"Often these are forward and reverse reads. The pair collections can be passed to tools and workflows in ",
|
||||
"order to have analyses done on both datasets. This interface allows you to create a pair, name it, and ",
|
||||
"swap which is forward and which reverse.",
|
||||
].join("")
|
||||
"link to make your forward dataset the reverse and the reverse dataset forward"
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
{{ localize("Click the ") }}
|
||||
<i data-target=".swap">
|
||||
{{ localize("Swap") }}
|
||||
</i>
|
||||
{{
|
||||
localize(
|
||||
"link to make your forward dataset the reverse and the reverse dataset forward"
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
|
||||
<li>
|
||||
{{ localize("Click the ") }}
|
||||
<i data-target=".cancel-create">
|
||||
{{ localize("Cancel") }}
|
||||
</i>
|
||||
{{ localize("button to exit the interface.") }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<p>
|
||||
{{ localize("Once your collection is complete, enter a ") }}
|
||||
<i data-target=".collection-name"> {{ localize("name") }}</i>
|
||||
{{ localize("and click ") }}
|
||||
<i data-target=".create-collection">
|
||||
{{ localize("Create list") }}
|
||||
<li>
|
||||
{{ localize("Click the ") }}
|
||||
<i data-target=".cancel-create">
|
||||
{{ localize("Cancel") }}
|
||||
</i>
|
||||
{{ localize(".") }}
|
||||
</p>
|
||||
</template>
|
||||
{{ localize("button to exit the interface.") }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<template v-slot:middle-content>
|
||||
<br />
|
||||
|
||||
<p>
|
||||
{{ localize("Once your collection is complete, enter a ") }}
|
||||
<i data-target=".collection-name"> {{ localize("name") }}</i>
|
||||
{{ localize("and click ") }}
|
||||
<i data-target=".create-collection">
|
||||
{{ localize("Create list") }}
|
||||
</i>
|
||||
{{ localize(".") }}
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template v-slot:middle-content>
|
||||
<div v-if="noElementsSelected">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ localize("No datasets were selected.") }}
|
||||
{{ localize("Exactly two elements needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements, or upload datasets.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else-if="allElementsAreInvalid">
|
||||
<BAlert v-if="!fromSelection" show variant="warning">
|
||||
{{
|
||||
localize(
|
||||
"No elements in your history are valid for this pair. \
|
||||
You may need to switch to a different history or upload valid datasets."
|
||||
)
|
||||
}}
|
||||
<div v-if="extensions?.length">
|
||||
{{ localize("The following extensions are required for this pair: ") }}
|
||||
<ul>
|
||||
<li v-for="extension in extensions" :key="extension">
|
||||
{{ extension }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</BAlert>
|
||||
<BAlert v-else show variant="warning" dismissible>
|
||||
{{ localize("The following selections could not be included due to problems:") }}
|
||||
<ul>
|
||||
<li v-for="problem in invalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ localize("Exactly two elements needed for the collection. You may need to") }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ localize("cancel") }}
|
||||
</a>
|
||||
{{ localize("and reselect new elements, or upload datasets.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="collection-elements-controls">
|
||||
<BButton
|
||||
class="swap"
|
||||
@@ -531,9 +515,9 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) {
|
||||
@onRename="(name) => (element.name = name)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CollectionCreator>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CollectionCreator>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -64,7 +64,7 @@ const emit = defineEmits<{
|
||||
const noElementsHeader = props.fromSelection ? localize("No elements selected") : localize("No elements available");
|
||||
const allInvalidElementsPartTwo = props.fromSelection
|
||||
? localize("and reselect new elements.")
|
||||
: localize("and change your current history or add valid datasets for this collection.");
|
||||
: localize("and change your current history or upload valid datasets for this collection.");
|
||||
|
||||
// Flags
|
||||
const state = ref<"build" | "error" | "duplicates">("build");
|
||||
@@ -817,261 +817,245 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) {
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="noElementsSelected">
|
||||
<div v-if="fromSelection && returnInvalidElementsLength">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ noElementsHeader }}
|
||||
{{ ALL_INVALID_ELEMENTS_PART_ONE }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
</BAlert>
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="allElementsAreInvalid">
|
||||
<BAlert v-if="!fromSelection" show variant="warning">
|
||||
{{
|
||||
localize(
|
||||
"No elements in your history are valid for this collection. You may need to switch to a different history."
|
||||
)
|
||||
}}
|
||||
<span v-if="extensions?.length">
|
||||
{{ localize("The following extensions are required for this collection: ") }}
|
||||
<ul>
|
||||
<li v-for="extension in extensions" :key="extension">
|
||||
{{ extension }}
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
</BAlert>
|
||||
<BAlert v-else show variant="warning" dismissible>
|
||||
{{ INVALID_HEADER }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ ALL_INVALID_ELEMENTS_PART_ONE }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
</BAlert>
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="tooFewElementsSelected">
|
||||
<div v-if="returnInvalidElementsLength">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ INVALID_HEADER }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
</BAlert>
|
||||
</div>
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ ALL_INVALID_ELEMENTS_PART_ONE }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
<div v-if="!autoPairsPossible">
|
||||
<BAlert show variant="danger" dismissible @dismissed="autoPairsPossible = true">
|
||||
{{
|
||||
localize(
|
||||
"Could not automatically create any pairs from the given dataset names. You may want to choose or enter different filters and try auto-pairing again."
|
||||
)
|
||||
}}
|
||||
<span v-if="fromSelection">
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
</span>
|
||||
</BAlert>
|
||||
<div class="float-left">
|
||||
<button class="cancel-create btn" tabindex="-1" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="fromSelection && returnInvalidElementsLength">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ INVALID_HEADER }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-if="!autoPairsPossible">
|
||||
<BAlert show variant="danger" dismissible @dismissed="autoPairsPossible = true">
|
||||
<div v-if="state == 'duplicates'">
|
||||
<BAlert show variant="danger">
|
||||
{{
|
||||
localize("Collections cannot have duplicated names. The following list names are duplicated: ")
|
||||
}}
|
||||
<ul>
|
||||
<li v-for="name in duplicatePairNames" :key="name">{{ name }}</li>
|
||||
</ul>
|
||||
{{ localize("Please fix these duplicates and try again.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<CollectionCreator
|
||||
:oncancel="() => emit('on-cancel')"
|
||||
:history-id="props.historyId"
|
||||
:hide-source-items="hideSourceItems"
|
||||
render-extensions-toggle
|
||||
:extensions-toggle="removeExtensions"
|
||||
:extensions="extensions"
|
||||
:no-items="props.initialElements.length == 0 && !props.fromSelection"
|
||||
@add-uploaded-files="addUploadedFiles"
|
||||
@onUpdateHideSourceItems="hideSourceItems = $event"
|
||||
@clicked-create="clickedCreate"
|
||||
@remove-extensions-toggle="removeExtensionsToggle">
|
||||
<template v-slot:help-content>
|
||||
<!-- TODO: Update help content for case where `fromSelection` is false -->
|
||||
<p>
|
||||
{{
|
||||
localize(
|
||||
"Could not automatically create any pairs from the given dataset names. You may want to choose or enter different filters and try auto-pairing again."
|
||||
[
|
||||
"Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ",
|
||||
"These collections can be passed to tools and workflows in order to have analyses done on each member of ",
|
||||
"the entire group. This interface allows you to create a collection, choose which datasets are paired, ",
|
||||
"and re-order the final collection.",
|
||||
].join("")
|
||||
)
|
||||
}}
|
||||
<span v-if="fromSelection">
|
||||
</p>
|
||||
<p>
|
||||
{{ localize("Unpaired datasets are shown in the") }}
|
||||
<i data-target=".unpaired-columns">
|
||||
{{ localize("unpaired section") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
{{ localize("Paired datasets are shown in the") }}
|
||||
<i data-target=".paired-columns">
|
||||
{{ localize("paired section") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
</p>
|
||||
<ul>
|
||||
{{
|
||||
localize("To pair datasets, you can:")
|
||||
}}
|
||||
<li>
|
||||
{{ localize("Click a dataset in the") }}
|
||||
<i data-target=".forward-column">
|
||||
{{ localize("forward column") }}
|
||||
</i>
|
||||
{{ localize("to select it then click a dataset in the") }}
|
||||
<i data-target=".reverse-column">
|
||||
{{ localize("reverse column") }}
|
||||
</i>
|
||||
</li>
|
||||
<li>
|
||||
{{
|
||||
localize(
|
||||
"Click one of the Pair these datasets buttons in the middle column to pair the datasets in a particular row."
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
<li>
|
||||
{{ localize("Click") }}
|
||||
<i data-target=".autopair-link">
|
||||
{{ localize("Auto-pair") }}
|
||||
</i>
|
||||
{{ localize("to have your datasets automatically paired based on name.") }}
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
{{
|
||||
localize("You can filter what is shown in the unpaired sections by:")
|
||||
}}
|
||||
<li>
|
||||
{{ localize("Entering partial dataset names in either the ") }}
|
||||
<i data-target=".forward-unpaired-filter input">
|
||||
{{ localize("forward filter") }}
|
||||
</i>
|
||||
{{ localize("or ") }}
|
||||
<i data-target=".reverse-unpaired-filter input">
|
||||
{{ localize("reverse filter") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
</li>
|
||||
<li>
|
||||
{{
|
||||
localize(
|
||||
"Choosing from a list of preset filters by clicking the arrow beside the filter input."
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
<li>
|
||||
{{ localize("Entering regular expressions to match dataset names. See:") }}
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions"
|
||||
target="_blank">
|
||||
{{ localize("MDN's JavaScript Regular Expression Tutorial") }}</a
|
||||
>
|
||||
{{ localize("Note: forward slashes (\\) are not needed.") }}
|
||||
</li>
|
||||
<li>
|
||||
{{ localize("Clearing the filters by clicking the ") }}
|
||||
<i data-target=".clear-filters-link">
|
||||
{{ localize("Clear filters link") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
{{ localize("To unpair individual dataset pairs, click the ") }}
|
||||
<i data-target=".unpair-btn">
|
||||
{{ localize("unpair buttons (") }}
|
||||
<span class="fa fa-unlink"></span>
|
||||
{{ ")" }}
|
||||
</i>
|
||||
{{ localize("Click the") }}
|
||||
<i data-target=".unpair-all-link">
|
||||
{{ localize("Unpair all") }}
|
||||
</i>
|
||||
{{ localize("link to unpair all pairs.") }}
|
||||
</p>
|
||||
<p>
|
||||
{{
|
||||
localize(
|
||||
'You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the'
|
||||
)
|
||||
}}
|
||||
<i data-target=".remove-extensions-prompt">
|
||||
{{ localize("Remove file extensions from pair names?") }}
|
||||
</i>
|
||||
{{ localize("control.") }}
|
||||
</p>
|
||||
<p>
|
||||
{{ localize("Once your collection is complete, enter a") }}
|
||||
<i data-target=".collection-name">
|
||||
{{ localize("name") }}
|
||||
</i>
|
||||
{{ localize("and click ") }}
|
||||
<i data-target=".create-collection">
|
||||
{{ localize("Create list") }}
|
||||
</i>
|
||||
{{ localize(". (Note: you do not have to pair all unpaired datasets to finish.)") }}
|
||||
</p>
|
||||
</template>
|
||||
<template v-slot:middle-content>
|
||||
<div v-if="noElementsSelected">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ noElementsHeader }}
|
||||
{{ ALL_INVALID_ELEMENTS_PART_ONE }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
</span>
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-if="state == 'duplicates'">
|
||||
<BAlert show variant="danger">
|
||||
{{
|
||||
localize(
|
||||
"Collections cannot have duplicated names. The following list names are duplicated: "
|
||||
)
|
||||
}}
|
||||
<ul>
|
||||
<li v-for="name in duplicatePairNames" :key="name">{{ name }}</li>
|
||||
</ul>
|
||||
{{ localize("Please fix these duplicates and try again.") }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<CollectionCreator
|
||||
:oncancel="() => emit('on-cancel')"
|
||||
:history-id="props.historyId"
|
||||
:hide-source-items="hideSourceItems"
|
||||
render-extensions-toggle
|
||||
:extensions-toggle="removeExtensions"
|
||||
:extensions="extensions"
|
||||
@add-uploaded-files="addUploadedFiles"
|
||||
@onUpdateHideSourceItems="hideSourceItems = $event"
|
||||
@clicked-create="clickedCreate"
|
||||
@remove-extensions-toggle="removeExtensionsToggle">
|
||||
<template v-slot:help-content>
|
||||
<!-- TODO: Update help content for case where `fromSelection` is false -->
|
||||
<p>
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else-if="allElementsAreInvalid">
|
||||
<BAlert v-if="!fromSelection" show variant="warning">
|
||||
{{
|
||||
localize(
|
||||
[
|
||||
"Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ",
|
||||
"These collections can be passed to tools and workflows in order to have analyses done on each member of ",
|
||||
"the entire group. This interface allows you to create a collection, choose which datasets are paired, ",
|
||||
"and re-order the final collection.",
|
||||
].join("")
|
||||
"No elements in your history are valid for this collection. You may need to switch to a different history."
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<p>
|
||||
{{ localize("Unpaired datasets are shown in the") }}
|
||||
<i data-target=".unpaired-columns">
|
||||
{{ localize("unpaired section") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
{{ localize("Paired datasets are shown in the") }}
|
||||
<i data-target=".paired-columns">
|
||||
{{ localize("paired section") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
</p>
|
||||
<ul>
|
||||
{{
|
||||
localize("To pair datasets, you can:")
|
||||
}}
|
||||
<li>
|
||||
{{ localize("Click a dataset in the") }}
|
||||
<i data-target=".forward-column">
|
||||
{{ localize("forward column") }}
|
||||
</i>
|
||||
{{ localize("to select it then click a dataset in the") }}
|
||||
<i data-target=".reverse-column">
|
||||
{{ localize("reverse column") }}
|
||||
</i>
|
||||
</li>
|
||||
<li>
|
||||
{{
|
||||
localize(
|
||||
"Click one of the Pair these datasets buttons in the middle column to pair the datasets in a particular row."
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
<li>
|
||||
{{ localize("Click") }}
|
||||
<i data-target=".autopair-link">
|
||||
{{ localize("Auto-pair") }}
|
||||
</i>
|
||||
{{ localize("to have your datasets automatically paired based on name.") }}
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
{{
|
||||
localize("You can filter what is shown in the unpaired sections by:")
|
||||
}}
|
||||
<li>
|
||||
{{ localize("Entering partial dataset names in either the ") }}
|
||||
<i data-target=".forward-unpaired-filter input">
|
||||
{{ localize("forward filter") }}
|
||||
</i>
|
||||
{{ localize("or ") }}
|
||||
<i data-target=".reverse-unpaired-filter input">
|
||||
{{ localize("reverse filter") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
</li>
|
||||
<li>
|
||||
{{
|
||||
localize(
|
||||
"Choosing from a list of preset filters by clicking the arrow beside the filter input."
|
||||
)
|
||||
}}
|
||||
</li>
|
||||
<li>
|
||||
{{ localize("Entering regular expressions to match dataset names. See:") }}
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions"
|
||||
target="_blank">
|
||||
{{ localize("MDN's JavaScript Regular Expression Tutorial") }}</a
|
||||
>
|
||||
{{ localize("Note: forward slashes (\\) are not needed.") }}
|
||||
</li>
|
||||
<li>
|
||||
{{ localize("Clearing the filters by clicking the ") }}
|
||||
<i data-target=".clear-filters-link">
|
||||
{{ localize("Clear filters link") }}
|
||||
</i>
|
||||
{{ "." }}
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
{{ localize("To unpair individual dataset pairs, click the ") }}
|
||||
<i data-target=".unpair-btn">
|
||||
{{ localize("unpair buttons (") }}
|
||||
<span class="fa fa-unlink"></span>
|
||||
{{ ")" }}
|
||||
</i>
|
||||
{{ localize("Click the") }}
|
||||
<i data-target=".unpair-all-link">
|
||||
{{ localize("Unpair all") }}
|
||||
</i>
|
||||
{{ localize("link to unpair all pairs.") }}
|
||||
</p>
|
||||
<p>
|
||||
{{
|
||||
localize(
|
||||
'You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the'
|
||||
)
|
||||
}}
|
||||
<i data-target=".remove-extensions-prompt">
|
||||
{{ localize("Remove file extensions from pair names?") }}
|
||||
</i>
|
||||
{{ localize("control.") }}
|
||||
</p>
|
||||
<p>
|
||||
{{ localize("Once your collection is complete, enter a") }}
|
||||
<i data-target=".collection-name">
|
||||
{{ localize("name") }}
|
||||
</i>
|
||||
{{ localize("and click ") }}
|
||||
<i data-target=".create-collection">
|
||||
{{ localize("Create list") }}
|
||||
</i>
|
||||
{{ localize(". (Note: you do not have to pair all unpaired datasets to finish.)") }}
|
||||
</p>
|
||||
</template>
|
||||
<template v-slot:middle-content>
|
||||
<span v-if="extensions?.length">
|
||||
{{ localize("The following extensions are required for this collection: ") }}
|
||||
<ul>
|
||||
<li v-for="extension in extensions" :key="extension">
|
||||
{{ extension }}
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
</BAlert>
|
||||
<BAlert v-else show variant="warning" dismissible>
|
||||
{{ INVALID_HEADER }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
{{ ALL_INVALID_ELEMENTS_PART_ONE }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else-if="tooFewElementsSelected">
|
||||
<div v-if="returnInvalidElementsLength">
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ INVALID_HEADER }}
|
||||
<ul>
|
||||
<li v-for="problem in returnInvalidElements" :key="problem">
|
||||
{{ problem }}
|
||||
</li>
|
||||
</ul>
|
||||
</BAlert>
|
||||
</div>
|
||||
<BAlert show variant="warning" dismissible>
|
||||
{{ ALL_INVALID_ELEMENTS_PART_ONE }}
|
||||
<a class="cancel-text" href="javascript:void(0)" role="button" @click="emit('on-cancel')">
|
||||
{{ CANCEL_TEXT }}
|
||||
</a>
|
||||
{{ allInvalidElementsPartTwo }}
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else>
|
||||
<BCard no-body class="mb-2">
|
||||
<BCardHeader
|
||||
class="d-flex justify-content-between align-items-center unselectable"
|
||||
@@ -1308,9 +1292,9 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CollectionCreator>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CollectionCreator>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { faChevronDown, faChevronUp, faPlus, faUpload } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { BAlert, BButton, BFormCheckbox, BFormGroup, BFormInput, BTab, BTabs } from "bootstrap-vue";
|
||||
import { BAlert, BButton, BFormCheckbox, BFormGroup, BFormInput, BLink, BTab, BTabs } from "bootstrap-vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
@@ -38,6 +38,7 @@ interface Props {
|
||||
renderExtensionsToggle?: boolean;
|
||||
extensions?: string[];
|
||||
extensionsToggle?: boolean;
|
||||
noItems?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -134,103 +135,114 @@ watch(
|
||||
<template>
|
||||
<BTabs v-model="currentTab" fill justified>
|
||||
<BTab class="collection-creator" :title="localize('Create Collection')">
|
||||
<div class="header flex-row no-flex">
|
||||
<div class="main-help well clear" :class="{ expanded: isExpanded }">
|
||||
<a
|
||||
class="more-help"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
:title="localize('Expand or Close Help')"
|
||||
@click="clickForHelp">
|
||||
<div v-if="!isExpanded">
|
||||
<FontAwesomeIcon :icon="faChevronDown" />
|
||||
<span class="sr-only">{{ localize("Expand Help") }}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<FontAwesomeIcon :icon="faChevronUp" />
|
||||
<span class="sr-only">{{ localize("Close Help") }}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="help-content">
|
||||
<!-- each collection that extends this will add their own help content -->
|
||||
<slot name="help-content"></slot>
|
||||
|
||||
<div v-if="props.noItems">
|
||||
<BAlert variant="info" show>
|
||||
{{ localize("No items available to create a collection.") }}
|
||||
{{ localize("Exit and change your current history, or") }}
|
||||
<BLink class="text-decoration-none" @click.stop.prevent="currentTab = Tabs.upload">
|
||||
{{ localize("Upload some datasets.") }}
|
||||
</BLink>
|
||||
</BAlert>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="header flex-row no-flex">
|
||||
<div class="main-help well clear" :class="{ expanded: isExpanded }">
|
||||
<a
|
||||
class="more-help"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
:title="localize('Expand or Close Help')"
|
||||
@click="clickForHelp">
|
||||
<span class="sr-only">{{ localize("Expand Help") }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="middle flex-row flex-row-container">
|
||||
<slot name="middle-content"></slot>
|
||||
</div>
|
||||
|
||||
<div class="footer flex-row">
|
||||
<div class="vertically-spaced">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<BAlert v-if="extensions?.length" class="w-100 py-0" variant="secondary" show>
|
||||
<HelpText
|
||||
uri="galaxy.collections.collectionBuilder.filteredExtensions"
|
||||
:text="localize('Filtered extensions: ')" />
|
||||
<strong>{{ orList(extensions) }}</strong>
|
||||
</BAlert>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<BFormGroup class="inputs-form-group">
|
||||
<BFormCheckbox
|
||||
v-if="renderExtensionsToggle"
|
||||
name="remove-extensions"
|
||||
switch
|
||||
:checked="extensionsToggle"
|
||||
@input="emit('remove-extensions-toggle')">
|
||||
{{ localize("Remove file extensions?") }}
|
||||
</BFormCheckbox>
|
||||
|
||||
<div data-description="hide original elements">
|
||||
<BFormCheckbox v-model="localHideSourceItems" name="hide-originals" switch>
|
||||
<HelpText
|
||||
uri="galaxy.collections.collectionBuilder.hideOriginalElements"
|
||||
:text="localize('Hide original elements')" />
|
||||
</BFormCheckbox>
|
||||
<div v-if="!isExpanded">
|
||||
<FontAwesomeIcon :icon="faChevronDown" />
|
||||
<span class="sr-only">{{ localize("Expand Help") }}</span>
|
||||
</div>
|
||||
</BFormGroup>
|
||||
<div v-else>
|
||||
<FontAwesomeIcon :icon="faChevronUp" />
|
||||
<span class="sr-only">{{ localize("Close Help") }}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<BFormGroup
|
||||
class="flex-gapx-1 d-flex align-items-center w-50 inputs-form-group"
|
||||
:label="localize('Name:')"
|
||||
label-for="collection-name">
|
||||
<BFormInput
|
||||
id="collection-name"
|
||||
v-model="collectionName"
|
||||
class="collection-name"
|
||||
:placeholder="localize('Enter a name for your new collection')"
|
||||
size="sm"
|
||||
required
|
||||
:state="!collectionName ? false : null" />
|
||||
</BFormGroup>
|
||||
<div class="help-content">
|
||||
<!-- each collection that extends this will add their own help content -->
|
||||
<slot name="help-content"></slot>
|
||||
|
||||
<a
|
||||
class="more-help"
|
||||
href="javascript:void(0);"
|
||||
role="button"
|
||||
:title="localize('Expand or Close Help')"
|
||||
@click="clickForHelp">
|
||||
<span class="sr-only">{{ localize("Expand Help") }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions vertically-spaced d-flex justify-content-between">
|
||||
<BButton tabindex="-1" @click="cancelCreate">
|
||||
{{ localize("Cancel") }}
|
||||
</BButton>
|
||||
<div class="middle flex-row flex-row-container">
|
||||
<slot name="middle-content"></slot>
|
||||
</div>
|
||||
|
||||
<BButton
|
||||
class="create-collection"
|
||||
variant="primary"
|
||||
:disabled="!validInput"
|
||||
@click="emit('clicked-create', collectionName)">
|
||||
{{ localize("Create collection") }}
|
||||
</BButton>
|
||||
<div class="footer flex-row">
|
||||
<div class="vertically-spaced">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<BAlert v-if="extensions?.length" class="w-100 py-0" variant="secondary" show>
|
||||
<HelpText
|
||||
uri="galaxy.collections.collectionBuilder.filteredExtensions"
|
||||
:text="localize('Filtered extensions: ')" />
|
||||
<strong>{{ orList(extensions) }}</strong>
|
||||
</BAlert>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<BFormGroup class="inputs-form-group">
|
||||
<BFormCheckbox
|
||||
v-if="renderExtensionsToggle"
|
||||
name="remove-extensions"
|
||||
switch
|
||||
:checked="extensionsToggle"
|
||||
@input="emit('remove-extensions-toggle')">
|
||||
{{ localize("Remove file extensions?") }}
|
||||
</BFormCheckbox>
|
||||
|
||||
<div data-description="hide original elements">
|
||||
<BFormCheckbox v-model="localHideSourceItems" name="hide-originals" switch>
|
||||
<HelpText
|
||||
uri="galaxy.collections.collectionBuilder.hideOriginalElements"
|
||||
:text="localize('Hide original elements')" />
|
||||
</BFormCheckbox>
|
||||
</div>
|
||||
</BFormGroup>
|
||||
|
||||
<BFormGroup
|
||||
class="flex-gapx-1 d-flex align-items-center w-50 inputs-form-group"
|
||||
:label="localize('Name:')"
|
||||
label-for="collection-name">
|
||||
<BFormInput
|
||||
id="collection-name"
|
||||
v-model="collectionName"
|
||||
class="collection-name"
|
||||
:placeholder="localize('Enter a name for your new collection')"
|
||||
size="sm"
|
||||
required
|
||||
:state="!collectionName ? false : null" />
|
||||
</BFormGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions vertically-spaced d-flex justify-content-between">
|
||||
<BButton tabindex="-1" @click="cancelCreate">
|
||||
{{ localize("Cancel") }}
|
||||
</BButton>
|
||||
|
||||
<BButton
|
||||
class="create-collection"
|
||||
variant="primary"
|
||||
:disabled="!validInput"
|
||||
@click="emit('clicked-create', collectionName)">
|
||||
{{ localize("Create collection") }}
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BTab>
|
||||
|
||||
@@ -90,6 +90,14 @@ const dragTarget: Ref<EventTarget | null> = ref(null);
|
||||
const collectionModalShow = ref(false);
|
||||
const collectionModalType = ref<"list" | "list:paired" | "paired">("list");
|
||||
const { currentHistoryId } = storeToRefs(useHistoryStore());
|
||||
const restrictsExtensions = computed(() => {
|
||||
const extensions = props.extensions;
|
||||
if (!extensions || extensions.length == 0 || extensions.indexOf("data") >= 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
/** Store options which need to be preserved **/
|
||||
const keepOptions: Record<string, SelectOption> = {};
|
||||
@@ -649,7 +657,7 @@ const noOptionsWarningMessage = computed(() => {
|
||||
</BButton>
|
||||
</BButtonGroup>
|
||||
</BButtonGroup>
|
||||
<div v-if="extensions && extensions.length > 0">
|
||||
<div v-if="restrictsExtensions">
|
||||
<BButton :id="formatsButtonId" class="ui-link" @click="formatsVisible = !formatsVisible">
|
||||
accepted formats
|
||||
<FontAwesomeIcon v-if="formatsVisible" :icon="faCaretUp" />
|
||||
|
||||
@@ -77,7 +77,14 @@ async function submitOIDCLogin(idp: string) {
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const { data } = await axios.post(withPrefix(`/authnz/${idp}/login`));
|
||||
const loginUrl = withPrefix(`/authnz/${idp}/login`);
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const redirectParam = urlParams.get("redirect");
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("next", redirectParam || "");
|
||||
|
||||
const { data } = await axios.post(loginUrl, formData, { withCredentials: true });
|
||||
|
||||
if (data.redirect_uri) {
|
||||
window.location = data.redirect_uri;
|
||||
|
||||
@@ -1209,7 +1209,7 @@ class NavigatesGalaxy(HasDriver):
|
||||
# Make sure we're on the workflow editor and not clicking the main tool panel.
|
||||
editor.canvas_body.wait_for_visible()
|
||||
|
||||
editor.tool_menu.wait_for_visible()
|
||||
self.open_toolbox()
|
||||
editor.tool_menu_section_link(section_name="inputs").wait_for_and_click()
|
||||
editor.tool_menu_item_link(item_name=item_name).wait_for_and_click()
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ from galaxy.webapps.base.controller import JSAppLauncher
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
PROVIDER_COOKIE_NAME = "galaxy-oidc-provider"
|
||||
LOGIN_NEXT_COOKIE_NAME = "galaxy-oidc-login-next"
|
||||
|
||||
|
||||
class OIDC(JSAppLauncher):
|
||||
@@ -72,12 +73,14 @@ class OIDC(JSAppLauncher):
|
||||
|
||||
@web.json
|
||||
@web.expose
|
||||
def login(self, trans, provider, idphint=None):
|
||||
def login(self, trans, provider, idphint=None, next=None):
|
||||
if not trans.app.config.enable_oidc:
|
||||
msg = "Login to Galaxy using third-party identities is not enabled on this Galaxy instance."
|
||||
log.debug(msg)
|
||||
return trans.show_error_message(msg)
|
||||
success, message, redirect_uri = trans.app.authnz_manager.authenticate(provider, trans, idphint=idphint)
|
||||
if next:
|
||||
trans.set_cookie(value=next, name=LOGIN_NEXT_COOKIE_NAME)
|
||||
success, message, redirect_uri = trans.app.authnz_manager.authenticate(provider, trans, idphint)
|
||||
if success:
|
||||
return {"redirect_uri": redirect_uri}
|
||||
else:
|
||||
@@ -86,6 +89,7 @@ class OIDC(JSAppLauncher):
|
||||
@web.expose
|
||||
def callback(self, trans, provider, idphint=None, **kwargs):
|
||||
user = trans.user.username if trans.user is not None else "anonymous"
|
||||
login_next = url_for(trans.get_cookie(name=LOGIN_NEXT_COOKIE_NAME) or "/")
|
||||
if not bool(kwargs):
|
||||
log.error(f"OIDC callback received no data for provider `{provider}` and user `{user}`")
|
||||
return trans.show_error_message(
|
||||
@@ -110,7 +114,7 @@ class OIDC(JSAppLauncher):
|
||||
kwargs.get("state", " "),
|
||||
kwargs["code"],
|
||||
trans,
|
||||
login_redirect_url=url_for("/"),
|
||||
login_redirect_url=login_next,
|
||||
idphint=idphint,
|
||||
)
|
||||
except exceptions.AuthenticationFailed:
|
||||
|
||||
Reference in New Issue
Block a user