All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.js.components.ObjectAction.tabs.ActionBuilder.tsx Maven / Gradle / Ivy

The newest version!
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

import ClayAlert from '@clayui/alert';
import {Option, Text} from '@clayui/core';
import {
	Card,
	SidebarCategory,
	SingleSelect,
	invalidateRequired,
} from '@liferay/object-js-components-web';
import {InputLocalized} from 'frontend-js-components-web';
import React, {useEffect, useMemo, useState} from 'react';

import {defaultLanguageId} from '../../../utils/constants';
import {DisabledGroovyScriptAlert} from '../../DisabledGroovyScriptAlert';
import {ActionError} from '../ObjectActionContainer';
import {ActionContainer} from './ActionContainer/ActionContainer';
import {ConditionContainer} from './ConditionContainer';

import './ActionBuilder.scss';

interface ActionBuilderProps {
	disableGroovyAction: boolean;
	errors: ActionError;
	isApproved: boolean;
	objectActionCodeEditorElements: SidebarCategory[];
	objectActionExecutors: ObjectActionTriggerExecutorItem[];
	objectActionTriggers: ObjectActionTriggerExecutorItem[];
	objectDefinitionExternalReferenceCode: string;
	objectDefinitionId: number;
	objectDefinitionsRelationshipsURL: string;
	objectFields: ObjectField[];
	scriptManagementConfigurationPortletURL: string;
	setValues: (values: Partial) => void;
	systemObject: boolean;
	validateExpressionURL: string;
	values: Partial;
}
export interface WarningStates {
	mandatoryRelationships: boolean;
	requiredFields: boolean;
}

const triggerKeys = [
	'liferay/commerce_order_status',
	'liferay/commerce_payment_status',
	'liferay/commerce_shipment_status',
	'onAfterAdd',
	'onAfterAttachmentDownload',
	'onAfterDelete',
	'onAfterRootUpdate',
	'onAfterUpdate',
];

export default function ActionBuilder({
	disableGroovyAction,
	errors,
	isApproved,
	objectActionCodeEditorElements,
	objectActionExecutors,
	objectActionTriggers,
	objectDefinitionExternalReferenceCode,
	objectDefinitionId,
	objectDefinitionsRelationshipsURL,
	objectFields,
	scriptManagementConfigurationPortletURL,
	setValues,
	systemObject,
	validateExpressionURL,
	values,
}: ActionBuilderProps) {
	const [newObjectActionExecutors, setNewObjectActionExecutors] = useState<
		ObjectActionTriggerExecutorItem[]
	>(objectActionExecutors);

	const [infoAlert, setInfoAlert] = useState(true);

	const [warningAlerts, setWarningAlerts] = useState({
		mandatoryRelationships: false,
		requiredFields: false,
	});

	const [currentObjectDefinitionFields, setCurrentObjectDefinitionFields] =
		useState([]);

	const [errorAlert, setErrorAlert] = useState(false);

	const objectFieldsMap = useMemo(() => {
		const fields = new Map();

		currentObjectDefinitionFields.forEach((field) => {
			fields.set(field.name, field);
		});

		return fields;
	}, [currentObjectDefinitionFields]);

	const showConditionContainer = values.objectActionTriggerKey
		? triggerKeys.includes(values.objectActionTriggerKey)
		: true;

	useEffect(() => {
		const predefinedValues = values.parameters?.predefinedValues;

		const requiredFields = predefinedValues
			? predefinedValues.filter(
					({name}) => objectFieldsMap.get(name)?.required
				)
			: [];

		const hasEmptyValues = requiredFields?.some((item) =>
			invalidateRequired(item.value)
		);

		setWarningAlerts((previousWarnings) => ({
			...previousWarnings,
			requiredFields: hasEmptyValues,
		}));
	}, [
		values.parameters?.predefinedValues,
		objectFieldsMap,
		setWarningAlerts,
	]);

	const closeWarningAlert = (warning: string) => {
		setWarningAlerts((previousWarnings) => ({
			...previousWarnings,
			[warning]: false,
		}));
	};

	const hasLocalizedField = useMemo(() => {
		return objectFields.some((field) => field.localized);
	}, [objectFields]);

	useEffect(() => {
		const predefinedValues = values.parameters?.predefinedValues;

		const requiredFields = predefinedValues
			? predefinedValues.filter(
					({name}) => objectFieldsMap.get(name)?.required
				)
			: [];

		const hasEmptyValues = requiredFields?.some((item) =>
			invalidateRequired(item.value)
		);

		setWarningAlerts((previousWarnings) => ({
			...previousWarnings,
			requiredFields: hasEmptyValues,
		}));
	}, [
		values.parameters?.predefinedValues,
		objectFieldsMap,
		setWarningAlerts,
	]);

	useEffect(() => {
		if (values.objectActionTriggerKey === 'onAfterDelete') {
			newObjectActionExecutors.map((action) => {
				if (action.value === 'update-object-entry') {
					action.disabled = true;
					action.popover = {
						body:
							Liferay.Language.get(
								'it-is-not-possible-to-create-an-update-action-with-an-on-after-delete-trigger'
							) +
							' ' +
							Liferay.Language.get(
								'please-change-the-action-trigger'
							),
						header: Liferay.Language.get('action-not-allowed'),
					};
				}
			});

			if (values.objectActionExecutorKey === 'update-object-entry') {
				setErrorAlert(true);
			}

			setNewObjectActionExecutors(newObjectActionExecutors);
		}
		else if (
			values.objectActionTriggerKey === 'onAfterAdd' ||
			values.objectActionTriggerKey === 'onAfterUpdate'
		) {
			newObjectActionExecutors.map((action) => {
				if (action.value === 'update-object-entry') {
					delete action.disabled;
					delete action.popover;
				}
			});

			if (values.objectActionExecutorKey === 'update-object-entry') {
				setErrorAlert(false);
			}

			setNewObjectActionExecutors(newObjectActionExecutors);
		}

		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [values.objectActionTriggerKey]);

	return (
		<>
			{disableGroovyAction && (
				
			)}

			{infoAlert && (
				 setInfoAlert(false)}
					title={`${Liferay.Language.get('info')}:`}
				>
					{Liferay.Language.get(
						'create-conditions-and-predefined-values-using-expressions'
					) + ' '}

					
						{Liferay.Language.get('click-here-for-documentation')}
					
				
			)}

			{Liferay.FeatureFlags['LPD-32050'] && hasLocalizedField && (
				 setInfoAlert(false)}
					title={`${Liferay.Language.get('info')}:`}
				>
					{`${Liferay.Language.get(
						'this-object-includes-translatable-fields'
					)} ${Liferay.Language.get(
						'actions-always-use-the-object-entrys-default-language'
					)}`}
				
			)}

			{errorAlert && (
				 setErrorAlert(false)}
					title={`${Liferay.Language.get('error')}:`}
				>
					{Liferay.Language.get(
						'it-is-not-possible-to-create-an-update-action-with-an-on-after-delete-trigger'
					)}
				
			)}

			
				
					
							setValues({
								conditionExpression: undefined,
								objectActionTriggerKey: value as string,
							})
						}
						placeholder={Liferay.Language.get('choose-a-trigger')}
						selectedKey={values.objectActionTriggerKey}
					>
						{(item) => (
							
						)}
					
				
			

			{showConditionContainer && (
				
			)}

			{warningAlerts.requiredFields && (
				 closeWarningAlert('requiredFields')}
					title={`${Liferay.Language.get('warning')}:`}
				>
					{Liferay.Language.get(
						'required-fields-must-have-predefined-values'
					)}
				
			)}

			{warningAlerts.mandatoryRelationships && (
				 closeWarningAlert('mandatoryRelationships')}
					title={`${Liferay.Language.get('warning')}:`}
				>
					{Liferay.Language.get(
						'the-selected-object-definition-has-mandatory-relationship-fields'
					)}
				
			)}
			

			{values.objectActionTriggerKey === 'standalone' && (
				
					
							setValues({
								errorMessage: value,
							})
						}
						required
						translations={
							values.errorMessage ?? {[defaultLanguageId]: ''}
						}
					/>
				
			)}
		
	);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy