1- import React , { useState , useCallback } from 'react' ;
1+ import React , { useState , useCallback , useMemo } from 'react' ;
22import PropTypes from 'prop-types' ;
33import { Edit } from '@carbon/react/icons' ;
44import { MultiSelect } from '@carbon/react' ;
55import { isEmpty } from 'lodash-es' ;
6+ import { v4 as uuidv4 } from 'uuid' ;
7+ import { MisuseOutline } from '@carbon/icons-react' ;
68
79import DataSeriesFormItemModal from '../../CardEditor/CardEditForm/CardEditFormItems/DataSeriesFormItemModal' ;
810import List from '../../List/List' ;
@@ -13,6 +15,9 @@ import {
1315 DashboardEditorActionsPropTypes ,
1416 defaultDashboardEditorActionsProps ,
1517} from '../../DashboardEditor/editorUtils' ;
18+ import HierarchyDataFormItems , {
19+ isHierarchyDataItem ,
20+ } from '../../CardEditor/CardEditForm/CardEditFormItems/HierarchyDataFormItems/HierarchyDataFormItems' ;
1621
1722const { iotPrefix } = settings ;
1823
@@ -47,7 +52,8 @@ const propTypes = {
4752 i18n : PropTypes . shape ( {
4853 selectDataItemsText : PropTypes . string ,
4954 dataItemText : PropTypes . string ,
50- editText : PropTypes . string ,
55+ edit : PropTypes . string ,
56+ remove : PropTypes . string ,
5157 dataItemEditorDataItemTitle : PropTypes . string ,
5258 dataItemEditorDataItemCustomLabel : PropTypes . string ,
5359 dataItemEditorDataItemUnit : PropTypes . string ,
@@ -85,7 +91,8 @@ const defaultProps = {
8591 i18n : {
8692 selectDataItemsText : 'Select data items' ,
8793 dataItemText : 'Data items' ,
88- editText : 'Edit' ,
94+ edit : 'Edit' ,
95+ remove : 'Remove' ,
8996 dataItemEditorDataItemTitle : 'Data items' ,
9097 dataItemEditorDataItemCustomLabel : 'Custom label' ,
9198 dataItemEditorDataItemUnit : 'Unit' ,
@@ -102,10 +109,12 @@ const defaultProps = {
102109} ;
103110
104111export const formatDataItemsForDropdown = ( dataItems ) =>
105- dataItems ?. map ( ( { dataSourceId, label } ) => ( {
106- id : dataSourceId ,
107- label,
108- } ) ) ;
112+ dataItems
113+ ?. filter ( ( dataItem ) => ! isHierarchyDataItem ( dataItem ) ) // filter hierarchy data items
114+ ?. map ( ( { dataSourceId, label } ) => ( {
115+ id : dataSourceId ,
116+ label,
117+ } ) ) ;
109118
110119const HotspotEditorDataSourceTab = ( {
111120 hotspot,
@@ -127,15 +136,14 @@ const HotspotEditorDataSourceTab = ({
127136 const selectedItemsArray = hotspot . content ?. attributes || [ ] ;
128137
129138 const baseClassName = `${ iotPrefix } --card-edit-form` ;
130- const initialSelectedItems = formatDataItemsForDropdown ( selectedItemsArray ) ;
131139 const { onEditDataItem } = actions ;
132140
133141 const handleSelectionChange = ( { selectedItems } ) => {
134142 const newArray = [ ] ;
135143 // loop through selected Items and find their selectedItemsArray object or the dataItem object with same id
136144 selectedItems . forEach ( ( item ) => {
137145 const containedItem = selectedItemsArray . find (
138- ( selectedItem ) => selectedItem . dataItemId === item . id
146+ ( selectedItem ) => selectedItem . dataSourceId === item . id
139147 ) ;
140148 const containedDataItem = dataItems . find (
141149 ( selectedItem ) => selectedItem . dataItemId === item . id
@@ -146,17 +154,37 @@ const HotspotEditorDataSourceTab = ({
146154 newArray . push ( containedDataItem ) ;
147155 }
148156 } ) ;
157+
158+ // Add existing hierarchy data items
159+ newArray . push ( ...selectedItemsArray . filter ( ( item ) => isHierarchyDataItem ( item ) ) ) ;
160+
149161 onChange ( { attributes : newArray } ) ;
150162 } ;
151163
164+ const handleHierarchyDataItemChange = useCallback (
165+ ( items ) => {
166+ const updatedItems = items ?. map ( ( item ) => ( {
167+ ...item ,
168+ // create a unique dataSourceId
169+ dataSourceId : `${ item . dataItemId } _${ uuidv4 ( ) } ` ,
170+ } ) ) ;
171+
172+ const selectedItems = [ ...selectedItemsArray , ...updatedItems ] ;
173+
174+ onChange ( { attributes : selectedItems } ) ;
175+ } ,
176+ [ onChange , selectedItemsArray ]
177+ ) ;
178+
152179 // MultiSelect
153- // For the initial selection to work the objects in prop "initialSelectedItems "
180+ // For the initial selection to work the objects in prop "selectedItemsArray "
154181 // must be identical to the objects in prop "items". It is not enough that the
155182 // ids are the same. Therefore, we must adjust the labels in "items" if they have
156- // been modified in the "initialSelectedItems ".
183+ // been modified in the "selectedItemsArray ".
157184 const multiSelectItems = formatDataItemsForDropdown ( dataItems ) . map ( ( item ) => ( {
158185 ...item ,
159- label : initialSelectedItems . find ( ( selected ) => selected . id === item . id ) ?. label ?? item . label ,
186+ label :
187+ selectedItemsArray . find ( ( selected ) => selected . dataSourceId === item . id ) ?. label ?? item . label ,
160188 } ) ) ;
161189
162190 const handleEditButton = useCallback (
@@ -182,6 +210,64 @@ const HotspotEditorDataSourceTab = ({
182210 [ cardConfig , onEditDataItem , dataItems ]
183211 ) ;
184212
213+ const handleRemoveButton = useCallback (
214+ ( selectedItem ) => {
215+ const newArray = selectedItemsArray . filter (
216+ ( item ) => item . dataSourceId !== selectedItem . dataSourceId
217+ ) ;
218+
219+ onChange ( { attributes : newArray } ) ;
220+ } ,
221+ [ selectedItemsArray , onChange ]
222+ ) ;
223+
224+ const generateListItems = useCallback (
225+ ( data , isHierarchy = false ) =>
226+ data
227+ ?. filter ( ( dataItem ) => isHierarchyDataItem ( dataItem ) === isHierarchy )
228+ ?. map ( ( dataItem ) => ( {
229+ id : dataItem . dataSourceId ,
230+ content : {
231+ value : dataItem . label ,
232+ rowActions : ( ) => [
233+ < Button
234+ key = { `data-item-${ dataItem . dataSourceId } ` }
235+ renderIcon = { Edit }
236+ hasIconOnly
237+ kind = "ghost"
238+ size = "sm"
239+ onClick = { ( ) => handleEditButton ( dataItem ) }
240+ iconDescription = { mergedI18n . edit }
241+ tooltipPosition = "left"
242+ tooltipAlignment = "center"
243+ /> ,
244+ < Button
245+ key = { `data-item-${ dataItem . dataSourceId } _remove` }
246+ renderIcon = { MisuseOutline }
247+ hasIconOnly
248+ kind = "ghost"
249+ size = "sm"
250+ onClick = { ( ) => handleRemoveButton ( dataItem ) }
251+ iconDescription = { mergedI18n . remove }
252+ tooltipPosition = "left"
253+ tooltipAlignment = "center"
254+ /> ,
255+ ] ,
256+ } ,
257+ } ) ) ,
258+ [ handleEditButton , handleRemoveButton , mergedI18n . edit , mergedI18n . remove ]
259+ ) ;
260+
261+ const dataListItems = useMemo (
262+ ( ) => generateListItems ( selectedItemsArray ) ,
263+ [ selectedItemsArray , generateListItems ]
264+ ) ;
265+
266+ const hierarchyDataListItems = useMemo (
267+ ( ) => generateListItems ( selectedItemsArray , true ) ,
268+ [ selectedItemsArray , generateListItems ]
269+ ) ;
270+
185271 return (
186272 < div data-testid = { testID || testId } >
187273 < DataSeriesFormItemModal
@@ -211,7 +297,7 @@ const HotspotEditorDataSourceTab = ({
211297 id = { `${ cardConfig . id } _dataSourceIds` }
212298 label = { mergedI18n . selectDataItemsText }
213299 direction = "bottom"
214- initialSelectedItems = { initialSelectedItems }
300+ selectedItems = { formatDataItemsForDropdown ( selectedItemsArray ) }
215301 items = { multiSelectItems }
216302 light
217303 onChange = { handleSelectionChange }
@@ -225,23 +311,14 @@ const HotspotEditorDataSourceTab = ({
225311 emptyState = { < div /> }
226312 testId = { `${ testId } -data-source-list` }
227313 title = ""
228- items = { selectedItemsArray ?. map ( ( dataItem ) => ( {
229- id : dataItem . dataSourceId ,
230- content : {
231- value : dataItem . label ,
232- rowActions : ( ) => [
233- < Button
234- key = { `data-item-${ dataItem . dataSourceId } ` }
235- renderIcon = { Edit }
236- hasIconOnly
237- kind = "ghost"
238- size = "sm"
239- onClick = { ( ) => handleEditButton ( dataItem ) }
240- iconDescription = { mergedI18n . editText }
241- /> ,
242- ] ,
243- } ,
244- } ) ) }
314+ items = { dataListItems }
315+ />
316+ < HierarchyDataFormItems
317+ cardConfig = { cardConfig }
318+ hierarchyDataItemListItems = { hierarchyDataListItems }
319+ handleHierarchyDataItemChange = { handleHierarchyDataItemChange }
320+ i18n = { i18n }
321+ actions = { actions }
245322 />
246323 </ div >
247324 ) ;
0 commit comments