@@ -22,6 +22,7 @@ import { type EventData, useEventStore } from "@/stores/eventStore";
2222import { orList } from " @/utils/strings" ;
2323
2424import type { DataOption } from " ./types" ;
25+ import { containsDataOption } from " ./types" ;
2526import { BATCH , SOURCE , VARIANTS } from " ./variants" ;
2627
2728import FormSelection from " ../FormSelection.vue" ;
@@ -384,49 +385,24 @@ function handleIncoming(incoming: Record<string, unknown> | Record<string, unkno
384385 const incomingValues: Array <DataOption > = [];
385386 values .forEach ((currVal ) => {
386387 // Map incoming objects to data option values
387- const { newSrc, datasetCollectionDataset } = getSrcAndContentType (currVal );
388- let v: HistoryOrCollectionItem | HDAObject ;
389- if (datasetCollectionDataset ) {
390- v = datasetCollectionDataset ;
391- } else {
392- v = currVal ;
393- }
394- const newHid = isHistoryItem (v ) ? v .hid : undefined ;
395- const newId = v .id ;
396- const newName = isHistoryItem (v ) && v .name ? v .name : newId ;
397- const newValue: DataOption = {
398- id: newId ,
399- src: newSrc ,
400- batch: false ,
401- map_over_type: undefined ,
402- hid: newHid ,
403- name: newName ,
404- keep: true ,
405- tags: [],
406- };
407- if (isHistoryItem (v ) && isHDCA (v ) && props .collectionTypes ?.length > 0 ) {
408- const itemCollectionType = v .collection_type ;
409- if (! props .collectionTypes .includes (itemCollectionType as CollectionType )) {
410- const mapOverType = props .collectionTypes .find ((collectionType ) =>
411- itemCollectionType .endsWith (collectionType )
412- );
413- if (! mapOverType ) {
414- return false ;
415- }
416- newValue [" batch" ] = true ;
417- newValue [" map_over_type" ] = mapOverType ;
418- }
388+ const newValue = toDataOption (currVal );
389+ if (! newValue ) {
390+ return false ;
419391 }
420392 // Verify that new value has corresponding option
421- const keepKey = ` ${newId }_${newSrc } ` ;
422- const existingOptions = props .options && props .options [newSrc ];
423- const foundOption = existingOptions && existingOptions .find ((option ) => option .id === newId );
393+ const keepKey = ` ${newValue . id }_${newValue . src } ` ;
394+ const existingOptions = props .options && props .options [newValue . src ];
395+ const foundOption = existingOptions && existingOptions .find ((option ) => option .id === newValue . id );
424396 if (! foundOption && ! (keepKey in keepOptions )) {
425- keepOptions [keepKey ] = { label: ` ${newHid || " Selected" }: ${newName } ` , value: newValue };
397+ keepOptions [keepKey ] = {
398+ label: ` ${newValue .hid || " Selected" }: ${newValue .name } ` ,
399+ value: newValue ,
400+ };
426401 }
427402 // Add new value to list
428403 incomingValues .push (newValue );
429404 });
405+ let hasDuplicates = false ;
430406 if (incomingValues .length > 0 && incomingValues [0 ]) {
431407 // Set new value
432408 const config = currentVariant .value ;
@@ -435,21 +411,68 @@ function handleIncoming(incoming: Record<string, unknown> | Record<string, unkno
435411 if (config .multiple ) {
436412 const newValues = currentValue .value ? currentValue .value .slice () : [];
437413 incomingValues .forEach ((v ) => {
438- newValues .push (v );
414+ if (containsDataOption (newValues , v )) {
415+ hasDuplicates = true ;
416+ } else {
417+ newValues .push (v );
418+ }
439419 });
440420 currentValue .value = newValues ;
441421 } else {
422+ if (containsDataOption (currentValue .value ?? [], firstValue )) {
423+ hasDuplicates = true ;
424+ }
442425 currentValue .value = [firstValue ];
443426 }
444427 } else {
445428 currentValue .value = incomingValues ;
446429 }
447430 }
431+ if (hasDuplicates ) {
432+ return false ;
433+ }
448434 }
449435 }
450436 return true ;
451437}
452438
439+ function toDataOption(item : HistoryOrCollectionItem ): DataOption | null {
440+ const { newSrc, datasetCollectionDataset } = getSrcAndContentType (item );
441+ let v: HistoryOrCollectionItem | HDAObject ;
442+ if (datasetCollectionDataset ) {
443+ v = datasetCollectionDataset ;
444+ } else {
445+ v = item ;
446+ }
447+ const newHid = isHistoryItem (v ) ? v .hid : undefined ;
448+ const newId = v .id ;
449+ const newName = isHistoryItem (v ) && v .name ? v .name : newId ;
450+ const newValue: DataOption = {
451+ id: newId ,
452+ src: newSrc ,
453+ batch: false ,
454+ map_over_type: undefined ,
455+ hid: newHid ,
456+ name: newName ,
457+ keep: true ,
458+ tags: [],
459+ };
460+ if (isHistoryItem (v ) && isHDCA (v ) && props .collectionTypes ?.length > 0 ) {
461+ const itemCollectionType = v .collection_type ;
462+ if (! props .collectionTypes .includes (itemCollectionType as CollectionType )) {
463+ const mapOverType = props .collectionTypes .find ((collectionType ) =>
464+ itemCollectionType .endsWith (collectionType )
465+ );
466+ if (! mapOverType ) {
467+ return null ;
468+ }
469+ newValue [" batch" ] = true ;
470+ newValue [" map_over_type" ] = mapOverType ;
471+ }
472+ }
473+ return newValue ;
474+ }
475+
453476/**
454477 * Open file dialog
455478 */
@@ -585,6 +608,16 @@ function isHistoryOrCollectionItem(item: EventData): item is HistoryOrCollection
585608 return isHistoryItem (item ) || isDCE (item );
586609}
587610
611+ function getNameForItem(item : HistoryOrCollectionItem ): string {
612+ if (isHistoryItem (item )) {
613+ return item .name ?? ` Item ${item .hid } ` ;
614+ } else if (isDCE (item )) {
615+ return item .element_identifier ;
616+ } else {
617+ throw new Error (" Unknown item type" );
618+ }
619+ }
620+
588621// Drag/Drop event handlers
589622function onDragEnter(evt : DragEvent ) {
590623 const eventData = eventStore .getDragItems ();
@@ -605,6 +638,13 @@ function onDragEnter(evt: DragEvent) {
605638 highlightingState = " warning" ;
606639 $emit (" alert" , ` ${historyContentType } is not an acceptable input type for this parameter. ` );
607640 }
641+ // Check if the item is already in the current value
642+ const option = toDataOption (item );
643+ const isAlreadyInValue = containsDataOption (currentValue .value ?? [], option );
644+ if (isAlreadyInValue ) {
645+ highlightingState = " warning" ;
646+ $emit (" alert" , ` ${getNameForItem (item )} is already selected. ` );
647+ }
608648 }
609649 }
610650 currentHighlighting .value = highlightingState ;
0 commit comments