UNPKG

@pilotlab/data

Version:

A luxurious user experience framework, developed by your friends at Pilot.

242 lines 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const is_1 = require("@pilotlab/is"); const nodes_1 = require("@pilotlab/nodes"); const signals_1 = require("@pilotlab/signals"); const attributeCreateOptions_1 = require("./attributeCreateOptions"); const attributeSetReturn_1 = require("./attributeSetReturn"); const attributeEnums_1 = require("./attributeEnums"); const attributeChangeOptions_1 = require("./attributeChangeOptions"); const attributeUpdateTracker_1 = require("./attributeUpdateTracker"); class AttributesBase extends nodes_1.NodesBase { constructor(factory, parent, pathSegment = '.') { super(factory, parent, pathSegment); /*====================================================================* START: Signals *====================================================================*/ this.saveTriggered = new signals_1.Signal(); /// IMPORTANT: This signal should only be dispatched from internalChanged. this.changed = new signals_1.Signal(false); this.p_factory = factory; } /*====================================================================* START: Factory *====================================================================*/ get create() { return this.p_factory; } /*====================================================================* START: Properties *====================================================================*/ get copy() { return this.create.collection.fromObject(this.toObject()); } /*====================================================================* START: Methods *====================================================================*/ /** * If an attribute exists at the given path, it will be returned. * Otherwise, if createOptions is supplied, a new attribute will * first be created with the given parameters, then returned. */ getOrCreate(path, createOptions, segmentCreateOptions) { if (is_1.default.empty(createOptions)) createOptions = new attributeCreateOptions_1.default(null, attributeEnums_1.DataType.COLLECTION); if (is_1.default.empty(segmentCreateOptions)) segmentCreateOptions = new attributeCreateOptions_1.default(null, attributeEnums_1.DataType.COLLECTION); return super.getOrCreate(path, createOptions, segmentCreateOptions); } get(path, createOptions, changeOptions = attributeChangeOptions_1.default.default) { if (is_1.default.empty(createOptions)) return this.getByPath(path); const segmentCreateOptions = new attributeCreateOptions_1.default(null, attributeEnums_1.DataType.COLLECTION, null, null, null, changeOptions); return this.getOrCreate(path, createOptions, segmentCreateOptions); } getOnly(paths) { let collection = this.create.collection.instance(); paths.forEach((path) => { let child = this.get(path); /// Return the child attributes by reference here, since that's what get() does. /// If the user doesn't want to modify the actual attributes, they can call .copy on the returned collection. if (is_1.default.notEmpty(child) && !child.isEmpty) collection.add(child, null, attributeChangeOptions_1.default.zero); }); return collection; } getAll(key, options, filter, sort) { let collectionIn; let collectionOut = this.create.collection.instance(); /// Retrieve only child attribute collections with a child key that matches the key argument. if (is_1.default.notEmpty(key)) { collectionIn = this.create.collection.instance(); this.forEach((childLevel1) => { if (this.create.getBaseDataType(childLevel1.dataType) === attributeEnums_1.DataType.COLLECTION) { childLevel1.value.forEach((nodeLevel2) => { if (nodeLevel2.key === key) { let isInclude = true; /// Were any options passed in? if (is_1.default.notEmpty(options)) { /// If a key was passed in as an option, check to see whether the value of the attribute matches the key. if (is_1.default.notEmpty(options.key)) if (nodeLevel2.value !== options.key) isInclude = false; } if (isInclude) collectionIn.set(childLevel1.key, childLevel1.value); } }); return true; } return true; }); } else collectionIn = this; if (is_1.default.notEmpty(filter)) { collectionIn.list.forEach((child) => { if (filter(child.toObject())) collectionOut.set(child.key, child.value); return true; }); } else collectionOut = collectionIn; if (is_1.default.notEmpty(sort)) collectionOut.sort(sort); else { collectionOut.list.sort((a, b) => { if (a.key > b.key) return 1; else if (a.key < b.key) return -1; return 0; }); } return collectionOut; } /** * If an attribute doesn't already exist at the given path, one will be created. */ set(path, value, dataType = attributeEnums_1.DataType.ANY, label, index, changeOptions) { let returnValue = new attributeSetReturn_1.default(null, false); if (is_1.default.empty(path, true)) return returnValue; let attribute = this.getByPath(path); if (is_1.default.empty(attribute) || attribute.isEmpty) { const createOptions = new attributeCreateOptions_1.default(value, dataType, label, index, null, changeOptions); const segmentCreateOptions = new attributeCreateOptions_1.default(null, attributeEnums_1.DataType.COLLECTION, null, null, null, changeOptions); attribute = this.getOrCreate(path, createOptions, segmentCreateOptions); returnValue.attribute = attribute; returnValue.isChanged = true; } else { returnValue = attribute.set(value, changeOptions); } return returnValue; } p_add(child, index, changeOptions) { super.p_add(child, index, changeOptions); if (is_1.default.notEmpty(child) && is_1.default.notEmpty(child.key)) { /// START: Create getters and setters. if (is_1.default.notEmpty(this.parent) && !this.parent.hasOwnProperty(child.key) && this.parent.isAllowAutoProperties) { const childKey = child.key; const childDataType = child.dataType; Object.defineProperty(this.parent, childKey, { get: () => { const attribute = this.get(childKey); if (is_1.default.notEmpty(attribute)) { if (this.create.getBaseDataType(attribute.dataType) === attributeEnums_1.DataType.COLLECTION) return attribute; else return attribute.value; } else return this.create.instance(); }, set: (value) => { this.set(childKey, value, childDataType, null, null, attributeChangeOptions_1.default.default.durationZero); }, enumerable: true, configurable: true }); } if (!this.hasOwnProperty(child.key)) { const childKey = child.key; Object.defineProperty(this, childKey, { get: () => { return this.get(childKey); }, enumerable: true, configurable: true }); } /// END: Create getters and setters. } } deleteByKey(key, changeOptions = attributeChangeOptions_1.default.default) { return super.deleteByKey(key, changeOptions); } interruptAnimationAll() { this.p_list.forEach(function (child) { if (is_1.default.empty(child)) return true; child.interruptAnimation(); return true; }); } set isAllowSave(value) { for (let i = 0; i < this.p_list.size; i++) { this.p_list.item(i).isAllowSave = value; } } /*====================================================================* START: Update *====================================================================*/ /** * <pre><code> * /// Just quietly initialize the data entity, but don't save to the data store or signal a change. * /// This is used when reloading data from the store to initialize the app. * * myComponent.data.update(data, AttributeChangeOptions.noSaveOrSignal); * * /// Update the data, and signal changes, but don't save to the data store. * /// Used for data entities that don't need to be saved to a store. * * myComponent.data.update(data, nodeChangeOptions.flags(AttributeChangeOptions.SIGNAL_CHANGE)); * * /// Update the data and save to the data store, but don’t signal a change. * /// Used for batch saving, when you may want to signal changes only at the end of the process. * * myComponent.data.update(data, nodeChangeOptions.flags(AttributeChangeOptions.SAVE)); * * /// And, finally, the default mode. Update the data, save to the store and signal the change. * * myComponent.data.update(data, AttributeChangeOptions.saveAndSignal); * </code></pre> */ update(data, changeOptions = attributeChangeOptions_1.default.default, progressTracker) { let attributesNew = this.create.collection.fromAny(data); let updateTracker = new attributeUpdateTracker_1.default(attributesNew, changeOptions, progressTracker); if (is_1.default.empty(attributesNew) || attributesNew.list.size === 0) { updateTracker.progressTracker.run(); return updateTracker; } this.updateTracked(updateTracker); return updateTracker; } /** * Cascades data down through all attributes and attribute * collections to update any that need to be changed. */ updateTracked(updateTracker) { updateTracker.update(this); updateTracker.progressTracker.run(); } internalAttachedAll(changeOptions) { if (is_1.default.notEmpty(this.parent)) { this.isSignalChange = this.parent.isSignalChange; this.isAllowSave = this.parent.isAllowSave; } super.internalAttachedAll(changeOptions); } } // End class exports.AttributesBase = AttributesBase; exports.default = AttributesBase; //# sourceMappingURL=attributesBase.js.map