From 761de1b7738fbe2fafbe795a182727029012cdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20=C4=8Ciko=C5=A1?= Date: Mon, 4 Sep 2023 15:41:10 +0200 Subject: [PATCH] LPS-195155 Create UI to save and reorder FDS Actions --- .../META-INF/resources/js/Constants.tsx | 3 + .../resources/js/fds_view/Actions.tsx | 361 ++++++++++++++---- .../js/utils/openDefaultFailureToast.ts | 13 + .../js/utils/openDefaultSuccessToast.ts | 13 + .../META-INF/resources/js/Constants.d.ts | 3 + .../resources/js/fds_view/Actions.d.ts | 6 +- .../js/utils/openDefaultFailureToast.d.ts | 6 + .../js/utils/openDefaultSuccessToast.d.ts | 6 + 8 files changed, 326 insertions(+), 85 deletions(-) create mode 100644 modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.ts create mode 100644 modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.ts create mode 100644 modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.d.ts create mode 100644 modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.d.ts diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/Constants.tsx b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/Constants.tsx index b18466dd7e5590..4729ad0600ec3c 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/Constants.tsx +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/Constants.tsx @@ -4,6 +4,7 @@ */ const API_URL = { + FDS_ACTIONS: '/o/data-set-manager/actions', FDS_DATE_FILTERS: '/o/data-set-manager/date-filters', FDS_DYNAMIC_FILTERS: '/o/data-set-manager/dynamic-filters', FDS_ENTRIES: '/o/data-set-manager/entries', @@ -20,6 +21,8 @@ const FUZZY_OPTIONS = { const OBJECT_RELATIONSHIP = { FDS_ENTRY_FDS_VIEW: 'fdsEntryFDSViewRelationship', FDS_ENTRY_FDS_VIEW_ID: 'r_fdsEntryFDSViewRelationship_c_fdsEntryId', + FDS_VIEW_FDS_ACTION: 'fdsViewFDSActionRelationship', + FDS_VIEW_FDS_ACTION_ID: 'r_fdsViewFDSActionRelationship_c_fdsViewId', FDS_VIEW_FDS_DATE_FILTER: 'fdsViewFDSDateFilterRelationship', FDS_VIEW_FDS_DATE_FILTER_ID: 'r_fdsViewFDSDateFilterRelationship_c_fdsViewId', diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/fds_view/Actions.tsx b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/fds_view/Actions.tsx index 9d3c59983a6605..4678abc838b141 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/fds_view/Actions.tsx +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/fds_view/Actions.tsx @@ -8,12 +8,18 @@ import ClayButton from '@clayui/button'; import ClayForm, {ClayInput, ClaySelectWithOption} from '@clayui/form'; import ClayIcon from '@clayui/icon'; import ClayLayout from '@clayui/layout'; +import ClayLoadingIndicator from '@clayui/loading-indicator'; import ClayPanel from '@clayui/panel'; import ClayTabs from '@clayui/tabs'; import {InputLocalized} from 'frontend-js-components-web'; -import React, {useState} from 'react'; +import {fetch} from 'frontend-js-web'; +import React, {useEffect, useState} from 'react'; +import {API_URL, OBJECT_RELATIONSHIP} from '../Constants'; +import {IFDSViewSectionInterface} from '../FDSView'; import OrderableTable from '../components/OrderableTable'; +import openDefaultFailureToast from '../utils/openDefaultFailureToast'; +import openDefaultSuccessToast from '../utils/openDefaultSuccessToast'; const MESSAGE_TYPES = [ { @@ -66,17 +72,220 @@ const TYPES = [ }, ]; +interface IFDSAction { + [OBJECT_RELATIONSHIP.FDS_VIEW_FDS_ACTION]: any; + icon: string; + id: number; + type: string; + url: string; +} + const noop = () => {}; -const Actions = () => { +const Actions = ({fdsView, namespace}: IFDSViewSectionInterface) => { const [activeSection, setActiveSection] = useState(SECTIONS.ACTIONS); const [activeTab, setActiveTab] = useState(0); + const [confirmationMessage, setConfirmationMessage] = useState(''); const [ confirmationMessageTranslations, setConfirmationMessageTranslations, ] = useState({}); + const [fdsActions, setFDSActions] = useState>([]); const [iconSymbol, setIconSymbol] = useState('bolt'); + const [label, setLabel] = useState(''); const [labelTranslations, setLabelTranslations] = useState({}); + const [loading, setLoading] = useState(true); + const [newActionsOrder, setNewActionsOrder] = useState(''); + const [type, setType] = useState('link'); + const [saveButtonDisabled, setSaveButtonDisabled] = useState(false); + const [url, setURL] = useState(''); + + const getFDSActions = async () => { + setLoading(true); + + const response = await fetch( + `${API_URL.FDS_ACTIONS}?filter=(${OBJECT_RELATIONSHIP.FDS_VIEW_FDS_ACTION_ID} eq '${fdsView.id}')&nestedFields=${OBJECT_RELATIONSHIP.FDS_VIEW_FDS_ACTION}` + ); + + const responseJSON = await response.json(); + + const storedFDSActions: IFDSAction[] = responseJSON.items; + + let ordered = storedFDSActions; + let notOrdered: IFDSAction[] = []; + + const fdsActionsOrder = + storedFDSActions?.[0]?.[OBJECT_RELATIONSHIP.FDS_VIEW_FDS_ACTION] + ?.fdsActionsOrder; + + if (fdsActionsOrder) { + const fdsActionsOrderArray = fdsActionsOrder.split(',') as string[]; + + ordered = fdsActionsOrderArray + .map((fdsActionId) => + storedFDSActions.find( + (fdsAction) => fdsAction.id === Number(fdsActionId) + ) + ) + .filter(Boolean) as IFDSAction[]; + + if (storedFDSActions.length > fdsActionsOrderArray.length) { + notOrdered = storedFDSActions.filter( + (fdsAction) => + !fdsActionsOrderArray.includes(String(fdsAction.id)) + ); + } + } + + setFDSActions([...ordered, ...notOrdered]); + + setLoading(false); + }; + + const saveFDSAction = async () => { + setSaveButtonDisabled(true); + + const body = { + [OBJECT_RELATIONSHIP.FDS_VIEW_FDS_ACTION_ID]: fdsView.id, + icon: iconSymbol, + type, + url, + } as any; + + if (Liferay.FeatureFlags['LPS-172017']) { + body.confirmationMessage_i18n = confirmationMessageTranslations; + body.label_i18n = labelTranslations; + } + else { + body.confirmationMessage = confirmationMessage; + body.label = labelTranslations; + } + + const response = await fetch(API_URL.FDS_ACTIONS, { + body: JSON.stringify(body), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + method: 'POST', + }); + + if (!response.ok) { + setSaveButtonDisabled(false); + + openDefaultFailureToast(); + + return; + } + + await response.json(); + + openDefaultSuccessToast(); + + setActiveSection(SECTIONS.ACTIONS); + + getFDSActions(); + }; + + const updateFDSActionsOrder = async () => { + const response = await fetch( + `${API_URL.FDS_VIEWS}/by-external-reference-code/${fdsView.externalReferenceCode}`, + { + body: JSON.stringify({ + fdsActionsOrder: newActionsOrder, + }), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + method: 'PATCH', + } + ); + + if (!response.ok) { + openDefaultFailureToast(); + + return null; + } + + const responseJSON = await response.json(); + + const fdsFiltersOrder = responseJSON?.fdsActionsOrder; + + if (fdsFiltersOrder && fdsFiltersOrder === newActionsOrder) { + openDefaultSuccessToast(); + + setNewActionsOrder(''); + } + else { + openDefaultFailureToast(); + } + }; + + useEffect(() => { + getFDSActions(); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + if (loading) { + return ; + } + + const labelFormElementId = `${namespace}Label`; + const iconFormElementId = `${namespace}Icon`; + const typeFormElementId = `${namespace}Type`; + const urlFormElementId = `${namespace}URL`; + const confirmationMessageFormElementId = `${namespace}ConfirmationMessage`; + const confirmationMessageTypeFormElementId = `${namespace}ConfirmationMessageType`; + + const ConfirmationMessageRow = () => ( + + + + {Liferay.FeatureFlags['LPS-172017'] ? ( + + ) : ( + + + + + setConfirmationMessage(event.target.value) + } + type="text" + value={label} + /> + + )} + + + + + + + + + + + + ); return ( @@ -151,7 +360,7 @@ const Actions = () => { name: 'type', }, ]} - items={[]} + items={fdsActions} noItemsButtonLabel={Liferay.Language.get( 'create-item-action' )} @@ -162,8 +371,18 @@ const Actions = () => { 'no-actions-were-created' )} onCancelButtonClick={noop} - onOrderChange={noop} - onSaveButtonClick={noop} + onOrderChange={({ + orderedItems, + }: { + orderedItems: IFDSAction[]; + }) => { + setNewActionsOrder( + orderedItems + .map((filter) => filter.id) + .join(',') + ); + }} + onSaveButtonClick={updateFDSActionsOrder} /> @@ -195,16 +414,39 @@ const Actions = () => { - + {Liferay.FeatureFlags['LPS-172017'] ? ( + + ) : ( + + + + + setLabel( + event.target.value + ) + } + type="text" + value={label} + /> + + )} { - - + {Liferay.Language.get('save')} diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.ts b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.ts new file mode 100644 index 00000000000000..ef5b7aac4f15a0 --- /dev/null +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.ts @@ -0,0 +1,13 @@ +/** + * 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 {openToast} from 'frontend-js-web'; + +export default function openDefaultFailureToast() { + openToast({ + message: Liferay.Language.get('your-request-failed-to-complete'), + type: 'danger', + }); +} diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.ts b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.ts new file mode 100644 index 00000000000000..ad15f73b23d01c --- /dev/null +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.ts @@ -0,0 +1,13 @@ +/** + * 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 {openToast} from 'frontend-js-web'; + +export default function openDefaultFailureToast() { + openToast({ + message: Liferay.Language.get('your-request-completed-successfully'), + type: 'success', + }); +} diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/Constants.d.ts b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/Constants.d.ts index d05afcfd3f94ee..483aa9defcfc9a 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/Constants.d.ts +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/Constants.d.ts @@ -4,6 +4,7 @@ */ declare const API_URL: { + FDS_ACTIONS: string; FDS_DATE_FILTERS: string; FDS_DYNAMIC_FILTERS: string; FDS_ENTRIES: string; @@ -18,6 +19,8 @@ declare const FUZZY_OPTIONS: { declare const OBJECT_RELATIONSHIP: { readonly FDS_ENTRY_FDS_VIEW: 'fdsEntryFDSViewRelationship'; readonly FDS_ENTRY_FDS_VIEW_ID: 'r_fdsEntryFDSViewRelationship_c_fdsEntryId'; + readonly FDS_VIEW_FDS_ACTION: 'fdsViewFDSActionRelationship'; + readonly FDS_VIEW_FDS_ACTION_ID: 'r_fdsViewFDSActionRelationship_c_fdsViewId'; readonly FDS_VIEW_FDS_DATE_FILTER: 'fdsViewFDSDateFilterRelationship'; readonly FDS_VIEW_FDS_DATE_FILTER_ID: 'r_fdsViewFDSDateFilterRelationship_c_fdsViewId'; readonly FDS_VIEW_FDS_DYNAMIC_FILTER: 'fdsViewFDSDynamicFilterRelationship'; diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/fds_view/Actions.d.ts b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/fds_view/Actions.d.ts index e420975d469b01..078dd77d535900 100644 --- a/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/fds_view/Actions.d.ts +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/fds_view/Actions.d.ts @@ -5,5 +5,9 @@ /// -declare const Actions: () => JSX.Element; +import {IFDSViewSectionInterface} from '../FDSView'; +declare const Actions: ({ + fdsView, + namespace, +}: IFDSViewSectionInterface) => JSX.Element; export default Actions; diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.d.ts b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.d.ts new file mode 100644 index 00000000000000..ddd96687be8bdb --- /dev/null +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultFailureToast.d.ts @@ -0,0 +1,6 @@ +/** + * 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 + */ + +export default function openDefaultFailureToast(): void; diff --git a/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.d.ts b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.d.ts new file mode 100644 index 00000000000000..ddd96687be8bdb --- /dev/null +++ b/modules/apps/frontend-data-set/frontend-data-set-views-web/types/src/main/resources/META-INF/resources/js/utils/openDefaultSuccessToast.d.ts @@ -0,0 +1,6 @@ +/** + * 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 + */ + +export default function openDefaultFailureToast(): void;