mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
add #shareRoot label to define an "index" note, closes #2567
This commit is contained in:
parent
1aff3db81f
commit
52b118df7f
18
package-lock.json
generated
18
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.49.4",
|
||||
"version": "0.49.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "trilium",
|
||||
"version": "0.49.4",
|
||||
"version": "0.49.5",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@electron/remote": "2.0.1",
|
||||
@ -62,7 +62,7 @@
|
||||
"tmp": "0.2.1",
|
||||
"turndown": "7.1.1",
|
||||
"unescape": "1.0.1",
|
||||
"ws": "8.4.0",
|
||||
"ws": "8.4.2",
|
||||
"yauzl": "2.10.0"
|
||||
},
|
||||
"bin": {
|
||||
@ -11045,9 +11045,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz",
|
||||
"integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==",
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
|
||||
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@ -19881,9 +19881,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz",
|
||||
"integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==",
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz",
|
||||
"integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==",
|
||||
"requires": {}
|
||||
},
|
||||
"xdg-basedir": {
|
||||
|
@ -77,7 +77,7 @@
|
||||
"tmp": "0.2.1",
|
||||
"turndown": "7.1.1",
|
||||
"unescape": "1.0.1",
|
||||
"ws": "8.4.1",
|
||||
"ws": "8.4.2",
|
||||
"yauzl": "2.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -40,7 +40,7 @@ async function createNote(parentNotePath, options = {}) {
|
||||
C-->D;`
|
||||
}
|
||||
|
||||
const {note, branch} = await server.post(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId}`, {
|
||||
const {note, branch} = await server.post(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId || ""}`, {
|
||||
title: newNoteName,
|
||||
content: options.content || "",
|
||||
isProtected: options.isProtected,
|
||||
|
@ -214,6 +214,7 @@ const ATTR_HELP = {
|
||||
"shareHiddenFromTree": "this note is hidden from left navigation tree, but still accessible with its URL",
|
||||
"shareAlias": "define an alias using which the note will be available under https://your_trilium_host/share/[your_alias]",
|
||||
"shareOmitDefaultCss": "default share page CSS will be omitted. Use when you make extensive styling changes.",
|
||||
"shareRoot": "marks note which is served on /share root.",
|
||||
},
|
||||
"relation": {
|
||||
"runOnNoteCreation": "executes when note is created on backend",
|
||||
|
@ -617,6 +617,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
||||
|
||||
/**
|
||||
* @param {Branch} branch
|
||||
* @param {boolean} forceLazy
|
||||
*/
|
||||
prepareNode(branch, forceLazy = false) {
|
||||
const note = branch.getNoteFromCache();
|
||||
|
@ -32,7 +32,7 @@ export default class SharedInfoWidget extends NoteContextAwareWidget {
|
||||
const syncServerHost = options.get("syncServerHost");
|
||||
let link;
|
||||
|
||||
const shareId = note.getOwnedLabelValue('shareAlias') || note.noteId;
|
||||
const shareId = this.getShareId(note);
|
||||
|
||||
if (syncServerHost) {
|
||||
link = syncServerHost + "/share/" + shareId;
|
||||
@ -46,6 +46,14 @@ export default class SharedInfoWidget extends NoteContextAwareWidget {
|
||||
this.$sharedLink.attr("href", link).text(link);
|
||||
}
|
||||
|
||||
getShareId(note) {
|
||||
if (note.hasOwnedLabel('shareRoot')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return note.getOwnedLabelValue('shareAlias') || note.noteId;
|
||||
}
|
||||
|
||||
entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.getAttributes().find(attr => attr.name.startsWith("share") && attributeService.isAffecting(attr, this.note))) {
|
||||
this.refresh();
|
||||
|
@ -5,72 +5,10 @@ const sql = require('./sql');
|
||||
const becca = require('../becca/becca');
|
||||
const Attribute = require('../becca/entities/attribute');
|
||||
const {formatAttrForSearch} = require("./attribute_formatter");
|
||||
const BUILTIN_ATTRIBUTES = require("./builtin_attributes");
|
||||
|
||||
const ATTRIBUTE_TYPES = [ 'label', 'relation' ];
|
||||
|
||||
const BUILTIN_ATTRIBUTES = [
|
||||
// label names
|
||||
{ type: 'label', name: 'inbox' },
|
||||
{ type: 'label', name: 'disableVersioning' },
|
||||
{ type: 'label', name: 'calendarRoot' },
|
||||
{ type: 'label', name: 'archived' },
|
||||
{ type: 'label', name: 'excludeFromExport' },
|
||||
{ type: 'label', name: 'disableInclusion' },
|
||||
{ type: 'label', name: 'appCss' },
|
||||
{ type: 'label', name: 'appTheme' },
|
||||
{ type: 'label', name: 'hidePromotedAttributes' },
|
||||
{ type: 'label', name: 'readOnly' },
|
||||
{ type: 'label', name: 'autoReadOnlyDisabled' },
|
||||
{ type: 'label', name: 'hoistedCssClass' },
|
||||
{ type: 'label', name: 'cssClass' },
|
||||
{ type: 'label', name: 'iconClass' },
|
||||
{ type: 'label', name: 'keyboardShortcut' },
|
||||
{ type: 'label', name: 'run', isDangerous: true },
|
||||
{ type: 'label', name: 'runOnInstance', isDangerous: false },
|
||||
{ type: 'label', name: 'runAtHour', isDangerous: false },
|
||||
{ type: 'label', name: 'customRequestHandler', isDangerous: true },
|
||||
{ type: 'label', name: 'customResourceProvider', isDangerous: true },
|
||||
{ type: 'label', name: 'widget', isDangerous: true },
|
||||
{ type: 'label', name: 'noteInfoWidgetDisabled' },
|
||||
{ type: 'label', name: 'linkMapWidgetDisabled' },
|
||||
{ type: 'label', name: 'noteRevisionsWidgetDisabled' },
|
||||
{ type: 'label', name: 'whatLinksHereWidgetDisabled' },
|
||||
{ type: 'label', name: 'similarNotesWidgetDisabled' },
|
||||
{ type: 'label', name: 'workspace' },
|
||||
{ type: 'label', name: 'workspaceIconClass' },
|
||||
{ type: 'label', name: 'workspaceTabBackgroundColor' },
|
||||
{ type: 'label', name: 'searchHome' },
|
||||
{ type: 'label', name: 'hoistedInbox' },
|
||||
{ type: 'label', name: 'hoistedSearchHome' },
|
||||
{ type: 'label', name: 'sqlConsoleHome' },
|
||||
{ type: 'label', name: 'datePattern' },
|
||||
{ type: 'label', name: 'pageSize' },
|
||||
{ type: 'label', name: 'viewType' },
|
||||
{ type: 'label', name: 'mapRootNoteId' },
|
||||
{ type: 'label', name: 'bookmarked' },
|
||||
{ type: 'label', name: 'bookmarkFolder' },
|
||||
{ type: 'label', name: 'sorted' },
|
||||
{ type: 'label', name: 'top' },
|
||||
{ type: 'label', name: 'fullContentWidth' },
|
||||
{ type: 'label', name: 'shareHiddenFromTree' },
|
||||
{ type: 'label', name: 'shareAlias' },
|
||||
{ type: 'label', name: 'shareOmitDefaultCss' },
|
||||
|
||||
// relation names
|
||||
{ type: 'relation', name: 'runOnNoteCreation', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnNoteTitleChange', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnNoteChange', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnChildNoteCreation', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnAttributeCreation', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnAttributeChange', isDangerous: true },
|
||||
{ type: 'relation', name: 'template' },
|
||||
{ type: 'relation', name: 'widget', isDangerous: true },
|
||||
{ type: 'relation', name: 'renderNote', isDangerous: true },
|
||||
{ type: 'relation', name: 'shareCss', isDangerous: false },
|
||||
{ type: 'relation', name: 'shareJs', isDangerous: false },
|
||||
{ type: 'relation', name: 'shareFavicon', isDangerous: false },
|
||||
];
|
||||
|
||||
/** @returns {Note[]} */
|
||||
function getNotesWithLabel(name, value) {
|
||||
const query = formatAttrForSearch({type: 'label', name, value}, true);
|
||||
|
63
src/services/builtin_attributes.js
Normal file
63
src/services/builtin_attributes.js
Normal file
@ -0,0 +1,63 @@
|
||||
module.exports = [
|
||||
// label names
|
||||
{ type: 'label', name: 'inbox' },
|
||||
{ type: 'label', name: 'disableVersioning' },
|
||||
{ type: 'label', name: 'calendarRoot' },
|
||||
{ type: 'label', name: 'archived' },
|
||||
{ type: 'label', name: 'excludeFromExport' },
|
||||
{ type: 'label', name: 'disableInclusion' },
|
||||
{ type: 'label', name: 'appCss' },
|
||||
{ type: 'label', name: 'appTheme' },
|
||||
{ type: 'label', name: 'hidePromotedAttributes' },
|
||||
{ type: 'label', name: 'readOnly' },
|
||||
{ type: 'label', name: 'autoReadOnlyDisabled' },
|
||||
{ type: 'label', name: 'hoistedCssClass' },
|
||||
{ type: 'label', name: 'cssClass' },
|
||||
{ type: 'label', name: 'iconClass' },
|
||||
{ type: 'label', name: 'keyboardShortcut' },
|
||||
{ type: 'label', name: 'run', isDangerous: true },
|
||||
{ type: 'label', name: 'runOnInstance', isDangerous: false },
|
||||
{ type: 'label', name: 'runAtHour', isDangerous: false },
|
||||
{ type: 'label', name: 'customRequestHandler', isDangerous: true },
|
||||
{ type: 'label', name: 'customResourceProvider', isDangerous: true },
|
||||
{ type: 'label', name: 'widget', isDangerous: true },
|
||||
{ type: 'label', name: 'noteInfoWidgetDisabled' },
|
||||
{ type: 'label', name: 'linkMapWidgetDisabled' },
|
||||
{ type: 'label', name: 'noteRevisionsWidgetDisabled' },
|
||||
{ type: 'label', name: 'whatLinksHereWidgetDisabled' },
|
||||
{ type: 'label', name: 'similarNotesWidgetDisabled' },
|
||||
{ type: 'label', name: 'workspace' },
|
||||
{ type: 'label', name: 'workspaceIconClass' },
|
||||
{ type: 'label', name: 'workspaceTabBackgroundColor' },
|
||||
{ type: 'label', name: 'searchHome' },
|
||||
{ type: 'label', name: 'hoistedInbox' },
|
||||
{ type: 'label', name: 'hoistedSearchHome' },
|
||||
{ type: 'label', name: 'sqlConsoleHome' },
|
||||
{ type: 'label', name: 'datePattern' },
|
||||
{ type: 'label', name: 'pageSize' },
|
||||
{ type: 'label', name: 'viewType' },
|
||||
{ type: 'label', name: 'mapRootNoteId' },
|
||||
{ type: 'label', name: 'bookmarked' },
|
||||
{ type: 'label', name: 'bookmarkFolder' },
|
||||
{ type: 'label', name: 'sorted' },
|
||||
{ type: 'label', name: 'top' },
|
||||
{ type: 'label', name: 'fullContentWidth' },
|
||||
{ type: 'label', name: 'shareHiddenFromTree' },
|
||||
{ type: 'label', name: 'shareAlias' },
|
||||
{ type: 'label', name: 'shareOmitDefaultCss' },
|
||||
{ type: 'label', name: 'shareRoot' },
|
||||
|
||||
// relation names
|
||||
{ type: 'relation', name: 'runOnNoteCreation', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnNoteTitleChange', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnNoteChange', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnChildNoteCreation', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnAttributeCreation', isDangerous: true },
|
||||
{ type: 'relation', name: 'runOnAttributeChange', isDangerous: true },
|
||||
{ type: 'relation', name: 'template' },
|
||||
{ type: 'relation', name: 'widget', isDangerous: true },
|
||||
{ type: 'relation', name: 'renderNote', isDangerous: true },
|
||||
{ type: 'relation', name: 'shareCss', isDangerous: false },
|
||||
{ type: 'relation', name: 'shareJs', isDangerous: false },
|
||||
{ type: 'relation', name: 'shareFavicon', isDangerous: false },
|
||||
];
|
@ -21,13 +21,7 @@ function getSharedSubTreeRoot(note) {
|
||||
}
|
||||
|
||||
function register(router) {
|
||||
router.get('/share/:shareId', (req, res, next) => {
|
||||
const {shareId} = req.params;
|
||||
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const note = shaca.aliasToNote[shareId] || shaca.notes[shareId];
|
||||
|
||||
function renderNote(note, res) {
|
||||
if (note) {
|
||||
const {header, content, isEmpty} = contentRenderer.getContent(note);
|
||||
|
||||
@ -40,10 +34,25 @@ function register(router) {
|
||||
isEmpty,
|
||||
subRoot
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
res.status(404).render("share/404");
|
||||
}
|
||||
}
|
||||
|
||||
router.get(['/share', '/share/'], (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
renderNote(shaca.shareRootNote, res);
|
||||
});
|
||||
|
||||
router.get('/share/:shareId', (req, res, next) => {
|
||||
const {shareId} = req.params;
|
||||
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const note = shaca.aliasToNote[shareId] || shaca.notes[shareId];
|
||||
|
||||
renderNote(note, res);
|
||||
});
|
||||
|
||||
router.get('/share/api/notes/:noteId', (req, res, next) => {
|
||||
|
@ -43,6 +43,10 @@ class Attribute extends AbstractEntity {
|
||||
if (this.type === 'label' && this.name === 'shareAlias' && this.value.trim()) {
|
||||
this.shaca.aliasToNote[this.value.trim()] = this.note;
|
||||
}
|
||||
|
||||
if (this.type === 'label' && this.name === 'shareRoot') {
|
||||
this.shaca.shareRootNote = this.note;
|
||||
}
|
||||
}
|
||||
|
||||
get isAffectingSubtree() {
|
||||
|
@ -406,6 +406,10 @@ class Note extends AbstractEntity {
|
||||
}
|
||||
|
||||
get shareId() {
|
||||
if (this.hasOwnedLabel('shareRoot')) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const sharedAlias = this.getOwnedLabelValue("shareAlias");
|
||||
|
||||
return sharedAlias || this.noteId;
|
||||
|
@ -17,6 +17,9 @@ class Shaca {
|
||||
/** @type {Object.<String, String>} */
|
||||
this.aliasToNote = {};
|
||||
|
||||
/** @type {Note|null} */
|
||||
this.shareRootNote = null;
|
||||
|
||||
this.loaded = false;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user