Commit 4f15743c authored by Azat Alimov's avatar Azat Alimov
Browse files

updated to last `dev` version

parent 87473aaf
Showing with 399 additions and 338 deletions
+399 -338
This diff is collapsed.
......@@ -6,11 +6,11 @@
// Copyright © 2020 memri. All rights reserved.
//
import {Action} from "ts-loader/dist/interfaces";
import {Expression} from "../../parsers/expression-parser/Expression";
import {Action, ActionMultiAction} from "./Action";
class Cascadable {
viewArguments;
export class Cascadable {
viewArguments?;
cascadeStack;
localCache = [];
......@@ -160,7 +160,7 @@ class Cascadable {
return result
}
init(cascadeStack, viewArguments) {
constructor(cascadeStack, viewArguments?) {
this.viewArguments = viewArguments
this.cascadeStack = cascadeStack
}
......
......@@ -6,6 +6,11 @@
// Copyright © 2020 memri. All rights reserved.
//
import {Cascadable} from "./Cascadable";
import {UserState, ViewArguments} from "./UserState";
import {CVUParsedRendererDefinition} from "../../parsers/cvu-parser/CVUParsedDefinition";
import {Expression} from "../../parsers/expression-parser/Expression";
class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
/// The name of the cascading view
......@@ -31,26 +36,40 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
else {
// Missing datasource on sessionview, that should never happen (I think)
// TODO ERROR REPORTING
//debugHistory.error("Unexpected state")
return new CascadingDatasource([], new ViewArguments(), new Datasource())
}
}
get userState() {
return this.sessionView.userState ?? new UserState(function (args) {
/*realmWriteIfAvailable(this.sessionView.realm, function (args) {
this.sessionView.userState = args
})*/
})
let args = this.sessionView.userState;
if (args) {
return args
}
try {
let args = new Cache.createItem(UserState.self, {});//TODO
this.sessionView.set("userState", args)
return args
} catch {
//debugHistory.error("Exception: Unable to create user state for session view: \(error)")
return null
}
}
// TODO let this cascade when the use case for it arrises
get viewArguments() {
return this.sessionView.viewArguments ?? new ViewArguments(function (args) {
/*realmWriteIfAvailable(this.sessionView.realm, function (args) {
this.sessionView.userState = args
})*/
})
let args = this.sessionView.viewArguments;
if (args) {
return args
}
try {
let args = new Cache.createItem(ViewArguments.self, {});//TODO
this.sessionView.set("viewArguments", args)
return args
} catch {
//debugHistory.error("Exception: Unable to create arguments for session view: \(error)")
return null
}
// cascadeProperty("viewArguments", )
}
......@@ -64,7 +83,7 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
this.localCache["resultSet"] = resultSet;
// Filter the results
let ft = this.userState("filterText") ?? "";
let ft = this.userState?.get("filterText") ?? "";
if (resultSet.filterText != ft) {
this.filterText = ft;
}
......@@ -87,8 +106,8 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
}
set activeRenderer(value) {
this.localCache.removeValue(value) // Remove renderConfig reference TODO
this.userState.set("activeRenderer", value) //TODO:??
this.localCache[value] = undefined; // Remove renderConfig reference TODO
this.userState?.set("activeRenderer", value) //TODO:??
}
get backTitle() { return this.cascadeProperty("backTitle") }
......@@ -124,9 +143,8 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
renderDef.push(this.context?.views
.fetchDefinitions(/*String(*/name/*)*/, "renderer") ?? [])
}
for (let def of renderDef) {
try {
try {
for (let def of renderDef) {
let parsedRenderDef = this.context?.views.parseDefinition(def)
if (parsedRenderDef instanceof CVUParsedRendererDefinition) {
if (parsedRenderDef.domain == "user") {
......@@ -138,36 +156,35 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
}
}
stack.splice(insertPoint, 0, parsedRenderDef)
}
else {
} else {
stack.push(parsedRenderDef)
}
}
else {
} else {
// TODO Error logging
// debugHistory.error("Exception: Unable to cascade render config")
}
}
catch (error) {
// TODO Error logging
debugHistory.error(`${error}`);
let RenderConfigType = this.allRenderers.allConfigTypes[this.activeRenderer]
if (this.allRenderers && RenderConfigType) {
let renderConfig = RenderConfigType.init(stack, new ViewArguments.clone(this.viewArguments, false)) //TODO:?
// Not actively preventing conflicts in namespace - assuming chance to be low
this.localCache[this.activeRenderer] = renderConfig;
return renderConfig
} else {
// TODO Error Logging
throw "Exception: Unable to cascade render config"
}
}
let RenderConfigType = this.allRenderers.allConfigTypes[this.activeRenderer]
if (this.allRenderers && RenderConfigType) {
let renderConfig = RenderConfigType.init(stack, this.viewArguments)//TODO:?
// Not actively preventing conflicts in namespace - assuming chance to be low
this.localCache[this.activeRenderer] = renderConfig;
return renderConfig
}
else {
// TODO Error Logging
// debugHistory.error("Exception: Unable to cascade render config")
return new CascadingRenderConfig([], ViewArguments())//TODO
} catch (error) {
// TODO Error logging
debugHistory.error(`${error}`);
}
return new CascadingRenderConfig([])//TODO
}
_emptyResultTextTemp = null;
get emptyResultText(){
......@@ -181,7 +198,7 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
_titleTemp = null;
get title() {
return this._titleTemp ?? this.cascadeProperty("title", String.constructor)?.nilIfBlank ?? this.cascadeProperty("titleIfNil") ?? ""//TODO
return this._titleTemp ?? this.cascadeProperty("title"/*, String.constructor*/) ?? ""//TODO
}
set title(newTitle) {
......@@ -200,19 +217,19 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
}
get filterText() {
return this.userState.get("filterText") ?? ""//TODO:?
return this.userState?.get("filterText") ?? ""//TODO:?
}
set filterText(newFilter) {
// Don't update the filter when it's already set
if (newFilter.length > 0 && this._titleTemp != null &&
this.userState.get("filterText") == newFilter) {
this.userState?.get("filterText") == newFilter) {
return
}
// Store the new value
if ((this.userState.get("filterText") ?? "") != newFilter) {
this.userState.set("filterText", newFilter)
if ((this.userState?.get("filterText") ?? "") != newFilter) {
this.userState?.set("filterText", newFilter)
}
// If this is a multi item result set
......@@ -229,7 +246,7 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
console.log("Warn: Filtering for single items not Implemented Yet!")
}
if (this.userState.get("filterText") == "") {
if (this.userState?.get("filterText") == "") {
this.title = ""
this.subtitle = ""
this.emptyResultText = ""
......@@ -243,22 +260,20 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
// Temporarily hide the subtitle
// subtitle = " " // TODO how to clear the subtitle ??
this.emptyResultText = `No results found using '${this.userState.get("filterText") ?? ""}'`
this.emptyResultText = `No results found using '${this.userState?.get("filterText") ?? ""}'`
}
}
get searchMatchText() {
return this.userState.get("searchMatchText") ?? ""
return this.userState?.get("searchMatchText") ?? ""
}
set searchMatchText(newValue) {
this.userState.set("searchMatchText", newValue)
this.userState?.set("searchMatchText", newValue)
}
constructor(sessionView,
cascadeStack
) {
super(cascadeStack, ViewArguments())
constructor(sessionView, cascadeStack) {
super(cascadeStack)
this.sessionView = sessionView
}
......@@ -311,8 +326,7 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
var result = source;
let expr = source;
if (expr instanceof Expression) {
let args = viewArguments ?? new ViewArguments()
result = expr.execute(args);
result = expr.execute(viewArguments);
}
let viewName = result;
if (typeof viewName == "string") {
......@@ -386,8 +400,11 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
if (inheritedView) {
let args = sessionView.viewArguments
let view = self.inherit(inheritedView, args, context, sessionView)
parse(view, domain)
if (view) {
parse(view, domain)
} else {
throw `Exception: Unable to inherit view from ${inheritedView}`
}
}
}
......@@ -407,7 +424,10 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
// Find views based on datatype
for (var domain of ["user", "session", "defaults"]) {
if (domain == "session") {
parse(sessionView.viewDefinition, domain)
let viewDef = sessionView.viewDefinition;
if (viewDef) {
parse(viewDef, domain)
}
continue
}
......@@ -420,7 +440,6 @@ class CascadingView extends Cascadable/*, ObservableObject*/ {//TODO
else if (domain != "user") {
// TODO Warn logging
//debugHistory.warn(`Could not find definition for '${needle}' in domain '${key}'`)
console.log(`Could not find definition for '${needle}' in domain '${domain}'`)
}
}
}
......
......@@ -5,9 +5,11 @@
//
class Colors {
import {Color} from "../../parsers/cvu-parser/CVUParser";
export class Colors {
byName(name) {
return new Color("#ff0000")
}
}
var globalColors = new Colors()
export var globalColors = new Colors()
......@@ -7,14 +7,14 @@
class CVUStoredDefinition extends DataItem {
constructor(args) {
constructor() {
super();
}
type = null
name = null
selector = null
definition = null
query = null
type
name
selector
definition
query
domain = "user"
get genericType (){return "CVUStoredDefinition"}
}
......@@ -6,6 +6,11 @@
// Potential solution: https://stackoverflow.com/questions/42746981/list-all-subclasses-of-one-class
import {Action} from "./Action";
import {Color} from "../../parsers/cvu-parser/CVUParser";
import {UIElement, UIElementFamily} from "./UIElement";
import {Cascadable} from "./Cascadable";
var allRenderers = null
class Renderers {
......@@ -15,15 +20,7 @@ class Renderers {
register(name, title, order, icon = "", view, renderConfigType, canDisplayResults) {
// var context = new FilterPanelRendererButton(context, name, order, title, icon, canDisplayResults)//TODO
/*this.all[name] = { context in FilterPanelRendererButton(context,
name: name,
order: order,
title: title,
icon: icon,
canDisplayResults: canDisplayResults
) }*/
this.all[name] = new FilterPanelRendererButton(context, name, order, title, icon, canDisplayResults) //TODO: confusing
this.allViews[name] = view
this.allConfigTypes[name] = renderConfigType
}
......@@ -55,7 +52,7 @@ class Renderers {
}
}
class FilterPanelRendererButton extends Action, ActionExec {
class FilterPanelRendererButton extends Action/*, ActionExec*/ {
defaults = {
activeColor: new Color("#6aa84f"),
activeBackgroundColor: new Color("#eee"),
......@@ -79,18 +76,18 @@ class FilterPanelRendererButton extends Action, ActionExec {
}*/
isActive() {
return this.context.cascadingView.activeRenderer == this.rendererName
return this.context.cascadingView?.activeRenderer == this.rendererName
}
exec(argumentsJs) {
this.context.cascadingView.activeRenderer = this.rendererName
this.context.scheduleUIUpdate(){ _ in true }//TODO // scheduleCascadingViewUpdate() // TODO why are userState not kept?
this.context.scheduleUIUpdate()/*{ _ in true }*///TODO // scheduleCascadingViewUpdate() // TODO why are userState not kept?
}
}
class RenderGroup {
options = {}
body = null
body: UIElement = null
constructor(dict) {
if (Array.isArray(dict["children"]) && dict["children"][0] instanceof UIElement) this.body = dict["children"][0]
......@@ -121,7 +118,6 @@ interface CascadingRendererDefaults {
class CascadingRenderConfig extends Cascadable {
constructor(cascadeStack = [], viewArguments) {
viewArguments = viewArguments || new ViewArguments();
super(cascadeStack, viewArguments)
}
......@@ -146,7 +142,7 @@ class CascadingRenderConfig extends Cascadable {
else if (group == "*" && this.cascadeProperty("*") == null) {
let list = this.cascadeProperty("children")
if (list) {
var dict = {children: list}
var dict = {"children": list}
let renderGroup = new RenderGroup(dict)
this.localCache[group] = renderGroup
return renderGroup
......@@ -167,7 +163,7 @@ class CascadingRenderConfig extends Cascadable {
render(item, group = "*", argumentsJs = null) {
function doRender(renderGroup) {
function doRender(renderGroup, item) {
let body = renderGroup.body
if (body) {
let s = this;//TODO
......@@ -177,15 +173,15 @@ class CascadingRenderConfig extends Cascadable {
return new UIElementView(body, item, argumentsJs ?? viewArguments)
}
return new UIElementView(new UIElement(), item)
return new UIElementView(new UIElement(UIElementFamily.Empty), item)
}
let renderGroup = this.getRenderGroup(group)
if (renderGroup) {
return doRender(renderGroup)
if (item && renderGroup) {
return doRender(renderGroup, item)
}
else {
return new UIElementView(new UIElement(), item)
return new UIElementView(new UIElement(UIElementFamily.Empty), item ?? new Item())
}
}
}
......@@ -6,33 +6,33 @@
// Copyright © 2020 memri. All rights reserved.
//
import {CVUParsedDatasourceDefinition} from "../../parsers/cvu-parser/CVUParsedDefinition";
import {UserState, ViewArguments} from "./UserState";
class SessionView extends DataItem {
get genericType (){return "SessionView"}
name = null
viewDefinition = null
userState = null
viewArguments = null
datasource = null // TODO refactor: fix cascading
session = null
name?: string
viewDefinition?: CVUStoredDefinition
userState?: UserState
viewArguments?: ViewArguments
datasource?: Datasource // TODO refactor: fix cascading
session?: Session
get computedTitle() {
// let value = this.name || this.title
// let rendererName = this.rendererName
// let query = this.datasource.query
// if (value) { return value }
// else if (rendererName) {
// return `A ${rendererName} showing: ${query ?? ""}`
// }
// else if (query) {
// return `Showing: ${query}`
// }
// if let value = self.name ?? self.title { return value }
// else if let rendererName = self.rendererName {
// return "A \(rendererName) showing: \(self.datasource?.query ?? "")"
// }
// else if let query = self.datasource?.query {
// return "Showing: \(query)"
// }
return "[No Name]"
}
constructor(values){
super(values);
constructor(){
super();
this.computedDescription = function () {//TODO
console.log("MAKE THIS DISSAPEAR")
......@@ -40,8 +40,8 @@ class SessionView extends DataItem {
}
}
mergeState(view) {
realmWriteIfAvailable(this.realm, function () {//TODO
mergeState(view: SessionView) {
/*realmWriteIfAvailable(this.realm, function () {//TODO
let us = view.userState
if (us) {
if (this.userState == null) { this.userState = new UserState() }
......@@ -52,7 +52,7 @@ class SessionView extends DataItem {
if (this.viewArguments == null) { this.viewArguments = new ViewArguments() }
Object.assign(this.viewArguments, args);//TODO
}
})
})*/
}
fromCVUDefinition(parsed = null, stored = null, viewArguments = null, userState = null, datasource = null) {
......@@ -70,16 +70,16 @@ class SessionView extends DataItem {
ds = new Datasource().fromCVUDefinition(src, viewArguments)//TODO
}
if (userState == null && parsed["userState"] instanceof UserState) {//TODO
us = Object.assign({}, parsed["userState"]);
us = parsed["userState"]?.clone();
}
if (viewArguments == null && parsed["viewArguments"] instanceof ViewArguments) {//TODO
args = Object.assign({}, parsed["viewArguments"]);
args = parsed["viewArguments"].clone();
}
var values = {//TODO
selector: parsed.selector || stored.selector || "[view]",
selector: parsed?.selector ?? stored?.selector ?? "[view]",
name: typeof parsed["name"] === 'string' ? parsed["name"] : stored?.name || "",
viewDefinition: stored || new CVUStoredDefinition({
viewDefinition: stored ?? new CVUStoredDefinition({
type: "view",
selector: parsed?.selector,
domain: parsed?.domain,
......
......@@ -20,11 +20,11 @@ import {DataItem, Item} from "../../model/DataItem";
import {CVUParsedDefinition} from "../../parsers/cvu-parser/CVUParsedDefinition";
export class UIElement /*extends CVUToString */{
type
type: UIElementFamily
children = []
properties = {} // TODO: ViewParserDefinitionContext
constructor(type, children, properties = {}) {
constructor(type, children?, properties = {}) {
//super()
this.type = type
this.children = children ?? this.children
......@@ -62,7 +62,7 @@ export class UIElement /*extends CVUToString */{
let list = x
if (Array.isArray(list)) {//TODO
for (var edge of list) {
let d = this.getItem(edge)
let d = edge.item()
if (d) {
result.push(d)
}
......@@ -77,12 +77,12 @@ export class UIElement /*extends CVUToString */{
}*/
} catch (error) {
// TODO: Refactor error handling
/*debugHistory.error(`Could note compute ${propName}\n
Arguments: [${viewArguments.asDict().keys.join(", ")}]\n
${expr.startInStringMode
? `Expression: ${expr.code}\n`
: `Expression: ${expr.code}\n`}
Error: ${error}`)*/
/*debugHistory.error("Could note compute \(propName)\n"
+ "Arguments: [\(viewArguments.asDict().keys.description)]\n"
+ (expr.startInStringMode
? "Expression: \"\(expr.code)\"\n"
: "Expression: \(expr.code)\n")
+ "Error: \(error)")*/
return null
}
}
......
......@@ -6,73 +6,84 @@
import {CVUSerializer} from "../../parsers/cvu-parser/CVUToString";
import {DataItem} from "../../model/DataItem";
import {DataItem, UUID} from "../../model/DataItem";
import {InMemoryObjectCache} from "../../model/InMemoryObjectCache";
class SchemaItem {
export class UserState /*extends Object, CVUToString*/ {
memriID = DataItem.generateUUID();
}//TODO: replace with normal class
export class UserState extends SchemaItem/*extends Object, CVUToString*/ {
state = ""
onFirstSave
cacheID = UUID();
/// Primary key used in the realm database of this Item
primaryKey() {
return "uid"
}
constructor(dict, onFirstSave) {//TODO
//super()
constructor(dict) {//TODO
super()
this.storeInCache(dict);
this.persist()
}
this.onFirstSave = onFirstSave
storeInCache(dict) {
new InMemoryObjectCache().set(`UserState:${this.uid && this.uid.value != undefined ? `${this.uid}` : this.cacheID}`, dict)
}
try { new InMemoryObjectCache().set(this.memriID, dict) }
catch {
// TODO: Refactor error reporting
}
getFromCache() {
return new InMemoryObjectCache().get(`UserState:${this.uid && this.uid.value != undefined ? `${this.uid}` : this.cacheID}`)
}
get(propName) {
let dict = this.asDict()
let lookup = dict[propName]
if (lookup && typeof lookup.isCVUObject === "function" && lookup["memriID"] != undefined) {
let x = this.getDataItem(lookup["type"] ?? "",
lookup["memriID"] ?? "")
return x
} else if (dict[propName] == undefined) {
if (dict[propName] == undefined) {
return null
}
return dict[propName]
return dict[propName];
}
set(propName, newValue, persist = true) {
let event = this.onFirstSave
if (event) {
event(this)
this.onFirstSave = null
var dict = this.asDict()
dict[propName] = newValue
try {
this.storeInCache(dict)
} catch {
/* TODO: ERROR HANDLIGNN */
//debugHistory.warn("Unable to store user state property \(propName)")
return
}
var x = this.asDict()
if (newValue instanceof DataItem) {
x[propName] = {type: newValue.genericType, memriID: newValue.memriID}
} else {
x[propName] = newValue
if (this.persist) {
this.scheduleWrite()
}
try { new InMemoryObjectCache().set(this.memriID, x) }
catch { /* TODO: ERROR HANDLIGNN */ }
if (persist) { this.scheduleWrite() }
}
transformToDict() {
if (this.state == "") { return {} }
let stored = Object.assign({},this.state) //TODO
let stored = this.unserialize(this.state) ?? {}
var dict = {}
for (let [key, value] of Object.entries(stored)) {
dict[key] = value.value
for (let [key, wrapper] of Object.entries(stored)) {
let lookup = wrapper.value;
if (typeof lookup.isCVUObject() == "function" && lookup["___"] != undefined) {
let itemType = lookup["_type"];
let uid = lookup["_uid"];
if (typeof itemType == "string" && typeof uid == "number") {
dict[key] = this.getItem(itemType, uid)
} else {
//debugHistory.warn("Could not expand item. View may not load as expected")
}
} else {
dict[key] = wrapper.value
}
}
new InMemoryObjectCache().set(this.memriID, dict)//TODO
this.storeInCache(dict);
return dict
}
......@@ -90,33 +101,37 @@ export class UserState /*extends Object, CVUToString*/ {
// Update UI
this.persist()
}*/
}*/ //TODO:
}
}
persist() {
if (realm == null) { return }//TODO
//if (realm == null) { return }//TODO
let x = new InMemoryObjectCache().get(this.memriID)
if (x && typeof x == "object") {
let x = this.getFromCache();
if (x) {
/*realmWriteIfAvailable(realm) {
try {
var values = {}
for (let [key, value] of Object.entries(x)) {
if (value instanceof AnyCodable) {
if (value instanceof Item) {
values[key] = {"_type": value.genericType,
"_uid": value.uid.value,
"___": true}
} else if let value = value as? AnyCodable {
values[key] = value
} else {
values[key] = new AnyCodable(value)
values[key] = AnyCodable(value)
}
}
let data = JSON.stringify(values)//TODO
this.state = String(data, encoding: .utf8) ?? ""//TODO
et data = try MemriJSONEncoder.encode(values)
self["state"] = String(data: data, encoding: .utf8) ?? ""
} catch {
debugHistory.error(`Could not persist state object: ${error}`)
}
}*/
}*/ //TODO
}
}
......@@ -133,24 +148,41 @@ export class UserState /*extends Object, CVUToString*/ {
}
asDict() {
var x
x = new InMemoryObjectCache().get(this.memriID)
try { if (x == null) { x = this.transformToDict() } } catch { return {} } // TODO: refactor: handle error
return x ?? {}
let cached = this.getFromCache();
if (cached) {
return cached
} else {
try {
return this.transformToDict()
} catch {
//debugHistory.error("Could not unserialize state object: \(error)")
return {}
} // TODO: refactor: handle error
}
}
merge(state) {
let dict = this.asDict().concat(state.asDict()) //TODO
new InMemoryObjectCache().set(this.memriID, dict) //TODO
}
clone() {
new UserState(this.asDict())//TODO
this.storeInCache(dict);
this.persist();
}
toCVUString(depth, tab) {
new CVUSerializer().dictToString(this.asDict(), depth, tab)
}
clone(viewArguments?: ViewArguments, values?, managed: boolean = true) {
var dict = viewArguments?.asDict() ?? {}
//let values = values;
if (values) {
dict = Object.assign({}, values, dict);
}
if (managed) { return new UserState(dict).fromDict(dict) }
else { return new UserState(dict) }
}
}
export var ViewArguments = UserState
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment