mirror of
https://github.com/zadam/trilium.git
synced 2025-11-03 20:06:08 +01:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24ae24a1ac | ||
|
|
fcf80f1e57 | ||
|
|
7bd7323097 | ||
|
|
0cb46f8f9b | ||
|
|
c2b64bad80 | ||
|
|
991b335c3e | ||
|
|
fd2d49de4f | ||
|
|
b990239219 | ||
|
|
bf9bfe920a | ||
|
|
ad878c078e | ||
|
|
8a019d617f | ||
|
|
4a76b7a9a5 | ||
|
|
1ac1bf12a2 |
@@ -7,10 +7,6 @@ fi
|
||||
|
||||
npm run webpack
|
||||
|
||||
# problem with circular dependencies: https://github.com/webpack/webpack/issues/9173
|
||||
# source issue: https://github.com/zadam/trilium/issues/1300
|
||||
find ./src/public/app-dist -type f -exec sed -i 's/const /var /g' {} +
|
||||
|
||||
DIR=$1
|
||||
|
||||
rm -rf $DIR
|
||||
|
||||
4135
package-lock.json
generated
4135
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.44.7",
|
||||
"version": "0.44.9",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@@ -86,8 +86,8 @@
|
||||
"jsdoc": "3.6.6",
|
||||
"lorem-ipsum": "2.0.3",
|
||||
"rcedit": "2.2.0",
|
||||
"webpack": "5.0.0-beta.32",
|
||||
"webpack-cli": "4.0.0-beta.8"
|
||||
"webpack": "5.1.0",
|
||||
"webpack-cli": "4.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"electron-installer-debian": "2.0.1"
|
||||
|
||||
@@ -5,6 +5,16 @@ import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
const LABEL = 'label';
|
||||
const RELATION = 'relation';
|
||||
|
||||
const NOTE_TYPE_ICONS = {
|
||||
"file": "bx bx-file",
|
||||
"image": "bx bx-image",
|
||||
"code": "bx bx-code",
|
||||
"render": "bx bx-extension",
|
||||
"search": "bx bx-file-find",
|
||||
"relation-map": "bx bx-map-alt",
|
||||
"book": "bx bx-book"
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: since there's no "full note" anymore we can rename this to Note
|
||||
*
|
||||
@@ -254,6 +264,31 @@ class NoteShort {
|
||||
return this.getAttributes(LABEL, name);
|
||||
}
|
||||
|
||||
getIcon(isFolder = false) {
|
||||
const iconCassLabels = this.getLabels('iconClass');
|
||||
|
||||
if (iconCassLabels.length > 0) {
|
||||
return iconCassLabels.map(l => l.value).join(' ');
|
||||
}
|
||||
else if (this.noteId === 'root') {
|
||||
return "bx bx-chevrons-right";
|
||||
}
|
||||
else if (this.type === 'text') {
|
||||
if (isFolder) {
|
||||
return "bx bx-folder";
|
||||
}
|
||||
else {
|
||||
return "bx bx-note";
|
||||
}
|
||||
}
|
||||
else if (this.type === 'code' && this.mime.startsWith('text/x-sql')) {
|
||||
return "bx bx-data";
|
||||
}
|
||||
else {
|
||||
return NOTE_TYPE_ICONS[this.type];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [name] - relation name to filter
|
||||
* @returns {Attribute[]} all note's relations (attributes with type relation), including inherited ones
|
||||
|
||||
@@ -62,14 +62,19 @@ const RIGHT_PANE_CSS = `
|
||||
}
|
||||
|
||||
#right-pane .widget-header-action {
|
||||
color: var(--link-color) !important;
|
||||
cursor: pointer;
|
||||
color: var(--main-text-color) !important;
|
||||
text-decoration: none;
|
||||
font-size: large;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
#right-pane .widget-help {
|
||||
color: var(--muted-text-color);
|
||||
position: relative;
|
||||
top: 2px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
#right-pane .widget-help.no-link:hover {
|
||||
@@ -82,6 +87,7 @@ const RIGHT_PANE_CSS = `
|
||||
color: var(--main-text-color) !important;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
#right-pane .widget-toggle-button:hover {
|
||||
|
||||
@@ -63,6 +63,27 @@ export default class LinkMap {
|
||||
noteIds.add(this.note.noteId);
|
||||
}
|
||||
|
||||
await treeCache.getNotes(Array.from(noteIds));
|
||||
|
||||
// pre-fetch the link titles, it's important to have hte construction afterwards synchronous
|
||||
// since jsPlumb caculates width of the element
|
||||
const $linkTitles = {};
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
const note = await treeCache.getNote(noteId);
|
||||
|
||||
$linkTitles[noteId] = await linkService.createNoteLink(noteId, {title: note.title});
|
||||
|
||||
$linkTitles[noteId].on('click', e => {
|
||||
try {
|
||||
$linkTitles[noteId].tooltip('dispose');
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
linkService.goToLink(e);
|
||||
})
|
||||
}
|
||||
|
||||
// preload all notes
|
||||
const notes = await treeCache.getNotes(Array.from(noteIds), true);
|
||||
|
||||
@@ -98,18 +119,15 @@ export default class LinkMap {
|
||||
.addClass("note-box")
|
||||
.prop("id", noteBoxId);
|
||||
|
||||
linkService.createNoteLink(noteId, {title: note.title}).then($link => {
|
||||
$link.on('click', e => {
|
||||
try {
|
||||
$link.tooltip('dispose');
|
||||
}
|
||||
catch (e) {}
|
||||
const $link = $linkTitles[noteId];
|
||||
|
||||
linkService.goToLink(e);
|
||||
});
|
||||
|
||||
$noteBox.append($("<span>").addClass("title").append($link));
|
||||
});
|
||||
$noteBox.append(
|
||||
$("<span>")
|
||||
.addClass(note.getIcon()),
|
||||
$("<span>")
|
||||
.addClass("title")
|
||||
.append($link)
|
||||
);
|
||||
|
||||
if (noteId === this.note.noteId) {
|
||||
$noteBox.addClass("link-map-active-note");
|
||||
|
||||
@@ -47,6 +47,9 @@ class TabContext extends Component {
|
||||
if (await hoistedNoteService.checkNoteAccess(resolvedNotePath) === false) {
|
||||
return; // note is outside of hoisted subtree and user chose not to unhoist
|
||||
}
|
||||
|
||||
// if user choise to unhoist, cache was reloaded, but might not contain this note (since it's on unexpanded path)
|
||||
await treeCache.getNote(noteId);
|
||||
}
|
||||
|
||||
await this.triggerEvent('beforeNoteSwitch', {tabContext: this});
|
||||
@@ -78,10 +81,19 @@ class TabContext extends Component {
|
||||
notePath: this.notePath
|
||||
});
|
||||
}
|
||||
|
||||
if (utils.isDesktop()) {
|
||||
// close dangling autocompletes after closing the tab
|
||||
$(".aa-input").autocomplete("close");
|
||||
}
|
||||
}
|
||||
|
||||
/** @property {NoteShort} */
|
||||
get note() {
|
||||
if (this.noteId && !(this.noteId in treeCache.notes)) {
|
||||
logError(`Cannot find tabContext's note id='${this.noteId}'`);
|
||||
}
|
||||
|
||||
return treeCache.notes[this.noteId];
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ async function resolveNotePathToSegments(notePath, logErrors = true) {
|
||||
|
||||
if (!parents.length) {
|
||||
if (logErrors) {
|
||||
ws.logError(`No parents found for ${childNoteId} (${child.title})`);
|
||||
ws.logError(`No parents found for ${childNoteId} (${child.title}) for path ${notePath}`);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -83,8 +83,6 @@ async function resolveNotePathToSegments(notePath, logErrors = true) {
|
||||
for (const noteId of pathToRoot) {
|
||||
effectivePath.push(noteId);
|
||||
}
|
||||
|
||||
effectivePath.push('root');
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -77,13 +77,7 @@ export default class CollapsibleWidget extends TabAwareWidget {
|
||||
}
|
||||
|
||||
this.$headerActions = this.$widget.find('.widget-header-actions');
|
||||
let headerActions = this.headerActions;
|
||||
|
||||
if (headerActions.length > 0) {
|
||||
headerActions = ["(", ...headerActions, ")"];
|
||||
}
|
||||
|
||||
this.$headerActions.append(...headerActions);
|
||||
this.$headerActions.append(this.headerActions);
|
||||
|
||||
this.initialized = this.doRenderBody();
|
||||
|
||||
|
||||
@@ -24,7 +24,11 @@ export default class LinkMapWidget extends CollapsibleWidget {
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
const $showFullButton = $("<a>").append("show full").addClass('widget-header-action');
|
||||
const $showFullButton = $("<a>")
|
||||
.addClass("bx bx-map-alt")
|
||||
.addClass('widget-header-action')
|
||||
.attr('title', 'Show full link map');
|
||||
|
||||
$showFullButton.on('click', async () => {
|
||||
const linkMapDialog = await import("../../dialogs/link_map.js");
|
||||
linkMapDialog.showDialog();
|
||||
|
||||
@@ -21,7 +21,11 @@ class NoteRevisionsWidget extends CollapsibleWidget {
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
const $showFullButton = $("<a>").append("show dialog").addClass('widget-header-action');
|
||||
const $showFullButton = $("<a>")
|
||||
.addClass("bx bx-list-ul")
|
||||
.addClass('widget-header-action')
|
||||
.attr('title', 'Show Note revisions dialog');
|
||||
|
||||
$showFullButton.on('click', async () => {
|
||||
const attributesDialog = await import("../../dialogs/note_revisions.js");
|
||||
attributesDialog.showCurrentNoteRevisions(this.noteId);
|
||||
|
||||
@@ -15,7 +15,11 @@ export default class WhatLinksHereWidget extends CollapsibleWidget {
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
const $showFullButton = $("<a>").append("show link map").addClass('widget-header-action');
|
||||
const $showFullButton = $("<a>")
|
||||
.addClass("bx bx-map-alt")
|
||||
.addClass('widget-header-action')
|
||||
.attr('title', 'Show full link map');
|
||||
|
||||
$showFullButton.on('click', async () => {
|
||||
const linkMapDialog = await import("../../dialogs/link_map.js");
|
||||
linkMapDialog.showDialog();
|
||||
|
||||
@@ -126,13 +126,6 @@ export default class NoteActionsWidget extends TabAwareWidget {
|
||||
this.$showSourceButton.attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
if (note.type === 'text') {
|
||||
this.$exportNoteButton.removeAttr('disabled');
|
||||
}
|
||||
else {
|
||||
this.$exportNoteButton.attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
this.$protectButton.toggle(!note.isProtected);
|
||||
this.$unprotectButton.toggle(!!note.isProtected);
|
||||
}
|
||||
|
||||
@@ -159,16 +159,6 @@ const TPL = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
const NOTE_TYPE_ICONS = {
|
||||
"file": "bx bx-file",
|
||||
"image": "bx bx-image",
|
||||
"code": "bx bx-code",
|
||||
"render": "bx bx-extension",
|
||||
"search": "bx bx-file-find",
|
||||
"relation-map": "bx bx-map-alt",
|
||||
"book": "bx bx-book"
|
||||
};
|
||||
|
||||
export default class NoteTreeWidget extends TabAwareWidget {
|
||||
constructor(treeName) {
|
||||
super();
|
||||
@@ -562,40 +552,14 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
return noteList;
|
||||
}
|
||||
|
||||
getIconClass(note) {
|
||||
const labels = note.getLabels('iconClass');
|
||||
|
||||
return labels.map(l => l.value).join(' ');
|
||||
}
|
||||
|
||||
getIcon(note, isFolder) {
|
||||
const hoistedNoteId = hoistedNoteService.getHoistedNoteId();
|
||||
|
||||
const iconClass = this.getIconClass(note);
|
||||
|
||||
if (iconClass) {
|
||||
return iconClass;
|
||||
}
|
||||
else if (note.noteId === 'root') {
|
||||
return "bx bx-chevrons-right";
|
||||
}
|
||||
else if (note.noteId === hoistedNoteId) {
|
||||
if (note.noteId !== 'root' && note.noteId === hoistedNoteId) {
|
||||
return "bx bxs-arrow-from-bottom";
|
||||
}
|
||||
else if (note.type === 'text') {
|
||||
if (isFolder) {
|
||||
return "bx bx-folder";
|
||||
}
|
||||
else {
|
||||
return "bx bx-note";
|
||||
}
|
||||
}
|
||||
else if (note.type === 'code' && note.mime.startsWith('text/x-sql')) {
|
||||
return "bx bx-data";
|
||||
}
|
||||
else {
|
||||
return NOTE_TYPE_ICONS[note.type];
|
||||
}
|
||||
|
||||
return note.getIcon(isFolder);
|
||||
}
|
||||
|
||||
updateNode(node) {
|
||||
|
||||
@@ -173,6 +173,9 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
|
||||
}
|
||||
else if (definition.labelType === 'boolean') {
|
||||
$input.prop("type", "checkbox");
|
||||
// hack, without this the checkbox is invisible
|
||||
// we should be using a different bootstrap structure for checkboxes
|
||||
$input.css('width', '80px');
|
||||
|
||||
if (valueAttr.value === "true") {
|
||||
$input.prop("checked", "checked");
|
||||
|
||||
@@ -122,6 +122,11 @@ export default class SimilarNotesWidget extends TabAwareWidget {
|
||||
|
||||
const similarNotes = await server.get('similar-notes/' + this.noteId);
|
||||
|
||||
if (!similarNotes) {
|
||||
this.toggleInt(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleInt(similarNotes.length > 0);
|
||||
|
||||
if (similarNotes.length === 0) {
|
||||
|
||||
@@ -4,22 +4,21 @@
|
||||
}
|
||||
|
||||
.link-map-container .note-box {
|
||||
padding: 8px;
|
||||
padding: 0px 8px 8px 8px;
|
||||
position: absolute !important;
|
||||
background-color: var(--main-background-color);
|
||||
color: var(--main-text-color);
|
||||
z-index: 4;
|
||||
border: 1px solid #666;
|
||||
box-shadow: 2px 2px 19px #999;
|
||||
border-radius: 8px;
|
||||
opacity: 0.8;
|
||||
font-size: 11px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-width: 200px;
|
||||
min-width: 120px;
|
||||
max-height: 100px;
|
||||
max-width: 250px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.link-map-container .note-box:hover {
|
||||
@@ -47,4 +46,21 @@
|
||||
|
||||
.link-map-widget .note-box .title {
|
||||
font-size: 19px !important;
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
#link-map-dialog .note-box .bx {
|
||||
font-size: 24px !important;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.link-map-widget .note-box .bx {
|
||||
font-size: 30px !important;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
@@ -111,6 +111,10 @@ span.fancytree-node.muted { opacity: 0.6; }
|
||||
|
||||
.zen-mode #center-pane {
|
||||
width: 100% !important;
|
||||
/* limit max width to improve readability */
|
||||
max-width: 1000px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.ui-autocomplete {
|
||||
|
||||
@@ -35,6 +35,12 @@ function saveNote(req) {
|
||||
mime: 'text/html'
|
||||
});
|
||||
|
||||
if (req.body.labels) {
|
||||
for (const {name, value} of req.body.labels) {
|
||||
note.setLabel(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
noteId: note.noteId,
|
||||
branchId: branch.branchId
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2020-10-13T23:45:39+02:00", buildRevision: "893b6053d22c159d6197900c988f0007eca4840d" };
|
||||
module.exports = { buildDate:"2020-10-20T22:43:25+02:00", buildRevision: "fcf80f1e577d22cd0b8c9489042873cd7571d66d" };
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function getAppDataDir() {
|
||||
let appDataDir = os.homedir(); // fallback if OS is not recognized
|
||||
@@ -43,13 +44,13 @@ function getTriliumDataDir() {
|
||||
return process.env.TRILIUM_DATA_DIR;
|
||||
}
|
||||
|
||||
const homePath = os.homedir() + "/" + DIR_NAME;
|
||||
const homePath = os.homedir() + path.sep + DIR_NAME;
|
||||
|
||||
if (fs.existsSync(homePath)) {
|
||||
return homePath;
|
||||
}
|
||||
|
||||
const appDataPath = getAppDataDir() + '/' + DIR_NAME;
|
||||
const appDataPath = getAppDataDir() + path.sep + DIR_NAME;
|
||||
|
||||
if (!fs.existsSync(appDataPath)) {
|
||||
fs.mkdirSync(appDataPath, 0o700);
|
||||
@@ -59,10 +60,10 @@ function getTriliumDataDir() {
|
||||
}
|
||||
|
||||
const TRILIUM_DATA_DIR = getTriliumDataDir();
|
||||
const DOCUMENT_PATH = TRILIUM_DATA_DIR + "/document.db";
|
||||
const BACKUP_DIR = TRILIUM_DATA_DIR + "/backup";
|
||||
const LOG_DIR = TRILIUM_DATA_DIR + "/log";
|
||||
const ANONYMIZED_DB_DIR = TRILIUM_DATA_DIR + "/anonymized-db";
|
||||
const DOCUMENT_PATH = TRILIUM_DATA_DIR + path.sep + "document.db";
|
||||
const BACKUP_DIR = TRILIUM_DATA_DIR + path.sep + "backup";
|
||||
const LOG_DIR = TRILIUM_DATA_DIR + path.sep + "log";
|
||||
const ANONYMIZED_DB_DIR = TRILIUM_DATA_DIR + path.sep + "anonymized-db";
|
||||
|
||||
module.exports = {
|
||||
TRILIUM_DATA_DIR,
|
||||
|
||||
@@ -21,7 +21,7 @@ function sanitize(dirtyHtml) {
|
||||
'input': [ 'class', 'type', 'disabled' ],
|
||||
'code': [ 'class' ]
|
||||
},
|
||||
allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'data']
|
||||
allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'data', 'evernote']
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user