diff --git a/client/src/components/Collections/ListCollectionCreator.vue b/client/src/components/Collections/ListCollectionCreator.vue index 17324166aca9..841a206a3635 100644 --- a/client/src/components/Collections/ListCollectionCreator.vue +++ b/client/src/components/Collections/ListCollectionCreator.vue @@ -9,6 +9,7 @@ import { computed, ref, watch } from "vue"; import draggable from "vuedraggable"; import type { HDASummary, HistoryItemSummary } from "@/api"; +import { useConfirmDialog } from "@/composables/confirmDialog"; import { Toast } from "@/composables/toast"; import STATES from "@/mvc/dataset/states"; import { useDatatypesMapperStore } from "@/stores/datatypesMapperStore"; @@ -41,6 +42,7 @@ const invalidElements = ref([]); const workingElements = ref([]); const selectedDatasetElements = ref([]); const hideSourceItems = ref(props.defaultHideSourceItems || false); +const atLeastOneElement = ref(true); const atLeastOneDatasetIsSelected = computed(() => { return selectedDatasetElements.value.length > 0; @@ -227,13 +229,24 @@ function clickSelectAll() { return element.id; }); } +const { confirm } = useConfirmDialog(); -function clickedCreate(collectionName: string) { +async function clickedCreate(collectionName: string) { checkForDuplicates(); const returnedElements = props.fromSelection ? workingElements.value : inListElements.value; + atLeastOneElement.value = returnedElements.length > 0; + + let confirmed = false; + if (!atLeastOneElement.value) { + confirmed = await confirm("Are you sure you want to create a list with no datasets?", { + title: "Create an empty list", + okTitle: "Create", + okVariant: "primary", + }); + } - if (state.value !== "error") { + if (state.value !== "error" && (atLeastOneElement.value || confirmed)) { emit("clicked-create", returnedElements, collectionName, hideSourceItems.value); } } @@ -370,6 +383,18 @@ function renameElement(element: any, name: string) { +
+ + {{ localize("At least one element is needed for the list.") }} + + + {{ localize("Cancel") }} + + {{ localize("and reselect new elements.") }} + + +
+
{{ diff --git a/client/src/components/Collections/PairedListCollectionCreator.vue b/client/src/components/Collections/PairedListCollectionCreator.vue index 86e4914cb193..ba46d2139934 100644 --- a/client/src/components/Collections/PairedListCollectionCreator.vue +++ b/client/src/components/Collections/PairedListCollectionCreator.vue @@ -13,6 +13,7 @@ import { computed, ref, watch } from "vue"; import draggable from "vuedraggable"; import type { HDASummary, HistoryItemSummary } from "@/api"; +import { useConfirmDialog } from "@/composables/confirmDialog"; import { Toast } from "@/composables/toast"; import STATES from "@/mvc/dataset/states"; import { useDatatypesMapperStore } from "@/stores/datatypesMapperStore"; @@ -81,6 +82,7 @@ const invalidElements = ref([]); const generatedPairs = ref([]); const selectedForwardElement = ref(null); const selectedReverseElement = ref(null); +const atLeastOnePair = ref(true); // Filters const forwardFilter = ref(COMMON_FILTERS[DEFAULT_FILTER][0] || ""); @@ -552,32 +554,6 @@ function _addToUnpaired(dataset: HDASummary) { workingElements.value.splice(binSearchSortedIndex(0, workingElements.value.length), 0, dataset); } -// /** add a dataset to the unpaired list in it's proper order */ -// _addToUnpaired: function (dataset) { -// // currently, unpaired is natural sorted by name, use binary search to find insertion point -// var binSearchSortedIndex = (low, hi) => { -// if (low === hi) { -// return low; -// } - -// var mid = Math.floor((hi - low) / 2) + low; - -// var compared = naturalSort(dataset.name, this.workingElements[mid].name); - -// if (compared < 0) { -// return binSearchSortedIndex(low, mid); -// } else if (compared > 0) { -// return binSearchSortedIndex(mid + 1, hi); -// } -// // walk the equal to find the last -// while (this.workingElements[mid] && this.workingElements[mid].name === dataset.name) { -// mid++; -// } -// return mid; -// }; - -// this.workingElements.splice(binSearchSortedIndex(0, this.workingElements.length), 0, dataset); -// }, /** * Unpair a pair, removing it from paired, and adding the fwd,rev @@ -749,9 +725,22 @@ function addUploadedFiles(files: HDASummary[]) { }); } +const { confirm } = useConfirmDialog(); + async function clickedCreate(collectionName: string) { checkForDuplicates(); - if (state.value == "build") { + atLeastOnePair.value = generatedPairs.value.length > 0; + + let confirmed = false; + if (!atLeastOnePair.value) { + confirmed = await confirm("Are you sure you want to create a list with no pairs?", { + title: "Create an empty list of pairs", + okTitle: "Create", + okVariant: "primary", + }); + } + + if (state.value == "build" && (atLeastOnePair.value || confirmed)) { emit("clicked-create", generatedPairs.value, collectionName, hideSourceItems.value); } } @@ -827,6 +816,19 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) {
+ +
+ + {{ localize("At least one pair is needed for the list of pairs.") }} + + + {{ localize("Cancel") }} + + {{ localize("and reselect new elements.") }} + + +
+
{{ @@ -842,6 +844,7 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) {
+
{{ @@ -853,6 +856,7 @@ function _naiveStartingAndEndingLCS(s1: string, s2: string) { {{ localize("Please fix these duplicates and try again.") }}
+