From b2147f05aa789b97fe3bfff461211e9b95791da5 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Fri, 13 Jun 2025 15:41:11 +0300 Subject: [PATCH 01/10] chore: rewrite RuntimeItemsMixin --- dist/js/entity/mixins/RuntimeItemsMixin.d.ts | 43 ++++++ dist/js/entity/mixins/RuntimeItemsMixin.js | 114 ++++++++++++++ dist/js/entity/mixins/runtime_items.d.ts | 77 ++-------- dist/js/entity/mixins/runtime_items.js | 117 +++++++------- dist/js/entity/other.d.ts | 33 ++-- src/js/entity/mixins/RuntimeItemsMixin.ts | 152 +++++++++++++++++++ src/js/entity/mixins/runtime_items.ts | 66 ++------ 7 files changed, 397 insertions(+), 205 deletions(-) create mode 100644 dist/js/entity/mixins/RuntimeItemsMixin.d.ts create mode 100644 dist/js/entity/mixins/RuntimeItemsMixin.js create mode 100644 src/js/entity/mixins/RuntimeItemsMixin.ts diff --git a/dist/js/entity/mixins/RuntimeItemsMixin.d.ts b/dist/js/entity/mixins/RuntimeItemsMixin.d.ts new file mode 100644 index 00000000..858b01db --- /dev/null +++ b/dist/js/entity/mixins/RuntimeItemsMixin.d.ts @@ -0,0 +1,43 @@ +import type { NameResultSchema, RuntimeItemSchema } from "@mat3ra/esse/dist/js/types"; +import type { Constructor } from "../../utils/types"; +import { InMemoryEntity } from "../in_memory"; +export declare enum ItemKey { + results = "results", + monitors = "monitors", + preProcessors = "preProcessors", + postProcessors = "postProcessors" +} +export type BaseRuntimeItemsInMemoryEntity = InMemoryEntity & { + _json: { + results?: NameResultSchema[]; + monitors?: NameResultSchema[]; + preProcessors?: NameResultSchema[]; + postProcessors?: NameResultSchema[]; + }; + defaultResults?: NameResultSchema[]; + defaultMonitors?: NameResultSchema[]; + defaultPreProcessors?: NameResultSchema[]; + defaultPostProcessors?: NameResultSchema[]; +}; +export declare function runtimeItemsMixin(item: BaseRuntimeItemsInMemoryEntity): { + results: NameResultSchema[]; + monitors: NameResultSchema[]; + preProcessors: NameResultSchema[]; + postProcessors: NameResultSchema[]; + readonly resultNames: string[]; + readonly monitorNames: string[]; + readonly preProcessorNames: string[]; + readonly postProcessorNames: string[]; + _addRuntimeItem(key: ItemKey, config: RuntimeItemSchema): void; + _removeRuntimeItem(key: ItemKey, config: RuntimeItemSchema): void; + _removeRuntimeItemByName(key: ItemKey, name: string): void; + _toggleRuntimeItem(key: ItemKey, data: RuntimeItemSchema, isAdding: boolean): void; + toggleResult(data: RuntimeItemSchema, isAdding: boolean): void; + toggleMonitor(data: RuntimeItemSchema, isAdding: boolean): void; + togglePreProcessor(data: RuntimeItemSchema, isAdding: boolean): void; + togglePostProcessor(data: RuntimeItemSchema, isAdding: boolean): void; + getResultByName(name: string): NameResultSchema | undefined; +}; +export type RuntimeItemsInMemoryEntity = ReturnType; +export type RuntimeItemsInMemoryEntityConstructor = Constructor; +export default function RuntimeItemsMixin>(superclass: S): S & RuntimeItemsInMemoryEntityConstructor; diff --git a/dist/js/entity/mixins/RuntimeItemsMixin.js b/dist/js/entity/mixins/RuntimeItemsMixin.js new file mode 100644 index 00000000..0800a37b --- /dev/null +++ b/dist/js/entity/mixins/RuntimeItemsMixin.js @@ -0,0 +1,114 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ItemKey = void 0; +exports.runtimeItemsMixin = runtimeItemsMixin; +exports.default = RuntimeItemsMixin; +const object_1 = require("../../utils/object"); +var ItemKey; +(function (ItemKey) { + ItemKey["results"] = "results"; + ItemKey["monitors"] = "monitors"; + ItemKey["preProcessors"] = "preProcessors"; + ItemKey["postProcessors"] = "postProcessors"; +})(ItemKey || (exports.ItemKey = ItemKey = {})); +/* + * @summary Contains runtime items: results, monitors, pre/postProcessors + * Is meant to work with Entity, InMemoryEntity b/c of `prop` extraction from `_json`. + */ +function runtimeItemsMixin(item) { + const properties = { + get results() { + const self = this; + return self.prop("results", self.defaultResults || []).map(object_1.safeMakeObject); + }, + set results(array) { + const self = this; + self.setProp("results", array); + }, + get monitors() { + const self = this; + return self.prop("monitors", self.defaultMonitors || []).map(object_1.safeMakeObject); + }, + set monitors(array) { + const self = this; + self.setProp("monitors", array); + }, + get preProcessors() { + const self = this; + return self.prop("preProcessors", self.defaultPreProcessors || []).map(object_1.safeMakeObject); + }, + set preProcessors(array) { + const self = this; + self.setProp("preProcessors", array); + }, + get postProcessors() { + const self = this; + return self + .prop("postProcessors", self.defaultPostProcessors || []) + .map(object_1.safeMakeObject); + }, + set postProcessors(array) { + const self = this; + self.setProp("postProcessors", array); + }, + get resultNames() { + return this.results.map((r) => r === null || r === void 0 ? void 0 : r.name); + }, + get monitorNames() { + return this.monitors.map((r) => r === null || r === void 0 ? void 0 : r.name); + }, + get preProcessorNames() { + return this.preProcessors.map((r) => r === null || r === void 0 ? void 0 : r.name); + }, + get postProcessorNames() { + return this.postProcessors.map((r) => r === null || r === void 0 ? void 0 : r.name); + }, + _addRuntimeItem(key, config) { + const self = this; + const runtimeItems = self._json[key || ItemKey.results]; + if (!runtimeItems) { + throw new Error("not found"); + } + runtimeItems.push((0, object_1.safeMakeObject)(config)); + }, + _removeRuntimeItem(key, config) { + const newConfig = (0, object_1.safeMakeObject)(config); + this._removeRuntimeItemByName(key, (newConfig === null || newConfig === void 0 ? void 0 : newConfig.name) || ""); + }, + _removeRuntimeItemByName(key, name) { + const self = this; + self._json[key] = self._json[key].filter((x) => x.name !== name); + }, + _toggleRuntimeItem(key, data, isAdding) { + if (isAdding) { + this._addRuntimeItem(key, data); + } + else { + this._removeRuntimeItem(key, data); + } + }, + toggleResult(data, isAdding) { + this._toggleRuntimeItem(ItemKey.results, data, isAdding); + }, + toggleMonitor(data, isAdding) { + this._toggleRuntimeItem(ItemKey.monitors, data, isAdding); + }, + togglePreProcessor(data, isAdding) { + this._toggleRuntimeItem(ItemKey.preProcessors, data, isAdding); + }, + togglePostProcessor(data, isAdding) { + this._toggleRuntimeItem(ItemKey.postProcessors, data, isAdding); + }, + getResultByName(name) { + return this.results.find((r) => (r === null || r === void 0 ? void 0 : r.name) === name); + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); + return properties; +} +function RuntimeItemsMixin(superclass) { + class RuntimeItemsMixin extends superclass { + } + runtimeItemsMixin(RuntimeItemsMixin.prototype); + return RuntimeItemsMixin; +} diff --git a/dist/js/entity/mixins/runtime_items.d.ts b/dist/js/entity/mixins/runtime_items.d.ts index b644dc18..569e081e 100644 --- a/dist/js/entity/mixins/runtime_items.d.ts +++ b/dist/js/entity/mixins/runtime_items.d.ts @@ -1,65 +1,19 @@ import { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; import { NameResultSchema, RuntimeItemSchema } from "@mat3ra/esse/dist/js/types"; +import type { Constructor } from "src/js/utils/types"; import { InMemoryEntityConstructor } from "../in_memory"; -export declare enum ItemKey { - results = "results", - monitors = "monitors", - preProcessors = "preProcessors", - postProcessors = "postProcessors" -} -export declare function RuntimeItemsMixin(superclass: T): { - new (...args: any[]): { - readonly results: NameResultSchema[]; - readonly monitors: NameResultSchema[]; - readonly preProcessors: NameResultSchema[]; - readonly postProcessors: NameResultSchema[]; - readonly defaultResults: NameResultSchema[]; - readonly defaultMonitors: NameResultSchema[]; - readonly defaultPreProcessors: NameResultSchema[]; - readonly defaultPostProcessors: NameResultSchema[]; - readonly hashObjectFromRuntimeItems: { - results: NameResultSchema[]; - preProcessors: NameResultSchema[]; - postProcessors: NameResultSchema[]; - }; - _json: AnyObject; - prop(name: string, defaultValue: T_1): T_1; - prop(name: string): T_1 | undefined; - setProp(name: string, value: unknown): void; - unsetProp(name: string): void; - setProps(json?: AnyObject): /*elided*/ any; - toJSON(exclude?: string[]): AnyObject; - toJSONSafe(exclude?: string[]): AnyObject; - toJSONQuick(exclude?: string[]): AnyObject; - clone(extraContext?: object): /*elided*/ any; - validate(): void; - clean(config: AnyObject): AnyObject; - isValid(): boolean; - readonly cls: string; - getClsName(): string; - getAsEntityReference(byIdOnly: true): { - _id: string; - }; - getAsEntityReference(byIdOnly?: false): Required; - getEntityByName(entities: import("../in_memory").InMemoryEntity[], entity: string, name: string): import("../in_memory").InMemoryEntity; - id: string; - _id: string; - schemaVersion: string; - systemName: string; - readonly slug: string; - readonly isSystemEntity: boolean; - }; -} & T; +import RuntimeItemsMixin, { type BaseRuntimeItemsInMemoryEntity, ItemKey } from "./RuntimeItemsMixin"; +export { RuntimeItemsMixin, ItemKey }; export interface RuntimeItemsUILogicJSON extends AnyObject { results?: NameResultSchema[]; monitors?: NameResultSchema[]; preProcessors?: NameResultSchema[]; postProcessors?: NameResultSchema[]; } -export declare function RuntimeItemsUILogicMixin(superclass: T): { +export declare function RuntimeItemsUILogicMixin>(superclass: T): { new (...params: any): { _json: RuntimeItemsUILogicJSON; - getDefaultsByKey(key: ItemKey): NameResultSchema[]; + getDefaultsByKey(key: ItemKey): NameResultSchema[] | undefined; setRuntimeItemsToDefaultValues(): void; /** * @summary Must pass config for subclasses to override and use initialization logic @@ -79,19 +33,6 @@ export declare function RuntimeItemsUILogicMixin(name: string, defaultValue: T_1): T_1; prop(name: string): T_1 | undefined; setProp(name: string, value: unknown): void; @@ -117,6 +58,14 @@ export declare function RuntimeItemsUILogicMixin(superclass: T): { diff --git a/dist/js/entity/mixins/runtime_items.js b/dist/js/entity/mixins/runtime_items.js index 0e381cc6..83e5fe83 100644 --- a/dist/js/entity/mixins/runtime_items.js +++ b/dist/js/entity/mixins/runtime_items.js @@ -1,66 +1,53 @@ "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); Object.defineProperty(exports, "__esModule", { value: true }); -exports.ItemKey = void 0; -exports.RuntimeItemsMixin = RuntimeItemsMixin; +exports.ItemKey = exports.RuntimeItemsMixin = void 0; exports.RuntimeItemsUILogicMixin = RuntimeItemsUILogicMixin; exports.RuntimeItemsUIAllowedMixin = RuntimeItemsUIAllowedMixin; const object_1 = require("../../utils/object"); -var ItemKey; -(function (ItemKey) { - ItemKey["results"] = "results"; - ItemKey["monitors"] = "monitors"; - ItemKey["preProcessors"] = "preProcessors"; - ItemKey["postProcessors"] = "postProcessors"; -})(ItemKey || (exports.ItemKey = ItemKey = {})); -/* - * @summary Contains runtime items: results, monitors, pre/postProcessors - * Is meant to work with Entity, InMemoryEntity b/c of `prop` extraction from `_json`. - */ -function RuntimeItemsMixin(superclass) { - return class extends superclass { - get results() { - return this.prop("results", this.defaultResults).map(object_1.safeMakeObject); - } - get monitors() { - return this.prop("monitors", this.defaultMonitors).map(object_1.safeMakeObject); - } - get preProcessors() { - // TODO: safeMakeObject could return null. Should we throw an error here? - return this.prop("preProcessors", this.defaultPreProcessors).map(object_1.safeMakeObject); - } - get postProcessors() { - // TODO: safeMakeObject could return null. Should we throw an error here? - return this.prop("postProcessors", this.defaultPostProcessors).map(object_1.safeMakeObject); - } - get defaultResults() { - return []; - } - get defaultMonitors() { - return []; - } - get defaultPreProcessors() { - return []; - } - get defaultPostProcessors() { - return []; - } - get hashObjectFromRuntimeItems() { - return { - results: this.results, - preProcessors: this.preProcessors, - postProcessors: this.postProcessors, - }; - } - }; -} +const RuntimeItemsMixin_1 = __importStar(require("./RuntimeItemsMixin")); +exports.RuntimeItemsMixin = RuntimeItemsMixin_1.default; +Object.defineProperty(exports, "ItemKey", { enumerable: true, get: function () { return RuntimeItemsMixin_1.ItemKey; } }); const allKeys = [ - ItemKey.results, - ItemKey.monitors, - ItemKey.postProcessors, - ItemKey.preProcessors, + RuntimeItemsMixin_1.ItemKey.results, + RuntimeItemsMixin_1.ItemKey.monitors, + RuntimeItemsMixin_1.ItemKey.postProcessors, + RuntimeItemsMixin_1.ItemKey.preProcessors, ]; function RuntimeItemsUILogicMixin(superclass) { - return class extends RuntimeItemsMixin(superclass) { + return class extends (0, RuntimeItemsMixin_1.default)(superclass) { // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor(...params) { super(...params); @@ -68,13 +55,13 @@ function RuntimeItemsUILogicMixin(superclass) { this._initRuntimeItems(allKeys, config); } getDefaultsByKey(key) { - if (key === ItemKey.results) { + if (key === RuntimeItemsMixin_1.ItemKey.results) { return this.defaultResults; } - if (key === ItemKey.monitors) { + if (key === RuntimeItemsMixin_1.ItemKey.monitors) { return this.defaultMonitors; } - if (key === ItemKey.preProcessors) { + if (key === RuntimeItemsMixin_1.ItemKey.preProcessors) { return this.defaultPreProcessors; } return this.defaultPostProcessors; @@ -98,7 +85,7 @@ function RuntimeItemsUILogicMixin(superclass) { }); } // eslint-disable-next-line default-param-last - _addRuntimeItem(key = ItemKey.results, config) { + _addRuntimeItem(key = RuntimeItemsMixin_1.ItemKey.results, config) { const runtimeItems = this._json[key]; if (!runtimeItems) { throw new Error("not found"); @@ -106,7 +93,7 @@ function RuntimeItemsUILogicMixin(superclass) { runtimeItems.push((0, object_1.safeMakeObject)(config)); } // eslint-disable-next-line default-param-last - _removeRuntimeItem(key = ItemKey.results, config) { + _removeRuntimeItem(key = RuntimeItemsMixin_1.ItemKey.results, config) { const newConfig = (0, object_1.safeMakeObject)(config); this._removeRuntimeItemByName(key, (newConfig === null || newConfig === void 0 ? void 0 : newConfig.name) || ""); } @@ -115,7 +102,7 @@ function RuntimeItemsUILogicMixin(superclass) { } _toggleRuntimeItem( // eslint-disable-next-line default-param-last - key = ItemKey.results, data, isAdding) { + key = RuntimeItemsMixin_1.ItemKey.results, data, isAdding) { if (isAdding) { this._addRuntimeItem(key, data); } @@ -124,16 +111,16 @@ function RuntimeItemsUILogicMixin(superclass) { } } toggleResult(data, isAdding) { - this._toggleRuntimeItem(ItemKey.results, data, isAdding); + this._toggleRuntimeItem(RuntimeItemsMixin_1.ItemKey.results, data, isAdding); } toggleMonitor(data, isAdding) { - this._toggleRuntimeItem(ItemKey.monitors, data, isAdding); + this._toggleRuntimeItem(RuntimeItemsMixin_1.ItemKey.monitors, data, isAdding); } togglePreProcessor(data, isAdding) { - this._toggleRuntimeItem(ItemKey.preProcessors, data, isAdding); + this._toggleRuntimeItem(RuntimeItemsMixin_1.ItemKey.preProcessors, data, isAdding); } togglePostProcessor(data, isAdding) { - this._toggleRuntimeItem(ItemKey.postProcessors, data, isAdding); + this._toggleRuntimeItem(RuntimeItemsMixin_1.ItemKey.postProcessors, data, isAdding); } get resultNames() { return this.results.map((r) => { diff --git a/dist/js/entity/other.d.ts b/dist/js/entity/other.d.ts index 7cdd7b15..87915cdd 100644 --- a/dist/js/entity/other.d.ts +++ b/dist/js/entity/other.d.ts @@ -320,13 +320,13 @@ export declare const NamedDefaultableRepetitionRuntimeItemsImportantSettingsCont } & { new (...params: any): { _json: import("./mixins/runtime_items").RuntimeItemsUILogicJSON; - getDefaultsByKey(key: import("./mixins/runtime_items").ItemKey): import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + getDefaultsByKey(key: import("./mixins/RuntimeItemsMixin").ItemKey): import("@mat3ra/esse/dist/js/types").NameResultSchema[] | undefined; setRuntimeItemsToDefaultValues(): void; - _initRuntimeItems(keys: import("./mixins/runtime_items").ItemKey[], _config: object): void; - _addRuntimeItem(key: import("./mixins/runtime_items").ItemKey | undefined, config: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema): void; - _removeRuntimeItem(key: import("./mixins/runtime_items").ItemKey | undefined, config: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema): void; - _removeRuntimeItemByName(key: import("./mixins/runtime_items").ItemKey, name: string): void; - _toggleRuntimeItem(key: import("./mixins/runtime_items").ItemKey | undefined, data: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema, isAdding: boolean): void; + _initRuntimeItems(keys: import("./mixins/RuntimeItemsMixin").ItemKey[], _config: object): void; + _addRuntimeItem(key: import("./mixins/RuntimeItemsMixin").ItemKey | undefined, config: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema): void; + _removeRuntimeItem(key: import("./mixins/RuntimeItemsMixin").ItemKey | undefined, config: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema): void; + _removeRuntimeItemByName(key: import("./mixins/RuntimeItemsMixin").ItemKey, name: string): void; + _toggleRuntimeItem(key: import("./mixins/RuntimeItemsMixin").ItemKey | undefined, data: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema, isAdding: boolean): void; toggleResult(data: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema, isAdding: boolean): void; toggleMonitor(data: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema, isAdding: boolean): void; togglePreProcessor(data: import("@mat3ra/esse/dist/js/types").RuntimeItemSchema, isAdding: boolean): void; @@ -336,19 +336,6 @@ export declare const NamedDefaultableRepetitionRuntimeItemsImportantSettingsCont readonly postProcessorNames: string[]; readonly preProcessorNames: string[]; getResultByName(name: string): import("@mat3ra/esse/dist/js/types").NameResultSchema | undefined; - readonly results: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly monitors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly preProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly postProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly defaultResults: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly defaultMonitors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly defaultPreProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly defaultPostProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - readonly hashObjectFromRuntimeItems: { - results: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - preProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - postProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; - }; prop(name: string, defaultValue: T): T; prop(name: string): T | undefined; setProp(name: string, value: unknown): void; @@ -374,6 +361,14 @@ export declare const NamedDefaultableRepetitionRuntimeItemsImportantSettingsCont systemName: string; readonly slug: string; readonly isSystemEntity: boolean; + defaultResults?: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + defaultMonitors?: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + defaultPreProcessors?: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + defaultPostProcessors?: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + results: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + monitors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + preProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + postProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; }; } & { new (...args: any[]): { diff --git a/src/js/entity/mixins/RuntimeItemsMixin.ts b/src/js/entity/mixins/RuntimeItemsMixin.ts new file mode 100644 index 00000000..65bd554b --- /dev/null +++ b/src/js/entity/mixins/RuntimeItemsMixin.ts @@ -0,0 +1,152 @@ +import type { NameResultSchema, RuntimeItemSchema } from "@mat3ra/esse/dist/js/types"; + +import { safeMakeObject } from "../../utils/object"; +import type { Constructor } from "../../utils/types"; +import { InMemoryEntity } from "../in_memory"; + +export enum ItemKey { + results = "results", + monitors = "monitors", + preProcessors = "preProcessors", + postProcessors = "postProcessors", +} + +export type BaseRuntimeItemsInMemoryEntity = InMemoryEntity & { + _json: { + results?: NameResultSchema[]; + monitors?: NameResultSchema[]; + preProcessors?: NameResultSchema[]; + postProcessors?: NameResultSchema[]; + }; + defaultResults?: NameResultSchema[]; + defaultMonitors?: NameResultSchema[]; + defaultPreProcessors?: NameResultSchema[]; + defaultPostProcessors?: NameResultSchema[]; +}; + +/* + * @summary Contains runtime items: results, monitors, pre/postProcessors + * Is meant to work with Entity, InMemoryEntity b/c of `prop` extraction from `_json`. + */ +export function runtimeItemsMixin(item: BaseRuntimeItemsInMemoryEntity) { + const properties = { + get results() { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + return self.prop("results", self.defaultResults || []).map(safeMakeObject); + }, + set results(array: NameResultSchema[]) { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + self.setProp("results", array); + }, + get monitors(): NameResultSchema[] { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + return self.prop("monitors", self.defaultMonitors || []).map(safeMakeObject); + }, + set monitors(array: NameResultSchema[]) { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + self.setProp("monitors", array); + }, + get preProcessors(): NameResultSchema[] { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + return self.prop("preProcessors", self.defaultPreProcessors || []).map(safeMakeObject); + }, + set preProcessors(array: NameResultSchema[]) { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + self.setProp("preProcessors", array); + }, + get postProcessors(): NameResultSchema[] { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + return self + .prop("postProcessors", self.defaultPostProcessors || []) + .map(safeMakeObject); + }, + set postProcessors(array: NameResultSchema[]) { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + self.setProp("postProcessors", array); + }, + + get resultNames() { + return this.results.map((r) => r?.name); + }, + + get monitorNames() { + return this.monitors.map((r) => r?.name); + }, + + get preProcessorNames() { + return this.preProcessors.map((r) => r?.name); + }, + + get postProcessorNames() { + return this.postProcessors.map((r) => r?.name); + }, + + _addRuntimeItem(key: ItemKey, config: RuntimeItemSchema) { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + const runtimeItems = self._json[key || ItemKey.results]; + + if (!runtimeItems) { + throw new Error("not found"); + } + + runtimeItems.push(safeMakeObject(config)); + }, + + _removeRuntimeItem(key: ItemKey, config: RuntimeItemSchema) { + const newConfig = safeMakeObject(config); + this._removeRuntimeItemByName(key, newConfig?.name || ""); + }, + + _removeRuntimeItemByName(key: ItemKey, name: string) { + const self = this as unknown as BaseRuntimeItemsInMemoryEntity; + self._json[key] = (self._json[key] as NameResultSchema[]).filter( + (x) => x.name !== name, + ); + }, + + _toggleRuntimeItem(key: ItemKey, data: RuntimeItemSchema, isAdding: boolean) { + if (isAdding) { + this._addRuntimeItem(key, data); + } else { + this._removeRuntimeItem(key, data); + } + }, + + toggleResult(data: RuntimeItemSchema, isAdding: boolean) { + this._toggleRuntimeItem(ItemKey.results, data, isAdding); + }, + + toggleMonitor(data: RuntimeItemSchema, isAdding: boolean) { + this._toggleRuntimeItem(ItemKey.monitors, data, isAdding); + }, + + togglePreProcessor(data: RuntimeItemSchema, isAdding: boolean) { + this._toggleRuntimeItem(ItemKey.preProcessors, data, isAdding); + }, + + togglePostProcessor(data: RuntimeItemSchema, isAdding: boolean) { + this._toggleRuntimeItem(ItemKey.postProcessors, data, isAdding); + }, + + getResultByName(name: string) { + return this.results.find((r) => r?.name === name); + }, + }; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); + + return properties; +} + +export type RuntimeItemsInMemoryEntity = ReturnType; +export type RuntimeItemsInMemoryEntityConstructor = Constructor; + +export default function RuntimeItemsMixin>( + superclass: S, +) { + class RuntimeItemsMixin extends superclass {} + + runtimeItemsMixin(RuntimeItemsMixin.prototype); + + return RuntimeItemsMixin as S & RuntimeItemsInMemoryEntityConstructor; +} diff --git a/src/js/entity/mixins/runtime_items.ts b/src/js/entity/mixins/runtime_items.ts index 57ac579d..3ea5facb 100644 --- a/src/js/entity/mixins/runtime_items.ts +++ b/src/js/entity/mixins/runtime_items.ts @@ -1,66 +1,16 @@ /* eslint-disable class-methods-use-this */ import { AnyObject } from "@mat3ra/esse/dist/js/esse/types"; import { NameResultSchema, RuntimeItemSchema } from "@mat3ra/esse/dist/js/types"; +import type { Constructor } from "src/js/utils/types"; import { safeMakeObject } from "../../utils/object"; import { InMemoryEntityConstructor } from "../in_memory"; +import RuntimeItemsMixin, { + type BaseRuntimeItemsInMemoryEntity, + ItemKey, +} from "./RuntimeItemsMixin"; -export enum ItemKey { - results = "results", - monitors = "monitors", - preProcessors = "preProcessors", - postProcessors = "postProcessors", -} -/* - * @summary Contains runtime items: results, monitors, pre/postProcessors - * Is meant to work with Entity, InMemoryEntity b/c of `prop` extraction from `_json`. - */ - -export function RuntimeItemsMixin(superclass: T) { - return class extends superclass { - get results(): NameResultSchema[] { - return this.prop("results", this.defaultResults).map(safeMakeObject); - } - - get monitors(): NameResultSchema[] { - return this.prop("monitors", this.defaultMonitors).map(safeMakeObject); - } - - get preProcessors(): NameResultSchema[] { - // TODO: safeMakeObject could return null. Should we throw an error here? - return this.prop("preProcessors", this.defaultPreProcessors).map(safeMakeObject); - } - - get postProcessors(): NameResultSchema[] { - // TODO: safeMakeObject could return null. Should we throw an error here? - return this.prop("postProcessors", this.defaultPostProcessors).map(safeMakeObject); - } - - get defaultResults(): NameResultSchema[] { - return []; - } - - get defaultMonitors(): NameResultSchema[] { - return []; - } - - get defaultPreProcessors(): NameResultSchema[] { - return []; - } - - get defaultPostProcessors(): NameResultSchema[] { - return []; - } - - get hashObjectFromRuntimeItems() { - return { - results: this.results, - preProcessors: this.preProcessors, - postProcessors: this.postProcessors, - }; - } - }; -} +export { RuntimeItemsMixin, ItemKey }; export interface RuntimeItemsUILogicJSON extends AnyObject { results?: NameResultSchema[]; @@ -76,7 +26,9 @@ const allKeys: ItemKey[] = [ ItemKey.preProcessors, ]; -export function RuntimeItemsUILogicMixin(superclass: T) { +export function RuntimeItemsUILogicMixin>( + superclass: T, +) { return class extends RuntimeItemsMixin(superclass) { declare _json: RuntimeItemsUILogicJSON; From 539184da724d5137cd4b700671d4d196b21edbb7 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Fri, 13 Jun 2025 23:35:04 +0300 Subject: [PATCH 02/10] chore: rewrite RuntimeItemsMixin --- dist/js/entity/mixins/RuntimeItemsMixin.d.ts | 24 ++-- dist/js/entity/mixins/RuntimeItemsMixin.js | 94 +++----------- dist/js/entity/mixins/runtime_items.d.ts | 5 + dist/js/entity/other.d.ts | 5 + src/js/entity/mixins/RuntimeItemsMixin.ts | 128 +++++-------------- 5 files changed, 67 insertions(+), 189 deletions(-) diff --git a/dist/js/entity/mixins/RuntimeItemsMixin.d.ts b/dist/js/entity/mixins/RuntimeItemsMixin.d.ts index 858b01db..91521250 100644 --- a/dist/js/entity/mixins/RuntimeItemsMixin.d.ts +++ b/dist/js/entity/mixins/RuntimeItemsMixin.d.ts @@ -1,4 +1,4 @@ -import type { NameResultSchema, RuntimeItemSchema } from "@mat3ra/esse/dist/js/types"; +import type { NameResultSchema } from "@mat3ra/esse/dist/js/types"; import type { Constructor } from "../../utils/types"; import { InMemoryEntity } from "../in_memory"; export declare enum ItemKey { @@ -19,25 +19,17 @@ export type BaseRuntimeItemsInMemoryEntity = InMemoryEntity & { defaultPreProcessors?: NameResultSchema[]; defaultPostProcessors?: NameResultSchema[]; }; -export declare function runtimeItemsMixin(item: BaseRuntimeItemsInMemoryEntity): { +export declare function runtimeItemsMixin(item: BaseRuntimeItemsInMemoryEntity): void; +export type RuntimeItemsInMemoryEntity = { results: NameResultSchema[]; monitors: NameResultSchema[]; preProcessors: NameResultSchema[]; postProcessors: NameResultSchema[]; - readonly resultNames: string[]; - readonly monitorNames: string[]; - readonly preProcessorNames: string[]; - readonly postProcessorNames: string[]; - _addRuntimeItem(key: ItemKey, config: RuntimeItemSchema): void; - _removeRuntimeItem(key: ItemKey, config: RuntimeItemSchema): void; - _removeRuntimeItemByName(key: ItemKey, name: string): void; - _toggleRuntimeItem(key: ItemKey, data: RuntimeItemSchema, isAdding: boolean): void; - toggleResult(data: RuntimeItemSchema, isAdding: boolean): void; - toggleMonitor(data: RuntimeItemSchema, isAdding: boolean): void; - togglePreProcessor(data: RuntimeItemSchema, isAdding: boolean): void; - togglePostProcessor(data: RuntimeItemSchema, isAdding: boolean): void; - getResultByName(name: string): NameResultSchema | undefined; + hashObjectFromRuntimeItems: { + results: NameResultSchema[]; + preProcessors: NameResultSchema[]; + postProcessors: NameResultSchema[]; + }; }; -export type RuntimeItemsInMemoryEntity = ReturnType; export type RuntimeItemsInMemoryEntityConstructor = Constructor; export default function RuntimeItemsMixin>(superclass: S): S & RuntimeItemsInMemoryEntityConstructor; diff --git a/dist/js/entity/mixins/RuntimeItemsMixin.js b/dist/js/entity/mixins/RuntimeItemsMixin.js index 0800a37b..1634358b 100644 --- a/dist/js/entity/mixins/RuntimeItemsMixin.js +++ b/dist/js/entity/mixins/RuntimeItemsMixin.js @@ -16,95 +16,35 @@ var ItemKey; * Is meant to work with Entity, InMemoryEntity b/c of `prop` extraction from `_json`. */ function runtimeItemsMixin(item) { + // @ts-expect-error - this is a hack to get the properties of the item const properties = { get results() { - const self = this; - return self.prop("results", self.defaultResults || []).map(object_1.safeMakeObject); - }, - set results(array) { - const self = this; - self.setProp("results", array); + var _a; + return this.prop("results", (_a = this.defaultResults) !== null && _a !== void 0 ? _a : []).map(object_1.safeMakeObject); }, get monitors() { - const self = this; - return self.prop("monitors", self.defaultMonitors || []).map(object_1.safeMakeObject); - }, - set monitors(array) { - const self = this; - self.setProp("monitors", array); + var _a; + return this.prop("monitors", (_a = this.defaultMonitors) !== null && _a !== void 0 ? _a : []).map(object_1.safeMakeObject); }, get preProcessors() { - const self = this; - return self.prop("preProcessors", self.defaultPreProcessors || []).map(object_1.safeMakeObject); - }, - set preProcessors(array) { - const self = this; - self.setProp("preProcessors", array); + var _a; + // TODO: safeMakeObject could return null. Should we throw an error here? + return this.prop("preProcessors", (_a = this.defaultPreProcessors) !== null && _a !== void 0 ? _a : []).map(object_1.safeMakeObject); }, get postProcessors() { - const self = this; - return self - .prop("postProcessors", self.defaultPostProcessors || []) - .map(object_1.safeMakeObject); - }, - set postProcessors(array) { - const self = this; - self.setProp("postProcessors", array); - }, - get resultNames() { - return this.results.map((r) => r === null || r === void 0 ? void 0 : r.name); - }, - get monitorNames() { - return this.monitors.map((r) => r === null || r === void 0 ? void 0 : r.name); - }, - get preProcessorNames() { - return this.preProcessors.map((r) => r === null || r === void 0 ? void 0 : r.name); - }, - get postProcessorNames() { - return this.postProcessors.map((r) => r === null || r === void 0 ? void 0 : r.name); - }, - _addRuntimeItem(key, config) { - const self = this; - const runtimeItems = self._json[key || ItemKey.results]; - if (!runtimeItems) { - throw new Error("not found"); - } - runtimeItems.push((0, object_1.safeMakeObject)(config)); - }, - _removeRuntimeItem(key, config) { - const newConfig = (0, object_1.safeMakeObject)(config); - this._removeRuntimeItemByName(key, (newConfig === null || newConfig === void 0 ? void 0 : newConfig.name) || ""); - }, - _removeRuntimeItemByName(key, name) { - const self = this; - self._json[key] = self._json[key].filter((x) => x.name !== name); - }, - _toggleRuntimeItem(key, data, isAdding) { - if (isAdding) { - this._addRuntimeItem(key, data); - } - else { - this._removeRuntimeItem(key, data); - } - }, - toggleResult(data, isAdding) { - this._toggleRuntimeItem(ItemKey.results, data, isAdding); - }, - toggleMonitor(data, isAdding) { - this._toggleRuntimeItem(ItemKey.monitors, data, isAdding); - }, - togglePreProcessor(data, isAdding) { - this._toggleRuntimeItem(ItemKey.preProcessors, data, isAdding); - }, - togglePostProcessor(data, isAdding) { - this._toggleRuntimeItem(ItemKey.postProcessors, data, isAdding); + var _a; + // TODO: safeMakeObject could return null. Should we throw an error here? + return this.prop("postProcessors", (_a = this.defaultPostProcessors) !== null && _a !== void 0 ? _a : []).map(object_1.safeMakeObject); }, - getResultByName(name) { - return this.results.find((r) => (r === null || r === void 0 ? void 0 : r.name) === name); + get hashObjectFromRuntimeItems() { + return { + results: this.results, + preProcessors: this.preProcessors, + postProcessors: this.postProcessors, + }; }, }; Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); - return properties; } function RuntimeItemsMixin(superclass) { class RuntimeItemsMixin extends superclass { diff --git a/dist/js/entity/mixins/runtime_items.d.ts b/dist/js/entity/mixins/runtime_items.d.ts index 569e081e..a5e844cb 100644 --- a/dist/js/entity/mixins/runtime_items.d.ts +++ b/dist/js/entity/mixins/runtime_items.d.ts @@ -66,6 +66,11 @@ export declare function RuntimeItemsUILogicMixin(superclass: T): { diff --git a/dist/js/entity/other.d.ts b/dist/js/entity/other.d.ts index 87915cdd..b2e97b20 100644 --- a/dist/js/entity/other.d.ts +++ b/dist/js/entity/other.d.ts @@ -369,6 +369,11 @@ export declare const NamedDefaultableRepetitionRuntimeItemsImportantSettingsCont monitors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; preProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; postProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + hashObjectFromRuntimeItems: { + results: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + preProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + postProcessors: import("@mat3ra/esse/dist/js/types").NameResultSchema[]; + }; }; } & { new (...args: any[]): { diff --git a/src/js/entity/mixins/RuntimeItemsMixin.ts b/src/js/entity/mixins/RuntimeItemsMixin.ts index 65bd554b..6f1dfbf5 100644 --- a/src/js/entity/mixins/RuntimeItemsMixin.ts +++ b/src/js/entity/mixins/RuntimeItemsMixin.ts @@ -1,4 +1,4 @@ -import type { NameResultSchema, RuntimeItemSchema } from "@mat3ra/esse/dist/js/types"; +import type { NameResultSchema } from "@mat3ra/esse/dist/js/types"; import { safeMakeObject } from "../../utils/object"; import type { Constructor } from "../../utils/types"; @@ -29,116 +29,52 @@ export type BaseRuntimeItemsInMemoryEntity = InMemoryEntity & { * Is meant to work with Entity, InMemoryEntity b/c of `prop` extraction from `_json`. */ export function runtimeItemsMixin(item: BaseRuntimeItemsInMemoryEntity) { - const properties = { - get results() { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - return self.prop("results", self.defaultResults || []).map(safeMakeObject); + // @ts-expect-error - this is a hack to get the properties of the item + const properties: BaseRuntimeItemsInMemoryEntity & RuntimeItemsInMemoryEntity = { + get results(): NameResultSchema[] { + return this.prop("results", this.defaultResults ?? []).map(safeMakeObject); }, - set results(array: NameResultSchema[]) { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - self.setProp("results", array); - }, - get monitors(): NameResultSchema[] { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - return self.prop("monitors", self.defaultMonitors || []).map(safeMakeObject); - }, - set monitors(array: NameResultSchema[]) { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - self.setProp("monitors", array); - }, - get preProcessors(): NameResultSchema[] { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - return self.prop("preProcessors", self.defaultPreProcessors || []).map(safeMakeObject); - }, - set preProcessors(array: NameResultSchema[]) { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - self.setProp("preProcessors", array); - }, - get postProcessors(): NameResultSchema[] { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - return self - .prop("postProcessors", self.defaultPostProcessors || []) - .map(safeMakeObject); - }, - set postProcessors(array: NameResultSchema[]) { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - self.setProp("postProcessors", array); - }, - - get resultNames() { - return this.results.map((r) => r?.name); - }, - - get monitorNames() { - return this.monitors.map((r) => r?.name); - }, - - get preProcessorNames() { - return this.preProcessors.map((r) => r?.name); - }, - - get postProcessorNames() { - return this.postProcessors.map((r) => r?.name); - }, - - _addRuntimeItem(key: ItemKey, config: RuntimeItemSchema) { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - const runtimeItems = self._json[key || ItemKey.results]; - if (!runtimeItems) { - throw new Error("not found"); - } - - runtimeItems.push(safeMakeObject(config)); + get monitors(): NameResultSchema[] { + return this.prop("monitors", this.defaultMonitors ?? []).map(safeMakeObject); }, - _removeRuntimeItem(key: ItemKey, config: RuntimeItemSchema) { - const newConfig = safeMakeObject(config); - this._removeRuntimeItemByName(key, newConfig?.name || ""); + get preProcessors(): NameResultSchema[] { + // TODO: safeMakeObject could return null. Should we throw an error here? + return this.prop("preProcessors", this.defaultPreProcessors ?? []).map(safeMakeObject); }, - _removeRuntimeItemByName(key: ItemKey, name: string) { - const self = this as unknown as BaseRuntimeItemsInMemoryEntity; - self._json[key] = (self._json[key] as NameResultSchema[]).filter( - (x) => x.name !== name, + get postProcessors(): NameResultSchema[] { + // TODO: safeMakeObject could return null. Should we throw an error here? + return this.prop("postProcessors", this.defaultPostProcessors ?? []).map( + safeMakeObject, ); }, - _toggleRuntimeItem(key: ItemKey, data: RuntimeItemSchema, isAdding: boolean) { - if (isAdding) { - this._addRuntimeItem(key, data); - } else { - this._removeRuntimeItem(key, data); - } - }, - - toggleResult(data: RuntimeItemSchema, isAdding: boolean) { - this._toggleRuntimeItem(ItemKey.results, data, isAdding); - }, - - toggleMonitor(data: RuntimeItemSchema, isAdding: boolean) { - this._toggleRuntimeItem(ItemKey.monitors, data, isAdding); - }, - - togglePreProcessor(data: RuntimeItemSchema, isAdding: boolean) { - this._toggleRuntimeItem(ItemKey.preProcessors, data, isAdding); - }, - - togglePostProcessor(data: RuntimeItemSchema, isAdding: boolean) { - this._toggleRuntimeItem(ItemKey.postProcessors, data, isAdding); - }, - - getResultByName(name: string) { - return this.results.find((r) => r?.name === name); + get hashObjectFromRuntimeItems() { + return { + results: this.results, + preProcessors: this.preProcessors, + postProcessors: this.postProcessors, + }; }, }; Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); - - return properties; } -export type RuntimeItemsInMemoryEntity = ReturnType; +export type RuntimeItemsInMemoryEntity = { + results: NameResultSchema[]; + monitors: NameResultSchema[]; + preProcessors: NameResultSchema[]; + postProcessors: NameResultSchema[]; + hashObjectFromRuntimeItems: { + results: NameResultSchema[]; + preProcessors: NameResultSchema[]; + postProcessors: NameResultSchema[]; + }; +}; + export type RuntimeItemsInMemoryEntityConstructor = Constructor; export default function RuntimeItemsMixin>( From 423654508eeec4a52fe38397e146fca7afd2f2a3 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 16 Jun 2025 13:43:14 +0300 Subject: [PATCH 03/10] chore: context mixins --- dist/js/context/JobContextMixin.d.ts | 11 ++ dist/js/context/JobContextMixin.js | 39 ++++ dist/js/context/MaterialContextMixin.d.ts | 24 +++ dist/js/context/MaterialContextMixin.js | 29 +++ dist/js/context/MaterialsContextMixin.d.ts | 18 ++ dist/js/context/MaterialsContextMixin.js | 30 +++ dist/js/context/MethodDataContextMixin.d.ts | 16 ++ dist/js/context/MethodDataContextMixin.js | 52 ++++++ dist/js/context/WorkflowContextMixin.d.ts | 11 ++ dist/js/context/WorkflowContextMixin.js | 27 +++ dist/js/context/mixins.d.ts | 65 +------ dist/js/context/mixins.js | 142 ++------------ src/js/context/JobContextMixin.ts | 59 ++++++ src/js/context/MaterialContextMixin.ts | 53 ++++++ src/js/context/MaterialsContextMixin.ts | 45 +++++ src/js/context/MethodDataContextMixin.ts | 74 ++++++++ src/js/context/WorkflowContextMixin.ts | 47 +++++ src/js/context/mixins.ts | 194 ++------------------ 18 files changed, 566 insertions(+), 370 deletions(-) create mode 100644 dist/js/context/JobContextMixin.d.ts create mode 100644 dist/js/context/JobContextMixin.js create mode 100644 dist/js/context/MaterialContextMixin.d.ts create mode 100644 dist/js/context/MaterialContextMixin.js create mode 100644 dist/js/context/MaterialsContextMixin.d.ts create mode 100644 dist/js/context/MaterialsContextMixin.js create mode 100644 dist/js/context/MethodDataContextMixin.d.ts create mode 100644 dist/js/context/MethodDataContextMixin.js create mode 100644 dist/js/context/WorkflowContextMixin.d.ts create mode 100644 dist/js/context/WorkflowContextMixin.js create mode 100644 src/js/context/JobContextMixin.ts create mode 100644 src/js/context/MaterialContextMixin.ts create mode 100644 src/js/context/MaterialsContextMixin.ts create mode 100644 src/js/context/MethodDataContextMixin.ts create mode 100644 src/js/context/WorkflowContextMixin.ts diff --git a/dist/js/context/JobContextMixin.d.ts b/dist/js/context/JobContextMixin.d.ts new file mode 100644 index 00000000..dfa82e02 --- /dev/null +++ b/dist/js/context/JobContextMixin.d.ts @@ -0,0 +1,11 @@ +import type { JobSchema } from "@mat3ra/esse/dist/js/types"; +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; +export type JobContextMixinType = { + isEdited?: boolean; + job: JobSchema; + _job: JobSchema; + initJobContextMixin: () => void; +}; +export declare function jobContextMixin(item: ContextProvider): void; +export declare function JobContextMixin>(superclass: T): T & Constructor; diff --git a/dist/js/context/JobContextMixin.js b/dist/js/context/JobContextMixin.js new file mode 100644 index 00000000..3c46b4ec --- /dev/null +++ b/dist/js/context/JobContextMixin.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.jobContextMixin = jobContextMixin; +exports.JobContextMixin = JobContextMixin; +const defaultJob = { + workflow: { + subworkflows: [], + units: [], + }, + status: "pre-submission", + compute: { + queue: "D", + nodes: 1, + ppn: 1, + timeLimit: "3600", + }, + _project: { + _id: "", + }, +}; +function jobContextMixin(item) { + const properties = { + isEdited: false, + _job: defaultJob, + get job() { + return this._job; + }, + initJobContextMixin() { + const config = this.config; + this._job = (config.context && config.context.job) || defaultJob; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} +function JobContextMixin(superclass) { + jobContextMixin(superclass.prototype); + return superclass; +} diff --git a/dist/js/context/MaterialContextMixin.d.ts b/dist/js/context/MaterialContextMixin.d.ts new file mode 100644 index 00000000..86351723 --- /dev/null +++ b/dist/js/context/MaterialContextMixin.d.ts @@ -0,0 +1,24 @@ +import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import type { InMemoryEntity } from "../entity/in_memory"; +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; +type Material = InMemoryEntity & MaterialSchema & { + hash: string; +}; +export type MaterialContextMixinType = { + isEditedIsSetToFalseOnMaterialUpdate?: boolean; + updateMaterialHash: () => void; + isMaterialCreatedDefault: boolean; + isMaterialUpdated: boolean; + material: Material; + extraData?: { + materialHash: string; + }; +}; +export declare function materialContextMixin(item: ContextProvider & { + _material: Material; +}): void; +export declare function MaterialContextMixin>(superclass: T): T & Constructor; +export {}; diff --git a/dist/js/context/MaterialContextMixin.js b/dist/js/context/MaterialContextMixin.js new file mode 100644 index 00000000..be3fed5b --- /dev/null +++ b/dist/js/context/MaterialContextMixin.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.materialContextMixin = materialContextMixin; +exports.MaterialContextMixin = MaterialContextMixin; +function materialContextMixin(item) { + const properties = { + updateMaterialHash() { + if (this.isEditedIsSetToFalseOnMaterialUpdate) + this.isEdited = false; + this.extraData = { materialHash: this.material.hash }; + }, + // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too + // does not have an id. Here we catch when such material is used and avoid resetting isEdited + get isMaterialCreatedDefault() { + return !this.material.id; + }, + get isMaterialUpdated() { + return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); + }, + get material() { + return this._material; + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} +function MaterialContextMixin(superclass) { + materialContextMixin(superclass.prototype); + return superclass; +} diff --git a/dist/js/context/MaterialsContextMixin.d.ts b/dist/js/context/MaterialsContextMixin.d.ts new file mode 100644 index 00000000..7edabbb9 --- /dev/null +++ b/dist/js/context/MaterialsContextMixin.d.ts @@ -0,0 +1,18 @@ +import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; +import type { InMemoryEntity } from "../entity/in_memory"; +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; +type Material = InMemoryEntity & MaterialSchema & { + hash: string; +}; +type MaterialsContextMixinType = { + materials: Material[]; + initMaterialsContextMixin: () => void; +}; +export declare function materialsContextMixin(item: ContextProvider & { + _materials: Material[]; +}): void; +export declare function MaterialsContextMixin>(superclass: T): T & Constructor; +export {}; diff --git a/dist/js/context/MaterialsContextMixin.js b/dist/js/context/MaterialsContextMixin.js new file mode 100644 index 00000000..a3439741 --- /dev/null +++ b/dist/js/context/MaterialsContextMixin.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.materialsContextMixin = materialsContextMixin; +exports.MaterialsContextMixin = MaterialsContextMixin; +function materialsContextMixin(item) { + const properties = { + get materials() { + return this._materials; + }, + initMaterialsContextMixin() { + var _a; + // @ts-ignore + const materials = (_a = this.config.context) === null || _a === void 0 ? void 0 : _a.materials; + // @ts-ignore + if (!this.constructor.Material) { + throw Error("MaterialsContextMixin: Material is undefined"); + } + this._materials = + materials && materials.length + ? materials + : // @ts-ignore + [this.constructor.Material.createDefault()]; + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} +function MaterialsContextMixin(superclass) { + materialsContextMixin(superclass.prototype); + return superclass; +} diff --git a/dist/js/context/MethodDataContextMixin.d.ts b/dist/js/context/MethodDataContextMixin.d.ts new file mode 100644 index 00000000..b4693339 --- /dev/null +++ b/dist/js/context/MethodDataContextMixin.d.ts @@ -0,0 +1,16 @@ +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; +export type MethodDataContextMixinType = { + isEdited?: boolean; + methodDataHash?: string; + extraData?: { + methodDataHash?: string; + }; + methodData: any; + _methodData: any; + isMethodDataUpdated: boolean; + _initMethodDataHash: () => void; + initMethodDataContextMixin: () => void; +}; +export declare function methodDataContextMixin(item: ContextProvider): void; +export declare function MethodDataContextMixin>(superclass: T): T & Constructor; diff --git a/dist/js/context/MethodDataContextMixin.js b/dist/js/context/MethodDataContextMixin.js new file mode 100644 index 00000000..a72f842d --- /dev/null +++ b/dist/js/context/MethodDataContextMixin.js @@ -0,0 +1,52 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.methodDataContextMixin = methodDataContextMixin; +exports.MethodDataContextMixin = MethodDataContextMixin; +const crypto_js_1 = __importDefault(require("crypto-js")); +function methodDataContextMixin(item) { + const properties = { + isEdited: false, + _methodData: {}, + get methodData() { + return this._methodData; + }, + get isMethodDataUpdated() { + return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); + }, + initMethodDataContextMixin() { + const config = this.config; + this._methodData = (config.context && config.context.methodData) || {}; + this.isEdited = Boolean(config.isEdited); + }, + /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between + * subsequent initializations of the derived class. Not used at present and kept for the record. + */ + _initMethodDataHash() { + this.methodDataHash = crypto_js_1.default.MD5(JSON.stringify(this.methodData)).toString(); + this.extraData = { methodDataHash: this.methodDataHash }; + if (!this._methodData) { + this._methodData = {}; + this.isEdited = false; + // Commented out to reduce effect on performance. Uncomment for debugging purposes. + // TODO: remove on next refactoring or convert to log + // console.warn("MethodDataContextMixin: methodData is undefined or null"); + } + else if (this.isMethodDataUpdated) { + this.isEdited = false; + } + else { + // @ts-ignore + // eslint-disable-next-line no-undef + this.isEdited = this.config.isEdited; + } + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} +function MethodDataContextMixin(superclass) { + methodDataContextMixin(superclass.prototype); + return superclass; +} diff --git a/dist/js/context/WorkflowContextMixin.d.ts b/dist/js/context/WorkflowContextMixin.d.ts new file mode 100644 index 00000000..95b2c65f --- /dev/null +++ b/dist/js/context/WorkflowContextMixin.d.ts @@ -0,0 +1,11 @@ +import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; +export type WorkflowContextMixinType = { + isEdited?: boolean; + workflow: WorkflowSchema; + _workflow: WorkflowSchema; + initWorkflowContextMixin: () => void; +}; +export declare function workflowContextMixin(item: ContextProvider): void; +export declare function WorkflowContextMixin>(superclass: T): T & Constructor; diff --git a/dist/js/context/WorkflowContextMixin.js b/dist/js/context/WorkflowContextMixin.js new file mode 100644 index 00000000..90b24291 --- /dev/null +++ b/dist/js/context/WorkflowContextMixin.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.workflowContextMixin = workflowContextMixin; +exports.WorkflowContextMixin = WorkflowContextMixin; +const defaultWorkflow = { + subworkflows: [], + units: [], +}; +function workflowContextMixin(item) { + const properties = { + isEdited: false, + _workflow: defaultWorkflow, + get workflow() { + return this._workflow; + }, + initWorkflowContextMixin() { + const config = this.config; + this._workflow = (config.context && config.context.workflow) || defaultWorkflow; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + }, + }; + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} +function WorkflowContextMixin(superclass) { + workflowContextMixin(superclass.prototype); + return superclass; +} diff --git a/dist/js/context/mixins.d.ts b/dist/js/context/mixins.d.ts index 37ed8288..754667f3 100644 --- a/dist/js/context/mixins.d.ts +++ b/dist/js/context/mixins.d.ts @@ -1,6 +1,10 @@ -import { ApplicationSchemaBase, JobSchema, MaterialSchema, WorkflowSchema } from "@mat3ra/esse/dist/js/types"; -import { InMemoryEntity } from "../entity"; +import { ApplicationSchemaBase } from "@mat3ra/esse/dist/js/types"; import type { OrderedInMemoryEntityInSet } from "../entity/set/ordered/OrderedInMemoryEntityInSetMixin"; +import { JobContextMixin } from "./JobContextMixin"; +import { MaterialContextMixin } from "./MaterialContextMixin"; +import { MaterialsContextMixin } from "./MaterialsContextMixin"; +import { MethodDataContextMixin } from "./MethodDataContextMixin"; +import { WorkflowContextMixin } from "./WorkflowContextMixin"; type Constructor = new (...args: any[]) => T; export declare function ApplicationContextMixin(superclass: T): { new (...args: any): { @@ -9,24 +13,7 @@ export declare function ApplicationContextMixin(superclas readonly application: ApplicationSchemaBase; }; } & T; -type Material = InMemoryEntity & MaterialSchema & { - hash: string; -}; -export declare function MaterialContextMixin(superclass: T): { - new (...args: any): { - [x: string]: any; - _material: Material; - extraData?: { - materialHash: string; - }; - isEdited?: boolean; - readonly isEditedIsSetToFalseOnMaterialUpdate: boolean; - updateMaterialHash(): void; - readonly isMaterialCreatedDefault: boolean; - readonly isMaterialUpdated: boolean; - readonly material: Material; - }; -} & T; +export { MaterialContextMixin, MaterialsContextMixin, MethodDataContextMixin, WorkflowContextMixin, JobContextMixin, }; export declare function MaterialsSetContextMixin(superclass: T): { new (...params: any): { [x: string]: any; @@ -37,41 +24,3 @@ export declare function MaterialsSetContextMixin(supercla }[]; }; } & T; -export declare function MaterialsContextMixin(superclass: T): { - new (...params: any): { - [x: string]: any; - _materials: any; - readonly materials: any; - }; -} & T; -export declare function MethodDataContextMixin(superclass: T): { - new (...params: any): { - [x: string]: any; - _methodData: any; - isEdited: boolean; - methodDataHash?: string; - extraData?: { - methodDataHash?: string; - }; - _initMethodDataHash(): void; - readonly methodData: any; - readonly isMethodDataUpdated: boolean; - }; -} & T; -export declare function WorkflowContextMixin(superclass: T): { - new (...params: any): { - [x: string]: any; - _workflow: WorkflowSchema; - isEdited: boolean; - readonly workflow: WorkflowSchema; - }; -} & T; -export declare function JobContextMixin(superclass: T): { - new (...params: any): { - [x: string]: any; - _job: JobSchema; - isEdited: boolean; - readonly job: JobSchema; - }; -} & T; -export {}; diff --git a/dist/js/context/mixins.js b/dist/js/context/mixins.js index d653b26a..7ba6f128 100644 --- a/dist/js/context/mixins.js +++ b/dist/js/context/mixins.js @@ -1,17 +1,19 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); +exports.JobContextMixin = exports.WorkflowContextMixin = exports.MethodDataContextMixin = exports.MaterialsContextMixin = exports.MaterialContextMixin = void 0; exports.ApplicationContextMixin = ApplicationContextMixin; -exports.MaterialContextMixin = MaterialContextMixin; exports.MaterialsSetContextMixin = MaterialsSetContextMixin; -exports.MaterialsContextMixin = MaterialsContextMixin; -exports.MethodDataContextMixin = MethodDataContextMixin; -exports.WorkflowContextMixin = WorkflowContextMixin; -exports.JobContextMixin = JobContextMixin; -const crypto_js_1 = __importDefault(require("crypto-js")); const utils_1 = require("../entity/set/ordered/utils"); +const JobContextMixin_1 = require("./JobContextMixin"); +Object.defineProperty(exports, "JobContextMixin", { enumerable: true, get: function () { return JobContextMixin_1.JobContextMixin; } }); +const MaterialContextMixin_1 = require("./MaterialContextMixin"); +Object.defineProperty(exports, "MaterialContextMixin", { enumerable: true, get: function () { return MaterialContextMixin_1.MaterialContextMixin; } }); +const MaterialsContextMixin_1 = require("./MaterialsContextMixin"); +Object.defineProperty(exports, "MaterialsContextMixin", { enumerable: true, get: function () { return MaterialsContextMixin_1.MaterialsContextMixin; } }); +const MethodDataContextMixin_1 = require("./MethodDataContextMixin"); +Object.defineProperty(exports, "MethodDataContextMixin", { enumerable: true, get: function () { return MethodDataContextMixin_1.MethodDataContextMixin; } }); +const WorkflowContextMixin_1 = require("./WorkflowContextMixin"); +Object.defineProperty(exports, "WorkflowContextMixin", { enumerable: true, get: function () { return WorkflowContextMixin_1.WorkflowContextMixin; } }); function ApplicationContextMixin(superclass) { return class ApplicationContextMixin extends superclass { constructor(...args) { @@ -31,44 +33,6 @@ function ApplicationContextMixin(superclass) { } }; } -function MaterialContextMixin(superclass) { - return class MaterialContextMixin extends superclass { - constructor(...args) { - super(...args); - // @ts-ignore - if (!this.constructor.Material) { - throw Error("MaterialContextMixin: Material is undefined"); - } - const config = args[0]; - this._material = config.context && config.context.material; - // @ts-ignore - if (!this._material) - // @ts-ignore - this._material = this.constructor.Material.createDefault(); - this.updateMaterialHash(); - } - // eslint-disable-next-line class-methods-use-this - get isEditedIsSetToFalseOnMaterialUpdate() { - return false; - } - updateMaterialHash() { - if (this.isEditedIsSetToFalseOnMaterialUpdate) - this.isEdited = false; - this.extraData = { materialHash: this.material.hash }; - } - // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too - // does not have an id. Here we catch when such material is used and avoid resetting isEdited - get isMaterialCreatedDefault() { - return !this.material.id; - } - get isMaterialUpdated() { - return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); - } - get material() { - return this._material; - } - }; -} function MaterialsSetContextMixin(superclass) { return class MaterialsSetContextMixin extends superclass { constructor(...params) { @@ -86,87 +50,3 @@ function MaterialsSetContextMixin(superclass) { } }; } -function MaterialsContextMixin(superclass) { - return class MaterialsContextMixin extends superclass { - constructor(...params) { - super(...params); - const materials = this.config.context && this.config.context.materials; - // @ts-ignore - if (!this.constructor.Material) { - throw Error("MaterialsContextMixin: Material is undefined"); - } - this._materials = - materials && materials.length - ? materials - : // @ts-ignore - [this.constructor.Material.createDefault()]; - } - get materials() { - return this._materials; - } - }; -} -function MethodDataContextMixin(superclass) { - return class extends superclass { - constructor(...params) { - super(...params); - const config = params[0]; - this._methodData = (config.context && config.context.methodData) || {}; - this.isEdited = Boolean(config.isEdited); - } - /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between - * subsequent initializations of the derived class. Not used at present and kept for the record. - */ - _initMethodDataHash() { - this.methodDataHash = crypto_js_1.default.MD5(JSON.stringify(this.methodData)).toString(); - this.extraData = { methodDataHash: this.methodDataHash }; - if (!this._methodData) { - this._methodData = {}; - this.isEdited = false; - // Commented out to reduce effect on performance. Uncomment for debugging purposes. - // TODO: remove on next refactoring or convert to log - // console.warn("MethodDataContextMixin: methodData is undefined or null"); - } - else if (this.isMethodDataUpdated) { - this.isEdited = false; - } - else { - // @ts-ignore - // eslint-disable-next-line no-undef - this.isEdited = config.isEdited; - } - } - get methodData() { - return this._methodData; - } - get isMethodDataUpdated() { - return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); - } - }; -} -function WorkflowContextMixin(superclass) { - return class extends superclass { - constructor(...params) { - super(...params); - const config = params[0]; - this._workflow = (config.context && config.context.workflow) || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } - get workflow() { - return this._workflow; - } - }; -} -function JobContextMixin(superclass) { - return class extends superclass { - constructor(...params) { - super(...params); - const config = params[0]; - this._job = (config.context && config.context.job) || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } - get job() { - return this._job; - } - }; -} diff --git a/src/js/context/JobContextMixin.ts b/src/js/context/JobContextMixin.ts new file mode 100644 index 00000000..677519b0 --- /dev/null +++ b/src/js/context/JobContextMixin.ts @@ -0,0 +1,59 @@ +import type { JobSchema } from "@mat3ra/esse/dist/js/types"; + +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; + +type JobConfig = { + context?: { + job?: JobSchema; + }; +}; + +const defaultJob: JobSchema = { + workflow: { + subworkflows: [], + units: [], + }, + status: "pre-submission", + compute: { + queue: "D", + nodes: 1, + ppn: 1, + timeLimit: "3600", + }, + _project: { + _id: "", + }, +}; + +export type JobContextMixinType = { + isEdited?: boolean; + job: JobSchema; + _job: JobSchema; + initJobContextMixin: () => void; +}; + +export function jobContextMixin(item: ContextProvider) { + const properties = { + isEdited: false, + + _job: defaultJob, + + get job() { + return this._job; + }, + + initJobContextMixin() { + const config = this.config as JobConfig; + this._job = (config.context && config.context.job) || defaultJob; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + }, + } as JobContextMixinType & typeof item; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} + +export function JobContextMixin>(superclass: T) { + jobContextMixin(superclass.prototype); + return superclass as T & Constructor; +} diff --git a/src/js/context/MaterialContextMixin.ts b/src/js/context/MaterialContextMixin.ts new file mode 100644 index 00000000..5efb149b --- /dev/null +++ b/src/js/context/MaterialContextMixin.ts @@ -0,0 +1,53 @@ +import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; + +import type { InMemoryEntity } from "../entity/in_memory"; +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; + +type Material = InMemoryEntity & + MaterialSchema & { + hash: string; + }; + +export type MaterialContextMixinType = { + isEditedIsSetToFalseOnMaterialUpdate?: boolean; + updateMaterialHash: () => void; + isMaterialCreatedDefault: boolean; + isMaterialUpdated: boolean; + material: Material; + extraData?: { + materialHash: string; + }; +}; + +export function materialContextMixin(item: ContextProvider & { _material: Material }) { + const properties = { + updateMaterialHash() { + if (this.isEditedIsSetToFalseOnMaterialUpdate) this.isEdited = false; + this.extraData = { materialHash: this.material.hash }; + }, + + // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too + // does not have an id. Here we catch when such material is used and avoid resetting isEdited + get isMaterialCreatedDefault() { + return !this.material.id; + }, + + get isMaterialUpdated() { + return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); + }, + + get material() { + return this._material; + }, + } as MaterialContextMixinType & typeof item; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} + +export function MaterialContextMixin< + T extends Constructor, +>(superclass: T) { + materialContextMixin(superclass.prototype); + return superclass as T & Constructor; +} diff --git a/src/js/context/MaterialsContextMixin.ts b/src/js/context/MaterialsContextMixin.ts new file mode 100644 index 00000000..bad3a3a3 --- /dev/null +++ b/src/js/context/MaterialsContextMixin.ts @@ -0,0 +1,45 @@ +import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; + +import type { InMemoryEntity } from "../entity/in_memory"; +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; + +type Material = InMemoryEntity & + MaterialSchema & { + hash: string; + }; + +type MaterialsContextMixinType = { + materials: Material[]; + initMaterialsContextMixin: () => void; +}; + +export function materialsContextMixin(item: ContextProvider & { _materials: Material[] }) { + const properties = { + get materials() { + return this._materials; + }, + initMaterialsContextMixin() { + // @ts-ignore + const materials = this.config.context?.materials; + // @ts-ignore + if (!this.constructor.Material) { + throw Error("MaterialsContextMixin: Material is undefined"); + } + this._materials = + materials && materials.length + ? materials + : // @ts-ignore + [this.constructor.Material.createDefault()]; + }, + } as MaterialsContextMixinType & typeof item; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} + +export function MaterialsContextMixin< + T extends Constructor, +>(superclass: T) { + materialsContextMixin(superclass.prototype); + return superclass as T & Constructor; +} diff --git a/src/js/context/MethodDataContextMixin.ts b/src/js/context/MethodDataContextMixin.ts new file mode 100644 index 00000000..03282a8f --- /dev/null +++ b/src/js/context/MethodDataContextMixin.ts @@ -0,0 +1,74 @@ +import CryptoJS from "crypto-js"; + +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; + +type MethodDataConfig = { + context?: { + methodData?: any; + }; + isEdited?: boolean; +}; + +export type MethodDataContextMixinType = { + isEdited?: boolean; + methodDataHash?: string; + extraData?: { + methodDataHash?: string; + }; + methodData: any; + _methodData: any; + isMethodDataUpdated: boolean; + _initMethodDataHash: () => void; + initMethodDataContextMixin: () => void; +}; + +export function methodDataContextMixin(item: ContextProvider) { + const properties = { + isEdited: false, + + _methodData: {}, + + get methodData() { + return this._methodData; + }, + + get isMethodDataUpdated() { + return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); + }, + + initMethodDataContextMixin() { + const config = this.config as MethodDataConfig; + this._methodData = (config.context && config.context.methodData) || {}; + this.isEdited = Boolean(config.isEdited); + }, + + /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between + * subsequent initializations of the derived class. Not used at present and kept for the record. + */ + _initMethodDataHash() { + this.methodDataHash = CryptoJS.MD5(JSON.stringify(this.methodData)).toString(); + this.extraData = { methodDataHash: this.methodDataHash }; + if (!this._methodData) { + this._methodData = {}; + this.isEdited = false; + // Commented out to reduce effect on performance. Uncomment for debugging purposes. + // TODO: remove on next refactoring or convert to log + // console.warn("MethodDataContextMixin: methodData is undefined or null"); + } else if (this.isMethodDataUpdated) { + this.isEdited = false; + } else { + // @ts-ignore + // eslint-disable-next-line no-undef + this.isEdited = this.config.isEdited; + } + }, + } as MethodDataContextMixinType & typeof item; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} + +export function MethodDataContextMixin>(superclass: T) { + methodDataContextMixin(superclass.prototype); + return superclass as T & Constructor; +} diff --git a/src/js/context/WorkflowContextMixin.ts b/src/js/context/WorkflowContextMixin.ts new file mode 100644 index 00000000..3081d5fb --- /dev/null +++ b/src/js/context/WorkflowContextMixin.ts @@ -0,0 +1,47 @@ +import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; + +import type { Constructor } from "../utils/types"; +import type { ContextProvider } from "./provider"; + +type WorkflowConfig = { + context?: { + workflow?: WorkflowSchema; + }; +}; + +const defaultWorkflow: WorkflowSchema = { + subworkflows: [], + units: [], +}; + +export type WorkflowContextMixinType = { + isEdited?: boolean; + workflow: WorkflowSchema; + _workflow: WorkflowSchema; + initWorkflowContextMixin: () => void; +}; + +export function workflowContextMixin(item: ContextProvider) { + const properties = { + isEdited: false, + + _workflow: defaultWorkflow, + + get workflow() { + return this._workflow; + }, + + initWorkflowContextMixin() { + const config = this.config as WorkflowConfig; + this._workflow = (config.context && config.context.workflow) || defaultWorkflow; + this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) + }, + } as WorkflowContextMixinType & typeof item; + + Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); +} + +export function WorkflowContextMixin>(superclass: T) { + workflowContextMixin(superclass.prototype); + return superclass as T & Constructor; +} diff --git a/src/js/context/mixins.ts b/src/js/context/mixins.ts index 0cde0edf..2497cf18 100644 --- a/src/js/context/mixins.ts +++ b/src/js/context/mixins.ts @@ -1,16 +1,14 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { - ApplicationSchemaBase, - JobSchema, - MaterialSchema, - WorkflowSchema, -} from "@mat3ra/esse/dist/js/types"; -import CryptoJS from "crypto-js"; +import { ApplicationSchemaBase } from "@mat3ra/esse/dist/js/types"; -import { InMemoryEntity } from "../entity"; import { DefaultableMixin } from "../entity/mixins/props"; import type { OrderedInMemoryEntityInSet } from "../entity/set/ordered/OrderedInMemoryEntityInSetMixin"; import { compareEntitiesInOrderedSetForSorting } from "../entity/set/ordered/utils"; +import { JobContextMixin } from "./JobContextMixin"; +import { MaterialContextMixin } from "./MaterialContextMixin"; +import { MaterialsContextMixin } from "./MaterialsContextMixin"; +import { MethodDataContextMixin } from "./MethodDataContextMixin"; +import { WorkflowContextMixin } from "./WorkflowContextMixin"; type Constructor = new (...args: any[]) => T; @@ -39,61 +37,13 @@ export function ApplicationContextMixin(superclass: T) { }; } -type Material = InMemoryEntity & - MaterialSchema & { - hash: string; - }; - -export function MaterialContextMixin(superclass: T) { - return class MaterialContextMixin extends superclass { - _material: Material; - - extraData?: { - materialHash: string; - }; - - declare isEdited?: boolean; - - constructor(...args: any) { - super(...args); - // @ts-ignore - if (!this.constructor.Material) { - throw Error("MaterialContextMixin: Material is undefined"); - } - const config = args[0]; - this._material = config.context && config.context.material; - // @ts-ignore - if (!this._material) - // @ts-ignore - this._material = (this.constructor.Material as Defaultable).createDefault(); - this.updateMaterialHash(); - } - - // eslint-disable-next-line class-methods-use-this - get isEditedIsSetToFalseOnMaterialUpdate() { - return false; - } - - updateMaterialHash() { - if (this.isEditedIsSetToFalseOnMaterialUpdate) this.isEdited = false; - this.extraData = { materialHash: this.material.hash }; - } - - // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too - // does not have an id. Here we catch when such material is used and avoid resetting isEdited - get isMaterialCreatedDefault() { - return !this.material.id; - } - - get isMaterialUpdated() { - return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); - } - - get material() { - return this._material; - } - }; -} +export { + MaterialContextMixin, + MaterialsContextMixin, + MethodDataContextMixin, + WorkflowContextMixin, + JobContextMixin, +}; export function MaterialsSetContextMixin(superclass: T) { return class MaterialsSetContextMixin extends superclass { @@ -116,121 +66,3 @@ export function MaterialsSetContextMixin(superclass: T) { } }; } - -export function MaterialsContextMixin(superclass: T) { - return class MaterialsContextMixin extends superclass { - _materials: any; - - constructor(...params: any) { - super(...params); - const materials = this.config.context && this.config.context.materials; - // @ts-ignore - if (!this.constructor.Material) { - throw Error("MaterialsContextMixin: Material is undefined"); - } - this._materials = - materials && materials.length - ? materials - : // @ts-ignore - [this.constructor.Material.createDefault()]; - } - - get materials() { - return this._materials; - } - }; -} - -export function MethodDataContextMixin(superclass: T) { - return class extends superclass { - _methodData: any; - - isEdited: boolean; - - methodDataHash?: string; - - extraData?: { - methodDataHash?: string; - }; - - constructor(...params: any) { - super(...params); - - const config = params[0]; - - this._methodData = (config.context && config.context.methodData) || {}; - this.isEdited = Boolean(config.isEdited); - } - - /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between - * subsequent initializations of the derived class. Not used at present and kept for the record. - */ - _initMethodDataHash() { - this.methodDataHash = CryptoJS.MD5(JSON.stringify(this.methodData)).toString(); - this.extraData = { methodDataHash: this.methodDataHash }; - if (!this._methodData) { - this._methodData = {}; - this.isEdited = false; - // Commented out to reduce effect on performance. Uncomment for debugging purposes. - // TODO: remove on next refactoring or convert to log - // console.warn("MethodDataContextMixin: methodData is undefined or null"); - } else if (this.isMethodDataUpdated) { - this.isEdited = false; - } else { - // @ts-ignore - // eslint-disable-next-line no-undef - this.isEdited = config.isEdited; - } - } - - get methodData() { - return this._methodData; - } - - get isMethodDataUpdated() { - return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); - } - }; -} - -export function WorkflowContextMixin(superclass: T) { - return class extends superclass { - _workflow: WorkflowSchema; - - isEdited: boolean; - - constructor(...params: any) { - super(...params); - - const config = params[0]; - - this._workflow = (config.context && config.context.workflow) || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } - - get workflow() { - return this._workflow; - } - }; -} - -export function JobContextMixin(superclass: T) { - return class extends superclass { - _job: JobSchema; - - isEdited: boolean; - - constructor(...params: any) { - super(...params); - - const config = params[0]; - - this._job = (config.context && config.context.job) || {}; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - } - - get job() { - return this._job; - } - }; -} From 433b5e25a1153ea04d5660fcef27693a1dfd8417 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 16 Jun 2025 15:39:52 +0300 Subject: [PATCH 04/10] chore: context mixins types --- dist/js/context/MethodDataContextMixin.d.ts | 13 +++++++++++-- src/js/context/MethodDataContextMixin.ts | 16 +++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/dist/js/context/MethodDataContextMixin.d.ts b/dist/js/context/MethodDataContextMixin.d.ts index b4693339..6f1baa17 100644 --- a/dist/js/context/MethodDataContextMixin.d.ts +++ b/dist/js/context/MethodDataContextMixin.d.ts @@ -1,16 +1,25 @@ import type { Constructor } from "../utils/types"; import type { ContextProvider } from "./provider"; +interface Pseudo { + element: string; + filename?: string; + path?: string; +} +interface MethodData { + pseudo?: Pseudo[]; +} export type MethodDataContextMixinType = { isEdited?: boolean; methodDataHash?: string; extraData?: { methodDataHash?: string; }; - methodData: any; - _methodData: any; + methodData: MethodData; + _methodData: MethodData; isMethodDataUpdated: boolean; _initMethodDataHash: () => void; initMethodDataContextMixin: () => void; }; export declare function methodDataContextMixin(item: ContextProvider): void; export declare function MethodDataContextMixin>(superclass: T): T & Constructor; +export {}; diff --git a/src/js/context/MethodDataContextMixin.ts b/src/js/context/MethodDataContextMixin.ts index 03282a8f..3af29376 100644 --- a/src/js/context/MethodDataContextMixin.ts +++ b/src/js/context/MethodDataContextMixin.ts @@ -3,9 +3,19 @@ import CryptoJS from "crypto-js"; import type { Constructor } from "../utils/types"; import type { ContextProvider } from "./provider"; +interface Pseudo { + element: string; + filename?: string; + path?: string; +} + +interface MethodData { + pseudo?: Pseudo[]; +} + type MethodDataConfig = { context?: { - methodData?: any; + methodData?: MethodData; }; isEdited?: boolean; }; @@ -16,8 +26,8 @@ export type MethodDataContextMixinType = { extraData?: { methodDataHash?: string; }; - methodData: any; - _methodData: any; + methodData: MethodData; + _methodData: MethodData; isMethodDataUpdated: boolean; _initMethodDataHash: () => void; initMethodDataContextMixin: () => void; From 3f12b20c2c6100c661631d448e63f6eb1a9ca55d Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Mon, 16 Jun 2025 15:45:12 +0300 Subject: [PATCH 05/10] chore: context mixins types --- dist/js/context/MethodDataContextMixin.d.ts | 11 ++++++++--- src/js/context/MethodDataContextMixin.ts | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/dist/js/context/MethodDataContextMixin.d.ts b/dist/js/context/MethodDataContextMixin.d.ts index 6f1baa17..f7f31fd4 100644 --- a/dist/js/context/MethodDataContextMixin.d.ts +++ b/dist/js/context/MethodDataContextMixin.d.ts @@ -1,13 +1,19 @@ import type { Constructor } from "../utils/types"; import type { ContextProvider } from "./provider"; -interface Pseudo { +export interface Pseudo { element: string; filename?: string; path?: string; } -interface MethodData { +export interface MethodData { pseudo?: Pseudo[]; } +export type MethodDataConfig = { + context?: { + methodData?: MethodData; + }; + isEdited?: boolean; +}; export type MethodDataContextMixinType = { isEdited?: boolean; methodDataHash?: string; @@ -22,4 +28,3 @@ export type MethodDataContextMixinType = { }; export declare function methodDataContextMixin(item: ContextProvider): void; export declare function MethodDataContextMixin>(superclass: T): T & Constructor; -export {}; diff --git a/src/js/context/MethodDataContextMixin.ts b/src/js/context/MethodDataContextMixin.ts index 3af29376..552ad2d9 100644 --- a/src/js/context/MethodDataContextMixin.ts +++ b/src/js/context/MethodDataContextMixin.ts @@ -3,17 +3,17 @@ import CryptoJS from "crypto-js"; import type { Constructor } from "../utils/types"; import type { ContextProvider } from "./provider"; -interface Pseudo { +export interface Pseudo { element: string; filename?: string; path?: string; } -interface MethodData { +export interface MethodData { pseudo?: Pseudo[]; } -type MethodDataConfig = { +export type MethodDataConfig = { context?: { methodData?: MethodData; }; From 05924d1e00a9ea88e0bfd70703b4c22b8c8537a1 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Tue, 17 Jun 2025 14:25:54 +0300 Subject: [PATCH 06/10] chore: types for context providers --- dist/js/context/index.d.ts | 4 +- dist/js/context/index.js | 8 +- dist/js/context/mixins.d.ts | 18 +- dist/js/context/mixins.js | 55 +++--- dist/js/context/provider.d.ts | 12 +- dist/js/context/registry.d.ts | 59 ++++-- dist/js/context/registry.js | 13 +- src/js/context/JobContextMixin.ts | 59 ------ src/js/context/MaterialContextMixin.ts | 53 ----- src/js/context/MaterialsContextMixin.ts | 45 ----- src/js/context/MethodDataContextMixin.ts | 84 -------- src/js/context/WorkflowContextMixin.ts | 47 ----- src/js/context/index.ts | 24 +-- src/js/context/mixins.ts | 64 +++--- src/js/context/provider.ts | 12 +- src/js/context/{registry.js => registry.ts} | 62 ++++-- tests/js/context.tests.ts | 204 ++++++++++---------- 17 files changed, 289 insertions(+), 534 deletions(-) delete mode 100644 src/js/context/JobContextMixin.ts delete mode 100644 src/js/context/MaterialContextMixin.ts delete mode 100644 src/js/context/MaterialsContextMixin.ts delete mode 100644 src/js/context/MethodDataContextMixin.ts delete mode 100644 src/js/context/WorkflowContextMixin.ts rename src/js/context/{registry.js => registry.ts} (55%) diff --git a/dist/js/context/index.d.ts b/dist/js/context/index.d.ts index d948761d..d3679e3e 100644 --- a/dist/js/context/index.d.ts +++ b/dist/js/context/index.d.ts @@ -1,6 +1,6 @@ import { JSONSchemaFormDataProvider } from "./json_schema_provider"; -import { ApplicationContextMixin, JobContextMixin, MaterialContextMixin, MaterialsContextMixin, MaterialsSetContextMixin, MethodDataContextMixin, WorkflowContextMixin } from "./mixins"; +import { ApplicationContextMixin } from "./mixins"; import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; import { ContextProvider } from "./provider"; import { ContextProviderRegistryContainer, createAndPatchRegistry, extendAndPatchRegistry } from "./registry"; -export { ContextProvider, ContextProviderRegistryContainer, extendAndPatchRegistry, createAndPatchRegistry, JobContextPickKeysForMixin, JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, ApplicationContextMixin, MaterialContextMixin, MaterialsContextMixin, MaterialsSetContextMixin, MethodDataContextMixin, JobContextMixin, WorkflowContextMixin, }; +export { ContextProvider, ContextProviderRegistryContainer, extendAndPatchRegistry, createAndPatchRegistry, JobContextPickKeysForMixin, JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, ApplicationContextMixin, }; diff --git a/dist/js/context/index.js b/dist/js/context/index.js index ff9df80b..b406606d 100644 --- a/dist/js/context/index.js +++ b/dist/js/context/index.js @@ -1,16 +1,10 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WorkflowContextMixin = exports.JobContextMixin = exports.MethodDataContextMixin = exports.MaterialsSetContextMixin = exports.MaterialsContextMixin = exports.MaterialContextMixin = exports.ApplicationContextMixin = exports.WorkflowContextPickKeysForMixin = exports.JSONSchemaFormDataProvider = exports.JobContextPickKeysForMixin = exports.createAndPatchRegistry = exports.extendAndPatchRegistry = exports.ContextProviderRegistryContainer = exports.ContextProvider = void 0; +exports.ApplicationContextMixin = exports.WorkflowContextPickKeysForMixin = exports.JSONSchemaFormDataProvider = exports.JobContextPickKeysForMixin = exports.createAndPatchRegistry = exports.extendAndPatchRegistry = exports.ContextProviderRegistryContainer = exports.ContextProvider = void 0; const json_schema_provider_1 = require("./json_schema_provider"); Object.defineProperty(exports, "JSONSchemaFormDataProvider", { enumerable: true, get: function () { return json_schema_provider_1.JSONSchemaFormDataProvider; } }); const mixins_1 = require("./mixins"); Object.defineProperty(exports, "ApplicationContextMixin", { enumerable: true, get: function () { return mixins_1.ApplicationContextMixin; } }); -Object.defineProperty(exports, "JobContextMixin", { enumerable: true, get: function () { return mixins_1.JobContextMixin; } }); -Object.defineProperty(exports, "MaterialContextMixin", { enumerable: true, get: function () { return mixins_1.MaterialContextMixin; } }); -Object.defineProperty(exports, "MaterialsContextMixin", { enumerable: true, get: function () { return mixins_1.MaterialsContextMixin; } }); -Object.defineProperty(exports, "MaterialsSetContextMixin", { enumerable: true, get: function () { return mixins_1.MaterialsSetContextMixin; } }); -Object.defineProperty(exports, "MethodDataContextMixin", { enumerable: true, get: function () { return mixins_1.MethodDataContextMixin; } }); -Object.defineProperty(exports, "WorkflowContextMixin", { enumerable: true, get: function () { return mixins_1.WorkflowContextMixin; } }); const pickers_1 = require("./pickers"); Object.defineProperty(exports, "JobContextPickKeysForMixin", { enumerable: true, get: function () { return pickers_1.JobContextPickKeysForMixin; } }); Object.defineProperty(exports, "WorkflowContextPickKeysForMixin", { enumerable: true, get: function () { return pickers_1.WorkflowContextPickKeysForMixin; } }); diff --git a/dist/js/context/mixins.d.ts b/dist/js/context/mixins.d.ts index 754667f3..0859af92 100644 --- a/dist/js/context/mixins.d.ts +++ b/dist/js/context/mixins.d.ts @@ -1,10 +1,4 @@ import { ApplicationSchemaBase } from "@mat3ra/esse/dist/js/types"; -import type { OrderedInMemoryEntityInSet } from "../entity/set/ordered/OrderedInMemoryEntityInSetMixin"; -import { JobContextMixin } from "./JobContextMixin"; -import { MaterialContextMixin } from "./MaterialContextMixin"; -import { MaterialsContextMixin } from "./MaterialsContextMixin"; -import { MethodDataContextMixin } from "./MethodDataContextMixin"; -import { WorkflowContextMixin } from "./WorkflowContextMixin"; type Constructor = new (...args: any[]) => T; export declare function ApplicationContextMixin(superclass: T): { new (...args: any): { @@ -13,14 +7,4 @@ export declare function ApplicationContextMixin(superclas readonly application: ApplicationSchemaBase; }; } & T; -export { MaterialContextMixin, MaterialsContextMixin, MethodDataContextMixin, WorkflowContextMixin, JobContextMixin, }; -export declare function MaterialsSetContextMixin(superclass: T): { - new (...params: any): { - [x: string]: any; - _materialsSet: any; - readonly materialsSet: any; - sortMaterialsByIndexInSet(materials?: OrderedInMemoryEntityInSet[]): { - getIndexByIdInOrderedSet(setId: string): number; - }[]; - }; -} & T; +export {}; diff --git a/dist/js/context/mixins.js b/dist/js/context/mixins.js index 7ba6f128..5755a481 100644 --- a/dist/js/context/mixins.js +++ b/dist/js/context/mixins.js @@ -1,19 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.JobContextMixin = exports.WorkflowContextMixin = exports.MethodDataContextMixin = exports.MaterialsContextMixin = exports.MaterialContextMixin = void 0; exports.ApplicationContextMixin = ApplicationContextMixin; -exports.MaterialsSetContextMixin = MaterialsSetContextMixin; -const utils_1 = require("../entity/set/ordered/utils"); -const JobContextMixin_1 = require("./JobContextMixin"); -Object.defineProperty(exports, "JobContextMixin", { enumerable: true, get: function () { return JobContextMixin_1.JobContextMixin; } }); -const MaterialContextMixin_1 = require("./MaterialContextMixin"); -Object.defineProperty(exports, "MaterialContextMixin", { enumerable: true, get: function () { return MaterialContextMixin_1.MaterialContextMixin; } }); -const MaterialsContextMixin_1 = require("./MaterialsContextMixin"); -Object.defineProperty(exports, "MaterialsContextMixin", { enumerable: true, get: function () { return MaterialsContextMixin_1.MaterialsContextMixin; } }); -const MethodDataContextMixin_1 = require("./MethodDataContextMixin"); -Object.defineProperty(exports, "MethodDataContextMixin", { enumerable: true, get: function () { return MethodDataContextMixin_1.MethodDataContextMixin; } }); -const WorkflowContextMixin_1 = require("./WorkflowContextMixin"); -Object.defineProperty(exports, "WorkflowContextMixin", { enumerable: true, get: function () { return WorkflowContextMixin_1.WorkflowContextMixin; } }); function ApplicationContextMixin(superclass) { return class ApplicationContextMixin extends superclass { constructor(...args) { @@ -33,20 +20,28 @@ function ApplicationContextMixin(superclass) { } }; } -function MaterialsSetContextMixin(superclass) { - return class MaterialsSetContextMixin extends superclass { - constructor(...params) { - super(...params); - this._materialsSet = this.config.context && this.config.context.materialsSet; - } - get materialsSet() { - return this._materialsSet; - } - sortMaterialsByIndexInSet(materials = []) { - // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). - return materials.concat().sort((a, b) => { - return (0, utils_1.compareEntitiesInOrderedSetForSorting)(a, b, this.materialsSet._id, false); - }); - } - }; -} +// export { +// MaterialContextMixin, +// MaterialsContextMixin, +// MethodDataContextMixin, +// WorkflowContextMixin, +// JobContextMixin, +// }; +// export function MaterialsSetContextMixin(superclass: T) { +// return class MaterialsSetContextMixin extends superclass { +// _materialsSet: any; +// constructor(...params: any) { +// super(...params); +// this._materialsSet = this.config.context && this.config.context.materialsSet; +// } +// get materialsSet() { +// return this._materialsSet; +// } +// sortMaterialsByIndexInSet(materials: OrderedInMemoryEntityInSet[] = []) { +// // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). +// return materials.concat().sort((a, b) => { +// return compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false); +// }); +// } +// }; +// } diff --git a/dist/js/context/provider.d.ts b/dist/js/context/provider.d.ts index 39746105..e1b891f5 100644 --- a/dist/js/context/provider.d.ts +++ b/dist/js/context/provider.d.ts @@ -1,3 +1,4 @@ +import type { ContextProviderInstance } from "./registry"; export interface ContextProviderConfig { name: string; domain?: string; @@ -7,6 +8,12 @@ export interface ContextProviderConfig { isEdited?: boolean; context?: object; } +export interface ContextProviderStatic { + getConstructorConfig: (config: ContextProviderConfig) => ContextProviderInstance; + createConfigFromContext: (config: ContextProviderConfig) => ContextProviderConfig; + getExtraDataKeyByName: (name: string) => string; + getIsEditedKeyByName: (name: string) => string; +} export declare class ContextProvider { config: ContextProviderConfig; name: string; @@ -16,10 +23,7 @@ export declare class ContextProvider { extraData?: object; isEdited?: boolean; constructor(config: ContextProviderConfig); - static getConstructorConfig(config: ContextProviderConfig): { - constructor: Function; - config: ContextProviderConfig; - }; + static getConstructorConfig(config: ContextProviderConfig): ContextProviderInstance; static createConfigFromContext(config: ContextProviderConfig): ContextProviderConfig & ({ data: any; extraData: any; diff --git a/dist/js/context/registry.d.ts b/dist/js/context/registry.d.ts index 28fcc1b2..49b0178c 100644 --- a/dist/js/context/registry.d.ts +++ b/dist/js/context/registry.d.ts @@ -1,16 +1,49 @@ -export class ContextProviderRegistryContainer { - _providers: any[]; - set providers(p: any[]); - get providers(): any[]; +import type { ContextProvider, ContextProviderConfig, ContextProviderStatic } from "./provider"; +export interface ContextProviderInstance { + constructor: typeof ContextProvider; + config: ContextProviderConfig; +} +export declare class ContextProviderRegistryContainer { + _providers: { + name: string; + instance: ContextProviderInstance; + }[]; + constructor(); + get providers(): { + name: string; + instance: ContextProviderInstance; + }[]; + set providers(p: { + name: string; + instance: ContextProviderInstance; + }[]); addProvider({ name, instance }: { - name: any; - instance: any; + name: string; + instance: ContextProviderInstance; }): void; - findProviderInstanceByName(name: any): any; - removeProvider(providerCls: any): void; - removeProviderByName(name: any): void; + findProviderInstanceByName(name: string): ContextProviderInstance | undefined; + removeProvider(providerCls: ContextProvider): void; + removeProviderByName(name: string): void; } -export function extendAndPatchRegistry(registryContainer: ContextProviderRegistryContainer, classConfigMap: Object, classesToPatch?: Object, defaultSettings?: {}): ContextProviderRegistryContainer; -export function createAndPatchRegistry(classConfigMap: Object, classesToPatch?: { - Material: SpecificMockMaterial; -}, defaultSettings?: {}): ContextProviderRegistryContainer; +/** Extends an existing context provider registry container and patches static class variables if applicable. + * @example + * const classConfigMap = { + * PlanewaveCutoffDataManager: { + * providerCls: PlanewaveCutoffsContextProvider, + * config: _makeImportant({ name: "cutoffs", entityName: "subworkflow" }) + * }, + * }; + */ +export declare const extendAndPatchRegistry: (registryContainer: ContextProviderRegistryContainer, classConfigMap: Record, classesToPatch?: Partial, defaultSettings?: Partial>) => ContextProviderRegistryContainer; +/** Creates a new context provider registry container and patches static class variables if applicable. + * + * @param {Object} classConfigMap + * @param {{Material: SpecificMockMaterial}} classesToPatch + */ +export declare const createAndPatchRegistry: (classConfigMap: Record, classesToPatch?: Partial, defaultSettings?: Partial>) => ContextProviderRegistryContainer; diff --git a/dist/js/context/registry.js b/dist/js/context/registry.js index 4cf40090..f156751e 100644 --- a/dist/js/context/registry.js +++ b/dist/js/context/registry.js @@ -30,10 +30,6 @@ class ContextProviderRegistryContainer { } exports.ContextProviderRegistryContainer = ContextProviderRegistryContainer; /** Extends an existing context provider registry container and patches static class variables if applicable. - * - * @param {ContextProviderRegistryContainer} registryContainer - * @param {Object} classConfigMap - * @param {Object} classesToPatch * @example * const classConfigMap = { * PlanewaveCutoffDataManager: { @@ -41,18 +37,21 @@ exports.ContextProviderRegistryContainer = ContextProviderRegistryContainer; * config: _makeImportant({ name: "cutoffs", entityName: "subworkflow" }) * }, * }; - * */ const extendAndPatchRegistry = (registryContainer, classConfigMap, classesToPatch = {}, defaultSettings = {}) => { Object.entries(classConfigMap).forEach(([name, { providerCls, config }]) => { - Object.entries(classesToPatch).forEach(([clsName, cls]) => { + const entries = Object.entries(classesToPatch); + entries.forEach(([clsName, cls]) => { if (providerCls[clsName]) { + // @ts-expect-error providerCls[clsName] = cls; } const providerDefaultSettings = defaultSettings[providerCls.name]; if (providerDefaultSettings) { - Object.entries(providerDefaultSettings).forEach(([key, value]) => { + const providerDefaultSettingsEntries = Object.entries(providerDefaultSettings); + providerDefaultSettingsEntries.forEach(([key, value]) => { if (providerCls[key]) { + // @ts-expect-error providerCls[key] = value; } }); diff --git a/src/js/context/JobContextMixin.ts b/src/js/context/JobContextMixin.ts deleted file mode 100644 index 677519b0..00000000 --- a/src/js/context/JobContextMixin.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { JobSchema } from "@mat3ra/esse/dist/js/types"; - -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; - -type JobConfig = { - context?: { - job?: JobSchema; - }; -}; - -const defaultJob: JobSchema = { - workflow: { - subworkflows: [], - units: [], - }, - status: "pre-submission", - compute: { - queue: "D", - nodes: 1, - ppn: 1, - timeLimit: "3600", - }, - _project: { - _id: "", - }, -}; - -export type JobContextMixinType = { - isEdited?: boolean; - job: JobSchema; - _job: JobSchema; - initJobContextMixin: () => void; -}; - -export function jobContextMixin(item: ContextProvider) { - const properties = { - isEdited: false, - - _job: defaultJob, - - get job() { - return this._job; - }, - - initJobContextMixin() { - const config = this.config as JobConfig; - this._job = (config.context && config.context.job) || defaultJob; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - }, - } as JobContextMixinType & typeof item; - - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} - -export function JobContextMixin>(superclass: T) { - jobContextMixin(superclass.prototype); - return superclass as T & Constructor; -} diff --git a/src/js/context/MaterialContextMixin.ts b/src/js/context/MaterialContextMixin.ts deleted file mode 100644 index 5efb149b..00000000 --- a/src/js/context/MaterialContextMixin.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; - -import type { InMemoryEntity } from "../entity/in_memory"; -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; - -type Material = InMemoryEntity & - MaterialSchema & { - hash: string; - }; - -export type MaterialContextMixinType = { - isEditedIsSetToFalseOnMaterialUpdate?: boolean; - updateMaterialHash: () => void; - isMaterialCreatedDefault: boolean; - isMaterialUpdated: boolean; - material: Material; - extraData?: { - materialHash: string; - }; -}; - -export function materialContextMixin(item: ContextProvider & { _material: Material }) { - const properties = { - updateMaterialHash() { - if (this.isEditedIsSetToFalseOnMaterialUpdate) this.isEdited = false; - this.extraData = { materialHash: this.material.hash }; - }, - - // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too - // does not have an id. Here we catch when such material is used and avoid resetting isEdited - get isMaterialCreatedDefault() { - return !this.material.id; - }, - - get isMaterialUpdated() { - return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); - }, - - get material() { - return this._material; - }, - } as MaterialContextMixinType & typeof item; - - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} - -export function MaterialContextMixin< - T extends Constructor, ->(superclass: T) { - materialContextMixin(superclass.prototype); - return superclass as T & Constructor; -} diff --git a/src/js/context/MaterialsContextMixin.ts b/src/js/context/MaterialsContextMixin.ts deleted file mode 100644 index bad3a3a3..00000000 --- a/src/js/context/MaterialsContextMixin.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; - -import type { InMemoryEntity } from "../entity/in_memory"; -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; - -type Material = InMemoryEntity & - MaterialSchema & { - hash: string; - }; - -type MaterialsContextMixinType = { - materials: Material[]; - initMaterialsContextMixin: () => void; -}; - -export function materialsContextMixin(item: ContextProvider & { _materials: Material[] }) { - const properties = { - get materials() { - return this._materials; - }, - initMaterialsContextMixin() { - // @ts-ignore - const materials = this.config.context?.materials; - // @ts-ignore - if (!this.constructor.Material) { - throw Error("MaterialsContextMixin: Material is undefined"); - } - this._materials = - materials && materials.length - ? materials - : // @ts-ignore - [this.constructor.Material.createDefault()]; - }, - } as MaterialsContextMixinType & typeof item; - - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} - -export function MaterialsContextMixin< - T extends Constructor, ->(superclass: T) { - materialsContextMixin(superclass.prototype); - return superclass as T & Constructor; -} diff --git a/src/js/context/MethodDataContextMixin.ts b/src/js/context/MethodDataContextMixin.ts deleted file mode 100644 index 552ad2d9..00000000 --- a/src/js/context/MethodDataContextMixin.ts +++ /dev/null @@ -1,84 +0,0 @@ -import CryptoJS from "crypto-js"; - -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; - -export interface Pseudo { - element: string; - filename?: string; - path?: string; -} - -export interface MethodData { - pseudo?: Pseudo[]; -} - -export type MethodDataConfig = { - context?: { - methodData?: MethodData; - }; - isEdited?: boolean; -}; - -export type MethodDataContextMixinType = { - isEdited?: boolean; - methodDataHash?: string; - extraData?: { - methodDataHash?: string; - }; - methodData: MethodData; - _methodData: MethodData; - isMethodDataUpdated: boolean; - _initMethodDataHash: () => void; - initMethodDataContextMixin: () => void; -}; - -export function methodDataContextMixin(item: ContextProvider) { - const properties = { - isEdited: false, - - _methodData: {}, - - get methodData() { - return this._methodData; - }, - - get isMethodDataUpdated() { - return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); - }, - - initMethodDataContextMixin() { - const config = this.config as MethodDataConfig; - this._methodData = (config.context && config.context.methodData) || {}; - this.isEdited = Boolean(config.isEdited); - }, - - /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between - * subsequent initializations of the derived class. Not used at present and kept for the record. - */ - _initMethodDataHash() { - this.methodDataHash = CryptoJS.MD5(JSON.stringify(this.methodData)).toString(); - this.extraData = { methodDataHash: this.methodDataHash }; - if (!this._methodData) { - this._methodData = {}; - this.isEdited = false; - // Commented out to reduce effect on performance. Uncomment for debugging purposes. - // TODO: remove on next refactoring or convert to log - // console.warn("MethodDataContextMixin: methodData is undefined or null"); - } else if (this.isMethodDataUpdated) { - this.isEdited = false; - } else { - // @ts-ignore - // eslint-disable-next-line no-undef - this.isEdited = this.config.isEdited; - } - }, - } as MethodDataContextMixinType & typeof item; - - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} - -export function MethodDataContextMixin>(superclass: T) { - methodDataContextMixin(superclass.prototype); - return superclass as T & Constructor; -} diff --git a/src/js/context/WorkflowContextMixin.ts b/src/js/context/WorkflowContextMixin.ts deleted file mode 100644 index 3081d5fb..00000000 --- a/src/js/context/WorkflowContextMixin.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; - -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; - -type WorkflowConfig = { - context?: { - workflow?: WorkflowSchema; - }; -}; - -const defaultWorkflow: WorkflowSchema = { - subworkflows: [], - units: [], -}; - -export type WorkflowContextMixinType = { - isEdited?: boolean; - workflow: WorkflowSchema; - _workflow: WorkflowSchema; - initWorkflowContextMixin: () => void; -}; - -export function workflowContextMixin(item: ContextProvider) { - const properties = { - isEdited: false, - - _workflow: defaultWorkflow, - - get workflow() { - return this._workflow; - }, - - initWorkflowContextMixin() { - const config = this.config as WorkflowConfig; - this._workflow = (config.context && config.context.workflow) || defaultWorkflow; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - }, - } as WorkflowContextMixinType & typeof item; - - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} - -export function WorkflowContextMixin>(superclass: T) { - workflowContextMixin(superclass.prototype); - return superclass as T & Constructor; -} diff --git a/src/js/context/index.ts b/src/js/context/index.ts index 1c59abec..20a0ef50 100644 --- a/src/js/context/index.ts +++ b/src/js/context/index.ts @@ -1,12 +1,12 @@ import { JSONSchemaFormDataProvider } from "./json_schema_provider"; import { ApplicationContextMixin, - JobContextMixin, - MaterialContextMixin, - MaterialsContextMixin, - MaterialsSetContextMixin, - MethodDataContextMixin, - WorkflowContextMixin, + // JobContextMixin, + // MaterialContextMixin, + // MaterialsContextMixin, + // MaterialsSetContextMixin, + // MethodDataContextMixin, + // WorkflowContextMixin, } from "./mixins"; import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; import { ContextProvider } from "./provider"; @@ -25,10 +25,10 @@ export { JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, ApplicationContextMixin, - MaterialContextMixin, - MaterialsContextMixin, - MaterialsSetContextMixin, - MethodDataContextMixin, - JobContextMixin, - WorkflowContextMixin, + // MaterialContextMixin, + // MaterialsContextMixin, + // MaterialsSetContextMixin, + // MethodDataContextMixin, + // JobContextMixin, + // WorkflowContextMixin, }; diff --git a/src/js/context/mixins.ts b/src/js/context/mixins.ts index 2497cf18..8e5337b2 100644 --- a/src/js/context/mixins.ts +++ b/src/js/context/mixins.ts @@ -2,13 +2,13 @@ import { ApplicationSchemaBase } from "@mat3ra/esse/dist/js/types"; import { DefaultableMixin } from "../entity/mixins/props"; -import type { OrderedInMemoryEntityInSet } from "../entity/set/ordered/OrderedInMemoryEntityInSetMixin"; -import { compareEntitiesInOrderedSetForSorting } from "../entity/set/ordered/utils"; -import { JobContextMixin } from "./JobContextMixin"; -import { MaterialContextMixin } from "./MaterialContextMixin"; -import { MaterialsContextMixin } from "./MaterialsContextMixin"; -import { MethodDataContextMixin } from "./MethodDataContextMixin"; -import { WorkflowContextMixin } from "./WorkflowContextMixin"; +// import type { OrderedInMemoryEntityInSet } from "../entity/set/ordered/OrderedInMemoryEntityInSetMixin"; +// import { compareEntitiesInOrderedSetForSorting } from "../entity/set/ordered/utils"; +// import { JobContextMixin } from "./JobContextMixin"; +// import { MaterialContextMixin } from "./MaterialContextMixin"; +// import { MaterialsContextMixin } from "./MaterialsContextMixin"; +// import { MethodDataContextMixin } from "./MethodDataContextMixin"; +// import { WorkflowContextMixin } from "./WorkflowContextMixin"; type Constructor = new (...args: any[]) => T; @@ -37,32 +37,32 @@ export function ApplicationContextMixin(superclass: T) { }; } -export { - MaterialContextMixin, - MaterialsContextMixin, - MethodDataContextMixin, - WorkflowContextMixin, - JobContextMixin, -}; +// export { +// MaterialContextMixin, +// MaterialsContextMixin, +// MethodDataContextMixin, +// WorkflowContextMixin, +// JobContextMixin, +// }; -export function MaterialsSetContextMixin(superclass: T) { - return class MaterialsSetContextMixin extends superclass { - _materialsSet: any; +// export function MaterialsSetContextMixin(superclass: T) { +// return class MaterialsSetContextMixin extends superclass { +// _materialsSet: any; - constructor(...params: any) { - super(...params); - this._materialsSet = this.config.context && this.config.context.materialsSet; - } +// constructor(...params: any) { +// super(...params); +// this._materialsSet = this.config.context && this.config.context.materialsSet; +// } - get materialsSet() { - return this._materialsSet; - } +// get materialsSet() { +// return this._materialsSet; +// } - sortMaterialsByIndexInSet(materials: OrderedInMemoryEntityInSet[] = []) { - // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). - return materials.concat().sort((a, b) => { - return compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false); - }); - } - }; -} +// sortMaterialsByIndexInSet(materials: OrderedInMemoryEntityInSet[] = []) { +// // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). +// return materials.concat().sort((a, b) => { +// return compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false); +// }); +// } +// }; +// } diff --git a/src/js/context/provider.ts b/src/js/context/provider.ts index 6a1345af..459d3b58 100644 --- a/src/js/context/provider.ts +++ b/src/js/context/provider.ts @@ -12,6 +12,7 @@ import lodash from "lodash"; import { deepClone } from "../utils/clone"; +import type { ContextProviderInstance } from "./registry"; export interface ContextProviderConfig { name: string; @@ -23,6 +24,13 @@ export interface ContextProviderConfig { context?: object; } +export interface ContextProviderStatic { + getConstructorConfig: (config: ContextProviderConfig) => ContextProviderInstance; + createConfigFromContext: (config: ContextProviderConfig) => ContextProviderConfig; + getExtraDataKeyByName: (name: string) => string; + getIsEditedKeyByName: (name: string) => string; +} + export class ContextProvider { config: ContextProviderConfig; @@ -59,9 +67,9 @@ export class ContextProvider { this.yieldData = this.yieldData.bind(this); } - static getConstructorConfig(config: ContextProviderConfig) { + static getConstructorConfig(config: ContextProviderConfig): ContextProviderInstance { return { - constructor: this.prototype.constructor, + constructor: this.prototype.constructor as typeof ContextProvider, config, }; } diff --git a/src/js/context/registry.js b/src/js/context/registry.ts similarity index 55% rename from src/js/context/registry.js rename to src/js/context/registry.ts index 804d3036..c6eff9d6 100644 --- a/src/js/context/registry.js +++ b/src/js/context/registry.ts @@ -1,4 +1,16 @@ +import type { ContextProvider, ContextProviderConfig, ContextProviderStatic } from "./provider"; + +export interface ContextProviderInstance { + constructor: typeof ContextProvider; + config: ContextProviderConfig; +} + export class ContextProviderRegistryContainer { + _providers: { + name: string; + instance: ContextProviderInstance; + }[]; + constructor() { this._providers = []; } @@ -11,32 +23,33 @@ export class ContextProviderRegistryContainer { this._providers = p; } - addProvider({ name, instance }) { + addProvider({ name, instance }: { name: string; instance: ContextProviderInstance }) { this._providers.push({ name, instance, }); } - findProviderInstanceByName(name) { + findProviderInstanceByName(name: string) { const provider = this.providers.find((p) => p.name === name); return provider && provider.instance; } - removeProvider(providerCls) { + removeProvider(providerCls: ContextProvider) { this.providers = this.providers.filter((p) => p.name === providerCls.name); } - removeProviderByName(name) { + removeProviderByName(name: string) { this.providers = this.providers.filter((p) => p.name === name); } } +type ContextProviderStaticEntry = [ + keyof ContextProviderStatic, + ContextProviderStatic[keyof ContextProviderStatic], +]; + /** Extends an existing context provider registry container and patches static class variables if applicable. - * - * @param {ContextProviderRegistryContainer} registryContainer - * @param {Object} classConfigMap - * @param {Object} classesToPatch * @example * const classConfigMap = { * PlanewaveCutoffDataManager: { @@ -44,23 +57,33 @@ export class ContextProviderRegistryContainer { * config: _makeImportant({ name: "cutoffs", entityName: "subworkflow" }) * }, * }; - * */ export const extendAndPatchRegistry = ( - registryContainer, - classConfigMap, - classesToPatch = {}, - defaultSettings = {}, + registryContainer: ContextProviderRegistryContainer, + classConfigMap: Record< + string, + { providerCls: typeof ContextProvider; config: ContextProviderConfig } + >, + classesToPatch: Partial = {}, + defaultSettings: Partial> = {}, ) => { Object.entries(classConfigMap).forEach(([name, { providerCls, config }]) => { - Object.entries(classesToPatch).forEach(([clsName, cls]) => { + const entries = Object.entries(classesToPatch) as ContextProviderStaticEntry[]; + + entries.forEach(([clsName, cls]) => { if (providerCls[clsName]) { + // @ts-expect-error providerCls[clsName] = cls; } const providerDefaultSettings = defaultSettings[providerCls.name]; if (providerDefaultSettings) { - Object.entries(providerDefaultSettings).forEach(([key, value]) => { + const providerDefaultSettingsEntries = Object.entries( + providerDefaultSettings, + ) as ContextProviderStaticEntry[]; + + providerDefaultSettingsEntries.forEach(([key, value]) => { if (providerCls[key]) { + // @ts-expect-error providerCls[key] = value; } }); @@ -81,9 +104,12 @@ export const extendAndPatchRegistry = ( * @param {{Material: SpecificMockMaterial}} classesToPatch */ export const createAndPatchRegistry = ( - classConfigMap, - classesToPatch = {}, - defaultSettings = {}, + classConfigMap: Record< + string, + { providerCls: typeof ContextProvider; config: ContextProviderConfig } + >, + classesToPatch: Partial = {}, + defaultSettings: Partial> = {}, ) => { const registryContainer = new ContextProviderRegistryContainer(); return extendAndPatchRegistry( diff --git a/tests/js/context.tests.ts b/tests/js/context.tests.ts index 47915821..fb97a8e4 100644 --- a/tests/js/context.tests.ts +++ b/tests/js/context.tests.ts @@ -1,102 +1,102 @@ -import { expect } from "chai"; - -import { - ApplicationContextMixin, - ContextProvider, - createAndPatchRegistry, - MaterialContextMixin, -} from "../../src/js/context"; -import { ContextProviderConfig } from "../../src/js/context/provider"; - -class MockMaterial { - static createDefault() { - return "defaultMockMaterial"; - } -} - -class SpecificMockMaterial { - static createDefault() { - return "defaultSpecificMockMaterial"; - } -} - -class MockApplication { - static createDefault() { - return "defaultMockApplication"; - } -} - -class SpecificMockApplication { - static createDefault() { - return "defaultSpecificMockApplication"; - } -} - -class ProviderEntity extends MaterialContextMixin(ApplicationContextMixin(ContextProvider)) { - static Material = MockMaterial; - - static Application = MockApplication; - - static setting = 10; -} - -class DerivedProviderEntity extends ProviderEntity { - static Material = SpecificMockMaterial; - - static Application = SpecificMockApplication; -} - -class ApplicationContextProvider extends ApplicationContextMixin(ContextProvider) { - static Application = SpecificMockApplication; -} - -describe("Material & Application ContextMixin", () => { - const config: ContextProviderConfig = { name: "test" }; - - it("uses static entity class", () => { - const provider = new ProviderEntity(config); - expect(provider.material).to.be.equal("defaultMockMaterial"); - expect(provider.application).to.be.equal("defaultMockApplication"); - }); - - it("uses static entity class from derived class", () => { - const provider = new DerivedProviderEntity(config); - expect(provider.material).to.be.equal("defaultSpecificMockMaterial"); - expect(provider.application).to.be.equal("defaultSpecificMockApplication"); - }); -}); - -describe("ContextProviderRegistryContainer", () => { - const classConfigObj = { - DataManager: { - providerCls: ProviderEntity, - config: { name: "example1", domain: "important" }, - }, - ApplicationDataManager: { - providerCls: ApplicationContextProvider, - config: { name: "example2", domain: "important" }, - }, - }; - - const defaultSettings = { - ProviderEntity: { - setting: 100, - }, - }; - - it("can be created and patched", () => { - const registry = createAndPatchRegistry( - classConfigObj, - { Material: SpecificMockMaterial }, - defaultSettings, - ); - - const _dataProvider = registry.findProviderInstanceByName("DataManager"); - const dataProvider = new _dataProvider.constructor(_dataProvider.config); - const _appProvider = registry.findProviderInstanceByName("ApplicationDataManager"); - const appProvider = new _appProvider.constructor(_appProvider.config); - expect(_dataProvider.constructor.setting).to.be.equal(100); - expect(dataProvider.material).to.be.equal("defaultSpecificMockMaterial"); - expect(appProvider.application).to.be.equal("defaultSpecificMockApplication"); - }); -}); +// import { expect } from "chai"; + +// import { +// ApplicationContextMixin, +// ContextProvider, +// createAndPatchRegistry, +// // MaterialContextMixin, +// } from "../../src/js/context"; +// import { ContextProviderConfig } from "../../src/js/context/provider"; + +// class MockMaterial { +// static createDefault() { +// return "defaultMockMaterial"; +// } +// } + +// class SpecificMockMaterial { +// static createDefault() { +// return "defaultSpecificMockMaterial"; +// } +// } + +// class MockApplication { +// static createDefault() { +// return "defaultMockApplication"; +// } +// } + +// class SpecificMockApplication { +// static createDefault() { +// return "defaultSpecificMockApplication"; +// } +// } + +// class ProviderEntity extends MaterialContextMixin(ApplicationContextMixin(ContextProvider)) { +// static Material = MockMaterial; + +// static Application = MockApplication; + +// static setting = 10; +// } + +// class DerivedProviderEntity extends ProviderEntity { +// static Material = SpecificMockMaterial; + +// static Application = SpecificMockApplication; +// } + +// class ApplicationContextProvider extends ApplicationContextMixin(ContextProvider) { +// static Application = SpecificMockApplication; +// } + +// describe("Material & Application ContextMixin", () => { +// const config: ContextProviderConfig = { name: "test" }; + +// it("uses static entity class", () => { +// const provider = new ProviderEntity(config); +// expect(provider.material).to.be.equal("defaultMockMaterial"); +// expect(provider.application).to.be.equal("defaultMockApplication"); +// }); + +// it("uses static entity class from derived class", () => { +// const provider = new DerivedProviderEntity(config); +// expect(provider.material).to.be.equal("defaultSpecificMockMaterial"); +// expect(provider.application).to.be.equal("defaultSpecificMockApplication"); +// }); +// }); + +// describe("ContextProviderRegistryContainer", () => { +// const classConfigObj = { +// DataManager: { +// providerCls: ProviderEntity, +// config: { name: "example1", domain: "important" }, +// }, +// ApplicationDataManager: { +// providerCls: ApplicationContextProvider, +// config: { name: "example2", domain: "important" }, +// }, +// }; + +// const defaultSettings = { +// ProviderEntity: { +// setting: 100, +// }, +// }; + +// it("can be created and patched", () => { +// const registry = createAndPatchRegistry( +// classConfigObj, +// { Material: SpecificMockMaterial }, +// defaultSettings, +// ); + +// const _dataProvider = registry.findProviderInstanceByName("DataManager"); +// const dataProvider = new _dataProvider.constructor(_dataProvider.config); +// const _appProvider = registry.findProviderInstanceByName("ApplicationDataManager"); +// const appProvider = new _appProvider.constructor(_appProvider.config); +// expect(_dataProvider.constructor.setting).to.be.equal(100); +// expect(dataProvider.material).to.be.equal("defaultSpecificMockMaterial"); +// expect(appProvider.application).to.be.equal("defaultSpecificMockApplication"); +// }); +// }); From cdf586647bf0c55c9a51280cc949a221de1e7268 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Wed, 18 Jun 2025 17:56:28 +0300 Subject: [PATCH 07/10] chore: dist cleanup --- dist/js/context/JobContextMixin.d.ts | 11 ----- dist/js/context/JobContextMixin.js | 39 ---------------- dist/js/context/MaterialContextMixin.d.ts | 24 ---------- dist/js/context/MaterialContextMixin.js | 29 ------------ dist/js/context/MaterialsContextMixin.d.ts | 18 ------- dist/js/context/MaterialsContextMixin.js | 30 ------------ dist/js/context/MethodDataContextMixin.d.ts | 30 ------------ dist/js/context/MethodDataContextMixin.js | 52 --------------------- dist/js/context/WorkflowContextMixin.d.ts | 11 ----- dist/js/context/WorkflowContextMixin.js | 27 ----------- 10 files changed, 271 deletions(-) delete mode 100644 dist/js/context/JobContextMixin.d.ts delete mode 100644 dist/js/context/JobContextMixin.js delete mode 100644 dist/js/context/MaterialContextMixin.d.ts delete mode 100644 dist/js/context/MaterialContextMixin.js delete mode 100644 dist/js/context/MaterialsContextMixin.d.ts delete mode 100644 dist/js/context/MaterialsContextMixin.js delete mode 100644 dist/js/context/MethodDataContextMixin.d.ts delete mode 100644 dist/js/context/MethodDataContextMixin.js delete mode 100644 dist/js/context/WorkflowContextMixin.d.ts delete mode 100644 dist/js/context/WorkflowContextMixin.js diff --git a/dist/js/context/JobContextMixin.d.ts b/dist/js/context/JobContextMixin.d.ts deleted file mode 100644 index dfa82e02..00000000 --- a/dist/js/context/JobContextMixin.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { JobSchema } from "@mat3ra/esse/dist/js/types"; -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; -export type JobContextMixinType = { - isEdited?: boolean; - job: JobSchema; - _job: JobSchema; - initJobContextMixin: () => void; -}; -export declare function jobContextMixin(item: ContextProvider): void; -export declare function JobContextMixin>(superclass: T): T & Constructor; diff --git a/dist/js/context/JobContextMixin.js b/dist/js/context/JobContextMixin.js deleted file mode 100644 index 3c46b4ec..00000000 --- a/dist/js/context/JobContextMixin.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.jobContextMixin = jobContextMixin; -exports.JobContextMixin = JobContextMixin; -const defaultJob = { - workflow: { - subworkflows: [], - units: [], - }, - status: "pre-submission", - compute: { - queue: "D", - nodes: 1, - ppn: 1, - timeLimit: "3600", - }, - _project: { - _id: "", - }, -}; -function jobContextMixin(item) { - const properties = { - isEdited: false, - _job: defaultJob, - get job() { - return this._job; - }, - initJobContextMixin() { - const config = this.config; - this._job = (config.context && config.context.job) || defaultJob; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - }, - }; - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} -function JobContextMixin(superclass) { - jobContextMixin(superclass.prototype); - return superclass; -} diff --git a/dist/js/context/MaterialContextMixin.d.ts b/dist/js/context/MaterialContextMixin.d.ts deleted file mode 100644 index 86351723..00000000 --- a/dist/js/context/MaterialContextMixin.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; -import type { InMemoryEntity } from "../entity/in_memory"; -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; -type Material = InMemoryEntity & MaterialSchema & { - hash: string; -}; -export type MaterialContextMixinType = { - isEditedIsSetToFalseOnMaterialUpdate?: boolean; - updateMaterialHash: () => void; - isMaterialCreatedDefault: boolean; - isMaterialUpdated: boolean; - material: Material; - extraData?: { - materialHash: string; - }; -}; -export declare function materialContextMixin(item: ContextProvider & { - _material: Material; -}): void; -export declare function MaterialContextMixin>(superclass: T): T & Constructor; -export {}; diff --git a/dist/js/context/MaterialContextMixin.js b/dist/js/context/MaterialContextMixin.js deleted file mode 100644 index be3fed5b..00000000 --- a/dist/js/context/MaterialContextMixin.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.materialContextMixin = materialContextMixin; -exports.MaterialContextMixin = MaterialContextMixin; -function materialContextMixin(item) { - const properties = { - updateMaterialHash() { - if (this.isEditedIsSetToFalseOnMaterialUpdate) - this.isEdited = false; - this.extraData = { materialHash: this.material.hash }; - }, - // Workaround: Material.createDefault() used to initiate workflow reducer and hence here too - // does not have an id. Here we catch when such material is used and avoid resetting isEdited - get isMaterialCreatedDefault() { - return !this.material.id; - }, - get isMaterialUpdated() { - return Boolean(this.extraData && this.extraData.materialHash !== this.material.hash); - }, - get material() { - return this._material; - }, - }; - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} -function MaterialContextMixin(superclass) { - materialContextMixin(superclass.prototype); - return superclass; -} diff --git a/dist/js/context/MaterialsContextMixin.d.ts b/dist/js/context/MaterialsContextMixin.d.ts deleted file mode 100644 index 7edabbb9..00000000 --- a/dist/js/context/MaterialsContextMixin.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { MaterialSchema } from "@mat3ra/esse/dist/js/types"; -import type { InMemoryEntity } from "../entity/in_memory"; -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; -type Material = InMemoryEntity & MaterialSchema & { - hash: string; -}; -type MaterialsContextMixinType = { - materials: Material[]; - initMaterialsContextMixin: () => void; -}; -export declare function materialsContextMixin(item: ContextProvider & { - _materials: Material[]; -}): void; -export declare function MaterialsContextMixin>(superclass: T): T & Constructor; -export {}; diff --git a/dist/js/context/MaterialsContextMixin.js b/dist/js/context/MaterialsContextMixin.js deleted file mode 100644 index a3439741..00000000 --- a/dist/js/context/MaterialsContextMixin.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.materialsContextMixin = materialsContextMixin; -exports.MaterialsContextMixin = MaterialsContextMixin; -function materialsContextMixin(item) { - const properties = { - get materials() { - return this._materials; - }, - initMaterialsContextMixin() { - var _a; - // @ts-ignore - const materials = (_a = this.config.context) === null || _a === void 0 ? void 0 : _a.materials; - // @ts-ignore - if (!this.constructor.Material) { - throw Error("MaterialsContextMixin: Material is undefined"); - } - this._materials = - materials && materials.length - ? materials - : // @ts-ignore - [this.constructor.Material.createDefault()]; - }, - }; - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} -function MaterialsContextMixin(superclass) { - materialsContextMixin(superclass.prototype); - return superclass; -} diff --git a/dist/js/context/MethodDataContextMixin.d.ts b/dist/js/context/MethodDataContextMixin.d.ts deleted file mode 100644 index f7f31fd4..00000000 --- a/dist/js/context/MethodDataContextMixin.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; -export interface Pseudo { - element: string; - filename?: string; - path?: string; -} -export interface MethodData { - pseudo?: Pseudo[]; -} -export type MethodDataConfig = { - context?: { - methodData?: MethodData; - }; - isEdited?: boolean; -}; -export type MethodDataContextMixinType = { - isEdited?: boolean; - methodDataHash?: string; - extraData?: { - methodDataHash?: string; - }; - methodData: MethodData; - _methodData: MethodData; - isMethodDataUpdated: boolean; - _initMethodDataHash: () => void; - initMethodDataContextMixin: () => void; -}; -export declare function methodDataContextMixin(item: ContextProvider): void; -export declare function MethodDataContextMixin>(superclass: T): T & Constructor; diff --git a/dist/js/context/MethodDataContextMixin.js b/dist/js/context/MethodDataContextMixin.js deleted file mode 100644 index a72f842d..00000000 --- a/dist/js/context/MethodDataContextMixin.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.methodDataContextMixin = methodDataContextMixin; -exports.MethodDataContextMixin = MethodDataContextMixin; -const crypto_js_1 = __importDefault(require("crypto-js")); -function methodDataContextMixin(item) { - const properties = { - isEdited: false, - _methodData: {}, - get methodData() { - return this._methodData; - }, - get isMethodDataUpdated() { - return Boolean(this.extraData && this.extraData.methodDataHash !== this.methodDataHash); - }, - initMethodDataContextMixin() { - const config = this.config; - this._methodData = (config.context && config.context.methodData) || {}; - this.isEdited = Boolean(config.isEdited); - }, - /* @summary Replace the logic in constructor with this in order to enable passing `methodDataHash` between - * subsequent initializations of the derived class. Not used at present and kept for the record. - */ - _initMethodDataHash() { - this.methodDataHash = crypto_js_1.default.MD5(JSON.stringify(this.methodData)).toString(); - this.extraData = { methodDataHash: this.methodDataHash }; - if (!this._methodData) { - this._methodData = {}; - this.isEdited = false; - // Commented out to reduce effect on performance. Uncomment for debugging purposes. - // TODO: remove on next refactoring or convert to log - // console.warn("MethodDataContextMixin: methodData is undefined or null"); - } - else if (this.isMethodDataUpdated) { - this.isEdited = false; - } - else { - // @ts-ignore - // eslint-disable-next-line no-undef - this.isEdited = this.config.isEdited; - } - }, - }; - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} -function MethodDataContextMixin(superclass) { - methodDataContextMixin(superclass.prototype); - return superclass; -} diff --git a/dist/js/context/WorkflowContextMixin.d.ts b/dist/js/context/WorkflowContextMixin.d.ts deleted file mode 100644 index 95b2c65f..00000000 --- a/dist/js/context/WorkflowContextMixin.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { WorkflowSchema } from "@mat3ra/esse/dist/js/types"; -import type { Constructor } from "../utils/types"; -import type { ContextProvider } from "./provider"; -export type WorkflowContextMixinType = { - isEdited?: boolean; - workflow: WorkflowSchema; - _workflow: WorkflowSchema; - initWorkflowContextMixin: () => void; -}; -export declare function workflowContextMixin(item: ContextProvider): void; -export declare function WorkflowContextMixin>(superclass: T): T & Constructor; diff --git a/dist/js/context/WorkflowContextMixin.js b/dist/js/context/WorkflowContextMixin.js deleted file mode 100644 index 90b24291..00000000 --- a/dist/js/context/WorkflowContextMixin.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.workflowContextMixin = workflowContextMixin; -exports.WorkflowContextMixin = WorkflowContextMixin; -const defaultWorkflow = { - subworkflows: [], - units: [], -}; -function workflowContextMixin(item) { - const properties = { - isEdited: false, - _workflow: defaultWorkflow, - get workflow() { - return this._workflow; - }, - initWorkflowContextMixin() { - const config = this.config; - this._workflow = (config.context && config.context.workflow) || defaultWorkflow; - this.isEdited = false; // we always get the `defaultData` (recalculated from scratch, not persistent) - }, - }; - Object.defineProperties(item, Object.getOwnPropertyDescriptors(properties)); -} -function WorkflowContextMixin(superclass) { - workflowContextMixin(superclass.prototype); - return superclass; -} From 6f53b8ce5ea3c7b6f9e3cdab483606aefa9254d6 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Wed, 18 Jun 2025 17:58:08 +0300 Subject: [PATCH 08/10] chore: dist cleanup --- dist/js/context/index.d.ts | 3 +- dist/js/context/index.js | 4 +-- dist/js/context/mixins.d.ts | 10 ------ dist/js/context/mixins.js | 47 ------------------------- src/js/context/index.ts | 16 --------- src/js/context/mixins.ts | 68 ------------------------------------- 6 files changed, 2 insertions(+), 146 deletions(-) delete mode 100644 dist/js/context/mixins.d.ts delete mode 100644 dist/js/context/mixins.js delete mode 100644 src/js/context/mixins.ts diff --git a/dist/js/context/index.d.ts b/dist/js/context/index.d.ts index d3679e3e..e308ca21 100644 --- a/dist/js/context/index.d.ts +++ b/dist/js/context/index.d.ts @@ -1,6 +1,5 @@ import { JSONSchemaFormDataProvider } from "./json_schema_provider"; -import { ApplicationContextMixin } from "./mixins"; import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; import { ContextProvider } from "./provider"; import { ContextProviderRegistryContainer, createAndPatchRegistry, extendAndPatchRegistry } from "./registry"; -export { ContextProvider, ContextProviderRegistryContainer, extendAndPatchRegistry, createAndPatchRegistry, JobContextPickKeysForMixin, JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, ApplicationContextMixin, }; +export { ContextProvider, ContextProviderRegistryContainer, extendAndPatchRegistry, createAndPatchRegistry, JobContextPickKeysForMixin, JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, }; diff --git a/dist/js/context/index.js b/dist/js/context/index.js index b406606d..7981f589 100644 --- a/dist/js/context/index.js +++ b/dist/js/context/index.js @@ -1,10 +1,8 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ApplicationContextMixin = exports.WorkflowContextPickKeysForMixin = exports.JSONSchemaFormDataProvider = exports.JobContextPickKeysForMixin = exports.createAndPatchRegistry = exports.extendAndPatchRegistry = exports.ContextProviderRegistryContainer = exports.ContextProvider = void 0; +exports.WorkflowContextPickKeysForMixin = exports.JSONSchemaFormDataProvider = exports.JobContextPickKeysForMixin = exports.createAndPatchRegistry = exports.extendAndPatchRegistry = exports.ContextProviderRegistryContainer = exports.ContextProvider = void 0; const json_schema_provider_1 = require("./json_schema_provider"); Object.defineProperty(exports, "JSONSchemaFormDataProvider", { enumerable: true, get: function () { return json_schema_provider_1.JSONSchemaFormDataProvider; } }); -const mixins_1 = require("./mixins"); -Object.defineProperty(exports, "ApplicationContextMixin", { enumerable: true, get: function () { return mixins_1.ApplicationContextMixin; } }); const pickers_1 = require("./pickers"); Object.defineProperty(exports, "JobContextPickKeysForMixin", { enumerable: true, get: function () { return pickers_1.JobContextPickKeysForMixin; } }); Object.defineProperty(exports, "WorkflowContextPickKeysForMixin", { enumerable: true, get: function () { return pickers_1.WorkflowContextPickKeysForMixin; } }); diff --git a/dist/js/context/mixins.d.ts b/dist/js/context/mixins.d.ts deleted file mode 100644 index 0859af92..00000000 --- a/dist/js/context/mixins.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ApplicationSchemaBase } from "@mat3ra/esse/dist/js/types"; -type Constructor = new (...args: any[]) => T; -export declare function ApplicationContextMixin(superclass: T): { - new (...args: any): { - [x: string]: any; - _application: ApplicationSchemaBase; - readonly application: ApplicationSchemaBase; - }; -} & T; -export {}; diff --git a/dist/js/context/mixins.js b/dist/js/context/mixins.js deleted file mode 100644 index 5755a481..00000000 --- a/dist/js/context/mixins.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ApplicationContextMixin = ApplicationContextMixin; -function ApplicationContextMixin(superclass) { - return class ApplicationContextMixin extends superclass { - constructor(...args) { - super(...args); - // @ts-ignore - if (!this.constructor.Application) { - throw Error("ApplicationContextMixin: Application is undefined"); - } - const config = args[0]; - this._application = - (config.context && config.context.application) || - // @ts-ignore - this.constructor.Application.createDefault(); - } - get application() { - return this._application; - } - }; -} -// export { -// MaterialContextMixin, -// MaterialsContextMixin, -// MethodDataContextMixin, -// WorkflowContextMixin, -// JobContextMixin, -// }; -// export function MaterialsSetContextMixin(superclass: T) { -// return class MaterialsSetContextMixin extends superclass { -// _materialsSet: any; -// constructor(...params: any) { -// super(...params); -// this._materialsSet = this.config.context && this.config.context.materialsSet; -// } -// get materialsSet() { -// return this._materialsSet; -// } -// sortMaterialsByIndexInSet(materials: OrderedInMemoryEntityInSet[] = []) { -// // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). -// return materials.concat().sort((a, b) => { -// return compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false); -// }); -// } -// }; -// } diff --git a/src/js/context/index.ts b/src/js/context/index.ts index 20a0ef50..885274c7 100644 --- a/src/js/context/index.ts +++ b/src/js/context/index.ts @@ -1,13 +1,4 @@ import { JSONSchemaFormDataProvider } from "./json_schema_provider"; -import { - ApplicationContextMixin, - // JobContextMixin, - // MaterialContextMixin, - // MaterialsContextMixin, - // MaterialsSetContextMixin, - // MethodDataContextMixin, - // WorkflowContextMixin, -} from "./mixins"; import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; import { ContextProvider } from "./provider"; import { @@ -24,11 +15,4 @@ export { JobContextPickKeysForMixin, JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, - ApplicationContextMixin, - // MaterialContextMixin, - // MaterialsContextMixin, - // MaterialsSetContextMixin, - // MethodDataContextMixin, - // JobContextMixin, - // WorkflowContextMixin, }; diff --git a/src/js/context/mixins.ts b/src/js/context/mixins.ts deleted file mode 100644 index 8e5337b2..00000000 --- a/src/js/context/mixins.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { ApplicationSchemaBase } from "@mat3ra/esse/dist/js/types"; - -import { DefaultableMixin } from "../entity/mixins/props"; -// import type { OrderedInMemoryEntityInSet } from "../entity/set/ordered/OrderedInMemoryEntityInSetMixin"; -// import { compareEntitiesInOrderedSetForSorting } from "../entity/set/ordered/utils"; -// import { JobContextMixin } from "./JobContextMixin"; -// import { MaterialContextMixin } from "./MaterialContextMixin"; -// import { MaterialsContextMixin } from "./MaterialsContextMixin"; -// import { MethodDataContextMixin } from "./MethodDataContextMixin"; -// import { WorkflowContextMixin } from "./WorkflowContextMixin"; - -type Constructor = new (...args: any[]) => T; - -type Defaultable = ReturnType; - -export function ApplicationContextMixin(superclass: T) { - return class ApplicationContextMixin extends superclass { - _application: ApplicationSchemaBase; - - constructor(...args: any) { - super(...args); - // @ts-ignore - if (!this.constructor.Application) { - throw Error("ApplicationContextMixin: Application is undefined"); - } - const config = args[0]; - this._application = - (config.context && config.context.application) || - // @ts-ignore - (this.constructor.Application as Defaultable).createDefault(); - } - - get application() { - return this._application; - } - }; -} - -// export { -// MaterialContextMixin, -// MaterialsContextMixin, -// MethodDataContextMixin, -// WorkflowContextMixin, -// JobContextMixin, -// }; - -// export function MaterialsSetContextMixin(superclass: T) { -// return class MaterialsSetContextMixin extends superclass { -// _materialsSet: any; - -// constructor(...params: any) { -// super(...params); -// this._materialsSet = this.config.context && this.config.context.materialsSet; -// } - -// get materialsSet() { -// return this._materialsSet; -// } - -// sortMaterialsByIndexInSet(materials: OrderedInMemoryEntityInSet[] = []) { -// // DO NOT SORT IN PLACE AS IT CHANGES THE ORDER IN `this.materials` AND HAS SIDE EFFECTS (MaterialViewer). -// return materials.concat().sort((a, b) => { -// return compareEntitiesInOrderedSetForSorting(a, b, this.materialsSet._id, false); -// }); -// } -// }; -// } From 18e25cec1cd51bc450505d329bca9c38ec694006 Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Wed, 18 Jun 2025 18:23:37 +0300 Subject: [PATCH 09/10] chore: move tests to wode --- tests/js/context.tests.ts | 102 -------------------------------------- 1 file changed, 102 deletions(-) delete mode 100644 tests/js/context.tests.ts diff --git a/tests/js/context.tests.ts b/tests/js/context.tests.ts deleted file mode 100644 index fb97a8e4..00000000 --- a/tests/js/context.tests.ts +++ /dev/null @@ -1,102 +0,0 @@ -// import { expect } from "chai"; - -// import { -// ApplicationContextMixin, -// ContextProvider, -// createAndPatchRegistry, -// // MaterialContextMixin, -// } from "../../src/js/context"; -// import { ContextProviderConfig } from "../../src/js/context/provider"; - -// class MockMaterial { -// static createDefault() { -// return "defaultMockMaterial"; -// } -// } - -// class SpecificMockMaterial { -// static createDefault() { -// return "defaultSpecificMockMaterial"; -// } -// } - -// class MockApplication { -// static createDefault() { -// return "defaultMockApplication"; -// } -// } - -// class SpecificMockApplication { -// static createDefault() { -// return "defaultSpecificMockApplication"; -// } -// } - -// class ProviderEntity extends MaterialContextMixin(ApplicationContextMixin(ContextProvider)) { -// static Material = MockMaterial; - -// static Application = MockApplication; - -// static setting = 10; -// } - -// class DerivedProviderEntity extends ProviderEntity { -// static Material = SpecificMockMaterial; - -// static Application = SpecificMockApplication; -// } - -// class ApplicationContextProvider extends ApplicationContextMixin(ContextProvider) { -// static Application = SpecificMockApplication; -// } - -// describe("Material & Application ContextMixin", () => { -// const config: ContextProviderConfig = { name: "test" }; - -// it("uses static entity class", () => { -// const provider = new ProviderEntity(config); -// expect(provider.material).to.be.equal("defaultMockMaterial"); -// expect(provider.application).to.be.equal("defaultMockApplication"); -// }); - -// it("uses static entity class from derived class", () => { -// const provider = new DerivedProviderEntity(config); -// expect(provider.material).to.be.equal("defaultSpecificMockMaterial"); -// expect(provider.application).to.be.equal("defaultSpecificMockApplication"); -// }); -// }); - -// describe("ContextProviderRegistryContainer", () => { -// const classConfigObj = { -// DataManager: { -// providerCls: ProviderEntity, -// config: { name: "example1", domain: "important" }, -// }, -// ApplicationDataManager: { -// providerCls: ApplicationContextProvider, -// config: { name: "example2", domain: "important" }, -// }, -// }; - -// const defaultSettings = { -// ProviderEntity: { -// setting: 100, -// }, -// }; - -// it("can be created and patched", () => { -// const registry = createAndPatchRegistry( -// classConfigObj, -// { Material: SpecificMockMaterial }, -// defaultSettings, -// ); - -// const _dataProvider = registry.findProviderInstanceByName("DataManager"); -// const dataProvider = new _dataProvider.constructor(_dataProvider.config); -// const _appProvider = registry.findProviderInstanceByName("ApplicationDataManager"); -// const appProvider = new _appProvider.constructor(_appProvider.config); -// expect(_dataProvider.constructor.setting).to.be.equal(100); -// expect(dataProvider.material).to.be.equal("defaultSpecificMockMaterial"); -// expect(appProvider.application).to.be.equal("defaultSpecificMockApplication"); -// }); -// }); From 3fbf30e5318c9f1ab7a3a5b967fa57d2b70cad3e Mon Sep 17 00:00:00 2001 From: Kostiantyn Dvornik Date: Thu, 19 Jun 2025 15:47:04 +0300 Subject: [PATCH 10/10] chore: remove context providers --- dist/js/context/index.d.ts | 5 +- dist/js/context/index.js | 10 +- dist/js/context/json_schema_provider.d.ts | 25 ---- dist/js/context/json_schema_provider.js | 46 ------- dist/js/context/provider.d.ts | 53 -------- dist/js/context/provider.js | 110 --------------- dist/js/context/registry.d.ts | 49 ------- dist/js/context/registry.js | 77 ----------- package.json | 2 - src/js/context/index.ts | 17 +-- src/js/context/json_schema_provider.ts | 56 -------- src/js/context/provider.ts | 157 ---------------------- src/js/context/registry.ts | 121 ----------------- tests/js/provider.tests.ts | 25 ---- 14 files changed, 3 insertions(+), 750 deletions(-) delete mode 100644 dist/js/context/json_schema_provider.d.ts delete mode 100644 dist/js/context/json_schema_provider.js delete mode 100644 dist/js/context/provider.d.ts delete mode 100644 dist/js/context/provider.js delete mode 100644 dist/js/context/registry.d.ts delete mode 100644 dist/js/context/registry.js delete mode 100644 src/js/context/json_schema_provider.ts delete mode 100644 src/js/context/provider.ts delete mode 100644 src/js/context/registry.ts delete mode 100644 tests/js/provider.tests.ts diff --git a/dist/js/context/index.d.ts b/dist/js/context/index.d.ts index e308ca21..1a1ae105 100644 --- a/dist/js/context/index.d.ts +++ b/dist/js/context/index.d.ts @@ -1,5 +1,2 @@ -import { JSONSchemaFormDataProvider } from "./json_schema_provider"; import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; -import { ContextProvider } from "./provider"; -import { ContextProviderRegistryContainer, createAndPatchRegistry, extendAndPatchRegistry } from "./registry"; -export { ContextProvider, ContextProviderRegistryContainer, extendAndPatchRegistry, createAndPatchRegistry, JobContextPickKeysForMixin, JSONSchemaFormDataProvider, WorkflowContextPickKeysForMixin, }; +export { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin }; diff --git a/dist/js/context/index.js b/dist/js/context/index.js index 7981f589..40362a12 100644 --- a/dist/js/context/index.js +++ b/dist/js/context/index.js @@ -1,14 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WorkflowContextPickKeysForMixin = exports.JSONSchemaFormDataProvider = exports.JobContextPickKeysForMixin = exports.createAndPatchRegistry = exports.extendAndPatchRegistry = exports.ContextProviderRegistryContainer = exports.ContextProvider = void 0; -const json_schema_provider_1 = require("./json_schema_provider"); -Object.defineProperty(exports, "JSONSchemaFormDataProvider", { enumerable: true, get: function () { return json_schema_provider_1.JSONSchemaFormDataProvider; } }); +exports.WorkflowContextPickKeysForMixin = exports.JobContextPickKeysForMixin = void 0; const pickers_1 = require("./pickers"); Object.defineProperty(exports, "JobContextPickKeysForMixin", { enumerable: true, get: function () { return pickers_1.JobContextPickKeysForMixin; } }); Object.defineProperty(exports, "WorkflowContextPickKeysForMixin", { enumerable: true, get: function () { return pickers_1.WorkflowContextPickKeysForMixin; } }); -const provider_1 = require("./provider"); -Object.defineProperty(exports, "ContextProvider", { enumerable: true, get: function () { return provider_1.ContextProvider; } }); -const registry_1 = require("./registry"); -Object.defineProperty(exports, "ContextProviderRegistryContainer", { enumerable: true, get: function () { return registry_1.ContextProviderRegistryContainer; } }); -Object.defineProperty(exports, "createAndPatchRegistry", { enumerable: true, get: function () { return registry_1.createAndPatchRegistry; } }); -Object.defineProperty(exports, "extendAndPatchRegistry", { enumerable: true, get: function () { return registry_1.extendAndPatchRegistry; } }); diff --git a/dist/js/context/json_schema_provider.d.ts b/dist/js/context/json_schema_provider.d.ts deleted file mode 100644 index 7dc39b2a..00000000 --- a/dist/js/context/json_schema_provider.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UiSchema } from "react-jsonschema-form"; -import { ContextProvider, ContextProviderConfig } from "./provider"; -interface JSONSchemaFormDataProviderConfig extends ContextProviderConfig { - isUsingJinjaVariables?: boolean; -} -/** - * @summary Provides jsonSchema and uiSchema for generating react-jsonschema-form - * See https://github.com/mozilla-services/react-jsonschema-form for Form UI. - * Form generation example: - * ``` - *
- * ``` - */ -declare class JSONSchemaFormDataProvider extends ContextProvider { - isUsingJinjaVariables: boolean; - constructor(config: JSONSchemaFormDataProviderConfig); - get jsonSchema(): void; - get uiSchema(): UiSchema; - get fields(): {}; - get defaultFieldStyles(): {}; - get uiSchemaStyled(): UiSchema; -} -export { JSONSchemaFormDataProvider }; diff --git a/dist/js/context/json_schema_provider.js b/dist/js/context/json_schema_provider.js deleted file mode 100644 index 67cd2e44..00000000 --- a/dist/js/context/json_schema_provider.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.JSONSchemaFormDataProvider = void 0; -const underscore_1 = __importDefault(require("underscore")); -const provider_1 = require("./provider"); -/** - * @summary Provides jsonSchema and uiSchema for generating react-jsonschema-form - * See https://github.com/mozilla-services/react-jsonschema-form for Form UI. - * Form generation example: - * ``` - * - * ``` - */ -class JSONSchemaFormDataProvider extends provider_1.ContextProvider { - constructor(config) { - super(config); - this.isUsingJinjaVariables = Boolean(config === null || config === void 0 ? void 0 : config.isUsingJinjaVariables); - } - get jsonSchema() { - throw new Error("Not implemented."); - } - get uiSchema() { - throw new Error("Not implemented."); - } - get fields() { - return {}; - } - get defaultFieldStyles() { - return {}; - } - get uiSchemaStyled() { - const schema = this.uiSchema; - // @ts-ignore - return underscore_1.default.each(schema, (v, k, l) => { - l[k] = { ...v, ...this.defaultFieldStyles }; - l[k].classNames = `${v.classNames || ""}`; - return null; - }); - } -} -exports.JSONSchemaFormDataProvider = JSONSchemaFormDataProvider; diff --git a/dist/js/context/provider.d.ts b/dist/js/context/provider.d.ts deleted file mode 100644 index e1b891f5..00000000 --- a/dist/js/context/provider.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { ContextProviderInstance } from "./registry"; -export interface ContextProviderConfig { - name: string; - domain?: string; - entityName?: string; - data?: object; - extraData?: object; - isEdited?: boolean; - context?: object; -} -export interface ContextProviderStatic { - getConstructorConfig: (config: ContextProviderConfig) => ContextProviderInstance; - createConfigFromContext: (config: ContextProviderConfig) => ContextProviderConfig; - getExtraDataKeyByName: (name: string) => string; - getIsEditedKeyByName: (name: string) => string; -} -export declare class ContextProvider { - config: ContextProviderConfig; - name: string; - domain?: string; - entityName?: string; - data?: object; - extraData?: object; - isEdited?: boolean; - constructor(config: ContextProviderConfig); - static getConstructorConfig(config: ContextProviderConfig): ContextProviderInstance; - static createConfigFromContext(config: ContextProviderConfig): ContextProviderConfig & ({ - data: any; - extraData: any; - isEdited: any; - } | { - data?: undefined; - extraData?: undefined; - isEdited?: undefined; - }); - setIsEdited(isEdited: boolean): void; - getData(): void | object; - setData(data: object): void; - get defaultData(): void; - transformData(data: object): object; - yieldData(...transformDataArgs: any): { - [x: string]: boolean | object | undefined; - }; - yieldDataForRendering(): { - [x: string]: boolean | object | undefined; - }; - get extraDataKey(): string; - static getExtraDataKeyByName(name: string): string; - get isEditedKey(): string; - static getIsEditedKeyByName(name: string): string; - get isUnitContextProvider(): boolean; - get isSubworkflowContextProvider(): boolean; -} diff --git a/dist/js/context/provider.js b/dist/js/context/provider.js deleted file mode 100644 index 6a5bd15b..00000000 --- a/dist/js/context/provider.js +++ /dev/null @@ -1,110 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ContextProvider = void 0; -/* - * @summary This is a standalone class that contains "data" for a property with "name". Helps facilitate UI logic. - * Can be initialized from context when user edits are present: - * - user edits the corresponding property, eg. "kpath" - * - isKpathEdited is set to `true` - * - context property is updated for the parent entity (eg. Unit) in a way that persists in Redux state - * - new entity inherits the "data" through "context" field in config - * - `extraData` field is used to store any other data that should be passed from one instance of provider - * to next one, for example data about material to track when it is changed. - * @notes Should hold static data only (see `setData` method), no classes or functions - */ -const lodash_1 = __importDefault(require("lodash")); -const clone_1 = require("../utils/clone"); -class ContextProvider { - constructor(config) { - this.config = config; - this.name = config.name; // property name, ie. "kpath" - this.domain = config.domain || "default"; - // if context is passed inside config, treat it as additional config - // eslint-disable-next-line no-param-reassign - if (config.context) - config = ContextProvider.createConfigFromContext(config); - this.entityName = config.entityName || "unit"; // entity this provider yields data to, eg. "unit", "subworkflow" - this.data = config.data; // property data container - this.extraData = config.extraData; // property extraData container, used track changes to data, for example - this.isEdited = config.isEdited; // whether property was edited by user, available under `isEdited` key - this.setIsEdited = this.setIsEdited.bind(this); - this.getData = this.getData.bind(this); - this.setData = this.setData.bind(this); - this.transformData = this.transformData.bind(this); - this.yieldData = this.yieldData.bind(this); - } - static getConstructorConfig(config) { - return { - constructor: this.prototype.constructor, - config, - }; - } - static createConfigFromContext(config) { - const data = lodash_1.default.get(config.context, config.name); - const isEdited = lodash_1.default.get(config.context, this.getIsEditedKeyByName(config.name)); - const extraData = lodash_1.default.get(config.context, this.getExtraDataKeyByName(config.name)); - return Object.assign(config, data - ? { - data, - extraData, - isEdited, - } - : {}); - } - setIsEdited(isEdited) { - this.isEdited = isEdited; - } - getData() { - return this.isEdited ? this.data : this.defaultData; - } - setData(data) { - this.data = (0, clone_1.deepClone)(data); - } - // override in children - // eslint-disable-next-line class-methods-use-this - get defaultData() { - throw new Error("Not implemented."); - } - // override in children - // eslint-disable-next-line class-methods-use-this - transformData(data) { - return data; - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - yieldData(...transformDataArgs) { - const extraDataObject = this.extraData ? { [this.extraDataKey]: this.extraData } : {}; - return { - ...extraDataObject, - // @ts-ignore - [this.name]: this.transformData(this.getData(), ...transformDataArgs), - [this.isEditedKey]: this.isEdited, - }; - } - // override when this.data needs additional processing before making it available to rendering context - // used to calculate explicit points path, for example - yieldDataForRendering() { - return this.yieldData(); - } - get extraDataKey() { - return `${this.name}ExtraData`; - } - static getExtraDataKeyByName(name) { - return `${name}ExtraData`; - } - get isEditedKey() { - return `is${lodash_1.default.capitalize(this.name)}Edited`; - } - static getIsEditedKeyByName(name) { - return `is${lodash_1.default.capitalize(name)}Edited`; - } - get isUnitContextProvider() { - return this.entityName === "unit"; - } - get isSubworkflowContextProvider() { - return this.entityName === "subworkflow"; - } -} -exports.ContextProvider = ContextProvider; diff --git a/dist/js/context/registry.d.ts b/dist/js/context/registry.d.ts deleted file mode 100644 index 49b0178c..00000000 --- a/dist/js/context/registry.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { ContextProvider, ContextProviderConfig, ContextProviderStatic } from "./provider"; -export interface ContextProviderInstance { - constructor: typeof ContextProvider; - config: ContextProviderConfig; -} -export declare class ContextProviderRegistryContainer { - _providers: { - name: string; - instance: ContextProviderInstance; - }[]; - constructor(); - get providers(): { - name: string; - instance: ContextProviderInstance; - }[]; - set providers(p: { - name: string; - instance: ContextProviderInstance; - }[]); - addProvider({ name, instance }: { - name: string; - instance: ContextProviderInstance; - }): void; - findProviderInstanceByName(name: string): ContextProviderInstance | undefined; - removeProvider(providerCls: ContextProvider): void; - removeProviderByName(name: string): void; -} -/** Extends an existing context provider registry container and patches static class variables if applicable. - * @example - * const classConfigMap = { - * PlanewaveCutoffDataManager: { - * providerCls: PlanewaveCutoffsContextProvider, - * config: _makeImportant({ name: "cutoffs", entityName: "subworkflow" }) - * }, - * }; - */ -export declare const extendAndPatchRegistry: (registryContainer: ContextProviderRegistryContainer, classConfigMap: Record, classesToPatch?: Partial, defaultSettings?: Partial>) => ContextProviderRegistryContainer; -/** Creates a new context provider registry container and patches static class variables if applicable. - * - * @param {Object} classConfigMap - * @param {{Material: SpecificMockMaterial}} classesToPatch - */ -export declare const createAndPatchRegistry: (classConfigMap: Record, classesToPatch?: Partial, defaultSettings?: Partial>) => ContextProviderRegistryContainer; diff --git a/dist/js/context/registry.js b/dist/js/context/registry.js deleted file mode 100644 index f156751e..00000000 --- a/dist/js/context/registry.js +++ /dev/null @@ -1,77 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.createAndPatchRegistry = exports.extendAndPatchRegistry = exports.ContextProviderRegistryContainer = void 0; -class ContextProviderRegistryContainer { - constructor() { - this._providers = []; - } - get providers() { - return this._providers; - } - set providers(p) { - this._providers = p; - } - addProvider({ name, instance }) { - this._providers.push({ - name, - instance, - }); - } - findProviderInstanceByName(name) { - const provider = this.providers.find((p) => p.name === name); - return provider && provider.instance; - } - removeProvider(providerCls) { - this.providers = this.providers.filter((p) => p.name === providerCls.name); - } - removeProviderByName(name) { - this.providers = this.providers.filter((p) => p.name === name); - } -} -exports.ContextProviderRegistryContainer = ContextProviderRegistryContainer; -/** Extends an existing context provider registry container and patches static class variables if applicable. - * @example - * const classConfigMap = { - * PlanewaveCutoffDataManager: { - * providerCls: PlanewaveCutoffsContextProvider, - * config: _makeImportant({ name: "cutoffs", entityName: "subworkflow" }) - * }, - * }; - */ -const extendAndPatchRegistry = (registryContainer, classConfigMap, classesToPatch = {}, defaultSettings = {}) => { - Object.entries(classConfigMap).forEach(([name, { providerCls, config }]) => { - const entries = Object.entries(classesToPatch); - entries.forEach(([clsName, cls]) => { - if (providerCls[clsName]) { - // @ts-expect-error - providerCls[clsName] = cls; - } - const providerDefaultSettings = defaultSettings[providerCls.name]; - if (providerDefaultSettings) { - const providerDefaultSettingsEntries = Object.entries(providerDefaultSettings); - providerDefaultSettingsEntries.forEach(([key, value]) => { - if (providerCls[key]) { - // @ts-expect-error - providerCls[key] = value; - } - }); - } - }); - registryContainer.addProvider({ - instance: providerCls.getConstructorConfig(config), - name, - }); - }); - return registryContainer; -}; -exports.extendAndPatchRegistry = extendAndPatchRegistry; -/** Creates a new context provider registry container and patches static class variables if applicable. - * - * @param {Object} classConfigMap - * @param {{Material: SpecificMockMaterial}} classesToPatch - */ -const createAndPatchRegistry = (classConfigMap, classesToPatch = {}, defaultSettings = {}) => { - const registryContainer = new ContextProviderRegistryContainer(); - return (0, exports.extendAndPatchRegistry)(registryContainer, classConfigMap, classesToPatch, defaultSettings); -}; -exports.createAndPatchRegistry = createAndPatchRegistry; diff --git a/package.json b/package.json index c2fac1df..548b7f20 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,6 @@ "mathjs": "^5.10.3", "mixwith": "^0.1.1", "nunjucks": "^3.2.4", - "react-jsonschema-form": "^1.8.1", "semver": "^7.6.3", "underscore": "^1.13.7", "underscore.string": "^3.3.6", @@ -63,7 +62,6 @@ "@types/json-schema": "^7.0.15", "@types/mocha": "^10.0.8", "@types/node": "^20.16.10", - "@types/react-jsonschema-form": "^1.7.13", "@types/underscore": "^1.11.15", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", diff --git a/src/js/context/index.ts b/src/js/context/index.ts index 885274c7..a6cd4f1b 100644 --- a/src/js/context/index.ts +++ b/src/js/context/index.ts @@ -1,18 +1,3 @@ -import { JSONSchemaFormDataProvider } from "./json_schema_provider"; import { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin } from "./pickers"; -import { ContextProvider } from "./provider"; -import { - ContextProviderRegistryContainer, - createAndPatchRegistry, - extendAndPatchRegistry, -} from "./registry"; -export { - ContextProvider, - ContextProviderRegistryContainer, - extendAndPatchRegistry, - createAndPatchRegistry, - JobContextPickKeysForMixin, - JSONSchemaFormDataProvider, - WorkflowContextPickKeysForMixin, -}; +export { JobContextPickKeysForMixin, WorkflowContextPickKeysForMixin }; diff --git a/src/js/context/json_schema_provider.ts b/src/js/context/json_schema_provider.ts deleted file mode 100644 index cf41d84c..00000000 --- a/src/js/context/json_schema_provider.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable class-methods-use-this */ -import { UiSchema } from "react-jsonschema-form"; -import _ from "underscore"; - -import { ContextProvider, ContextProviderConfig } from "./provider"; - -interface JSONSchemaFormDataProviderConfig extends ContextProviderConfig { - isUsingJinjaVariables?: boolean; -} - -/** - * @summary Provides jsonSchema and uiSchema for generating react-jsonschema-form - * See https://github.com/mozilla-services/react-jsonschema-form for Form UI. - * Form generation example: - * ``` - * - * ``` - */ -class JSONSchemaFormDataProvider extends ContextProvider { - isUsingJinjaVariables: boolean; - - constructor(config: JSONSchemaFormDataProviderConfig) { - super(config); - this.isUsingJinjaVariables = Boolean(config?.isUsingJinjaVariables); - } - - get jsonSchema() { - throw new Error("Not implemented."); - } - - get uiSchema(): UiSchema { - throw new Error("Not implemented."); - } - - get fields() { - return {}; - } - - get defaultFieldStyles() { - return {}; - } - - get uiSchemaStyled(): UiSchema { - const schema = this.uiSchema; - // @ts-ignore - return _.each(schema, (v: UiSchema, k: string, l: UiSchema) => { - l[k] = { ...v, ...this.defaultFieldStyles }; - l[k].classNames = `${v.classNames || ""}`; - return null; - }); - } -} - -export { JSONSchemaFormDataProvider }; diff --git a/src/js/context/provider.ts b/src/js/context/provider.ts deleted file mode 100644 index 459d3b58..00000000 --- a/src/js/context/provider.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* - * @summary This is a standalone class that contains "data" for a property with "name". Helps facilitate UI logic. - * Can be initialized from context when user edits are present: - * - user edits the corresponding property, eg. "kpath" - * - isKpathEdited is set to `true` - * - context property is updated for the parent entity (eg. Unit) in a way that persists in Redux state - * - new entity inherits the "data" through "context" field in config - * - `extraData` field is used to store any other data that should be passed from one instance of provider - * to next one, for example data about material to track when it is changed. - * @notes Should hold static data only (see `setData` method), no classes or functions - */ -import lodash from "lodash"; - -import { deepClone } from "../utils/clone"; -import type { ContextProviderInstance } from "./registry"; - -export interface ContextProviderConfig { - name: string; - domain?: string; - entityName?: string; - data?: object; - extraData?: object; - isEdited?: boolean; - context?: object; -} - -export interface ContextProviderStatic { - getConstructorConfig: (config: ContextProviderConfig) => ContextProviderInstance; - createConfigFromContext: (config: ContextProviderConfig) => ContextProviderConfig; - getExtraDataKeyByName: (name: string) => string; - getIsEditedKeyByName: (name: string) => string; -} - -export class ContextProvider { - config: ContextProviderConfig; - - name: string; - - domain?: string; - - entityName?: string; - - data?: object; - - extraData?: object; - - isEdited?: boolean; - - constructor(config: ContextProviderConfig) { - this.config = config; - this.name = config.name; // property name, ie. "kpath" - this.domain = config.domain || "default"; - - // if context is passed inside config, treat it as additional config - // eslint-disable-next-line no-param-reassign - if (config.context) config = ContextProvider.createConfigFromContext(config); - - this.entityName = config.entityName || "unit"; // entity this provider yields data to, eg. "unit", "subworkflow" - this.data = config.data; // property data container - this.extraData = config.extraData; // property extraData container, used track changes to data, for example - this.isEdited = config.isEdited; // whether property was edited by user, available under `isEdited` key - - this.setIsEdited = this.setIsEdited.bind(this); - this.getData = this.getData.bind(this); - this.setData = this.setData.bind(this); - this.transformData = this.transformData.bind(this); - this.yieldData = this.yieldData.bind(this); - } - - static getConstructorConfig(config: ContextProviderConfig): ContextProviderInstance { - return { - constructor: this.prototype.constructor as typeof ContextProvider, - config, - }; - } - - static createConfigFromContext(config: ContextProviderConfig) { - const data = lodash.get(config.context, config.name); - const isEdited = lodash.get(config.context, this.getIsEditedKeyByName(config.name)); - const extraData = lodash.get(config.context, this.getExtraDataKeyByName(config.name)); - return Object.assign( - config, - data - ? { - data, - extraData, - isEdited, - } - : {}, - ); - } - - setIsEdited(isEdited: boolean) { - this.isEdited = isEdited; - } - - getData() { - return this.isEdited ? this.data : this.defaultData; - } - - setData(data: object) { - this.data = deepClone(data); - } - - // override in children - // eslint-disable-next-line class-methods-use-this - get defaultData() { - throw new Error("Not implemented."); - } - - // override in children - // eslint-disable-next-line class-methods-use-this - transformData(data: object) { - return data; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - yieldData(...transformDataArgs: any) { - const extraDataObject = this.extraData ? { [this.extraDataKey]: this.extraData } : {}; - return { - ...extraDataObject, - // @ts-ignore - [this.name]: this.transformData(this.getData(), ...transformDataArgs), - [this.isEditedKey]: this.isEdited, - }; - } - - // override when this.data needs additional processing before making it available to rendering context - // used to calculate explicit points path, for example - yieldDataForRendering() { - return this.yieldData(); - } - - get extraDataKey() { - return `${this.name}ExtraData`; - } - - static getExtraDataKeyByName(name: string) { - return `${name}ExtraData`; - } - - get isEditedKey() { - return `is${lodash.capitalize(this.name)}Edited`; - } - - static getIsEditedKeyByName(name: string) { - return `is${lodash.capitalize(name)}Edited`; - } - - get isUnitContextProvider() { - return this.entityName === "unit"; - } - - get isSubworkflowContextProvider() { - return this.entityName === "subworkflow"; - } -} diff --git a/src/js/context/registry.ts b/src/js/context/registry.ts deleted file mode 100644 index c6eff9d6..00000000 --- a/src/js/context/registry.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { ContextProvider, ContextProviderConfig, ContextProviderStatic } from "./provider"; - -export interface ContextProviderInstance { - constructor: typeof ContextProvider; - config: ContextProviderConfig; -} - -export class ContextProviderRegistryContainer { - _providers: { - name: string; - instance: ContextProviderInstance; - }[]; - - constructor() { - this._providers = []; - } - - get providers() { - return this._providers; - } - - set providers(p) { - this._providers = p; - } - - addProvider({ name, instance }: { name: string; instance: ContextProviderInstance }) { - this._providers.push({ - name, - instance, - }); - } - - findProviderInstanceByName(name: string) { - const provider = this.providers.find((p) => p.name === name); - return provider && provider.instance; - } - - removeProvider(providerCls: ContextProvider) { - this.providers = this.providers.filter((p) => p.name === providerCls.name); - } - - removeProviderByName(name: string) { - this.providers = this.providers.filter((p) => p.name === name); - } -} - -type ContextProviderStaticEntry = [ - keyof ContextProviderStatic, - ContextProviderStatic[keyof ContextProviderStatic], -]; - -/** Extends an existing context provider registry container and patches static class variables if applicable. - * @example - * const classConfigMap = { - * PlanewaveCutoffDataManager: { - * providerCls: PlanewaveCutoffsContextProvider, - * config: _makeImportant({ name: "cutoffs", entityName: "subworkflow" }) - * }, - * }; - */ -export const extendAndPatchRegistry = ( - registryContainer: ContextProviderRegistryContainer, - classConfigMap: Record< - string, - { providerCls: typeof ContextProvider; config: ContextProviderConfig } - >, - classesToPatch: Partial = {}, - defaultSettings: Partial> = {}, -) => { - Object.entries(classConfigMap).forEach(([name, { providerCls, config }]) => { - const entries = Object.entries(classesToPatch) as ContextProviderStaticEntry[]; - - entries.forEach(([clsName, cls]) => { - if (providerCls[clsName]) { - // @ts-expect-error - providerCls[clsName] = cls; - } - const providerDefaultSettings = defaultSettings[providerCls.name]; - if (providerDefaultSettings) { - const providerDefaultSettingsEntries = Object.entries( - providerDefaultSettings, - ) as ContextProviderStaticEntry[]; - - providerDefaultSettingsEntries.forEach(([key, value]) => { - if (providerCls[key]) { - // @ts-expect-error - providerCls[key] = value; - } - }); - } - }); - - registryContainer.addProvider({ - instance: providerCls.getConstructorConfig(config), - name, - }); - }); - return registryContainer; -}; - -/** Creates a new context provider registry container and patches static class variables if applicable. - * - * @param {Object} classConfigMap - * @param {{Material: SpecificMockMaterial}} classesToPatch - */ -export const createAndPatchRegistry = ( - classConfigMap: Record< - string, - { providerCls: typeof ContextProvider; config: ContextProviderConfig } - >, - classesToPatch: Partial = {}, - defaultSettings: Partial> = {}, -) => { - const registryContainer = new ContextProviderRegistryContainer(); - return extendAndPatchRegistry( - registryContainer, - classConfigMap, - classesToPatch, - defaultSettings, - ); -}; diff --git a/tests/js/provider.tests.ts b/tests/js/provider.tests.ts deleted file mode 100644 index d72b3ad6..00000000 --- a/tests/js/provider.tests.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { expect } from "chai"; - -import { ContextProvider } from "../../src/js/context/provider"; - -describe("ContextProvider", () => { - const minimal = { name: "name" }; - const data = { a: "test" }; - - it("can be created", () => { - const provider = new ContextProvider(minimal); - // eslint-disable-next-line no-unused-expressions - expect(provider).to.exist; - }); - - it("sets and gets data", () => { - const provider = new ContextProvider(minimal); - provider.setData(data); - expect(() => provider.getData()).to.throw("Not implemented."); - provider.setIsEdited(true); - expect(JSON.stringify(provider.getData())).to.equal(JSON.stringify(data)); - expect(() => provider.defaultData).to.throw("Not implemented."); - }); - - // transform, yieldData, yieldDataForRendering -});