UNPKG

outsystems-ui

Version:
208 lines (186 loc) 7.19 kB
/// <reference path="AbstractPattern.ts" /> // eslint-disable-next-line @typescript-eslint/no-unused-vars namespace OSFramework.OSUI.Patterns { /** * Defines the Default props and methods for Patterns that will have other Patterns as its childs * * @export * @abstract * @class AbstractParent * @implements {Interface.IParent} * @template {C extends AbstractConfiguration, CT extends Interface.IChild} */ export abstract class AbstractParent<C extends AbstractConfiguration, CT extends Interface.IChild> extends AbstractPattern<C> implements Interface.IParent { // Store a collection about all the child items <childId, childType> in the parent scope private _childIdsByType: Map<string, string> = new Map<string, string>(); // Associative Array that will contain the childType as keyName and a map with all childs of same type! private _childItemsByType = {}; /** * Get the child reference based on given Id * * @protected * @param childId Child Id of the element to be found * @returns Child Reference * @memberof OSFramework.Patterns.AbstractParent */ protected getChild(childId: string): CT { // Get ChildType const childType = this._childIdsByType.get(childId); // Check if there are childs of the given ChildId type! if (this._childItemsByType[childType]) { return this._childItemsByType[childType].get(childId); } else { return undefined; } } /** * Get a child reference by a given Index position * * @protected * @param index Index of the item to be returned * @param childType To be based on childType childs collection, otherwise will assume parent only contains one child type! * @returns Child Reference * @memberof OSFramework.Patterns.AbstractParent */ protected getChildByIndex(index: number, childType?: string): CT { // If childType undefined, get the first key object name! if (childType === undefined) { childType = Object.keys(this._childItemsByType)[0]; } // Get the correct map based on the given childType const childsMap = this._childItemsByType[childType]; return childsMap ? this.getChild(Helper.MapOperation.ExportKeys(childsMap)[index]) : undefined; } /** * Get a child index from a given child Id * * @protected * @param childId Child id where index will be found * @returns Index value * @memberof OSFramework.Patterns.AbstractParent */ protected getChildIndex(childId: string): number { // Get ChildType const childType = this._childIdsByType.get(childId); // Get the correct map based on the given childType const childsMap = this._childItemsByType[childType]; return Helper.MapOperation.ExportKeys(childsMap).indexOf(childId); } /** * Method that is used to set a given child as a Parent child. * * @protected * @param childId Id that should be added * @param childItem Reference to be added * @memberof OSFramework.Patterns.AbstractParent */ protected setChild(childItem: CT): void { const childType = childItem.constructor.name; if (this._childItemsByType[childType] === undefined) { this._childItemsByType[childType] = new Map<string, CT>(); } // Check if we have no items yet if (this._childItemsByType[childType].size === 0) { // Set item as First and Last child childItem.isFirstChild = true; childItem.isLastChild = true; } else { // Since we've more than one child, get the previous and unset it as lastChild this.getChildByIndex(this._childItemsByType[childType].size - 1, childType).isLastChild = false; // Set the current one as lastChild childItem.isLastChild = true; } // Set the child into the global _childIdsByType this._childIdsByType.set(childItem.uniqueId, childType); // Set the given child into the map with the same type this._childItemsByType[childType].set(childItem.uniqueId, childItem); } /** * Method that will remove Child by given Id * * @protected * @param childId Id of the item that will be removed * @memberof OSFramework.Patterns.AbstractParent */ protected unsetChild(childId: string): void { // Get ChildType const childType = this._childIdsByType.get(childId); if (childType === undefined) { // Was not able to get type! throw new Error( `${ErrorCodes.AbstractParent.FailTypeNotFound}:Child Type of Child ('${childId}') was not found!` ); } // Get the correct map based on the given childType const childsMap = this._childItemsByType[childType]; if (childsMap === undefined) { // Was not able to get childs of type! throw new Error( `${ErrorCodes.AbstractParent.FailChildsNotFound}:Childs of Type ('${childType}') were not found!` ); } // Get the child reference const childItem = this.getChild(childId); if (childItem === undefined) { // Was not able to get child by id! throw new Error( `${ErrorCodes.AbstractParent.FailChildNotFound}:Child of Id ('${childId}') was not found!` ); } // Check if it's the firstChild if (childItem.isFirstChild) { // unSet it as firstChild childItem.isFirstChild = false; // Set the 2nd child as firsChild since it will turns into the first one! const nextSibling = this.getChildByIndex(1, childType); if (nextSibling) { nextSibling.isFirstChild = true; } } // Check if it's the lastChild if (childItem.isLastChild) { // unSet it as lastChild childItem.isLastChild = false; // Set the previous child as lastChild since it will turns into the last one! // The current last child (childsMap.size - 1), the prevSibling will be the child before (-2) const prevSibling = this.getChildByIndex(childsMap.size - 2, childType); if (prevSibling) { prevSibling.isLastChild = true; } } // Remove child from it's Map of all child items global reference! this._childIdsByType.delete(childId); // Remove child from it's Map of items with the same type! childsMap.delete(childId); } /** * Getter that allows to obtain all the childs when parent only contains childs of one type, * otherwise a type must be passed in order to return all child of the given type! * * @param type To be based on childType childs collection, otherwise will assume parent only contains one child type! * @returns * @memberof OSFramework.Patterns.AbstractParent */ public getChildItems(type?: string): Array<CT> { // If type undefined, get the first key object name! if (type === undefined) { type = Object.keys(this._childItemsByType)[0]; } // Get the correct map based on the given type const childsMap = this._childItemsByType[type]; return childsMap === undefined ? [] : [...childsMap.values()]; } /** * Method used to be notified by a given ChildId about a given action and act accordingly * * @abstract * @param {string} childItem Child Item * @param {string} notifiedTo Notification name (Should be based on an Enum) * @memberof OSFramework.Patterns.AbstractParent */ public abstract beNotifiedByChild(childItem: CT, notifiedTo: string): void; } }