diff --git a/core/app/core/src/lib/core.ts b/core/app/core/src/lib/core.ts index 1945b6e481..351140c602 100644 --- a/core/app/core/src/lib/core.ts +++ b/core/app/core/src/lib/core.ts @@ -361,6 +361,8 @@ export * from './fields/enum/templates/edit/enum.component'; export * from './fields/enum/templates/edit/enum.module'; export * from './fields/field-logic/field-logic.action'; export * from './fields/field-logic/field-logic.manager'; +export * from './fields/field-logic/actionable-field-logic/actionable-field-logic.action'; +export * from './fields/field-logic/conditional-options/conditional-options.action'; export * from './fields/field-logic/currency-conversion/update-base-currency.action'; export * from './fields/field-logic/currency-conversion/update-currency.action'; export * from './fields/field-logic/display-type/display-type.action'; diff --git a/core/app/core/src/lib/fields/field-logic/actionable-field-logic/actionable-field-logic.action.ts b/core/app/core/src/lib/fields/field-logic/actionable-field-logic/actionable-field-logic.action.ts new file mode 100644 index 0000000000..09c6f12987 --- /dev/null +++ b/core/app/core/src/lib/fields/field-logic/actionable-field-logic/actionable-field-logic.action.ts @@ -0,0 +1,84 @@ +/** + * SuiteCRM is a customer relationship management program developed by SalesAgility Ltd. + * Copyright (C) 2023 SalesAgility Ltd. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE + * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * In accordance with Section 7(b) of the GNU Affero General Public License + * version 3, these Appropriate Legal Notices must retain the display of the + * "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably + * feasible for technical reasons, the Appropriate Legal Notices must display + * the words "Supercharged by SuiteCRM". + */ + +import {isArray, isString} from 'lodash-es'; +import { + Action, + ALL_VIEW_MODES, + Field, + Record, +} from 'common'; +import { FieldLogicActionData, FieldLogicActionHandler } from '../field-logic.action'; +import {ActiveLogicChecker} from '../../../services/logic/active-logic-checker.service'; + +export type FieldValueTypes = string | string[] | object; + +export abstract class ActionableFieldLogicActionHandler extends FieldLogicActionHandler { + modes = ALL_VIEW_MODES; + + protected constructor( + protected activeLogicChecker: ActiveLogicChecker, + ) { + super(); + } + + run(data: FieldLogicActionData, action: Action): void { + const record = data.record; + const field = data.field; + if (!record || !field) { + return; + } + const params = action.params ?? {}; + + const logicIsActive = this.activeLogicChecker.run(record, action); + + this.executeLogic(logicIsActive, params, field, record); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + shouldDisplay(data: FieldLogicActionData): boolean { + return true; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + executeLogic(logicIsActive: boolean, params: { [p: string]: any }, field: Field, record: Record): void { + } + + protected updateValue(value: FieldValueTypes, field: Field, record: Record): void { + if (isString(value)) { + field.value = value; + } else if (isArray(value)) { + field.valueList = value; + } else { + field.valueObject = value; + } + + field.formControl.setValue(value); + + // re-validate the parent form-control after value update + record.formGroup.updateValueAndValidity({onlySelf: true, emitEvent: true}); + } +} diff --git a/core/app/core/src/lib/fields/field-logic/conditional-options/conditional-options.action.ts b/core/app/core/src/lib/fields/field-logic/conditional-options/conditional-options.action.ts new file mode 100644 index 0000000000..d1bfe7f9e8 --- /dev/null +++ b/core/app/core/src/lib/fields/field-logic/conditional-options/conditional-options.action.ts @@ -0,0 +1,71 @@ +/** + * SuiteCRM is a customer relationship management program developed by SalesAgility Ltd. + * Copyright (C) 2023 SalesAgility Ltd. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License version 3 as published by the + * Free Software Foundation with the addition of the following permission added + * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK + * IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE + * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * In accordance with Section 7(b) of the GNU Affero General Public License + * version 3, these Appropriate Legal Notices must retain the display of the + * "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably + * feasible for technical reasons, the Appropriate Legal Notices must display + * the words "Supercharged by SuiteCRM". + */ + +import {Injectable} from '@angular/core'; +import {Action, Field, Option, Record, ViewMode} from 'common'; +import {ActionableFieldLogicActionHandler} from '../actionable-field-logic/actionable-field-logic.action'; +import {ActiveLogicChecker} from '../../../services/logic/active-logic-checker.service'; + +interface ConditionalOptionsParams { + conditionalOptions?: (Option & Action)[]; +} + +@Injectable({ + providedIn: 'root' +}) +export class ConditionalOptionsAction extends ActionableFieldLogicActionHandler { + + key = 'conditional-options'; + modes = ['detail', 'edit', 'create'] as ViewMode[]; + + constructor( + protected activeLogicChecker: ActiveLogicChecker + ) { + super(activeLogicChecker); + } + + executeLogic(logicIsActive: boolean, params: ConditionalOptionsParams, field: Field, record: Record) { + const conditionalOptions = params.conditionalOptions ?? []; + const currentFieldOptions: { [key: string]: Option } = {}; + + conditionalOptions.forEach((conditionalOption) => { + const isActive = this.activeLogicChecker.run(record, conditionalOption); + + if (!isActive) { + return; + } + + currentFieldOptions[conditionalOption.value] = { + value: conditionalOption.value ?? '', + label: conditionalOption.label ?? '', + labelKey: conditionalOption.labelKey ?? '' + }; + }); + + field.metadata.conditionalOptions = currentFieldOptions; + field.options = [...(field.options ?? [])]; + } +} diff --git a/core/app/core/src/lib/fields/field-logic/field-logic.manager.ts b/core/app/core/src/lib/fields/field-logic/field-logic.manager.ts index c355d444ba..7df742b893 100644 --- a/core/app/core/src/lib/fields/field-logic/field-logic.manager.ts +++ b/core/app/core/src/lib/fields/field-logic/field-logic.manager.ts @@ -37,6 +37,7 @@ import {UpdateFlexRelateModuleAction} from './update-flex-relate-module/update-f import {UpdateValueAction} from './update-value/update-value.action'; import {UpdateValueBackendAction} from './update-value-backend/update-value-backend.action'; import {DisplayTypeBackendAction} from './display-type-backend/display-type-backend.action'; +import {ConditionalOptionsAction} from './conditional-options/conditional-options.action'; @Injectable({ providedIn: 'root' @@ -62,6 +63,7 @@ export class FieldLogicManager extends BaseActionManager { updateFlexRelateModule: UpdateFlexRelateModuleAction, updateValueBackend: UpdateValueBackendAction, dislayTypeBackend: DisplayTypeBackendAction, + conditionalOptionsAction: ConditionalOptionsAction, ) { super(); displayType.modes.forEach(mode => this.actions[mode][displayType.key] = displayType); @@ -73,6 +75,7 @@ export class FieldLogicManager extends BaseActionManager { updateValue.modes.forEach(mode => this.actions[mode][updateValue.key] = updateValue); updateValueBackend.modes.forEach(mode => this.actions[mode][updateValueBackend.key] = updateValueBackend); dislayTypeBackend.modes.forEach(mode => this.actions[mode][dislayTypeBackend.key] = dislayTypeBackend); + conditionalOptionsAction.modes.forEach(mode => this.actions[mode][conditionalOptionsAction.key] = conditionalOptionsAction); } /**