@pega/custom-dx-components
Version:
Utility for building custom UI components
315 lines (297 loc) • 11.4 kB
text/typescript
import { isEmbeddedField, isPageListInPath, PAGE, PAGELIST, buildAggOrCalcId } from './repeat-utils';
export const AT_FILTEREDLIST = '@FILTERED_LIST';
export const AT_PROPERTY = '@P';
/**
* [getFieldNameFromEmbeddedFieldName]
* Description - converting embeddedField name starting with !P! or !PL! to normal field
* @ignore
* @param {string} propertyName EmbeddedField name starting with !P! or !PL!
* @returns {string} returns converted string without !P! or !PL! and :
*
* @example <caption>Example for getFieldNameFromEmbeddedFieldName </caption>
* getFieldNameFromEmbeddedFieldName('!P!Organisation:Name') return 'Organisation.Name'
* getFieldNameFromEmbeddedFieldName('!PL!Employees:Name') return 'Employees.Name'
*/
export function getFieldNameFromEmbeddedFieldName(propertyName: string) {
let value = propertyName;
if (value.startsWith(PAGE) || value.startsWith(PAGELIST)) {
value = value.substring(value.lastIndexOf('!') + 1);
value = value.replace(/:/g, '.');
}
return value;
}
/**
* [getEmbeddedFieldName]
* Description - converting normal field name to embedded field starting with !P! or !PL!
* @ignore
* @param {string} propertyName Field name
* @param {string} classID classID of datapage
* @returns {string} returns converted string with !P! or !PL! and :
*
* @example <caption>Example for getEmbeddedFieldName </caption>
* For page property, getEmbeddedFieldName('Organisation.Name') return '!P!Organisation:Name'
* For pageList property, getEmbeddedFieldName('Employees.Name') return '!PL!Employees:Name'
*/
export function getEmbeddedFieldName(propertyName: string, classID: string) {
let value = propertyName;
if (isPageListInPath(value, classID)) {
value = `!PL!${value.replace(/\./g, ':')}`;
} else {
value = `!P!${value.replace(/\./g, ':')}`;
}
return value;
}
/**
* [updateMetaEmbeddedFieldID]
* Description - If the fieldID in meta starts with '!P!' or '!PL!' and contains ':' then replace them with .(dot)
* @ignore
* @param {Array} metaFields Fields metadata Array. Contains metadata of all the fields.
*/
export function updateMetaEmbeddedFieldID(metaFields: any[]) {
return metaFields.forEach((metaField) => {
if (metaField.fieldID?.startsWith(PAGE) || metaField.fieldID?.startsWith(PAGELIST)) {
metaField.fieldID = getFieldNameFromEmbeddedFieldName(metaField.fieldID);
}
});
}
/**
* [getConfigEmbeddedFieldsMeta]
* Description - Get the metadata for configured embedded fields
* @ignore
* @param {Set} configFields Set of config fields
* @param {string} classID clasID of datapage
* @returns {Array} Metadata of configured embedded fields
*/
export function getConfigEmbeddedFieldsMeta(configFields: any, classID: string) {
const configEmbeddedFieldsMeta: (object | null)[] = [];
configFields.forEach((field: any) => {
let value = field;
if (isEmbeddedField(value)) {
// conversion Page.PageList[].property => Page.PageList.property
if (value.includes('[')) {
value = value.substring(0, value.indexOf('[')) + value.substring(value.indexOf(']') + 1);
}
const meta: any = PCore.getMetadataUtils().getEmbeddedPropertyMetadata(value, classID);
meta.fieldID = field;
configEmbeddedFieldsMeta.push(meta);
}
});
return configEmbeddedFieldsMeta;
}
/**
* [mergeConfigEmbeddedFieldsMeta]
* Description - Get the metadata for configured embedded fields
* @ignore
* @param {Array} configEmbeddedFieldsMeta config fields metadata.
* @param {Array} metaFields Fields metadata Array. Contains metadata of all the fields
*/
export function mergeConfigEmbeddedFieldsMeta(configEmbeddedFieldsMeta: any[], metaFields: any[]) {
const mergedMetaFields = [...metaFields];
configEmbeddedFieldsMeta.forEach((configFieldMeta) => {
const fieldMeta = metaFields.find((metaField) => metaField.fieldID === configFieldMeta.fieldID);
if (!fieldMeta) mergedMetaFields.push(configFieldMeta);
});
return mergedMetaFields;
}
/**
* [preparePropertyValue]
* Description - Preparing pageList value from FILTERED_LIST annotation to Property annotation
* @ignore
* @param {string} value Pagelist value starts with FILTERED_LIST annotation
* @returns {string} returns converted string starting with Property annotation
*
* @example <caption>Example for preparePropertyValue </caption>
* preparePropertyValue('@FILTERED_LIST .Employees[].Name') return '@P .Employees.Name'
*/
// FIXME #EmbeddedPropertyPatch
// TODO: Remove this utility when we have nested response for queryable pageList and supports @FILTERED_LIST annotation
export function preparePropertyValue(value: any) {
if (value.startsWith(AT_FILTEREDLIST)) {
value = value.substring(value.indexOf(' ') + 1);
value = value.substring(0, value.indexOf('[')) + value.substring(value.indexOf(']') + 1);
value = `${AT_PROPERTY} ${value}`;
}
return value;
}
/**
* [updatePageListFieldsConfig]
* Description - updating configured pageList property's type and value
* @ignore
* @param {Array} configFields configured fields
*
* @example <caption>Modified config pageListField </caption>
*
{
"type": "ScalarList",
"config": {
"value": "@FILTERED_LIST .Employees[].Name",
"label": "@L Emp_Name",
"componentType": "TextInput",
"readOnly": true
}
}
modified to
{
"type": "TextInput",
"config": {
"value": "@P .Employees.Name",
"label": "@L Emp_Name",
"componentType": "TextInput",
"readOnly": true
}
}
*/
// FIXME #EmbeddedPropertyPatch
// TODO: Remove this utility when we have nested response for queryable pageList and supports scalarList component
export function updatePageListFieldsConfig(configFields: any[]) {
return configFields.forEach((item) => {
if (item.type === 'ScalarList') {
if (!item.config.originalValue) {
item.config.originalValue = item.config.value;
}
item.config.value = preparePropertyValue(item.config.value);
}
});
}
/**
* Update the renderer type for the properties of type Page.
*/
export function updatePageFieldsConfig(configFields: any[], parentClassID: string) {
return configFields.forEach((item) => {
const {
type,
config: { value }
} = item;
const propertyName = PCore.getAnnotationUtils().getPropertyName(value);
if (isEmbeddedField(value) && !isPageListInPath(propertyName, parentClassID)) {
item.config.componentType = type;
item.type = 'PagePropertyRenderer';
}
});
}
export function updateChangeSetValueKeys(changeSetObj: any, getOriginalProperty: any) {
const newChangeSetObject: any = {};
for (const [key, value] of Object.entries(changeSetObj)) {
let newKey = key;
if (newKey.startsWith(PAGE)) {
newKey = `.${getOriginalProperty(newKey)}`;
}
newChangeSetObject[newKey] = value;
}
return newChangeSetObject;
}
/**
* [isPageListProperty]
* Description - checking if propertyName is pageList or not
* @ignore
* @param {string} propertyName PropertyName
* @returns {boolean} true if property is pageList else false
*
* @example <caption>Example for isPageListProperty </caption>
* isPageListProperty('!PL!Employees.Name') return true
* isPageListProperty('!P!Employees.Name') return false
* isPageListProperty('Name') return false
*/
export function isPageListProperty(propertyName: string) {
return propertyName.startsWith(PAGELIST);
}
/**
* [preparePropertyMaps]
* Description - preparing maps for property names and set it in dataApi context
* @ignore
* @param {Array} fields fields array
* @param {string} classID classID of datapage
* @param {string} context dataApi context
* @returns {boolean} true if pageListProperty is present
*/
export function preparePropertyMaps(fields: any[], classID: string, context: string) {
const { setPropertyMaps } : any = context;
const maps = fields.reduce(
(acc, field) => {
let { value } = field.config;
if (value.startsWith('@')) {
value = value.substring(value.indexOf(' ') + 1);
if (value[0] === '.') value = value.substring(1);
}
let name = value;
// Preparing name for embedded property
if (isEmbeddedField(name)) {
name = getEmbeddedFieldName(name, classID);
}
if (isPageListProperty(name) && !acc[2]) {
acc[2] = true;
}
acc[0][value] = name;
acc[1][name] = value;
return acc;
},
[{}, {}, false]
);
setPropertyMaps(maps[0], maps[1]);
return maps[2];
}
/**
* [getPageListFields]
* Description - getting pageListFields names from the fields
* @ignore
* @param {Array} fields fields array
* @returns {Array} array of pageListFields name
*/
// FIXME #EmbeddedPropertyPatch
// TODO: Remove this utility when we have nested response for queryable pageList property
export function getPageListFields(fields: any[]) {
const parentPaths = new Set();
const pageListFields: any = [];
fields.forEach((field) => {
const { name } = field;
if (isPageListProperty(name)) {
const parentPath = name.substring(0, name.lastIndexOf(':'));
if (!parentPaths.has(parentPath)) {
parentPaths.add(parentPath);
pageListFields.push(name);
}
}
});
return pageListFields;
}
export function mergePageListFieldAggregation(
pageListName :string,
select: { aggregation: string; }[],
existingAggregations: { [x: string]: { field: string; summaryFunction: string; }; },
existingAggregationsName: string | string[]) {
// Build a dummy genericAggregationId to check if any type of aggregation for that pagelist is included in existing aggregations.
const genericAggregationId = buildAggOrCalcId(pageListName, '');
if (existingAggregationsName.includes(genericAggregationId)) {
return;
}
const countAggregationId = buildAggOrCalcId(pageListName, 'COUNT');
select.push({ aggregation: countAggregationId });
existingAggregations[countAggregationId] = { field: pageListName, summaryFunction: 'COUNT' };
}
export function mergePageListFieldsAggregation(fields: any[], select: { aggregation: string; }[], existingAggregations: { [x: string]: { field: string; summaryFunction: string; }; }) {
const parentPaths = new Set();
const existingAggregationsName = Object.keys(existingAggregations).toString();
const pageListFields: any[] = [];
fields.forEach((field) => {
const { name } = field;
if (isPageListProperty(name)) {
const parentPath = name.substring(0, name.lastIndexOf(':'));
if (!parentPaths.has(parentPath)) {
parentPaths.add(parentPath);
pageListFields.push(name);
mergePageListFieldAggregation(name, select, existingAggregations, existingAggregationsName);
}
}
});
return pageListFields;
}
/**
* [hasPageListProperty]
* Description - getting pageListFields names from the fields
* @ignore
* @param {Array} fieldDefs fields array
* @returns {object | undefined} value of first pageListProperty found
*/
export function hasPageListProperty(fieldDefs: any[]) {
return fieldDefs?.find((field) => isPageListProperty(field.name));
}