Skip to content

Commit 0b22655

Browse files
Merge pull request #8 from Exabyte-io/feature/SOF-5795
Draft: Feature/sof 5795
2 parents 4f3e9d4 + 8d1c8ae commit 0b22655

File tree

11 files changed

+664
-105
lines changed

11 files changed

+664
-105
lines changed

package-lock.json

Lines changed: 214 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,24 @@
5050
"lodash": "^4.17.21",
5151
"mathjs": "^3.9.0",
5252
"mixwith": "^0.1.1",
53-
"underscore": "^1.13.3"
53+
"underscore": "^1.13.3",
54+
"underscore.string": "^3.3.4"
5455
},
5556
"devDependencies": {
5657
"chai": "^4.3.4",
5758
"eslint": "7.32.0",
5859
"eslint-config-airbnb": "19.0.2",
5960
"eslint-config-prettier": "8.3.0",
61+
"eslint-plugin-react": "^7.30.0",
6062
"eslint-plugin-import": "2.25.3",
6163
"eslint-plugin-jsdoc": "37.1.0",
6264
"eslint-plugin-jsx-a11y": "6.5.1",
63-
"eslint-plugin-prettier": "4.0.0",
6465
"eslint-plugin-simple-import-sort": "7.0.0",
6566
"husky": "^7.0.4",
6667
"lint-staged": "^12.1.2",
6768
"mocha": "^9.1.3",
68-
"nyc": "^15.1.0"
69+
"nyc": "^15.1.0",
70+
"prettier": "^2.7.1"
6971
},
7072
"engines": {
7173
"node": ">=12.0.0"

src/entity/index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import {
77
DefaultableInMemoryEntity,
88
NamedDefaultableInMemoryEntity,
99
HasMetadataNamedDefaultableInMemoryEntity,
10+
NamedDefaultableRepetitionContextAndRenderInMemoryEntity,
11+
NamedDefaultableRepetitionImportantSettingsInMemoryEntity,
12+
NamedDefaultableRepetitionRuntimeItemsImportantSettingsContextAndRenderHashedInMemoryEntity,
1013
} from "./other";
1114

1215
import {
@@ -15,15 +18,22 @@ import {
1518
HasMetadataMixin,
1619
TaggableMixin,
1720
NamedEntityMixin,
18-
} from "./mixins";
21+
} from "./mixins/props";
22+
23+
import { HashedInputArrayMixin } from "./mixins/hash";
24+
import { RuntimeItemsMixin } from "./mixins/runtime_items";
25+
import { RuntimeContextFieldMixin } from "./mixins/context_runtime";
1926

2027
import { InMemoryEntitySet } from "./set";
2128
import { ENTITY_SET_TYPES } from "./set/enums";
2229

2330
import { constructEntitySetFactoryByConfig } from "./set/factory";
2431
import { InMemoryEntitySetMixin, InMemoryEntityInSetMixin } from "./set/mixins";
2532
import * as selectorsForEntitySet from "./set/selectors";
26-
import { OrderedInMemoryEntityInSetMixin, OrderedInMemoryEntitySetMixin } from "./set/ordered/mixins";
33+
import {
34+
OrderedInMemoryEntityInSetMixin,
35+
OrderedInMemoryEntitySetMixin,
36+
} from "./set/ordered/mixins";
2737

2838
export {
2939

@@ -32,12 +42,18 @@ export {
3242
DefaultableInMemoryEntity,
3343
NamedDefaultableInMemoryEntity,
3444
HasMetadataNamedDefaultableInMemoryEntity,
45+
NamedDefaultableRepetitionContextAndRenderInMemoryEntity,
46+
NamedDefaultableRepetitionImportantSettingsInMemoryEntity,
47+
NamedDefaultableRepetitionRuntimeItemsImportantSettingsContextAndRenderHashedInMemoryEntity,
3548

3649
DefaultableMixin,
3750
HasDescriptionMixin,
3851
HasMetadataMixin,
3952
TaggableMixin,
4053
NamedEntityMixin,
54+
RuntimeItemsMixin,
55+
RuntimeContextFieldMixin,
56+
HashedInputArrayMixin,
4157

4258
InMemoryEntitySet,
4359
ENTITY_SET_TYPES,

src/entity/mixins.js

Lines changed: 0 additions & 66 deletions
This file was deleted.

src/entity/mixins/context.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { deepClone } from "../../utils/clone";
2+
3+
export const ContextAndRenderFieldsMixin = (superclass) => {
4+
return class extends superclass {
5+
constructor(config) {
6+
super(config);
7+
this._context = config.context || {};
8+
}
9+
10+
// in-memory, or "volatile" context that is reset when the `parent` object is destroyed
11+
get context() {
12+
return this._context;
13+
}
14+
15+
set context(newContext) {
16+
this._context = newContext;
17+
}
18+
19+
updateContext(ctx = {}, executeRender = false) {
20+
this._context = Object.assign({}, this.context, ctx);
21+
executeRender && this.render();
22+
}
23+
24+
// to get "persistent" context, that is stored in database and further should be provided to constructor
25+
// when the `parent` object is re-created
26+
getPersistentContext() {
27+
return this.prop("context");
28+
}
29+
30+
// to make context persistent in `_json`
31+
updatePersistentContext(ctx = {}) {
32+
this.setProp("context", Object.assign({}, ctx));
33+
}
34+
35+
// to get persistent and volatile context combined
36+
getCombinedContext() {
37+
return Object.assign({}, this.getPersistentContext(), this.context);
38+
}
39+
40+
// override in subclasses
41+
render(context = this.context) {
42+
throw new Error("RenderInitMixin: render not implemented in derived class");
43+
}
44+
};
45+
};
46+
47+
/*
48+
* @summary Handles logic for domain-specific context, eg. "important settings".
49+
* Important settings are stored inside "important" property and have context providers associated with it.
50+
*/
51+
export const DomainContextProviderMixin = (superclass) => {
52+
return class extends superclass {
53+
constructor(config) {
54+
super(config);
55+
this._contextProviders = [];
56+
}
57+
58+
get contextProviders() {
59+
// override in children
60+
return this._contextProviders;
61+
}
62+
};
63+
};
64+
65+
export const ImportantSettingsProviderMixin = (superclass) => {
66+
return class extends DomainContextProviderMixin(superclass) {
67+
get important() {
68+
return deepClone(this._json.important || {});
69+
}
70+
71+
setImportant(key, value) {
72+
this.setProp("important", {[key]: value})
73+
}
74+
75+
/**
76+
* @return {JSONSchemaFormDataProvider[]}
77+
*/
78+
get importantSettingsProviders() {
79+
return this.contextProviders.filter(p => p.domain === "important");
80+
}
81+
82+
get isImportantEdited() {
83+
return this.prop("important.isEdited");
84+
}
85+
86+
set isImportantEdited(bool) {
87+
this.setProp("important", Object.assign(this.important, {isEdited: bool}));
88+
}
89+
};
90+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export const RuntimeContextFieldMixin = (superclass) => {
2+
return class extends superclass {
3+
constructor(config) {
4+
super(config);
5+
this._runtimeContext = config.runtimeContext || {};
6+
}
7+
8+
// in-memory, or "volatile" runtimeContext that is reset when the `parent` object is destroyed
9+
get runtimeContext() {
10+
return this._runtimeContext;
11+
}
12+
13+
set runtimeContext(newContext) {
14+
this._runtimeContext = newContext;
15+
}
16+
17+
updateRuntimeContext(ctx = {}) {
18+
this.runtimeContext = Object.assign(this._runtimeContext, ctx);
19+
}
20+
21+
toJSON() {
22+
return Object.assign({}, super.toJSON(), {runtimeContext: this._runtimeContext});
23+
}
24+
};
25+
};

src/entity/mixins/hash.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { calculateHashFromObject } from "../../utils/hash";
2+
import { removeCommentsFromSourceCode, removeEmptyLinesFromString } from "../../utils/str";
3+
4+
export const HashedEntityMixin = (superclass) => {
5+
return class extends superclass {
6+
/*
7+
* @summary Returns an object based on meaningful fields for this unit, that will be used to calculate the hash
8+
* Must be overridden.
9+
*/
10+
getHashObject() {
11+
return {};
12+
}
13+
14+
/**
15+
* @summary Calculates hash based on meaningful fields and unit-specific fields. Unit-specific fields are
16+
* separated into _typeSpecificHash function which can be overwritten by child classes.
17+
* head and next are also important but not considered since they are included in subworkflow hash.
18+
*/
19+
calculateHash() {
20+
return calculateHashFromObject(this.getHashObject());
21+
}
22+
};
23+
};
24+
25+
export const HashedInputArrayMixin = (superclass) => {
26+
return class extends superclass {
27+
/*
28+
* @summary expects an array with elements containing field [{content: "..."}]
29+
*/
30+
get hashFromArrayInputContent() {
31+
const objectForHashing = this.input.map(i =>
32+
removeEmptyLinesFromString(removeCommentsFromSourceCode(i.content))
33+
);
34+
return calculateHashFromObject(objectForHashing)
35+
}
36+
};
37+
};

src/entity/mixins/props.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
export const DefaultableMixin = (superclass) => {
2+
return class extends superclass {
3+
get isDefault() {
4+
return this.prop("isDefault", false);
5+
}
6+
7+
// Define in superclass
8+
// static get defaultConfig() {
9+
// }
10+
11+
static createDefault() {
12+
return new this.prototype.constructor(this.defaultConfig);
13+
}
14+
};
15+
};
16+
17+
export const TaggableMixin = (superclass) => {
18+
return class extends superclass {
19+
get tags() {return this.prop("tags", [])}
20+
21+
set tags(array) {this.setProp("tags", array)}
22+
23+
// only keep unique elements in tags
24+
setTags(array) {this.tags = array.filter((value, index, self) => self.indexOf(value) === index)}
25+
};
26+
};
27+
28+
export const HasMetadataMixin = (superclass) => {
29+
return class extends superclass {
30+
get metadata() {return this.prop("metadata", {})}
31+
32+
set metadata(object) {this.setProp("metadata", object)}
33+
34+
updateMetadata(object) {this.metadata = Object.assign({}, this.metadata, object)}
35+
};
36+
};
37+
38+
export const HasDescriptionMixin = (superclass) => {
39+
return class extends superclass {
40+
get description() {return this.prop("description", "")}
41+
42+
set description(string) {this.setProp("description", string)}
43+
44+
get descriptionObject() {return this.prop("descriptionObject")}
45+
46+
set descriptionObject(obj) {this.setProp("descriptionObject", obj)}
47+
};
48+
};
49+
50+
export const NamedEntityMixin = (superclass) => {
51+
return class extends superclass {
52+
get name() {
53+
return this.prop("name", "");
54+
}
55+
56+
set name(name) {
57+
this.setProp("name", name);
58+
}
59+
60+
// to be used when getter is overriden
61+
setName(name) {
62+
this.setProp("name", name);
63+
}
64+
};
65+
};

src/entity/mixins/repetition.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export const HasRepetitionMixin = (superclass) => {
2+
return class extends superclass {
3+
get repetition() {
4+
return this._repetition || 0
5+
}
6+
7+
setRepetition(repetition) {
8+
this._repetition = repetition;
9+
10+
if (["Subworkflow", "Workflow"].find(n => this.constructor.name === n)) {
11+
this.units.forEach(u => u.setRepetition(repetition));
12+
}
13+
14+
if (this.constructor.name === "Workflow") {
15+
this.subworkflows.forEach(sw => sw.setRepetition(repetition));
16+
this.workflows.forEach(wf => wf.setRepetition(repetition));
17+
}
18+
}
19+
20+
get totalRepetitions() {
21+
return this._totalRepetitions || 1
22+
}
23+
24+
setTotalRepetitions(totalRepetition) {
25+
this._totalRepetitions = totalRepetition;
26+
}
27+
};
28+
};

0 commit comments

Comments
 (0)