import { faExclamation, faSpinner, type IconDefinition } from "@fortawesome/free-solid-svg-icons"; import { computed, type Ref } from "vue"; import { type HDASummary, type HistoryItemSummary, isHDA } from "@/api"; import type { ComponentColor } from "@/components/BaseComponents/componentVariants"; import type { UploadRowModel } from "@/components/Upload/model"; import { useHistoryItemsStore } from "@/stores/historyItemsStore"; import STATES from "@/utils/datasetStates"; const REFER_TO_HISTORY_MSG = "Refer to the history panel to view dataset state."; /** Terminal states that are not usable from an upload (anything but `ok` or `deferred`) */ const UNUSABLE_FROM_UPLOAD_STATES = Object.values(STATES.READY_STATES).filter( (state) => state !== STATES.OK && state !== STATES.DEFERRED, ); /** * For given uploaded items, monitor the states of those items from the history. * * @param uploadValues - The uploaded values from the upload `DefaultBox` * @param historyId - The ID of the history being uploaded to * @param enableStart - If an upload is enabled to start * @param creatingPairedType - If the user has selected to create a `paired` * or `list:paired` collection JUST from these uploads */ export function monitorUploadedHistoryItems( uploadValues: Ref, historyId: Ref, enableStart: Ref, creatingPairedType: Ref, ) { const historyItemsStore = useHistoryItemsStore(); /** Uploaded items from the history */ const uploadedHistoryItems = computed(() => { // Get all successfully uploaded datasets const uploadedDatasets: HistoryItemSummary[] = []; uploadValues.value.forEach((model) => { const outputs = model.outputs; // Some uploads (e.g.: in the case of remote file upload) may have the entire set of uploaded files // in the `outputs` object, while typically, the `outputs` object contains each individual upload. if (outputs) { Object.entries(outputs).forEach((output) => { const outputDetails = output[1] as HistoryItemSummary; // Since there is a possibility of all uploads being in the `outputs` object, // we need to ensure that we only add unique datasets to the list. if (!uploadedDatasets.some((item) => item.id === outputDetails.id)) { uploadedDatasets.push(outputDetails); } }); } }); // Get uploaded datasets from history const historyItems = historyItemsStore.getHistoryItems(historyId.value, ""); return uploadedDatasets .map((item) => historyItems.find((historyItem) => historyItem.id === item.id)) .filter((item) => isHDA(item)) as HDASummary[]; }); const uploadedHistoryItemsReady = computed(() => uploadedHistoryItems.value.every((item) => item && item.extension !== "auto"), ); // TODO: Could be refactored to use `useCollectionCreator.isElementInvalid()` instead? (with the added `auto` check) const uploadedHistoryItemsOk = computed(() => uploadedHistoryItems.value.filter( (item) => item && !UNUSABLE_FROM_UPLOAD_STATES.includes(item.state) && item.extension !== "auto", ), ); const historyItemsStateInfo = computed<{ color?: ComponentColor; message: string; icon?: IconDefinition; spin?: boolean; } | null>(() => { if (!enableStart.value && uploadValues.value.length) { if (!uploadedHistoryItems.value?.length) { return { color: "blue", message: `Dataset(s) not uploaded yet. ${REFER_TO_HISTORY_MSG}`, icon: faSpinner, spin: true, }; } else if (!uploadedHistoryItemsReady.value) { return { color: "blue", message: `Waiting for upload(s) to have valid extension(s). ${REFER_TO_HISTORY_MSG}`, icon: faSpinner, spin: true, }; } else if (uploadedHistoryItems.value.length > uploadedHistoryItemsOk.value.length) { return { color: "orange", message: `Only ${uploadedHistoryItemsOk.value.length} / ${uploadedHistoryItems.value.length} uploaded items are usable. ${REFER_TO_HISTORY_MSG}`, icon: faExclamation, }; } else if (creatingPairedType.value && uploadedHistoryItemsOk.value.length % 2 !== 0) { return { color: "red", message: "Please upload an even number of datasets to create a dataset pair or a list of dataset pairs.", icon: faExclamation, }; } else if (uploadedHistoryItemsOk.value.length) { return { color: "blue", // Not "green" because this is for a `GButton`, that is ready message: "Upload(s) ready to be used.", }; } else { return null; } } else { return null; } }); return { /** Uploaded history items with the `ok` state */ uploadedHistoryItemsOk, /** If all uploaded history items have achieved a terminal state */ uploadedHistoryItemsReady, historyItemsStateInfo, }; }