mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
Merge branch 'stable'
# Conflicts: # src/services/build.js
This commit is contained in:
commit
dba0c9f373
@ -96,7 +96,7 @@ class BAttribute extends AbstractBeccaEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.type === 'relation' && !(this.value in this.becca.notes)) {
|
if (this.type === 'relation' && !(this.value in this.becca.notes)) {
|
||||||
throw new Error(`Cannot save relation '${this.name}' of note '${this.noteId}' since it target not existing note '${this.value}'.`);
|
throw new Error(`Cannot save relation '${this.name}' of note '${this.noteId}' since it targets not existing note '${this.value}'.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ class BNote extends AbstractBeccaEntity {
|
|||||||
* @private */
|
* @private */
|
||||||
this.parents = [];
|
this.parents = [];
|
||||||
/** @type {BNote[]}
|
/** @type {BNote[]}
|
||||||
* @private*/
|
* @private */
|
||||||
this.children = [];
|
this.children = [];
|
||||||
/** @type {BAttribute[]}
|
/** @type {BAttribute[]}
|
||||||
* @private */
|
* @private */
|
||||||
@ -107,11 +107,11 @@ class BNote extends AbstractBeccaEntity {
|
|||||||
* @private */
|
* @private */
|
||||||
this.__attributeCache = null;
|
this.__attributeCache = null;
|
||||||
/** @type {BAttribute[]|null}
|
/** @type {BAttribute[]|null}
|
||||||
* @private*/
|
* @private */
|
||||||
this.inheritableAttributeCache = null;
|
this.inheritableAttributeCache = null;
|
||||||
|
|
||||||
/** @type {BAttribute[]}
|
/** @type {BAttribute[]}
|
||||||
* @private*/
|
* @private */
|
||||||
this.targetRelations = [];
|
this.targetRelations = [];
|
||||||
|
|
||||||
this.becca.addNote(this.noteId, this);
|
this.becca.addNote(this.noteId, this);
|
||||||
@ -532,6 +532,20 @@ class BNote extends AbstractBeccaEntity {
|
|||||||
*/
|
*/
|
||||||
hasLabel(name, value) { return this.hasAttribute(LABEL, name, value); }
|
hasLabel(name, value) { return this.hasAttribute(LABEL, name, value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name - label name
|
||||||
|
* @returns {boolean} true if label exists (including inherited) and does not have "false" value.
|
||||||
|
*/
|
||||||
|
isLabelTruthy(name) {
|
||||||
|
const label = this.getLabel(name);
|
||||||
|
|
||||||
|
if (!label) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return label && label.value !== 'false';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} name - label name
|
* @param {string} name - label name
|
||||||
* @param {string} [value] - label value
|
* @param {string} [value] - label value
|
||||||
|
@ -595,6 +595,20 @@ class FNote {
|
|||||||
*/
|
*/
|
||||||
hasLabel(name) { return this.hasAttribute(LABEL, name); }
|
hasLabel(name) { return this.hasAttribute(LABEL, name); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name - label name
|
||||||
|
* @returns {boolean} true if label exists (including inherited) and does not have "false" value.
|
||||||
|
*/
|
||||||
|
isLabelTruthy(name) {
|
||||||
|
const label = this.getLabel(name);
|
||||||
|
|
||||||
|
if (!label) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return label && label.value !== 'false';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} name - relation name
|
* @param {string} name - relation name
|
||||||
* @returns {boolean} true if relation exists (excluding inherited)
|
* @returns {boolean} true if relation exists (excluding inherited)
|
||||||
|
@ -128,6 +128,10 @@ export default class DesktopLayout {
|
|||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
new RibbonContainer()
|
new RibbonContainer()
|
||||||
|
// order of the widgets matter. Some of these want to "activate" themselves
|
||||||
|
// when visible, when this happens to multiple of them, the first one "wins".
|
||||||
|
// promoted attributes should always win.
|
||||||
|
.ribbon(new PromotedAttributesWidget())
|
||||||
.ribbon(new ScriptExecutorWidget())
|
.ribbon(new ScriptExecutorWidget())
|
||||||
.ribbon(new SearchDefinitionWidget())
|
.ribbon(new SearchDefinitionWidget())
|
||||||
.ribbon(new EditedNotesWidget())
|
.ribbon(new EditedNotesWidget())
|
||||||
@ -135,7 +139,6 @@ export default class DesktopLayout {
|
|||||||
.ribbon(new NotePropertiesWidget())
|
.ribbon(new NotePropertiesWidget())
|
||||||
.ribbon(new FilePropertiesWidget())
|
.ribbon(new FilePropertiesWidget())
|
||||||
.ribbon(new ImagePropertiesWidget())
|
.ribbon(new ImagePropertiesWidget())
|
||||||
.ribbon(new PromotedAttributesWidget())
|
|
||||||
.ribbon(new BasicPropertiesWidget())
|
.ribbon(new BasicPropertiesWidget())
|
||||||
.ribbon(new OwnedAttributeListWidget())
|
.ribbon(new OwnedAttributeListWidget())
|
||||||
.ribbon(new InheritedAttributesWidget())
|
.ribbon(new InheritedAttributesWidget())
|
||||||
|
@ -14,7 +14,7 @@ async function processEntityChanges(entityChanges) {
|
|||||||
if (ec.entityName === 'notes') {
|
if (ec.entityName === 'notes') {
|
||||||
processNoteChange(loadResults, ec);
|
processNoteChange(loadResults, ec);
|
||||||
} else if (ec.entityName === 'branches') {
|
} else if (ec.entityName === 'branches') {
|
||||||
processBranchChange(loadResults, ec);
|
await processBranchChange(loadResults, ec);
|
||||||
} else if (ec.entityName === 'attributes') {
|
} else if (ec.entityName === 'attributes') {
|
||||||
processAttributeChange(loadResults, ec);
|
processAttributeChange(loadResults, ec);
|
||||||
} else if (ec.entityName === 'note_reordering') {
|
} else if (ec.entityName === 'note_reordering') {
|
||||||
@ -105,7 +105,7 @@ function processNoteChange(loadResults, ec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processBranchChange(loadResults, ec) {
|
async function processBranchChange(loadResults, ec) {
|
||||||
if (ec.isErased && ec.entityId in froca.branches) {
|
if (ec.isErased && ec.entityId in froca.branches) {
|
||||||
utils.reloadFrontendApp(`${ec.entityName} ${ec.entityId} is erased, need to do complete reload.`);
|
utils.reloadFrontendApp(`${ec.entityName} ${ec.entityId} is erased, need to do complete reload.`);
|
||||||
return;
|
return;
|
||||||
@ -139,7 +139,15 @@ function processBranchChange(loadResults, ec) {
|
|||||||
loadResults.addBranch(ec.entityId, ec.componentId);
|
loadResults.addBranch(ec.entityId, ec.componentId);
|
||||||
|
|
||||||
const childNote = froca.notes[ec.entity.noteId];
|
const childNote = froca.notes[ec.entity.noteId];
|
||||||
const parentNote = froca.notes[ec.entity.parentNoteId];
|
let parentNote = froca.notes[ec.entity.parentNoteId];
|
||||||
|
|
||||||
|
if (childNote && !parentNote) {
|
||||||
|
// a branch cannot exist without the parent
|
||||||
|
// a note loaded into froca has to also contain all its ancestors
|
||||||
|
// this problem happened e.g. in sharing where _share was hidden and thus not loaded
|
||||||
|
// sharing meant cloning into _share, which crashed because _share was not loaded
|
||||||
|
parentNote = await froca.getNote(ec.entity.parentNoteId);
|
||||||
|
}
|
||||||
|
|
||||||
if (branch) {
|
if (branch) {
|
||||||
branch.update(ec.entity);
|
branch.update(ec.entity);
|
||||||
|
@ -65,7 +65,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
|||||||
await ws.waitForMaxKnownEntityChangeId();
|
await ws.waitForMaxKnownEntityChangeId();
|
||||||
|
|
||||||
await appContext.tabManager.getActiveContext().setNote(notePath);
|
await appContext.tabManager.getActiveContext().setNote(notePath);
|
||||||
appContext.triggerEvent('focusAndSelectTitle');
|
await appContext.triggerEvent('focusAndSelectTitle');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,7 +82,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
|||||||
await appContext.tabManager.openContextWithNote(notePath, { activate });
|
await appContext.tabManager.openContextWithNote(notePath, { activate });
|
||||||
|
|
||||||
if (activate) {
|
if (activate) {
|
||||||
appContext.triggerEvent('focusAndSelectTitle');
|
await appContext.triggerEvent('focusAndSelectTitle');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,10 +100,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
|||||||
const subContexts = appContext.tabManager.getActiveContext().getSubContexts();
|
const subContexts = appContext.tabManager.getActiveContext().getSubContexts();
|
||||||
const {ntxId} = subContexts[subContexts.length - 1];
|
const {ntxId} = subContexts[subContexts.length - 1];
|
||||||
|
|
||||||
appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath});
|
await appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath});
|
||||||
|
|
||||||
if (activate) {
|
if (activate) {
|
||||||
appContext.triggerEvent('focusAndSelectTitle');
|
await appContext.triggerEvent('focusAndSelectTitle');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -285,7 +285,11 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.$title = this.$widget.find('.attr-detail-title');
|
this.$title = this.$widget.find('.attr-detail-title');
|
||||||
|
|
||||||
this.$inputName = this.$widget.find('.attr-input-name');
|
this.$inputName = this.$widget.find('.attr-input-name');
|
||||||
this.$inputName.on('keyup', () => this.userEditedAttribute());
|
this.$inputName.on('input', ev => {
|
||||||
|
if (!ev.originalEvent?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
||||||
|
this.userEditedAttribute();
|
||||||
|
}
|
||||||
|
});
|
||||||
this.$inputName.on('change', () => this.userEditedAttribute());
|
this.$inputName.on('change', () => this.userEditedAttribute());
|
||||||
this.$inputName.on('autocomplete:closed', () => this.userEditedAttribute());
|
this.$inputName.on('autocomplete:closed', () => this.userEditedAttribute());
|
||||||
|
|
||||||
@ -299,7 +303,11 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
this.$rowValue = this.$widget.find('.attr-row-value');
|
this.$rowValue = this.$widget.find('.attr-row-value');
|
||||||
this.$inputValue = this.$widget.find('.attr-input-value');
|
this.$inputValue = this.$widget.find('.attr-input-value');
|
||||||
this.$inputValue.on('keyup', () => this.userEditedAttribute());
|
this.$inputValue.on('input', ev => {
|
||||||
|
if (!ev.originalEvent?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
||||||
|
this.userEditedAttribute();
|
||||||
|
}
|
||||||
|
});
|
||||||
this.$inputValue.on('change', () => this.userEditedAttribute());
|
this.$inputValue.on('change', () => this.userEditedAttribute());
|
||||||
this.$inputValue.on('autocomplete:closed', () => this.userEditedAttribute());
|
this.$inputValue.on('autocomplete:closed', () => this.userEditedAttribute());
|
||||||
this.$inputValue.on('focus', () => {
|
this.$inputValue.on('focus', () => {
|
||||||
@ -328,7 +336,11 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
this.$rowInverseRelation = this.$widget.find('.attr-row-inverse-relation');
|
this.$rowInverseRelation = this.$widget.find('.attr-row-inverse-relation');
|
||||||
this.$inputInverseRelation = this.$widget.find('.attr-input-inverse-relation');
|
this.$inputInverseRelation = this.$widget.find('.attr-input-inverse-relation');
|
||||||
this.$inputInverseRelation.on('keyup', () => this.userEditedAttribute());
|
this.$inputInverseRelation.on('input', ev => {
|
||||||
|
if (!ev.originalEvent?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
||||||
|
this.userEditedAttribute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.$rowTargetNote = this.$widget.find('.attr-row-target-note');
|
this.$rowTargetNote = this.$widget.find('.attr-row-target-note');
|
||||||
this.$inputTargetNote = this.$widget.find('.attr-input-target-note');
|
this.$inputTargetNote = this.$widget.find('.attr-input-target-note');
|
||||||
|
@ -63,7 +63,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
|||||||
return {
|
return {
|
||||||
show: true,
|
show: true,
|
||||||
activate: true,
|
activate: true,
|
||||||
title: "Promoted attributes",
|
title: "Promoted Attributes",
|
||||||
icon: "bx bx-table"
|
icon: "bx bx-table"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
|
|||||||
return {
|
return {
|
||||||
show: this.isEnabled(),
|
show: this.isEnabled(),
|
||||||
activate: true,
|
activate: true,
|
||||||
title: 'Search parameters',
|
title: 'Search Parameters',
|
||||||
icon: 'bx bx-search'
|
icon: 'bx bx-search'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,14 @@ export default class SharedInfoWidget extends NoteContextAwareWidget {
|
|||||||
this.$sharedText.text("This note is shared publicly on");
|
this.$sharedText.text("This note is shared publicly on");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
link = `${location.protocol}//${location.host}${location.pathname}share/${shareId}`;
|
let host = location.host;
|
||||||
|
if (host.endsWith('/')) {
|
||||||
|
// seems like IE has trailing slash
|
||||||
|
// https://github.com/zadam/trilium/issues/3782
|
||||||
|
host = host.substr(0, host.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
link = `${location.protocol}//${host}${location.pathname}share/${shareId}`;
|
||||||
this.$sharedText.text("This note is shared locally on");
|
this.$sharedText.text("This note is shared locally on");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const ValidationError = require("../errors/validation_error");
|
|||||||
const noteTypesService = require("./note_types");
|
const noteTypesService = require("./note_types");
|
||||||
|
|
||||||
function getNewNotePosition(parentNote) {
|
function getNewNotePosition(parentNote) {
|
||||||
if (parentNote.hasLabel('newNotesOnTop')) {
|
if (parentNote.isLabelTruthy('newNotesOnTop')) {
|
||||||
const minNotePos = parentNote.getChildBranches()
|
const minNotePos = parentNote.getChildBranches()
|
||||||
.reduce((min, note) => Math.min(min, note.notePosition), 0);
|
.reduce((min, note) => Math.min(min, note.notePosition), 0);
|
||||||
|
|
||||||
@ -841,7 +841,7 @@ function duplicateSubtree(origNoteId, newParentNoteId) {
|
|||||||
throw new Error('Duplicating root is not possible');
|
throw new Error('Duplicating root is not possible');
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(`Duplicating ${origNoteId} subtree into ${newParentNoteId}`);
|
log.info(`Duplicating '${origNoteId}' subtree into '${newParentNoteId}'`);
|
||||||
|
|
||||||
const origNote = becca.notes[origNoteId];
|
const origNote = becca.notes[origNoteId];
|
||||||
// might be null if orig note is not in the target newParentNoteId
|
// might be null if orig note is not in the target newParentNoteId
|
||||||
@ -919,7 +919,8 @@ function duplicateSubtreeInner(origNote, origBranch, newParentNoteId, noteIdMapp
|
|||||||
attr.value = noteIdMapping[attr.value];
|
attr.value = noteIdMapping[attr.value];
|
||||||
}
|
}
|
||||||
|
|
||||||
attr.save();
|
// the relation targets may not be created yet, the mapping is pre-generated
|
||||||
|
attr.save({skipValidation: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const childBranch of origNote.getChildBranches()) {
|
for (const childBranch of origNote.getChildBranches()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user