From 558cd1cc2fb323e90d66e1b3602c000e2abe9dc0 Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Fri, 20 Nov 2020 20:05:39 +0100 Subject: [PATCH] improved js integration of api --- .idea/totpal.iml | 2 +- js_conversion.py | 6 +-- server/abstract_api.py | 3 +- server/models/models.py | 2 +- static/api.js | 91 ++++++++++++++++++++++++++++++++++------- static/models.js | 54 ++++++++++++------------ templates/base.html | 2 +- 7 files changed, 111 insertions(+), 49 deletions(-) diff --git a/.idea/totpal.iml b/.idea/totpal.iml index c617868..02d2170 100644 --- a/.idea/totpal.iml +++ b/.idea/totpal.iml @@ -7,7 +7,7 @@ - + diff --git a/js_conversion.py b/js_conversion.py index c932542..be42098 100644 --- a/js_conversion.py +++ b/js_conversion.py @@ -18,15 +18,15 @@ def get_set_attr(name, attr) -> str: if RelationshipDefinition in attr.__class__.__mro__: return f""" get_{name}() {{ - return this.json.{name} + return this._get_relation('{name}') }} link_{name}(ref) {{ - return this._link_property('{name}', ref) + return this._link_relation('{name}', ref) }} unlink_{name}(ref) {{ - return this._unlink_property('{name}', ref) + return this._unlink_relation('{name}', ref) }} """ else: diff --git a/server/abstract_api.py b/server/abstract_api.py index e411e7a..077be5d 100644 --- a/server/abstract_api.py +++ b/server/abstract_api.py @@ -153,7 +153,8 @@ def handle_object_api_request_id(cls: Type[StructuredNode], uid: str): obj = cls.nodes.get_or_none(uid=uid) if not obj: raise ApiError.not_found(cls, uid) - + obj.delete() + return '', 204 def handle_object_api_request_for_relation(cls: Type[StructuredNode], uid, relation, reluid): obj = cls.nodes.get_or_none(uid=uid) diff --git a/server/models/models.py b/server/models/models.py index b14bf0d..171a05f 100644 --- a/server/models/models.py +++ b/server/models/models.py @@ -1,5 +1,5 @@ from neomodel import StructuredNode, StringProperty, RelationshipTo, RelationshipFrom, \ - UniqueIdProperty, DateProperty, StructuredRel, RelationshipManager, + UniqueIdProperty, DateProperty, StructuredRel, RelationshipManager from neomodel.cardinality import ZeroOrOne, ZeroOrMore, One, OneOrMore diff --git a/static/api.js b/static/api.js index 07c43fd..58cfef4 100644 --- a/static/api.js +++ b/static/api.js @@ -1,5 +1,5 @@ class StructuredNode { - constructor(json) { + constructor(json = {}) { if (this.constructor === StructuredNode) { throw new TypeError('Cannot instantiate object of abstract type StructuredNode!') } @@ -10,13 +10,65 @@ class StructuredNode { this.hooks = [] this.deleted = false this.__name__ = this.constructor.name.toLowerCase() + // holds a list of all relations that are already loaded + + this._update_json() + } + + _update_json(json) { + let old_json = this.json; + this.__loaded__ = []; + if (json) { + this.json = json + } else { + old_json = {} + } + + Object.values(this.definition.rels).forEach(rel => { + // if we did not recieve an update for this relation, don't touch it! + // we might have gotten an update without relational information + if (this.json[rel.field] === undefined) { + return + } + + this.__loaded__.push(rel.field) + const type = StructuredNode.classes[rel.target].klass; + + if (rel.cardinality.endsWith('OrMore')) { + this.json[rel.field] = this.json[rel.field].map(x => new type(x)) + } else { + if (this.json[rel.field] === null) { + return + } + this.json[rel.field] = new type(this.json[rel.field]) + } + }) + + Object.values(this.definition.props).forEach(prop => { + // no update for this prop? don't put anything in. + if (this.json[prop.field] === undefined || this.json[prop.field] === null) + return + + this.json[prop.field] = PropertyConversion.deserialize(prop.type, this.json[prop.field]) + }) + + // keep fields from old_json which are not defined in the new json + Object.keys(old_json).forEach(key => { + if (this.json[key] === undefined) { + this.json = old_json[key]; + // keep loaded state + if (this.definition.rels[key]) { + this.__loaded__.push(key) + } + } + }) } check(name, new_value) { return true } - _link_property(name, elm) { + _link_relation(name, elm) { const relation = this.definition.rels[name] if (!relation) { @@ -34,7 +86,7 @@ class StructuredNode { // make results available immediately if (relation.cardinality.endsWith('OrMore')) { - if (!this.json[name].contains(elm)) { + if (!this.json[name].filter(e => e.json.uid === elm.json.uid)) { this.json[name].push(elm) } } else { @@ -42,30 +94,38 @@ class StructuredNode { } return Api.post(`/${this.__name__}/${this.json.uid}/${name}/${elm.json.uid}`).then(json => { - this.json = json + this._update_json(json) this.update('link') return this }) } } - _unlink_property(name, type, elm) { + _unlink_relation(name, type, elm) { return Api.delete(`/${this.__name__}/${this.json.uid}/${name}/${elm.json.uid}`).then(json => { - this.json = json + this._update_json(json) this.update('link') return this }) } - _set(name, new_val) { - if (this.check(name, new_val)) { - const def = this.definition.props[name] + _get_relation(name) { + if (this.__loaded__.indexOf(name) > -1) { + return Promise.resolve(this.json[name]) + } else { + return this.refresh().then(elm => elm.json[name]) + } + } - if (!def) { - throw new Error("No attribute " + name + " found!") - } + _set(name, new_val) { + const def = this.definition.props[name] + if (!def) + throw new Error("No attribute " + name + " found!") + if (this.check(def, new_val)) { + this.json[name] = new_val + this.changes[name] = PropertyConversion.serialize(def.type, new_val) } } @@ -76,14 +136,15 @@ class StructuredNode { if (this.json.uid) { return Api.put(`/${this.__name__}/${this.json.uid}`, this.changes).then(json => { - this.json = json + this._update_json(json) this.changes = {} this.update('save') return this }) } else { return Api.post('/' + this.__name__, this.json).then(json => { - this.json = json + debugger; + this._update_json(json) this.changes = {} this.update('created') return this @@ -104,7 +165,7 @@ class StructuredNode { refresh() { return Api.get(`/${this.__name__}/${this.json.uid}`).then(json => { - this.json = json + this._update_json(json) this.update('refresh') return this }) diff --git a/static/models.js b/static/models.js index 3d20b2c..4b03fb5 100644 --- a/static/models.js +++ b/static/models.js @@ -20,28 +20,28 @@ class Person extends StructuredNode { get_father() { - return this.json.father + return this._get_relation('father') } link_father(ref) { - return this._link_property('father', ref) + return this._link_relation('father', ref) } unlink_father(ref) { - return this._unlink_property('father', ref) + return this._unlink_relation('father', ref) } get_mother() { - return this.json.mother + return this._get_relation('mother') } link_mother(ref) { - return this._link_property('mother', ref) + return this._link_relation('mother', ref) } unlink_mother(ref) { - return this._unlink_property('mother', ref) + return this._unlink_relation('mother', ref) } @@ -82,15 +82,15 @@ class Person extends StructuredNode { get_places() { - return this.json.places + return this._get_relation('places') } link_places(ref) { - return this._link_property('places', ref) + return this._link_relation('places', ref) } unlink_places(ref) { - return this._unlink_property('places', ref) + return this._unlink_relation('places', ref) } } @@ -116,28 +116,28 @@ class Event extends StructuredNode { get_participants() { - return this.json.participants + return this._get_relation('participants') } link_participants(ref) { - return this._link_property('participants', ref) + return this._link_relation('participants', ref) } unlink_participants(ref) { - return this._unlink_property('participants', ref) + return this._unlink_relation('participants', ref) } get_places() { - return this.json.places + return this._get_relation('places') } link_places(ref) { - return this._link_property('places', ref) + return this._link_relation('places', ref) } unlink_places(ref) { - return this._unlink_property('places', ref) + return this._unlink_relation('places', ref) } @@ -160,15 +160,15 @@ class Event extends StructuredNode { get_related_events() { - return this.json.related_events + return this._get_relation('related_events') } link_related_events(ref) { - return this._link_property('related_events', ref) + return this._link_relation('related_events', ref) } unlink_related_events(ref) { - return this._unlink_property('related_events', ref) + return this._unlink_relation('related_events', ref) } } @@ -203,15 +203,15 @@ class Place extends StructuredNode { get_visitors() { - return this.json.visitors + return this._get_relation('visitors') } link_visitors(ref) { - return this._link_property('visitors', ref) + return this._link_relation('visitors', ref) } unlink_visitors(ref) { - return this._unlink_property('visitors', ref) + return this._unlink_relation('visitors', ref) } } @@ -237,28 +237,28 @@ class Image extends StructuredNode { get_pictured() { - return this.json.pictured + return this._get_relation('pictured') } link_pictured(ref) { - return this._link_property('pictured', ref) + return this._link_relation('pictured', ref) } unlink_pictured(ref) { - return this._unlink_property('pictured', ref) + return this._unlink_relation('pictured', ref) } get_place() { - return this.json.place + return this._get_relation('place') } link_place(ref) { - return this._link_property('place', ref) + return this._link_relation('place', ref) } unlink_place(ref) { - return this._unlink_property('place', ref) + return this._unlink_relation('place', ref) } diff --git a/templates/base.html b/templates/base.html index 942f059..de54ac8 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,7 +1,7 @@ - +