Skip to content

Commit

Permalink
add multiple item drag and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedhamidawan committed Feb 22, 2024
1 parent 7c3a954 commit 5025693
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 16 deletions.
6 changes: 6 additions & 0 deletions client/src/components/DragGhost.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faPaperPlane } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { storeToRefs } from "pinia";
import { useEventStore } from "stores/eventStore";
import { computed } from "vue";
Expand All @@ -10,9 +11,14 @@ import TextShort from "@/components/Common/TextShort.vue";
library.add(faPaperPlane);
const eventStore = useEventStore();
const { multipleDragData } = storeToRefs(eventStore);
const name = computed(() => {
const dragData = eventStore.getDragData();
if (multipleDragData.value) {
const count = Object.keys(dragData).length;
return `${count} items`;
}
return dragData?.name ?? "Draggable";
});
</script>
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/History/Content/ContentItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ import { updateContentFields } from "components/History/model/queries";
import StatelessTags from "components/TagsMultiselect/StatelessTags";
import { useEntryPointStore } from "stores/entryPointStore";
import { clearDrag, setDrag } from "@/utils/setDrag.js";
import { clearDrag } from "@/utils/setDrag.js";
import CollectionDescription from "./Collection/CollectionDescription";
import { JobStateSummary } from "./Collection/JobStateSummary";
Expand Down Expand Up @@ -287,9 +287,9 @@ export default {
this.$emit("delete", this.item, recursive);
},
onDragStart(evt) {
setDrag(evt, this.item);
this.$emit("drag-start", evt);
},
onDragEnd: function () {
onDragEnd() {
clearDrag();
},
onEdit() {
Expand Down
62 changes: 52 additions & 10 deletions client/src/components/History/CurrentHistory/HistoryPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { HistoryFilters } from "@/components/History/HistoryFilters";
import { deleteContent, updateContentFields } from "@/components/History/model/queries";
import { Toast } from "@/composables/toast";
import { startWatchingHistory } from "@/store/historyStore/model/watchHistory";
import { useEventStore } from "@/stores/eventStore";
import { type HistoryItem, useHistoryItemsStore } from "@/stores/historyItemsStore";
import { useHistoryStore } from "@/stores/historyStore";
import { type Alias, getOperatorForAlias } from "@/utils/filtering";
import { setDrag } from "@/utils/setDrag";
import HistoryCounter from "./HistoryCounter.vue";
import HistoryDetails from "./HistoryDetails.vue";
Expand Down Expand Up @@ -312,26 +314,45 @@ function onDragLeave(e: DragEvent) {
}
async function onDrop(evt: any) {
const eventStore = useEventStore();
showDropZone.value = false;
let data;
let data: HistoryItem[] | undefined;
let historyId: string | undefined;
const multiple = eventStore.multipleDragData;
try {
data = JSON.parse(evt.dataTransfer.getData("text"))[0];
if (multiple) {
const dragData = eventStore.getDragData() as Record<string, HistoryItem>;
// set historyId to the first history_id in the multiple drag data
const firstItem = Object.values(dragData)[0];
if (firstItem) {
historyId = firstItem.history_id;
}
data = Object.values(dragData);
} else {
data = [eventStore.getDragData() as HistoryItem];
if (data[0]) {
historyId = data[0].history_id;
}
}
} catch (error) {
// this was not a valid object for this dropzone, ignore
}
if (!data || data.history_id === props.history.id) {
if (!data || historyId === props.history.id) {
return;
}
try {
const dataSource = data.history_content_type === "dataset" ? "hda" : "hdca";
await copyDataset(data.id, props.history.id, data.history_content_type, dataSource);
if (data.history_content_type === "dataset") {
Toast.info("Dataset copied to history");
} else {
Toast.info("Collection copied to history");
// 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);
if (item.history_content_type === "dataset") {
Toast.info("Dataset copied to history");
} else {
Toast.info("Collection copied to history");
}
}
historyStore.loadHistoryById(props.history.id);
Expand Down Expand Up @@ -378,6 +399,24 @@ function arrowNavigate(item: HistoryItem, eventKey: string) {
}
return nextItem;
}
function setItemDragstart(
item: HistoryItem,
showSelection: boolean,
selectedItems: Map<string, HistoryItem>,
selectionSize: number,
event: DragEvent
) {
if (showSelection && 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 @@ -528,6 +567,9 @@ function arrowNavigate(item: HistoryItem, eventKey: string) {
arrowNavigate(item, $event);
initKeySelection();
"
@drag-start="
setItemDragstart(item, showSelection, selectedItems, selectionSize, $event)
"
@hide-selection="setShowSelection(false)"
@shift-select="(eventKey) => shiftSelect(nextSelections(item, eventKey))"
@select-all="selectAllInCurrentQuery(historyItems)"
Expand Down
7 changes: 6 additions & 1 deletion client/src/stores/eventStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,25 @@ export type EventData = { [key: string]: unknown };

export const useEventStore = defineStore("eventStore", () => {
const dragData: Ref<EventData | null> = ref(null);
const multipleDragData: Ref<boolean> = ref(false);

function clearDragData() {
dragData.value = null;
multipleDragData.value = false;
}

function getDragData() {
return dragData.value;
}

function setDragData(data: EventData) {
function setDragData(data: EventData, multiple = false) {
dragData.value = data;
multipleDragData.value = multiple;
}

return {
multipleDragData,
dragData,
clearDragData,
getDragData,
setDragData,
Expand Down
4 changes: 2 additions & 2 deletions client/src/utils/setDrag.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
*/
import { useEventStore } from "stores/eventStore";

export function setDrag(evt, data = null) {
export function setDrag(evt, data = null, multiple = false) {
const eventStore = useEventStore();
if (data) {
evt.dataTransfer.setData("text", JSON.stringify([data]));
// data submitted through datatransfer is only available upon drop,
// in order to access the drop data immediately this event store is used.
eventStore.setDragData(data);
eventStore.setDragData(data, multiple);
}
evt.dataTransfer.dropEffect = "move";
evt.dataTransfer.effectAllowed = "move";
Expand Down

0 comments on commit 5025693

Please sign in to comment.