mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	* refactoring of repository layer to represent booleans as true/false instead of 1/0
* show list of inherited attributes, fixes #136 * properly work with inheritance
This commit is contained in:
		| @@ -13,6 +13,8 @@ class Attribute extends Entity { | |||||||
|     constructor(row) { |     constructor(row) { | ||||||
|         super(row); |         super(row); | ||||||
|  |  | ||||||
|  |         this.isInheritable = !!this.isInheritable; | ||||||
|  |  | ||||||
|         if (this.isDefinition()) { |         if (this.isDefinition()) { | ||||||
|             try { |             try { | ||||||
|                 this.value = JSON.parse(this.value); |                 this.value = JSON.parse(this.value); | ||||||
|   | |||||||
| @@ -7,6 +7,10 @@ class Entity { | |||||||
|         for (const key in row) { |         for (const key in row) { | ||||||
|             this[key] = row[key]; |             this[key] = row[key]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if ('isDeleted' in this) { | ||||||
|  |             this.isDeleted = !!this.isDeleted; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     beforeSaving() { |     beforeSaving() { | ||||||
|   | |||||||
| @@ -13,6 +13,8 @@ class Note extends Entity { | |||||||
|     constructor(row) { |     constructor(row) { | ||||||
|         super(row); |         super(row); | ||||||
|  |  | ||||||
|  |         this.isProtected = !!this.isProtected; | ||||||
|  |  | ||||||
|         // check if there's noteId, otherwise this is a new entity which wasn't encrypted yet |         // check if there's noteId, otherwise this is a new entity which wasn't encrypted yet | ||||||
|         if (this.isProtected && this.noteId) { |         if (this.isProtected && this.noteId) { | ||||||
|             protectedSessionService.decryptNote(this); |             protectedSessionService.decryptNote(this); | ||||||
|   | |||||||
| @@ -7,11 +7,13 @@ const repository = require('../services/repository'); | |||||||
| class NoteRevision extends Entity { | class NoteRevision extends Entity { | ||||||
|     static get tableName() { return "note_revisions"; } |     static get tableName() { return "note_revisions"; } | ||||||
|     static get primaryKeyName() { return "noteRevisionId"; } |     static get primaryKeyName() { return "noteRevisionId"; } | ||||||
|     static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "content", "dateModifiedFrom", "dateModifiedTo"]; } |     static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "content", "isProtected", "dateModifiedFrom", "dateModifiedTo"]; } | ||||||
|  |  | ||||||
|     constructor(row) { |     constructor(row) { | ||||||
|         super(row); |         super(row); | ||||||
|  |  | ||||||
|  |         this.isProtected = !!this.isProtected; | ||||||
|  |  | ||||||
|         if (this.isProtected) { |         if (this.isProtected) { | ||||||
|             protectedSessionService.decryptNoteRevision(this); |             protectedSessionService.decryptNoteRevision(this); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -8,6 +8,12 @@ class Option extends Entity { | |||||||
|     static get primaryKeyName() { return "name"; } |     static get primaryKeyName() { return "name"; } | ||||||
|     static get hashedProperties() { return ["name", "value"]; } |     static get hashedProperties() { return ["name", "value"]; } | ||||||
|  |  | ||||||
|  |     constructor(row) { | ||||||
|  |         super(row); | ||||||
|  |  | ||||||
|  |         this.isSynced = !!this.isSynced; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     beforeSaving() { |     beforeSaving() { | ||||||
|         this.dateModified = dateUtils.nowDate(); |         this.dateModified = dateUtils.nowDate(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,18 +3,18 @@ import server from '../services/server.js'; | |||||||
| import infoService from "../services/info.js"; | import infoService from "../services/info.js"; | ||||||
| import treeUtils from "../services/tree_utils.js"; | import treeUtils from "../services/tree_utils.js"; | ||||||
| import linkService from "../services/link.js"; | import linkService from "../services/link.js"; | ||||||
| import noteAutocompleteService from "../services/note_autocomplete.js"; |  | ||||||
|  |  | ||||||
| const $dialog = $("#attributes-dialog"); | const $dialog = $("#attributes-dialog"); | ||||||
| const $saveAttributesButton = $("#save-attributes-button"); | const $saveAttributesButton = $("#save-attributes-button"); | ||||||
| const $attributesBody = $('#attributes-table tbody'); | const $ownedAttributesBody = $('#owned-attributes-table tbody'); | ||||||
|  |  | ||||||
| const attributesModel = new AttributesModel(); | const attributesModel = new AttributesModel(); | ||||||
|  |  | ||||||
| function AttributesModel() { | function AttributesModel() { | ||||||
|     const self = this; |     const self = this; | ||||||
|  |  | ||||||
|     this.attributes = ko.observableArray(); |     this.ownedAttributes = ko.observableArray(); | ||||||
|  |     this.inheritedAttributes = ko.observableArray(); | ||||||
|  |  | ||||||
|     this.availableTypes = [ |     this.availableTypes = [ | ||||||
|         { text: "Label", value: "label" }, |         { text: "Label", value: "label" }, | ||||||
| @@ -47,8 +47,8 @@ function AttributesModel() { | |||||||
|         let position = 0; |         let position = 0; | ||||||
|  |  | ||||||
|         // we need to update positions by searching in the DOM, because order of the |         // we need to update positions by searching in the DOM, because order of the | ||||||
|         // attributes in the viewmodel (self.attributes()) stays the same |         // attributes in the viewmodel (self.ownedAttributes()) stays the same | ||||||
|         $attributesBody.find('input[name="position"]').each(function() { |         $ownedAttributesBody.find('input[name="position"]').each(function() { | ||||||
|             const attribute = self.getTargetAttribute(this); |             const attribute = self.getTargetAttribute(this); | ||||||
|  |  | ||||||
|             attribute().position = position++; |             attribute().position = position++; | ||||||
| @@ -56,7 +56,9 @@ function AttributesModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     async function showAttributes(attributes) { |     async function showAttributes(attributes) { | ||||||
|         for (const attr of attributes) { |         const ownedAttributes = attributes.filter(attr => attr.isOwned); | ||||||
|  |  | ||||||
|  |         for (const attr of ownedAttributes) { | ||||||
|             attr.labelValue = attr.type === 'label' ? attr.value : ''; |             attr.labelValue = attr.type === 'label' ? attr.value : ''; | ||||||
|             attr.relationValue = attr.type === 'relation' ? (await treeUtils.getNoteTitle(attr.value) + " (" + attr.value + ")") : ''; |             attr.relationValue = attr.type === 'relation' ? (await treeUtils.getNoteTitle(attr.value) + " (" + attr.value + ")") : ''; | ||||||
|             attr.labelDefinition = (attr.type === 'label-definition' && attr.value) ? attr.value : { |             attr.labelDefinition = (attr.type === 'label-definition' && attr.value) ? attr.value : { | ||||||
| @@ -72,9 +74,13 @@ function AttributesModel() { | |||||||
|             delete attr.value; |             delete attr.value; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         self.attributes(attributes.map(ko.observable)); |         self.ownedAttributes(ownedAttributes.map(ko.observable)); | ||||||
|  |  | ||||||
|         addLastEmptyRow(); |         addLastEmptyRow(); | ||||||
|  |  | ||||||
|  |         const inheritedAttributes = attributes.filter(attr => !attr.isOwned); | ||||||
|  |  | ||||||
|  |         self.inheritedAttributes(inheritedAttributes); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     this.loadAttributes = async function() { |     this.loadAttributes = async function() { | ||||||
| @@ -87,9 +93,9 @@ function AttributesModel() { | |||||||
|         // attribute might not be rendered immediatelly so could not focus |         // attribute might not be rendered immediatelly so could not focus | ||||||
|         setTimeout(() => $(".attribute-name:last").focus(), 100); |         setTimeout(() => $(".attribute-name:last").focus(), 100); | ||||||
|  |  | ||||||
|         $attributesBody.sortable({ |         $ownedAttributesBody.sortable({ | ||||||
|             handle: '.handle', |             handle: '.handle', | ||||||
|             containment: $attributesBody, |             containment: $ownedAttributesBody, | ||||||
|             update: this.updateAttributePositions |             update: this.updateAttributePositions | ||||||
|         }); |         }); | ||||||
|     }; |     }; | ||||||
| @@ -99,7 +105,7 @@ function AttributesModel() { | |||||||
|         const attributeData = attribute(); |         const attributeData = attribute(); | ||||||
|  |  | ||||||
|         if (attributeData) { |         if (attributeData) { | ||||||
|             attributeData.isDeleted = 1; |             attributeData.isDeleted = true; | ||||||
|  |  | ||||||
|             attribute(attributeData); |             attribute(attributeData); | ||||||
|  |  | ||||||
| @@ -108,7 +114,7 @@ function AttributesModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     function isValid() { |     function isValid() { | ||||||
|         for (let attributes = self.attributes(), i = 0; i < attributes.length; i++) { |         for (let attributes = self.ownedAttributes(), i = 0; i < attributes.length; i++) { | ||||||
|             if (self.isEmptyName(i)) { |             if (self.isEmptyName(i)) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
| @@ -132,7 +138,7 @@ function AttributesModel() { | |||||||
|  |  | ||||||
|         const noteId = noteDetailService.getCurrentNoteId(); |         const noteId = noteDetailService.getCurrentNoteId(); | ||||||
|  |  | ||||||
|         const attributesToSave = self.attributes() |         const attributesToSave = self.ownedAttributes() | ||||||
|             .map(attribute => attribute()) |             .map(attribute => attribute()) | ||||||
|             .filter(attribute => attribute.attributeId !== "" || attribute.name !== ""); |             .filter(attribute => attribute.attributeId !== "" || attribute.name !== ""); | ||||||
|  |  | ||||||
| @@ -166,18 +172,18 @@ function AttributesModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     function addLastEmptyRow() { |     function addLastEmptyRow() { | ||||||
|         const attributes = self.attributes().filter(attr => attr().isDeleted === 0); |         const attributes = self.ownedAttributes().filter(attr => !attr().isDeleted); | ||||||
|         const last = attributes.length === 0 ? null : attributes[attributes.length - 1](); |         const last = attributes.length === 0 ? null : attributes[attributes.length - 1](); | ||||||
|  |  | ||||||
|         if (!last || last.name.trim() !== "") { |         if (!last || last.name.trim() !== "") { | ||||||
|             self.attributes.push(ko.observable({ |             self.ownedAttributes.push(ko.observable({ | ||||||
|                 attributeId: '', |                 attributeId: '', | ||||||
|                 type: 'label', |                 type: 'label', | ||||||
|                 name: '', |                 name: '', | ||||||
|                 labelValue: '', |                 labelValue: '', | ||||||
|                 relationValue: '', |                 relationValue: '', | ||||||
|                 isInheritable: false, |                 isInheritable: false, | ||||||
|                 isDeleted: 0, |                 isDeleted: false, | ||||||
|                 position: 0, |                 position: 0, | ||||||
|                 labelDefinition: { |                 labelDefinition: { | ||||||
|                     labelType: "text", |                     labelType: "text", | ||||||
| @@ -201,13 +207,13 @@ function AttributesModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     this.isNotUnique = function(index) { |     this.isNotUnique = function(index) { | ||||||
|         const cur = self.attributes()[index](); |         const cur = self.ownedAttributes()[index](); | ||||||
|  |  | ||||||
|         if (cur.name.trim() === "") { |         if (cur.name.trim() === "") { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (let attributes = self.attributes(), i = 0; i < attributes.length; i++) { |         for (let attributes = self.ownedAttributes(), i = 0; i < attributes.length; i++) { | ||||||
|             const attribute = attributes[i](); |             const attribute = attributes[i](); | ||||||
|  |  | ||||||
|             if (index !== i && cur.name === attribute.name && cur.type === attribute.type) { |             if (index !== i && cur.name === attribute.name && cur.type === attribute.type) { | ||||||
| @@ -219,7 +225,7 @@ function AttributesModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     this.isEmptyName = function(index) { |     this.isEmptyName = function(index) { | ||||||
|         const cur = self.attributes()[index](); |         const cur = self.ownedAttributes()[index](); | ||||||
|  |  | ||||||
|         return cur.name.trim() === "" && (cur.attributeId !== "" || cur.labelValue !== "" || cur.relationValue); |         return cur.name.trim() === "" && (cur.attributeId !== "" || cur.labelValue !== "" || cur.relationValue); | ||||||
|     }; |     }; | ||||||
| @@ -228,7 +234,7 @@ function AttributesModel() { | |||||||
|         const context = ko.contextFor(target); |         const context = ko.contextFor(target); | ||||||
|         const index = context.$index(); |         const index = context.$index(); | ||||||
|  |  | ||||||
|         return self.attributes()[index]; |         return self.ownedAttributes()[index]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ function LabelsModel() { | |||||||
|         const labelData = label(); |         const labelData = label(); | ||||||
|  |  | ||||||
|         if (labelData) { |         if (labelData) { | ||||||
|             labelData.isDeleted = 1; |             labelData.isDeleted = true; | ||||||
|  |  | ||||||
|             label(labelData); |             label(labelData); | ||||||
|  |  | ||||||
| @@ -101,7 +101,7 @@ function LabelsModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     function addLastEmptyRow() { |     function addLastEmptyRow() { | ||||||
|         const labels = self.labels().filter(attr => attr().isDeleted === 0); |         const labels = self.labels().filter(attr => !attr().isDeleted); | ||||||
|         const last = labels.length === 0 ? null : labels[labels.length - 1](); |         const last = labels.length === 0 ? null : labels[labels.length - 1](); | ||||||
|  |  | ||||||
|         if (!last || last.name.trim() !== "" || last.value !== "") { |         if (!last || last.name.trim() !== "" || last.value !== "") { | ||||||
| @@ -109,7 +109,7 @@ function LabelsModel() { | |||||||
|                 labelId: '', |                 labelId: '', | ||||||
|                 name: '', |                 name: '', | ||||||
|                 value: '', |                 value: '', | ||||||
|                 isDeleted: 0, |                 isDeleted: false, | ||||||
|                 position: 0 |                 position: 0 | ||||||
|             })); |             })); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ function RelationsModel() { | |||||||
|         const relationData = relation(); |         const relationData = relation(); | ||||||
|  |  | ||||||
|         if (relationData) { |         if (relationData) { | ||||||
|             relationData.isDeleted = 1; |             relationData.isDeleted = true; | ||||||
|  |  | ||||||
|             relation(relationData); |             relation(relationData); | ||||||
|  |  | ||||||
| @@ -115,7 +115,7 @@ function RelationsModel() { | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     function addLastEmptyRow() { |     function addLastEmptyRow() { | ||||||
|         const relations = self.relations().filter(attr => attr().isDeleted === 0); |         const relations = self.relations().filter(attr => !attr().isDeleted); | ||||||
|         const last = relations.length === 0 ? null : relations[relations.length - 1](); |         const last = relations.length === 0 ? null : relations[relations.length - 1](); | ||||||
|  |  | ||||||
|         if (!last || last.name.trim() !== "" || last.targetNoteId !== "") { |         if (!last || last.name.trim() !== "" || last.targetNoteId !== "") { | ||||||
| @@ -123,8 +123,8 @@ function RelationsModel() { | |||||||
|                 relationId: '', |                 relationId: '', | ||||||
|                 name: '', |                 name: '', | ||||||
|                 targetNoteId: '', |                 targetNoteId: '', | ||||||
|                 isInheritable: 0, |                 isInheritable: false, | ||||||
|                 isDeleted: 0, |                 isDeleted: false, | ||||||
|                 position: 0 |                 position: 0 | ||||||
|             })); |             })); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ function getNotePathFromLabel(label) { | |||||||
|     return null; |     return null; | ||||||
| } | } | ||||||
|  |  | ||||||
| async function createNoteLink(notePath, noteTitle) { | async function createNoteLink(notePath, noteTitle = null) { | ||||||
|     if (!noteTitle) { |     if (!noteTitle) { | ||||||
|         const noteId = treeUtils.getNoteIdFromNotePath(notePath); |         const noteId = treeUtils.getNoteIdFromNotePath(notePath); | ||||||
|  |  | ||||||
| @@ -90,6 +90,18 @@ function addTextToEditor(text) { | |||||||
|     doc.enqueueChanges(() => editor.data.insertText(text), doc.selection); |     doc.enqueueChanges(() => editor.data.insertText(text), doc.selection); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | ko.bindingHandlers.noteLink = { | ||||||
|  |     init: async function(element, valueAccessor, allBindings, viewModel, bindingContext) { | ||||||
|  |         const noteId = ko.unwrap(valueAccessor()); | ||||||
|  |  | ||||||
|  |         if (noteId) { | ||||||
|  |             const link = await createNoteLink(noteId); | ||||||
|  |  | ||||||
|  |             $(element).append(link); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
| // when click on link popup, in case of internal link, just go the the referenced note instead of default behavior | // when click on link popup, in case of internal link, just go the the referenced note instead of default behavior | ||||||
| // of opening the link in new window/tab | // of opening the link in new window/tab | ||||||
| $(document).on('click', "a[action='note']", goToLink); | $(document).on('click', "a[action='note']", goToLink); | ||||||
|   | |||||||
| @@ -228,6 +228,7 @@ async function showChildrenOverview(hideChildrenOverview) { | |||||||
|  |  | ||||||
| async function loadAttributes() { | async function loadAttributes() { | ||||||
|     $promotedAttributesContainer.empty(); |     $promotedAttributesContainer.empty(); | ||||||
|  |     $attributeList.hide(); | ||||||
|  |  | ||||||
|     const noteId = getCurrentNoteId(); |     const noteId = getCurrentNoteId(); | ||||||
|  |  | ||||||
| @@ -244,7 +245,7 @@ async function loadAttributes() { | |||||||
|         const $labelCell = $("<th>").append(valueAttr.name); |         const $labelCell = $("<th>").append(valueAttr.name); | ||||||
|         const $input = $("<input>") |         const $input = $("<input>") | ||||||
|             .prop("id", inputId) |             .prop("id", inputId) | ||||||
|             .prop("attribute-id", valueAttr.attributeId) |             .prop("attribute-id", valueAttr.isOwned ? valueAttr.attributeId : '') // if not owned, we'll force creation of a new attribute instead of updating the inherited one | ||||||
|             .prop("attribute-type", valueAttr.type) |             .prop("attribute-type", valueAttr.type) | ||||||
|             .prop("attribute-name", valueAttr.name) |             .prop("attribute-name", valueAttr.name) | ||||||
|             .prop("value", valueAttr.value) |             .prop("value", valueAttr.value) | ||||||
| @@ -409,9 +410,6 @@ async function loadAttributes() { | |||||||
|  |  | ||||||
|             $attributeList.show(); |             $attributeList.show(); | ||||||
|         } |         } | ||||||
|         else { |  | ||||||
|             $attributeList.hide(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import linkService from "./link.js"; | |||||||
|  |  | ||||||
| function setupTooltip() { | function setupTooltip() { | ||||||
|     $(document).tooltip({ |     $(document).tooltip({ | ||||||
|         items: "#note-detail-wrapper a", |         items: "body a", | ||||||
|         content: function (callback) { |         content: function (callback) { | ||||||
|             let notePath = linkService.getNotePathFromLink($(this).attr("href")); |             let notePath = linkService.getNotePathFromLink($(this).attr("href")); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -51,6 +51,10 @@ async function getEffectiveNoteAttributes(req) { | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     for (const attr of filteredAttributes) { | ||||||
|  |         attr.isOwned = attr.noteId === noteId; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return filteredAttributes; |     return filteredAttributes; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -70,7 +74,7 @@ async function updateNoteAttribute(req) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (attribute.noteId !== noteId) { |     if (attribute.noteId !== noteId) { | ||||||
|         throw new Error(`Attribute ${body.attributeId} does not belong to note ${noteId}`); |         return [400, `Attribute ${body.attributeId} is not owned by ${noteId}`]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     attribute.value = body.value; |     attribute.value = body.value; | ||||||
| @@ -83,12 +87,17 @@ async function updateNoteAttribute(req) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function deleteNoteAttribute(req) { | async function deleteNoteAttribute(req) { | ||||||
|  |     const noteId = req.params.noteId; | ||||||
|     const attributeId = req.params.attributeId; |     const attributeId = req.params.attributeId; | ||||||
|  |  | ||||||
|     const attribute = await repository.getAttribute(attributeId); |     const attribute = await repository.getAttribute(attributeId); | ||||||
|  |  | ||||||
|     if (attribute) { |     if (attribute) { | ||||||
|         attribute.isDeleted = 1; |         if (attribute.noteId !== noteId) { | ||||||
|  |             return [400, `Attribute ${attributeId} is not owned by ${noteId}`]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         attribute.isDeleted = true; | ||||||
|         await attribute.save(); |         await attribute.save(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -102,6 +111,10 @@ async function updateNoteAttributes(req) { | |||||||
|  |  | ||||||
|         if (attribute.attributeId) { |         if (attribute.attributeId) { | ||||||
|             attributeEntity = await repository.getAttribute(attribute.attributeId); |             attributeEntity = await repository.getAttribute(attribute.attributeId); | ||||||
|  |  | ||||||
|  |             if (attributeEntity.noteId !== noteId) { | ||||||
|  |                 return [400, `Attribute ${attributeEntity.noteId} is not owned by ${noteId}`]; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             // if it was "created" and then immediatelly deleted, we just don't create it at all |             // if it was "created" and then immediatelly deleted, we just don't create it at all | ||||||
| @@ -120,12 +133,10 @@ async function updateNoteAttributes(req) { | |||||||
|         attributeEntity.isInheritable = attribute.isInheritable; |         attributeEntity.isInheritable = attribute.isInheritable; | ||||||
|         attributeEntity.isDeleted = attribute.isDeleted; |         attributeEntity.isDeleted = attribute.isDeleted; | ||||||
|  |  | ||||||
|         console.log("ATTR: ", attributeEntity); |  | ||||||
|  |  | ||||||
|         await attributeEntity.save(); |         await attributeEntity.save(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return await repository.getEntities("SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]); |     return await getEffectiveNoteAttributes(req); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function getAttributeNames(req) { | async function getAttributeNames(req) { | ||||||
|   | |||||||
| @@ -192,7 +192,7 @@ async function saveNoteRevision(note) { | |||||||
|             content: note.content, |             content: note.content, | ||||||
|             type: note.type, |             type: note.type, | ||||||
|             mime: note.mime, |             mime: note.mime, | ||||||
|             isProtected: 0, // will be fixed in the protectNoteRevisions() call |             isProtected: false, // will be fixed in the protectNoteRevisions() call | ||||||
|             dateModifiedFrom: note.dateModified, |             dateModifiedFrom: note.dateModified, | ||||||
|             dateModifiedTo: dateUtils.nowDate() |             dateModifiedTo: dateUtils.nowDate() | ||||||
|         }).save(); |         }).save(); | ||||||
| @@ -226,7 +226,7 @@ async function updateNote(noteId, noteUpdates) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function deleteNote(branch) { | async function deleteNote(branch) { | ||||||
|     if (!branch || branch.isDeleted === 1) { |     if (!branch || branch.isDeleted) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -566,7 +566,7 @@ | |||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <div style="height: 97%; overflow: auto"> |         <div style="height: 97%; overflow: auto"> | ||||||
|           <table id="attributes-table" class="table"> |           <table id="owned-attributes-table" class="table"> | ||||||
|             <thead> |             <thead> | ||||||
|             <tr> |             <tr> | ||||||
|               <th></th> |               <th></th> | ||||||
| @@ -577,8 +577,8 @@ | |||||||
|               <th></th> |               <th></th> | ||||||
|             </tr> |             </tr> | ||||||
|             </thead> |             </thead> | ||||||
|             <tbody data-bind="foreach: attributes"> |             <tbody data-bind="foreach: ownedAttributes"> | ||||||
|               <tr data-bind="if: isDeleted == 0"> |               <tr data-bind="if: !isDeleted"> | ||||||
|                 <td class="handle"> |                 <td class="handle"> | ||||||
|                   <span class="glyphicon glyphicon-resize-vertical"></span> |                   <span class="glyphicon glyphicon-resize-vertical"></span> | ||||||
|                   <input type="hidden" name="position" data-bind="value: position"/> |                   <input type="hidden" name="position" data-bind="value: position"/> | ||||||
| @@ -624,6 +624,45 @@ | |||||||
|               </tr> |               </tr> | ||||||
|             </tbody> |             </tbody> | ||||||
|           </table> |           </table> | ||||||
|  |  | ||||||
|  |           <div data-bind="if: inheritedAttributes().length > 0"> | ||||||
|  |             <h4>Inherited attributes</h4> | ||||||
|  |  | ||||||
|  |             <table class="table"> | ||||||
|  |               <thead> | ||||||
|  |                 <tr> | ||||||
|  |                   <th>Type</th> | ||||||
|  |                   <th>Name</th> | ||||||
|  |                   <th>Value</th> | ||||||
|  |                   <th>Owning note</th> | ||||||
|  |                 </tr> | ||||||
|  |               </thead> | ||||||
|  |               <tbody data-bind="foreach: inheritedAttributes"> | ||||||
|  |                 <tr> | ||||||
|  |                   <td data-bind="text: type"></td> | ||||||
|  |                   <td data-bind="text: name"></td> | ||||||
|  |                   <td> | ||||||
|  |                     <span data-bind="if: type == 'label'"> | ||||||
|  |                       <span data-bind="text: value"></span> | ||||||
|  |                     </span> | ||||||
|  |                     <span data-bind="if: type == 'relation'"> | ||||||
|  |                       <span data-bind="noteLink: value"></span> | ||||||
|  |                     </span> | ||||||
|  |                     <span data-bind="if: type == 'label-definition'"> | ||||||
|  |                       <span data-bind="text: value.labelType"></span> | ||||||
|  |                       <span data-bind="text: value.multiplicityType"></span> | ||||||
|  |                       promoted: <span data-bind="text: value.isPromoted"></span> | ||||||
|  |                     </span> | ||||||
|  |                     <span data-bind="if: type == 'relation-definition'"> | ||||||
|  |                       <span data-bind="text: value.multiplicityType"></span> | ||||||
|  |                       promoted: <span data-bind="text: value.isPromoted"></span> | ||||||
|  |                     </span> | ||||||
|  |                     <td data-bind="noteLink: noteId"></td> | ||||||
|  |                   </tr> | ||||||
|  |                 </tr> | ||||||
|  |               </tbody> | ||||||
|  |             </table> | ||||||
|  |           </div> | ||||||
|         </div> |         </div> | ||||||
|       </form> |       </form> | ||||||
|     </div> |     </div> | ||||||
| @@ -646,7 +685,7 @@ | |||||||
|             </tr> |             </tr> | ||||||
|           </thead> |           </thead> | ||||||
|           <tbody data-bind="foreach: labels"> |           <tbody data-bind="foreach: labels"> | ||||||
|             <tr data-bind="if: isDeleted == 0"> |             <tr data-bind="if: !isDeleted"> | ||||||
|               <td class="handle"> |               <td class="handle"> | ||||||
|                 <span class="glyphicon glyphicon-resize-vertical"></span> |                 <span class="glyphicon glyphicon-resize-vertical"></span> | ||||||
|                 <input type="hidden" name="position" data-bind="value: position"/> |                 <input type="hidden" name="position" data-bind="value: position"/> | ||||||
| @@ -691,7 +730,7 @@ | |||||||
|             </tr> |             </tr> | ||||||
|             </thead> |             </thead> | ||||||
|             <tbody data-bind="foreach: relations"> |             <tbody data-bind="foreach: relations"> | ||||||
|             <tr data-bind="if: isDeleted == 0"> |             <tr data-bind="if: !isDeleted"> | ||||||
|               <td class="handle"> |               <td class="handle"> | ||||||
|                 <span class="glyphicon glyphicon-resize-vertical"></span> |                 <span class="glyphicon glyphicon-resize-vertical"></span> | ||||||
|                 <input type="hidden" name="position" data-bind="value: position"/> |                 <input type="hidden" name="position" data-bind="value: position"/> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user