
META-INF.resources.js.data_set.actions.components.ActionForm.tsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.frontend.data.set.admin.web
Show all versions of com.liferay.frontend.data.set.admin.web
Liferay Frontend Data Set Admin Web
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 ClayForm, {ClayInput, ClaySelectWithOption} from '@clayui/form';
import ClayIcon from '@clayui/icon';
import ClayLayout from '@clayui/layout';
import ClayPanel from '@clayui/panel';
import ClayTabs from '@clayui/tabs';
import classNames from 'classnames';
import {InputLocalized, openModal} from 'frontend-js-components-web';
import {fetch} from 'frontend-js-web';
import React, {useEffect, useState} from 'react';
import RequiredMark from '../../../components/RequiredMark';
import Search from '../../../components/Search';
import ValidationFeedback from '../../../components/ValidationFeedback';
import {
API_URL,
DEFAULT_FETCH_HEADERS,
OBJECT_RELATIONSHIP,
} from '../../../utils/constants';
import openDefaultFailureToast from '../../../utils/openDefaultFailureToast';
import openDefaultSuccessToast from '../../../utils/openDefaultSuccessToast';
import {IDataSet} from '../../../utils/types';
import {EActionTarget, EActionType, IAction} from '../Actions';
enum EAsyncActionMethod {
DELETE = 'DELETE',
GET = 'GET',
PATCH = 'PATCH',
POST = 'POST',
PUT = 'PUT',
}
const ACTION_TARGETS = [
{
label: Liferay.Language.get('link'),
value: EActionTarget.LINK,
},
{
label: Liferay.Language.get('modal'),
value: EActionTarget.MODAL,
},
{
label: Liferay.Language.get('side-panel'),
value: EActionTarget.SIDEPANEL,
},
];
const ITEM_ACTION_TARGETS = [
{
label: Liferay.Language.get('async'),
value: EActionTarget.ASYNC,
},
{
label: Liferay.Language.get('headless'),
value: EActionTarget.HEADLESS,
},
].concat(ACTION_TARGETS);
const MESSAGE_TYPES = [
{
label: Liferay.Language.get('info'),
value: 'info',
},
{
label: Liferay.Language.get('secondary'),
value: 'secondary',
},
{
label: Liferay.Language.get('success'),
value: 'success',
},
{
label: Liferay.Language.get('danger'),
value: 'danger',
},
{
label: Liferay.Language.get('warning'),
value: 'warning',
},
];
const MODAL_SIZES = [
{
label: Liferay.Language.get('full-screen'),
value: 'full-screen',
},
{
label: Liferay.Language.get('large'),
value: 'lg',
},
{
label: Liferay.Language.get('small'),
value: 'sm',
},
];
const translationExists = ({translations}: {translations: any}) => {
return Boolean(Object.keys(translations).find((key) => translations[key]));
};
const ActionForm = ({
activeTab,
dataSet,
editing = false,
initialValues,
namespace,
onCancel,
onSave,
spritemap,
}: {
activeTab: number;
dataSet: IDataSet;
editing?: boolean;
initialValues?: IAction;
namespace: string;
onCancel: () => void;
onSave: () => void;
spritemap: string;
}) => {
const [activeMessageTab, setActiveMessageTab] = useState(0);
const [availableIconSymbols, setAvailableIconSymbols] = useState<
Array<{label: string; value: string}>
>([]);
const [
confirmationMessageTranslations,
setConfirmationMessageTranslations,
] = useState(initialValues?.confirmationMessage_i18n ?? {});
const [errorMessageTranslations, setErrorMessageTranslations] = useState(
initialValues?.errorMessage_i18n ?? {}
);
const [labelTranslations, setLabelTranslations] = useState(
initialValues?.label_i18n ?? {}
);
const [requestBodyValidationError, setRequestBodyValidationError] =
useState(false);
const [labelValidationError, setLabelValidationError] = useState(false);
const [permissionKeyValidationError, setPermissionKeyValidationError] =
useState(false);
const [saveButtonDisabled, setSaveButtonDisabled] = useState(false);
const [successMessageTranslations, setSuccessMessageTranslations] =
useState(initialValues?.successMessage_i18n ?? {});
const [titleTranslations, setTitleTranslations] = useState(
initialValues?.title_i18n ?? {}
);
const [urlValidationError, setURLValidationError] = useState(false);
const [actionData, setActionData] = useState({
confirmationMessage: initialValues?.confirmationMessage ?? '',
confirmationMessageType:
initialValues?.confirmationMessageType ?? 'warning',
icon: initialValues?.icon ?? '',
label: initialValues?.label ?? '',
method: initialValues?.method ?? '',
modalSize: initialValues?.modalSize ?? '',
permissionKey: initialValues?.permissionKey ?? '',
requestBody: initialValues?.requestBody ?? '',
target: initialValues?.target ?? 'link',
title: initialValues?.title ?? '',
type: initialValues?.type ?? '',
url: initialValues?.url ?? '',
} as IAction);
const isRequestBodyInputValid = (value: string | undefined) => {
if (!value) {
return true;
}
if (!value.match(/{[^}]*}/)) {
return false;
}
try {
JSON.parse(value);
return true;
}
catch {
return false;
}
};
const onActionTargetChange = (event: any) => {
const target = event.target.value;
setActionData({
...actionData,
method:
target === EActionTarget.ASYNC ? EAsyncActionMethod.DELETE : '',
modalSize:
target === EActionTarget.MODAL ? MODAL_SIZES[0].value : '',
target,
});
if (target !== EActionTarget.HEADLESS) {
setPermissionKeyValidationError(false);
}
};
const saveAction = async () => {
setSaveButtonDisabled(true);
const {
confirmationMessageType,
icon,
method,
modalSize,
permissionKey,
requestBody,
target,
url,
} = actionData;
const type: string =
activeTab === 0 ? EActionType.ITEM : EActionType.CREATION;
const body = {
confirmationMessage_i18n: confirmationMessageTranslations,
icon,
label_i18n: labelTranslations,
method,
modalSize,
permissionKey,
[OBJECT_RELATIONSHIP.DATA_SET_ACTIONS_ID]: dataSet.id,
requestBody,
target,
title_i18n: titleTranslations,
type,
url,
} as any;
if (Object.keys(confirmationMessageTranslations).length) {
body.confirmationMessageType = confirmationMessageType;
}
if (
actionData.target === EActionTarget.ASYNC ||
actionData.target === EActionTarget.HEADLESS
) {
body.errorMessage_i18n = errorMessageTranslations;
body.successMessage_i18n = successMessageTranslations;
}
if (actionData.target === EActionTarget.ASYNC) {
body.method = method;
}
let apiURL = API_URL.ACTIONS;
let fetchMethod = 'POST';
if (editing) {
apiURL = `${apiURL}/${initialValues?.id}`;
fetchMethod = 'PUT';
}
const response = await fetch(apiURL, {
body: JSON.stringify(body),
headers: DEFAULT_FETCH_HEADERS,
method: fetchMethod,
});
if (!response.ok) {
setSaveButtonDisabled(false);
openDefaultFailureToast();
return;
}
setSaveButtonDisabled(false);
openDefaultSuccessToast();
onSave();
};
const validate = () => {
let valid: boolean = true;
const {permissionKey, requestBody, target, url} = actionData;
if (
!translationExists({
translations: labelTranslations,
})
) {
valid = false;
setLabelValidationError(true);
}
if (!url && target !== EActionTarget.HEADLESS) {
valid = false;
setURLValidationError(true);
}
if (
target === EActionTarget.ASYNC ||
target === EActionTarget.HEADLESS
) {
if (!isRequestBodyInputValid(requestBody)) {
valid = false;
setRequestBodyValidationError(true);
}
}
if (!permissionKey && target === EActionTarget.HEADLESS) {
valid = false;
setPermissionKeyValidationError(true);
}
return valid;
};
useEffect(() => {
const getIcons = async () => {
const response = await fetch(spritemap);
const responseText = await response.text();
if (responseText.length) {
const spritemapDocument = new DOMParser().parseFromString(
responseText,
'text/xml'
);
const symbolElements =
spritemapDocument.querySelectorAll('symbol');
const iconSymbols = Array.from(symbolElements!).map(
(element) => ({
label: element.id,
value: element.id,
})
);
setAvailableIconSymbols(iconSymbols);
}
};
getIcons();
}, [spritemap]);
const confirmationMessageFormElementId = `${namespace}ConfirmationMessage`;
const confirmationMessageTypeFormElementId = `${namespace}ConfirmationMessageType`;
const errorMessageFormElementId = `${namespace}ErrorMessage`;
const iconFormElementId = `${namespace}Icon`;
const labelFormElementId = `${namespace}Label`;
const methodFormElementId = `${namespace}Method`;
const modalSizeFormElementId = `${namespace}ModalSize`;
const permissionKeyFormElementId = `${namespace}PermissionKey`;
const requestBodyFormElementId = `${namespace}RequestBody`;
const successMessageFormElementId = `${namespace}SuccessMessage`;
const titleFormElementId = `${namespace}Title`;
const typeFormElementId = `${namespace}Type`;
const urlFormElementId = `${namespace}URL`;
const ModalBody = ({closeModal}: {closeModal: Function}) => {
const [filteredIconSymbols, setFilteredIconSymbols] =
useState>(
availableIconSymbols
);
const [query, setQuery] = useState('');
const onSearch = (query: string) => {
setQuery(query);
const regexp = new RegExp(query, 'i');
setFilteredIconSymbols(
query
? availableIconSymbols.filter((item) =>
String(item.value).match(regexp)
)
: availableIconSymbols
);
};
return (
<>
{filteredIconSymbols.map((item) => {
return (
- {
setActionData({
...actionData,
icon: item.value,
});
closeModal();
}}
>
{item.label}
);
})}
>
);
};
return (
<>
{editing && initialValues?.label}
{!editing &&
activeTab === 0 &&
Liferay.Language.get('new-item-action')}
{!editing &&
activeTab === 1 &&
Liferay.Language.get('new-creation-action')}
{
setLabelTranslations(translations);
setLabelValidationError(
!translationExists({
translations,
})
);
}}
placeholder={Liferay.Language.get(
'action-name'
)}
required
translations={labelTranslations}
/>
setActionData({
...actionData,
icon: value,
})
}
placeholder={Liferay.Language.get(
'no-icon-selected'
)}
type="text"
value={actionData.icon}
/>
openModal({
bodyComponent: ModalBody,
containerProps: {
className:
'dsm-actions-icon-selection-modal',
},
size: 'lg',
title: Liferay.Language.get(
'select-an-icon'
),
})
}
symbol={
actionData.icon !== ''
? 'change'
: 'plus'
}
/>
{actionData.icon !== '' && (
setActionData({
...actionData,
icon: '',
})
}
symbol="trash"
/>
)}
{actionData.target === EActionTarget.ASYNC && (
setActionData({
...actionData,
method: event.target.value,
})
}
options={Object.values(
EAsyncActionMethod
).map((method) => ({
label: method,
value: method,
}))}
placeholder={Liferay.Language.get(
'please-select-an-option'
)}
value={actionData.method}
/>
)}
{actionData.target === EActionTarget.MODAL && (
setActionData({
...actionData,
modalSize: event.target.value,
})
}
options={MODAL_SIZES}
placeholder={Liferay.Language.get(
'please-select-an-option'
)}
value={actionData.modalSize}
/>
)}
{(actionData.target === EActionTarget.MODAL ||
actionData.target === EActionTarget.SIDEPANEL) && (
{
setTitleTranslations(translations);
}}
placeholder={
actionData.target ===
EActionTarget.MODAL
? Liferay.Language.get(
'add-the-title-of-the-modal'
)
: Liferay.Language.get(
'add-the-title-of-the-side-panel'
)
}
translations={titleTranslations}
/>
)}
{actionData.target !== EActionTarget.HEADLESS && (
{
const url = event.target.value;
setActionData({
...actionData,
url,
});
setURLValidationError(!url);
}}
placeholder={Liferay.Language.get(
'add-a-url-here'
)}
value={actionData.url}
/>
{urlValidationError && (
)}
)}
{(actionData.target === EActionTarget.HEADLESS ||
actionData.target === EActionTarget.ASYNC) && (
{
const requestBody =
event.target.value;
setActionData({
...actionData,
requestBody,
});
setRequestBodyValidationError(
!isRequestBodyInputValid(
requestBody
)
);
}}
placeholder={Liferay.Language.get(
'add-a-request-body-here'
)}
value={actionData.requestBody}
/>
{requestBodyValidationError && (
)}
)}
{
const permissionKey =
event.target.value;
setActionData({
...actionData,
permissionKey,
});
if (
actionData.target ===
EActionTarget.HEADLESS
) {
setPermissionKeyValidationError(
!permissionKey
);
}
}}
placeholder={Liferay.Language.get(
'add-a-value-here'
)}
value={actionData.permissionKey}
/>
{permissionKeyValidationError && (
)}
{activeTab === 0 && (
setActionData({
...actionData,
confirmationMessageType:
event.target.value,
})
}
options={MESSAGE_TYPES}
value={
actionData.confirmationMessageType
}
/>
)}
{(actionData.target === EActionTarget.ASYNC ||
actionData.target === EActionTarget.HEADLESS) && (
{Liferay.Language.get(
'you-can-write-status-messages-related-to-this-action'
)}
{
setActiveMessageTab(tab);
}}
>
{Liferay.Language.get('success')}
{Liferay.Language.get('error')}
)}
{
const valid = validate();
if (valid) {
saveAction();
}
}}
>
{Liferay.Language.get('save')}
{Liferay.Language.get('cancel')}
>
);
};
export default ActionForm;
© 2015 - 2025 Weber Informatics LLC | Privacy Policy