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 url = require("url");
|
||||
const port = require('./src/services/port');
|
||||
const env = require('./src/services/env');
|
||||
const appIconService = require('./src/services/app_icon');
|
||||
const windowStateKeeper = require('electron-window-state');
|
||||
const contextMenu = require('electron-context-menu');
|
||||
@ -74,7 +75,7 @@ async function createMainWindow() {
|
||||
webPreferences: {
|
||||
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);
|
||||
|
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": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.3.1.tgz",
|
||||
@ -770,26 +806,27 @@
|
||||
"integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="
|
||||
},
|
||||
"app-builder-bin": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.0.tgz",
|
||||
"integrity": "sha512-ZyQqfFnyjAmXep29PmuMIu2KvGlfHiziz2/I38zOFe5kqnkMqeNNn/qmnwD6wdCKKeHqBuZtoWQnft8q0YyLpw==",
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.2.tgz",
|
||||
"integrity": "sha512-E9VvUrZm60oLl0rvLw/ErvZiEOIHkulZbJ9C9TWMD4ftNrkXFc2+a5JGlD19Bwvj329d4qz91zs/hWD01q18TQ==",
|
||||
"dev": true
|
||||
},
|
||||
"app-builder-lib": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.1.1.tgz",
|
||||
"integrity": "sha512-nG5w9xjv4c16ki+pyBPqJvUCtQY97XQNsA4dEBryq6vClwDTkwKrl7aS0cXjo3dsWKsf/5EIcLrV0tfIiXUqJA==",
|
||||
"version": "21.1.5",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.1.5.tgz",
|
||||
"integrity": "sha512-hLsSVSstMTq33a9jbBStrF0e+fa6eWXWIpsatPvHnJlkjx7dAZ5d2cZPe/1bAO3bCL3afpRl5j+HU853eGfDCg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"7zip-bin": "~5.0.3",
|
||||
"@develar/schema-utils": "~2.1.0",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "21.1.1",
|
||||
"builder-util": "21.1.5",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chromium-pickle-js": "^0.2.0",
|
||||
"debug": "^4.1.1",
|
||||
"ejs": "^2.6.2",
|
||||
"electron-publish": "21.1.1",
|
||||
"electron-publish": "21.1.5",
|
||||
"fs-extra": "^8.1.0",
|
||||
"hosted-git-info": "^2.7.1",
|
||||
"is-ci": "^2.0.0",
|
||||
@ -798,9 +835,9 @@
|
||||
"lazy-val": "^1.0.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
"read-config-file": "4.0.1",
|
||||
"read-config-file": "5.0.0",
|
||||
"sanitize-filename": "^1.6.1",
|
||||
"semver": "^6.2.0",
|
||||
"semver": "^6.3.0",
|
||||
"temp-file": "^3.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -1577,14 +1614,14 @@
|
||||
}
|
||||
},
|
||||
"builder-util": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.1.1.tgz",
|
||||
"integrity": "sha512-+t6pbMo/COTYDfqfRDrWDi9tuPxBctb0S9PVt8Kgd+K0eqD1lvbF05rrkiQpXIrhb6cndXgcl3FG18Oqgy5YPg==",
|
||||
"version": "21.1.5",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.1.5.tgz",
|
||||
"integrity": "sha512-RBr06OnoTKTkg0W7Om2dnuKe8I82CiciU9EdsNnLO8DAfH0ZVCPsVpc3qYmr7g/7cH3zXA3yyQP73QDGNpbVYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"7zip-bin": "~5.0.3",
|
||||
"@types/debug": "^4.1.4",
|
||||
"app-builder-bin": "3.4.0",
|
||||
"app-builder-bin": "3.4.2",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chalk": "^2.4.2",
|
||||
@ -2243,9 +2280,9 @@
|
||||
}
|
||||
},
|
||||
"content-security-policy-builder": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.0.0.tgz",
|
||||
"integrity": "sha512-j+Nhmj1yfZAikJLImCvPJFE29x/UuBi+/MWqggGGc515JKaZrjuei2RhULJmy0MsstW3E3htl002bwmBNMKr7w=="
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz",
|
||||
"integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ=="
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.4",
|
||||
@ -2869,18 +2906,17 @@
|
||||
}
|
||||
},
|
||||
"dmg-builder": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.1.1.tgz",
|
||||
"integrity": "sha512-WsafJ+LkG20ddVfKfNlJC6AMRKTvLMJhAwAmBHzb+KWhMZVs9/3QY2yd2BIpvWYRfUD/lWd+LmclTNWw7540Cw==",
|
||||
"version": "21.1.5",
|
||||
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-21.1.5.tgz",
|
||||
"integrity": "sha512-o9rZua7mzNzZIo9SZJi57ZXe4zjNaajxEJ0LO/8k2z8Q2CL57RIaJZ95sA6G0dC1/g5Gm4cmW3O5nv9Ur8Ayow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"app-builder-lib": "~21.1.1",
|
||||
"app-builder-lib": "~21.1.5",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "~21.1.1",
|
||||
"builder-util": "~21.1.5",
|
||||
"fs-extra": "^8.1.0",
|
||||
"iconv-lite": "^0.5.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"parse-color": "^1.0.0",
|
||||
"sanitize-filename": "^1.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -3088,21 +3124,21 @@
|
||||
}
|
||||
},
|
||||
"electron-builder": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.1.1.tgz",
|
||||
"integrity": "sha512-4A3h0dhqSranoX7cM0eqkzABeHABH9Nch12003XIZ9MUPV4jL97nK5WBbbVG06qglYTV9x62XAqPPDS+KBOsEg==",
|
||||
"version": "21.1.5",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.1.5.tgz",
|
||||
"integrity": "sha512-2tEgBESGWQ661dC9/rZlpbtmhlofoNPwnkO6KUuCZUBYpFMRvpMzH2IF7vQYsCst78yxnrV0CtiBePhM1i+DfA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"app-builder-lib": "21.1.1",
|
||||
"app-builder-lib": "21.1.5",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "21.1.1",
|
||||
"builder-util": "21.1.5",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chalk": "^2.4.2",
|
||||
"dmg-builder": "21.1.1",
|
||||
"dmg-builder": "21.1.5",
|
||||
"fs-extra": "^8.1.0",
|
||||
"is-ci": "^2.0.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
"read-config-file": "4.0.1",
|
||||
"read-config-file": "5.0.0",
|
||||
"sanitize-filename": "^1.6.1",
|
||||
"update-notifier": "^3.0.1",
|
||||
"yargs": "^13.3.0"
|
||||
@ -3372,15 +3408,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"package-json": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/package-json/-/package-json-6.4.0.tgz",
|
||||
"integrity": "sha512-bd1T8OBG7hcvMd9c/udgv6u5v9wISP3Oyl9Cm7Weop8EFwrtcQDnS2sb6zhwqus2WslSr5wSTIPiTTpxxmPm7Q==",
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
|
||||
"integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"got": "^9.6.0",
|
||||
"registry-auth-token": "^3.4.0",
|
||||
"registry-auth-token": "^4.0.0",
|
||||
"registry-url": "^5.0.0",
|
||||
"semver": "^6.1.1"
|
||||
"semver": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"prepend-http": {
|
||||
@ -3390,12 +3426,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"registry-auth-token": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
|
||||
"integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"rc": "^1.1.6",
|
||||
"rc": "^1.2.8",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
@ -3901,13 +3937,13 @@
|
||||
}
|
||||
},
|
||||
"electron-publish": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.1.1.tgz",
|
||||
"integrity": "sha512-cM5XLFolIB5NnVpBKewcUM3Ggg+wm+LeKRYHjcB9ri58cbPKxaN+fRUXAZs3m1U9t7SIgjZy83sUSi3asxMXgQ==",
|
||||
"version": "21.1.5",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.1.5.tgz",
|
||||
"integrity": "sha512-EgFxZJBrb+EBUcEwg8RNKouoBaOEpACnjLi+ipUsk72x+/6kzhcofAYBchIkGns7meengoXy7QdoiThgpr6rew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "~21.1.1",
|
||||
"builder-util": "~21.1.5",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chalk": "^2.4.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
@ -6488,9 +6524,9 @@
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||
},
|
||||
"helmet": {
|
||||
"version": "3.19.0",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.19.0.tgz",
|
||||
"integrity": "sha512-l58Q3unSpYatlurvFzkCbTRQ8oWUmdXbOs7h+pnwQbFJRhRJDjER6UMyqHxp9iFtWPcVA05VLcUGSi0EXIv7GA==",
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.20.0.tgz",
|
||||
"integrity": "sha512-Ob+TqmQFZ5f7WgP8kBbAzNPsbf6p1lOj5r+327/ymw/IILWih3wcx9u/u/S8Mwv5wbBkO7Li6x5s23t3COhUKw==",
|
||||
"requires": {
|
||||
"depd": "2.0.0",
|
||||
"dns-prefetch-control": "0.2.0",
|
||||
@ -6499,7 +6535,7 @@
|
||||
"feature-policy": "0.3.0",
|
||||
"frameguard": "3.1.0",
|
||||
"helmet-crossdomain": "0.4.0",
|
||||
"helmet-csp": "2.7.1",
|
||||
"helmet-csp": "2.8.0",
|
||||
"hide-powered-by": "1.1.0",
|
||||
"hpkp": "2.0.0",
|
||||
"hsts": "2.2.0",
|
||||
@ -6522,12 +6558,12 @@
|
||||
"integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
|
||||
},
|
||||
"helmet-csp": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.1.tgz",
|
||||
"integrity": "sha512-sCHwywg4daQ2mY0YYwXSZRsgcCeerUwxMwNixGA7aMLkVmPTYBl7gJoZDHOZyXkqPrtuDT3s2B1A+RLI7WxSdQ==",
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.8.0.tgz",
|
||||
"integrity": "sha512-MlCPeM0Sm3pS9RACRihx70VeTHmkQwa7sum9EK1tfw1VZyvFU0dBWym9nHh3CRkTRNlyNm/WFCMvuh9zXkOjNw==",
|
||||
"requires": {
|
||||
"camelize": "1.0.0",
|
||||
"content-security-policy-builder": "2.0.0",
|
||||
"content-security-policy-builder": "2.1.0",
|
||||
"dasherize": "2.0.0",
|
||||
"platform": "1.3.5"
|
||||
}
|
||||
@ -9701,23 +9737,6 @@
|
||||
"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": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
|
||||
@ -10875,13 +10894,11 @@
|
||||
}
|
||||
},
|
||||
"read-config-file": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-4.0.1.tgz",
|
||||
"integrity": "sha512-5caED3uo2IAZMPcbh/9hx/O29s2430RLxtnFDdzxpH/epEpawOrQnGBHueotIXUrGPPIgdNQN+S/CIp2WmiSfw==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-5.0.0.tgz",
|
||||
"integrity": "sha512-jIKUu+C84bfnKxyJ5j30CxCqgXWYjZLXuVE/NYlMEpeni+dhESgAeZOZd0JZbg1xTkMmnCdxksDoarkOyfEsOg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.10.1",
|
||||
"ajv-keywords": "^3.4.1",
|
||||
"dotenv": "^8.0.0",
|
||||
"dotenv-expand": "^5.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
@ -10890,30 +10907,12 @@
|
||||
"lazy-val": "^1.0.4"
|
||||
},
|
||||
"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": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"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": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
@ -10923,12 +10922,6 @@
|
||||
"argparse": "^1.0.7",
|
||||
"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": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
|
||||
"integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A=="
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"semver-diff": {
|
||||
"version": "2.1.0",
|
||||
|
@ -40,7 +40,7 @@
|
||||
"express-session": "1.16.2",
|
||||
"file-type": "12.0.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"helmet": "3.19.0",
|
||||
"helmet": "3.20.0",
|
||||
"html": "1.0.0",
|
||||
"html2plaintext": "2.1.2",
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
@ -64,7 +64,7 @@
|
||||
"rimraf": "2.6.3",
|
||||
"sanitize-filename": "1.6.1",
|
||||
"sax": "1.2.4",
|
||||
"semver": "6.2.0",
|
||||
"semver": "6.3.0",
|
||||
"serve-favicon": "2.5.0",
|
||||
"session-file-store": "1.3.1",
|
||||
"simple-node-logger": "18.12.23",
|
||||
@ -79,7 +79,7 @@
|
||||
"devDependencies": {
|
||||
"devtron": "1.4.0",
|
||||
"electron": "6.0.0-beta.14",
|
||||
"electron-builder": "21.1.1",
|
||||
"electron-builder": "21.1.5",
|
||||
"electron-compile": "6.4.4",
|
||||
"electron-installer-debian": "2.0.0",
|
||||
"electron-packager": "14.0.2",
|
||||
|
@ -42,6 +42,7 @@ import noteAutocompleteService from './services/note_autocomplete.js';
|
||||
import macInit from './services/mac_init.js';
|
||||
import cssLoader from './services/css_loader.js';
|
||||
import dateNoteService from './services/date_notes.js';
|
||||
import sidebarService from './services/sidebar.js';
|
||||
|
||||
window.glob.isDesktop = utils.isDesktop;
|
||||
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 protectedSessionService from "./protected_session.js";
|
||||
import linkService from "./link.js";
|
||||
import Sidebar from "./sidebar.js";
|
||||
|
||||
const $tabContentsContainer = $("#note-tab-container");
|
||||
|
||||
@ -61,6 +62,7 @@ class TabContext {
|
||||
this.attributes = new Attributes(this);
|
||||
|
||||
if (utils.isDesktop()) {
|
||||
this.sidebar = new Sidebar(this);
|
||||
this.noteType = new NoteTypeContext(this);
|
||||
}
|
||||
|
||||
@ -131,6 +133,10 @@ class TabContext {
|
||||
|
||||
this.showPaths();
|
||||
|
||||
if (this.sidebar) {
|
||||
this.sidebar.noteLoaded();
|
||||
}
|
||||
|
||||
console.debug(`Switched tab ${this.tabId} to ${this.noteId}`);
|
||||
}
|
||||
|
||||
|
@ -69,10 +69,19 @@ class TabRow {
|
||||
}
|
||||
|
||||
setupEvents() {
|
||||
window.addEventListener('resize', _ => {
|
||||
const resizeListener = _ => {
|
||||
this.cleanUpPreviouslyDraggedTabs();
|
||||
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));
|
||||
}
|
||||
|
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;
|
||||
}
|
||||
|
||||
body {
|
||||
/* FF basic styling */
|
||||
scrollbar-color: var(--active-item-background-color) var(--main-background-color);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
}
|
||||
@ -142,8 +147,12 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
|
||||
border: 1px solid var(--main-border-color);
|
||||
}
|
||||
|
||||
#note-info-table td, #note-info-table th {
|
||||
padding: 15px;
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.widget .note-info-table td, .widget .note-info-table th {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
[data-toggle="tooltip"] span {
|
||||
|
@ -1,10 +1,10 @@
|
||||
#link-map-container {
|
||||
.link-map-container {
|
||||
position: relative;
|
||||
height: calc(95vh - 130px);
|
||||
height: 300px;
|
||||
outline: none; /* remove dotted outline on click */
|
||||
}
|
||||
|
||||
#link-map-container .note-box {
|
||||
.link-map-container .note-box {
|
||||
padding: 8px;
|
||||
position: absolute !important;
|
||||
background-color: var(--accented-background-color);
|
||||
@ -23,16 +23,16 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#link-map-container .note-box:hover {
|
||||
.link-map-container .note-box:hover {
|
||||
background-color: var(--more-accented-background-color);
|
||||
}
|
||||
|
||||
#link-map-container .note-box .title {
|
||||
.link-map-container .note-box .title {
|
||||
font-size: larger;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#link-map-container .floating-button {
|
||||
.link-map-container .floating-button {
|
||||
position: absolute !important;
|
||||
z-index: 100;
|
||||
}
|
||||
|
@ -103,11 +103,64 @@ ul.fancytree-container {
|
||||
}
|
||||
|
||||
.note-tab-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.note-detail-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
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 {
|
||||
flex-grow: 100;
|
||||
position: relative;
|
||||
|
@ -19,14 +19,21 @@ async function getLinks(noteIds, linkTypes) {
|
||||
|
||||
async function getLinkMap(req) {
|
||||
const {noteId} = req.params;
|
||||
const {linkTypes, maxNotes} = req.body;
|
||||
const {linkTypes, maxNotes, maxDepth} = req.body;
|
||||
|
||||
let noteIds = new Set([noteId]);
|
||||
let links = [];
|
||||
|
||||
let depth = 0;
|
||||
|
||||
while (true) {
|
||||
const newLinks = await getLinks(noteIds, linkTypes);
|
||||
const newNoteIds = new Set(newLinks.map(l => l.noteId).concat(newLinks.map(l => l.targetNoteId)));
|
||||
links = await getLinks(noteIds, linkTypes);
|
||||
|
||||
if (depth === maxDepth) {
|
||||
break;
|
||||
}
|
||||
|
||||
const newNoteIds = new Set(links.map(l => l.noteId).concat(links.map(l => l.targetNoteId)));
|
||||
|
||||
if (newNoteIds.size === noteIds.size) {
|
||||
// no new note discovered, no need to search any further
|
||||
@ -39,7 +46,8 @@ async function getLinkMap(req) {
|
||||
}
|
||||
|
||||
noteIds = newNoteIds;
|
||||
links = newLinks;
|
||||
|
||||
depth++;
|
||||
}
|
||||
|
||||
// keep only links coming from and targetting some note in the noteIds set
|
||||
|
@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const sql = require('./sql');
|
||||
const log = require('./log');
|
||||
const sqlInit = require('./sql_init');
|
||||
const utils = require('./utils');
|
||||
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
|
||||
async function checkApiAuthOrElectron(req, res, next) {
|
||||
if (!req.session.loggedIn && !utils.isElectron()) {
|
||||
res.status(401).send("Not authorized");
|
||||
reject(req, res, "Not authorized");
|
||||
}
|
||||
else {
|
||||
next();
|
||||
@ -31,7 +32,7 @@ async function checkApiAuthOrElectron(req, res, next) {
|
||||
|
||||
async function checkApiAuth(req, res, next) {
|
||||
if (!req.session.loggedIn) {
|
||||
res.status(401).send("Not authorized");
|
||||
reject(req, res, "Not authorized");
|
||||
}
|
||||
else {
|
||||
next();
|
||||
@ -49,7 +50,7 @@ async function checkAppInitialized(req, res, next) {
|
||||
|
||||
async function checkAppNotInitialized(req, res, next) {
|
||||
if (await sqlInit.isDbInitialized()) {
|
||||
res.status(400).send("App already initialized.");
|
||||
reject(req, res, "App already initialized.");
|
||||
}
|
||||
else {
|
||||
next();
|
||||
@ -60,13 +61,19 @@ async function checkToken(req, res, next) {
|
||||
const token = req.headers.authorization;
|
||||
|
||||
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 {
|
||||
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) {
|
||||
const header = req.headers.authorization || '';
|
||||
const token = header.split(/\s+/).pop() || '';
|
||||
|
@ -6,7 +6,7 @@
|
||||
</head>
|
||||
<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>
|
||||
<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="history-navigation" style="display: none;">
|
||||
<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 id="left-pane" class="hide-toggle">
|
||||
<div id="left-pane" class="hide-toggle" style="resize: horizontal; overflow: scroll;">
|
||||
<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>
|
||||
|
||||
|
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,42 +4,46 @@
|
||||
|
||||
<div id="note-tab-container">
|
||||
<div class="note-tab-content note-tab-content-template">
|
||||
<% include title.ejs %>
|
||||
<div class="note-detail-content">
|
||||
<% include title.ejs %>
|
||||
|
||||
<div class="note-detail-script-area"></div>
|
||||
<div class="note-detail-script-area"></div>
|
||||
|
||||
<table class="note-detail-promoted-attributes"></table>
|
||||
<table class="note-detail-promoted-attributes"></table>
|
||||
|
||||
<div class="note-detail-component-wrapper">
|
||||
<div class="note-detail-text note-detail-component">
|
||||
<div class="note-detail-text-editor" tabindex="10000"></div>
|
||||
<div class="note-detail-component-wrapper">
|
||||
<div class="note-detail-text note-detail-component">
|
||||
<div class="note-detail-text-editor" tabindex="10000"></div>
|
||||
</div>
|
||||
|
||||
<div class="note-detail-code note-detail-component">
|
||||
<div class="note-detail-code-editor"></div>
|
||||
</div>
|
||||
|
||||
<% include details/empty.ejs %>
|
||||
|
||||
<% include details/search.ejs %>
|
||||
|
||||
<% include details/render.ejs %>
|
||||
|
||||
<% include details/file.ejs %>
|
||||
|
||||
<% include details/image.ejs %>
|
||||
|
||||
<% include details/relation_map.ejs %>
|
||||
|
||||
<% include details/protected_session_password.ejs %>
|
||||
|
||||
<div class="children-overview hide-toggle"></div>
|
||||
</div>
|
||||
|
||||
<div class="note-detail-code note-detail-component">
|
||||
<div class="note-detail-code-editor"></div>
|
||||
<div class="attribute-list">
|
||||
<button class="btn btn-sm show-attributes-button">Attributes:</button>
|
||||
|
||||
<span class="attribute-list-inner"></span>
|
||||
</div>
|
||||
|
||||
<% include details/empty.ejs %>
|
||||
|
||||
<% include details/search.ejs %>
|
||||
|
||||
<% include details/render.ejs %>
|
||||
|
||||
<% include details/file.ejs %>
|
||||
|
||||
<% include details/image.ejs %>
|
||||
|
||||
<% include details/relation_map.ejs %>
|
||||
|
||||
<% include details/protected_session_password.ejs %>
|
||||
|
||||
<div class="children-overview hide-toggle"></div>
|
||||
</div>
|
||||
|
||||
<div class="attribute-list">
|
||||
<button class="btn btn-sm show-attributes-button">Attributes:</button>
|
||||
|
||||
<span class="attribute-list-inner"></span>
|
||||
</div>
|
||||
<% include sidebar.ejs %>
|
||||
</div>
|
||||
</div>
|
@ -73,6 +73,8 @@
|
||||
<a class="dropdown-item show-note-info-button">Note info</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm icon-button jam jam-chevron-left show-sidebar-button" title="Show sidebar"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user