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

META-INF.resources.js.components.ObjectField.ObjectFieldFormBase.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 ClayButton, {ClayButtonWithIcon} from '@clayui/button';
import {Option, Text} from '@clayui/core';
import ClayForm from '@clayui/form';
import {
	API,
	FormError,
	Input,
	SingleSelect,
	Toggle,
} from '@liferay/object-js-components-web';
import {createResourceURL} from 'frontend-js-web';
import React, {
	ChangeEventHandler,
	ReactNode,
	useEffect,
	useMemo,
	useState,
} from 'react';

import {defaultLanguageId} from '../../utils/constants';
import {
	getDefaultValueFieldSettings,
	getUpdatedDefaultValueType,
} from '../../utils/defaultValues';
import {removeFieldSettings} from '../../utils/fieldSettings';
import {toCamelCase} from '../../utils/string';
import {AggregationFormBase} from './AggregationFormBase';
import {AttachmentFormBase} from './AttachmentFormBase';
import {AutoIncrementFormBase} from './AutoIncrementFormBase';
import {TimeStorage} from './TimeStorage';
import {UniqueValues} from './UniqueValues';
import {FORMULA_OUTPUT_OPTIONS, FormulaOutput} from './formulaFieldUtil';

import './ObjectFieldFormBase.scss';

import ClayIcon from '@clayui/icon';
import ClayLoadingIndicator from '@clayui/loading-indicator';
import classNames from 'classnames';

interface ObjectFieldFormBaseProps {
	baseResourceURL: string;
	children?: ReactNode;
	className?: string;
	creationLanguageId2?: Liferay.Language.Locale;
	dbObjectFieldRequired?: boolean;
	disabled?: boolean;
	editingObjectField?: boolean;
	errors: ObjectFieldErrors;
	handleChange: ChangeEventHandler;
	modelBuilder?: boolean;
	objectDefinition?: ObjectDefinition;
	objectField: Partial;
	objectFieldBusinessTypesInfo: ObjectFieldBusinessType[];
	objectRelationshipId?: number;
	onAggregationFilterChange?: (aggregationFilterArray: []) => void;
	onObjectRelationshipChange?: (
		objectDefinitionExternalReferenceCode2: string
	) => void;
	onSubmit?: (values?: Partial) => void;
	setDbObjectFieldRequired?: (value: boolean) => void;
	setValues: (values: Partial) => void;
}

type TObjectRelationship = {
	deletionType: string;
	edge: boolean;
	id: number;
	label: LocalizedValue;
	name: string;
	objectDefinitionExternalReferenceCode2: number;
};

export type ObjectFieldErrors = FormError<
	ObjectField & {[key in ObjectFieldSettingName]: unknown}
>;

const fieldSettingsMap = new Map([
	[
		'Aggregation',
		[
			{
				name: 'filters',
				objectFieldId: 0,
				value: Array(0),
			},
		],
	],
	[
		'Attachment',
		[
			{
				name: 'acceptedFileExtensions',
				value: 'jpeg, jpg, pdf, png',
			},
			{
				name: 'maximumFileSize',
				value: 0,
			},
		],
	],
	[
		'LongText' || 'Text',
		[
			{
				name: 'showCounter',
				value: false,
			},
		],
	],
	[
		'DateTime',
		[
			{
				name: 'timeStorage',
				value: 'convertToUTC',
			},
		],
	],
]);

async function updateListTypeDefinitions(
	setListTypeDefinitions: (value: ListTypeDefinition[]) => void
) {
	const listTypeDefinitions = await API.getListTypeDefinitions();

	setListTypeDefinitions(listTypeDefinitions);
}

async function getObjectFieldSettingsByBusinessType(
	objectRelationshipId: number,
	setListTypeDefinitions: (value: ListTypeDefinition[]) => void,
	setOneToManyObjectRelationship: (value: TObjectRelationship) => void,
	setReloadPicklistSingleSelect: (value: boolean) => void,
	setSelectedOutputValue: (value: string) => void,
	values: Partial
) {
	const {businessType, objectFieldSettings} = values;

	if (businessType === 'Picklist' || businessType === 'MultiselectPicklist') {
		setReloadPicklistSingleSelect(true);
		updateListTypeDefinitions(setListTypeDefinitions);
	}

	if (businessType === 'Formula') {
		const output = objectFieldSettings?.find(
			(fieldSetting) => fieldSetting.name === 'output'
		);

		if (output) {
			setSelectedOutputValue(
				FORMULA_OUTPUT_OPTIONS.find(
					(formulaOption) => formulaOption.value === output?.value
				)?.value as string
			);
		}
	}

	if (businessType === 'Relationship' && objectRelationshipId !== 0) {
		const relationshipData =
			await API.getObjectRelationship(
				objectRelationshipId!
			);

		if (relationshipData.id) {
			setOneToManyObjectRelationship(relationshipData);
		}
	}
}

export default function ObjectFieldFormBase({
	baseResourceURL,
	children,
	className,
	creationLanguageId2,
	dbObjectFieldRequired,
	disabled,
	editingObjectField = false,
	errors,
	handleChange,
	modelBuilder = false,
	objectDefinition,
	objectField: values,
	objectFieldBusinessTypesInfo,
	objectRelationshipId,
	onAggregationFilterChange,
	onObjectRelationshipChange,
	onSubmit,
	setDbObjectFieldRequired,
	setValues,
}: ObjectFieldFormBaseProps) {
	const [listTypeDefinitions, setListTypeDefinitions] = useState<
		Partial[]
	>([]);

	const [listTypeDefinitionsURL, setListTypeDefinitionsURL] =
		useState('');

	const [oneToManyObjectRelationship, setOneToManyObjectRelationship] =
		useState();
	const [reloadPicklistSingleSelect, setReloadPicklistSingleSelect] =
		useState(false);
	const [selectedOutputValue, setSelectedOutputValue] = useState();
	const validListTypeDefinitionId =
		values.listTypeDefinitionId !== undefined &&
		values.listTypeDefinitionId !== 0;

	const listTypeDefinitionsItems = useMemo(() => {
		return listTypeDefinitions.map(({externalReferenceCode, name}) => ({
			label: name,
			value: externalReferenceCode,
		})) as LabelValueObject[];
	}, [listTypeDefinitions]);

	const selectedListTypeDefinitionExternalReferenceCode = useMemo(() => {
		return listTypeDefinitions.find(
			({externalReferenceCode}) =>
				values.listTypeDefinitionExternalReferenceCode ===
				externalReferenceCode
		)?.externalReferenceCode;
	}, [listTypeDefinitions, values.listTypeDefinitionExternalReferenceCode]);

	const handleTypeChange = async (selectedBusinessType: string) => {
		const selectedObjectFieldBusinessTypeInfo =
			objectFieldBusinessTypesInfo.find(
				(objectFieldBusinessTypeInfo) =>
					objectFieldBusinessTypeInfo.businessType ===
					selectedBusinessType
			);

		const objectFieldSettings: ObjectFieldSetting[] =
			fieldSettingsMap.get(selectedBusinessType) || [];

		const indexed =
			selectedBusinessType !== 'Aggregation' &&
			selectedBusinessType !== 'Formula' &&
			selectedBusinessType !== 'Encrypted';

		const isSearchableByText =
			selectedBusinessType === 'Attachment' ||
			selectedObjectFieldBusinessTypeInfo?.dbType === 'Clob' ||
			selectedObjectFieldBusinessTypeInfo?.dbType === 'String';

		const indexedAsKeyword = isSearchableByText && values.indexedAsKeyword;

		const indexedLanguageId =
			isSearchableByText && !values.indexedAsKeyword
				? values.indexedLanguageId ?? defaultLanguageId
				: '';

		setSelectedOutputValue(undefined);

		setValues({
			DBType: selectedObjectFieldBusinessTypeInfo?.dbType,
			businessType: selectedObjectFieldBusinessTypeInfo?.businessType,
			indexed,
			indexedAsKeyword,
			indexedLanguageId,
			listTypeDefinitionExternalReferenceCode: '',
			listTypeDefinitionId: 0,
			objectFieldSettings,
			state: false,
		});

		if (onSubmit) {
			onSubmit({
				...values,
				DBType: selectedObjectFieldBusinessTypeInfo?.dbType,
				businessType: selectedObjectFieldBusinessTypeInfo?.businessType,
				indexed,
				indexedAsKeyword,
				indexedLanguageId,
				listTypeDefinitionExternalReferenceCode: '',
				listTypeDefinitionId: 0,
				objectFieldSettings,
				state: false,
			});
		}
	};

	const getMandatoryToggleDisabledState = () => {
		if (
			objectDefinition?.accountEntryRestricted &&
			objectDefinition?.accountEntryRestrictedObjectFieldName ===
				values.name
		) {
			return true;
		}

		if (values.readOnly === 'true' || values.readOnly === 'conditional') {
			return true;
		}

		if (
			oneToManyObjectRelationship &&
			oneToManyObjectRelationship.deletionType !== 'disassociate'
		) {
			return Liferay.FeatureFlags['LPD-34594']
				? oneToManyObjectRelationship.edge
				: false;
		}

		if (
			!dbObjectFieldRequired &&
			editingObjectField &&
			objectDefinition?.status?.label === 'approved'
		) {
			return true;
		}

		return (
			!!values.relationshipType ||
			(!Liferay.FeatureFlags['LPD-32050'] && values.localized) ||
			values.state
		);
	};

	const handleStateToggleChange = (toggled: boolean) => {
		let defaultValue;
		let defaultValueType;

		if (values.id) {
			const currentDefaultValueSettings =
				getDefaultValueFieldSettings(values);
			defaultValue = currentDefaultValueSettings.defaultValue;
			defaultValueType = currentDefaultValueSettings.defaultValueType;
		}

		if (toggled) {
			if (defaultValueType && defaultValue) {
				setValues({required: toggled, state: toggled});

				if (onSubmit) {
					onSubmit({
						...values,
						required: toggled,
						state: toggled,
					});
				}
			}
			else if (!defaultValueType || !defaultValue) {
				setValues({
					objectFieldSettings: getUpdatedDefaultValueType(
						values,
						'inputAsValue'
					),
					required: toggled,
					state: toggled,
				});

				if (onSubmit) {
					onSubmit({
						...values,
						objectFieldSettings: getUpdatedDefaultValueType(
							values,
							'inputAsValue'
						),
						required: toggled,
						state: toggled,
					});
				}
			}
		}
		else {
			setValues({
				required: toggled,
				state: toggled,
			});

			if (onSubmit) {
				onSubmit({
					...values,
					required: toggled,
					state: toggled,
				});
			}
		}
	};

	useEffect(() => {
		const makeFetch = async () => {
			await getObjectFieldSettingsByBusinessType(
				objectRelationshipId as number,
				setListTypeDefinitions,
				setOneToManyObjectRelationship,
				setReloadPicklistSingleSelect,
				setSelectedOutputValue,
				values
			);

			const listTypeDefinitionsURL = createResourceURL(baseResourceURL, {
				p_p_resource_id:
					'/object_definitions/get_view_list_type_definitions_url',
			}).href;

			const {url} = await API.fetchJSON<{
				url: string;
			}>(listTypeDefinitionsURL);

			setListTypeDefinitionsURL(url);
		};

		makeFetch();

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

	useEffect(() => {
		if (reloadPicklistSingleSelect) {
			setTimeout(() => setReloadPicklistSingleSelect(false), 200);
		}
	}, [reloadPicklistSingleSelect]);

	return (
		<>
			 {
					event.stopPropagation();

					if (onSubmit) {
						onSubmit();
					}
				}}
				onChange={handleChange}
				required
				value={
					values.name ??
					toCamelCase(values.label?.[defaultLanguageId] ?? '', true)
				}
			/>

			
				className={className}
				disabled={disabled}
				error={errors.businessType}
				items={objectFieldBusinessTypesInfo}
				label={Liferay.Language.get('type')}
				onSelectionChange={(value) => {
					handleTypeChange(value as string);
				}}
				required
				selectedKey={values.businessType}
			>
				{(item) => (
					
				)}
			

			{values.businessType === 'Attachment' && objectDefinition && (
				
			)}

			{values.businessType === 'AutoIncrement' && !editingObjectField && (
				
			)}

			{values.businessType === 'Aggregation' &&
				objectDefinition?.externalReferenceCode && (
					
				)}

			{values.businessType === 'Formula' && (
				
					error={errors.output}
					items={FORMULA_OUTPUT_OPTIONS}
					label={Liferay.Language.get('output')}
					onSelectionChange={(value) => {
						let newObjectFieldSettings: ObjectFieldSetting[] = [];

						if (values.objectFieldSettings) {
							newObjectFieldSettings =
								values.objectFieldSettings?.filter(
									(objectFieldSetting) =>
										objectFieldSetting.name !== 'output'
								) as ObjectFieldSetting[];
						}

						setValues({
							objectFieldSettings: [
								...newObjectFieldSettings,
								{
									name: 'output',
									value,
								},
							],
						});

						if (onSubmit) {
							onSubmit({
								...values,
								objectFieldSettings: [
									...newObjectFieldSettings,
									{
										name: 'output',
										value,
									},
								],
							});
						}

						setSelectedOutputValue(
							FORMULA_OUTPUT_OPTIONS.find(
								(formulaFieldOption) =>
									formulaFieldOption.value === value
							)?.value as string
						);
					}}
					required
					selectedKey={selectedOutputValue}
				/>
			)}

			{(values.businessType === 'Picklist' ||
				values.businessType === 'MultiselectPicklist') && (
				
{reloadPicklistSingleSelect ? ( ) : (
{ const selectedListTypeDefinition = listTypeDefinitions.find( ({externalReferenceCode}) => externalReferenceCode === value ); if (selectedListTypeDefinition) { setValues({ listTypeDefinitionExternalReferenceCode: selectedListTypeDefinition.externalReferenceCode, listTypeDefinitionId: selectedListTypeDefinition.id, objectFieldSettings: removeFieldSettings( [ 'defaultValue', 'stateFlow', ], values ), }); if (onSubmit) { onSubmit({ ...values, listTypeDefinitionExternalReferenceCode: selectedListTypeDefinition.externalReferenceCode, listTypeDefinitionId: selectedListTypeDefinition.id, objectFieldSettings: removeFieldSettings( [ 'defaultValue', 'stateFlow', ], values ), }); } } }} selectedKey={ selectedListTypeDefinitionExternalReferenceCode } /> updateListTypeDefinitions( setListTypeDefinitions ) } symbol="reload" title={Liferay.Language.get('refresh-list')} />
)} { window.open(listTypeDefinitionsURL, '_blank'); }} > {Liferay.Language.get('manage-picklists')}
)} {values.businessType === 'DateTime' && ( )} {children} {values.businessType !== 'Aggregation' && values.businessType !== 'AutoIncrement' && values.businessType !== 'Formula' && ( { setValues({required}); if ( dbObjectFieldRequired && editingObjectField && modelBuilder && objectDefinition?.status?.label === 'approved' && setDbObjectFieldRequired ) { setDbObjectFieldRequired(required); } if (onSubmit) { onSubmit({ ...values, required, }); } }} toggled={values.required || values.state} /> )} {values.businessType === 'Picklist' && validListTypeDefinitionId && ( { handleStateToggleChange(state); }} toggled={values.state} /> )} {(values.businessType === 'Text' || values.businessType === 'Integer') && ( )} ); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy