diff --git a/client/src/api/datasets.ts b/client/src/api/datasets.ts index c6096ea18f65..2a568f77130c 100644 --- a/client/src/api/datasets.ts +++ b/client/src/api/datasets.ts @@ -67,7 +67,7 @@ export async function purgeDataset(datasetId: string) { } const datasetCopy = fetcher.path("/api/histories/{history_id}/contents/{type}s").method("post").create(); -type HistoryContentsArgs = FetchArgType; +export type HistoryContentsArgs = FetchArgType; export async function copyDataset( datasetId: HistoryContentsArgs["content"], historyId: HistoryContentsArgs["history_id"], diff --git a/client/src/api/index.ts b/client/src/api/index.ts index d1dbc8854bbb..be992a9a504f 100644 --- a/client/src/api/index.ts +++ b/client/src/api/index.ts @@ -128,6 +128,14 @@ export interface DCECollection extends DCESummary { object: DCObject; } +/** + * DatasetCollectionElement specific type for datasets. + */ +export interface DCEDataset extends DCESummary { + element_type: "hda"; + object: HDAObject; +} + /** * Contains summary information about a HDCA (HistoryDatasetCollectionAssociation). * @@ -148,6 +156,8 @@ export type HDCADetailed = components["schemas"]["HDCADetailed"]; */ export type DCObject = components["schemas"]["DCObject"]; +export type HDAObject = components["schemas"]["HDAObject"]; + export type DatasetCollectionAttributes = components["schemas"]["DatasetCollectionAttributesResult"]; export type ConcreteObjectStoreModel = components["schemas"]["ConcreteObjectStoreModel"]; @@ -187,6 +197,13 @@ export function isCollectionElement(element: DCESummary): element is DCECollecti return element.element_type === "dataset_collection"; } +/** + * Returns true if the given element of a collection is a Dataset. + */ +export function isDatasetElement(element: DCESummary): element is DCEDataset { + return element.element_type === "hda"; +} + /** * Returns true if the given dataset entry is an instance of DatasetDetails. */ diff --git a/client/src/components/History/CurrentCollection/CollectionPanel.vue b/client/src/components/History/CurrentCollection/CollectionPanel.vue index 825ba5a5baa5..81030f035777 100644 --- a/client/src/components/History/CurrentCollection/CollectionPanel.vue +++ b/client/src/components/History/CurrentCollection/CollectionPanel.vue @@ -8,6 +8,7 @@ import { canMutateHistory, isCollectionElement, isHDCA } from "@/api"; import ExpandedItems from "@/components/History/Content/ExpandedItems"; import { updateContentFields } from "@/components/History/model/queries"; import { useCollectionElementsStore } from "@/stores/collectionElementsStore"; +import { setItemDragstart } from "@/utils/setDrag"; import CollectionDetails from "./CollectionDetails.vue"; import CollectionNavigation from "./CollectionNavigation.vue"; @@ -158,6 +159,7 @@ watch( :expand-dataset="isExpanded(item)" :is-dataset="item.element_type == 'hda'" :filterable="filterable" + @drag-start="setItemDragstart(item, $event)" @update:expand-dataset="setExpanded(item, $event)" @view-collection="onViewDatasetCollectionElement(item)" /> diff --git a/client/src/components/History/CurrentHistory/HistoryPanel.vue b/client/src/components/History/CurrentHistory/HistoryPanel.vue index ca6738f303dd..deb96c456c88 100644 --- a/client/src/components/History/CurrentHistory/HistoryPanel.vue +++ b/client/src/components/History/CurrentHistory/HistoryPanel.vue @@ -3,8 +3,15 @@ import { BAlert } from "bootstrap-vue"; import { storeToRefs } from "pinia"; import { computed, onMounted, type Ref, ref, set as VueSet, unref, watch } from "vue"; -import { type HistoryItemSummary, type HistorySummaryExtended, isHistoryItem, userOwnsHistory } from "@/api"; -import { copyDataset } from "@/api/datasets"; +import { + type HDAObject, + type HistoryItemSummary, + type HistorySummaryExtended, + isDatasetElement, + isHistoryItem, + userOwnsHistory, +} from "@/api"; +import { copyDataset, HistoryContentsArgs } from "@/api/datasets"; import ExpandedItems from "@/components/History/Content/ExpandedItems"; import SelectedItems from "@/components/History/Content/SelectedItems"; import { HistoryFilters } from "@/components/History/HistoryFilters"; @@ -17,7 +24,7 @@ import { useHistoryItemsStore } from "@/stores/historyItemsStore"; import { useHistoryStore } from "@/stores/historyStore"; import { useUserStore } from "@/stores/userStore"; import { type Alias, getOperatorForAlias } from "@/utils/filtering"; -import { setDrag } from "@/utils/setDrag"; +import { setItemDragstart } from "@/utils/setDrag"; import HistoryCounter from "./HistoryCounter.vue"; import HistoryDetails from "./HistoryDetails.vue"; @@ -54,6 +61,8 @@ interface Props { isMultiViewItem?: boolean; } +type DraggableHistoryItem = HistoryItemSummary | HDAObject; + type ContentItemRef = Record | null>>; const props = withDefaults(defineProps(), { @@ -227,7 +236,13 @@ function getDragData() { const eventStore = useEventStore(); const dragItems = eventStore.getDragItems(); // Filter out any non-history items - const historyItems = dragItems?.filter((item: any) => isHistoryItem(item)) as HistoryItemSummary[]; + const historyItems = dragItems?.map((item: any) => { + if (isHistoryItem(item)) { + return item; + } else if (isDatasetElement(item)) { + return item.object; + } + }) as DraggableHistoryItem[]; const historyId = historyItems?.[0]?.history_id; return { data: historyItems, sameHistory: historyId === props.history.id, multiple: historyItems?.length > 1 }; } @@ -381,10 +396,18 @@ async function onDrop() { try { // iterate over the data array and copy each item to the current history for (const item of data) { - const dataSource = item.history_content_type === "dataset" ? "hda" : "hdca"; - await copyDataset(item.id, props.history.id, item.history_content_type, dataSource); + let dataSource: HistoryContentsArgs["source"]; + const type = item.history_content_type as "dataset" | "dataset_collection" | undefined; + if (type) { + // it's a `HistoryItemSummary` + dataSource = type === "dataset" ? "hda" : "hdca"; + } else { + // it's a `HDAObject` from a collection + dataSource = "hda"; + } + await copyDataset(item.id, props.history.id, type, dataSource); - if (item.history_content_type === "dataset") { + if (dataSource === "hda") { datasetCount++; if (!multiple) { Toast.info("Dataset copied to history"); @@ -451,24 +474,6 @@ function arrowNavigate(item: HistoryItemSummary, eventKey: string) { } return nextItem; } - -function setItemDragstart( - item: HistoryItemSummary, - itemIsSelected: boolean, - selectedItems: Map, - selectionSize: number, - event: DragEvent -) { - if (itemIsSelected && selectionSize > 1) { - const selectedItemsObj: any = {}; - for (const [key, value] of selectedItems) { - selectedItemsObj[key] = value; - } - setDrag(event, selectedItemsObj, true); - } else { - setDrag(event, item as any); - } -}