diff --git a/apps/core/src/__tests__/mocks/actionsList.ts b/apps/core/src/__tests__/mocks/actionsList.ts index d19355ba4..d00f5939e 100644 --- a/apps/core/src/__tests__/mocks/actionsList.ts +++ b/apps/core/src/__tests__/mocks/actionsList.ts @@ -8,6 +8,7 @@ const mockActionBase: IActionsListFunction = { id: 'myAction', name: 'MyAction', description: 'My action', + compute: false, input_types: Object.values(ActionsListIOTypes), output_types: Object.values(ActionsListIOTypes), action: jest.fn() diff --git a/apps/core/src/_types/actionsList.ts b/apps/core/src/_types/actionsList.ts index a4a32c15c..f4bc392b1 100644 --- a/apps/core/src/_types/actionsList.ts +++ b/apps/core/src/_types/actionsList.ts @@ -70,6 +70,7 @@ export interface IActionsListFunction< output_types: ActionsListIOTypes[]; params?: Array>; error_message?: ISystemTranslation; + compute: boolean; action: ( values: IValue[], params: PartialByCondition, ParamsRequired>, diff --git a/apps/core/src/app/core/attributeApp/attributeApp.ts b/apps/core/src/app/core/attributeApp/attributeApp.ts index 333602aef..42248cd8f 100644 --- a/apps/core/src/app/core/attributeApp/attributeApp.ts +++ b/apps/core/src/app/core/attributeApp/attributeApp.ts @@ -70,6 +70,7 @@ export default function (deps: IDeps): ICoreAttributeApp { coreApp.filterSysTranslationField(attributeData.description, args.lang || []), input_types: (attributeData, _, ctx) => attributeDomain.getInputTypes({attrData: attributeData, ctx}), output_types: (attributeData, _, ctx) => attributeDomain.getOutputTypes({attrData: attributeData, ctx}), + compute: (attributeData, _, ctx) => attributeDomain.doesCompute(attributeData), metadata_fields: async (attributeData: IAttribute, _, ctx) => !!attributeData.metadata_fields ? Promise.all( @@ -138,6 +139,7 @@ export default function (deps: IDeps): ICoreAttributeApp { output_types: ActionListIOTypes!, metadata_fields: [StandardAttribute!], libraries: [Library!], + compute: Boolean!, # Permissions for this attribute. # If record is specified, returns permissions for this specific record, otherwise returns global attribute permissions @@ -195,14 +197,14 @@ export default function (deps: IDeps): ICoreAttributeApp { maxLength: Int } - type LinkAttribute implements Attribute{ + type LinkAttribute implements Attribute { ${attributesInterfaceSchema} linked_library: Library, values_list: LinkValuesListConf, reverse_link: String } - type TreeAttribute implements Attribute{ + type TreeAttribute implements Attribute { ${attributesInterfaceSchema} linked_tree: Tree, values_list: TreeValuesListConf diff --git a/apps/core/src/domain/actions/dateRangeToNumberAction.ts b/apps/core/src/domain/actions/dateRangeToNumberAction.ts index 340fb351d..befb04b94 100644 --- a/apps/core/src/domain/actions/dateRangeToNumberAction.ts +++ b/apps/core/src/domain/actions/dateRangeToNumberAction.ts @@ -11,6 +11,7 @@ export default function (): IActionsListFunction { description: 'Convert date range dates to numbers', input_types: [ActionsListIOTypes.OBJECT], output_types: [ActionsListIOTypes.OBJECT], + compute: false, action: values => ({ values: values.map(valueElement => { const dateRangeValue = valueElement.payload as IDateRangeValue; diff --git a/apps/core/src/domain/actions/encryptAction.ts b/apps/core/src/domain/actions/encryptAction.ts index fbb6095d5..41dac83b2 100644 --- a/apps/core/src/domain/actions/encryptAction.ts +++ b/apps/core/src/domain/actions/encryptAction.ts @@ -12,6 +12,7 @@ export default function (): IActionsListFunction { description: 'Encrypt value', input_types: [ActionsListIOTypes.STRING], output_types: [ActionsListIOTypes.STRING], + compute: false, action: async values => values.reduce( async (promAcc, valueElement) => { diff --git a/apps/core/src/domain/actions/excelCalculationAction.ts b/apps/core/src/domain/actions/excelCalculationAction.ts index 08ee8fc01..30afc4aa8 100644 --- a/apps/core/src/domain/actions/excelCalculationAction.ts +++ b/apps/core/src/domain/actions/excelCalculationAction.ts @@ -74,6 +74,7 @@ export default function ({ description: 'Performs an excel calculation', input_types: [ActionsListIOTypes.STRING, ActionsListIOTypes.NUMBER], output_types: [ActionsListIOTypes.STRING], + compute: true, params: [ { name: 'Description', diff --git a/apps/core/src/domain/actions/formatDateAction.ts b/apps/core/src/domain/actions/formatDateAction.ts index 6e227400c..de9f18233 100644 --- a/apps/core/src/domain/actions/formatDateAction.ts +++ b/apps/core/src/domain/actions/formatDateAction.ts @@ -21,6 +21,7 @@ export default function (): IActionsListFunction<{localized: false; universal: f description: 'Convert timestamp to a date', input_types: [ActionsListIOTypes.NUMBER], output_types: [ActionsListIOTypes.STRING], + compute: false, params: [ { name: 'localized', diff --git a/apps/core/src/domain/actions/formatDateRangeAction.ts b/apps/core/src/domain/actions/formatDateRangeAction.ts index b5a7dc93a..58910fae7 100644 --- a/apps/core/src/domain/actions/formatDateRangeAction.ts +++ b/apps/core/src/domain/actions/formatDateRangeAction.ts @@ -22,6 +22,7 @@ export default function (): IActionsListFunction<{localized: false; universal: f description: 'Convert range timestamps to a range dates', input_types: [ActionsListIOTypes.OBJECT], output_types: [ActionsListIOTypes.OBJECT], + compute: false, params: [ { name: 'localized', diff --git a/apps/core/src/domain/actions/formatNumberAction.ts b/apps/core/src/domain/actions/formatNumberAction.ts index e4e78840c..9fd4e9ee5 100644 --- a/apps/core/src/domain/actions/formatNumberAction.ts +++ b/apps/core/src/domain/actions/formatNumberAction.ts @@ -31,6 +31,7 @@ export default function (): IActionsListFunction<{ description: 'Format a number', input_types: [ActionsListIOTypes.NUMBER], output_types: [ActionsListIOTypes.STRING], + compute: false, params: [ { name: 'decimals', diff --git a/apps/core/src/domain/actions/inheritanceCalculationAction.ts b/apps/core/src/domain/actions/inheritanceCalculationAction.ts index 7af808b34..2906c1478 100644 --- a/apps/core/src/domain/actions/inheritanceCalculationAction.ts +++ b/apps/core/src/domain/actions/inheritanceCalculationAction.ts @@ -31,6 +31,7 @@ export default function ({ ActionsListIOTypes.OBJECT, ActionsListIOTypes.BOOLEAN ], + compute: true, params: [ { name: 'Description', diff --git a/apps/core/src/domain/actions/maskValueAction.ts b/apps/core/src/domain/actions/maskValueAction.ts index ab43ea4fe..7975ccfec 100644 --- a/apps/core/src/domain/actions/maskValueAction.ts +++ b/apps/core/src/domain/actions/maskValueAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Mask any value by replacing with dots or empty string if no value', input_types: [ActionsListIOTypes.STRING, ActionsListIOTypes.NUMBER, ActionsListIOTypes.OBJECT], output_types: [ActionsListIOTypes.STRING], + compute: false, action: values => { const _isValueDefined = value => value !== null && value !== '' && (typeof value !== 'object' || Object.keys(value).length); diff --git a/apps/core/src/domain/actions/parseJSONAction.ts b/apps/core/src/domain/actions/parseJSONAction.ts index 1f3b4233e..5368788b1 100644 --- a/apps/core/src/domain/actions/parseJSONAction.ts +++ b/apps/core/src/domain/actions/parseJSONAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Parse a JSON string', input_types: [ActionsListIOTypes.STRING], output_types: [ActionsListIOTypes.OBJECT], + compute: false, action: values => { const computedValues = values.map(elementValue => { elementValue.payload = JSON.parse('' + elementValue.payload); diff --git a/apps/core/src/domain/actions/toBooleanAction.ts b/apps/core/src/domain/actions/toBooleanAction.ts index 8e3884c1e..a78efc2f6 100644 --- a/apps/core/src/domain/actions/toBooleanAction.ts +++ b/apps/core/src/domain/actions/toBooleanAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Convert value to boolean', input_types: [ActionsListIOTypes.STRING, ActionsListIOTypes.NUMBER, ActionsListIOTypes.BOOLEAN], output_types: [ActionsListIOTypes.BOOLEAN], + compute: false, action: values => { const computedValues = values.map(elementValue => { switch (elementValue.payload) { diff --git a/apps/core/src/domain/actions/toJSONAction.ts b/apps/core/src/domain/actions/toJSONAction.ts index e34c2f3fc..44536f7ca 100644 --- a/apps/core/src/domain/actions/toJSONAction.ts +++ b/apps/core/src/domain/actions/toJSONAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Convert value to a JSON string', input_types: [ActionsListIOTypes.OBJECT], output_types: [ActionsListIOTypes.STRING], + compute: false, action: values => { const computedValues = values.map(elementValue => { elementValue.payload = elementValue?.payload === null ? null : JSON.stringify(elementValue.payload); diff --git a/apps/core/src/domain/actions/toNumberAction.ts b/apps/core/src/domain/actions/toNumberAction.ts index 1fea9b2c9..1e6afb1d2 100644 --- a/apps/core/src/domain/actions/toNumberAction.ts +++ b/apps/core/src/domain/actions/toNumberAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Convert value to number', input_types: [ActionsListIOTypes.STRING, ActionsListIOTypes.NUMBER, ActionsListIOTypes.BOOLEAN], output_types: [ActionsListIOTypes.NUMBER], + compute: false, action: values => { const computedValues = values.map(elementValue => { elementValue.payload = elementValue.payload !== null ? Number(elementValue.payload) : null; diff --git a/apps/core/src/domain/actions/toStringAction.ts b/apps/core/src/domain/actions/toStringAction.ts index 720931a55..ea5099192 100644 --- a/apps/core/src/domain/actions/toStringAction.ts +++ b/apps/core/src/domain/actions/toStringAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Convert value to string', input_types: [ActionsListIOTypes.STRING, ActionsListIOTypes.NUMBER, ActionsListIOTypes.BOOLEAN], output_types: [ActionsListIOTypes.STRING], + compute: false, action: values => { const computedValues = values.map(elementValue => { elementValue.payload = elementValue.payload !== null ? String(elementValue.payload) : null; diff --git a/apps/core/src/domain/actions/toUppercaseAction.ts b/apps/core/src/domain/actions/toUppercaseAction.ts index bedab8c75..372e04f15 100644 --- a/apps/core/src/domain/actions/toUppercaseAction.ts +++ b/apps/core/src/domain/actions/toUppercaseAction.ts @@ -10,6 +10,7 @@ export default function (): IActionsListFunction { description: 'Convert the string to uppercase', input_types: [ActionsListIOTypes.STRING], output_types: [ActionsListIOTypes.STRING], + compute: false, action: values => { const computedValues = values.map(elementValue => { elementValue.payload = diff --git a/apps/core/src/domain/actions/validateEmailAction.ts b/apps/core/src/domain/actions/validateEmailAction.ts index 28687e03a..21f4381db 100644 --- a/apps/core/src/domain/actions/validateEmailAction.ts +++ b/apps/core/src/domain/actions/validateEmailAction.ts @@ -13,6 +13,7 @@ export default function (): IActionsListFunction { description: 'Check if value is a string matching email format', input_types: [ActionsListIOTypes.STRING], output_types: [ActionsListIOTypes.STRING], + compute: false, action: values => { const allErrors = values.reduce((errors, elementValue) => { if (!elementValue.payload.match(EMAIL_REGEX)) { diff --git a/apps/core/src/domain/actions/validateFormatAction.ts b/apps/core/src/domain/actions/validateFormatAction.ts index 69209d92f..dea6a94ea 100644 --- a/apps/core/src/domain/actions/validateFormatAction.ts +++ b/apps/core/src/domain/actions/validateFormatAction.ts @@ -13,6 +13,7 @@ export default function (): IActionsListFunction { id: 'validateFormat', name: 'Validate Format', description: 'Check if value matches attribute format', + compute: false, input_types: [ ActionsListIOTypes.STRING, ActionsListIOTypes.NUMBER, diff --git a/apps/core/src/domain/actions/validateRegexAction.ts b/apps/core/src/domain/actions/validateRegexAction.ts index 9e2b1b2a5..6d7943a29 100644 --- a/apps/core/src/domain/actions/validateRegexAction.ts +++ b/apps/core/src/domain/actions/validateRegexAction.ts @@ -13,6 +13,7 @@ export default function (): IActionsListFunction<{regex: true}> { input_types: [ActionsListIOTypes.STRING], output_types: [ActionsListIOTypes.STRING], params: [{name: 'regex', type: 'string', description: 'Validation regex', required: true, default_value: ''}], + compute: false, action: (values, params) => { const allErrors = values.reduce>( (errors, elementValue) => { diff --git a/apps/core/src/domain/actions/validateURLAction.ts b/apps/core/src/domain/actions/validateURLAction.ts index cf3692834..0a1e70729 100644 --- a/apps/core/src/domain/actions/validateURLAction.ts +++ b/apps/core/src/domain/actions/validateURLAction.ts @@ -12,6 +12,7 @@ export default function (): IActionsListFunction { description: 'Check if value is a string matching URL format', input_types: [ActionsListIOTypes.STRING], output_types: [ActionsListIOTypes.STRING], + compute: false, action: (values: IValue[]) => { const allErrors = values.reduce>( (errors, elementValue) => { diff --git a/apps/core/src/domain/attribute/attributeDomain.ts b/apps/core/src/domain/attribute/attributeDomain.ts index 373f33142..5785330ba 100644 --- a/apps/core/src/domain/attribute/attributeDomain.ts +++ b/apps/core/src/domain/attribute/attributeDomain.ts @@ -26,6 +26,7 @@ import {IActionsListDomain} from '../actionsList/actionsListDomain'; import getPermissionCachePatternKey from '../permission/helpers/getPermissionCachePatternKey'; import {getActionsListToSave, getAllowedInputTypes, getAllowedOutputTypes} from './helpers/attributeALHelper'; import {validateAttributeData} from './helpers/attributeValidationHelper'; +import {ActionsListEvents} from '../../_types/actionsList'; export interface IAttributeDomain { getAttributeProperties({id, ctx}: {id: string; ctx: IQueryInfos}): Promise; @@ -55,6 +56,8 @@ export interface IAttributeDomain { * Retrieve libraries linked to attribute */ getAttributeLibraries(params: {attributeId: string; ctx: IQueryInfos}): Promise; + + doesCompute(attrData: IAttribute): boolean; } export interface IAttributeDomainDeps { @@ -112,6 +115,13 @@ export default function ({ }; return { + doesCompute(attrData): boolean { + const availableActions = actionsListDomain.getAvailableActions(); + + return attrData.actions_list[ActionsListEvents.GET_VALUE].some( + action => availableActions.find(availableAction => availableAction.id === action.id).compute + ); + }, async getLibraryAttributes(libraryId: string, ctx): Promise { const _execute = async () => { const libs = await libraryRepo.getLibraries({params: {filters: {id: libraryId}}, ctx}); diff --git a/libs/ui/src/__mocks__/common/attribute.ts b/libs/ui/src/__mocks__/common/attribute.ts index 35c6f855d..6cb213538 100644 --- a/libs/ui/src/__mocks__/common/attribute.ts +++ b/libs/ui/src/__mocks__/common/attribute.ts @@ -134,7 +134,15 @@ export const mockFormAttribute: RecordFormAttributeFragment = { } } ], - versions_conf: null + versions_conf: null, + compute: false +}; + +export const mockFormAttributeCompute: RecordFormAttributeFragment = { + ...mockFormAttribute, + id: 'test_compute_attribute', + format: AttributeFormat.text, + compute: true }; export const mockFormAttributeTree: RecordFormAttributeTreeAttributeFragment = { diff --git a/libs/ui/src/__mocks__/common/value.ts b/libs/ui/src/__mocks__/common/value.ts index 29d772cf1..4a238eaae 100644 --- a/libs/ui/src/__mocks__/common/value.ts +++ b/libs/ui/src/__mocks__/common/value.ts @@ -43,6 +43,7 @@ export const mockRecordPropertyWithAttribute: IRecordPropertyWithAttribute = { }, multiple_values: false, readonly: false, - permissions: {access_attribute: true, edit_value: true} + permissions: {access_attribute: true, edit_value: true}, + compute: false } }; diff --git a/libs/ui/src/_gqlTypes/index.ts b/libs/ui/src/_gqlTypes/index.ts index 408aeaaa2..cc514a441 100644 --- a/libs/ui/src/_gqlTypes/index.ts +++ b/libs/ui/src/_gqlTypes/index.ts @@ -1,8 +1,8 @@ // Copyright LEAV Solutions 2017 until 2023/11/05, Copyright Aristid from 2023/11/06 // This file is released under LGPL V3 // License text available at https://www.gnu.org/licenses/lgpl-3.0.txt -import {IPreviewScalar} from '@leav/utils'; -import {gql} from '@apollo/client'; +import {IPreviewScalar} from '@leav/utils' +import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; export type Maybe = T | null; export type InputMaybe = Maybe; @@ -283,6 +283,17 @@ export enum FormsSortableFields { system = 'system' } +export enum GenerationStatus { + DONE = 'DONE', + GENERATION_FAILED = 'GENERATION_FAILED', + GENERATION_IN_PROGRESS = 'GENERATION_IN_PROGRESS', + GENERATION_IN_PROGRESS_WITH_FAILURE = 'GENERATION_IN_PROGRESS_WITH_FAILURE', + PREPARATION_FAILED = 'PREPARATION_FAILED', + PREPARATION_IN_PROGRESS = 'PREPARATION_IN_PROGRESS', + TRANSMISSION_FAILED = 'TRANSMISSION_FAILED', + TRANSMISSION_IN_PROGRESS = 'TRANSMISSION_IN_PROGRESS' +} + export type GlobalSettingsFileInput = { library: Scalars['String']; recordId: Scalars['String']; @@ -903,7 +914,7 @@ export type LibraryLinkAttributeDetailsFragment = { linked_library?: { id: strin export type LibraryPreviewsSettingsFragment = { label: any, description?: any | null, system: boolean, versions: { background: string, density: number, sizes: Array<{ name: string, size: number }> } }; -export type RecordFormElementFragment = { id: string, containerId: string, uiElementType: string, type: FormElementTypes, valueError?: string | null, values?: Array<{ id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, linkValue?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, treeValue?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { payload?: any | null, raw_payload?: any | null, value?: any | null, raw_value?: any | null, id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null }> | null, attribute?: { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, linked_library?: { id: string, label?: any | null, behavior: LibraryBehavior, permissions?: { create_record: boolean } | null } | null, linkValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, linked_tree?: { id: string, label?: any | null } | null, treeValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | null, settings: Array<{ key: string, value: any }> }; +export type RecordFormElementFragment = { id: string, containerId: string, uiElementType: string, type: FormElementTypes, valueError?: string | null, values?: Array<{ id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, linkValue?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, treeValue?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { payload?: any | null, raw_payload?: any | null, value?: any | null, raw_value?: any | null, id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null }> | null, attribute?: { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, linked_library?: { id: string, label?: any | null, behavior: LibraryBehavior, permissions?: { create_record: boolean } | null } | null, linkValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, linked_tree?: { id: string, label?: any | null } | null, treeValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | null, settings: Array<{ key: string, value: any }> }; export type ValueDetailsLinkValueFragment = { id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, linkValue?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null }; @@ -915,11 +926,11 @@ export type ValueDetailsFragment = ValueDetailsLinkValueFragment | ValueDetailsT export type ValuesVersionDetailsFragment = { treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null }; -export type RecordFormAttributeLinkAttributeFragment = { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, linked_library?: { id: string, label?: any | null, behavior: LibraryBehavior, permissions?: { create_record: boolean } | null } | null, linkValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null }; +export type RecordFormAttributeLinkAttributeFragment = { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, linked_library?: { id: string, label?: any | null, behavior: LibraryBehavior, permissions?: { create_record: boolean } | null } | null, linkValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null }; -export type RecordFormAttributeStandardAttributeFragment = { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null }; +export type RecordFormAttributeStandardAttributeFragment = { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null }; -export type RecordFormAttributeTreeAttributeFragment = { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, linked_tree?: { id: string, label?: any | null } | null, treeValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null }; +export type RecordFormAttributeTreeAttributeFragment = { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, linked_tree?: { id: string, label?: any | null } | null, treeValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null }; export type RecordFormAttributeFragment = RecordFormAttributeLinkAttributeFragment | RecordFormAttributeStandardAttributeFragment | RecordFormAttributeTreeAttributeFragment; @@ -1195,7 +1206,7 @@ export type RecordFormQueryVariables = Exact<{ }>; -export type RecordFormQuery = { recordForm?: { id: string, recordId?: string | null, library: { id: string }, dependencyAttributes?: Array<{ id: string }> | null, elements: Array<{ id: string, containerId: string, uiElementType: string, type: FormElementTypes, valueError?: string | null, values?: Array<{ id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, linkValue?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, treeValue?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { payload?: any | null, raw_payload?: any | null, value?: any | null, raw_value?: any | null, id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null }> | null, attribute?: { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, linked_library?: { id: string, label?: any | null, behavior: LibraryBehavior, permissions?: { create_record: boolean } | null } | null, linkValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, linked_tree?: { id: string, label?: any | null } | null, treeValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | null, settings: Array<{ key: string, value: any }> }> } | null }; +export type RecordFormQuery = { recordForm?: { id: string, recordId?: string | null, library: { id: string }, dependencyAttributes?: Array<{ id: string }> | null, elements: Array<{ id: string, containerId: string, uiElementType: string, type: FormElementTypes, valueError?: string | null, values?: Array<{ id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, linkValue?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, treeValue?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null } | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null } | { payload?: any | null, raw_payload?: any | null, value?: any | null, raw_value?: any | null, id_value?: string | null, isInherited?: boolean | null, isCalculated?: boolean | null, modified_at?: number | null, created_at?: number | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null, attribute: { id: string, format?: AttributeFormat | null, type: AttributeType, system: boolean }, metadata?: Array<{ name: string, value?: { id_value?: string | null, modified_at?: number | null, created_at?: number | null, payload?: any | null, raw_payload?: any | null, modified_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, created_by?: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } | null, version?: Array<{ treeId: string, treeNode?: { id: string, record: { id: string, whoAmI: { id: string, label?: string | null, library: { id: string } } } } | null } | null> | null } | null } | null> | null }> | null, attribute?: { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, linked_library?: { id: string, label?: any | null, behavior: LibraryBehavior, permissions?: { create_record: boolean } | null } | null, linkValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | { id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, compute: boolean, linked_tree?: { id: string, label?: any | null } | null, treeValuesList?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array<{ id: string, record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } }, ancestors?: Array<{ record: { id: string, whoAmI: { id: string, label?: string | null, subLabel?: string | null, color?: string | null, preview?: IPreviewScalar | null, library: { id: string, label?: any | null } } } }> | null }> | null } | null, permissions: { access_attribute: boolean, edit_value: boolean }, versions_conf?: { versionable: boolean, profile?: { id: string, trees: Array<{ id: string, label?: any | null }> } | null } | null, metadata_fields?: Array<{ id: string, label?: any | null, description?: any | null, type: AttributeType, format?: AttributeFormat | null, system: boolean, readonly: boolean, multiple_values: boolean, permissions: { access_attribute: boolean, edit_value: boolean }, values_list?: { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, dateRangeValues?: Array<{ from?: string | null, to?: string | null }> | null } | { enable: boolean, allowFreeEntry?: boolean | null, allowListUpdate?: boolean | null, values?: Array | null } | null, metadata_fields?: Array<{ id: string }> | null }> | null } | null, settings: Array<{ key: string, value: any }> }> } | null }; export type RecordUpdateSubscriptionVariables = Exact<{ filters?: InputMaybe; @@ -1707,6 +1718,7 @@ export const RecordFormAttributeFragmentDoc = gql` system readonly multiple_values + compute permissions(record: {id: $recordId, library: $libraryId}) { access_attribute edit_value diff --git a/libs/ui/src/_queries/records/getRecordColumnsValues.ts b/libs/ui/src/_queries/records/getRecordColumnsValues.ts index b493bc007..ad91fcb50 100644 --- a/libs/ui/src/_queries/records/getRecordColumnsValues.ts +++ b/libs/ui/src/_queries/records/getRecordColumnsValues.ts @@ -23,6 +23,8 @@ export interface IRecordColumnTreeValue { export interface IRecordColumnValueStandard { value: string | null; + isCalculated: boolean; + isInherited: boolean; } export interface IRecordColumnValueLink { @@ -35,8 +37,8 @@ export interface IRecordColumnValueTree { export type RecordColumnValue = IRecordColumnValueStandard | IRecordColumnValueLink | IRecordColumnValueTree; -export type GetRecordColumnsValuesRecord = { - [attributeName: string]: RecordColumnValue[]; +export type GetRecordColumnsValuesRecord = { + [attributeName: string]: RecordColumnValues[]; } & { _id: string; }; @@ -55,7 +57,10 @@ export interface IGetRecordColumnsValuesVariables { const _getColumnQueryPart = (column: string): string => ` ${column}: property(attribute: "${column}") { ...on Value { - value + payload + raw_payload + isInherited + isCalculated } ...on LinkValue { diff --git a/libs/ui/src/_queries/records/recordFormAttributeFragment.ts b/libs/ui/src/_queries/records/recordFormAttributeFragment.ts index 8eab127d7..262e71a17 100644 --- a/libs/ui/src/_queries/records/recordFormAttributeFragment.ts +++ b/libs/ui/src/_queries/records/recordFormAttributeFragment.ts @@ -13,6 +13,7 @@ export const recordFormAttributeFragment = gql` system readonly multiple_values + compute permissions(record: {id: $recordId, library: $libraryId}) { access_attribute edit_value diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/EditRecordContent.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/EditRecordContent.tsx index af3895892..508ffab79 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/EditRecordContent.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/EditRecordContent.tsx @@ -20,6 +20,7 @@ import {DeleteMultipleValuesFunc, DeleteValueFunc, FormElement, SubmitValueFunc} import {Form, FormInstance} from 'antd'; import {EDIT_OR_CREATE_RECORD_FORM_ID} from './formConstants'; import {getAntdFormInitialValues} from '_ui/components/RecordEdition/EditRecordContent/antdUtils'; +import {useGetRecordValuesQuery} from '_ui/hooks/useGetRecordValuesQuery/useGetRecordValuesQuery'; interface IEditRecordContentProps { antdForm: FormInstance; @@ -70,6 +71,14 @@ const EditRecordContent: FunctionComponent = ({ version: state.valuesVersion }); + const {data: computeFieldsData, refetch: refetchComputeFields} = useGetRecordValuesQuery( + library, + recordForm + ? recordForm.elements.filter(element => element.attribute?.compute).map(element => element.attribute.id) + : [], + [record?.id] + ); + // Generate a hash of recordForm to detect changes const recordFormHash = useMemo(() => simpleStringHash(JSON.stringify(recordForm)), [recordForm]); @@ -105,6 +114,11 @@ const EditRecordContent: FunctionComponent = ({ _checkDependencyChange(element[0].attribute.id); + const isEditing = Boolean(record); + if (isEditing) { + refetchComputeFields(); + } + return submitRes; }; @@ -131,6 +145,7 @@ const EditRecordContent: FunctionComponent = ({ }; const antdFormInitialValues = getAntdFormInitialValues(recordForm); + const recordComputedValues = computeFieldsData && record ? computeFieldsData[record.id] : null; return (
= ({ initialValues={antdFormInitialValues} onFinish={onRecordSubmit} > - + & { - uiElement: (props: IFormElementProps & {antdForm?: FormInstance}) => JSX.Element; + uiElement: ( + props: IFormElementProps & { + antdForm?: FormInstance; + computedValues?: GetRecordColumnsValuesRecord; + } + ) => JSX.Element; }; export interface IDependencyValues { diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.test.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.test.tsx index 029ab4527..636ff3af4 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.test.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.test.tsx @@ -1,14 +1,44 @@ // Copyright LEAV Solutions 2017 until 2023/11/05, Copyright Aristid from 2023/11/06 // This file is released under LGPL V3 // License text available at https://www.gnu.org/licenses/lgpl-3.0.txt -import {getAntdFormInitialValues, getEmptyInitialValue} from '_ui/components/RecordEdition/EditRecordContent/antdUtils'; +import { + getAntdDisplayedValue, + getAntdFormInitialValues, + getEmptyInitialValue +} from '_ui/components/RecordEdition/EditRecordContent/antdUtils'; import {AttributeFormat, AttributeType} from '_ui/_gqlTypes'; import {mockFormAttribute} from '_ui/__mocks__/common/attribute'; +import {RecordFormElementAttribute, RecordFormElementsValueStandardValue} from '_ui/hooks/useGetRecordForm'; jest.mock('dayjs', () => ({ unix: jest.fn(t => t) })); +describe('getAntdDisplayedValue', () => { + it.each` + values | attribute | result + ${[{raw_payload: ''}]} | ${{format: AttributeFormat.text}} | ${''} + ${[{raw_payload: 'truc'}]} | ${{format: AttributeFormat.text}} | ${'truc'} + ${[{raw_payload: null}, {raw_payload: 'calcul', isCalculated: true}]} | ${{format: AttributeFormat.text}} | ${'calcul'} + ${[{raw_payload: null}, {raw_payload: 'inherited', isInherited: true}]} | ${{format: AttributeFormat.text}} | ${'inherited'} + ${[{raw_payload: '12'}]} | ${{format: AttributeFormat.numeric}} | ${12} + `( + 'Should submit empty value on clear and call onChange with inherited value', + async ({ + values, + attribute, + result + }: { + values: RecordFormElementsValueStandardValue[]; + attribute: RecordFormElementAttribute; + result: any; + }) => { + const antdFormInitialValues = getAntdDisplayedValue(values, attribute); + expect(antdFormInitialValues).toEqual(result); + } + ); +}); + describe('getAntdFormInitialValues', () => { test('Should return empty object on empty elements', async () => { const recordForm = {elements: []}; diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.tsx index b49d2f88e..17b95221f 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/antdUtils.tsx @@ -21,7 +21,7 @@ const getCalculatedValue = values => values.find(value => value.isCalculated); const getInheritedValue = values => values.find(value => value.isInherited); const getUserInputValue = values => - values.find(value => !value.isInherited && !value.isCalculated && value.raw_value !== null); + values.find(value => !value.isInherited && !value.isCalculated && value.raw_payload !== null); const isRecordFormElementsValueLinkValue = ( value: RecordFormElementsValue, @@ -80,6 +80,15 @@ export const getEmptyInitialValue = (attribute: RecordFormElementAttribute) => { return EMPTY_INITIAL_VALUE_STRING; }; +export const getAntdDisplayedValue = ( + values: RecordFormElementsValueStandardValue[], + attribute: RecordFormElementAttribute +) => + formatStandardInitialValue( + getUserInputValue(values) ?? getInheritedValue(values) ?? getCalculatedValue(values) ?? null, + attribute + ); + export const getAntdFormInitialValues = (recordForm: IRecordForm) => recordForm.elements.reduce((acc, {attribute, values}) => { if (!attribute) { diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.test.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.test.tsx index 68f338351..02736ee7b 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.test.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.test.tsx @@ -23,7 +23,7 @@ jest.mock('../../hooks/useRecordEditionContext', () => ({ describe('Container', () => { test('Render children', async () => { - render(); + render(); const children = await screen.findAllByTestId('container-child-element'); expect(children.length).toBe(4); diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.tsx index a6df2109a..3f24d789c 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/Container/Container.tsx @@ -4,15 +4,17 @@ import {Col, FormInstance, Row} from 'antd'; import {useRecordEditionContext} from '../../hooks/useRecordEditionContext'; import {IFormElementProps} from '../../_types'; +import {GetRecordColumnsValuesRecord} from '_ui/_queries/records/getRecordColumnsValues'; function Container({ element, + computedValues, antdForm, readonly, onValueSubmit, onValueDelete, onDeleteMultipleValues -}: IFormElementProps<{}> & {antdForm?: FormInstance}): JSX.Element { +}: IFormElementProps<{}> & {antdForm?: FormInstance; computedValues: GetRecordColumnsValuesRecord}): JSX.Element { const {elements: formElements} = useRecordEditionContext(); const children = formElements[element.id] ?? []; @@ -24,6 +26,7 @@ function Container({ {el.uiElement && ( ({ data: { [mockRecord.id]: { _id: null, - col1: [{value: 'col1 value'}], - col2: [{value: 'col2 value'}] + col1: [{value: 'col1 value', isCalculated: false, isInherited: false}], + col2: [{value: 'col2 value', isCalculated: false, isInherited: false}] } }, refetch: jest.fn() diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardField.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardField.tsx index 8c1dc2780..eec472b72 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardField.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardField.tsx @@ -2,7 +2,7 @@ // This file is released under LGPL V3 // License text available at https://www.gnu.org/licenses/lgpl-3.0.txt import {AnyPrimitive, ErrorTypes, IRequiredFieldsSettings, localizedTranslation} from '@leav/utils'; -import {FunctionComponent, useRef, useState} from 'react'; +import {FunctionComponent, useEffect, useRef, useState} from 'react'; import styled from 'styled-components'; import {ErrorDisplay} from '_ui/components'; import {RecordFormElementsValueStandardValue} from '_ui/hooks/useGetRecordForm/useGetRecordForm'; @@ -17,8 +17,9 @@ import {DeleteAllValuesButton} from './DeleteAllValuesButton'; import {computeCalculatedFlags, computeInheritedFlags} from './calculatedInheritedFlags'; import {useGetPresentationValues} from './useGetPresentationValues'; import {useSharedTranslation} from '_ui/hooks/useSharedTranslation'; -import {getEmptyInitialValue} from '../../antdUtils'; import {ComputeIndicator} from './ComputeIndicator'; +import {getAntdDisplayedValue, getEmptyInitialValue} from '../../antdUtils'; +import {GetRecordColumnsValuesRecord, IRecordColumnValueStandard} from '_ui/_queries/records/getRecordColumnsValues'; const Wrapper = styled.div<{$metadataEdit: boolean}>` margin-bottom: ${props => (props.$metadataEdit ? 0 : '1.5em')}; @@ -65,8 +66,18 @@ const KitAddValueButton = styled(KitButton)` const StandardField: FunctionComponent< IFormElementProps & { antdForm?: FormInstance; + computedValues?: GetRecordColumnsValuesRecord; } -> = ({element, antdForm, readonly, onValueSubmit, onValueDelete, onDeleteMultipleValues, metadataEdit = false}) => { +> = ({ + element, + computedValues, + antdForm, + readonly, + onValueSubmit, + onValueDelete, + onDeleteMultipleValues, + metadataEdit = false +}) => { const {t} = useSharedTranslation(); const {lang: availableLang} = useLang(); @@ -78,6 +89,13 @@ const StandardField: FunctionComponent< const {attribute} = element; + useEffect(() => { + if (computedValues && computedValues[attribute.id]) { + setBackendValues(computedValues[attribute.id]); + antdForm.setFieldValue(attribute.id, getAntdDisplayedValue(computedValues[attribute.id], attribute)); + } + }, [computedValues]); + if (!attribute) { return ; } diff --git a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardFieldValue/ValuesList/DSListSelect.test.tsx b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardFieldValue/ValuesList/DSListSelect.test.tsx index 025591838..00c3c24ff 100644 --- a/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardFieldValue/ValuesList/DSListSelect.test.tsx +++ b/libs/ui/src/components/RecordEdition/EditRecordContent/uiElements/StandardField/StandardFieldValue/ValuesList/DSListSelect.test.tsx @@ -52,7 +52,8 @@ describe('', () => { ...mockAttributeSimple, readonly: false, multiple_values: false, - permissions: {access_attribute: true, edit_value: true} + permissions: {access_attribute: true, edit_value: true}, + compute: false }; const valuesList = { diff --git a/libs/ui/src/components/RecordEdition/EditRecordPage/EditRecordPage.integration.test.tsx b/libs/ui/src/components/RecordEdition/EditRecordPage/EditRecordPage.integration.test.tsx new file mode 100644 index 000000000..817c796f6 --- /dev/null +++ b/libs/ui/src/components/RecordEdition/EditRecordPage/EditRecordPage.integration.test.tsx @@ -0,0 +1,104 @@ +// Copyright LEAV Solutions 2017 until 2023/11/05, Copyright Aristid from 2023/11/06 +// This file is released under LGPL V3 +// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt +import userEvent from '@testing-library/user-event'; +import {screen, render} from '_ui/_tests/testUtils'; +import {mockRecord} from '_ui/__mocks__/common/record'; +import {EditRecordPage} from './EditRecordPage'; +import {mockFormElementInput, mockRecordForm} from '_ui/__mocks__/common/form'; +import {mockAttributeSimple, mockFormAttributeCompute} from '_ui/__mocks__/common/attribute'; + +let user!: ReturnType; +const useGetRecordFormMock = jest.fn(); +jest.mock('_ui/hooks/useGetRecordForm', () => () => useGetRecordFormMock()); + +jest.mock('_ui/hooks/useCanEditRecord', () => ({ + useCanEditRecord: () => ({loading: false, canEdit: true, isReadOnly: false}) +})); + +const useGetRecordValuesQueryMock = jest.fn(); +jest.mock('_ui/hooks/useGetRecordValuesQuery/useGetRecordValuesQuery', () => ({ + useGetRecordValuesQuery: () => useGetRecordValuesQueryMock() +})); + +describe('EditRecordPage', () => { + beforeEach(() => { + user = userEvent.setup(); + useGetRecordFormMock.mockClear(); + useGetRecordValuesQueryMock.mockClear(); + }); + + test('Should render an input component', () => { + useGetRecordFormMock.mockReturnValue({loading: false, recordForm: mockRecordForm, refetch: jest.fn()}); + useGetRecordValuesQueryMock.mockReturnValue({}); + render(); + + expect(screen.getByPlaceholderText('record_edition.placeholder.enter_a_text')); + }); + + test('Should update calculated values on update of dependant field', async () => { + const simpleElementInput = { + ...mockFormElementInput, + settings: [{key: 'label', value: {fr: 'simple attribute'}}] + }; + const calculatedValues = (value: string) => [ + { + isCalculated: false, + payload: null, + raw_payload: null, + created_at: 123456789, + modified_at: 123456789, + id_value: null, + attribute: mockAttributeSimple, + metadata: null, + version: null + }, + { + isCalculated: true, + payload: value, + raw_payload: value, + created_at: 123456789, + modified_at: 123456789, + id_value: null, + attribute: mockAttributeSimple, + metadata: null, + version: null + } + ]; + const calculatedElementInput = { + ...mockFormElementInput, + id: 'input_calculated_element', + attribute: mockFormAttributeCompute, + values: calculatedValues('calculated'), + settings: [{key: 'label', value: {fr: 'calculated attribute'}}] + }; + + useGetRecordFormMock.mockReturnValue({ + loading: false, + recordForm: {...mockRecordForm, elements: [simpleElementInput, calculatedElementInput]}, + refetch: jest.fn() + }); + + const refetchMock = jest.fn(); + useGetRecordValuesQueryMock.mockReturnValue({ + loading: false, + data: {[mockRecord.id]: {[mockFormAttributeCompute.id]: calculatedValues('updated calculated')}}, + refetch: refetchMock + }); + + render(); + + const calculatedInput = screen.getByRole('textbox', {name: 'calculated attribute'}); + const simpleInput = screen.getByRole('textbox', {name: 'simple attribute'}); + + expect(screen.getAllByRole('textbox')).toHaveLength(2); + expect(calculatedInput).toBeVisible(); + + await user.click(simpleInput); + await userEvent.type(simpleInput, 'some value'); + await userEvent.tab(); + + expect(refetchMock).toHaveBeenCalledTimes(1); + expect(calculatedInput).toHaveValue('updated calculated'); + }); +});