Skip to content

Commit

Permalink
[24.1] Allow drag and drop for collection elements
Browse files Browse the repository at this point in the history
We extract the `HDAObject` from the `DCESummary` to be able to drag and drop it.
For now, this works on dragging and dropping items to histories, since that process only needs the dataset's id. However, this doesn't work on tool forms; as we would need to get the full `HDASummary` to do that.
  • Loading branch information
ahmedhamidawan committed Aug 16, 2024
1 parent ea35ee5 commit 4ad37d0
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 28 deletions.
2 changes: 1 addition & 1 deletion client/src/api/datasets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof datasetCopy>;
export type HistoryContentsArgs = FetchArgType<typeof datasetCopy>;
export async function copyDataset(
datasetId: HistoryContentsArgs["content"],
historyId: HistoryContentsArgs["history_id"],
Expand Down
17 changes: 17 additions & 0 deletions client/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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).
*
Expand All @@ -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"];
Expand Down Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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)" />
</template>
Expand Down
59 changes: 32 additions & 27 deletions client/src/components/History/CurrentHistory/HistoryPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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";
Expand Down Expand Up @@ -54,6 +61,8 @@ interface Props {
isMultiViewItem?: boolean;
}
type DraggableHistoryItem = HistoryItemSummary | HDAObject;
type ContentItemRef = Record<string, Ref<InstanceType<typeof ContentItem> | null>>;
const props = withDefaults(defineProps<Props>(), {
Expand Down Expand Up @@ -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 };
}
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -451,24 +474,6 @@ function arrowNavigate(item: HistoryItemSummary, eventKey: string) {
}
return nextItem;
}
function setItemDragstart(
item: HistoryItemSummary,
itemIsSelected: boolean,
selectedItems: Map<string, HistoryItemSummary>,
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);
}
}
</script>

<template>
Expand Down Expand Up @@ -629,10 +634,10 @@ function setItemDragstart(
@drag-start="
setItemDragstart(
item,
$event,
showSelection && isSelected(item),
selectedItems,
selectionSize,
$event
selectedItems
)
"
@hide-selection="setShowSelection(false)"
Expand Down
18 changes: 18 additions & 0 deletions client/src/utils/setDrag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,21 @@ export function clearDrag() {
const eventStore = useEventStore();
eventStore.clearDragData();
}

export function setItemDragstart<T>(
item: T,
event: DragEvent,
itemIsSelected = false,
selectionSize = 0,
selectedItems?: Map<string, T>
) {
if (selectedItems && itemIsSelected && selectionSize > 1) {
const selectedItemsObj: Record<string, T> = {};
for (const [key, value] of selectedItems) {
selectedItemsObj[key] = value;
}
setDrag(event, selectedItemsObj, true);
} else {
setDrag(event, item as any);
}
}

0 comments on commit 4ad37d0

Please sign in to comment.