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

META-INF.resources.js.components.ObjectValidation.UniqueCompositeKey.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 {
	API,
	BuilderScreen,
	Card,
	MultiSelectItem,
	MultiSelectItemChild,
	MultipleSelect,
	TBuilderScreenItem,
	stringUtils,
} from '@liferay/object-js-components-web';
import {createResourceURL, sub} from 'frontend-js-web';
import React, {useEffect, useMemo, useState} from 'react';

import {Alert} from '../ModalSelectObjectFields';
import {ErrorMessage} from './ErrorMessage';
import {ObjectValidationErrors} from './useObjectValidationForm';

import './UniqueCompositeKey.scss';

interface isMatchingObjectFieldObjectValidationRuleSettingProps {
	objectField: ObjectField;
	objectValidationRuleSetting: ObjectValidationRuleSetting;
	objectValidationRuleSettingNameMatches:
		| 'compositeKeyObjectFieldExternalReferenceCode'
		| 'outputObjectFieldExternalReferenceCode';
}

interface ModalSelectObjectFieldItem extends ObjectField {
	checked: boolean;
	disableCheckbox: boolean;
}
export interface UniqueCompositeKeyProps {
	baseResourceURL: string;
	creationLanguageId: Liferay.Language.Locale;
	customObjectFields: ObjectField[];
	disabled: boolean;
	errors: ObjectValidationErrors;
	objectDefinitionExternalReferenceCode: string;
	setShowUniqueCompositeKeyAlert: (value: boolean) => void;
	setValues: (values: Partial) => void;
	showUniqueCompositeKeyAlert: boolean;
	values: Partial;
}

const isMatchingObjectFieldObjectValidationRuleSetting = ({
	objectField,
	objectValidationRuleSetting,
	objectValidationRuleSettingNameMatches,
}: isMatchingObjectFieldObjectValidationRuleSettingProps) => {
	return (
		objectField.externalReferenceCode ===
			objectValidationRuleSetting.value &&
		objectValidationRuleSetting.name ===
			objectValidationRuleSettingNameMatches
	);
};

export function UniqueCompositeKey({
	baseResourceURL,
	creationLanguageId,
	customObjectFields,
	disabled,
	errors,
	objectDefinitionExternalReferenceCode,
	setShowUniqueCompositeKeyAlert,
	setValues,
	showUniqueCompositeKeyAlert,
	values,
}: UniqueCompositeKeyProps) {
	const [alerts, setAlerts] = useState([]);
	const [builderScreenItems, setBuilderScreenItems] = useState<
		TBuilderScreenItem[]
	>([]);
	const [modalSelectObjectFieldsItems, setModalSelectObjectFieldsItems] =
		useState([]);
	const [multipleSelectOptions, setMultipleSelectOptions] = useState<
		MultiSelectItem[]
	>([]);
	const [objectDefinition, setObjectDefinition] =
		useState();

	const allowedObjectFieldBusinessTypes = [
		'AutoIncrement',
		'Integer',
		'Picklist',
		'Relationship',
		'Text',
	] as ObjectFieldBusinessTypeName[];

	const filteredCustomObjectFields = customObjectFields.filter(
		(customObjectField) =>
			allowedObjectFieldBusinessTypes.includes(
				customObjectField.businessType
			)
	);

	const handleAddObjectFields = () => {
		const parentWindow = Liferay.Util.getOpener();

		if (objectDefinition) {
			parentWindow.Liferay.fire('openModalSelectObjectFields', {
				alerts,
				emptyState: {
					message: Liferay.Language.get(
						'there-are-no-valid-fields-in-this-definition-that-can-be-added-to-the-unique-composite-key'
					),
					title: Liferay.Language.get(
						'there-are-no-valid-fields-created-yet'
					),
				},
				getName: ({label, name}: ObjectField) =>
					stringUtils.getLocalizableLabel({
						fallbackLabel: name,
						fallbackLanguageId: creationLanguageId,
						labels: label,
					}),
				header: Liferay.Language.get(
					'add-fields-to-unique-composite-key'
				),
				items: modalSelectObjectFieldsItems,
				onAfterClose: setAlerts(([firstItem]) => {
					return firstItem ? [firstItem] : [];
				}),
				onSave: async (selectedObjectFields: ObjectField[]) => {
					if (selectedObjectFields.length) {
						const newSelectedObjectFields =
							selectedObjectFields?.filter(
								(selectedObjectField) =>
									!values.objectValidationRuleSettings?.some(
										(objectValidationRuleSetting) =>
											selectedObjectField.externalReferenceCode ===
												objectValidationRuleSetting.value &&
											objectValidationRuleSetting.name ===
												'compositeKeyObjectFieldExternalReferenceCode'
									)
							);

						if (
							newSelectedObjectFields.length &&
							objectDefinition.status.label === 'approved'
						) {
							const newSelectedObjectFieldsIds =
								newSelectedObjectFields?.map(({id}) => id);

							const addObjectFieldKeyCandidatesUrl =
								createResourceURL(baseResourceURL, {
									objectDefinitionId: (
										objectDefinition as ObjectDefinition
									).id,
									objectFieldsIds:
										newSelectedObjectFieldsIds.length > 1
											? newSelectedObjectFieldsIds.join(
													', '
												)
											: newSelectedObjectFieldsIds[0],
									p_p_resource_id:
										'/object_definitions/add_object_field_composite_key_candidates',
								}).href;

							const addObjectFieldKeyCandidatesResponse =
								await API.fetchJSON<{
									errorLabel: string;
									status: string;
								}>(addObjectFieldKeyCandidatesUrl);

							if (
								addObjectFieldKeyCandidatesResponse.status ===
								'error'
							) {
								setAlerts(([previousAlerts]) => [
									previousAlerts,
									{
										content:
											addObjectFieldKeyCandidatesResponse.errorLabel,
										otherProps: {
											displayType: 'danger',
											title: Liferay.Language.get(
												'error'
											),
											variant: 'stripe',
										},
									},
								]);

								return;
							}
						}
					}

					const objectValidationRuleSettings: ObjectValidationRuleSetting[] =
						[];

					selectedObjectFields.map((selectedObjectField) =>
						values.outputType === 'partialValidation'
							? objectValidationRuleSettings?.push(
									{
										name: 'compositeKeyObjectFieldExternalReferenceCode',
										value: selectedObjectField.externalReferenceCode,
									},
									{
										name: 'outputObjectFieldExternalReferenceCode',
										value: selectedObjectField.externalReferenceCode,
									}
								)
							: objectValidationRuleSettings?.push({
									name: 'compositeKeyObjectFieldExternalReferenceCode',
									value: selectedObjectField.externalReferenceCode,
								})
					);

					setValues({
						objectValidationRuleSettings,
					});
				},
				selected: modalSelectObjectFieldsItems.filter(
					(modalSelectObjectFieldsItem) =>
						modalSelectObjectFieldsItem.checked
				),
				showModal: true,
				title: Liferay.Language.get('select-the-fields'),
			});
		}
	};

	const persistedObjectValidation = useMemo(() => {
		return values;

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

	useEffect(() => {
		if (alerts.length >= 2) {
			handleAddObjectFields();
		}

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

	useEffect(() => {
		const makeFetch = async () => {
			const objectDefinitionResponse =
				await API.getObjectDefinitionByExternalReferenceCode(
					objectDefinitionExternalReferenceCode
				);

			setObjectDefinition(objectDefinitionResponse);
			if (objectDefinitionResponse.status.label === 'approved') {
				setAlerts([
					{
						content: sub(
							Liferay.Language.get(
								'x-is-already-published.-as-a-result,-you-can-only-add-fields-to-unique-composite-keys-with-no-data'
							),
							objectDefinitionResponse.name!
						),
						otherProps: {
							displayType: 'info',
							title: Liferay.Language.get('info'),
							variant: 'stripe',
						},
					},
				]);
			}
		};

		makeFetch();

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

	useEffect(() => {
		if (!values.objectValidationRuleSettings) {
			return;
		}

		const newBuilderScreenItems: TBuilderScreenItem[] = [];
		const newModalSelectObjectFieldsItems: ModalSelectObjectFieldItem[] =
			[];
		const newMultipleSelectOptionsChildren: MultiSelectItemChild[] = [];

		values.objectValidationRuleSettings.forEach(
			(objectValidationRuleSetting) => {
				const filteredObjectFieldObjectValidationRuleSetting =
					filteredCustomObjectFields.find(
						(filteredCustomObjectField) =>
							isMatchingObjectFieldObjectValidationRuleSetting({
								objectField: filteredCustomObjectField,
								objectValidationRuleSetting,
								objectValidationRuleSettingNameMatches:
									'compositeKeyObjectFieldExternalReferenceCode',
							})
					);

				if (filteredObjectFieldObjectValidationRuleSetting) {
					const label = stringUtils.getLocalizableLabel({
						fallbackLabel:
							filteredObjectFieldObjectValidationRuleSetting.name,
						fallbackLanguageId: creationLanguageId,
						labels: filteredObjectFieldObjectValidationRuleSetting.label,
					});

					newBuilderScreenItems.push({
						externalReferenceCode:
							filteredObjectFieldObjectValidationRuleSetting.externalReferenceCode,
						fieldLabel: label,
						label: filteredObjectFieldObjectValidationRuleSetting.label,
						objectFieldBusinessType:
							filteredObjectFieldObjectValidationRuleSetting.businessType,
						objectFieldName:
							filteredObjectFieldObjectValidationRuleSetting.name,
					});

					newMultipleSelectOptionsChildren.push({
						checked: !!values.objectValidationRuleSettings?.find(
							(objectValidationRuleSetting) =>
								isMatchingObjectFieldObjectValidationRuleSetting(
									{
										objectField:
											filteredObjectFieldObjectValidationRuleSetting,
										objectValidationRuleSetting,
										objectValidationRuleSettingNameMatches:
											'outputObjectFieldExternalReferenceCode',
									}
								)
						),
						label,
						value: filteredObjectFieldObjectValidationRuleSetting.externalReferenceCode,
					});
				}
			}
		);

		filteredCustomObjectFields.forEach((filteredCustomObjectField) =>
			newModalSelectObjectFieldsItems.push({
				...filteredCustomObjectField,
				checked: !!values.objectValidationRuleSettings?.find(
					(objectValidationRuleSetting) =>
						isMatchingObjectFieldObjectValidationRuleSetting({
							objectField: filteredCustomObjectField,
							objectValidationRuleSetting,
							objectValidationRuleSettingNameMatches:
								'compositeKeyObjectFieldExternalReferenceCode',
						})
				),
				disableCheckbox:
					objectDefinition?.status.label === 'approved' &&
					!!persistedObjectValidation.objectValidationRuleSettings?.find(
						(objectValidationRuleSetting) =>
							isMatchingObjectFieldObjectValidationRuleSetting({
								objectField: filteredCustomObjectField,
								objectValidationRuleSetting,
								objectValidationRuleSettingNameMatches:
									'compositeKeyObjectFieldExternalReferenceCode',
							})
					),
			})
		);

		setBuilderScreenItems(newBuilderScreenItems);
		setModalSelectObjectFieldsItems(newModalSelectObjectFieldsItems);

		setMultipleSelectOptions([
			{
				children: newMultipleSelectOptionsChildren,
				label: '',
				value: 'objectFields',
			},
		]);

		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [objectDefinition?.status, values.objectValidationRuleSettings]);

	return (
		<>
			
				 {
						const cannotDeleteObjectField = builderScreenItems.some(
							(builderScreenItem) =>
								builderScreenItem.objectFieldName ===
									objectFieldName &&
								(objectDefinition as ObjectDefinition).status
									.label === 'approved' &&
								(
									persistedObjectValidation.objectValidationRuleSettings as ObjectValidationRuleSetting[]
								).some(
									(objectValidationRuleSetting) =>
										objectValidationRuleSetting.value ===
										builderScreenItem.externalReferenceCode
								)
						);

						if (cannotDeleteObjectField) {
							const parentWindow = Liferay.Util.getOpener();

							parentWindow.Liferay.fire(
								'openModalDeletionNotAllowed',
								{
									contentLiferayFire: (
										
											{Liferay.Language.get(
												'fields-cannot-be-deleted-from-unique-composite-keys-after-the-definition-is-published'
											)}
										
									),
								}
							);
						}
						else {
							let removedBuilderScreenItem: TBuilderScreenItem[];

							builderScreenItems.forEach(
								(builderScreenItem, index) => {
									if (
										builderScreenItem.objectFieldName ===
										objectFieldName
									) {
										removedBuilderScreenItem =
											builderScreenItems.splice(index, 1);
									}
								}
							);
							setValues({
								objectValidationRuleSettings:
									values.objectValidationRuleSettings?.filter(
										(objectValidationRuleSetting) =>
											objectValidationRuleSetting.value !==
											removedBuilderScreenItem[0]
												.externalReferenceCode
									),
							});
						}
					}}
					openModal={handleAddObjectFields}
					secondColumnHeader={Liferay.Language.get('type')}
				/>
			

			
				 {
						const objectValidationRuleSettings =
							values.objectValidationRuleSettings?.filter(
								(objectValidationRuleSetting) =>
									objectValidationRuleSetting.name !==
									'outputObjectFieldExternalReferenceCode'
							);

						newOutputObjectFieldOption.children.forEach(
							(newOutputObjectFieldOptionChild) => {
								if (newOutputObjectFieldOptionChild.checked) {
									objectValidationRuleSettings?.push({
										name: 'outputObjectFieldExternalReferenceCode',
										value: newOutputObjectFieldOptionChild.value,
									});
								}
							}
						);

						setValues({objectValidationRuleSettings});
						setMultipleSelectOptions([newOutputObjectFieldOption]);
					}}
				/>
			
		
	);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy