From 9fc2cf23980d83772502d9c5ecfb765cf00733eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Collin=20L=C3=B8kken?= Date: Tue, 12 Sep 2023 08:47:46 +0200 Subject: [PATCH] fix: disables all edit form buttons when in readOnly mode --- .../plugins/form/read_only/car.recipe.json | 25 ++++++++++- .../read_only/carRentalCompany.recipe.json | 12 +++++ .../form/read_only/customer.recipe.json | 27 ++++++++++- .../blueprints/list/ListPluginConfig.json | 7 +++ .../src/form/fields/AttributeField.tsx | 1 + .../src/form/fields/ObjectField.tsx | 45 ++++++++++++++----- .../dm-core-plugins/src/list/Components.tsx | 3 +- .../dm-core-plugins/src/list/ListPlugin.tsx | 13 ++++-- .../dm-core/src/components/EntityView.tsx | 2 +- .../components/Pickers/EntityPickerButton.tsx | 12 ++++- 10 files changed, 127 insertions(+), 20 deletions(-) diff --git a/example/app/data/DemoDataSource/recipes/plugins/form/read_only/car.recipe.json b/example/app/data/DemoDataSource/recipes/plugins/form/read_only/car.recipe.json index 06d0c69fb..3d8e4af33 100644 --- a/example/app/data/DemoDataSource/recipes/plugins/form/read_only/car.recipe.json +++ b/example/app/data/DemoDataSource/recipes/plugins/form/read_only/car.recipe.json @@ -17,5 +17,28 @@ ], "readOnly": true } - } + }, + "uiRecipes": [ + { + "name": "MyCustomList", + "type": "dmss://system/SIMOS/UiRecipe", + "description": "", + "plugin": "@development-framework/dm-core-plugins/list", + "dimensions": "*", + "config": { + "type": "PLUGINS:dm-core-plugins/list/ListPluginConfig", + "views": [], + "headers": [ + "name", + "plateNumber" + ], + "openInline": false, + "functionality": { + "type": "PLUGINS:dm-core-plugins/list/FunctionalityConfig", + "delete": true + }, + "readOnly": true + } + } + ] } diff --git a/example/app/data/DemoDataSource/recipes/plugins/form/read_only/carRentalCompany.recipe.json b/example/app/data/DemoDataSource/recipes/plugins/form/read_only/carRentalCompany.recipe.json index 78e1a24a4..7aec2cddb 100644 --- a/example/app/data/DemoDataSource/recipes/plugins/form/read_only/carRentalCompany.recipe.json +++ b/example/app/data/DemoDataSource/recipes/plugins/form/read_only/carRentalCompany.recipe.json @@ -35,6 +35,12 @@ "showInline": false, "uiRecipe": "defaultForm" }, + { + "name": "ceo", + "type": "PLUGINS:dm-core-plugins/form/fields/ObjectField", + "showInline": false, + "uiRecipe": "defaultForm" + }, { "name": "trainee", "type": "PLUGINS:dm-core-plugins/form/fields/ObjectField", @@ -56,6 +62,12 @@ "name": "locations", "type": "PLUGINS:dm-core-plugins/form/fields/ArrayField", "showInline": true + }, + { + "name": "customers", + "type": "PLUGINS:dm-core-plugins/form/fields/ArrayField", + "showInline": false, + "uiRecipe": "myCustomArrayRecipe" } ], "fields": [ diff --git a/example/app/data/DemoDataSource/recipes/plugins/form/read_only/customer.recipe.json b/example/app/data/DemoDataSource/recipes/plugins/form/read_only/customer.recipe.json index 0765180b6..8e49b3d9a 100644 --- a/example/app/data/DemoDataSource/recipes/plugins/form/read_only/customer.recipe.json +++ b/example/app/data/DemoDataSource/recipes/plugins/form/read_only/customer.recipe.json @@ -4,7 +4,11 @@ "initialUiRecipe": { "name": "form", "type": "CORE:UiRecipe", - "plugin": "@development-framework/dm-core-plugins/form" + "plugin": "@development-framework/dm-core-plugins/form", + "config": { + "type": "PLUGINS:dm-core-plugins/form/FormInput", + "readOnly": true + } }, "uiRecipes": [ { @@ -18,6 +22,27 @@ "type": "CORE:UiRecipe", "plugin": "@development-framework/dm-core-plugins/form", "category": "edit" + }, + { + "name": "myCustomArrayRecipe", + "type": "dmss://system/SIMOS/UiRecipe", + "description": "", + "plugin": "@development-framework/dm-core-plugins/list", + "dimensions": "*", + "config": { + "type": "PLUGINS:dm-core-plugins/list/ListPluginConfig", + "views": [], + "headers": [ + "name", + "plateNumber" + ], + "openInline": false, + "functionality": { + "type": "PLUGINS:dm-core-plugins/list/FunctionalityConfig", + "delete": true + }, + "readOnly": true + } } ] } diff --git a/packages/dm-core-plugins/blueprints/list/ListPluginConfig.json b/packages/dm-core-plugins/blueprints/list/ListPluginConfig.json index c85f1acab..21f21e811 100644 --- a/packages/dm-core-plugins/blueprints/list/ListPluginConfig.json +++ b/packages/dm-core-plugins/blueprints/list/ListPluginConfig.json @@ -52,6 +52,13 @@ "dimensions": "*", "default": [], "optional": false + }, + { + "name": "readOnly", + "type": "CORE:BlueprintAttribute", + "attributeType": "boolean", + "optional": true, + "default": false } ] } diff --git a/packages/dm-core-plugins/src/form/fields/AttributeField.tsx b/packages/dm-core-plugins/src/form/fields/AttributeField.tsx index 662323ecd..644edcb62 100644 --- a/packages/dm-core-plugins/src/form/fields/AttributeField.tsx +++ b/packages/dm-core-plugins/src/form/fields/AttributeField.tsx @@ -65,6 +65,7 @@ export const AttributeField = (props: TAttributeFieldProps) => { optional={attribute.optional ?? false} uiAttribute={uiAttribute} defaultValue={attribute.default} + readOnly={readOnly} /> ) diff --git a/packages/dm-core-plugins/src/form/fields/ObjectField.tsx b/packages/dm-core-plugins/src/form/fields/ObjectField.tsx index 855181e61..8b4b7d3d5 100644 --- a/packages/dm-core-plugins/src/form/fields/ObjectField.tsx +++ b/packages/dm-core-plugins/src/form/fields/ObjectField.tsx @@ -24,8 +24,13 @@ import { OpenObjectButton } from '../components/OpenObjectButton' import { useRegistryContext } from '../context/RegistryContext' import { getWidget } from '../context/WidgetContext' import { TContentProps, TObjectFieldProps, TUiRecipeForm } from '../types' +import * as readline from 'readline' -const SelectReference = (props: { type: string; namePath: string }) => { +const SelectReference = (props: { + type: string + namePath: string + disabled?: boolean +}) => { const { setValue, watch } = useFormContext() const dmssAPI = useDMSS() const { idReference } = useRegistryContext() @@ -70,6 +75,7 @@ const SelectReference = (props: { type: string; namePath: string }) => { buttonVariant="outlined" typeFilter={props.type} alternativeButtonText="Select and save" + disabled={props.disabled} /> ) } @@ -78,8 +84,9 @@ const AddObject = (props: { type: string namePath: string defaultValue: any + disabled?: boolean }) => { - const { type, namePath, defaultValue } = props + const { type, namePath, defaultValue, disabled } = props const { setValue } = useFormContext() const dmssAPI = useDMSS() const { idReference } = useRegistryContext() @@ -118,14 +125,15 @@ const AddObject = (props: { variant="outlined" data-testid={`add-${namePath}`} onClick={handleAdd} + disabled={disabled} > Add and save ) } -const RemoveObject = (props: { namePath: string }) => { - const { namePath } = props +const RemoveObject = (props: { namePath: string; disabled?: boolean }) => { + const { namePath, disabled } = props const { setValue } = useFormContext() const { idReference } = useRegistryContext() const dmssAPI = useDMSS() @@ -151,6 +159,7 @@ const RemoveObject = (props: { namePath: string }) => { variant="outlined" data-testid={`remove-${namePath}`} onClick={onClick} + disabled={disabled} > Remove and save @@ -167,23 +176,24 @@ export const ContainedAttribute = (props: TContentProps): JSX.Element => { uiRecipe, blueprint, defaultValue, + readOnly, } = props const { watch } = useFormContext() const { idReference, onOpen } = useRegistryContext() const value = watch(namePath) const isDefined = value && Object.keys(value).length > 0 - return ( {displayLabel} {optional && (isDefined ? ( - + ) : ( ))} {isDefined && @@ -247,8 +257,15 @@ const Indent = styled.div` ` export const UncontainedAttribute = (props: TContentProps): JSX.Element => { - const { type, namePath, displayLabel, uiAttribute, uiRecipe, optional } = - props + const { + type, + namePath, + displayLabel, + uiAttribute, + uiRecipe, + optional, + readOnly, + } = props const { watch } = useFormContext() const { idReference, onOpen } = useRegistryContext() const value = watch(namePath) @@ -263,8 +280,10 @@ export const UncontainedAttribute = (props: TContentProps): JSX.Element => { {displayLabel} {address && Address: {value.address}} - - {optional && address && } + + {optional && address && ( + + )} {address && onOpen && !uiAttribute?.showInline && ( { } export const ObjectField = (props: TObjectFieldProps): JSX.Element => { - const { type, namePath, uiAttribute, displayLabel, defaultValue } = props + const { type, namePath, uiAttribute, displayLabel, defaultValue, readOnly } = + props const { getValues } = useFormContext() // Be able to override the object field @@ -308,6 +328,7 @@ export const ObjectField = (props: TObjectFieldProps): JSX.Element => { label={displayLabel} type={type === 'object' && values ? values.type : type} defaultValue={defaultValue} + readOnly={readOnly} /> ) } @@ -321,6 +342,7 @@ export const ObjectTypeSelector = (props: TObjectFieldProps): JSX.Element => { contained, uiAttribute, defaultValue, + readOnly, } = props const { blueprint, uiRecipes, isLoading, error } = useBlueprint(type) @@ -345,6 +367,7 @@ export const ObjectTypeSelector = (props: TObjectFieldProps): JSX.Element => { uiRecipe={uiRecipe} uiAttribute={uiAttribute} defaultValue={defaultValue} + readOnly={readOnly} /> ) } diff --git a/packages/dm-core-plugins/src/list/Components.tsx b/packages/dm-core-plugins/src/list/Components.tsx index b3b6dda05..7124e3add 100644 --- a/packages/dm-core-plugins/src/list/Components.tsx +++ b/packages/dm-core-plugins/src/list/Components.tsx @@ -9,8 +9,9 @@ import { export const AppendButton = (props: { onClick: (event: MouseEvent) => void + disabled: boolean }) => ( - ) diff --git a/packages/dm-core-plugins/src/list/ListPlugin.tsx b/packages/dm-core-plugins/src/list/ListPlugin.tsx index dcc824aa7..43135d71d 100644 --- a/packages/dm-core-plugins/src/list/ListPlugin.tsx +++ b/packages/dm-core-plugins/src/list/ListPlugin.tsx @@ -30,6 +30,7 @@ type TListConfig = { sort: boolean delete: boolean } + readOnly: boolean } const defaultConfig: TListConfig = { expanded: false, @@ -44,6 +45,7 @@ const defaultConfig: TListConfig = { sort: false, delete: false, }, + readOnly: false, } type ItemRow = { @@ -230,7 +232,7 @@ export const ListPlugin = (props: IUIPlugin & { config?: TListConfig }) => { {internalConfig?.functionality?.delete && ( <> { setItems(moveItem(items, item.key, 'up')) setUnsavedChanges(true) @@ -241,7 +243,8 @@ export const ListPlugin = (props: IUIPlugin & { config?: TListConfig }) => { type="down" disabled={ index === paginationRowsPerPage - 1 || - index === items?.length - 1 + index === items?.length - 1 || + internalConfig.readOnly } onClick={() => { setItems(moveItem(items, item.key, 'down')) @@ -253,6 +256,7 @@ export const ListPlugin = (props: IUIPlugin & { config?: TListConfig }) => { onClick={() => deleteItem(`${idReference}[${item.index}]`, item.key) } + disabled={internalConfig.readOnly} /> )} @@ -285,7 +289,10 @@ export const ListPlugin = (props: IUIPlugin & { config?: TListConfig }) => { setRowsPerPage={setPaginationRowsPerPage} /> - addItem()} /> + addItem()} + disabled={internalConfig.readOnly} + /> { recipeName, dimensions ) - + console.log(type, recipeName, recipe) if (isLoading) return (
diff --git a/packages/dm-core/src/components/Pickers/EntityPickerButton.tsx b/packages/dm-core/src/components/Pickers/EntityPickerButton.tsx index 535d9ea29..4d4706972 100644 --- a/packages/dm-core/src/components/Pickers/EntityPickerButton.tsx +++ b/packages/dm-core/src/components/Pickers/EntityPickerButton.tsx @@ -32,9 +32,16 @@ export const EntityPickerButton = (props: { alternativeButtonText?: string buttonVariant?: 'contained' | 'outlined' | 'ghost' | 'ghost_icon' scope?: string + disabled?: boolean }) => { - const { onChange, typeFilter, alternativeButtonText, buttonVariant, scope } = - props + const { + onChange, + typeFilter, + alternativeButtonText, + buttonVariant, + scope, + disabled, + } = props const appConfig = useContext(ApplicationContext) const [showModal, setShowModal] = useState(false) const [loading, setLoading] = useState(true) @@ -81,6 +88,7 @@ export const EntityPickerButton = (props: {