
META-INF.resources.js.CustomDataSets.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 from '@clayui/button';
import ClayDropDown from '@clayui/drop-down';
import ClayForm, {ClayInput} from '@clayui/form';
import ClayIcon from '@clayui/icon';
import ClayLink from '@clayui/link';
import ClayModal from '@clayui/modal';
import {ClayTooltipProvider} from '@clayui/tooltip';
import {FrontendDataSet} from '@liferay/frontend-data-set-web';
import classNames from 'classnames';
import {openModal} from 'frontend-js-components-web';
import {fetch, navigate} from 'frontend-js-web';
import React, {useState} from 'react';
import '../css/DataSets.scss';
import RequiredMark from './components/RequiredMark';
import ValidationFeedback from './components/ValidationFeedback';
import RESTApplicationDropdownItem from './components/rest/RESTApplicationDropdownItem';
import RESTApplicationDropdownMenu from './components/rest/RESTApplicationDropdownMenu';
import RESTEndpointDropdownMenu from './components/rest/RESTEndpointDropdownMenu';
import RESTSchemaDropdownMenu from './components/rest/RESTSchemaDropdownMenu';
import {
ALLOWED_ENDPOINTS_PARAMETERS,
API_URL,
DEFAULT_FETCH_HEADERS,
FDS_DEFAULT_PROPS,
} from './utils/constants';
import getAPIExplorerURL from './utils/getAPIExplorerURL';
import openDefaultFailureToast from './utils/openDefaultFailureToast';
import openDefaultSuccessToast from './utils/openDefaultSuccessToast';
import {IDataSet, ISystemDataSet} from './utils/types';
const LIST_OF_ITEMS_PER_PAGE = '4, 8, 20, 40, 60';
const DEFAULT_ITEMS_PER_PAGE = 20;
const LabelInput = ({
labelValidationError,
namespace,
onBlur,
onChange,
value,
}: {
labelValidationError: boolean;
namespace: string;
onBlur: () => void;
onChange: Function;
value: string;
}) => (
onChange(event.target.value)}
type="text"
value={value}
/>
{labelValidationError && }
);
const NewDataSetModalContent = ({
closeModal,
loadData,
namespace,
resolvedRESTSchemas,
restApplications,
}: {
closeModal: Function;
loadData: Function;
namespace: string;
resolvedRESTSchemas?: Array;
restApplications?: Array;
}) => {
const [label, setLabel] = useState('');
const [saveButtonDisabled, setSaveButtonDisabled] = useState(false);
const [labelValidationError, setLabelValidationError] = useState(false);
const [
requiredRESTApplicationValidationError,
setRequiredRESTApplicationValidationError,
] = useState(false);
const [
noEnpointsRESTApplicationValidationError,
setNoEnpointsRESTApplicationValidationError,
] = useState(false);
const [restSchemaValidationError, setRESTSchemaValidationError] =
useState(false);
const [restEndpointValidationError, setRESTEndpointValidationError] =
useState(false);
const [restSchemaEndpoints, setRESTSchemaEndpoints] = useState<
Map>
>(new Map());
const [selectedRESTApplication, setSelectedRESTApplication] = useState<
string | null
>();
const [selectedRESTSchema, setSelectedRESTSchema] = useState<
string | null
>();
const [selectedRESTEndpoint, setSelectedRESTEndpoint] = useState<
string | null
>();
const saveDataSet = async () => {
if (!selectedRESTApplication) {
return;
}
selectedRESTApplication;
const body = {
defaultItemsPerPage: DEFAULT_ITEMS_PER_PAGE,
label,
listOfItemsPerPage: LIST_OF_ITEMS_PER_PAGE,
restApplication: selectedRESTApplication,
restEndpoint: selectedRESTEndpoint,
restSchema: selectedRESTSchema,
};
const response = await fetch(API_URL.DATA_SETS, {
body: JSON.stringify(body),
headers: DEFAULT_FETCH_HEADERS,
method: 'POST',
});
if (!response.ok) {
openDefaultFailureToast();
return;
}
const dataSet: IDataSet = await response.json();
if (dataSet?.id) {
closeModal();
openDefaultSuccessToast();
loadData();
}
else {
setSaveButtonDisabled(false);
openDefaultFailureToast();
}
};
const isPathValid = (
path: string,
allowedParameters: string[]
): boolean => {
const paramsMatcher = RegExp('{(.*?)}', 'g');
let matches;
while ((matches = paramsMatcher.exec(path)) !== null) {
if (!allowedParameters.includes(matches[1])) {
return false;
}
}
return true;
};
const getRESTSchemas = async (
restApplication: string,
resolvedRESTSchemas: Array = []
) => {
if (!restApplication) {
return;
}
const response = await fetch(`/o${restApplication}/openapi.json`, {
headers: DEFAULT_FETCH_HEADERS,
});
if (!response.ok) {
openDefaultFailureToast();
return;
}
const responseJson = await response.json();
const paths = Object.keys(responseJson.paths ?? []);
const schemaNames = Object.keys(responseJson.components?.schemas ?? []);
const schemaEndpoints: Map> = new Map();
schemaNames.forEach((schemaName) => {
paths.forEach((path: string) => {
if (
!isPathValid(path, ALLOWED_ENDPOINTS_PARAMETERS) &&
!resolvedRESTSchemas.includes(schemaName)
) {
return;
}
if (
responseJson.paths[path]?.get?.responses.default.content[
'application/json'
]?.schema?.$ref?.endsWith(`/Page${schemaName}`)
) {
const endpoints = schemaEndpoints.get(schemaName) ?? [];
endpoints.push(path);
if (endpoints.length === 1) {
schemaEndpoints.set(schemaName, endpoints);
}
}
});
});
if (schemaEndpoints.size === 0) {
setSelectedRESTSchema(null);
setSelectedRESTEndpoint(null);
setNoEnpointsRESTApplicationValidationError(true);
}
else if (schemaEndpoints.size === 1) {
const schema = Array.from(schemaEndpoints.keys())[0];
setSelectedRESTSchema(schema);
const paths = schemaEndpoints.get(schema);
if (paths?.length === 1) {
setSelectedRESTEndpoint(paths[0]);
}
setNoEnpointsRESTApplicationValidationError(false);
}
else {
setSelectedRESTSchema(null);
setSelectedRESTEndpoint(null);
setNoEnpointsRESTApplicationValidationError(false);
}
setRESTSchemaEndpoints(schemaEndpoints);
};
const validate = () => {
if (!label) {
setLabelValidationError(true);
return false;
}
if (!selectedRESTApplication) {
setRequiredRESTApplicationValidationError(true);
return false;
}
if (noEnpointsRESTApplicationValidationError) {
return false;
}
if (!selectedRESTSchema) {
setRESTSchemaValidationError(true);
return false;
}
if (!selectedRESTEndpoint) {
setRESTEndpointValidationError(true);
return false;
}
return true;
};
const RestApplicationDropdown = () => (
{selectedRESTApplication ? (
) : (
Liferay.Language.get('choose-an-option')
)}
}
>
{
setSelectedRESTApplication(item);
setRequiredRESTApplicationValidationError(false);
getRESTSchemas(item, resolvedRESTSchemas);
}}
restApplications={restApplications!}
/>
);
const RestSchemaDropdown = () => (
{selectedRESTSchema ||
Liferay.Language.get('choose-an-option')}
}
>
{
setSelectedRESTSchema(item);
const endpoints = restSchemaEndpoints.get(item);
if (endpoints?.length === 1) {
setSelectedRESTEndpoint(endpoints[0]);
}
else {
setSelectedRESTEndpoint(null);
}
setRESTSchemaValidationError(false);
}}
restSchemas={Array.from(restSchemaEndpoints.keys())}
/>
);
const RestEndpointDropdown = () => (
{selectedRESTEndpoint ||
Liferay.Language.get('choose-an-option')}
}
>
{
setSelectedRESTEndpoint(item);
setRESTEndpointValidationError(false);
}}
restEndpoints={
restSchemaEndpoints.get(selectedRESTSchema ?? '') ?? []
}
/>
);
return (
<>
{Liferay.Language.get('new-data-set')}
{
setLabelValidationError(!label);
}}
onChange={setLabel}
value={label}
/>
{restApplications && (
{requiredRESTApplicationValidationError && (
)}
{noEnpointsRESTApplicationValidationError && (
)}
)}
{restSchemaEndpoints.size > 0 && (
{restSchemaValidationError && }
)}
{selectedRESTSchema && (
{restEndpointValidationError && }
)}
{
setSaveButtonDisabled(true);
const success = validate();
if (success) {
saveDataSet();
}
else {
setSaveButtonDisabled(false);
}
}}
>
{Liferay.Language.get('save')}
closeModal()}
>
{Liferay.Language.get('cancel')}
}
/>
>
);
};
const CustomDataSets = ({
editDataSetURL,
hasAddDataSetObjectEntryPermission,
namespace,
permissionsURL,
resolvedRESTSchemas,
restApplications,
systemDataSets,
}: {
editDataSetURL: string;
hasAddDataSetObjectEntryPermission: boolean;
namespace: string;
permissionsURL: string;
resolvedRESTSchemas: Array;
restApplications: Array;
systemDataSets: Array;
}) => {
const getAPIURL = () => {
if (!systemDataSets.length) {
return API_URL.DATA_SETS;
}
const systemDataSetNames: string = systemDataSets
.map((systemDataSet) => `'${systemDataSet.name}'`)
.join(',');
return `${API_URL.DATA_SETS}?filter=not (externalReferenceCode in (${systemDataSetNames}))`;
};
const getEditURL = (itemData: IDataSet) => {
const url = new URL(editDataSetURL);
url.searchParams.set(
`${namespace}dataSetERC`,
itemData.externalReferenceCode
);
url.searchParams.set(`${namespace}dataSetLabel`, itemData.label);
return url;
};
const onDeleteClick = ({
itemData,
loadData,
}: {
itemData: IDataSet;
loadData: Function;
}) => {
openModal({
bodyHTML: Liferay.Language.get(
'deleting-a-data-set-is-an-action-that-cannot-be-reversed'
),
buttons: [
{
autoFocus: true,
displayType: 'secondary',
label: Liferay.Language.get('cancel'),
type: 'cancel',
},
{
displayType: 'danger',
label: Liferay.Language.get('delete'),
onClick: ({processClose}: {processClose: Function}) => {
processClose();
fetch(itemData.actions.delete.href, {
headers: DEFAULT_FETCH_HEADERS,
method: itemData.actions.delete.method,
})
.then(() => {
openDefaultSuccessToast();
loadData();
})
.catch(openDefaultFailureToast);
},
},
],
status: 'danger',
title: Liferay.Language.get('delete-data-set'),
});
};
const restApplicationRenderer = function ({
itemData,
}: {
itemData: IDataSet;
}) {
const apiExplorerURL = getAPIExplorerURL(itemData.restApplication);
return (
{itemData.restApplication}
);
};
const creationMenu = {
primaryItems: [
{
label: Liferay.Language.get('new-data-set'),
onClick: ({loadData}: {loadData: Function}) => {
openModal({
contentComponent: ({
closeModal,
}: {
closeModal: Function;
}) => (
),
});
},
},
],
};
const views = [
{
contentRenderer: 'table',
name: 'table',
schema: {
fields: [
{
actionId: 'edit',
contentRenderer: 'actionLink',
fieldName: 'label',
label: Liferay.Language.get('name'),
sortable: true,
},
{
contentRenderer: 'restApplicationRenderer',
fieldName: 'restApplication',
label: Liferay.Language.get('rest-application'),
sortable: true,
},
{
fieldName: 'restSchema',
label: Liferay.Language.get('rest-schema'),
sortable: true,
},
{
fieldName: 'restEndpoint',
label: Liferay.Language.get('rest-endpoint'),
sortable: true,
},
{
contentRenderer: 'dateTime',
fieldName: 'dateModified',
label: Liferay.Language.get('modified-date'),
sortable: true,
},
],
},
},
];
return (
{
navigate(getEditURL(itemData));
},
},
{
data: {
permissionKey: 'permissions',
size: 'full-screen',
title: Liferay.Language.get('permissions'),
},
href: permissionsURL,
icon: 'password-policies',
label: Liferay.Language.get('permissions'),
target: 'modal-permissions',
},
{
data: {
permissionKey: 'delete',
},
icon: 'trash',
label: Liferay.Language.get('delete'),
onClick: onDeleteClick,
},
]}
sorts={[{direction: 'desc', key: 'dateCreated'}]}
views={views}
/>
);
};
export default CustomDataSets;
© 2015 - 2025 Weber Informatics LLC | Privacy Policy