fixed switch between autobook and text

This commit is contained in:
zadam
2020-02-02 11:44:08 +01:00
parent 34150e7177
commit 27ab55d26a
22 changed files with 3311 additions and 805 deletions

View File

@@ -41,10 +41,31 @@ class NoteShort {
/**
* @param {TreeCache} treeCache
* @param {Object.<string, Object>} row
* @param {Branch[]} branches - all relevant branches, i.e. where this note is either child or parent
*/
constructor(treeCache, row, branches) {
constructor(treeCache, row) {
this.treeCache = treeCache;
/** @type {string[]} */
this.attributes = [];
/** @type {string[]} */
this.targetRelations = [];
/** @type {string[]} */
this.parents = [];
/** @type {string[]} */
this.children = [];
/** @type {Object.<string, string>} */
this.parentToBranch = {};
/** @type {Object.<string, string>} */
this.childToBranch = {};
this.update(row);
}
update(row) {
/** @param {string} */
this.noteId = row.noteId;
/** @param {string} */
@@ -59,37 +80,6 @@ class NoteShort {
this.mime = row.mime;
/** @param {boolean} */
this.isDeleted = row.isDeleted;
/** @param {boolean} */
this.archived = row.archived;
/** @param {string} */
this.cssClass = row.cssClass;
/** @param {string} */
this.iconClass = row.iconClass;
/** @type {string[]} */
this.parents = [];
/** @type {string[]} */
this.children = [];
/** @type {Object.<string, string>} */
this.parentToBranch = {};
/** @type {Object.<string, string>} */
this.childToBranch = {};
for (const branch of branches) {
if (this.noteId === branch.noteId) {
this.parents.push(branch.parentNoteId);
this.parentToBranch[branch.parentNoteId] = branch.branchId;
}
else if (this.noteId === branch.parentNoteId) {
this.children.push(branch.noteId);
this.childToBranch[branch.noteId] = branch.branchId;
}
else {
throw new Error(`Unknown branch ${branch.branchId} for note ${this.noteId}`);
}
}
}
addParent(parentNoteId, branchId) {
@@ -181,31 +171,76 @@ class NoteShort {
return await this.treeCache.getNotes(this.children);
}
/**
* @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter
* @returns {Attribute[]} all note's attributes, including inherited ones
*/
getOwnedAttributes(type, name) {
const attrs = this.attributes
.map(attributeId => this.treeCache.attributes[attributeId])
.filter(attr => !!attr);
return this.__filterAttrs(attrs, type, name)
}
/**
* @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter
* @returns {Promise<Attribute[]>} all note's attributes, including inherited ones
*/
async getAttributes(type, name) {
if (!this.__attributeCache) {
this.__attributeCache = (await server.get('notes/' + this.noteId + '/attributes'))
.map(attrRow => new Attribute(this.treeCache, attrRow));
const ownedAttributes = this.getOwnedAttributes();
const attrArrs = [
ownedAttributes
];
for (const templateAttr of ownedAttributes.filter(oa => oa.type === 'relation' && oa.name === 'template')) {
const templateNote = await this.treeCache.getNote(templateAttr.value);
if (templateNote) {
attrArrs.push(await templateNote.getAttributes());
}
}
if (this.noteId !== 'root') {
for (const parentNote of await this.getParentNotes()) {
attrArrs.push(await parentNote.getInheritableAttributes());
}
}
const attributes = attrArrs.flat();
return this.__filterAttrs(attributes, type, name);
}
__filterAttrs(attributes, type, name) {
if (type && name) {
return this.__attributeCache.filter(attr => attr.type === type && attr.name === name);
}
else if (type) {
return this.__attributeCache.filter(attr => attr.type === type);
}
else if (name) {
return this.__attributeCache.filter(attr => attr.name === name);
}
else {
return this.__attributeCache.slice();
return attributes.filter(attr => attr.type === type && attr.name === name);
} else if (type) {
return attributes.filter(attr => attr.type === type);
} else if (name) {
return attributes.filter(attr => attr.name === name);
} else {
return attributes;
}
}
async getInheritableAttributes() {
const attrs = await this.getAttributes();
return attrs.filter(attr => attr.isInheritable);
}
/**
* @param {string} [name] - label name to filter
* @returns {Attribute[]} all note's labels (attributes with type label), including inherited ones
*/
getOwnedLabels(name) {
return this.getOwnedAttributes(LABEL, name);
}
/**
* @param {string} [name] - label name to filter
* @returns {Promise<Attribute[]>} all note's labels (attributes with type label), including inherited ones
@@ -222,6 +257,14 @@ class NoteShort {
return await this.getAttributes(LABEL_DEFINITION, name);
}
/**
* @param {string} [name] - relation name to filter
* @returns {Attribute[]} all note's relations (attributes with type relation), including inherited ones
*/
getOwnedRelations(name) {
return this.getOwnedAttributes(RELATION, name);
}
/**
* @param {string} [name] - relation name to filter
* @returns {Promise<Attribute[]>} all note's relations (attributes with type relation), including inherited ones
@@ -247,15 +290,46 @@ class NoteShort {
return !!await this.getAttribute(type, name);
}
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {boolean} true if note has an attribute with given type and name (including inherited)
*/
hasOwnedAttribute(type, name) {
return !!this.getOwnedAttribute(type, name);
}
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {Attribute} attribute of given type and name. If there's more such attributes, first is returned. Returns null if there's no such attribute belonging to this note.
*/
getOwnedAttribute(type, name) {
const attributes = this.getOwnedAttributes(type, name);
return attributes.length > 0 ? attributes[0] : 0;
}
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {Promise<Attribute>} attribute of given type and name. If there's more such attributes, first is returned. Returns null if there's no such attribute belonging to this note.
*/
async getAttribute(type, name) {
const attributes = await this.getAttributes();
const attributes = await this.getAttributes(type, name);
return attributes.find(attr => attr.type === type && attr.name === name);
return attributes.length > 0 ? attributes[0] : 0;
}
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {string} attribute value of given type and name or null if no such attribute exists.
*/
getOwnedAttributeValue(type, name) {
const attr = this.getOwnedAttribute(type, name);
return attr ? attr.value : null;
}
/**
@@ -269,36 +343,72 @@ class NoteShort {
return attr ? attr.value : null;
}
/**
* @param {string} name - label name
* @returns {boolean} true if label exists (excluding inherited)
*/
hasOwnedLabel(name) { return this.hasOwnedAttribute(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Promise<boolean>} true if label exists (including inherited)
*/
async hasLabel(name) { return await this.hasAttribute(LABEL, name); }
/**
* @param {string} name - relation name
* @returns {boolean} true if relation exists (excluding inherited)
*/
hasOwnedRelation(name) { return this.hasOwnedAttribute(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Promise<boolean>} true if relation exists (including inherited)
*/
async hasRelation(name) { return await this.hasAttribute(RELATION, name); }
/**
* @param {string} name - label name
* @returns {Attribute} label if it exists, null otherwise
*/
getOwnedLabel(name) { return this.getOwnedAttribute(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Promise<Attribute>} label if it exists, null otherwise
*/
async getLabel(name) { return await this.getAttribute(LABEL, name); }
/**
* @param {string} name - relation name
* @returns {Attribute} relation if it exists, null otherwise
*/
getOwnedRelation(name) { return this.getOwnedAttribute(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Promise<Attribute>} relation if it exists, null otherwise
*/
async getRelation(name) { return await this.getAttribute(RELATION, name); }
/**
* @param {string} name - label name
* @returns {string} label value if label exists, null otherwise
*/
getOwnedLabelValue(name) { return this.getOwnedAttributeValue(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Promise<string>} label value if label exists, null otherwise
*/
async getLabelValue(name) { return await this.getAttributeValue(LABEL, name); }
/**
* @param {string} name - relation name
* @returns {string} relation value if relation exists, null otherwise
*/
getOwnedRelationValue(name) { return this.getOwnedAttributeValue(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Promise<string>} relation value if relation exists, null otherwise
@@ -334,18 +444,18 @@ class NoteShort {
* Clear note's attributes cache to force fresh reload for next attribute request.
* Cache is note instance scoped.
*/
invalidate__attributeCache() {
invalidateAttributeCache() {
this.__attributeCache = null;
}
/**
* Get relations which target this note
*
* @returns {Promise<Attribute[]>}
* @returns {Attribute[]}
*/
async getTargetRelations() {
return (await server.get('notes/' + this.noteId + '/target-relations'))
.map(attrRow => new Attribute(this.treeCache, attrRow));
getTargetRelations() {
return this.targetRelations
.map(attributeId => this.treeCache.attributes[attributeId]);
}
get toString() {
@@ -355,8 +465,6 @@ class NoteShort {
get dto() {
const dto = Object.assign({}, this);
delete dto.treeCache;
delete dto.archived;
delete dto.__attributeCache;
return dto;
}
@@ -372,7 +480,7 @@ export default NoteShort;</code></pre>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteFull.html">NoteFull</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3><a href="global.html">Global</a></h3>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">