mirror of
https://github.com/zadam/trilium.git
synced 2025-10-28 08:46:43 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38e7649ac3 | ||
|
|
7a2c7edd7e | ||
|
|
cfb850acb2 | ||
|
|
a16aaf7a81 | ||
|
|
522f71cb91 |
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"version": "0.37.2",
|
"version": "0.37.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"productName": "Trilium Notes",
|
"productName": "Trilium Notes",
|
||||||
"description": "Trilium Notes",
|
"description": "Trilium Notes",
|
||||||
"version": "0.37.3",
|
"version": "0.37.4",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"main": "electron.js",
|
"main": "electron.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ $form.on('submit', () => {
|
|||||||
function exportBranch(branchId, type, format, version) {
|
function exportBranch(branchId, type, format, version) {
|
||||||
taskId = utils.randomString(10);
|
taskId = utils.randomString(10);
|
||||||
|
|
||||||
const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`;
|
const url = utils.getUrlForDownload(`api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`);
|
||||||
|
|
||||||
utils.download(url);
|
utils.download(url);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ async function setContentPane() {
|
|||||||
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
|
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
|
||||||
|
|
||||||
$downloadButton.on('click', () => {
|
$downloadButton.on('click', () => {
|
||||||
utils.download(utils.getHost() + `/api/notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}/download`);
|
const url = utils.getUrlForDownload(`api/notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}/download`);
|
||||||
|
|
||||||
|
utils.download(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
$titleButtons.append($downloadButton);
|
$titleButtons.append($downloadButton);
|
||||||
|
|||||||
@@ -4,83 +4,97 @@ import cloningService from "./cloning.js";
|
|||||||
import toastService from "./toast.js";
|
import toastService from "./toast.js";
|
||||||
import hoistedNoteService from "./hoisted_note.js";
|
import hoistedNoteService from "./hoisted_note.js";
|
||||||
|
|
||||||
let clipboardIds = [];
|
/*
|
||||||
|
* Clipboard contains node keys which are not stable. If a (part of the) tree is reloaded,
|
||||||
|
* node keys in the clipboard might not exist anymore. Code here should then be ready to deal
|
||||||
|
* with this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let clipboardNodeKeys = [];
|
||||||
let clipboardMode = null;
|
let clipboardMode = null;
|
||||||
|
|
||||||
async function pasteAfter(node) {
|
async function pasteAfter(afterNode) {
|
||||||
|
if (isClipboardEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (clipboardMode === 'cut') {
|
if (clipboardMode === 'cut') {
|
||||||
const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
|
const nodes = clipboardNodeKeys.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
|
||||||
|
|
||||||
await treeChangesService.moveAfterNode(nodes, node);
|
await treeChangesService.moveAfterNode(nodes, afterNode);
|
||||||
|
|
||||||
clipboardIds = [];
|
clipboardNodeKeys = [];
|
||||||
clipboardMode = null;
|
clipboardMode = null;
|
||||||
}
|
}
|
||||||
else if (clipboardMode === 'copy') {
|
else if (clipboardMode === 'copy') {
|
||||||
for (const noteId of clipboardIds) {
|
for (const nodeKey of clipboardNodeKeys) {
|
||||||
await cloningService.cloneNoteAfter(noteId, node.data.branchId);
|
const clipNode = treeUtils.getNodeByKey(nodeKey);
|
||||||
|
|
||||||
|
await cloningService.cloneNoteAfter(clipNode.data.noteId, afterNode.data.branchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places
|
// copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places
|
||||||
}
|
}
|
||||||
else if (clipboardIds.length === 0) {
|
|
||||||
// just do nothing
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
toastService.throwError("Unrecognized clipboard mode=" + clipboardMode);
|
toastService.throwError("Unrecognized clipboard mode=" + clipboardMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pasteInto(node) {
|
async function pasteInto(parentNode) {
|
||||||
|
if (isClipboardEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (clipboardMode === 'cut') {
|
if (clipboardMode === 'cut') {
|
||||||
const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
|
const nodes = clipboardNodeKeys.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
|
||||||
|
|
||||||
await treeChangesService.moveToNode(nodes, node);
|
await treeChangesService.moveToNode(nodes, parentNode);
|
||||||
|
|
||||||
await node.setExpanded(true);
|
await parentNode.setExpanded(true);
|
||||||
|
|
||||||
clipboardIds = [];
|
clipboardNodeKeys = [];
|
||||||
clipboardMode = null;
|
clipboardMode = null;
|
||||||
}
|
}
|
||||||
else if (clipboardMode === 'copy') {
|
else if (clipboardMode === 'copy') {
|
||||||
for (const noteId of clipboardIds) {
|
for (const nodeKey of clipboardNodeKeys) {
|
||||||
await cloningService.cloneNoteTo(noteId, node.data.noteId);
|
const clipNode = treeUtils.getNodeByKey(nodeKey);
|
||||||
|
|
||||||
|
await cloningService.cloneNoteTo(clipNode.data.noteId, parentNode.data.noteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await node.setExpanded(true);
|
await parentNode.setExpanded(true);
|
||||||
|
|
||||||
// copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places
|
// copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places
|
||||||
}
|
}
|
||||||
else if (clipboardIds.length === 0) {
|
|
||||||
// just do nothing
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
toastService.throwError("Unrecognized clipboard mode=" + mode);
|
toastService.throwError("Unrecognized clipboard mode=" + mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function copy(nodes) {
|
function copy(nodes) {
|
||||||
clipboardIds = nodes.map(node => node.data.noteId);
|
clipboardNodeKeys = nodes.map(node => node.key);
|
||||||
clipboardMode = 'copy';
|
clipboardMode = 'copy';
|
||||||
|
|
||||||
toastService.showMessage("Note(s) have been copied into clipboard.");
|
toastService.showMessage("Note(s) have been copied into clipboard.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function cut(nodes) {
|
function cut(nodes) {
|
||||||
clipboardIds = nodes
|
clipboardNodeKeys = nodes
|
||||||
.filter(node => node.data.noteId !== hoistedNoteService.getHoistedNoteNoPromise())
|
.filter(node => node.data.noteId !== hoistedNoteService.getHoistedNoteNoPromise())
|
||||||
.filter(node => node.getParent().data.noteType !== 'search')
|
.filter(node => node.getParent().data.noteType !== 'search')
|
||||||
.map(node => node.data.noteId);
|
.map(node => node.key);
|
||||||
|
|
||||||
if (clipboardIds.length > 0) {
|
if (clipboardNodeKeys.length > 0) {
|
||||||
clipboardMode = 'cut';
|
clipboardMode = 'cut';
|
||||||
|
|
||||||
toastService.showMessage("Note(s) have been cut into clipboard.");
|
toastService.showMessage("Note(s) have been cut into clipboard.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEmpty() {
|
function isClipboardEmpty() {
|
||||||
return clipboardIds.length === 0;
|
clipboardNodeKeys = clipboardNodeKeys.filter(key => !!treeUtils.getNodeByKey(key));
|
||||||
|
|
||||||
|
return clipboardNodeKeys.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -88,5 +102,5 @@ export default {
|
|||||||
pasteInto,
|
pasteInto,
|
||||||
cut,
|
cut,
|
||||||
copy,
|
copy,
|
||||||
isEmpty
|
isClipboardEmpty
|
||||||
}
|
}
|
||||||
@@ -185,8 +185,7 @@ class NoteDetailBook {
|
|||||||
}
|
}
|
||||||
else if (type === 'file') {
|
else if (type === 'file') {
|
||||||
function getFileUrl() {
|
function getFileUrl() {
|
||||||
// electron needs absolute URL so we extract current host, port, protocol
|
return utils.getUrlForDownload("api/notes/" + note.noteId + "/download");
|
||||||
return utils.getHost() + "/api/notes/" + note.noteId + "/download";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const $downloadButton = $('<button class="file-download btn btn-primary" type="button">Download</button>');
|
const $downloadButton = $('<button class="file-download btn btn-primary" type="button">Download</button>');
|
||||||
|
|||||||
@@ -87,8 +87,7 @@ class NoteDetailFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFileUrl() {
|
getFileUrl() {
|
||||||
// electron needs absolute URL so we extract current host, port, protocol
|
return utils.getUrlForDownload("api/notes/" + this.ctx.note.noteId + "/download");
|
||||||
return utils.getHost() + "/api/notes/" + this.ctx.note.noteId + "/download";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {}
|
show() {}
|
||||||
|
|||||||
@@ -98,8 +98,7 @@ class NoteDetailImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFileUrl() {
|
getFileUrl() {
|
||||||
// electron needs absolute URL so we extract current host, port, protocol
|
return utils.getUrlForDownload(`api/notes/${this.ctx.note.noteId}/download`);
|
||||||
return utils.getHost() + `/api/notes/${this.ctx.note.noteId}/download`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {}
|
show() {}
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ class TreeContextMenu {
|
|||||||
{ title: "Move to ... <kbd>Ctrl+Shift+X</kbd>", cmd: "moveTo", uiIcon: "empty",
|
{ title: "Move to ... <kbd>Ctrl+Shift+X</kbd>", cmd: "moveTo", uiIcon: "empty",
|
||||||
enabled: isNotRoot && !isHoisted && parentNotSearch },
|
enabled: isNotRoot && !isHoisted && parentNotSearch },
|
||||||
{ title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "paste",
|
{ title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "paste",
|
||||||
enabled: !clipboard.isEmpty() && notSearch && noSelectedNotes },
|
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes },
|
||||||
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "paste",
|
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "paste",
|
||||||
enabled: !clipboard.isEmpty() && isNotRoot && parentNotSearch && noSelectedNotes },
|
enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes },
|
||||||
{ title: "Duplicate note here", cmd: "duplicateNote", uiIcon: "empty",
|
{ title: "Duplicate note here", cmd: "duplicateNote", uiIcon: "empty",
|
||||||
enabled: noSelectedNotes && parentNotSearch && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
enabled: noSelectedNotes && parentNotSearch && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
||||||
{ title: "----" },
|
{ title: "----" },
|
||||||
|
|||||||
@@ -214,6 +214,20 @@ async function clearBrowserCache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param url - should be without initial slash!!!
|
||||||
|
*/
|
||||||
|
function getUrlForDownload(url) {
|
||||||
|
if (isElectron()) {
|
||||||
|
// electron needs absolute URL so we extract current host, port, protocol
|
||||||
|
return getHost() + '/' + url;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// web server can be deployed on subdomain so we need to use relative path
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
reloadApp,
|
reloadApp,
|
||||||
parseDate,
|
parseDate,
|
||||||
@@ -230,7 +244,6 @@ export default {
|
|||||||
escapeHtml,
|
escapeHtml,
|
||||||
stopWatch,
|
stopWatch,
|
||||||
formatLabel,
|
formatLabel,
|
||||||
getHost,
|
|
||||||
download,
|
download,
|
||||||
toObject,
|
toObject,
|
||||||
randomString,
|
randomString,
|
||||||
@@ -245,5 +258,6 @@ export default {
|
|||||||
getMimeTypeClass,
|
getMimeTypeClass,
|
||||||
closeActiveDialog,
|
closeActiveDialog,
|
||||||
isHtmlEmpty,
|
isHtmlEmpty,
|
||||||
clearBrowserCache
|
clearBrowserCache,
|
||||||
|
getUrlForDownload
|
||||||
};
|
};
|
||||||
@@ -76,12 +76,12 @@ function SetupModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// not using server.js because it loads too many dependencies
|
// not using server.js because it loads too many dependencies
|
||||||
$.post('/api/setup/new-document', {
|
$.post('api/setup/new-document', {
|
||||||
username: username,
|
username: username,
|
||||||
password: password1,
|
password: password1,
|
||||||
theme: theme
|
theme: theme
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
window.location.replace("/");
|
window.location.replace("./");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (this.setupType() === 'sync-from-server') {
|
else if (this.setupType() === 'sync-from-server') {
|
||||||
@@ -128,10 +128,10 @@ function SetupModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function checkOutstandingSyncs() {
|
async function checkOutstandingSyncs() {
|
||||||
const { stats, initialized } = await $.get('/api/sync/stats');
|
const { stats, initialized } = await $.get('api/sync/stats');
|
||||||
|
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
window.location.replace("/");
|
window.location.replace("./");
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalOutstandingSyncs = stats.outstandingPushes + stats.outstandingPulls;
|
const totalOutstandingSyncs = stats.outstandingPushes + stats.outstandingPulls;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
module.exports = { buildDate:"2019-11-19T23:05:54+01:00", buildRevision: "07043fb177afb9d754428a410b3019d53d7b6fa0" };
|
module.exports = { buildDate:"2019-11-22T22:38:03+01:00", buildRevision: "7a2c7edd7e9b975bf64f732629e711379baecf48" };
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ async function searchForNoteIds(searchString) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInFilter = filters.find(filter => filter.name.toLowerCase() === 'in');
|
const isInFilters = filters.filter(filter => filter.name.toLowerCase() === 'in');
|
||||||
|
|
||||||
if (isInFilter) {
|
for (const isInFilter of isInFilters) {
|
||||||
if (isInFilter.operator === '=') {
|
if (isInFilter.operator === '=') {
|
||||||
noteIds = noteIds.filter(noteId => noteCacheService.isInAncestor(noteId, isInFilter.value));
|
noteIds = noteIds.filter(noteId => noteCacheService.isInAncestor(noteId, isInFilter.value));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
const baseApiUrl = 'api/';
|
|
||||||
const glob = {
|
const glob = {
|
||||||
sourceId: ''
|
sourceId: ''
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user