From c128dc3032c3076c4376e685253736d0e8ac169a Mon Sep 17 00:00:00 2001 From: masillan Date: Thu, 31 Oct 2024 18:02:29 +0200 Subject: [PATCH 01/17] CSCFC4EMSCR-561 Clicking mapping source/target node only highlights one side of the schema trees: Changed clicking mapping source/target to highligt both source and target on crosswalk schema trees. --- .../src/modules/crosswalk-editor/index.tsx | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/mscr-ui/src/modules/crosswalk-editor/index.tsx b/mscr-ui/src/modules/crosswalk-editor/index.tsx index 4697088e8..5b7f8d5c7 100644 --- a/mscr-ui/src/modules/crosswalk-editor/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/index.tsx @@ -86,7 +86,10 @@ export default function CrosswalkEditor({ const [isOneToManyMapping, setIsOneToManyMapping] = useState(false); const [isPatchMappingOperation, setIsMappingPatchOperation] = useState(false); - const [scrollToSelectedNodeId, setScrollToSelectedNodeId] = useState< + const [scrollToSelectedSourceNodeId, setScrollToSelectedSourceNodeId] = useState< + string | undefined + >(''); + const [scrollToSelectedTargetNodeId, setScrollToSelectedTargetNodeId] = useState< string | undefined >(''); const [mappingToBeEdited, setMappingToBeEdited] = useState< @@ -395,6 +398,21 @@ export default function CrosswalkEditor({ } }; + function handleScrolling(mapping: NodeMapping, nodeId? : string) { + if (nodeId === undefined) { + setScrollToSelectedSourceNodeId(nodeId); + setScrollToSelectedTargetNodeId(nodeId); + } else { + if (nodeId === mapping.source[0].id) { + setScrollToSelectedSourceNodeId(nodeId); + setScrollToSelectedTargetNodeId(mapping.target[0].id); + } else { + setScrollToSelectedTargetNodeId(nodeId); + setScrollToSelectedSourceNodeId(mapping.source[0].id); + } + } + } + const performCallbackFromAccordionAction = ( mapping: NodeMapping, action: string, @@ -402,22 +420,29 @@ export default function CrosswalkEditor({ mappingOrHighlightOperationId?: string, isSourceTree?: boolean ) => { - setScrollToSelectedNodeId(''); + setScrollToSelectedSourceNodeId(''); + setScrollToSelectedTargetNodeId(''); // TODO: implement add notes from accordion if needed? if (action === 'remove') { removeMapping(mapping); } else if (action === 'selectFromTreesByMapping') { - setScrollToSelectedNodeId(nodeId); + if (isSourceTree === true) { + setScrollToSelectedSourceNodeId(nodeId); + setScrollToSelectedTargetNodeId(mapping.target[0].id); + } else { + setScrollToSelectedTargetNodeId(nodeId); + setScrollToSelectedSourceNodeId(mapping.source[0].id); + } selectFromTreeByNodeMapping(mapping, true); selectFromTreeByNodeMapping(mapping, false); } else if (action === 'openMappingDetails') { - setScrollToSelectedNodeId(nodeId); + handleScrolling(mapping, nodeId); setIsMappingPatchOperation(true); setPatchPid(mapping.pid ? mapping.pid : ''); selectFromTreeByNodeMapping(mapping, true); selectFromTreeByNodeMapping(mapping, false); } else if (action === 'highlightFunctionField') { - setScrollToSelectedNodeId(nodeId); + handleScrolling(mapping, nodeId); setHighlightOperation({ operationId: mappingOrHighlightOperationId ? mappingOrHighlightOperationId @@ -429,7 +454,7 @@ export default function CrosswalkEditor({ selectFromTreeByNodeMapping(mapping, true); selectFromTreeByNodeMapping(mapping, false); } else if (action === 'removeMapping') { - setScrollToSelectedNodeId(nodeId); + handleScrolling(mapping, nodeId); removeMapping(mapping.pid); } }; @@ -495,7 +520,7 @@ export default function CrosswalkEditor({ treeSelection={sourceTreeSelection} caption={t('crosswalk-editor.search-from-source-schema')} schemaUrn={sourceSchemaUrn} - scrollToSelectedNodeId={scrollToSelectedNodeId} + scrollToSelectedNodeId={scrollToSelectedSourceNodeId} /> @@ -541,7 +566,7 @@ export default function CrosswalkEditor({ treeSelection={targetTreeSelection} caption={t('crosswalk-editor.search-from-target-schema')} schemaUrn={targetSchemaUrn} - scrollToSelectedNodeId={scrollToSelectedNodeId} + scrollToSelectedNodeId={scrollToSelectedTargetNodeId} /> From 4d6838c6140df73dbe0ef8f989953c4cf5af2c7a Mon Sep 17 00:00:00 2001 From: rquazi Date: Tue, 5 Nov 2024 14:54:40 +0200 Subject: [PATCH 02/17] added putMscrRevision mutation --- .../common/components/schema/schema.slice.tsx | 9 +++++ mscr-ui/src/modules/form/generate-payload.tsx | 2 +- mscr-ui/src/modules/form/index.tsx | 37 +++++++++++++++++-- mscr-ui/src/modules/form/validate-form.tsx | 2 + mscr-ui/src/modules/schema-view/index.tsx | 31 +++++++++++----- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/mscr-ui/src/common/components/schema/schema.slice.tsx b/mscr-ui/src/common/components/schema/schema.slice.tsx index fb1009770..f1b259ad7 100644 --- a/mscr-ui/src/common/components/schema/schema.slice.tsx +++ b/mscr-ui/src/common/components/schema/schema.slice.tsx @@ -64,6 +64,14 @@ export const schemaApi = createApi({ }, }) }), + // this should be the API for creating revisions of schemas in MSCR format + putMscrSchemaRevision: builder.mutation }>({ + query: ({pid, data }) => ({ + url: `/schema?action=revisionOf&target=${pid}`, + method: 'PUT', + data: data, + }) + }), putSchemaMscrCopy: builder.mutation }>({ query: ({pid, data }) => ({ url: `/schema?action=mscrCopyOf&target=${pid}`, @@ -182,6 +190,7 @@ export const { useGetSchemasQuery, usePutSchemaFullMutation, usePutSchemaRevisionMutation, + usePutMscrSchemaRevisionMutation, usePutSchemaMscrCopyMutation, usePatchSchemaMutation, usePatchSchemaRootSelectionMutation, diff --git a/mscr-ui/src/modules/form/generate-payload.tsx b/mscr-ui/src/modules/form/generate-payload.tsx index f2826199d..d6ce6d848 100644 --- a/mscr-ui/src/modules/form/generate-payload.tsx +++ b/mscr-ui/src/modules/form/generate-payload.tsx @@ -72,7 +72,7 @@ export default function generatePayload( } } else if (modalType == ModalType.RevisionMscr) { if (contentType == Type.Schema) { - const { namespace, organizations, format, ...revisionPayload } = + const { organizations, ...revisionPayload } = schemaPayload; return revisionPayload; } else if (contentType == Type.Crosswalk) { diff --git a/mscr-ui/src/modules/form/index.tsx b/mscr-ui/src/modules/form/index.tsx index c7dff51f6..46747f85b 100644 --- a/mscr-ui/src/modules/form/index.tsx +++ b/mscr-ui/src/modules/form/index.tsx @@ -18,6 +18,7 @@ import { useTranslation } from 'next-i18next'; import getApiError from '@app/common/utils/getApiErrors'; import { useRouter } from 'next/router'; import { + usePutMscrSchemaRevisionMutation, usePutSchemaFullMutation, usePutSchemaMscrCopyMutation, usePutSchemaRevisionMutation, @@ -100,6 +101,8 @@ export default function FormModal({ const [putCrosswalkFull, resultCrosswalkFull] = usePutCrosswalkFullMutation(); const [putSchemaRevision, resultSchemaRevision] = usePutSchemaRevisionMutation(); + const [putMscrSchemaRevision, resultMscrSchemaRevision] = + usePutMscrSchemaRevisionMutation(); const [putCrosswalkRevision, resultCrosswalkRevision] = usePutCrosswalkRevisionMutation(); const [putCrosswalkFullRevision, resultCrosswalkFullRevision] = @@ -113,7 +116,7 @@ export default function FormModal({ if (!initialData) return; const existingData: FormType = { format: - modalType == ModalType.MscrCopy ? Format.Mscr : initialData.format, + modalType == ModalType.MscrCopy||ModalType.RevisionMscr ? Format.Mscr : initialData.format, languages: [ { labelText: t('language-english-with-suffix'), @@ -202,6 +205,10 @@ export default function FormModal({ resultCrosswalkRevision.data ) { pid = resultCrosswalkRevision.data.pid; + } else if(contentType == Type.Schema && + resultMscrSchemaRevision.isSuccess && + resultMscrSchemaRevision.data) { + pid = resultMscrSchemaRevision.data.pid; } break; case ModalType.RevisionFull: @@ -228,6 +235,15 @@ export default function FormModal({ pid = resultSchemaMscrCopy.data.pid; } break; + case ModalType.RevisionMscr: + if ( + contentType == Type.Schema && + resultMscrSchemaRevision.isSuccess && + resultMscrSchemaRevision.data + ) { + pid = resultMscrSchemaRevision.data.pid; + } + break; // TODO: MscrCopy API slice and then pid retrieval for crosswalk here } return pid; @@ -247,6 +263,8 @@ export default function FormModal({ resultSchemaMscrCopy.isSuccess, resultSchemaRevision.data, resultSchemaRevision.isSuccess, + resultMscrSchemaRevision.data, + resultMscrSchemaRevision.isSuccess ] ); @@ -325,6 +343,7 @@ export default function FormModal({ fileData, fileUri ); + console.log(formErrors); setErrors(formErrors); if ( @@ -352,6 +371,7 @@ export default function FormModal({ } else if (formData.format !== Format.Mscr) { return; } + console.log(newFormData); // Choose the api call and parameters according to content type and modal type let makeApiCall; @@ -363,7 +383,7 @@ export default function FormModal({ setSubmitAnimationVisible(false); } ); - } else if (modalType == ModalType.RegisterNewMscr) { + } else if (modalType == ModalType.RegisterNewMscr) {//what is register new MSCR? Promise.all([spinnerDelay(), putCrosswalk(payload)]).then((_values) => { setSubmitAnimationVisible(false); }); @@ -400,8 +420,19 @@ export default function FormModal({ ]).then((_values) => { setSubmitAnimationVisible(false); }); + // Creating revision of MSCR format schemas + } else if (initialData && + modalType == ModalType.RevisionMscr && + contentType == Type.Schema) { + console.log("creating mscr revision"+initialData.format ) + Promise.all([ + spinnerDelay(), + putMscrSchemaRevision({ pid: initialData.pid, data: payload }), + ]).then((_values) => { + setSubmitAnimationVisible(false); + }); } - // Missing scenarios: MSCR copy of a crosswalk, revision of an MSCR copy + // Missing scenarios: MSCR copy of a crosswalk } }; diff --git a/mscr-ui/src/modules/form/validate-form.tsx b/mscr-ui/src/modules/form/validate-form.tsx index 5c24bd3b1..852db6274 100644 --- a/mscr-ui/src/modules/form/validate-form.tsx +++ b/mscr-ui/src/modules/form/validate-form.tsx @@ -7,6 +7,7 @@ import { formatsAvailableForSchemaRegistration, } from '@app/common/interfaces/format.interface'; + export interface InputErrors { languageAmount: boolean; titleAmount: string[]; @@ -77,6 +78,7 @@ export function validateForm( errors.fileData = true; } // Format should be provided + console.log(formData.format); if (!formData.format) { errors.format = true; } diff --git a/mscr-ui/src/modules/schema-view/index.tsx b/mscr-ui/src/modules/schema-view/index.tsx index 576733e82..9884b0c4f 100644 --- a/mscr-ui/src/modules/schema-view/index.tsx +++ b/mscr-ui/src/modules/schema-view/index.tsx @@ -352,15 +352,28 @@ export default function SchemaView({ schemaId }: { schemaId: string }) { /> )} {/*ToDo: When making a revision of an mscr copy is possible, take that into account here (Modaltype.RevisionMscr)*/} - - dispatch(setFormModalState({ key: 'version', value: value })) - } - initialData={schemaData} - /> + {schemaData.format == Format.Mscr ? ( + + dispatch(setFormModalState({ key: 'version', value: value })) + } + initialData={schemaData} + /> + ) : ( + + dispatch(setFormModalState({ key: 'version', value: value })) + } + initialData={schemaData} + /> + )} + Date: Mon, 11 Nov 2024 10:56:15 +0200 Subject: [PATCH 03/17] removing log messages --- mscr-ui/src/modules/form/generate-payload.tsx | 1 + mscr-ui/src/modules/form/index.tsx | 17 +++++++++-------- mscr-ui/src/modules/form/validate-form.tsx | 1 - 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/mscr-ui/src/modules/form/generate-payload.tsx b/mscr-ui/src/modules/form/generate-payload.tsx index d6ce6d848..4c907df84 100644 --- a/mscr-ui/src/modules/form/generate-payload.tsx +++ b/mscr-ui/src/modules/form/generate-payload.tsx @@ -16,6 +16,7 @@ export default function generatePayload( ): Partial { const organizations: Organization[] = []; if (user && organizationPid && organizationPid !== '') { + console.log(organizationPid); const ownerOrg = user?.organizations.find((x) => x.id == organizationPid); if (ownerOrg) organizations.push(ownerOrg); } diff --git a/mscr-ui/src/modules/form/index.tsx b/mscr-ui/src/modules/form/index.tsx index 46747f85b..4ed5d2ab1 100644 --- a/mscr-ui/src/modules/form/index.tsx +++ b/mscr-ui/src/modules/form/index.tsx @@ -111,12 +111,12 @@ export default function FormModal({ usePutSchemaMscrCopyMutation(); const [submitAnimationVisible, setSubmitAnimationVisible] = useState(false); - + const formDataFromInitialData = useCallback(() => { if (!initialData) return; const existingData: FormType = { format: - modalType == ModalType.MscrCopy||ModalType.RevisionMscr ? Format.Mscr : initialData.format, + modalType == ModalType.MscrCopy? Format.Mscr : initialData.format, languages: [ { labelText: t('language-english-with-suffix'), @@ -205,10 +205,12 @@ export default function FormModal({ resultCrosswalkRevision.data ) { pid = resultCrosswalkRevision.data.pid; - } else if(contentType == Type.Schema && + } else if ( + contentType == Type.Schema && resultMscrSchemaRevision.isSuccess && - resultMscrSchemaRevision.data) { - pid = resultMscrSchemaRevision.data.pid; + resultMscrSchemaRevision.data + ) { + pid = resultMscrSchemaRevision.data.pid; } break; case ModalType.RevisionFull: @@ -343,7 +345,7 @@ export default function FormModal({ fileData, fileUri ); - console.log(formErrors); + setErrors(formErrors); if ( @@ -371,7 +373,7 @@ export default function FormModal({ } else if (formData.format !== Format.Mscr) { return; } - console.log(newFormData); + // Choose the api call and parameters according to content type and modal type let makeApiCall; @@ -424,7 +426,6 @@ export default function FormModal({ } else if (initialData && modalType == ModalType.RevisionMscr && contentType == Type.Schema) { - console.log("creating mscr revision"+initialData.format ) Promise.all([ spinnerDelay(), putMscrSchemaRevision({ pid: initialData.pid, data: payload }), diff --git a/mscr-ui/src/modules/form/validate-form.tsx b/mscr-ui/src/modules/form/validate-form.tsx index 852db6274..849a29f94 100644 --- a/mscr-ui/src/modules/form/validate-form.tsx +++ b/mscr-ui/src/modules/form/validate-form.tsx @@ -78,7 +78,6 @@ export function validateForm( errors.fileData = true; } // Format should be provided - console.log(formData.format); if (!formData.format) { errors.format = true; } From 6cee1df2490939e4890c97611857cbcf5bc51e5c Mon Sep 17 00:00:00 2001 From: rquazi Date: Mon, 11 Nov 2024 12:48:07 +0200 Subject: [PATCH 04/17] Removing duplicate code --- mscr-ui/src/modules/form/generate-payload.tsx | 1 - mscr-ui/src/modules/form/index.tsx | 9 --------- 2 files changed, 10 deletions(-) diff --git a/mscr-ui/src/modules/form/generate-payload.tsx b/mscr-ui/src/modules/form/generate-payload.tsx index 4c907df84..d6ce6d848 100644 --- a/mscr-ui/src/modules/form/generate-payload.tsx +++ b/mscr-ui/src/modules/form/generate-payload.tsx @@ -16,7 +16,6 @@ export default function generatePayload( ): Partial { const organizations: Organization[] = []; if (user && organizationPid && organizationPid !== '') { - console.log(organizationPid); const ownerOrg = user?.organizations.find((x) => x.id == organizationPid); if (ownerOrg) organizations.push(ownerOrg); } diff --git a/mscr-ui/src/modules/form/index.tsx b/mscr-ui/src/modules/form/index.tsx index 4ed5d2ab1..c8391d15f 100644 --- a/mscr-ui/src/modules/form/index.tsx +++ b/mscr-ui/src/modules/form/index.tsx @@ -237,15 +237,6 @@ export default function FormModal({ pid = resultSchemaMscrCopy.data.pid; } break; - case ModalType.RevisionMscr: - if ( - contentType == Type.Schema && - resultMscrSchemaRevision.isSuccess && - resultMscrSchemaRevision.data - ) { - pid = resultMscrSchemaRevision.data.pid; - } - break; // TODO: MscrCopy API slice and then pid retrieval for crosswalk here } return pid; From cd9cfafb61e157724921de53eae09c956acfd0ac Mon Sep 17 00:00:00 2001 From: masillan Date: Mon, 11 Nov 2024 13:19:12 +0200 Subject: [PATCH 05/17] CSCFC4EMSCR-599 Fix mapping table rendering for all schema formats. Added root element as parent class to path in SHACL format where mapped element is the child of root element. Returning label / name of mapped element, if format is not SHACL, Xsd ,Csv Jsonschema, Enum or Mscr. --- .../mappings-accordion/index.tsx | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx b/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx index 358b3fd44..8ad866596 100644 --- a/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx @@ -360,7 +360,7 @@ function returnFullPath(id: string) : string { function returnPath(id: string, label: string, schemaFormat: Format | undefined, schemaData: SchemaWithContent | undefined) : string { let returnString = ''; - if (schemaFormat === Format.Xsd || schemaFormat === Format.Csv || schemaFormat === Format.Jsonschema || schemaFormat === Format.Skosrdf + if (schemaFormat === Format.Xsd || schemaFormat === Format.Csv || schemaFormat === Format.Jsonschema || schemaFormat === Format.Enum || schemaFormat === Format.Mscr) { returnString = id.substring(id?.indexOf("#root-Root-") + "#root-Root-".length); let strings; @@ -376,36 +376,26 @@ function returnPath(id: string, label: string, schemaFormat: Format | undefined, } } return returnString; - } else { + let className = ''; - if (schemaFormat === Format.Rdfs || schemaFormat === Format.Owl) { - if (id.lastIndexOf('#') === -1) { - returnString = id.substring(id.lastIndexOf('/') + 1); - } else { - className = id.substring(id?.lastIndexOf('/') + 1, label.lastIndexOf('#')) + ':'; - let itemName = id.substring(id.lastIndexOf('#') + 1); - returnString = className + itemName; - } } else if (schemaFormat === Format.Shacl) { let definitions = schemaData?.content?.definitions; if (definitions) { let keys = Object.keys(definitions); if (keys && keys.length > 0) { + outer: for (let i = 0; i < keys.length; i++) { let value = definitions[keys[i]]; let secondLevelKeys = Object.keys(value); for (let k = 0; k < secondLevelKeys.length; k += 1) { - if (secondLevelKeys[k] === 'properties') { - let secondLevelValue = value[secondLevelKeys[k]]; - let thirdLevelKeys = Object.keys(secondLevelValue); - for (let j = 0; j < thirdLevelKeys.length; j += 1) { - if (thirdLevelKeys[j] === id) { - for (let l = 0; l < secondLevelKeys.length; l += 1) { - if (secondLevelKeys[l] === 'title') { - let titleValue = value[secondLevelKeys[l]]; - returnString = titleValue + ':' + label; - } - } + if (secondLevelKeys[k] === 'title') { + let titleValue = value[secondLevelKeys[k]]; + if (titleValue === label) { + if (value && value.qname && value.qname.length > label.length) { + let parentString = value.qname.substring(0, value.qname.length - (label.length + 1)); + parentString = parentString.substring(parentString.lastIndexOf('/') + 1); + returnString = parentString + ':' + label; + break outer; } } } @@ -413,9 +403,10 @@ function returnPath(id: string, label: string, schemaFormat: Format | undefined, } } } + return returnString; + } else { + return label; } - return returnString; - } } function filterMappings(nodeMappingsInput: NodeMapping[], value: string, showAttributeNames: boolean) { let results: NodeMapping[] = []; From dccae7b4b58a8d9d7d2e558034e0cc976f47f262 Mon Sep 17 00:00:00 2001 From: masillan Date: Mon, 11 Nov 2024 15:21:46 +0200 Subject: [PATCH 06/17] CSCFC4EMSCR-602 When filtering from mappings, results get duplicated. Added check that allows adding searched item only once to searced items array. --- .../mappings-accordion/index.tsx | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx b/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx index 358b3fd44..d5e2ef0d0 100644 --- a/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx @@ -421,19 +421,27 @@ function filterMappings(nodeMappingsInput: NodeMapping[], value: string, showAtt let results: NodeMapping[] = []; const searchString = value.toLowerCase(); nodeMappingsInput.forEach(item => { - if (item?.notes && item.notes.toLowerCase().includes(searchString)) { + let itemFound = false + if (item?.notes && item.notes.toLowerCase().includes(searchString) && !itemFound) { results.push(item); + itemFound = true; + } + if (!itemFound) { + item.source.forEach(src => { + if (src.label.toLowerCase().includes(searchString) && !itemFound) { + results.push(item); + itemFound = true; + } + }); + } + if (!itemFound) { + item.target.forEach(src => { + if (src.label.toLowerCase().includes(searchString) && !itemFound) { + results.push(item); + itemFound = true; + } + }); } - item.source.forEach(src => { - if (src.label.toLowerCase().includes(searchString)) { - results.push(item); - } - }); - item.target.forEach(src => { - if (src.label.toLowerCase().includes(searchString)) { - results.push(item); - } - }); } ); return results; From a60e05ce9e02e28abdf6ee57868d5ec6a1d49fae Mon Sep 17 00:00:00 2001 From: masillan Date: Tue, 12 Nov 2024 15:45:26 +0200 Subject: [PATCH 07/17] CSCFC4EMSCR-599 allow ROOT element selection to mapping. --- .../node-listing-accordion/index.tsx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/node-listing-accordion/index.tsx b/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/node-listing-accordion/index.tsx index 0fd7a09af..e82a37bb3 100644 --- a/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/node-listing-accordion/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/tabs/node-mappings/node-listing-accordion/index.tsx @@ -338,11 +338,11 @@ export default function NodeListingAccordion(props: nodeListingAccordionProps) { // Source accordion if (props.isOneToManyMapping) { let newNode: NodeListingRow = { - description: props.nodes[0].source.properties.description, - processingSelection: props.nodes[0].sourceProcessing?.id, - processing: props.nodes[0].sourceProcessing, - type: props.nodes[0].source.properties.type, - isSelected: false, notes: undefined, name: props.nodes[0].source.name, id: props.nodes[0].source.id + description: props.nodes[0]?.source?.properties?.description, + processingSelection: props.nodes[0]?.sourceProcessing?.id, + processing: props.nodes[0]?.sourceProcessing, + type: props.nodes[0]?.source?.properties?.type, + isSelected: false, notes: undefined, name: props.nodes[0]?.source?.name, id: props.nodes[0]?.source?.id } newNodes.push(newNode); } else { @@ -362,21 +362,21 @@ export default function NodeListingAccordion(props: nodeListingAccordionProps) { if (props.isOneToManyMapping) { props.nodes.forEach((node: CrosswalkConnectionNew) => { let newNode: NodeListingRow = { - description: node?.target.properties.description, + description: node?.target?.properties?.description, processingSelection: node?.targetProcessing?.id, processing: node?.targetProcessing, - type: node?.target.properties.type, - isSelected: false, notes: undefined, name: node.target.name, id: node.target.id + type: node?.target?.properties?.type, + isSelected: false, notes: undefined, name: node?.target?.name, id: node?.target?.id } newNodes.push(newNode); }); } else { let newNode: NodeListingRow = { - description: props.nodes[0].target.properties.description, - processingSelection: props.nodes[0].targetProcessing?.id, - processing: props.nodes[0].targetProcessing, - type: props.nodes[0].target.properties.type, - isSelected: false, notes: undefined, name: props.nodes[0].target.name, id: props.nodes[0].target.id + description: props.nodes[0]?.target?.properties?.description, + processingSelection: props.nodes[0]?.targetProcessing?.id, + processing: props.nodes[0]?.targetProcessing, + type: props.nodes[0]?.target?.properties?.type, + isSelected: false, notes: undefined, name: props.nodes[0]?.target?.name, id: props.nodes[0]?.target?.id } newNodes.push(newNode); } From f6d1c81243410bcd3bd15750afca9591ec968725 Mon Sep 17 00:00:00 2001 From: masillan Date: Tue, 12 Nov 2024 15:47:39 +0200 Subject: [PATCH 08/17] CSCFC4EMSCR-599 fix to add ROOT element or ROOT element as parent class to mapping on SHACL format. --- .../mappings-accordion/index.tsx | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx b/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx index d8e38b579..601d595da 100644 --- a/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx +++ b/mscr-ui/src/modules/crosswalk-editor/mappings-accordion/index.tsx @@ -380,22 +380,25 @@ function returnPath(id: string, label: string, schemaFormat: Format | undefined, let className = ''; } else if (schemaFormat === Format.Shacl) { let definitions = schemaData?.content?.definitions; + let titleValue = undefined; if (definitions) { let keys = Object.keys(definitions); if (keys && keys.length > 0) { - outer: for (let i = 0; i < keys.length; i++) { let value = definitions[keys[i]]; let secondLevelKeys = Object.keys(value); for (let k = 0; k < secondLevelKeys.length; k += 1) { - if (secondLevelKeys[k] === 'title') { - let titleValue = value[secondLevelKeys[k]]; - if (titleValue === label) { - if (value && value.qname && value.qname.length > label.length) { - let parentString = value.qname.substring(0, value.qname.length - (label.length + 1)); - parentString = parentString.substring(parentString.lastIndexOf('/') + 1); - returnString = parentString + ':' + label; - break outer; + if (secondLevelKeys[k] === 'properties') { + let secondLevelValue = value[secondLevelKeys[k]]; + let thirdLevelKeys = Object.keys(secondLevelValue); + for (let j = 0; j < thirdLevelKeys.length; j += 1) { + if (thirdLevelKeys[j] === id) { + for (let l = 0; l < secondLevelKeys.length; l += 1) { + if (secondLevelKeys[l] === 'title') { + titleValue = value[secondLevelKeys[l]]; + returnString = titleValue + ':' + label; + } + } } } } @@ -403,6 +406,11 @@ function returnPath(id: string, label: string, schemaFormat: Format | undefined, } } } + if (!titleValue && label && label.toLowerCase() === 'root') { + return label; + } else if (!titleValue && label && label.toLowerCase() !== 'root') { + return 'ROOT:' + label; + } return returnString; } else { return label; From 70aa938598445cd0f3acf0ccbaf50dc6285eae0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maaria=20Wahlstr=C3=B6m?= Date: Wed, 13 Nov 2024 11:25:36 +0200 Subject: [PATCH 09/17] CSCFC4EMSCR-612 Hide create content buttons from group members --- mscr-ui/src/common/utils/has-permission.tsx | 5 +- .../modules/workspace/group-home/index.tsx | 99 ++++++++++--------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/mscr-ui/src/common/utils/has-permission.tsx b/mscr-ui/src/common/utils/has-permission.tsx index 95dc631ef..634ea2368 100644 --- a/mscr-ui/src/common/utils/has-permission.tsx +++ b/mscr-ui/src/common/utils/has-permission.tsx @@ -11,16 +11,15 @@ import { Roles } from '../interfaces/format.interface'; // Need to specify the actions permitted for each type of user const actions = [ - // 'CREATE_SCHEMA', // 'EDIT_SCHEMA', // 'EDIT_SCHEMA_METADATA', // 'EDIT_SCHEMA_FILES', // 'DELETE_SCHEMA', - // 'CREATE_CROSSWALK', // 'EDIT_CROSSWALK_MAPPINGS', // 'EDIT_CROSSWALK_METADATA', // 'EDIT_CROSSWALK_FILES', // 'DELETE_CROSSWALK', + 'CREATE_CONTENT', 'EDIT_CONTENT', 'MAKE_MSCR_COPY', ] as const; @@ -77,7 +76,7 @@ export default function HasPermission({ action, owner }: hasPermissionProps) { } export function checkPermission({ user, action, owner }: checkPermissionProps) { - if (action == 'EDIT_CONTENT'||'MAKE_MSCR_COPY') { + if (action == 'EDIT_CONTENT' || action == 'CREATE_CONTENT' || action == 'MAKE_MSCR_COPY') { if (owner?.includes(user.id)) { //user is the owner, Check for personal Contents return true; diff --git a/mscr-ui/src/modules/workspace/group-home/index.tsx b/mscr-ui/src/modules/workspace/group-home/index.tsx index 1cbc0779d..64469182b 100644 --- a/mscr-ui/src/modules/workspace/group-home/index.tsx +++ b/mscr-ui/src/modules/workspace/group-home/index.tsx @@ -23,6 +23,7 @@ import FormModal, { ModalType } from '@app/modules/form'; import Link from 'next/link'; import { SpinnerWrapper } from '@app/modules/crosswalk-view/crosswalk-view.styles'; import SpinnerOverlay from '@app/common/components/spinner-overlay'; +import HasPermission from '@app/common/utils/has-permission'; interface GroupHomeProps { user: MscrUser; @@ -34,6 +35,10 @@ export default function GroupWorkspace({ pid, contentType, }: GroupHomeProps) { + const hasCreatePermission = HasPermission({ + action: 'CREATE_CONTENT', + owner: [pid], + }); const { t } = useTranslation('common'); const router = useRouter(); const lang = router.locale ?? ''; @@ -122,52 +127,54 @@ export default function GroupWorkspace({ } /> - -
- - {contentType == 'SCHEMA' ? ( - <> - - - - ) : ( - <> - - - - - - )} - -
- + {hasCreatePermission && +
+ + + {contentType == 'SCHEMA' ? ( + <> + + + + ) : ( + <> + + + + + + )} + + +
+ } {data?.hits.hits && data?.hits.hits.length < 1 ? (
{contentType == 'SCHEMA' From eb151ecbcf00cc01ebfa2491bf5aa4dba253c794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maaria=20Wahlstr=C3=B6m?= Date: Wed, 13 Nov 2024 14:39:01 +0200 Subject: [PATCH 10/17] CSCFC4EMSCR-616 Construct tree without extra ROOT node --- .../common/components/schema-info/index.tsx | 2 +- .../schema-info/schema-tree/index.tsx | 13 +- .../schema-tree-renderer/index.tsx | 239 +----------------- 3 files changed, 11 insertions(+), 243 deletions(-) diff --git a/mscr-ui/src/common/components/schema-info/index.tsx b/mscr-ui/src/common/components/schema-info/index.tsx index b6baff4ce..4c5b3a07c 100644 --- a/mscr-ui/src/common/components/schema-info/index.tsx +++ b/mscr-ui/src/common/components/schema-info/index.tsx @@ -321,7 +321,7 @@ export default function SchemaInfo(props: { > {isTreeDataFetched && ( void; @@ -78,16 +78,7 @@ export default function SchemaTree({ defaultExpandIcon={} multiSelect > - - {Array.isArray(nodes.children) - ? nodes.children.map((node: RenderTree) => toTree(node, showQname)) - : null} - + {nodes.map((node: RenderTree) => toTree(node, showQname))} ); } diff --git a/mscr-ui/src/common/components/schema-info/schema-tree/schema-tree-renderer/index.tsx b/mscr-ui/src/common/components/schema-info/schema-tree/schema-tree-renderer/index.tsx index b7fc8b64b..f346c78eb 100644 --- a/mscr-ui/src/common/components/schema-info/schema-tree/schema-tree-renderer/index.tsx +++ b/mscr-ui/src/common/components/schema-info/schema-tree/schema-tree-renderer/index.tsx @@ -1,211 +1,4 @@ -import {RenderTree, RenderTreeOld} from '@app/common/interfaces/crosswalk-connection.interface'; - -// export default function MockupSchemaLoader(emptyTemplate: boolean): Promise { -// -// let allTreeNodes: RenderTreeOld[] = []; -// -// let currentTreeNode: RenderTreeOld = { -// idNumeric: 0, -// id: '0', -// name: '', -// isLinked: false, -// title: '', -// type: '', -// description: '', -// required: '', -// isMappable: '', -// parentName: '', -// jsonPath: '$schema', -// parentId: 0, -// children: [] -// }; -// -// let nodeId = 0; -// -// function increaseNodeNumber() { -// nodeId += 1; -// } -// -// function createTreeObject(object: string, value: string, parent: string, rootId: any, jsonPath: string) { -// currentTreeNode.jsonPath = jsonPath + '.' + object; -// currentTreeNode.idNumeric = nodeId; -// currentTreeNode.id = nodeId.toString(); -// currentTreeNode.parentId = rootId; -// currentTreeNode.name = object; -// currentTreeNode.title = value; -// currentTreeNode.parentName = parent; -// increaseNodeNumber(); -// } -// -// function walkJson(json_object: any, parent: any, rootId: number, jsonPath: string) { -// for (const obj in json_object) { -// if (typeof json_object[obj] === 'string') { -// //console.log(`leaf ${obj} = ${json_object[obj]}`); -// -// // OBJECT IS A LEAF LEVEL OBJECT -// currentTreeNode = { -// isLinked: false, -// idNumeric: 0, -// id: '0', -// name: '', -// title: '', -// type: 'string', -// description: '', -// required: '', -// parentId: 0, -// jsonPath, -// children: [] -// }; -// createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); -// allTreeNodes.push(cloneDeep(currentTreeNode)); -// } else { -// // OBJECT HAS CHILDREN -// currentTreeNode = { -// isLinked: false, -// idNumeric: 0, -// id: '0', -// name: '', -// title: '', -// type: Array.isArray(json_object[obj]) ? 'array' : 'composite', -// description: '', -// required: '', -// parentId: 0, -// jsonPath, -// children: [] -// }; -// currentTreeNode.name = obj; -// currentTreeNode.parentName = parent; -// currentTreeNode.parentId = rootId; -// currentTreeNode.idNumeric = nodeId; -// currentTreeNode.id = nodeId.toString(); -// -// -// currentTreeNode.jsonPath = jsonPath + '.' + obj; -// increaseNodeNumber(); -// allTreeNodes.push(cloneDeep(currentTreeNode)); -// walkJson(json_object[obj], obj, nodeId - 1, currentTreeNode.jsonPath); -// } -// } -// return allTreeNodes; -// } -// -// -// function walkJsonOld(json_object: any, parent: any, rootId: number, jsonPath: string) { -// for (const obj in json_object) { -// if (typeof json_object[obj] === 'string') { -// //console.log(`leaf ${obj} = ${json_object[obj]}`); -// -// // OBJECT IS A LEAF LEVEL OBJECT -// currentTreeNode = { -// isLinked: false, -// idNumeric: 0, -// id: '0', -// name: '', -// title: '', -// type: 'string', -// description: '', -// required: '', -// parentId: 0, -// jsonPath, -// children: [] -// }; -// createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); -// allTreeNodes.push(cloneDeep(currentTreeNode)); -// } else if (typeof json_object[obj] === 'boolean') { -// //console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FOUND BOOLEAN', obj, json_object[obj], json_object); -// -// // OBJECT IS A LEAF LEVEL OBJECT -// currentTreeNode = { -// isLinked: false, -// idNumeric: 0, -// id: '0', -// name: '', -// title: '', -// type: json_object[obj].toString(), -// description: '', -// required: '', -// parentId: 0, -// jsonPath, -// children: [] -// }; -// createTreeObject(obj, json_object[obj], parent, rootId, jsonPath); -// allTreeNodes.push(cloneDeep(currentTreeNode)); -// } else { -// // OBJECT HAS CHILDREN -// currentTreeNode = { -// isLinked: false, -// idNumeric: 0, -// id: '0', -// name: '', -// title: '', -// type: Array.isArray(json_object[obj]) ? 'array' : 'composite', -// description: '', -// required: '', -// parentId: 0, -// jsonPath, -// children: [] -// }; -// currentTreeNode.name = obj; -// currentTreeNode.parentName = parent; -// currentTreeNode.parentId = rootId; -// currentTreeNode.idNumeric = nodeId; -// currentTreeNode.id = nodeId.toString(); -// -// -// currentTreeNode.jsonPath = jsonPath + '.' + obj; -// increaseNodeNumber(); -// allTreeNodes.push(cloneDeep(currentTreeNode)); -// walkJsonOld(json_object[obj], obj, nodeId - 1, currentTreeNode.jsonPath); -// } -// } -// return allTreeNodes; -// } -// -// function mergeAttributesToParent(inputNodes: RenderTreeOld[] | undefined) { -// if (inputNodes) { -// let outputNodes = inputNodes.map((parent: RenderTreeOld) => { -// if (parent.children) { -// let i = parent.children.length; -// while (i--) { -// // @ts-ignore -// if (parent.children[i] && parent.children[i].children.length > 0) { -// mergeAttributesToParent([parent.children[i]]); -// } -// if (parent.children[i].name === 'type') { -// parent.type = parent.children[i].title; -// //parent.children.splice(i, 1); -// } else if (parent.children[i].name === 'description') { -// parent.description = parent.children[i].title; -// //parent.children.splice(i, 1); -// } else if (parent.children[i].name === 'title') { -// parent.title = parent.children[i].title; -// //parent.children.splice(i, 1); -// } -// } -// } -// return parent; -// } -// ); -// return outputNodes; -// } -// } -// -// // Unused -// function reverseTreeChildren(inputNodes: RenderTreeOld[] | undefined) { -// if (inputNodes) { -// for (let i = 0; i < inputNodes.length; i += 1) { -// // @ts-ignore -// if (inputNodes[i].children.length > 1) { -// // @ts-ignore -// inputNodes[i].children = inputNodes[i].children.reverse() -// reverseTreeChildren(inputNodes[i].children); -// } -// } -// return inputNodes; -// } -// } -// } - +import { RenderTree } from '@app/common/interfaces/crosswalk-connection.interface'; let treeIndex = 0; @@ -217,14 +10,13 @@ function createRenderTree( ) { const retArray: RenderTree[] = []; for (const obj in input) { - treeIndex += 1; const newNode: RenderTree = { name: definitions[obj].title, qname: definitions[obj]?.qname ? definitions[obj]?.qname : 'empty', visualTreeId: treeIndex.toString(), id: obj.toString(), properties: definitions[obj], - elementPath: elementPath + '.' + obj.toString(), + elementPath: elementPath == '' ? obj.toString() : elementPath + '.' + obj.toString(), parentElementPath: elementPath, children: [], uri: definitions[obj]['@id'], @@ -234,48 +26,33 @@ function createRenderTree( //console.log('OBJ', obj, input[obj].keys, Object.keys(input[obj])); if (Object.keys(input[obj]).length > 0) { - // HAS CHILDREN + // HAS CHILDREN, OTHERWISE IS LEAF newNode.children = createRenderTree( input[obj], newNode.elementPath, definitions, idToNodeDictionary, ); - } else { - // IS LEAF } retArray.push(newNode); + treeIndex += 1; } return retArray; } export function generateTreeFromJson(jsonInput: any) { + // console.log('input-content-tree:', jsonInput.content.tree); const nodeIdToShallowNode: { [key: string]: RenderTree[] } = {}; - const treeRoot: RenderTree = { - name: 'ROOT', - qname: 'ROOT', - visualTreeId: '0', - id: 'ROOT', - properties: undefined, - uri: '', - elementPath: 'ROOT', - parentElementPath: undefined, - children: [], - }; - nodeIdToShallowNode['ROOT'] = [treeRoot]; const generatedTree = new Promise((resolve) => { const renderedTree = createRenderTree( jsonInput.content.tree, - 'ROOT', + '', jsonInput.content.definitions, nodeIdToShallowNode ); - const retTree: RenderTree[] = []; - treeRoot.children = renderedTree; - retTree.push(treeRoot); - // console.log('renderedTree', renderedTree); - resolve(retTree); + // console.log('renderedTree ', renderedTree); + resolve(renderedTree); }); return {generatedTree, nodeIdToShallowNode}; } From 524c258984e22ae6b2c41745d97b3cfd83913baa Mon Sep 17 00:00:00 2001 From: rquazi Date: Wed, 20 Nov 2024 14:43:19 +0200 Subject: [PATCH 11/17] added changes from the review --- mscr-ui/src/modules/form/index.tsx | 67 +++++++++++----------- mscr-ui/src/modules/form/validate-form.tsx | 1 - mscr-ui/src/modules/schema-view/index.tsx | 1 - 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/mscr-ui/src/modules/form/index.tsx b/mscr-ui/src/modules/form/index.tsx index c8391d15f..2230e0d3e 100644 --- a/mscr-ui/src/modules/form/index.tsx +++ b/mscr-ui/src/modules/form/index.tsx @@ -111,12 +111,11 @@ export default function FormModal({ usePutSchemaMscrCopyMutation(); const [submitAnimationVisible, setSubmitAnimationVisible] = useState(false); - const formDataFromInitialData = useCallback(() => { if (!initialData) return; - const existingData: FormType = { + const existingData: FormType = { format: - modalType == ModalType.MscrCopy? Format.Mscr : initialData.format, + modalType == ModalType.MscrCopy ? Format.Mscr : initialData.format, languages: [ { labelText: t('language-english-with-suffix'), @@ -257,7 +256,7 @@ export default function FormModal({ resultSchemaRevision.data, resultSchemaRevision.isSuccess, resultMscrSchemaRevision.data, - resultMscrSchemaRevision.isSuccess + resultMscrSchemaRevision.isSuccess, ] ); @@ -355,6 +354,7 @@ export default function FormModal({ modalType, organizationPid ); + const newFormData = new FormData(); newFormData.append('metadata', JSON.stringify(payload)); if (fileUri && fileUri.length > 0) { @@ -364,8 +364,6 @@ export default function FormModal({ } else if (formData.format !== Format.Mscr) { return; } - - // Choose the api call and parameters according to content type and modal type let makeApiCall; if (modalType == ModalType.RegisterNewFull) { @@ -376,7 +374,8 @@ export default function FormModal({ setSubmitAnimationVisible(false); } ); - } else if (modalType == ModalType.RegisterNewMscr) {//what is register new MSCR? + } else if (modalType == ModalType.RegisterNewMscr) { + //what is register new MSCR? Promise.all([spinnerDelay(), putCrosswalk(payload)]).then((_values) => { setSubmitAnimationVisible(false); }); @@ -413,16 +412,18 @@ export default function FormModal({ ]).then((_values) => { setSubmitAnimationVisible(false); }); - // Creating revision of MSCR format schemas - } else if (initialData && + // Creating revision of MSCR format schemas + } else if ( + initialData && modalType == ModalType.RevisionMscr && - contentType == Type.Schema) { - Promise.all([ - spinnerDelay(), - putMscrSchemaRevision({ pid: initialData.pid, data: payload }), - ]).then((_values) => { - setSubmitAnimationVisible(false); - }); + contentType == Type.Schema + ) { + Promise.all([ + spinnerDelay(), + putMscrSchemaRevision({ pid: initialData.pid, data: payload }), + ]).then((_values) => { + setSubmitAnimationVisible(false); + }); } // Missing scenarios: MSCR copy of a crosswalk } @@ -588,19 +589,19 @@ export default function FormModal({ ? modalType == ModalType.RegisterNewFull ? t('content-form.title.schema-register') : modalType == ModalType.MscrCopy - ? t('content-form.title.schema-mscr-copy') - : t('content-form.title.schema-revision') + ? t('content-form.title.schema-mscr-copy') + : t('content-form.title.schema-revision') : modalType == ModalType.RegisterNewFull - ? t('content-form.title.crosswalk-register') - : modalType == ModalType.RegisterNewMscr - ? t('content-form.title.crosswalk-create') - : modalType == ModalType.MscrCopy - ? t('content-form.title.crosswalk-mscr-copy') - : t('content-form.title.crosswalk-revision')} + ? t('content-form.title.crosswalk-register') + : modalType == ModalType.RegisterNewMscr + ? t('content-form.title.crosswalk-create') + : modalType == ModalType.MscrCopy + ? t('content-form.title.crosswalk-mscr-copy') + : t('content-form.title.crosswalk-revision')} {(modalType == ModalType.RegisterNewFull || - modalType == ModalType.RevisionFull) && + modalType == ModalType.RevisionFull) && renderFileDropArea()} {contentType == Type.Schema && ( @@ -651,15 +652,15 @@ export default function FormModal({ ? modalType == ModalType.RegisterNewFull ? t('content-form.button.schema-register') : modalType == ModalType.MscrCopy - ? t('content-form.button.mscr-copy') - : t('content-form.button.schema-revision') + ? t('content-form.button.mscr-copy') + : t('content-form.button.schema-revision') : modalType == ModalType.RegisterNewFull - ? t('content-form.button.crosswalk-register') - : modalType == ModalType.RegisterNewMscr - ? t('content-form.button.crosswalk-create') - : modalType == ModalType.MscrCopy - ? t('content-form.button.mscr-copy') - : t('content-form.button.crosswalk-revision')} + ? t('content-form.button.crosswalk-register') + : modalType == ModalType.RegisterNewMscr + ? t('content-form.button.crosswalk-create') + : modalType == ModalType.MscrCopy + ? t('content-form.button.mscr-copy') + : t('content-form.button.crosswalk-revision')}