diff --git a/src/components/Dashboard/common/ObjectSelect.jsx b/src/components/Dashboard/common/ObjectSelect.jsx index 393b158a..76ab3a3b 100644 --- a/src/components/Dashboard/common/ObjectSelect.jsx +++ b/src/components/Dashboard/common/ObjectSelect.jsx @@ -25,6 +25,14 @@ const areValuesEqual = (v1, v2) => { return String(id1) === String(id2) } +const toSelectValue = (id) => { + if (id == null || id === '') return null + return String(id).toLowerCase() +} + +const getValueId = (item) => + item && typeof item === 'object' ? item._id : item + const getFirstSelectableLeaf = (nodes) => { if (!Array.isArray(nodes)) return null for (const node of nodes) { @@ -69,6 +77,23 @@ const isValueInTree = (nodes, id) => { return findTreeNodeByValue(nodes, id) != null } +const getSelectValueFromExternal = (externalValue, multiple, nodes) => { + if (externalValue == null || !Array.isArray(nodes) || nodes.length === 0) { + return undefined + } + + if (multiple) { + const values = Array.isArray(externalValue) ? externalValue : [] + const ids = values + .map((item) => toSelectValue(getValueId(item))) + .filter((id) => id != null && isValueInTree(nodes, id)) + return ids + } + + const node = findTreeNodeByValue(nodes, getValueId(externalValue)) + return node?.value +} + const isExternalValueMissing = ( externalValue, multiple, @@ -528,9 +553,27 @@ const ObjectSelect = ({ setObjectList(objects) setTreeData(treeNodes) treeDataRef.current = treeNodes + + const syncedValue = getSelectValueFromExternal( + valueRef.current, + multiple, + treeNodes + ) + if (multiple) { + if (Array.isArray(syncedValue) && syncedValue.length > 0) { + setTreeSelectValue(syncedValue) + setValueNotFound(false) + clearedMissingValueRef.current = false + } + } else if (syncedValue != null) { + setTreeSelectValue(syncedValue) + setValueNotFound(false) + clearedMissingValueRef.current = false + } + return { treeNodes, objects } }, - [buildTreeData] + [buildTreeData, multiple] ) const buildFilterFromNode = useCallback( @@ -633,6 +676,17 @@ const ObjectSelect = ({ const onTreeSelectChange = useCallback( (value) => { + const isEmptySelection = multiple + ? !Array.isArray(value) || value.length === 0 + : value == null || value === '' + if ( + isEmptySelection && + treeDataRef.current.length === 0 && + valueRef.current != null + ) { + return + } + setValueNotFound(false) clearedMissingValueRef.current = false // Mark this as an internal change @@ -827,7 +881,7 @@ const ObjectSelect = ({ setExpandedKeys([...new Set(pathKeys)]) setTreeSelectValue( value - .map((item) => (item && typeof item === 'object' ? item._id : item)) + .map((item) => toSelectValue(getValueId(item))) .filter((id) => id != null) ) setInitialized(true) @@ -880,7 +934,7 @@ const ObjectSelect = ({ setExpandedKeys(pathKeys) // Fetch with the new filter handleFetchObjectsProperties(valueFilter) - setTreeSelectValue(valueRef.current._id) + setTreeSelectValue(toSelectValue(valueRef.current._id)) setInitialized(true) return } @@ -905,7 +959,13 @@ const ObjectSelect = ({ setInitialized(true) } } - handleValue() + const timeoutId = setTimeout(() => { + handleValue() + }, 10) + + return () => { + clearTimeout(timeoutId) + } }, [ value, filter, @@ -940,6 +1000,7 @@ const ObjectSelect = ({ setTreeVersion((v) => v + 1) setExpandedKeys([]) setInitialized(false) + valueRef.current = null onTreeSelectChange(null) setTreeSelectValue(null) setInitialLoading(true) @@ -963,7 +1024,12 @@ const ObjectSelect = ({ if (changeSource == 'external') { setObjectPropertiesTree({}) setTreeData([]) + treeDataRef.current = [] setInitialized(false) + setInitialLoading(true) + valueRef.current = null + clearedMissingValueRef.current = false + setValueNotFound(false) prevValuesRef.current = { type, masterFilter } }