@pilotlab/data
Version:
A luxurious user experience framework, developed by your friends at Pilot.
242 lines • 11.4 kB
JavaScript
"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