UNPKG

@itwin/presentation-frontend

Version:

Frontend of iModel.js Presentation library

643 lines • 30.6 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Core */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createFieldOrderInfos = exports.getFieldInfos = exports.FavoritePropertiesManager = exports.FavoritePropertiesScope = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const IModelConnectionInitialization_js_1 = require("../IModelConnectionInitialization.js"); /** * Scopes that favorite properties can be stored in. * @public */ var FavoritePropertiesScope; (function (FavoritePropertiesScope) { FavoritePropertiesScope[FavoritePropertiesScope["Global"] = 0] = "Global"; FavoritePropertiesScope[FavoritePropertiesScope["ITwin"] = 1] = "ITwin"; FavoritePropertiesScope[FavoritePropertiesScope["IModel"] = 2] = "IModel"; })(FavoritePropertiesScope || (exports.FavoritePropertiesScope = FavoritePropertiesScope = {})); /** * The favorite property manager which lets to store favorite properties * and check if field contains favorite properties. * * @public */ class FavoritePropertiesManager { /** Event raised after favorite properties have changed. */ onFavoritesChanged = new core_bentley_1.BeEvent(); storage; _globalProperties; _iTwinProperties; _imodelProperties; _imodelBaseClassesByClass; _imodelInitializationPromises; _imodelInitializationHandler; /** Property order is saved only in iModel scope */ _propertiesOrder; constructor(props) { this.storage = props.storage; this._iTwinProperties = new Map(); this._imodelProperties = new Map(); this._propertiesOrder = new Map(); this._imodelBaseClassesByClass = new Map(); this._imodelInitializationPromises = new Map(); IModelConnectionInitialization_js_1.imodelInitializationHandlers.add((this._imodelInitializationHandler = { startInitialization: (imodel) => this.startConnectionInitialization(imodel), ensureInitialized: async (imodel) => this.ensureInitialized(imodel), })); } [Symbol.dispose]() { IModelConnectionInitialization_js_1.imodelInitializationHandlers.delete(this._imodelInitializationHandler); if ((0, core_bentley_1.isDisposable)(this.storage)) { this.storage[Symbol.dispose](); /* c8 ignore next 4 */ /* eslint-disable-next-line @typescript-eslint/no-deprecated */ } else if ((0, core_bentley_1.isIDisposable)(this.storage)) { this.storage.dispose(); } } /** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */ /* c8 ignore next 3 */ dispose() { this[Symbol.dispose](); } /** * Initialize favorite properties for the provided IModelConnection. * @deprecated in 4.5 - will not be removed until after 2026-06-13. Initialization is performed automatically by all async methods and only needed for deprecated [[FavoritePropertiesManager.has]] and [[FavoritePropertiesManager.sortFields]]. */ initializeConnection = async (imodel) => { const imodelId = imodel.iModelId; const iTwinId = imodel.iTwinId; if (this._globalProperties === undefined) { this._globalProperties = (await this.storage.loadProperties()) || new Set(); } if (!this._iTwinProperties.has(iTwinId)) { const iTwinProperties = (await this.storage.loadProperties(iTwinId)) || new Set(); this._iTwinProperties.set(iTwinId, iTwinProperties); } if (!this._imodelProperties.has(getiModelInfo(iTwinId, imodelId))) { const imodelProperties = (await this.storage.loadProperties(iTwinId, imodelId)) || new Set(); this._imodelProperties.set(getiModelInfo(iTwinId, imodelId), imodelProperties); } const propertiesOrder = (await this.storage.loadPropertiesOrder(iTwinId, imodelId)) || []; this._propertiesOrder.set(getiModelInfo(iTwinId, imodelId), propertiesOrder); await this._adjustPropertyOrderInfos(iTwinId, imodelId); }; /** * Function that removes order information of properties that are no longer * favorited and adds missing order information for favorited properties. */ _adjustPropertyOrderInfos = async (iTwinId, imodelId) => { const propertiesOrder = this._propertiesOrder.get(getiModelInfo(iTwinId, imodelId)); const globalProperties = this._globalProperties; const iTwinProperties = this._iTwinProperties.get(iTwinId); const imodelProperties = this._imodelProperties.get(getiModelInfo(iTwinId, imodelId)); // favorite property infos that need to be added to the propertiesOrder array const infosToAdd = new Set([...globalProperties, ...iTwinProperties, ...imodelProperties]); for (let i = propertiesOrder.length - 1; i >= 0; i--) { if (infosToAdd.has(propertiesOrder[i].name)) { infosToAdd.delete(propertiesOrder[i].name); } else { propertiesOrder.splice(i, 1); } } infosToAdd.forEach((info) => propertiesOrder.push({ name: info, parentClassName: getPropertyClassName(info), orderedTimestamp: new Date(), priority: 0, })); let priority = propertiesOrder.length; propertiesOrder.forEach((oi) => (oi.priority = priority--)); }; isInitialized(imodel) { const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; return this._imodelProperties.has(getiModelInfo(iTwinId, imodelId)); } /** * Checks if [[FavoritePropertiesManager.initializeConnection]] has been called for a given imodel. * Can be removed when [[FavoritePropertiesManager.has]] and [[FavoritePropertiesManager.sortFields]] are removed. */ validateInitialization(imodel) { const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; if (!this.isInitialized(imodel)) { throw Error(`Favorite properties are not initialized for iModel: '${imodelId}', in iTwin: '${iTwinId}'. Call initializeConnection() with an IModelConnection to initialize.`); } } startConnectionInitialization(imodel) { if (!this.isInitialized(imodel) && !this._imodelInitializationPromises.has(imodel)) { // eslint-disable-next-line @typescript-eslint/no-deprecated this._imodelInitializationPromises.set(imodel, this.initializeConnection(imodel)); } } async ensureInitialized(imodel) { if (this.isInitialized(imodel)) { return; } let promise = this._imodelInitializationPromises.get(imodel); if (!promise) { // eslint-disable-next-line @typescript-eslint/no-deprecated promise = this.initializeConnection(imodel); // Put the promise in the map to avoid possible multiple initializations from different promises. this._imodelInitializationPromises.set(imodel, promise); } await promise; // Remove this promise from the map, because the next time this method is called, `this.isInitialized` should return true. this._imodelInitializationPromises.delete(imodel); } /** * Adds favorite properties into a certain scope. * @param field Field that contains properties. If field contains multiple properties, all of them will be favorited. * @param imodel IModelConnection. * @param scope FavoritePropertiesScope to put the favorite properties into. */ async add(field, imodel, scope) { await this.ensureInitialized(imodel); const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; let favoriteProperties; let saveProperties; switch (scope) { case FavoritePropertiesScope.Global: favoriteProperties = this._globalProperties; saveProperties = async (properties) => this.storage.saveProperties(properties); break; case FavoritePropertiesScope.ITwin: favoriteProperties = this._iTwinProperties.get(iTwinId); saveProperties = async (properties) => this.storage.saveProperties(properties, iTwinId); break; default: favoriteProperties = this._imodelProperties.get(getiModelInfo(iTwinId, imodelId)); saveProperties = async (properties) => this.storage.saveProperties(properties, iTwinId, imodelId); } const countBefore = favoriteProperties.size; const fieldInfos = (0, exports.getFieldInfos)(field); fieldInfos.forEach((info) => favoriteProperties.add(info)); if (favoriteProperties.size !== countBefore) { const saves = []; saves.push(saveProperties(favoriteProperties)); const propertiesOrder = this._propertiesOrder.get(getiModelInfo(iTwinId, imodelId)); addOrderInfos(propertiesOrder, (0, exports.createFieldOrderInfos)(field)); saves.push(this.storage.savePropertiesOrder(propertiesOrder, iTwinId, imodelId)); await Promise.all(saves); this.onFavoritesChanged.raiseEvent(); } } /** * Removes favorite properties from a scope specified and all the more general scopes. * @param field Field that contains properties. If field contains multiple properties, all of them will be un-favorited. * @param imodel IModelConnection. * @param scope FavoritePropertiesScope to remove the favorite properties from. It also removes from more general scopes. */ async remove(field, imodel, scope) { await this.ensureInitialized(imodel); const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; const fieldInfos = (0, exports.getFieldInfos)(field); const workingScopes = []; workingScopes.push({ properties: this._globalProperties, save: async (properties) => this.storage.saveProperties(properties), }); if (scope === FavoritePropertiesScope.ITwin || scope === FavoritePropertiesScope.IModel) { workingScopes.push({ properties: this._iTwinProperties.get(iTwinId), save: async (properties) => this.storage.saveProperties(properties, iTwinId), }); } if (scope === FavoritePropertiesScope.IModel) { workingScopes.push({ properties: this._imodelProperties.get(getiModelInfo(iTwinId, imodelId)), save: async (properties) => this.storage.saveProperties(properties, iTwinId, imodelId), }); } const saves = []; let favoritesChanged = false; for (const { properties, save } of workingScopes) { const countBefore = properties.size; fieldInfos.forEach((info) => properties.delete(info)); if (properties.size !== countBefore) { saves.push(save(properties)); favoritesChanged = true; } } if (!favoritesChanged) { return; } const propertiesOrder = this._propertiesOrder.get(getiModelInfo(iTwinId, imodelId)); removeOrderInfos(propertiesOrder, (0, exports.createFieldOrderInfos)(field)); saves.push(this.storage.savePropertiesOrder(propertiesOrder, iTwinId, imodelId)); await Promise.all(saves); this.onFavoritesChanged.raiseEvent(); } /** * Removes all favorite properties from a certain scope. * @param imodel IModelConnection. * @param scope FavoritePropertiesScope to remove the favorite properties from. */ async clear(imodel, scope) { await this.ensureInitialized(imodel); const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; let favoriteProperties; let saveProperties; switch (scope) { case FavoritePropertiesScope.Global: favoriteProperties = this._globalProperties; saveProperties = async () => this.storage.saveProperties(new Set()); break; case FavoritePropertiesScope.ITwin: favoriteProperties = this._iTwinProperties.get(iTwinId); saveProperties = async () => this.storage.saveProperties(new Set(), iTwinId); break; default: favoriteProperties = this._imodelProperties.get(getiModelInfo(iTwinId, imodelId)); saveProperties = async () => this.storage.saveProperties(new Set(), iTwinId, imodelId); } if (favoriteProperties.size === 0) { return; } favoriteProperties.clear(); const saves = []; saves.push(saveProperties()); saves.push(this._adjustPropertyOrderInfos(iTwinId, imodelId)); await Promise.all(saves); this.onFavoritesChanged.raiseEvent(); } /** * Check if field contains at least one favorite property. * @param field Field that contains properties. * @param imodel IModelConnection. * @param scope FavoritePropertiesScope to check for favorite properties. It also checks the more general scopes. * @note `initializeConnection` must be called with the `imodel` before calling this function. * @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[FavoritePropertiesManager.hasAsync]] instead. This method is not async, therefore it requires early initialization by calling [[FavoritePropertiesManager.initializeConnection]]. */ has(field, imodel, scope) { this.validateInitialization(imodel); const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; const fieldInfos = (0, exports.getFieldInfos)(field); return (setHasAny(this._globalProperties, fieldInfos) || (scope !== FavoritePropertiesScope.Global && setHasAny(this._iTwinProperties.get(iTwinId), fieldInfos)) || (scope === FavoritePropertiesScope.IModel && setHasAny(this._imodelProperties.get(getiModelInfo(iTwinId, imodelId)), fieldInfos))); } /** * Check if field contains at least one favorite property. * @param field Field that contains properties. * @param imodel IModelConnection. * @param scope FavoritePropertiesScope to check for favorite properties. It also checks the more general scopes. */ async hasAsync(field, imodel, scope) { await this.ensureInitialized(imodel); // eslint-disable-next-line @typescript-eslint/no-deprecated return this.has(field, imodel, scope); } /** * Sorts an array of fields with respect to favorite property order. * Non-favorited fields get sorted by their default priority and always have lower priority than favorited fields. * @param imodel IModelConnection. * @param fields Array of Field's that needs to be sorted. * @note `initializeConnection` must be called with the `imodel` before calling this function. * @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[FavoritePropertiesManager.sortFieldsAsync]] instead. This method is not async, therefore it requires early initialization by calling [[FavoritePropertiesManager.initializeConnection]]. */ sortFields = (imodel, fields) => { this.validateInitialization(imodel); const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; const fieldPriority = new Map(); fields.forEach((field) => fieldPriority.set(field, this.getFieldPriority(field, iTwinId, imodelId))); const sortFunction = (left, right) => { const lp = fieldPriority.get(left); const rp = fieldPriority.get(right); return lp < rp ? 1 : lp > rp ? -1 : left.priority < right.priority ? 1 // if favorite fields have equal priorities, sort by field priority : left.priority > right.priority ? -1 : left.name.localeCompare(right.name); }; return fields.sort(sortFunction); }; /** * Sorts an array of fields with respect to favorite property order. * Non-favorited fields get sorted by their default priority and always have lower priority than favorited fields. * @param imodel IModelConnection. * @param fields Array of Field's that needs to be sorted. */ async sortFieldsAsync(imodel, fields) { await this.ensureInitialized(imodel); // eslint-disable-next-line @typescript-eslint/no-deprecated return this.sortFields(imodel, fields); } getFieldPriority(field, iTwinId, imodelId) { const orderInfos = this._propertiesOrder.get(getiModelInfo(iTwinId, imodelId)); const fieldOrderInfos = getFieldOrderInfos(field, orderInfos); if (fieldOrderInfos.length === 0) { return -1; } const mostRecent = getMostRecentOrderInfo(fieldOrderInfos); return mostRecent.priority; } _getBaseClassesByClass = async (imodel, neededClasses) => { const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; const imodelInfo = getiModelInfo(iTwinId, imodelId); let baseClasses; if (this._imodelBaseClassesByClass.has(imodelInfo)) { baseClasses = this._imodelBaseClassesByClass.get(imodelInfo); } else { this._imodelBaseClassesByClass.set(imodelInfo, (baseClasses = {})); } const missingClasses = new Set(); neededClasses.forEach((className) => { if (!baseClasses.hasOwnProperty(className)) { missingClasses.add(className); } }); if (missingClasses.size === 0) { return baseClasses; } const query = ` SELECT (derivedSchema.Name || ':' || derivedClass.Name) AS "ClassFullName", (baseSchema.Name || ':' || baseClass.Name) AS "BaseClassFullName" FROM ECDbMeta.ClassHasAllBaseClasses baseClassRels INNER JOIN ECDbMeta.ECClassDef derivedClass ON derivedClass.ECInstanceId = baseClassRels.SourceECInstanceId INNER JOIN ECDbMeta.ECSchemaDef derivedSchema ON derivedSchema.ECInstanceId = derivedClass.Schema.Id INNER JOIN ECDbMeta.ECClassDef baseClass ON baseClass.ECInstanceId = baseClassRels.TargetECInstanceId INNER JOIN ECDbMeta.ECSchemaDef baseSchema ON baseSchema.ECInstanceId = baseClass.Schema.Id WHERE (derivedSchema.Name || ':' || derivedClass.Name) IN (${[...missingClasses].map((className) => `'${className}'`).join(",")})`; const reader = imodel.createQueryReader(query, undefined, { rowFormat: core_common_1.QueryRowFormat.UseJsPropertyNames }); while (await reader.step()) { const row = reader.current.toRow(); if (!(row.classFullName in baseClasses)) { baseClasses[row.classFullName] = []; } baseClasses[row.classFullName].push(row.baseClassFullName); } return baseClasses; }; /** Changes field properties priorities to lower than another fields priority * @param imodel IModelConnection. * @param field Field that priority is being changed. * @param afterField Field that goes before the moved field. If undefined the moving field is changed to the highest priority (to the top). * @param visibleFields Array of fields to move the field in. */ async changeFieldPriority(imodel, field, afterField, visibleFields) { /** * How it works: * 1. Gets the orderInfo's for `field` (`orderInfo`) and `afterField` (`afterOrderInfo`) by selecting the most recent order informations for each field * 2. Iterates all orderInfo's that are in between `afterOrderInfo` and `orderInfo` when sorted by priority * 3. For each iterated orderInfo it checks if it is relevant: * 3.1. If orderInfo belongs to a primitive property, orderInfo is relevant * 3.2. If orderInfo's field is visible, orderInfo is relevant * 3.3. If orderInfo's class has a base class or itself in previously labeled relevant orderInfo's, orderInfo is relevant * 3.4. If 3.1 - 3.3 don't pass, orderInfo is irrelevant * 4. Irrelevant orderInfos's get moved after `orderInfo` (depends on the direction) * 5. All `field` orderInfo's get moved after `afterOrderInfo` */ await this.ensureInitialized(imodel); const iTwinId = imodel.iTwinId; const imodelId = imodel.iModelId; if (field === afterField) { throw Error("`field` can not be the same as `afterField`."); } const allOrderInfos = this._propertiesOrder.get(getiModelInfo(iTwinId, imodelId)); const findFieldOrderInfoData = (f) => { if (!visibleFields.includes(f)) { throw Error("Field is not contained in visible fields."); } const infos = getFieldOrderInfos(f, allOrderInfos); if (infos.length === 0) { throw Error("Field has no property order information."); } const info = getMostRecentOrderInfo(infos); const index = allOrderInfos.indexOf(info); return { infos, mostRecent: { info, index } }; }; const { infos: movingOrderInfos, mostRecent: { index: orderInfoIndex }, } = findFieldOrderInfoData(field); let afterOrderInfo; let afterOrderInfoIndex; if (afterField === undefined) { afterOrderInfo = undefined; afterOrderInfoIndex = -1; } else { ({ mostRecent: { info: afterOrderInfo, index: afterOrderInfoIndex }, } = findFieldOrderInfoData(afterField)); } let direction; // where to go from `afterOrderInfo` to `orderInfo` let startIndex; if (orderInfoIndex < afterOrderInfoIndex) { direction = Direction.Up; startIndex = afterOrderInfoIndex; } else { direction = Direction.Down; startIndex = afterOrderInfoIndex + 1; } const neededClassNames = allOrderInfos.reduce((classNames, oi) => { if (oi.parentClassName) { classNames.add(oi.parentClassName); } return classNames; }, new Set()); const baseClassesByClass = await this._getBaseClassesByClass(imodel, neededClassNames); const visibleOrderInfos = visibleFields.reduce((union, currField) => union.concat(getFieldOrderInfos(currField, allOrderInfos)), []); const irrelevantOrderInfos = []; // orderInfos's that won't change their logical order in respect to other properties const relevantClasses = new Set(); // currently relevant classes for (let i = startIndex; i !== orderInfoIndex; i += direction) { const currOrderInfo = allOrderInfos[i]; // primitive properties are always relevant, because we can't determine their relevance based on the class hierarchy if (currOrderInfo.parentClassName === undefined) { continue; } const visible = visibleOrderInfos.includes(currOrderInfo); if (visible) { relevantClasses.add(currOrderInfo.parentClassName); continue; } const hasBaseClasses = baseClassesByClass[currOrderInfo.parentClassName].some((classId) => relevantClasses.has(classId)); if (hasBaseClasses) { continue; } if (direction === Direction.Down) { irrelevantOrderInfos.push(currOrderInfo); } else { irrelevantOrderInfos.unshift(currOrderInfo); } } // remove irrelevantOrderInfo's to add them after the `orderInfo` irrelevantOrderInfos.forEach((foi) => { const index = allOrderInfos.findIndex((oi) => oi.parentClassName === foi.parentClassName && oi.name === foi.name); allOrderInfos.splice(index, 1); }); // remove movingOrderInfos's to add them after the `afterOrderInfo` movingOrderInfos.forEach((foi) => { const index = allOrderInfos.findIndex((oi) => oi.parentClassName === foi.parentClassName && oi.name === foi.name); allOrderInfos.splice(index, 1); }); movingOrderInfos.forEach((oi) => (oi.orderedTimestamp = new Date())); afterOrderInfoIndex = afterOrderInfo === undefined ? -1 : allOrderInfos.indexOf(afterOrderInfo); allOrderInfos.splice(afterOrderInfoIndex + 1, 0, ...movingOrderInfos); allOrderInfos.splice(afterOrderInfoIndex + 1 + (direction === Direction.Up ? movingOrderInfos.length : 0), 0, ...irrelevantOrderInfos); // reassign priority numbers let priority = allOrderInfos.length; allOrderInfos.forEach((oi) => (oi.priority = priority--)); await this.storage.savePropertiesOrder(allOrderInfos, iTwinId, imodelId); this.onFavoritesChanged.raiseEvent(); } } exports.FavoritePropertiesManager = FavoritePropertiesManager; var Direction; (function (Direction) { Direction[Direction["Up"] = -1] = "Up"; Direction[Direction["Down"] = 1] = "Down"; })(Direction || (Direction = {})); const getiModelInfo = (iTwinId, imodelId) => `${iTwinId}/${imodelId}`; const getPropertiesFieldPropertyNames = (field) => { const nestingPrefix = getNestingPrefix(field.parent); return field.properties.map((property) => `${nestingPrefix}${property.property.classInfo.name}:${property.property.name}`); }; const getNestedContentFieldPropertyName = (field) => { const nestingPrefix = getNestingPrefix(field); return `${nestingPrefix}${field.contentClassInfo.name}`; }; const getNestingPrefix = (field) => { const path = []; let curr = field; while (curr !== undefined) { curr.pathToPrimaryClass.forEach((rel) => { // Relationship directions are reversed, because we are generating a relationship list starting from the parent path.push(`${rel.isForwardRelationship ? "B" : "F"}:${rel.relationshipInfo.name}`); path.push(rel.targetClassInfo.name); }); curr = curr.parent; } if (path.length === 0) { return ""; } path.reverse(); return `${path.join("-")}-`; }; const getPropertyClassName = (propertyName) => { const propertyNameStart = propertyName.split("-")[0]; const parts = propertyNameStart.split(":").length; if (parts === 1) { // primitive return undefined; } if (parts === 2) { // nested property OR nested property parent class OR regular property parent class return propertyNameStart; } // regular property without parent class return propertyNameStart.substring(0, propertyName.lastIndexOf(":")); }; /** @internal */ const getFieldInfos = (field) => { const fieldInfos = new Set(); if (field.isPropertiesField()) { getPropertiesFieldPropertyNames(field).forEach((info) => fieldInfos.add(info)); } else if (field.isNestedContentField()) { fieldInfos.add(getNestedContentFieldPropertyName(field)); } else { fieldInfos.add(field.name); } return fieldInfos; }; exports.getFieldInfos = getFieldInfos; const setHasAny = (set, lookup) => { for (const key of lookup) { if (set.has(key)) { return true; } } return false; }; const addOrderInfos = (dest, source) => { source.forEach((si) => { const index = dest.findIndex((di) => di.name === si.name); if (index === -1) { si.orderedTimestamp = new Date(); dest.push(si); } }); let priority = dest.length; dest.forEach((info) => (info.priority = priority--)); }; const removeOrderInfos = (container, toRemove) => { toRemove.forEach((roi) => { const index = container.findIndex((oi) => oi.name === roi.name); if (index >= 0) { container.splice(index, 1); } }); }; /** @internal */ const createFieldOrderInfos = (field) => { if (field.isNestedContentField()) { const propertyName = getNestedContentFieldPropertyName(field); return [ { parentClassName: getPropertyClassName(propertyName), name: propertyName, priority: 0, orderedTimestamp: new Date(), }, ]; } if (field.isPropertiesField()) { return getPropertiesFieldPropertyNames(field).map((propertyName) => ({ parentClassName: getPropertyClassName(propertyName), name: propertyName, priority: 0, orderedTimestamp: new Date(), })); } return [ { parentClassName: undefined, name: field.name, priority: 0, orderedTimestamp: new Date(), }, ]; }; exports.createFieldOrderInfos = createFieldOrderInfos; const getFieldOrderInfos = (field, orderInfos) => { const fieldOrderInfos = []; const tryAddOrderInfo = (name) => { const fieldOrderInfo = orderInfos.find((oi) => oi.name === name); if (fieldOrderInfo !== undefined) { fieldOrderInfos.push(fieldOrderInfo); } }; if (field.isPropertiesField()) { getPropertiesFieldPropertyNames(field).forEach(tryAddOrderInfo); } else if (field.isNestedContentField()) { tryAddOrderInfo(getNestedContentFieldPropertyName(field)); } else { tryAddOrderInfo(field.name); } return fieldOrderInfos; }; const getMostRecentOrderInfo = (orderInfos) => orderInfos.reduce((recent, curr) => (recent && recent.orderedTimestamp >= curr.orderedTimestamp ? recent : curr)); //# sourceMappingURL=FavoritePropertiesManager.js.map