import Kinibind from "kinibind/ts/kinibind"; import EntityApi from "../api/entity-api"; import EntityArrayProxy from "./entity-array-proxy"; import Request from "../util/request"; import KinisiteDataFormatters from "./formatters/kinisite-data-formatters"; import KinisiteCssFormatters from "./formatters/kinisite-css-formatters"; import KWysiwyg from "./binders/k-wysiwyg"; import KinisiteUrlFormatters from "./formatters/kinisite-url-formatters"; import KinisiteRemoteFormatters from "./formatters/kinisite-remote-formatters"; import KSetState from "./binders/k-set-state"; import KWidget from "./binders/k-widget"; import KScript from "./components/k-script"; import LocalStorage from "../util/local-storage"; import SessionStorage from "../util/session-storage"; import * as dayjs from "dayjs"; import Env from "../env/env"; export default class KinisiteBind extends Kinibind { /** * Entity API * * @private */ private _entityAPI: EntityApi; // All active kinibinds private static _allKinisiteBinds = []; /** * Kinibind class */ public static Kinibind = Kinibind; /** * Allow access to the kinibind component class * * @private */ public static Component = Kinibind.Component; /** * Single current instacne * @private */ private static _emptyCurrent = {}; /** * Config initialised * * @private */ private static _configInitialised = false; /** * Construct with required attributes * * @param element * @param model * @param config * @param entityAPI * */ constructor(element: any, model: any = {}, config: any = {}, entityAPI: EntityApi = new EntityApi()) { // If no global configuration yet, ensure we initialise. if (!KinisiteBind._configInitialised) KinisiteBind.config = {}; let coreParams = { entityDefinitions: {}, request: Request.instance, localStorage: LocalStorage.instance, sessionStorage: SessionStorage.instance, state: {}, current: KinisiteBind._emptyCurrent, now: (dayjs)().format('YYYY-MM-DD HH:mm:ss') }; let combinedModel = config.noModelMerge ? model : {...coreParams, ...model}; // Construct parent super(element, combinedModel, config); // Store the entity API this._entityAPI = entityAPI; // Load up core data unless we are suppressing it if (!config.suppressEntityData) this._loadData(); KinisiteBind._allKinisiteBinds.push(this); } /** * Set static config on global instance * * @param config */ static set config(config: any) { let configuredFormatters = config.formatters ? config.formatters : {}; let configuredBinders = config.binders ? config.binders : {}; let configuredComponents = config.components ? config.components : {}; // Customise kinibind config with merged aspects let mergedConfig = { "prefix": config.prefix ? config.prefix : "k", "formatters": { ...KinisiteDataFormatters, ...KinisiteCssFormatters, ...KinisiteUrlFormatters, ...KinisiteRemoteFormatters, ...configuredFormatters }, "binders": { "set-state-*": KSetState, "wysiwyg": KWysiwyg, "widget": KWidget, ...configuredBinders }, "components": { "script": KScript, ...configuredComponents } }; // Call parent config Kinibind.config = mergedConfig; // Config initialised this._configInitialised = true; } /** * Get all bound kinibind instances */ public static get all() { return this._allKinisiteBinds; } /** * Unregister a kinibind which has been previously added * * @param kinibind */ public static unregister(kinibind: never) { let index: any = KinisiteBind._allKinisiteBinds.indexOf(kinibind); if (index >= 0) { KinisiteBind._allKinisiteBinds.splice(index, 1); } } // Load data private _loadData() { // Grab all definitions first this._entityAPI.definitions.then((definitions: any) => { this.model.entityDefinitions = definitions; this._entityAPI.current.then((current: any) => { if (!current) { current = KinisiteBind._emptyCurrent; } KinisiteBind.addNewProperty(this.model, "current", current); }); // Add definitions as array proxies Object.keys(definitions).forEach(name => { // if we have a sub object, make sure we make whole tree let parentContainer = this.model; let propertyName = name; if (name.includes("/")) { let exploded = name.split("/"); let parentKey = exploded[0]; if (!this.model[parentKey]) { KinisiteBind.addNewProperty(this.model, parentKey, {}); } parentContainer = this.model[parentKey]; propertyName = exploded[1]; } if (definitions[name].singleInstance) { this._entityAPI.single(name).then((single: any) => { KinisiteBind.addNewProperty(parentContainer, propertyName, single); }); } else { KinisiteBind.addNewProperty(parentContainer, propertyName, new EntityArrayProxy(name)); } }); }); // Add env properties Env.env.then(((env: any) => { KinisiteBind.addNewProperty(this.model, "env", env); })); } }