diff --git a/geonode_mapstore_client/client/MapStore2 b/geonode_mapstore_client/client/MapStore2 index d28c1d37f4..ce856fe854 160000 --- a/geonode_mapstore_client/client/MapStore2 +++ b/geonode_mapstore_client/client/MapStore2 @@ -1 +1 @@ -Subproject commit d28c1d37f48df2b40089303ea92a8e1c3990449b +Subproject commit ce856fe8544476155ae3d0bbe3077be1653a8d06 diff --git a/geonode_mapstore_client/client/js/api/geonode/v2/metadata.js b/geonode_mapstore_client/client/js/api/geonode/v2/metadata.js index 1dd7afe7e5..f45fe62016 100644 --- a/geonode_mapstore_client/client/js/api/geonode/v2/metadata.js +++ b/geonode_mapstore_client/client/js/api/geonode/v2/metadata.js @@ -12,19 +12,34 @@ import { RESOURCES, getEndpointUrl } from './constants'; -import { isObject, isArray, castArray } from 'lodash'; +import isObject from 'lodash/isObject'; +import isArray from 'lodash/isArray'; +import castArray from 'lodash/castArray'; +import isEmpty from 'lodash/isEmpty'; + +const uiKeys = (entry) => Object.keys(entry).filter(propertyKey => propertyKey.indexOf('ui:') === 0); const parseUiSchema = (properties) => { return Object.keys(properties).reduce((acc, key) => { const entry = properties[key]; - const uiKeys = Object.keys(entry).filter(propertyKey => propertyKey.indexOf('ui:') === 0); - if (uiKeys.length) { - acc[key] = Object.fromEntries(uiKeys.map(uiKey => [uiKey, entry[uiKey]])); + const uiKeysRoot = uiKeys(entry); + if (uiKeysRoot.length) { + acc[key] = Object.fromEntries(uiKeysRoot.map(uiKey => [uiKey, entry[uiKey]])); + } + if (entry.type === 'array') { + const uiKeysNested = uiKeys(entry?.items); + if (uiKeysNested.length) { + acc[key] = Object.fromEntries(uiKeysNested.map(uiKey => [uiKey, entry?.items?.[uiKey]])); + } } if (entry.type === 'object') { const nestedProperties = parseUiSchema(entry?.properties); acc[key] = { ...acc[key], ...nestedProperties }; } + if (entry.type === 'array' && entry.items?.type === 'object') { + const nestedProperties = parseUiSchema(entry?.items?.properties); + acc[key] = { ...acc[key], ...(!isEmpty(nestedProperties) && {items: {...nestedProperties}}) }; + } return acc; }, {}); }; diff --git a/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/SchemaField.jsx b/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/SchemaField.jsx index 4df04dd55a..a91aa21525 100644 --- a/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/SchemaField.jsx +++ b/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/SchemaField.jsx @@ -11,8 +11,10 @@ import axios from '@mapstore/framework/libs/ajax'; import castArray from 'lodash/castArray'; import isEmpty from 'lodash/isEmpty'; import isString from 'lodash/isString'; +import template from 'lodash/template'; import Autocomplete from '../Autocomplete'; import DefaultSchemaField from '@rjsf/core/lib/components/fields/SchemaField'; +import useSchemaReference from './useSchemaReference'; function findProperty(name, properties) { return Object.keys(properties || {}).some((key) => { @@ -58,6 +60,7 @@ const SchemaField = (props) => { (isSchemaItemObject && !isEmpty(schema?.items?.properties)) ); const isSingleSelect = schema?.type === 'object' && !isEmpty(schema?.properties); + const { referenceValue, referenceKey } = useSchemaReference({...props, isMultiSelect }); if (autocomplete && (isMultiSelect || isSingleSelect)) { const { @@ -87,7 +90,10 @@ const SchemaField = (props) => { const autocompleteOptions = isString(autocomplete) ? { url: autocomplete } : autocomplete; - const autocompleteUrl = autocompleteOptions?.url; + let autocompleteUrl = autocompleteOptions?.url; + if (referenceValue) { + autocompleteUrl = template(autocompleteUrl)({[referenceKey ?? 'id']: referenceValue }); + } const queryKey = autocompleteOptions?.queryKey || 'q'; const resultsKey = autocompleteOptions?.resultsKey || 'results'; const valueKey = autocompleteOptions?.valueKey || 'id'; diff --git a/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/useSchemaReference.js b/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/useSchemaReference.js new file mode 100644 index 0000000000..fe7c93fc79 --- /dev/null +++ b/geonode_mapstore_client/client/js/plugins/MetadataEditor/components/_fields/useSchemaReference.js @@ -0,0 +1,47 @@ +import {useEffect, useRef} from 'react'; +import get from 'lodash/get'; +import template from 'lodash/template'; + +export default ({ + uiSchema, + idSchema, + onChange, + isMultiSelect, + formContext, + name +}) => { + const uiOptions = uiSchema?.['ui:options']; + const referenceValuePath = uiOptions?.['geonode-ui:referencevalue']; + const referenceKey = uiOptions?.['geonode-ui:referencekey']; + + // Extract index from the ID schema + const match = idSchema.$id.match(/_(\d+)(_|$)/); + const index = match ? parseInt(match[1], 10) : null; + const referenceValue = referenceValuePath + ? get(formContext, `metadata.${template(referenceValuePath)({'index': index})}`) + : null; + const prevReferenceValue = useRef(null); + + const storeReferenceValue = (value) => { + prevReferenceValue.current = { + ...prevReferenceValue.current, [name]: value + }; + }; + + useEffect(() => { + // store the initial reference value + if (prevReferenceValue.current === null && referenceValuePath) { + storeReferenceValue(referenceValue); + } + }, []); + + useEffect(()=> { + // to reset the form data when the parent field reference value changes + if (referenceValuePath && referenceValue !== prevReferenceValue.current?.[name]) { + storeReferenceValue(referenceValue); + onChange(isMultiSelect ? [] : {}); + } + }, [referenceValuePath, referenceValue]); + + return { referenceValue, referenceKey }; +}; diff --git a/geonode_mapstore_client/client/js/plugins/MetadataEditor/containers/MetadataEditor.jsx b/geonode_mapstore_client/client/js/plugins/MetadataEditor/containers/MetadataEditor.jsx index 9713dcb464..35275f59c7 100644 --- a/geonode_mapstore_client/client/js/plugins/MetadataEditor/containers/MetadataEditor.jsx +++ b/geonode_mapstore_client/client/js/plugins/MetadataEditor/containers/MetadataEditor.jsx @@ -109,7 +109,8 @@ function MetadataEditor({ readonly={readOnly} ref={initialize.current} formContext={{ - title: metadata?.title + title: metadata?.title, + metadata }} schema={schema} widgets={widgets}