@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
170 lines • 7.73 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module InstancesFilter
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.INSTANCE_FILTER_FIELD_SEPARATOR = exports.DEFAULT_ROOT_CATEGORY_NAME = void 0;
exports.createInstanceFilterPropertyInfos = createInstanceFilterPropertyInfos;
exports.getInstanceFilterFieldName = getInstanceFilterFieldName;
exports.createPropertyInfoFromPropertiesField = createPropertyInfoFromPropertiesField;
exports.isFilterNonEmpty = isFilterNonEmpty;
exports.useFilterBuilderNavigationPropertyEditorContextProviderProps = useFilterBuilderNavigationPropertyEditorContextProviderProps;
exports.filterRuleValidator = filterRuleValidator;
const react_1 = require("react");
const appui_abstract_1 = require("@itwin/appui-abstract");
const components_react_1 = require("@itwin/components-react");
const presentation_common_1 = require("@itwin/presentation-common");
const ContentBuilder_js_1 = require("../common/ContentBuilder.js");
const Utils_js_1 = require("../common/Utils.js");
/** @internal */
function createInstanceFilterPropertyInfos(descriptor) {
const propertyInfos = new Array();
for (const field of descriptor.fields) {
propertyInfos.push(...createPropertyInfos(field));
}
return propertyInfos;
}
/** @internal */
function getInstanceFilterFieldName(property) {
const [_, fieldName] = property.name.split(exports.INSTANCE_FILTER_FIELD_SEPARATOR);
return fieldName;
}
/** @internal */
exports.DEFAULT_ROOT_CATEGORY_NAME = "/selected-item/";
function getPropertySourceClassInfos(field) {
if (field.parent) {
return getPropertySourceClassInfos(field.parent);
}
if (field.isPropertiesField()) {
return field.properties.map((fieldProperty) => fieldProperty.property.classInfo);
}
return [field.pathToPrimaryClass[field.pathToPrimaryClass.length - 1].targetClassInfo];
}
function getPropertyClassInfo(field) {
if (field.parent && field.parent.isNestedContentField()) {
return field.parent.contentClassInfo;
}
return field.properties[0].property.classInfo;
}
function createPropertyInfos(field) {
if (field.isNestedContentField()) {
return field.nestedFields.flatMap((nestedField) => createPropertyInfos(nestedField));
}
if (field.isPropertiesField()) {
return [createPropertyInfoFromPropertiesField(field)];
}
/* c8 ignore next 3 */
return [];
}
function getCategoryInfo(category, categoryInfo) {
if (category.name === exports.DEFAULT_ROOT_CATEGORY_NAME) {
return categoryInfo;
}
const newInfo = {
name: categoryInfo.name ? `${category.name}/${categoryInfo.name}` : `${category.name}`,
label: categoryInfo.label ? `${category.label} | ${categoryInfo.label}` : `${category.label}`,
};
return category.parent ? getCategoryInfo(category.parent, newInfo) : newInfo;
}
function getParentNames(field, name) {
if (!field.parent) {
return (0, presentation_common_1.combineFieldNames)(name, field.name);
}
return getParentNames(field.parent, (0, presentation_common_1.combineFieldNames)(name, field.name));
}
/** @internal */
function createPropertyInfoFromPropertiesField(field) {
const categoryInfo = getCategoryInfo(field.category, { name: undefined, label: undefined });
const name = field.parent ? getParentNames(field.parent, field.name) : field.name;
const propertyDescription = (0, ContentBuilder_js_1.createPropertyDescriptionFromFieldInfo)({
...(0, ContentBuilder_js_1.createFieldInfo)(field),
name: getCategorizedFieldName(name, categoryInfo.name),
});
const sourceClassIds = getPropertySourceClassInfos(field).map((classInfo) => classInfo.id);
return {
field,
sourceClassIds,
sourceClassId: sourceClassIds[0],
propertyDescription,
categoryLabel: categoryInfo.label,
className: getPropertyClassInfo(field).name,
};
}
/** @internal */
function isFilterNonEmpty(rootGroup) {
return rootGroup.items.length > 1 || (rootGroup.items.length === 1 && rootGroup.items[0].operator !== undefined);
}
/** @internal */
exports.INSTANCE_FILTER_FIELD_SEPARATOR = "#";
function getCategorizedFieldName(fieldName, categoryName) {
return `${categoryName ?? ""}${exports.INSTANCE_FILTER_FIELD_SEPARATOR}${fieldName}`;
}
/** @internal */
function useFilterBuilderNavigationPropertyEditorContextProviderProps(imodel, descriptor) {
return (0, react_1.useMemo)(() => ({
imodel,
getNavigationPropertyInfo: async (property) => {
const field = descriptor.getFieldByName(getInstanceFilterFieldName(property));
if (!field || !field.isPropertiesField()) {
return undefined;
}
return field.properties[0].property.navigationPropertyInfo;
},
}), [imodel, descriptor]);
}
/** @internal */
function filterRuleValidator(item) {
// skip empty rules and rules that do not require value
if (item.property === undefined || item.operator === undefined || (0, components_react_1.isUnaryPropertyFilterBuilderOperator)(item.operator)) {
return undefined;
}
/* c8 ignore next 3 */
if (item.value !== undefined && item.value.valueFormat !== appui_abstract_1.PropertyValueFormat.Primitive) {
return undefined;
}
const error = numericPropertyValidator({
property: item.property,
operator: item.operator,
value: item.value,
});
if (error) {
return error;
}
// TODO: refactor to `useDefaultPropertyFilterBuilderRuleValidator` after AppUI peer dep bumped to 5.0
// eslint-disable-next-line @typescript-eslint/no-deprecated
return (0, components_react_1.defaultPropertyFilterBuilderRuleValidator)(item);
}
function numericPropertyValidator({ property, value, operator }) {
// If equality operator is set the value should not be validated since it is supplied by the `UniquePropertyValuesSelector`.
if (!isPropertyNumeric(property.typename) || value === undefined || isEqualityOperator(operator)) {
return undefined;
}
function getErrorMessage() {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return property.kindOfQuantityName === undefined && property.quantityType === undefined
? (0, Utils_js_1.translate)("instance-filter-builder.error-messages.not-a-number")
: (0, Utils_js_1.translate)("instance-filter-builder.error-messages.invalid");
}
if (operator === "between") {
const { from, to } = components_react_1.PropertyFilterBuilderRuleRangeValue.parse(value);
return isInvalidNumericValue(from) || isInvalidNumericValue(to) ? getErrorMessage() : undefined;
}
if (isInvalidNumericValue(value)) {
return getErrorMessage();
}
return undefined;
}
function isEqualityOperator(operator) {
return operator === "is-equal" || operator === "is-not-equal";
}
function isPropertyNumeric(typename) {
return (typename === appui_abstract_1.StandardTypeNames.Number || typename === appui_abstract_1.StandardTypeNames.Int || typename === appui_abstract_1.StandardTypeNames.Float || typename === appui_abstract_1.StandardTypeNames.Double);
}
function isInvalidNumericValue(value) {
return value.displayValue && isNaN(Number(value.value));
}
//# sourceMappingURL=Utils.js.map