mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
Merge remote-tracking branch 'origin/t35'
# Conflicts: # src/views/tabs.ejs
This commit is contained in:
commit
385b79ad34
@ -7,6 +7,7 @@ const sqlInit = require('./src/services/sql_init');
|
|||||||
const cls = require('./src/services/cls');
|
const cls = require('./src/services/cls');
|
||||||
const url = require("url");
|
const url = require("url");
|
||||||
const port = require('./src/services/port');
|
const port = require('./src/services/port');
|
||||||
|
const env = require('./src/services/env');
|
||||||
const appIconService = require('./src/services/app_icon');
|
const appIconService = require('./src/services/app_icon');
|
||||||
const windowStateKeeper = require('electron-window-state');
|
const windowStateKeeper = require('electron-window-state');
|
||||||
const contextMenu = require('electron-context-menu');
|
const contextMenu = require('electron-context-menu');
|
||||||
@ -74,7 +75,7 @@ async function createMainWindow() {
|
|||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true
|
nodeIntegration: true
|
||||||
},
|
},
|
||||||
icon: path.join(__dirname, 'images/app-icons/png/256x256.png')
|
icon: path.join(__dirname, 'images/app-icons/png/256x256' + (env.isDev() ? '-dev' : '') + '.png')
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindowState.manage(win);
|
mainWindowState.manage(win);
|
||||||
|
BIN
images/app-icons/png/256x256-dev.png
Normal file
BIN
images/app-icons/png/256x256-dev.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
15537
libraries/jsplumb.js
15537
libraries/jsplumb.js
File diff suppressed because one or more lines are too long
193
package-lock.json
generated
193
package-lock.json
generated
@ -77,6 +77,42 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@develar/schema-utils": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.1.0",
|
||||||
|
"ajv-keywords": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": {
|
||||||
|
"version": "6.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||||
|
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^2.0.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@electron/get": {
|
"@electron/get": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.3.1.tgz",
|
||||||
@ -770,26 +806,27 @@
|
|||||||
"integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="
|
"integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="
|
||||||
},
|
},
|
||||||
"app-builder-bin": {
|
"app-builder-bin": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.2.tgz",
|
||||||
"integrity": "sha512-ZyQqfFnyjAmXep29PmuMIu2KvGlfHiziz2/I38zOFe5kqnkMqeNNn/qmnwD6wdCKKeHqBuZtoWQnft8q0YyLpw==",
|
"integrity": "sha512-E9VvUrZm60oLl0rvLw/ErvZiEOIHkulZbJ9C9TWMD4ftNrkXFc2+a5JGlD19Bwvj329d4qz91zs/hWD01q18TQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"app-builder-lib": {
|
"app-builder-lib": {
|
||||||
"version": "21.1.1",
|
"version": "21.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.1.5.tgz",
|
||||||
"integrity": "sha512-nG5w9xjv4c16ki+pyBPqJvUCtQY97XQNsA4dEBryq6vClwDTkwKrl7aS0cXjo3dsWKsf/5EIcLrV0tfIiXUqJA==",
|
"integrity": "sha512-hLsSVSstMTq33a9jbBStrF0e+fa6eWXWIpsatPvHnJlkjx7dAZ5d2cZPe/1bAO3bCL3afpRl5j+HU853eGfDCg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"7zip-bin": "~5.0.3",
|
"7zip-bin": "~5.0.3",
|
||||||
|
"@develar/schema-utils": "~2.1.0",
|
||||||
"async-exit-hook": "^2.0.1",
|
"async-exit-hook": "^2.0.1",
|
||||||
"bluebird-lst": "^1.0.9",
|
"bluebird-lst": "^1.0.9",
|
||||||
"builder-util": "21.1.1",
|
"builder-util": "21.1.5",
|
||||||
"builder-util-runtime": "8.3.0",
|
"builder-util-runtime": "8.3.0",
|
||||||
"chromium-pickle-js": "^0.2.0",
|
"chromium-pickle-js": "^0.2.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"ejs": "^2.6.2",
|
"ejs": "^2.6.2",
|
||||||
"electron-publish": "21.1.1",
|
"electron-publish": "21.1.5",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"hosted-git-info": "^2.7.1",
|
"hosted-git-info": "^2.7.1",
|
||||||
"is-ci": "^2.0.0",
|
"is-ci": "^2.0.0",
|
||||||
@ -798,9 +835,9 @@
|
|||||||
"lazy-val": "^1.0.4",
|
"lazy-val": "^1.0.4",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
"normalize-package-data": "^2.5.0",
|
"normalize-package-data": "^2.5.0",
|
||||||
"read-config-file": "4.0.1",
|
"read-config-file": "5.0.0",
|
||||||
"sanitize-filename": "^1.6.1",
|
"sanitize-filename": "^1.6.1",
|
||||||
"semver": "^6.2.0",
|
"semver": "^6.3.0",
|
||||||
"temp-file": "^3.3.4"
|
"temp-file": "^3.3.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1577,14 +1614,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"builder-util": {
|
"builder-util": {
|
||||||
"version": "21.1.1",
|
"version": "21.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.1.5.tgz",
|
||||||
"integrity": "sha512-+t6pbMo/COTYDfqfRDrWDi9tuPxBctb0S9PVt8Kgd+K0eqD1lvbF05rrkiQpXIrhb6cndXgcl3FG18Oqgy5YPg==",
|
"integrity": "sha512-RBr06OnoTKTkg0W7Om2dnuKe8I82CiciU9EdsNnLO8DAfH0ZVCPsVpc3qYmr7g/7cH3zXA3yyQP73QDGNpbVYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"7zip-bin": "~5.0.3",
|
"7zip-bin": "~5.0.3",
|
||||||
"@types/debug": "^4.1.4",
|
"@types/debug": "^4.1.4",
|
||||||
"app-builder-bin": "3.4.0",
|
"app-builder-bin": "3.4.2",
|
||||||
"bluebird-lst": "^1.0.9",
|
"bluebird-lst": "^1.0.9",
|
||||||
"builder-util-runtime": "8.3.0",
|
"builder-util-runtime": "8.3.0",
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
@ -2243,9 +2280,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"content-security-policy-builder": {
|
"content-security-policy-builder": {
|
||||||
"version": "2.0.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz",
|
||||||
"integrity": "sha512-j+Nhmj1yfZAikJLImCvPJFE29x/UuBi+/MWqggGGc515JKaZrjuei2RhULJmy0MsstW3E3htl002bwmBNMKr7w=="
|
"integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ=="
|
||||||
},
|
},
|
||||||
"content-type": {
|
"content-type": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
@ -2869,18 +2906,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dmg-builder": {
|
"dmg-builder": {
|
||||||
"version": "21.1.1",
|
"version": "21.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.1.5.tgz",
|
||||||
"integrity": "sha512-WsafJ+LkG20ddVfKfNlJC6AMRKTvLMJhAwAmBHzb+KWhMZVs9/3QY2yd2BIpvWYRfUD/lWd+LmclTNWw7540Cw==",
|
"integrity": "sha512-o9rZua7mzNzZIo9SZJi57ZXe4zjNaajxEJ0LO/8k2z8Q2CL57RIaJZ95sA6G0dC1/g5Gm4cmW3O5nv9Ur8Ayow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"app-builder-lib": "~21.1.1",
|
"app-builder-lib": "~21.1.5",
|
||||||
"bluebird-lst": "^1.0.9",
|
"bluebird-lst": "^1.0.9",
|
||||||
"builder-util": "~21.1.1",
|
"builder-util": "~21.1.5",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"iconv-lite": "^0.5.0",
|
"iconv-lite": "^0.5.0",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"parse-color": "^1.0.0",
|
|
||||||
"sanitize-filename": "^1.6.1"
|
"sanitize-filename": "^1.6.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -3088,21 +3124,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"electron-builder": {
|
"electron-builder": {
|
||||||
"version": "21.1.1",
|
"version": "21.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.1.5.tgz",
|
||||||
"integrity": "sha512-4A3h0dhqSranoX7cM0eqkzABeHABH9Nch12003XIZ9MUPV4jL97nK5WBbbVG06qglYTV9x62XAqPPDS+KBOsEg==",
|
"integrity": "sha512-2tEgBESGWQ661dC9/rZlpbtmhlofoNPwnkO6KUuCZUBYpFMRvpMzH2IF7vQYsCst78yxnrV0CtiBePhM1i+DfA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"app-builder-lib": "21.1.1",
|
"app-builder-lib": "21.1.5",
|
||||||
"bluebird-lst": "^1.0.9",
|
"bluebird-lst": "^1.0.9",
|
||||||
"builder-util": "21.1.1",
|
"builder-util": "21.1.5",
|
||||||
"builder-util-runtime": "8.3.0",
|
"builder-util-runtime": "8.3.0",
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"dmg-builder": "21.1.1",
|
"dmg-builder": "21.1.5",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"is-ci": "^2.0.0",
|
"is-ci": "^2.0.0",
|
||||||
"lazy-val": "^1.0.4",
|
"lazy-val": "^1.0.4",
|
||||||
"read-config-file": "4.0.1",
|
"read-config-file": "5.0.0",
|
||||||
"sanitize-filename": "^1.6.1",
|
"sanitize-filename": "^1.6.1",
|
||||||
"update-notifier": "^3.0.1",
|
"update-notifier": "^3.0.1",
|
||||||
"yargs": "^13.3.0"
|
"yargs": "^13.3.0"
|
||||||
@ -3372,15 +3408,15 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"package-json": {
|
"package-json": {
|
||||||
"version": "6.4.0",
|
"version": "6.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/package-json/-/package-json-6.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
|
||||||
"integrity": "sha512-bd1T8OBG7hcvMd9c/udgv6u5v9wISP3Oyl9Cm7Weop8EFwrtcQDnS2sb6zhwqus2WslSr5wSTIPiTTpxxmPm7Q==",
|
"integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"got": "^9.6.0",
|
"got": "^9.6.0",
|
||||||
"registry-auth-token": "^3.4.0",
|
"registry-auth-token": "^4.0.0",
|
||||||
"registry-url": "^5.0.0",
|
"registry-url": "^5.0.0",
|
||||||
"semver": "^6.1.1"
|
"semver": "^6.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prepend-http": {
|
"prepend-http": {
|
||||||
@ -3390,12 +3426,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"registry-auth-token": {
|
"registry-auth-token": {
|
||||||
"version": "3.4.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz",
|
||||||
"integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
|
"integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"rc": "^1.1.6",
|
"rc": "^1.2.8",
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3901,13 +3937,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"electron-publish": {
|
"electron-publish": {
|
||||||
"version": "21.1.1",
|
"version": "21.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.1.5.tgz",
|
||||||
"integrity": "sha512-cM5XLFolIB5NnVpBKewcUM3Ggg+wm+LeKRYHjcB9ri58cbPKxaN+fRUXAZs3m1U9t7SIgjZy83sUSi3asxMXgQ==",
|
"integrity": "sha512-EgFxZJBrb+EBUcEwg8RNKouoBaOEpACnjLi+ipUsk72x+/6kzhcofAYBchIkGns7meengoXy7QdoiThgpr6rew==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bluebird-lst": "^1.0.9",
|
"bluebird-lst": "^1.0.9",
|
||||||
"builder-util": "~21.1.1",
|
"builder-util": "~21.1.5",
|
||||||
"builder-util-runtime": "8.3.0",
|
"builder-util-runtime": "8.3.0",
|
||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
@ -6488,9 +6524,9 @@
|
|||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||||
},
|
},
|
||||||
"helmet": {
|
"helmet": {
|
||||||
"version": "3.19.0",
|
"version": "3.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.20.0.tgz",
|
||||||
"integrity": "sha512-l58Q3unSpYatlurvFzkCbTRQ8oWUmdXbOs7h+pnwQbFJRhRJDjER6UMyqHxp9iFtWPcVA05VLcUGSi0EXIv7GA==",
|
"integrity": "sha512-Ob+TqmQFZ5f7WgP8kBbAzNPsbf6p1lOj5r+327/ymw/IILWih3wcx9u/u/S8Mwv5wbBkO7Li6x5s23t3COhUKw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"depd": "2.0.0",
|
"depd": "2.0.0",
|
||||||
"dns-prefetch-control": "0.2.0",
|
"dns-prefetch-control": "0.2.0",
|
||||||
@ -6499,7 +6535,7 @@
|
|||||||
"feature-policy": "0.3.0",
|
"feature-policy": "0.3.0",
|
||||||
"frameguard": "3.1.0",
|
"frameguard": "3.1.0",
|
||||||
"helmet-crossdomain": "0.4.0",
|
"helmet-crossdomain": "0.4.0",
|
||||||
"helmet-csp": "2.7.1",
|
"helmet-csp": "2.8.0",
|
||||||
"hide-powered-by": "1.1.0",
|
"hide-powered-by": "1.1.0",
|
||||||
"hpkp": "2.0.0",
|
"hpkp": "2.0.0",
|
||||||
"hsts": "2.2.0",
|
"hsts": "2.2.0",
|
||||||
@ -6522,12 +6558,12 @@
|
|||||||
"integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
|
"integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
|
||||||
},
|
},
|
||||||
"helmet-csp": {
|
"helmet-csp": {
|
||||||
"version": "2.7.1",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.8.0.tgz",
|
||||||
"integrity": "sha512-sCHwywg4daQ2mY0YYwXSZRsgcCeerUwxMwNixGA7aMLkVmPTYBl7gJoZDHOZyXkqPrtuDT3s2B1A+RLI7WxSdQ==",
|
"integrity": "sha512-MlCPeM0Sm3pS9RACRihx70VeTHmkQwa7sum9EK1tfw1VZyvFU0dBWym9nHh3CRkTRNlyNm/WFCMvuh9zXkOjNw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"camelize": "1.0.0",
|
"camelize": "1.0.0",
|
||||||
"content-security-policy-builder": "2.0.0",
|
"content-security-policy-builder": "2.1.0",
|
||||||
"dasherize": "2.0.0",
|
"dasherize": "2.0.0",
|
||||||
"platform": "1.3.5"
|
"platform": "1.3.5"
|
||||||
}
|
}
|
||||||
@ -9701,23 +9737,6 @@
|
|||||||
"xml2js": "^0.4.5"
|
"xml2js": "^0.4.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse-color": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "~0.5.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": {
|
|
||||||
"version": "0.5.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
|
|
||||||
"integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"parse-glob": {
|
"parse-glob": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
|
||||||
@ -10875,13 +10894,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"read-config-file": {
|
"read-config-file": {
|
||||||
"version": "4.0.1",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-5.0.0.tgz",
|
||||||
"integrity": "sha512-5caED3uo2IAZMPcbh/9hx/O29s2430RLxtnFDdzxpH/epEpawOrQnGBHueotIXUrGPPIgdNQN+S/CIp2WmiSfw==",
|
"integrity": "sha512-jIKUu+C84bfnKxyJ5j30CxCqgXWYjZLXuVE/NYlMEpeni+dhESgAeZOZd0JZbg1xTkMmnCdxksDoarkOyfEsOg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.10.1",
|
|
||||||
"ajv-keywords": "^3.4.1",
|
|
||||||
"dotenv": "^8.0.0",
|
"dotenv": "^8.0.0",
|
||||||
"dotenv-expand": "^5.1.0",
|
"dotenv-expand": "^5.1.0",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
@ -10890,30 +10907,12 @@
|
|||||||
"lazy-val": "^1.0.4"
|
"lazy-val": "^1.0.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": {
|
|
||||||
"version": "6.10.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
|
||||||
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"fast-deep-equal": "^2.0.1",
|
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
|
||||||
"json-schema-traverse": "^0.4.1",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"esprima": {
|
"esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fast-deep-equal": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.13.1",
|
"version": "3.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||||
@ -10923,12 +10922,6 @@
|
|||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"json-schema-traverse": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
|
||||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -11424,9 +11417,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.2.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
"integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A=="
|
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||||
},
|
},
|
||||||
"semver-diff": {
|
"semver-diff": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
"express-session": "1.16.2",
|
"express-session": "1.16.2",
|
||||||
"file-type": "12.0.1",
|
"file-type": "12.0.1",
|
||||||
"fs-extra": "8.1.0",
|
"fs-extra": "8.1.0",
|
||||||
"helmet": "3.19.0",
|
"helmet": "3.20.0",
|
||||||
"html": "1.0.0",
|
"html": "1.0.0",
|
||||||
"html2plaintext": "2.1.2",
|
"html2plaintext": "2.1.2",
|
||||||
"http-proxy-agent": "^2.1.0",
|
"http-proxy-agent": "^2.1.0",
|
||||||
@ -64,7 +64,7 @@
|
|||||||
"rimraf": "2.6.3",
|
"rimraf": "2.6.3",
|
||||||
"sanitize-filename": "1.6.1",
|
"sanitize-filename": "1.6.1",
|
||||||
"sax": "1.2.4",
|
"sax": "1.2.4",
|
||||||
"semver": "6.2.0",
|
"semver": "6.3.0",
|
||||||
"serve-favicon": "2.5.0",
|
"serve-favicon": "2.5.0",
|
||||||
"session-file-store": "1.3.1",
|
"session-file-store": "1.3.1",
|
||||||
"simple-node-logger": "18.12.23",
|
"simple-node-logger": "18.12.23",
|
||||||
@ -79,7 +79,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"devtron": "1.4.0",
|
"devtron": "1.4.0",
|
||||||
"electron": "6.0.0-beta.14",
|
"electron": "6.0.0-beta.14",
|
||||||
"electron-builder": "21.1.1",
|
"electron-builder": "21.1.5",
|
||||||
"electron-compile": "6.4.4",
|
"electron-compile": "6.4.4",
|
||||||
"electron-installer-debian": "2.0.0",
|
"electron-installer-debian": "2.0.0",
|
||||||
"electron-packager": "14.0.2",
|
"electron-packager": "14.0.2",
|
||||||
|
@ -42,6 +42,7 @@ import noteAutocompleteService from './services/note_autocomplete.js';
|
|||||||
import macInit from './services/mac_init.js';
|
import macInit from './services/mac_init.js';
|
||||||
import cssLoader from './services/css_loader.js';
|
import cssLoader from './services/css_loader.js';
|
||||||
import dateNoteService from './services/date_notes.js';
|
import dateNoteService from './services/date_notes.js';
|
||||||
|
import sidebarService from './services/sidebar.js';
|
||||||
|
|
||||||
window.glob.isDesktop = utils.isDesktop;
|
window.glob.isDesktop = utils.isDesktop;
|
||||||
window.glob.isMobile = utils.isMobile;
|
window.glob.isMobile = utils.isMobile;
|
||||||
|
93
src/public/javascripts/services/sidebar.js
Normal file
93
src/public/javascripts/services/sidebar.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import NoteInfoWidget from "../widgets/note_info.js";
|
||||||
|
import LinkMapWidget from "../widgets/link_map.js";
|
||||||
|
import NoteRevisionsWidget from "../widgets/note_revisions.js";
|
||||||
|
|
||||||
|
const WIDGET_TPL = `
|
||||||
|
<div class="card widget">
|
||||||
|
<div class="card-header">
|
||||||
|
<button class="btn btn-sm widget-title" data-toggle="collapse" data-target="#collapseOne">
|
||||||
|
Collapsible Group Item
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="widget-header-actions"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="collapseOne" class="collapse show body-wrapper">
|
||||||
|
<div class="card-body"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
let widgetIdCtr = 1;
|
||||||
|
|
||||||
|
class Sidebar {
|
||||||
|
/**
|
||||||
|
* @param {TabContext} ctx
|
||||||
|
*/
|
||||||
|
constructor(ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.$sidebar = ctx.$tabContent.find(".note-detail-sidebar");
|
||||||
|
this.$widgets = this.$sidebar.find(".note-detail-widgets");
|
||||||
|
this.$showSideBarButton = this.ctx.$tabContent.find(".show-sidebar-button");
|
||||||
|
this.$showSideBarButton.hide();
|
||||||
|
|
||||||
|
this.$hideSidebarButton = this.$sidebar.find(".hide-sidebar-button");
|
||||||
|
|
||||||
|
this.$hideSidebarButton.click(() => {
|
||||||
|
this.$sidebar.hide();
|
||||||
|
this.$showSideBarButton.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$showSideBarButton.click(() => {
|
||||||
|
this.$sidebar.show();
|
||||||
|
this.$showSideBarButton.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async noteLoaded() {
|
||||||
|
this.$widgets.empty();
|
||||||
|
|
||||||
|
this.addNoteInfoWidget();
|
||||||
|
this.addLinkMapWidget();
|
||||||
|
this.addNoteRevisionsWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
async addNoteInfoWidget() {
|
||||||
|
const $widget = this.createWidgetElement();
|
||||||
|
|
||||||
|
const noteInfoWidget = new NoteInfoWidget(this.ctx, $widget);
|
||||||
|
await noteInfoWidget.renderBody();
|
||||||
|
|
||||||
|
this.$widgets.append($widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addLinkMapWidget() {
|
||||||
|
const $widget = this.createWidgetElement();
|
||||||
|
|
||||||
|
const linkMapWidget = new LinkMapWidget(this.ctx, $widget);
|
||||||
|
await linkMapWidget.renderBody();
|
||||||
|
|
||||||
|
this.$widgets.append($widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addNoteRevisionsWidget() {
|
||||||
|
const $widget = this.createWidgetElement();
|
||||||
|
|
||||||
|
const noteRevisionsWidget = new NoteRevisionsWidget(this.ctx, $widget);
|
||||||
|
await noteRevisionsWidget.renderBody();
|
||||||
|
|
||||||
|
this.$widgets.append($widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
createWidgetElement() {
|
||||||
|
const widgetId = 'widget-' + widgetIdCtr++;
|
||||||
|
|
||||||
|
const $widget = $(WIDGET_TPL);
|
||||||
|
$widget.find('[data-target]').attr('data-target', "#" + widgetId);
|
||||||
|
$widget.find('.body-wrapper').attr('id', widgetId);
|
||||||
|
|
||||||
|
return $widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Sidebar;
|
@ -18,6 +18,7 @@ import noteDetailRelationMap from "./note_detail_relation_map.js";
|
|||||||
import noteDetailProtectedSession from "./note_detail_protected_session.js";
|
import noteDetailProtectedSession from "./note_detail_protected_session.js";
|
||||||
import protectedSessionService from "./protected_session.js";
|
import protectedSessionService from "./protected_session.js";
|
||||||
import linkService from "./link.js";
|
import linkService from "./link.js";
|
||||||
|
import Sidebar from "./sidebar.js";
|
||||||
|
|
||||||
const $tabContentsContainer = $("#note-tab-container");
|
const $tabContentsContainer = $("#note-tab-container");
|
||||||
|
|
||||||
@ -61,6 +62,7 @@ class TabContext {
|
|||||||
this.attributes = new Attributes(this);
|
this.attributes = new Attributes(this);
|
||||||
|
|
||||||
if (utils.isDesktop()) {
|
if (utils.isDesktop()) {
|
||||||
|
this.sidebar = new Sidebar(this);
|
||||||
this.noteType = new NoteTypeContext(this);
|
this.noteType = new NoteTypeContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +133,10 @@ class TabContext {
|
|||||||
|
|
||||||
this.showPaths();
|
this.showPaths();
|
||||||
|
|
||||||
|
if (this.sidebar) {
|
||||||
|
this.sidebar.noteLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
console.debug(`Switched tab ${this.tabId} to ${this.noteId}`);
|
console.debug(`Switched tab ${this.tabId} to ${this.noteId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,10 +69,19 @@ class TabRow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupEvents() {
|
setupEvents() {
|
||||||
window.addEventListener('resize', _ => {
|
const resizeListener = _ => {
|
||||||
this.cleanUpPreviouslyDraggedTabs();
|
this.cleanUpPreviouslyDraggedTabs();
|
||||||
this.layoutTabs();
|
this.layoutTabs();
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// ResizeObserver exists only in FF69
|
||||||
|
if (typeof ResizeObserver !== "undefined") {
|
||||||
|
new ResizeObserver(resizeListener).observe(this.el);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// for older firefox
|
||||||
|
window.addEventListener('resize', resizeListener);
|
||||||
|
}
|
||||||
|
|
||||||
this.tabEls.forEach((tabEl) => this.setTabCloseEventListener(tabEl));
|
this.tabEls.forEach((tabEl) => this.setTabCloseEventListener(tabEl));
|
||||||
}
|
}
|
||||||
|
230
src/public/javascripts/widgets/link_map.js
Normal file
230
src/public/javascripts/widgets/link_map.js
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
import libraryLoader from "../services/library_loader.js";
|
||||||
|
import linkMapDialog from "../dialogs/link_map.js";
|
||||||
|
import server from "../services/server.js";
|
||||||
|
import treeCache from "../services/tree_cache.js";
|
||||||
|
import linkService from "../services/link.js";
|
||||||
|
|
||||||
|
let linkMapContainerIdCtr = 1;
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<div style="outline: none; overflow: hidden;">
|
||||||
|
<div class="link-map-container"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const linkOverlays = [
|
||||||
|
[ "Arrow", {
|
||||||
|
location: 1,
|
||||||
|
id: "arrow",
|
||||||
|
length: 10,
|
||||||
|
width: 10,
|
||||||
|
foldback: 0.7
|
||||||
|
} ]
|
||||||
|
];
|
||||||
|
|
||||||
|
class LinkMapWidget {
|
||||||
|
/**
|
||||||
|
* @param {TabContext} ctx
|
||||||
|
* @param {jQuery} $widget
|
||||||
|
*/
|
||||||
|
constructor(ctx, $widget) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.$widget = $widget;
|
||||||
|
this.$title = this.$widget.find('.widget-title');
|
||||||
|
this.$title.text("Link map");
|
||||||
|
this.$headerActions = this.$widget.find('.widget-header-actions');
|
||||||
|
|
||||||
|
const $showFullButton = $("<a>").append("show full").addClass('widget-header-action');
|
||||||
|
$showFullButton.click(() => {
|
||||||
|
linkMapDialog.showDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$headerActions.append($showFullButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
async renderBody() {
|
||||||
|
const $body = this.$widget.find('.card-body');
|
||||||
|
$body.html(TPL);
|
||||||
|
|
||||||
|
this.$linkMapContainer = $body.find('.link-map-container');
|
||||||
|
this.$linkMapContainer.attr("id", "link-map-container-" + linkMapContainerIdCtr++);
|
||||||
|
|
||||||
|
await libraryLoader.requireLibrary(libraryLoader.LINK_MAP);
|
||||||
|
|
||||||
|
jsPlumb.ready(() => {
|
||||||
|
this.initJsPlumbInstance();
|
||||||
|
|
||||||
|
this.initPanZoom();
|
||||||
|
|
||||||
|
this.loadNotesAndRelations();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadNotesAndRelations() {
|
||||||
|
this.cleanup();
|
||||||
|
|
||||||
|
const linkTypes = [ "hyper", "image", "relation", "relation-map" ];
|
||||||
|
const maxNotes = 50;
|
||||||
|
|
||||||
|
const noteId = this.ctx.note.noteId;
|
||||||
|
|
||||||
|
const links = await server.post(`notes/${noteId}/link-map`, {
|
||||||
|
linkTypes,
|
||||||
|
maxNotes,
|
||||||
|
maxDepth: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
const noteIds = new Set(links.map(l => l.noteId).concat(links.map(l => l.targetNoteId)));
|
||||||
|
|
||||||
|
if (noteIds.size === 0) {
|
||||||
|
noteIds.add(noteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// preload all notes
|
||||||
|
const notes = await treeCache.getNotes(Array.from(noteIds));
|
||||||
|
|
||||||
|
const graph = new Springy.Graph();
|
||||||
|
graph.addNodes(...noteIds);
|
||||||
|
graph.addEdges(...links.map(l => [l.noteId, l.targetNoteId]));
|
||||||
|
|
||||||
|
const layout = new Springy.Layout.ForceDirected(
|
||||||
|
graph,
|
||||||
|
400.0, // Spring stiffness
|
||||||
|
400.0, // Node repulsion
|
||||||
|
0.5 // Damping
|
||||||
|
);
|
||||||
|
|
||||||
|
const getNoteBox = noteId => {
|
||||||
|
const noteBoxId = this.noteIdToId(noteId);
|
||||||
|
const $existingNoteBox = $("#" + noteBoxId);
|
||||||
|
|
||||||
|
if ($existingNoteBox.length > 0) {
|
||||||
|
return $existingNoteBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
const note = notes.find(n => n.noteId === noteId);
|
||||||
|
|
||||||
|
const $noteBox = $("<div>")
|
||||||
|
.addClass("note-box")
|
||||||
|
.prop("id", noteBoxId);
|
||||||
|
|
||||||
|
linkService.createNoteLink(noteId, note.title).then($link => {
|
||||||
|
$noteBox.append($("<span>").addClass("title").append($link));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (noteId === noteId) {
|
||||||
|
$noteBox.addClass("link-map-active-note");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$linkMapContainer.append($noteBox);
|
||||||
|
|
||||||
|
this.jsPlumbInstance.draggable($noteBox[0], {
|
||||||
|
start: params => {
|
||||||
|
renderer.stop();
|
||||||
|
},
|
||||||
|
drag: params => {},
|
||||||
|
stop: params => {}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return $noteBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.renderer = new Springy.Renderer(
|
||||||
|
layout,
|
||||||
|
() => {},
|
||||||
|
(edge, p1, p2) => {
|
||||||
|
const connectionId = edge.source.id + '-' + edge.target.id;
|
||||||
|
|
||||||
|
if ($("#" + connectionId).length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getNoteBox(edge.source.id);
|
||||||
|
getNoteBox(edge.target.id);
|
||||||
|
|
||||||
|
const connection = this.jsPlumbInstance.connect({
|
||||||
|
source: this.noteIdToId(edge.source.id),
|
||||||
|
target: this.noteIdToId(edge.target.id),
|
||||||
|
type: 'link'
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.canvas.id = connectionId;
|
||||||
|
},
|
||||||
|
(node, p) => {
|
||||||
|
const $noteBox = getNoteBox(node.id);
|
||||||
|
const middleW = this.$linkMapContainer.width() / 2;
|
||||||
|
const middleH = this.$linkMapContainer.height() / 2;
|
||||||
|
|
||||||
|
$noteBox
|
||||||
|
.css("left", (middleW + p.x * 100) + "px")
|
||||||
|
.css("top", (middleH + p.y * 100) + "px");
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
() => {},
|
||||||
|
() => {
|
||||||
|
this.jsPlumbInstance.repaintEverything();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.renderer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
initPanZoom() {
|
||||||
|
if (this.pzInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pzInstance = panzoom(this.$linkMapContainer[0], {
|
||||||
|
maxZoom: 2,
|
||||||
|
minZoom: 0.3,
|
||||||
|
smoothScroll: false,
|
||||||
|
filterKey: function (e, dx, dy, dz) {
|
||||||
|
// if ALT is pressed then panzoom should bubble the event up
|
||||||
|
// this is to preserve ALT-LEFT, ALT-RIGHT navigation working
|
||||||
|
return e.altKey;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if (this.renderer) {
|
||||||
|
this.renderer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete all endpoints and connections
|
||||||
|
// this is done at this point (after async operations) to reduce flicker to the minimum
|
||||||
|
this.jsPlumbInstance.deleteEveryEndpoint();
|
||||||
|
|
||||||
|
// without this we still end up with note boxes remaining in the canvas
|
||||||
|
this.$linkMapContainer.empty();
|
||||||
|
|
||||||
|
// reset zoom/pan
|
||||||
|
this.pzInstance.zoomTo(0, 0, 0.7);
|
||||||
|
this.pzInstance.moveTo(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
initJsPlumbInstance() {
|
||||||
|
if (this.jsPlumbInstance) {
|
||||||
|
this.cleanup();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.jsPlumbInstance = jsPlumb.getInstance({
|
||||||
|
Endpoint: ["Blank", {}],
|
||||||
|
ConnectionOverlays: linkOverlays,
|
||||||
|
PaintStyle: { stroke: "var(--muted-text-color)", strokeWidth: 1 },
|
||||||
|
HoverPaintStyle: { stroke: "var(--main-text-color)", strokeWidth: 1 },
|
||||||
|
Container: this.$linkMapContainer.attr("id")
|
||||||
|
});
|
||||||
|
|
||||||
|
this.jsPlumbInstance.registerConnectionType("link", { anchor: "Continuous", connector: "Straight", overlays: linkOverlays });
|
||||||
|
}
|
||||||
|
|
||||||
|
noteIdToId(noteId) {
|
||||||
|
return "link-map-note-" + noteId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LinkMapWidget;
|
59
src/public/javascripts/widgets/note_info.js
Normal file
59
src/public/javascripts/widgets/note_info.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
const TPL = `
|
||||||
|
<table class="note-info-table">
|
||||||
|
<tr>
|
||||||
|
<th>Note ID</th>
|
||||||
|
<td class="note-info-note-id"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Created</th>
|
||||||
|
<td class="note-info-date-created"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Modified</th>
|
||||||
|
<td class="note-info-date-modified"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<td class="note-info-type"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>MIME</th>
|
||||||
|
<td class="note-info-mime"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
class NoteInfoWidget {
|
||||||
|
/**
|
||||||
|
* @param {TabContext} ctx
|
||||||
|
* @param {jQuery} $widget
|
||||||
|
*/
|
||||||
|
constructor(ctx, $widget) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.$widget = $widget;
|
||||||
|
this.$title = this.$widget.find('.widget-title');
|
||||||
|
this.$title.text("Note info");
|
||||||
|
}
|
||||||
|
|
||||||
|
async renderBody() {
|
||||||
|
const $body = this.$widget.find('.card-body');
|
||||||
|
|
||||||
|
$body.html(TPL);
|
||||||
|
|
||||||
|
const $noteId = $body.find(".note-info-note-id");
|
||||||
|
const $dateCreated = $body.find(".note-info-date-created");
|
||||||
|
const $dateModified = $body.find(".note-info-date-modified");
|
||||||
|
const $type = $body.find(".note-info-type");
|
||||||
|
const $mime = $body.find(".note-info-mime");
|
||||||
|
|
||||||
|
const note = this.ctx.note;
|
||||||
|
|
||||||
|
$noteId.text(note.noteId);
|
||||||
|
$dateCreated.text(note.dateCreated);
|
||||||
|
$dateModified.text(note.dateModified);
|
||||||
|
$type.text(note.type);
|
||||||
|
$mime.text(note.mime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NoteInfoWidget;
|
44
src/public/javascripts/widgets/note_revisions.js
Normal file
44
src/public/javascripts/widgets/note_revisions.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import server from "../services/server.js";
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<ul class="note-revision-list" style="max-height: 150px; overflow: auto;">
|
||||||
|
</ul>
|
||||||
|
`;
|
||||||
|
|
||||||
|
class NoteRevisionsWidget {
|
||||||
|
/**
|
||||||
|
* @param {TabContext} ctx
|
||||||
|
* @param {jQuery} $widget
|
||||||
|
*/
|
||||||
|
constructor(ctx, $widget) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.$widget = $widget;
|
||||||
|
this.$title = this.$widget.find('.widget-title');
|
||||||
|
this.$title.text("Note revisions");
|
||||||
|
}
|
||||||
|
|
||||||
|
async renderBody() {
|
||||||
|
const $body = this.$widget.find('.card-body');
|
||||||
|
const revisionItems = await server.get(`notes/${this.ctx.note.noteId}/revisions`);
|
||||||
|
|
||||||
|
if (revisionItems.length === 0) {
|
||||||
|
$body.text("No revisions yet...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body.html(TPL);
|
||||||
|
|
||||||
|
const $list = $body.find('.note-revision-list');
|
||||||
|
|
||||||
|
for (const item of revisionItems) {
|
||||||
|
$list.append($('<li>').append($("<a>", {
|
||||||
|
'data-action': 'note-revision',
|
||||||
|
'data-note-path': this.ctx.note.noteId,
|
||||||
|
'data-note-revision-id': item.noteRevisionId,
|
||||||
|
href: 'javascript:'
|
||||||
|
}).text(item.dateModifiedFrom)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NoteRevisionsWidget;
|
@ -133,6 +133,11 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
|
|||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* FF basic styling */
|
||||||
|
scrollbar-color: var(--active-item-background-color) var(--main-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
}
|
}
|
||||||
@ -142,8 +147,12 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
|
|||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--main-border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#note-info-table td, #note-info-table th {
|
::-webkit-scrollbar-corner {
|
||||||
padding: 15px;
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget .note-info-table td, .widget .note-info-table th {
|
||||||
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-toggle="tooltip"] span {
|
[data-toggle="tooltip"] span {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#link-map-container {
|
.link-map-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: calc(95vh - 130px);
|
height: 300px;
|
||||||
outline: none; /* remove dotted outline on click */
|
outline: none; /* remove dotted outline on click */
|
||||||
}
|
}
|
||||||
|
|
||||||
#link-map-container .note-box {
|
.link-map-container .note-box {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
background-color: var(--accented-background-color);
|
background-color: var(--accented-background-color);
|
||||||
@ -23,16 +23,16 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#link-map-container .note-box:hover {
|
.link-map-container .note-box:hover {
|
||||||
background-color: var(--more-accented-background-color);
|
background-color: var(--more-accented-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#link-map-container .note-box .title {
|
.link-map-container .note-box .title {
|
||||||
font-size: larger;
|
font-size: larger;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
#link-map-container .floating-button {
|
.link-map-container .floating-button {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
@ -103,11 +103,64 @@ ul.fancytree-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.note-tab-content {
|
.note-tab-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar {
|
||||||
|
min-width: 350px;
|
||||||
|
overflow: auto;
|
||||||
|
padding-top: 12px;
|
||||||
|
padding-left: 7px;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar .card {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar .card-header {
|
||||||
|
background: inherit;
|
||||||
|
padding: 3px 10px 3px 10px;
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--button-background-color);
|
||||||
|
border-color: var(--button-border-color);
|
||||||
|
border-width: 1px 0 1px 0;
|
||||||
|
border-style: solid;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar .widget-title {
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: inherit;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar .widget-header-actions {
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar .widget-header-action {
|
||||||
|
color: var(--link-color) !important;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-detail-sidebar .card-body {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.note-detail-component-wrapper {
|
.note-detail-component-wrapper {
|
||||||
flex-grow: 100;
|
flex-grow: 100;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -19,14 +19,21 @@ async function getLinks(noteIds, linkTypes) {
|
|||||||
|
|
||||||
async function getLinkMap(req) {
|
async function getLinkMap(req) {
|
||||||
const {noteId} = req.params;
|
const {noteId} = req.params;
|
||||||
const {linkTypes, maxNotes} = req.body;
|
const {linkTypes, maxNotes, maxDepth} = req.body;
|
||||||
|
|
||||||
let noteIds = new Set([noteId]);
|
let noteIds = new Set([noteId]);
|
||||||
let links = [];
|
let links = [];
|
||||||
|
|
||||||
|
let depth = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const newLinks = await getLinks(noteIds, linkTypes);
|
links = await getLinks(noteIds, linkTypes);
|
||||||
const newNoteIds = new Set(newLinks.map(l => l.noteId).concat(newLinks.map(l => l.targetNoteId)));
|
|
||||||
|
if (depth === maxDepth) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newNoteIds = new Set(links.map(l => l.noteId).concat(links.map(l => l.targetNoteId)));
|
||||||
|
|
||||||
if (newNoteIds.size === noteIds.size) {
|
if (newNoteIds.size === noteIds.size) {
|
||||||
// no new note discovered, no need to search any further
|
// no new note discovered, no need to search any further
|
||||||
@ -39,7 +46,8 @@ async function getLinkMap(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
noteIds = newNoteIds;
|
noteIds = newNoteIds;
|
||||||
links = newLinks;
|
|
||||||
|
depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep only links coming from and targetting some note in the noteIds set
|
// keep only links coming from and targetting some note in the noteIds set
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const sql = require('./sql');
|
const sql = require('./sql');
|
||||||
|
const log = require('./log');
|
||||||
const sqlInit = require('./sql_init');
|
const sqlInit = require('./sql_init');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const passwordEncryptionService = require('./password_encryption');
|
const passwordEncryptionService = require('./password_encryption');
|
||||||
@ -22,7 +23,7 @@ async function checkAuth(req, res, next) {
|
|||||||
// currently we're doing that for file upload because handling form data seems to be difficult
|
// currently we're doing that for file upload because handling form data seems to be difficult
|
||||||
async function checkApiAuthOrElectron(req, res, next) {
|
async function checkApiAuthOrElectron(req, res, next) {
|
||||||
if (!req.session.loggedIn && !utils.isElectron()) {
|
if (!req.session.loggedIn && !utils.isElectron()) {
|
||||||
res.status(401).send("Not authorized");
|
reject(req, res, "Not authorized");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next();
|
next();
|
||||||
@ -31,7 +32,7 @@ async function checkApiAuthOrElectron(req, res, next) {
|
|||||||
|
|
||||||
async function checkApiAuth(req, res, next) {
|
async function checkApiAuth(req, res, next) {
|
||||||
if (!req.session.loggedIn) {
|
if (!req.session.loggedIn) {
|
||||||
res.status(401).send("Not authorized");
|
reject(req, res, "Not authorized");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next();
|
next();
|
||||||
@ -49,7 +50,7 @@ async function checkAppInitialized(req, res, next) {
|
|||||||
|
|
||||||
async function checkAppNotInitialized(req, res, next) {
|
async function checkAppNotInitialized(req, res, next) {
|
||||||
if (await sqlInit.isDbInitialized()) {
|
if (await sqlInit.isDbInitialized()) {
|
||||||
res.status(400).send("App already initialized.");
|
reject(req, res, "App already initialized.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next();
|
next();
|
||||||
@ -60,13 +61,19 @@ async function checkToken(req, res, next) {
|
|||||||
const token = req.headers.authorization;
|
const token = req.headers.authorization;
|
||||||
|
|
||||||
if (await sql.getValue("SELECT COUNT(*) FROM api_tokens WHERE isDeleted = 0 AND token = ?", [token]) === 0) {
|
if (await sql.getValue("SELECT COUNT(*) FROM api_tokens WHERE isDeleted = 0 AND token = ?", [token]) === 0) {
|
||||||
res.status(401).send("Not authorized");
|
reject(req, res, "Not authorized");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reject(req, res, message) {
|
||||||
|
log.info(`${req.method} ${req.path} rejected with 401 ${message}`);
|
||||||
|
|
||||||
|
res.status(401).send(message);
|
||||||
|
}
|
||||||
|
|
||||||
async function checkBasicAuth(req, res, next) {
|
async function checkBasicAuth(req, res, next) {
|
||||||
const header = req.headers.authorization || '';
|
const header = req.headers.authorization || '';
|
||||||
const token = header.split(/\s+/).pop() || '';
|
const token = header.split(/\s+/).pop() || '';
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="desktop theme-<%= theme %>" style="--main-font-size: <%= mainFontSize %>%; --tree-font-size: <%= treeFontSize %>%; --detail-font-size: <%= detailFontSize %>%;">
|
<body class="desktop theme-<%= theme %>" style="--main-font-size: <%= mainFontSize %>%; --tree-font-size: <%= treeFontSize %>%; --detail-font-size: <%= detailFontSize %>%;">
|
||||||
<noscript>Trilium requires JavaScript to be enabled.</noscript>
|
<noscript>Trilium requires JavaScript to be enabled.</noscript>
|
||||||
<div id="container" style="display: none; grid-template-columns: minmax(<%= leftPaneMinWidth %>px, <%= leftPaneWidthPercent %>fr) minmax(0, <%= rightPaneWidthPercent %>fr)">
|
<div id="container" style="display: none; grid-template-columns: <%= leftPaneWidthPercent %>fr <%= rightPaneWidthPercent %>fr">
|
||||||
<div id="header" class="hide-toggle">
|
<div id="header" class="hide-toggle">
|
||||||
<div id="history-navigation" style="display: none;">
|
<div id="history-navigation" style="display: none;">
|
||||||
<a id="history-back-button" title="Go to previous note." class="icon-action jam jam-arrow-square-left"></a>
|
<a id="history-back-button" title="Go to previous note." class="icon-action jam jam-arrow-square-left"></a>
|
||||||
@ -106,7 +106,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="left-pane" class="hide-toggle">
|
<div id="left-pane" class="hide-toggle" style="resize: horizontal; overflow: scroll;">
|
||||||
<div id="global-buttons">
|
<div id="global-buttons">
|
||||||
<a id="create-top-level-note-button" title="Create new top level note" class="icon-action jam jam-plus-circle"></a>
|
<a id="create-top-level-note-button" title="Create new top level note" class="icon-action jam jam-plus-circle"></a>
|
||||||
|
|
||||||
|
7
src/views/sidebar.ejs
Normal file
7
src/views/sidebar.ejs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<div class="note-detail-sidebar">
|
||||||
|
<div style="text-align: center; margin-bottom: 10px;">
|
||||||
|
<button class="hide-sidebar-button" style="background: none; border: none;">hide sidebar <span class="jam jam-chevron-right"></span></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="note-detail-widgets"></div>
|
||||||
|
</div>
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
<div id="note-tab-container">
|
<div id="note-tab-container">
|
||||||
<div class="note-tab-content note-tab-content-template">
|
<div class="note-tab-content note-tab-content-template">
|
||||||
|
<div class="note-detail-content">
|
||||||
<% include title.ejs %>
|
<% include title.ejs %>
|
||||||
|
|
||||||
<div class="note-detail-script-area"></div>
|
<div class="note-detail-script-area"></div>
|
||||||
@ -42,4 +43,7 @@
|
|||||||
<span class="attribute-list-inner"></span>
|
<span class="attribute-list-inner"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<% include sidebar.ejs %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
@ -73,6 +73,8 @@
|
|||||||
<a class="dropdown-item show-note-info-button">Note info</a>
|
<a class="dropdown-item show-note-info-button">Note info</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-sm icon-button jam jam-chevron-left show-sidebar-button" title="Show sidebar"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user