mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +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:
parent
d3e44b37e9
commit
5f36856571
@ -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"/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user