@pilotlab/data
Version:
A luxurious user experience framework, developed by your friends at Pilot.
294 lines • 13.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const is_1 = require("@pilotlab/is");
const signals_1 = require("@pilotlab/signals");
const ids_1 = require("@pilotlab/ids");
const result_1 = require("@pilotlab/result");
const nodes_1 = require("@pilotlab/nodes");
const attributeEnums_1 = require("./attributeEnums");
const dataTools_1 = require("../dataTools");
const attributesBase_1 = require("./attributesBase");
const attributeSetReturn_1 = require("./attributeSetReturn");
const attributeChangeOptions_1 = require("./attributeChangeOptions");
const attributeEventArgs_1 = require("./attributeEventArgs");
class AttributeBase extends nodes_1.NodeBase {
constructor(factory, value, dataType, label, key = '', nodeType = nodes_1.NodeType.BASIC, isInitialize = true) {
super(factory, nodeType, key, false);
this.p_value = null;
if (is_1.default.notEmpty(label, true))
this.p_label = label;
this.p_dataType = attributeEnums_1.DataType.UNDEFINED;
this.p_changed = new signals_1.Signal(false);
this.p_isSignalChange = true;
this.p_isAllowSave = true;
this.p_isAllowAutoPropterties = true;
this.p_returnValue = new attributeSetReturn_1.default(this, false);
this.p_formatter = (value) => value;
if (isInitialize)
this.initialize(value, dataType, nodeType);
}
p_onInitializeStarted(result, args) {
const value = args[0];
const dataType = args[1];
const nodeType = args[2];
super.p_onInitializeStarted(new result_1.Result(), [nodeType]).then(() => {
/// Set the data type first, then the value
if (is_1.default.notEmpty(dataType))
this.p_dataType = dataType;
else {
if (is_1.default.notEmpty(value, false))
this.p_dataType = dataTools_1.default.getDataType(value);
else
this.p_dataType = attributeEnums_1.DataType.OBJECT;
}
if (this.create.getBaseDataType(this.p_dataType) === attributeEnums_1.DataType.COLLECTION) {
this.p_wrapAttributes(value, attributeEnums_1.AttributesWrapType.CLEAR_BASE);
}
else if (is_1.default.notEmpty(value, false))
this.p_value = value;
result.resolve(value);
});
return result;
}
/**
* All data associated with this entity will be saved to the provided attribute collection,
* and all change events will be propagated through that collection.
*/
p_wrapAttributes(value, wrapType = attributeEnums_1.AttributesWrapType.OVERWRITE_BASE) {
let changeOptions = attributeChangeOptions_1.default.noSaveOrSignal;
let attributes;
/// If an Attributes instance was passed as the value, it will be directly assigned to this.p_value.
if (is_1.default.notEmpty(value)) {
attributes = this.create.collection.fromAny(value, this);
}
if (is_1.default.empty(attributes))
attributes = this.create.collection.instance(this);
this.p_value = attributes;
if (is_1.default.notEmpty(this.p_value)) {
if (wrapType === attributeEnums_1.AttributesWrapType.CLEAR_BASE) {
/// Do nothing.
}
else if (wrapType === attributeEnums_1.AttributesWrapType.CLEAR_WRAPPED) {
attributes.clear(changeOptions);
attributes.update(this.p_value, changeOptions);
}
else if (wrapType === attributeEnums_1.AttributesWrapType.OVERWRITE_BASE) {
this.p_value.update(attributes, changeOptions);
attributes.clear(attributeChangeOptions_1.default.noSaveOrSignal);
attributes.update(this.p_value, changeOptions);
}
else if (wrapType === attributeEnums_1.AttributesWrapType.OVERWRITE_WRAPPED) {
attributes.update(this.p_value, changeOptions);
}
}
}
/*====================================================================*
START: Factory
*====================================================================*/
get create() { return this.p_factory; }
/**
* A UI-friendly title for the attribute that can be presented to users.
* If no label is set, the key of the node will be returned.
*/
get label() { return is_1.default.notEmpty(this.p_label, true) ? this.p_label : this.key; }
set label(value) { this.p_label = value; }
/**
* A brief description of that attribute that can be used to supply info to the user
* about how the attribute should be used.
*/
get summary() { return is_1.default.notEmpty(this.p_summary, true) ? this.p_summary : ''; }
set summary(value) { this.p_summary = value; }
/**
* The value of the associated data.
* This property cannot be set directly. You must use the set() method to change the value.
* This allows attributes to be wrapped in an AttributeReader instance, which effectively
* renders them immutable.
*/
get value() { return this.p_value; }
set value(value) { this.set(value, this.isSignalChange ? attributeChangeOptions_1.default.save : attributeChangeOptions_1.default.zero); }
get formatted() {
let value = this.p_value;
value = this.p_format(value);
return value;
}
get isCollection() {
return (this.nodeType === nodes_1.NodeType.ROOT ||
this.nodeType === nodes_1.NodeType.COLLECTION ||
this.create.getBaseDataType(this.dataType) === attributeEnums_1.DataType.COLLECTION);
}
/// This property will hold dynamically generated getters and setters
/// for each child attribute that is added to this attribute.
get attributes() { return this.p_value; }
get children() { return this.isCollection ? this.p_value : this.p_children; }
get valuePrevious() { return this.p_valuePrevious; }
get dataType() { return this.p_dataType; }
/**
* Attributes will be considered empty if no key or value has been set.
*/
get isEmpty() {
if (is_1.default.undefined(this.p_value))
return true;
if (is_1.default.empty(this.p_value, false))
return true;
if (is_1.default.empty(this.key, true))
return true;
if (is_1.default.empty(this.dataType, true))
return true;
if (this.dataType === attributeEnums_1.DataType.UNDEFINED)
return true;
if (this.dataType === attributeEnums_1.DataType.NULL)
return true;
return false;
}
/**
* If this function returns true, the attribute will be omitted from data transfer objects
* when saving data to the data store.
*/
get omitFromDataStore() { return this.p_omitFromDataStore; }
set omitFromDataStore(fn) { this.p_omitFromDataStore = fn; }
get formatter() { return this.p_formatter; }
set formatter(value) { this.p_formatter = value; }
p_format(value) { return this.p_formatter(value); }
get copy() { return this.create.fromObject(this.toObject()); }
/**
* An automatically generated unique ID that is used when animating attribute values.
*/
get animationKey() {
if (is_1.default.empty(this._animationKey))
this._animationKey = this.key + '_' + ids_1.Identifier.getSessionUniqueInteger();
return this._animationKey;
}
get isEditable() { return this.p_isEditable; }
set isEditable(value) {
this.p_isEditable = value;
}
get isHidden() { return this.p_isHidden; }
set isHidden(value) {
this.p_isHidden = value;
}
get isAllowSave() { return this.p_isAllowSave; }
set isAllowSave(value) {
if (this.isCollection)
this.children.isAllowSave = value;
this.p_isAllowSave = value;
}
/**
* Should we allow accessor properties to be generated automatically when
* a new child Attribute is added to our Attribute collection?
*/
get isAllowAutoProperties() { return this.p_isAllowAutoPropterties; }
set isAllowAutoProperties(value) { this.p_isAllowAutoPropterties = value; }
/*====================================================================*
START: Signals
*====================================================================*/
get changed() { return this.p_changed; }
/*====================================================================*
START: Internal
*====================================================================*/
/// Overridden to take isSave into account.
internalChanged(args) {
if (!this.isSignalChange && !this.isAllowSave)
return;
if ((args.changeOptions.isSignalChange || args.changeOptions.isSave) && this.isSignalChange)
this.changed.dispatch(args);
if (is_1.default.notEmpty(this.parentCollection) && (is_1.default.notEmpty(this.parentCollection.internalChanged))) {
this.parentCollection.internalChanged(args);
}
}
/*====================================================================*
START: Public Methods
*====================================================================*/
/**
* Save the value to the attribute.
*/
set(value, changeOptions = attributeChangeOptions_1.default.default) {
let returnValue = this.p_returnValue;
if (is_1.default.empty(value))
return returnValue;
if (this.create.getBaseDataType(this.p_dataType) === attributeEnums_1.DataType.COLLECTION) {
/// This attribute holds a collection...
if (is_1.default.notEmpty(this.p_value) && (this.p_value instanceof attributesBase_1.default)) {
let tracker = this.p_value.update(value, changeOptions);
returnValue.updateTracker = tracker;
tracker.then((tracker) => {
returnValue.isChanged = tracker.isChanged;
});
}
}
else {
value = this.p_format(value);
if (this.p_value === value) {
if (changeOptions.action === attributeEnums_1.AttributeChangeActions.SAVE) {
this.doChanged(changeOptions.action);
}
return returnValue;
}
this.p_valuePrevious = this.p_valueTarget;
this.p_value = value;
this.p_valueTarget = value;
returnValue.isChanged = true;
this.doChanged(changeOptions.action);
}
return returnValue;
}
/**
* Interrupt any animated value transitions that are in effect.
*/
interruptAnimation() { if (is_1.default.notEmpty(this.p_animation))
this.p_animation.interrupt(); }
/**
* Manually trigger a dispatch on the 'changed' signal.
*/
doChanged(action) {
if (!this.isSignalChange && !this.isAllowSave)
return;
else if (action === attributeEnums_1.AttributeChangeActions.SIGNAL_CHANGE && !this.isSignalChange)
return;
else if (action === attributeEnums_1.AttributeChangeActions.SAVE && !this.isAllowSave)
return;
let args = new attributeEventArgs_1.default(this, nodes_1.NodeChangeType.UPDATED, new attributeChangeOptions_1.default(action).durationZero);
this.internalChanged(args);
}
toObject(isIncludeDataTypes = true, isIncludeLabels = true, appendToObject, isForceInclude = false) {
if (!isForceInclude && (is_1.default.notEmpty(this.p_omitFromDataStore) && this.p_omitFromDataStore(this.p_value)))
return appendToObject;
let object = {};
if (isIncludeDataTypes ||
(isIncludeLabels && is_1.default.notEmpty(this.label, true) && this.label !== this.key)) {
if (isIncludeDataTypes)
object['dataType'] = this.dataType.toString();
if (isIncludeLabels && (is_1.default.notEmpty(this.label, true) && this.label !== this.key))
object['label'] = this.label;
object['isEditable'] = this.isEditable;
object['isHidden'] = this.isHidden;
if (this.p_value instanceof attributesBase_1.default) {
object['value'] = this.p_value.toObject(isIncludeDataTypes, isIncludeLabels, isForceInclude);
}
else
object['value'] = this.formatted;
}
else {
if (this.p_value instanceof attributesBase_1.default) {
object = this.p_value.toObject(isIncludeDataTypes, isIncludeLabels, isForceInclude);
}
else
object = this.formatted;
}
if (is_1.default.notEmpty(appendToObject)) {
appendToObject[this.key] = object;
return appendToObject;
}
else
return object;
}
internalAttached(changeOptions) {
if (is_1.default.notEmpty(this.parentCollection)) {
this.isSignalChange = this.parentCollection.isSignalChange;
this.isAllowSave = this.parentCollection.isAllowSave;
}
super.internalAttached(changeOptions);
}
} // End class
exports.AttributeBase = AttributeBase;
exports.default = AttributeBase;
//# sourceMappingURL=attributeBase.js.map