mirror of
https://github.com/zadam/trilium.git
synced 2025-06-05 01:18:44 +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)) {
|
||||
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 */
|
||||
this.parents = [];
|
||||
/** @type {BNote[]}
|
||||
* @private*/
|
||||
* @private */
|
||||
this.children = [];
|
||||
/** @type {BAttribute[]}
|
||||
* @private */
|
||||
@ -107,11 +107,11 @@ class BNote extends AbstractBeccaEntity {
|
||||
* @private */
|
||||
this.__attributeCache = null;
|
||||
/** @type {BAttribute[]|null}
|
||||
* @private*/
|
||||
* @private */
|
||||
this.inheritableAttributeCache = null;
|
||||
|
||||
/** @type {BAttribute[]}
|
||||
* @private*/
|
||||
* @private */
|
||||
this.targetRelations = [];
|
||||
|
||||
this.becca.addNote(this.noteId, this);
|
||||
@ -532,6 +532,20 @@ class BNote extends AbstractBeccaEntity {
|
||||
*/
|
||||
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} [value] - label value
|
||||
|
@ -595,6 +595,20 @@ class FNote {
|
||||
*/
|
||||
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
|
||||
* @returns {boolean} true if relation exists (excluding inherited)
|
||||
|
@ -128,6 +128,10 @@ export default class DesktopLayout {
|
||||
)
|
||||
.child(
|
||||
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 SearchDefinitionWidget())
|
||||
.ribbon(new EditedNotesWidget())
|
||||
@ -135,7 +139,6 @@ export default class DesktopLayout {
|
||||
.ribbon(new NotePropertiesWidget())
|
||||
.ribbon(new FilePropertiesWidget())
|
||||
.ribbon(new ImagePropertiesWidget())
|
||||
.ribbon(new PromotedAttributesWidget())
|
||||
.ribbon(new BasicPropertiesWidget())
|
||||
.ribbon(new OwnedAttributeListWidget())
|
||||
.ribbon(new InheritedAttributesWidget())
|
||||
|
@ -14,7 +14,7 @@ async function processEntityChanges(entityChanges) {
|
||||
if (ec.entityName === 'notes') {
|
||||
processNoteChange(loadResults, ec);
|
||||
} else if (ec.entityName === 'branches') {
|
||||
processBranchChange(loadResults, ec);
|
||||
await processBranchChange(loadResults, ec);
|
||||
} else if (ec.entityName === 'attributes') {
|
||||
processAttributeChange(loadResults, ec);
|
||||
} 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) {
|
||||
utils.reloadFrontendApp(`${ec.entityName} ${ec.entityId} is erased, need to do complete reload.`);
|
||||
return;
|
||||
@ -139,7 +139,15 @@ function processBranchChange(loadResults, ec) {
|
||||
loadResults.addBranch(ec.entityId, ec.componentId);
|
||||
|
||||
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) {
|
||||
branch.update(ec.entity);
|
||||
|
@ -65,7 +65,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
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 });
|
||||
|
||||
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 {ntxId} = subContexts[subContexts.length - 1];
|
||||
|
||||
appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath});
|
||||
await appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath});
|
||||
|
||||
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.$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('autocomplete:closed', () => this.userEditedAttribute());
|
||||
|
||||
@ -299,7 +303,11 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
||||
|
||||
this.$rowValue = this.$widget.find('.attr-row-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('autocomplete:closed', () => this.userEditedAttribute());
|
||||
this.$inputValue.on('focus', () => {
|
||||
@ -328,7 +336,11 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
||||
|
||||
this.$rowInverseRelation = this.$widget.find('.attr-row-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.$inputTargetNote = this.$widget.find('.attr-input-target-note');
|
||||
|
@ -63,7 +63,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
||||
return {
|
||||
show: true,
|
||||
activate: true,
|
||||
title: "Promoted attributes",
|
||||
title: "Promoted Attributes",
|
||||
icon: "bx bx-table"
|
||||
};
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
|
||||
return {
|
||||
show: this.isEnabled(),
|
||||
activate: true,
|
||||
title: 'Search parameters',
|
||||
title: 'Search Parameters',
|
||||
icon: 'bx bx-search'
|
||||
};
|
||||
}
|
||||
|
@ -39,7 +39,14 @@ export default class SharedInfoWidget extends NoteContextAwareWidget {
|
||||
this.$sharedText.text("This note is shared publicly on");
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ const ValidationError = require("../errors/validation_error");
|
||||
const noteTypesService = require("./note_types");
|
||||
|
||||
function getNewNotePosition(parentNote) {
|
||||
if (parentNote.hasLabel('newNotesOnTop')) {
|
||||
if (parentNote.isLabelTruthy('newNotesOnTop')) {
|
||||
const minNotePos = parentNote.getChildBranches()
|
||||
.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');
|
||||
}
|
||||
|
||||
log.info(`Duplicating ${origNoteId} subtree into ${newParentNoteId}`);
|
||||
log.info(`Duplicating '${origNoteId}' subtree into '${newParentNoteId}'`);
|
||||
|
||||
const origNote = becca.notes[origNoteId];
|
||||
// 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.save();
|
||||
// the relation targets may not be created yet, the mapping is pre-generated
|
||||
attr.save({skipValidation: true});
|
||||
}
|
||||
|
||||
for (const childBranch of origNote.getChildBranches()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user