diff --git a/packages/dm-core-plugins/blueprints/common/Meta.json b/packages/dm-core-plugins/blueprints/common/Meta.json new file mode 100644 index 000000000..73a5c3525 --- /dev/null +++ b/packages/dm-core-plugins/blueprints/common/Meta.json @@ -0,0 +1,19 @@ +{ + "name": "Meta", + "type": "CORE:Blueprint", + "extends": ["CORE:Entity"], + "description": "Purely for convenience. A wrapper that contains any entity. Used to render the 'meta' plugin around entities.", + "attributes": [ + { + "name": "type", + "type": "CORE:BlueprintAttribute", + "attributeType": "string" + }, + { + "name": "content", + "type": "CORE:BlueprintAttribute", + "attributeType": "object", + "optional": true + } + ] +} diff --git a/packages/dm-core-plugins/blueprints/publish/PublishConfig.json b/packages/dm-core-plugins/blueprints/publish/PublishConfig.json new file mode 100644 index 000000000..47498fda2 --- /dev/null +++ b/packages/dm-core-plugins/blueprints/publish/PublishConfig.json @@ -0,0 +1,31 @@ +{ + "name": "PublishConfig", + "type": "CORE:Blueprint", + "attributes": [ + { + "name": "type", + "type": "CORE:BlueprintAttribute", + "attributeType": "string" + }, + { + "name": "publishDestination", + "type": "dmss://system/SIMOS/BlueprintAttribute", + "attributeType": "string", + "description": "A reference/Id to where the published copy should be added." + }, + { + "name": "publishWrapper", + "type": "dmss://system/SIMOS/BlueprintAttribute", + "description": "A blueprint for which an entity of will serve as a wrapper for the published document", + "attributeType": "string", + "optional": true + }, + { + "name": "publishWrapperAttribute", + "type": "dmss://system/SIMOS/BlueprintAttribute", + "description": "Name of attribute in the 'publishWrapper'-blueprint of which the document will be placed.", + "attributeType": "string", + "optional": true + } + ] +} diff --git a/packages/dm-core-plugins/blueprints/publish/package.json b/packages/dm-core-plugins/blueprints/publish/package.json new file mode 100644 index 000000000..8d3904a50 --- /dev/null +++ b/packages/dm-core-plugins/blueprints/publish/package.json @@ -0,0 +1,25 @@ +{ + "name": "publish", + "type": "CORE:Package", + "isRoot": false, + "_meta_": { + "type": "CORE:Meta", + "version": "0.0.1", + "dependencies": [ + { + "type": "CORE:Dependency", + "alias": "CORE", + "address": "system/SIMOS", + "version": "0.0.1", + "protocol": "dmss" + }, + { + "type": "CORE:Dependency", + "alias": "PLUGINS", + "address": "system/Plugins", + "version": "0.0.1", + "protocol": "dmss" + } + ] + } +} diff --git a/packages/dm-core-plugins/src/index.tsx b/packages/dm-core-plugins/src/index.tsx index fe73ad94f..077aa8d78 100644 --- a/packages/dm-core-plugins/src/index.tsx +++ b/packages/dm-core-plugins/src/index.tsx @@ -151,4 +151,18 @@ export default ({ })) ), }, + '@development-framework/dm-core-plugins/meta': { + component: lazy(() => + import('./meta/MetaPlugin').then((module) => ({ + default: module.MetaPlugin, + })) + ), + }, + '@development-framework/dm-core-plugins/publish': { + component: lazy(() => + import('./publish/PublishPlugin').then((module) => ({ + default: module.PublishPlugin, + })) + ), + }, } as TUiPluginMap) diff --git a/packages/dm-core-plugins/src/meta/MetaPlugin.tsx b/packages/dm-core-plugins/src/meta/MetaPlugin.tsx new file mode 100644 index 000000000..86e4e8b32 --- /dev/null +++ b/packages/dm-core-plugins/src/meta/MetaPlugin.tsx @@ -0,0 +1,89 @@ +import { + EntityView, + IUIPlugin, + Loading, + TGenericObject, + TMeta, + useDocument, +} from '@development-framework/dm-core' +import { Table } from '@equinor/eds-core-react' +import { DateTime } from 'luxon' + +export const MetaPlugin = (props: IUIPlugin) => { + const { document, isLoading, error } = useDocument( + props.idReference, + 0 + ) + + if (isLoading) return + + if (error) throw new Error(JSON.stringify(error, null, 2)) + + if (!document) return + + const meta: TMeta = document._meta_ + + if (document.type !== 'dmss://system/Plugins/dm-core-plugins/common/Meta') + throw new Error( + 'The meta plugin only supports entities of type "Meta" at this stage' + ) + + return ( + <> + + + + Created by + Created time + Last modified by + Last modified time + + + + + {meta?.createdBy ?? '-'} + + {meta?.createdTimestamp + ? DateTime.fromISO(meta.createdTimestamp).toLocaleString( + { + day: '2-digit', + month: '2-digit', + year: '2-digit', + hour: '2-digit', + minute: '2-digit', + hourCycle: 'h23', + }, + { locale: 'nb' } + ) + : '-'} + + {meta?.lastModifiedBy ?? '-'} + + {meta?.lastModifiedTimestamp + ? DateTime.fromISO(meta.lastModifiedTimestamp).toLocaleString( + { + day: '2-digit', + month: '2-digit', + year: '2-digit', + hour: '2-digit', + minute: '2-digit', + hourCycle: 'h23', + }, + { locale: 'nb' } + ) + : '-'} + + + +
+ {/*This empty div wrapper is kind of a hack to avoid EntityView take the same height as the entire plugin*/} +
+ +
+ + ) +} diff --git a/packages/dm-core-plugins/src/publish/PublishPlugin.tsx b/packages/dm-core-plugins/src/publish/PublishPlugin.tsx new file mode 100644 index 000000000..0275ee4e4 --- /dev/null +++ b/packages/dm-core-plugins/src/publish/PublishPlugin.tsx @@ -0,0 +1,53 @@ +import { + CopyLinkDialog, + EntityView, + IUIPlugin, +} from '@development-framework/dm-core' +import { Button, Icon } from '@equinor/eds-core-react' +import { approve } from '@equinor/eds-icons' +import { useState } from 'react' + +export const PublishPlugin = ( + props: IUIPlugin & { + config: { + publishDestination: string + publishWrapper?: string + publishWrapperAttribute?: string + } + } +) => { + const { idReference } = props + const [showPublishDialog, setShowPublishDialog] = useState(false) + + return ( +
+
+ + +
+ +
+ ) +} diff --git a/packages/dm-core/src/components/CopyLinkDialog.tsx b/packages/dm-core/src/components/CopyLinkDialog.tsx index 45ed39d41..a2eb6c21c 100644 --- a/packages/dm-core/src/components/CopyLinkDialog.tsx +++ b/packages/dm-core/src/components/CopyLinkDialog.tsx @@ -16,7 +16,7 @@ import { } from '../index' import { setMetaInDocument } from '../utils/setMetaInDocument' -type TProps = { +type TPropsBase = { idReference: string open: boolean setOpen: (v: boolean) => void @@ -27,6 +27,13 @@ type TProps = { hideProvidedFields?: boolean } +type TProps = + | (TPropsBase & { wrapper?: undefined; wrapperAttribute?: undefined }) + | (TPropsBase & { + wrapper: string + wrapperAttribute: string + }) + export const CopyLinkDialog = (props: TProps) => { const { idReference, @@ -37,6 +44,8 @@ export const CopyLinkDialog = (props: TProps) => { hideProvidedFields, title, buttonText, + wrapper, + wrapperAttribute, } = props const { tokenData } = useContext(AuthContext) @@ -62,7 +71,7 @@ export const CopyLinkDialog = (props: TProps) => { const [isLoading, setIsLoading] = useState(false) const dmss = useDMSS() - const copyEntityToDestination = () => { + const copyEntityToDestination = async () => { if (!selectedDestination) return setIsLoading(true) let newDocument = window.structuredClone(document) as TValidEntity @@ -79,6 +88,16 @@ export const CopyLinkDialog = (props: TProps) => { newDocument = setMetaInDocument(newDocument, username) + if (wrapper) { + const wrapperEntity: TValidEntity = + // TODO: Handle relative/unresolved addresses? Perhaps in blueprint upload? + (await dmss.instantiateEntity({ entity: { type: wrapper } })) + .data as TValidEntity + wrapperEntity[wrapperAttribute] = newDocument + wrapperEntity._meta_ = newDocument._meta_ + newDocument = wrapperEntity + } + dmss .documentAdd({ address: selectedDestination.address, @@ -86,13 +105,15 @@ export const CopyLinkDialog = (props: TProps) => { }) .then(() => { toast.success(`Entity copied to '${selectedDestination.path}'`) - setOpen(false) }) .catch((error: AxiosError) => { console.error(error) toast.error(error.response?.data.message) }) - .finally(() => setIsLoading(false)) + .finally(() => { + setOpen(false) + setIsLoading(false) + }) } const insertLinkAtDestination = () => { @@ -120,7 +141,7 @@ export const CopyLinkDialog = (props: TProps) => { } return ( - + {title || 'Copy or link entity'}