mirror of
https://github.com/zadam/trilium.git
synced 2025-10-27 16:26:31 +01:00
Compare commits
38 Commits
v0.36.1-be
...
v0.36.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8730f1722 | ||
|
|
72fda89360 | ||
|
|
7075842954 | ||
|
|
a2c78e2c5c | ||
|
|
9c9ef1c7b4 | ||
|
|
df40accdd4 | ||
|
|
b67aa99b86 | ||
|
|
fcb6a06d68 | ||
|
|
f7c59700a5 | ||
|
|
f1a7fce277 | ||
|
|
1a182d1b58 | ||
|
|
8bd52f349a | ||
|
|
68faa47c6f | ||
|
|
2f2a14d4b8 | ||
|
|
a2a53deb94 | ||
|
|
d50e072ea4 | ||
|
|
904eb25f64 | ||
|
|
205081c804 | ||
|
|
c4d5060a0b | ||
|
|
5bba18191f | ||
|
|
5e3538669d | ||
|
|
23c449ca0c | ||
|
|
b7344329f4 | ||
|
|
e04845335b | ||
|
|
86a330c8c3 | ||
|
|
f82e99b5ed | ||
|
|
bdf42749f3 | ||
|
|
7ccbf45569 | ||
|
|
c0b30e603a | ||
|
|
d3c957768f | ||
|
|
ed9ecf2a57 | ||
|
|
22d48b0586 | ||
|
|
edc23940d0 | ||
|
|
c72ea2ed60 | ||
|
|
4570319517 | ||
|
|
69d739400c | ||
|
|
ec7c0f0723 | ||
|
|
3de124748d |
@@ -1,4 +1,4 @@
|
||||
FROM node:12.12.0-alpine
|
||||
FROM node:12.13.0-alpine
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
@@ -47,4 +47,11 @@ Or clone locally and run
|
||||
```
|
||||
npm install
|
||||
npm run start-server
|
||||
```
|
||||
```
|
||||
|
||||
## Shoutouts
|
||||
|
||||
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - best WYSIWYG editor on the market, very interactive and listening team
|
||||
* [FancyTree](https://github.com/mar10/fancytree) - very feature rich tree library without real competition. Trilium Notes would not be the same without it.
|
||||
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages
|
||||
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library without competition. Used in [relation maps](https://github.com/zadam/trilium/wiki/Relation-map) and [link maps](https://github.com/zadam/trilium/wiki/Link-map)
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PKG_DIR=dist/trilium-linux-x64-server
|
||||
NODE_VERSION=12.12.0
|
||||
NODE_VERSION=12.13.0
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
|
||||
@@ -15,6 +15,7 @@ rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/giflossy/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/keyboard-layout/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/cld/build/Release/*
|
||||
|
||||
cp -r bin/deps/win-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/win-x64/image/cjpeg.exe $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
echo "Deleting existing builds"
|
||||
|
||||
rm -r dist/*
|
||||
rm -rf dist/*
|
||||
|
||||
SRC_DIR=dist/trilium-src
|
||||
|
||||
|
||||
@@ -73,6 +73,10 @@ class Branch extends Entity {
|
||||
this.notePosition = maxNotePos === null ? 0 : maxNotePos + 10;
|
||||
}
|
||||
|
||||
if (!this.isExpanded) {
|
||||
this.isExpanded = false;
|
||||
}
|
||||
|
||||
if (!this.isDeleted) {
|
||||
this.isDeleted = false;
|
||||
}
|
||||
|
||||
@@ -1240,6 +1240,162 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="bindGlobalShortcut"><span class="type-signature"></span>bindGlobalShortcut<span class="signature">(keyboardShortcut, handler)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>keyboardShortcut</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">e.g. "ctrl+shift+a"</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>handler</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">function</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line368">line 368</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1390,7 +1546,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line279">line 279</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line275">line 275</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1523,7 +1679,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line239">line 239</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line235">line 235</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1629,7 +1785,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line285">line 285</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line281">line 281</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1735,7 +1891,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line291">line 291</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line287">line 287</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1894,7 +2050,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line338">line 338</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line334">line 334</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2001,7 +2157,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line232">line 232</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line228">line 228</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2156,7 +2312,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line347">line 347</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line343">line 343</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2619,7 +2775,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line329">line 329</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line325">line 325</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2774,7 +2930,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line356">line 356</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line352">line 352</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2883,7 +3039,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line302">line 302</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line298">line 298</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3038,7 +3194,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line310">line 310</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line306">line 306</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3171,7 +3327,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line246">line 246</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line242">line 242</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3277,7 +3433,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line321">line 321</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line317">line 317</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3365,7 +3521,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line270">line 270</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line266">line 266</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3419,13 +3575,17 @@ note.
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="reloadNotesAndTheirChildren"><span class="type-signature"></span>reloadNotesAndTheirChildren<span class="signature">(noteId)</span><span class="type-signature"></span></h4>
|
||||
<h4 class="name" id="reloadNotes"><span class="type-signature"></span>reloadNotes<span class="signature">(noteIds)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Update frontend tree (note) cache from the backend.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3459,13 +3619,13 @@ note.
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>noteId</code></td>
|
||||
<td class="name"><code>noteIds</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
<span class="param-type">Array.<string></span>
|
||||
|
||||
|
||||
|
||||
@@ -3516,140 +3676,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line218">line 218</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="reloadParents"><span class="type-signature"></span>reloadParents<span class="signature">(noteId)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>noteId</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line224">line 224</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line220">line 220</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4281,7 +4308,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line365">line 365</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line361">line 361</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4432,7 +4459,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line316">line 316</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line312">line 312</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4569,7 +4596,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line262">line 262</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line258">line 258</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4706,7 +4733,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line254">line 254</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line250">line 250</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<header>
|
||||
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>NoteShort<span class="signature">()</span><span class="type-signature"></span></h2>
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>NoteShort<span class="signature">(treeCache, row, branches)</span><span class="type-signature"></span></h2>
|
||||
|
||||
<div class="class-description">FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache.
|
||||
Attribute cache should be limited to "transaction".
|
||||
@@ -48,7 +48,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="NoteShort"><span class="type-signature"></span>new NoteShort<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
<h4 class="name" id="NoteShort"><span class="type-signature"></span>new NoteShort<span class="signature">(treeCache, row, branches)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,101 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>treeCache</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">TreeCache</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>row</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object.<string, Object></span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>branches</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Array.<<a href="Branch.html">Branch</a>></span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">all relevant branches, i.e. where this note is either child or parent</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +191,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line16">line 16</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line22">line 22</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -186,7 +281,143 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line29">line 29</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line37">line 37</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="children"><span class="type-signature"></span>children<span class="type-signature"> :Array.<string></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Type:</h5>
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
<span class="param-type">Array.<string></span>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line44">line 44</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="childToBranch"><span class="type-signature"></span>childToBranch<span class="type-signature"> :Object.<string, string></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Type:</h5>
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
<span class="param-type">Object.<string, string></span>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line50">line 50</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -244,7 +475,65 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line31">line 31</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line39">line 39</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="isDeleted"><span class="type-signature"></span>isDeleted<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line35">line 35</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -302,7 +591,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line23">line 23</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line29">line 29</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -360,7 +649,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line27">line 27</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line33">line 33</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -418,7 +707,143 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line19">line 19</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line25">line 25</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="parents"><span class="type-signature"></span>parents<span class="type-signature"> :Array.<string></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Type:</h5>
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
<span class="param-type">Array.<string></span>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line42">line 42</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="parentToBranch"><span class="type-signature"></span>parentToBranch<span class="type-signature"> :Object.<string, string></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Type:</h5>
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
<span class="param-type">Object.<string, string></span>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line47">line 47</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -476,7 +901,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line21">line 21</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line27">line 27</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -534,7 +959,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line25">line 25</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line31">line 31</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -682,7 +1107,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line169">line 169</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line220">line 220</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -849,7 +1274,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line109">line 109</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line160">line 160</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1023,7 +1448,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line180">line 180</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line231">line 231</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1129,7 +1554,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line60">line 60</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line117">line 117</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1231,7 +1656,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line74">line 74</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line129">line 129</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1333,7 +1758,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line96">line 96</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line147">line 147</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1435,7 +1860,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line101">line 101</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line152">line 152</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1586,7 +2011,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line202">line 202</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line253">line 253</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1753,7 +2178,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line135">line 135</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line186">line 186</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1920,7 +2345,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line127">line 127</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line178">line 178</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2075,7 +2500,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line214">line 214</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line265">line 265</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2181,7 +2606,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line86">line 86</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line137">line 137</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2283,7 +2708,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line91">line 91</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line142">line 142</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2434,7 +2859,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line208">line 208</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line259">line 259</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2601,7 +3026,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line151">line 151</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line202">line 202</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2768,7 +3193,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line143">line 143</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line194">line 194</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2923,7 +3348,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line226">line 226</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line277">line 277</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3093,7 +3518,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line236">line 236</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line287">line 287</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3244,7 +3669,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line220">line 220</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line271">line 271</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3354,7 +3779,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line260">line 260</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line311">line 311</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3528,7 +3953,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line160">line 160</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line211">line 211</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3634,7 +4059,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line68">line 68</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line124">line 124</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3785,7 +4210,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line190">line 190</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line241">line 241</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3940,7 +4365,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line196">line 196</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line247">line 247</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4051,7 +4476,7 @@ Cache is note instance scoped.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line251">line 251</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line302">line 302</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4135,7 +4560,7 @@ Cache is note instance scoped.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line35">line 35</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line92">line 92</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
* Represents full note, specifically including note's content.
|
||||
*/
|
||||
class NoteFull extends NoteShort {
|
||||
constructor(treeCache, row) {
|
||||
super(treeCache, row);
|
||||
constructor(treeCache, row, noteShort) {
|
||||
super(treeCache, row, []);
|
||||
|
||||
/** @param {string} */
|
||||
this.content = row.content;
|
||||
@@ -49,6 +49,12 @@ class NoteFull extends NoteShort {
|
||||
|
||||
/** @param {string} */
|
||||
this.utcDateModified = row.utcDateModified;
|
||||
|
||||
/* ugly */
|
||||
this.parents = noteShort.parents;
|
||||
this.parentToBranch = noteShort.parentToBranch;
|
||||
this.children = noteShort.children;
|
||||
this.childToBranch = noteShort.childToBranch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import server from '../services/server.js';
|
||||
import Attribute from './attribute.js';
|
||||
import branches from "../services/branches.js";
|
||||
|
||||
const LABEL = 'label';
|
||||
const LABEL_DEFINITION = 'label-definition';
|
||||
@@ -41,7 +42,12 @@ const RELATION_DEFINITION = 'relation-definition';
|
||||
* This note's representation is used in note tree and is kept in TreeCache.
|
||||
*/
|
||||
class NoteShort {
|
||||
constructor(treeCache, row) {
|
||||
/**
|
||||
* @param {TreeCache} treeCache
|
||||
* @param {Object.<string, Object>} row
|
||||
* @param {Branch[]} branches - all relevant branches, i.e. where this note is either child or parent
|
||||
*/
|
||||
constructor(treeCache, row, branches) {
|
||||
this.treeCache = treeCache;
|
||||
/** @param {string} */
|
||||
this.noteId = row.noteId;
|
||||
@@ -54,9 +60,60 @@ class NoteShort {
|
||||
/** @param {string} content-type, e.g. "application/json" */
|
||||
this.mime = row.mime;
|
||||
/** @param {boolean} */
|
||||
this.isDeleted = row.isDeleted;
|
||||
/** @param {boolean} */
|
||||
this.archived = row.archived;
|
||||
/** @param {string} */
|
||||
this.cssClass = row.cssClass;
|
||||
|
||||
/** @type {string[]} */
|
||||
this.parents = [];
|
||||
/** @type {string[]} */
|
||||
this.children = [];
|
||||
|
||||
/** @type {Object.<string, string>} */
|
||||
this.parentToBranch = {};
|
||||
|
||||
/** @type {Object.<string, string>} */
|
||||
this.childToBranch = {};
|
||||
|
||||
for (const branch of branches) {
|
||||
if (this.noteId === branch.noteId) {
|
||||
this.parents.push(branch.parentNoteId);
|
||||
this.parentToBranch[branch.parentNoteId] = branch.branchId;
|
||||
}
|
||||
else if (this.noteId === branch.parentNoteId) {
|
||||
this.children.push(branch.noteId);
|
||||
this.childToBranch[branch.noteId] = branch.branchId;
|
||||
}
|
||||
else {
|
||||
throw new Error(`Unknown branch ${branch.branchId} for note ${this.noteId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addParent(parentNoteId, branchId) {
|
||||
if (!this.parents.includes(parentNoteId)) {
|
||||
this.parents.push(parentNoteId);
|
||||
}
|
||||
|
||||
this.parentToBranch[parentNoteId] = branchId;
|
||||
}
|
||||
|
||||
addChild(childNoteId, branchId) {
|
||||
if (!this.children.includes(childNoteId)) {
|
||||
this.children.push(childNoteId);
|
||||
}
|
||||
|
||||
this.childToBranch[childNoteId] = branchId;
|
||||
|
||||
const branchIdPos = {};
|
||||
|
||||
for (const branchId of Object.values(this.childToBranch)) {
|
||||
branchIdPos[branchId] = this.treeCache.getBranch(branchId).notePosition;
|
||||
}
|
||||
|
||||
this.children.sort((a, b) => branchIdPos[this.childToBranch[a]] < branchIdPos[this.childToBranch[b]] ? -1 : 1);
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
@@ -86,48 +143,42 @@ class NoteShort {
|
||||
|
||||
/** @returns {Promise<Branch[]>} */
|
||||
async getBranches() {
|
||||
const branchIds = this.treeCache.parents[this.noteId].map(
|
||||
parentNoteId => this.treeCache.getBranchIdByChildParent(this.noteId, parentNoteId));
|
||||
const branchIds = Object.values(this.parentToBranch);
|
||||
|
||||
return this.treeCache.getBranches(branchIds);
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
hasChildren() {
|
||||
return this.treeCache.children[this.noteId]
|
||||
&& this.treeCache.children[this.noteId].length > 0;
|
||||
return this.children.length > 0;
|
||||
}
|
||||
|
||||
/** @returns {Promise<Branch[]>} */
|
||||
async getChildBranches() {
|
||||
if (!this.treeCache.children[this.noteId]) {
|
||||
return [];
|
||||
}
|
||||
// don't use Object.values() to guarantee order
|
||||
const branchIds = this.children.map(childNoteId => this.childToBranch[childNoteId]);
|
||||
|
||||
const branchIds = this.treeCache.children[this.noteId].map(
|
||||
childNoteId => this.treeCache.getBranchIdByChildParent(childNoteId, this.noteId));
|
||||
|
||||
return await this.treeCache.getBranches(branchIds);
|
||||
return this.treeCache.getBranches(branchIds);
|
||||
}
|
||||
|
||||
/** @returns {string[]} */
|
||||
getParentNoteIds() {
|
||||
return this.treeCache.parents[this.noteId] || [];
|
||||
return this.parents;
|
||||
}
|
||||
|
||||
/** @returns {Promise<NoteShort[]>} */
|
||||
async getParentNotes() {
|
||||
return await this.treeCache.getNotes(this.getParentNoteIds());
|
||||
return await this.treeCache.getNotes(this.parents);
|
||||
}
|
||||
|
||||
/** @returns {string[]} */
|
||||
getChildNoteIds() {
|
||||
return this.treeCache.children[this.noteId] || [];
|
||||
return this.children;
|
||||
}
|
||||
|
||||
/** @returns {Promise<NoteShort[]>} */
|
||||
async getChildNotes() {
|
||||
return await this.treeCache.getNotes(this.getChildNoteIds());
|
||||
return await this.treeCache.getNotes(this.children);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -240,16 +240,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
this.getNotes = async (noteIds, silentNotFoundError = false) => await treeCache.getNotes(noteIds, silentNotFoundError);
|
||||
|
||||
/**
|
||||
* @param {string} noteId
|
||||
* Update frontend tree (note) cache from the backend.
|
||||
*
|
||||
* @param {string[]} noteIds
|
||||
* @method
|
||||
*/
|
||||
this.reloadNotesAndTheirChildren = async noteId => await treeCache.reloadNotesAndTheirChildren(noteId);
|
||||
|
||||
/**
|
||||
* @param {string} noteId
|
||||
* @method
|
||||
*/
|
||||
this.reloadParents = async noteId => await treeCache.reloadParents(noteId);
|
||||
this.reloadNotes = async noteIds => await treeCache.reloadNotes(noteIds);
|
||||
|
||||
/**
|
||||
* Instance name identifies particular Trilium instance. It can be useful for scripts
|
||||
@@ -391,6 +387,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.setHoistedNoteId = hoistedNoteService.setHoistedNoteId;
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @param {string} keyboardShortcut - e.g. "ctrl+shift+a"
|
||||
* @param {function} handler
|
||||
*/
|
||||
this.bindGlobalShortcut = utils.bindGlobalShortcut;
|
||||
}
|
||||
|
||||
export default FrontendScriptApi;</code></pre>
|
||||
|
||||
4
libraries/autocomplete.jquery.min.js
vendored
4
libraries/autocomplete.jquery.min.js
vendored
File diff suppressed because one or more lines are too long
2
libraries/ckeditor/ckeditor.js
vendored
2
libraries/ckeditor/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
/*! jQuery Fancytree Plugin - 2.32.0 - 2019-09-10T07:42:12Z
|
||||
/*! jQuery Fancytree Plugin - 2.33.0 - 2019-10-29T08:00:07Z
|
||||
* https://github.com/mar10/fancytree
|
||||
* Copyright (c) 2019 Martin Wendt; Licensed MIT
|
||||
*/
|
||||
@@ -1365,8 +1365,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
/** Core Fancytree module.
|
||||
@@ -2947,15 +2947,7 @@ var uniqueId = $.fn.extend( {
|
||||
// i.e. return false for nodes (but not parents) that are hidden
|
||||
// by a filter
|
||||
if (hasFilter && !this.match && !this.subMatchCount) {
|
||||
this.debug(
|
||||
"isVisible: HIDDEN (" +
|
||||
hasFilter +
|
||||
", " +
|
||||
this.match +
|
||||
", " +
|
||||
this.match +
|
||||
")"
|
||||
);
|
||||
// this.debug( "isVisible: HIDDEN (" + hasFilter + ", " + this.match + ", " + this.match + ")" );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2963,7 +2955,7 @@ var uniqueId = $.fn.extend( {
|
||||
n = parents[i];
|
||||
|
||||
if (!n.expanded) {
|
||||
this.debug("isVisible: HIDDEN (parent collapsed)");
|
||||
// this.debug("isVisible: HIDDEN (parent collapsed)");
|
||||
return false;
|
||||
}
|
||||
// if (hasFilter && !n.match && !n.subMatchCount) {
|
||||
@@ -2971,7 +2963,7 @@ var uniqueId = $.fn.extend( {
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
this.debug("isVisible: VISIBLE");
|
||||
// this.debug("isVisible: VISIBLE");
|
||||
return true;
|
||||
},
|
||||
/** Deprecated.
|
||||
@@ -4788,6 +4780,10 @@ var uniqueId = $.fn.extend( {
|
||||
},
|
||||
/**
|
||||
* Return an array of selected nodes.
|
||||
*
|
||||
* Note: you cannot send this result via Ajax directly. Instead the
|
||||
* node object need to be converted to plain objects, for example
|
||||
* by using `$.map()` and `node.toDict()`.
|
||||
* @param {boolean} [stopOnParents=false] only return the topmost selected
|
||||
* node (useful with selectMode 3)
|
||||
* @returns {FancytreeNode[]}
|
||||
@@ -6714,7 +6710,13 @@ var uniqueId = $.fn.extend( {
|
||||
dfd.done(function() {
|
||||
var lastChild = node.getLastChild();
|
||||
|
||||
if (flag && opts.autoScroll && !noAnimation && lastChild) {
|
||||
if (
|
||||
flag &&
|
||||
opts.autoScroll &&
|
||||
!noAnimation &&
|
||||
lastChild &&
|
||||
tree._enableUpdate
|
||||
) {
|
||||
// Scroll down to last child, but keep current node visible
|
||||
lastChild
|
||||
.scrollIntoView(true, { topNode: node })
|
||||
@@ -6773,9 +6775,7 @@ var uniqueId = $.fn.extend( {
|
||||
$(node.li).addClass(cn.animating); // #717
|
||||
|
||||
if ($.isFunction($(node.ul)[effect.effect])) {
|
||||
tree.debug(
|
||||
"use jquery." + effect.effect + " method"
|
||||
);
|
||||
// tree.debug( "use jquery." + effect.effect + " method" );
|
||||
$(node.ul)[effect.effect]({
|
||||
duration: effect.duration,
|
||||
always: function() {
|
||||
@@ -7263,16 +7263,30 @@ var uniqueId = $.fn.extend( {
|
||||
type = $container.data("type") || "html";
|
||||
switch (type) {
|
||||
case "html":
|
||||
$ul = $container.find(">ul").first();
|
||||
$ul.addClass(
|
||||
"ui-fancytree-source fancytree-helper-hidden"
|
||||
);
|
||||
source = $.ui.fancytree.parseHtml($ul);
|
||||
// allow to init tree.data.foo from <ul data-foo=''>
|
||||
this.data = $.extend(
|
||||
this.data,
|
||||
_getElementDataAsDict($ul)
|
||||
);
|
||||
// There should be an embedded `<ul>` with initial nodes,
|
||||
// but another `<ul class='fancytree-container'>` is appended
|
||||
// to the tree's <div> on startup anyway.
|
||||
$ul = $container
|
||||
.find(">ul")
|
||||
.not(".fancytree-container")
|
||||
.first();
|
||||
|
||||
if ($ul.length) {
|
||||
$ul.addClass(
|
||||
"ui-fancytree-source fancytree-helper-hidden"
|
||||
);
|
||||
source = $.ui.fancytree.parseHtml($ul);
|
||||
// allow to init tree.data.foo from <ul data-foo=''>
|
||||
this.data = $.extend(
|
||||
this.data,
|
||||
_getElementDataAsDict($ul)
|
||||
);
|
||||
} else {
|
||||
FT.warn(
|
||||
"No `source` option was passed and container does not contain `<ul>`: assuming `source: []`."
|
||||
);
|
||||
source = [];
|
||||
}
|
||||
break;
|
||||
case "json":
|
||||
source = $.parseJSON($container.text());
|
||||
@@ -7312,8 +7326,9 @@ var uniqueId = $.fn.extend( {
|
||||
$.error("Not implemented");
|
||||
}
|
||||
|
||||
// TODO: might be useful? Let's wait for a use case...
|
||||
// tree._triggerTreeEvent("beforeInitLoad", null);
|
||||
// preInit is fired when the widget markup is created, but nodes
|
||||
// not yet loaded
|
||||
tree._triggerTreeEvent("preInit", null);
|
||||
|
||||
// Trigger fancytreeinit after nodes have been loaded
|
||||
dfd = this.nodeLoadChildren(rootCtx, source)
|
||||
@@ -7927,7 +7942,7 @@ var uniqueId = $.fn.extend( {
|
||||
/** @lends Fancytree_Static# */
|
||||
{
|
||||
/** @type {string} */
|
||||
version: "2.32.0", // Set to semver by 'grunt release'
|
||||
version: "2.33.0", // Set to semver by 'grunt release'
|
||||
/** @type {string} */
|
||||
buildType: "production", // Set to 'production' by 'grunt build'
|
||||
/** @type {int} */
|
||||
@@ -8550,8 +8565,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
// To keep the global namespace clean, we wrap everything in a closure.
|
||||
@@ -8670,7 +8685,7 @@ var uniqueId = $.fn.extend( {
|
||||
// Every extension must be registered by a unique name.
|
||||
name: "childcounter",
|
||||
// Version information should be compliant with [semver](http://semver.org)
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
|
||||
// Extension specific options and their defaults.
|
||||
// This options will be available as `tree.options.childcounter.hideExpanded`
|
||||
@@ -8781,8 +8796,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -9140,7 +9155,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "clones",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers
|
||||
@@ -9302,8 +9317,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -10123,6 +10138,7 @@ var uniqueId = $.fn.extend( {
|
||||
// ": dropEffect: " +
|
||||
// dataTransfer.dropEffect
|
||||
// );
|
||||
prepareDropEffectCallback(event, data);
|
||||
LAST_HIT_MODE = handleDragOver(event, data);
|
||||
|
||||
// The flag controls the preventDefault() below:
|
||||
@@ -10306,7 +10322,7 @@ var uniqueId = $.fn.extend( {
|
||||
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "dnd5",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
autoExpandMS: 1500, // Expand nodes after n milliseconds of hovering
|
||||
@@ -10439,8 +10455,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -10732,7 +10748,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "edit",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
adjustWidthOfs: 4, // null: don't adjust input size to content
|
||||
@@ -10843,8 +10859,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -11008,7 +11024,9 @@ var uniqueId = $.fn.extend( {
|
||||
count++;
|
||||
node.match = true;
|
||||
node.visitParents(function(p) {
|
||||
p.subMatchCount += 1;
|
||||
if (p !== node) {
|
||||
p.subMatchCount += 1;
|
||||
}
|
||||
// Expand match (unless this is no real match, but only a node in a matched branch)
|
||||
if (opts.autoExpand && !matchedByBranch && !p.expanded) {
|
||||
p.setExpanded(true, {
|
||||
@@ -11180,7 +11198,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "filter",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
autoApply: true, // Re-apply last filter if lazy data is loaded
|
||||
@@ -11300,8 +11318,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -11484,7 +11502,7 @@ var uniqueId = $.fn.extend( {
|
||||
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "glyph",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
preset: null, // 'awesome3', 'awesome4', 'bootstrap3', 'material'
|
||||
@@ -11638,8 +11656,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -11756,7 +11774,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "gridnav",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
autofocusInput: false, // Focus first embedded input if node gets activated
|
||||
@@ -11863,8 +11881,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -11893,7 +11911,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "multi",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
allowNoSelect: false, //
|
||||
@@ -11995,8 +12013,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -12196,7 +12214,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "persist",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
cookieDelimiter: "~",
|
||||
@@ -12489,8 +12507,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -12573,7 +12591,7 @@ var uniqueId = $.fn.extend( {
|
||||
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "table",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx)
|
||||
@@ -13039,8 +13057,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -13063,7 +13081,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "themeroller",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
activeClass: "ui-state-active", // Class added to active node
|
||||
@@ -13159,8 +13177,8 @@ var uniqueId = $.fn.extend( {
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
*/
|
||||
|
||||
(function(factory) {
|
||||
@@ -13290,7 +13308,7 @@ var uniqueId = $.fn.extend( {
|
||||
*/
|
||||
$.ui.fancytree.registerExtension({
|
||||
name: "wide",
|
||||
version: "2.32.0",
|
||||
version: "2.33.0",
|
||||
// Default options for this extension.
|
||||
options: {
|
||||
iconWidth: null, // Adjust this if @fancy-icon-width != "16px"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -13,8 +13,8 @@
|
||||
* Released under the MIT license
|
||||
* https://github.com/mar10/fancytree/wiki/LicenseInfo
|
||||
*
|
||||
* @version 2.32.0
|
||||
* @date 2019-09-10T07:42:12Z
|
||||
* @version 2.33.0
|
||||
* @date 2019-10-29T08:00:07Z
|
||||
******************************************************************************/
|
||||
/*------------------------------------------------------------------------------
|
||||
* Helpers
|
||||
@@ -121,7 +121,6 @@ span.fancytree-drag-helper-img,
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left;
|
||||
background-image: url("../skin-win8/icons.gif");
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -191,7 +191,7 @@
|
||||
this.addNodes.apply(this, json['nodes']);
|
||||
this.addEdges.apply(this, json['edges']);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// find the edges from node1 to node2
|
||||
@@ -479,51 +479,35 @@
|
||||
return energy;
|
||||
};
|
||||
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; // stolen from coffeescript, thanks jashkenas! ;-)
|
||||
|
||||
Springy.requestAnimationFrame = __bind(this.requestAnimationFrame ||
|
||||
this.webkitRequestAnimationFrame ||
|
||||
this.mozRequestAnimationFrame ||
|
||||
this.oRequestAnimationFrame ||
|
||||
this.msRequestAnimationFrame ||
|
||||
(function(callback, element) {
|
||||
this.setTimeout(callback, 10);
|
||||
}), this);
|
||||
|
||||
|
||||
/**
|
||||
* Start simulation if it's not running already.
|
||||
* In case it's running then the call is ignored, and none of the callbacks passed is ever executed.
|
||||
*/
|
||||
Layout.ForceDirected.prototype.start = function(render, onRenderStop, onRenderStart) {
|
||||
Layout.ForceDirected.prototype.start = function(onRenderStop) {
|
||||
var t = this;
|
||||
|
||||
if (this._started) return;
|
||||
this._started = true;
|
||||
this._stop = false;
|
||||
|
||||
if (onRenderStart !== undefined) { onRenderStart(); }
|
||||
|
||||
Springy.requestAnimationFrame(function step() {
|
||||
function step() {
|
||||
t.tick(0.03);
|
||||
|
||||
if (!t._stop && render !== undefined) {
|
||||
render();
|
||||
}
|
||||
|
||||
// stop simulation when energy of the system goes below a threshold
|
||||
if (t._stop || t.totalEnergy() < t.minEnergyThreshold) {
|
||||
t._started = false;
|
||||
if (onRenderStop !== undefined) { onRenderStop(); }
|
||||
onRenderStop();
|
||||
} else {
|
||||
Springy.requestAnimationFrame(step);
|
||||
setImmediate(step);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
step();
|
||||
};
|
||||
|
||||
Layout.ForceDirected.prototype.stop = function() {
|
||||
this._stop = true;
|
||||
}
|
||||
};
|
||||
|
||||
Layout.ForceDirected.prototype.tick = function(timestep) {
|
||||
this.applyCoulombsLaw();
|
||||
@@ -644,85 +628,35 @@
|
||||
|
||||
/**
|
||||
* Renderer handles the layout rendering loop
|
||||
* @param onRenderStop optional callback function that gets executed whenever rendering stops.
|
||||
* @param onRenderStart optional callback function that gets executed whenever rendering starts.
|
||||
* @param onRenderFrame optional callback function that gets executed after each frame is rendered.
|
||||
*/
|
||||
var Renderer = Springy.Renderer = function(layout, clear, drawEdge, drawNode, onRenderStop, onRenderStart, onRenderFrame) {
|
||||
var Renderer = Springy.Renderer = function(layout, onRenderStop) {
|
||||
this.layout = layout;
|
||||
this.clear = clear;
|
||||
this.drawEdge = drawEdge;
|
||||
this.drawNode = drawNode;
|
||||
this.onRenderStop = onRenderStop;
|
||||
this.onRenderStart = onRenderStart;
|
||||
this.onRenderFrame = onRenderFrame;
|
||||
|
||||
this.layout.graph.addGraphListener(this);
|
||||
}
|
||||
};
|
||||
|
||||
Renderer.prototype.graphChanged = function(e) {
|
||||
Renderer.prototype.graphChanged = function() {
|
||||
this.start();
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the simulation of the layout in use.
|
||||
*
|
||||
* Note that in case the algorithm is still or already running then the layout that's in use
|
||||
* might silently ignore the call, and your optional <code>done</code> callback is never executed.
|
||||
* At least the built-in ForceDirected layout behaves in this way.
|
||||
*
|
||||
* @param done An optional callback function that gets executed when the springy algorithm stops,
|
||||
* either because it ended or because stop() was called.
|
||||
*/
|
||||
Renderer.prototype.start = function(done) {
|
||||
var t = this;
|
||||
this.layout.start(function render() {
|
||||
t.clear();
|
||||
Renderer.prototype.start = function(maxTime) {
|
||||
if (maxTime) {
|
||||
setTimeout(() => this.stop(), maxTime);
|
||||
}
|
||||
|
||||
t.layout.eachEdge(function(edge, spring) {
|
||||
t.drawEdge(edge, spring.point1.p, spring.point2.p);
|
||||
});
|
||||
|
||||
t.layout.eachNode(function(node, point) {
|
||||
t.drawNode(node, point.p);
|
||||
});
|
||||
|
||||
if (t.onRenderFrame !== undefined) { t.onRenderFrame(); }
|
||||
}, this.onRenderStop, this.onRenderStart);
|
||||
return new Promise((res, rej) => {
|
||||
this.layout.start(res);
|
||||
});
|
||||
};
|
||||
|
||||
Renderer.prototype.stop = function() {
|
||||
this.layout.stop();
|
||||
};
|
||||
|
||||
// Array.forEach implementation for IE support..
|
||||
//https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach
|
||||
if ( !Array.prototype.forEach ) {
|
||||
Array.prototype.forEach = function( callback, thisArg ) {
|
||||
var T, k;
|
||||
if ( this == null ) {
|
||||
throw new TypeError( " this is null or not defined" );
|
||||
}
|
||||
var O = Object(this);
|
||||
var len = O.length >>> 0; // Hack to convert O.length to a UInt32
|
||||
if ( {}.toString.call(callback) != "[object Function]" ) {
|
||||
throw new TypeError( callback + " is not a function" );
|
||||
}
|
||||
if ( thisArg ) {
|
||||
T = thisArg;
|
||||
}
|
||||
k = 0;
|
||||
while( k < len ) {
|
||||
var kValue;
|
||||
if ( k in O ) {
|
||||
kValue = O[ k ];
|
||||
callback.call( T, kValue, k, O );
|
||||
}
|
||||
k++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var isEmpty = function(obj) {
|
||||
for (var k in obj) {
|
||||
if (obj.hasOwnProperty(k)) {
|
||||
|
||||
515
package-lock.json
generated
515
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.36.0-beta",
|
||||
"version": "0.36.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -106,14 +106,16 @@
|
||||
}
|
||||
},
|
||||
"@electron/get": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.5.0.tgz",
|
||||
"integrity": "sha512-tafxBz6n08G6SX961F/h8XFtpB/DdwRvJJoDeOH9x78jDSCMQ2G/rRWqSwLFp9oeMFBJf0Pf5Kkw6TKt5w9TWg==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.6.0.tgz",
|
||||
"integrity": "sha512-xuvAzbN9iBApfAMvW0hKUpxHR5wPVbG9RaoSTbpu/WaHISDu0MVfMWYhfeU0X730CpBV0G2RkLgwAs9WDan3GA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"env-paths": "^2.2.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"global-agent": "^2.0.2",
|
||||
"global-tunnel-ng": "^2.7.1",
|
||||
"got": "^9.6.0",
|
||||
"sanitize-filename": "^1.6.2",
|
||||
"sumchecker": "^3.0.0"
|
||||
@@ -782,29 +784,29 @@
|
||||
"integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="
|
||||
},
|
||||
"app-builder-bin": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.3.tgz",
|
||||
"integrity": "sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg==",
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.4.tgz",
|
||||
"integrity": "sha512-Xib+wgdK+8zZhbZr5pma3pNB23Y4JRY5Yt6h8peou6MTFSQzXdIkqalh/ezy9SMLuS43S4b0s7jTVAmUs8WVmA==",
|
||||
"dev": true
|
||||
},
|
||||
"app-builder-lib": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.2.0.tgz",
|
||||
"integrity": "sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A==",
|
||||
"version": "22.1.0",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.1.0.tgz",
|
||||
"integrity": "sha512-jDTfWsVS/MePO4FexqiSQcsWM9Yfr81ETIYbmVbKmW05o0dn9k1DvMOMoLb0kTLQpW+pWBVvGMAOPfk68HnBrg==",
|
||||
"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.2.0",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"builder-util": "22.1.0",
|
||||
"builder-util-runtime": "8.4.0",
|
||||
"chromium-pickle-js": "^0.2.0",
|
||||
"debug": "^4.1.1",
|
||||
"ejs": "^2.6.2",
|
||||
"electron-publish": "21.2.0",
|
||||
"ejs": "^2.7.1",
|
||||
"electron-publish": "22.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"hosted-git-info": "^2.7.1",
|
||||
"hosted-git-info": "^3.0.0",
|
||||
"is-ci": "^2.0.0",
|
||||
"isbinaryfile": "^4.0.2",
|
||||
"js-yaml": "^3.13.1",
|
||||
@@ -812,9 +814,20 @@
|
||||
"minimatch": "^3.0.4",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
"read-config-file": "5.0.0",
|
||||
"sanitize-filename": "^1.6.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"semver": "^6.3.0",
|
||||
"temp-file": "^3.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"hosted-git-info": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.2.tgz",
|
||||
"integrity": "sha512-ezZMWtHXm7Eb7Rq4Mwnx2vs79WUx2QmRg3+ZqeGroKzfDO+EprOcgRPYghsOP9JuYBfK18VojmRTGCg8Ma+ktw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^5.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"append-field": {
|
||||
@@ -1339,6 +1352,13 @@
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"boolean": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-2.0.2.tgz",
|
||||
"integrity": "sha512-ymsbJQlux/uogyEWfsXJUYzuyoOzPyp6NvEV71s6/ptQR7ptKO9uHF+WZL2GRATDeN52EFhNyrIu+exNZKh3Cw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"bowser": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz",
|
||||
@@ -1536,16 +1556,16 @@
|
||||
}
|
||||
},
|
||||
"builder-util": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz",
|
||||
"integrity": "sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A==",
|
||||
"version": "22.1.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.1.0.tgz",
|
||||
"integrity": "sha512-BPvpWvxQ5XOzm2WepIgmOAyo2IyaM/Bd1LJmeTYy5CtknNAtxgmAPQJfCHCikMKKQA4Obz/KYecXQiGpGJ2ThA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"7zip-bin": "~5.0.3",
|
||||
"@types/debug": "^4.1.4",
|
||||
"app-builder-bin": "3.4.3",
|
||||
"@types/debug": "^4.1.5",
|
||||
"app-builder-bin": "3.4.4",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"builder-util-runtime": "8.4.0",
|
||||
"chalk": "^2.4.2",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
@@ -1594,9 +1614,9 @@
|
||||
}
|
||||
},
|
||||
"builder-util-runtime": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz",
|
||||
"integrity": "sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw==",
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.4.0.tgz",
|
||||
"integrity": "sha512-CJB/eKfPf2vHrkmirF5eicVnbDCkMBbwd5tRYlTlgud16zFeqD7QmrVUAOEXdnsrcNkiLg9dbuUsQKtl/AwsYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
@@ -2735,6 +2755,13 @@
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
|
||||
},
|
||||
"detect-node": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
|
||||
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"dicer": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
|
||||
@@ -2790,6 +2817,108 @@
|
||||
"sanitize-filename": "^1.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"app-builder-bin": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.4.3.tgz",
|
||||
"integrity": "sha512-qMhayIwi3juerQEVJMQ76trObEbfQT0nhUdxZz9a26/3NLT3pE6awmQ8S1cEnrGugaaM5gYqR8OElcDezfmEsg==",
|
||||
"dev": true
|
||||
},
|
||||
"app-builder-lib": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-21.2.0.tgz",
|
||||
"integrity": "sha512-aOX/nv77/Bti6NymJDg7p9T067xD8m1ipIEJR7B4Mm1GsJWpMm9PZdXtCRiMNRjHtQS5KIljT0g17781y6qn5A==",
|
||||
"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.2.0",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chromium-pickle-js": "^0.2.0",
|
||||
"debug": "^4.1.1",
|
||||
"ejs": "^2.6.2",
|
||||
"electron-publish": "21.2.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"hosted-git-info": "^2.7.1",
|
||||
"is-ci": "^2.0.0",
|
||||
"isbinaryfile": "^4.0.2",
|
||||
"js-yaml": "^3.13.1",
|
||||
"lazy-val": "^1.0.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
"read-config-file": "5.0.0",
|
||||
"sanitize-filename": "^1.6.2",
|
||||
"semver": "^6.3.0",
|
||||
"temp-file": "^3.3.4"
|
||||
}
|
||||
},
|
||||
"builder-util": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-21.2.0.tgz",
|
||||
"integrity": "sha512-Nd6CUb6YgDY8EXAXEIegx+1kzKqyFQ5ZM5BoYkeunAlwz/zDJoH1UCyULjoS5wQe5czNClFQy07zz2bzYD0Z4A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"7zip-bin": "~5.0.3",
|
||||
"@types/debug": "^4.1.4",
|
||||
"app-builder-bin": "3.4.3",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chalk": "^2.4.2",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"is-ci": "^2.0.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"source-map-support": "^0.5.13",
|
||||
"stat-mode": "^0.3.0",
|
||||
"temp-file": "^3.3.4"
|
||||
}
|
||||
},
|
||||
"builder-util-runtime": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.3.0.tgz",
|
||||
"integrity": "sha512-CSOdsYqf4RXIHh1HANPbrZHlZ9JQJXSuDDloblZPcWQVN62inyYoTQuSmY3KrgefME2Sv3Kn2MxHvbGQHRf8Iw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"sax": "^1.2.4"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"electron-publish": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz",
|
||||
"integrity": "sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "~21.2.0",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"chalk": "^2.4.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
"mime": "^2.4.4"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz",
|
||||
@@ -2798,6 +2927,27 @@
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
||||
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
|
||||
"dev": true
|
||||
},
|
||||
"stat-mode": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.3.0.tgz",
|
||||
"integrity": "sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2874,9 +3024,9 @@
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.1.0.tgz",
|
||||
"integrity": "sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
|
||||
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
|
||||
"dev": true
|
||||
},
|
||||
"dotenv-expand": {
|
||||
@@ -2978,34 +3128,40 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.14.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.21.tgz",
|
||||
"integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ==",
|
||||
"version": "10.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.0.tgz",
|
||||
"integrity": "sha512-wuJwN2KV4tIRz1bu9vq5kSPasJ8IsEjZaP1ZR7KlmdUZvGF/rXy8DmXOVwUD0kAtvtJ7aqMKPqUXC0NUTDbrDg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-builder": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-21.2.0.tgz",
|
||||
"integrity": "sha512-x8EXrqFbAb2L3N22YlGar3dGh8vwptbB3ovo3OF6K7NTpcsmM2zEoJv7GhFyX73rNzSG2HaWpXwGAtOp2JWiEw==",
|
||||
"version": "22.1.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.1.0.tgz",
|
||||
"integrity": "sha512-uu2W9BLG38D0i2PG6dHupmOYc+q/TRL+Ztf8xitqK+2Quq33PFbeN0ipfySuVEDg4I6whDRBOgxBEWwnUYqZZQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"app-builder-lib": "21.2.0",
|
||||
"app-builder-lib": "22.1.0",
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "21.2.0",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"builder-util": "22.1.0",
|
||||
"builder-util-runtime": "8.4.0",
|
||||
"chalk": "^2.4.2",
|
||||
"dmg-builder": "21.2.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"is-ci": "^2.0.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
"read-config-file": "5.0.0",
|
||||
"sanitize-filename": "^1.6.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"update-notifier": "^3.0.1",
|
||||
"yargs": "^13.3.0"
|
||||
"yargs": "^14.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
@@ -3015,6 +3171,12 @@
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
@@ -3026,6 +3188,41 @@
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^7.0.1",
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
@@ -3034,6 +3231,35 @@
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.0.tgz",
|
||||
"integrity": "sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^5.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^3.0.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^3.0.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^15.0.0"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "15.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
|
||||
"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3478,12 +3704,12 @@
|
||||
}
|
||||
},
|
||||
"electron-packager": {
|
||||
"version": "14.0.6",
|
||||
"resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-14.0.6.tgz",
|
||||
"integrity": "sha512-X+ikV+TnnNkIrK93vOjsjPeykCQBFxBS7LXKMTE1s62rXWirGMdjWL+edVkBOMRkH0ROJyFmWM28Dpj6sfEg+A==",
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-14.1.0.tgz",
|
||||
"integrity": "sha512-4oGtQYYjSA/M4BGOwG0NBqEtThBf7aCV76C2AZsD71eGocYqZNvtvfzeeMnKkc3EW1nPq7iJ4Wge+GXma0kwIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@electron/get": "^1.3.0",
|
||||
"@electron/get": "^1.6.0",
|
||||
"asar": "^2.0.1",
|
||||
"cross-zip": "^2.1.5",
|
||||
"debug": "^4.0.1",
|
||||
@@ -3499,18 +3725,36 @@
|
||||
"resolve": "^1.1.6",
|
||||
"sanitize-filename": "^1.6.0",
|
||||
"semver": "^6.0.0",
|
||||
"yargs-parser": "^13.0.0"
|
||||
"yargs-parser": "^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.0.0.tgz",
|
||||
"integrity": "sha512-WyNdFYED0penIaLqLSDSeFksC5lVjrjp9vNkG7IKfgQNiAYa6FfHuJXjuaQgt0eOVN2z+gJhHJSX7uRhJKPc7Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-publish": {
|
||||
"version": "21.2.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-21.2.0.tgz",
|
||||
"integrity": "sha512-mWavuoWJe87iaeKd0I24dNWIaR+0yRzshjNVqGyK019H766fsPWl3caQJnVKFaEyrZRP397v4JZVG0e7s16AxA==",
|
||||
"version": "22.1.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.1.0.tgz",
|
||||
"integrity": "sha512-jHjMCaL2dFU+iOq8wW568F59+DW1jFJGT3vc2xqm9iXyZ8gWlQ+NVve4bq9HZG7m4iNqWbGw9StmZcOzmIBxMQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird-lst": "^1.0.9",
|
||||
"builder-util": "~21.2.0",
|
||||
"builder-util-runtime": "8.3.0",
|
||||
"builder-util": "~22.1.0",
|
||||
"builder-util-runtime": "8.4.0",
|
||||
"chalk": "^2.4.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
"lazy-val": "^1.0.4",
|
||||
@@ -3731,6 +3975,13 @@
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"es6-error": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
|
||||
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
@@ -4968,9 +5219,9 @@
|
||||
}
|
||||
},
|
||||
"file-type": {
|
||||
"version": "12.3.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-12.3.0.tgz",
|
||||
"integrity": "sha512-4E4Esq9KLwjYCY32E7qSmd0h7LefcniZHX+XcdJ4Wfx1uGJX7QCigiqw/U0yT7WOslm28yhxl87DJ0wHYv0RAA=="
|
||||
"version": "12.3.1",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-12.3.1.tgz",
|
||||
"integrity": "sha512-FXxY5h6vSYMjrRal4YqbtfuoKD/oE0AMjJ7E5Hm+BdaQECcFVD03B41RAWYJ7wyuLr/wRnCtFo7y37l+nh+TAA=="
|
||||
},
|
||||
"filename-regex": {
|
||||
"version": "2.0.1",
|
||||
@@ -5658,6 +5909,31 @@
|
||||
"process": "~0.5.1"
|
||||
}
|
||||
},
|
||||
"global-agent": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.5.tgz",
|
||||
"integrity": "sha512-pYJjCxxNBzYxo6iNO62JZn8iCFVbvpiM0zE4w/G5hBNIvLjnvzIeCVQPMKc3aK8ju5L7Q8NNI/oBSosU0eeSYw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"boolean": "^2.0.2",
|
||||
"core-js": "^3.3.3",
|
||||
"es6-error": "^4.1.1",
|
||||
"matcher": "^2.0.0",
|
||||
"roarr": "^2.14.2",
|
||||
"semver": "^6.3.0",
|
||||
"serialize-error": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "3.3.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.5.tgz",
|
||||
"integrity": "sha512-0J3K+Par/ZydhKg8pEiTcK/9d65/nqJOzY62uMkjeBmt05fDOt/khUVjDdh8TpeIuGQDy1yLDDCjiWN/8pFIuw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"global-dirs": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
|
||||
@@ -5667,12 +5943,37 @@
|
||||
"ini": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"global-tunnel-ng": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz",
|
||||
"integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"encodeurl": "^1.0.2",
|
||||
"lodash": "^4.17.10",
|
||||
"npm-conf": "^1.1.3",
|
||||
"tunnel": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||
"dev": true
|
||||
},
|
||||
"globalthis": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.0.tgz",
|
||||
"integrity": "sha512-vcCAZTJ3r5Qcu5l8/2oyVdoFwxKgfYnMTR2vwWeux/NAVZK3PwcMaWkdUIn4GJbmKuRK7xcvDsLuK+CKcXyodg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"function-bind": "^1.1.1",
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
|
||||
@@ -6003,9 +6304,9 @@
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||
},
|
||||
"helmet": {
|
||||
"version": "3.21.1",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.21.1.tgz",
|
||||
"integrity": "sha512-IC/54Lxvvad2YiUdgLmPlNFKLhNuG++waTF5KPYq/Feo3NNhqMFbcLAlbVkai+9q0+4uxjxGPJ9bNykG+3zZNg==",
|
||||
"version": "3.21.2",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.21.2.tgz",
|
||||
"integrity": "sha512-okUo+MeWgg00cKB8Csblu8EXgcIoDyb5ZS/3u0W4spCimeVuCUvVZ6Vj3O2VJ1Sxpyb8jCDvzu0L1KKT11pkIg==",
|
||||
"requires": {
|
||||
"depd": "2.0.0",
|
||||
"dns-prefetch-control": "0.2.0",
|
||||
@@ -6014,7 +6315,7 @@
|
||||
"feature-policy": "0.3.0",
|
||||
"frameguard": "3.1.0",
|
||||
"helmet-crossdomain": "0.4.0",
|
||||
"helmet-csp": "2.9.2",
|
||||
"helmet-csp": "2.9.4",
|
||||
"hide-powered-by": "1.1.0",
|
||||
"hpkp": "2.0.0",
|
||||
"hsts": "2.2.0",
|
||||
@@ -6037,11 +6338,11 @@
|
||||
"integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
|
||||
},
|
||||
"helmet-csp": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.9.2.tgz",
|
||||
"integrity": "sha512-Lt5WqNfbNjEJ6ysD4UNpVktSyjEKfU9LVJ1LaFmPfYseg/xPealPfgHhtqdAdjPDopp5zbg/VWCyp4cluMIckw==",
|
||||
"version": "2.9.4",
|
||||
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.9.4.tgz",
|
||||
"integrity": "sha512-qUgGx8+yk7Xl8XFEGI4MFu1oNmulxhQVTlV8HP8tV3tpfslCs30OZz/9uQqsWPvDISiu/NwrrCowsZBhFADYqg==",
|
||||
"requires": {
|
||||
"bowser": "^2.6.1",
|
||||
"bowser": "^2.7.0",
|
||||
"camelize": "1.0.0",
|
||||
"content-security-policy-builder": "2.1.0",
|
||||
"dasherize": "2.0.0"
|
||||
@@ -6175,9 +6476,9 @@
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz",
|
||||
"integrity": "sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz",
|
||||
"integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==",
|
||||
"requires": {
|
||||
"agent-base": "^4.3.0",
|
||||
"debug": "^3.1.0"
|
||||
@@ -7728,6 +8029,25 @@
|
||||
"integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
|
||||
"dev": true
|
||||
},
|
||||
"matcher": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/matcher/-/matcher-2.0.0.tgz",
|
||||
"integrity": "sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"math-random": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
|
||||
@@ -8646,9 +8966,9 @@
|
||||
"integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
|
||||
},
|
||||
"node-abi": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.11.0.tgz",
|
||||
"integrity": "sha512-kuy/aEg75u40v378WRllQ4ZexaXJiCvB68D2scDXclp/I4cRq6togpbOoKhmN07tns9Zldu51NNERo0wehfX9g==",
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.12.0.tgz",
|
||||
"integrity": "sha512-VhPBXCIcvmo/5K8HPmnWJyyhvgKxnHTUMXR/XwGHV68+wrgkzST4UmQrY/XszSWA5dtnXpNp528zkcyJ/pzVcw==",
|
||||
"requires": {
|
||||
"semver": "^5.4.1"
|
||||
},
|
||||
@@ -10994,6 +11314,30 @@
|
||||
"resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz",
|
||||
"integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w="
|
||||
},
|
||||
"roarr": {
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.14.2.tgz",
|
||||
"integrity": "sha512-ibqv70DCUhGVMfPe0JSUHBZ9PKLhxdk8VJ/Y2M7vVr+L4VakW1CdVTU9cJQBbM2STQa84CgBAzd7hJGcnALGeg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"boolean": "^2.0.2",
|
||||
"detect-node": "^2.0.4",
|
||||
"globalthis": "^1.0.0",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"semver-compare": "^1.0.0",
|
||||
"sprintf-js": "^1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"sprintf-js": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
|
||||
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"run-async": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
|
||||
@@ -11069,6 +11413,13 @@
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"semver-compare": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
||||
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"semver-diff": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
|
||||
@@ -11148,6 +11499,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"serialize-error": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-5.0.0.tgz",
|
||||
"integrity": "sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"type-fest": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-favicon": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz",
|
||||
@@ -11457,9 +11827,9 @@
|
||||
}
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.13",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
|
||||
"integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
|
||||
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
@@ -12295,6 +12665,13 @@
|
||||
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
|
||||
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
|
||||
|
||||
14
package.json
14
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.36.1-beta",
|
||||
"version": "0.36.3",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@@ -37,13 +37,13 @@
|
||||
"electron-window-state": "5.0.3",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.0",
|
||||
"file-type": "12.3.0",
|
||||
"file-type": "12.3.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"helmet": "3.21.1",
|
||||
"helmet": "3.21.2",
|
||||
"html": "1.0.0",
|
||||
"html2plaintext": "2.1.2",
|
||||
"http-proxy-agent": "2.1.0",
|
||||
"https-proxy-agent": "3.0.0",
|
||||
"https-proxy-agent": "3.0.1",
|
||||
"image-type": "4.1.0",
|
||||
"imagemin": "7.0.0",
|
||||
"imagemin-giflossy": "5.1.10",
|
||||
@@ -54,7 +54,7 @@
|
||||
"mime-types": "2.1.24",
|
||||
"moment": "2.24.0",
|
||||
"multer": "1.4.2",
|
||||
"node-abi": "2.11.0",
|
||||
"node-abi": "2.12.0",
|
||||
"open": "7.0.0",
|
||||
"pngjs": "3.4.0",
|
||||
"portscanner": "2.2.0",
|
||||
@@ -79,10 +79,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "6.0.12",
|
||||
"electron-builder": "21.2.0",
|
||||
"electron-builder": "22.1.0",
|
||||
"electron-compile": "6.4.4",
|
||||
"electron-installer-debian": "2.0.1",
|
||||
"electron-packager": "14.0.6",
|
||||
"electron-packager": "14.1.0",
|
||||
"electron-rebuild": "1.8.6",
|
||||
"jsdoc": "3.6.3",
|
||||
"lorem-ipsum": "2.0.3",
|
||||
|
||||
@@ -91,6 +91,8 @@ app.use((err, req, res, next) => {
|
||||
if (err && err.message && (
|
||||
err.message.includes("Invalid package")
|
||||
|| (err.message.includes("Router not found for request") && err.message.includes("node_modules"))
|
||||
|| (err.message.includes("Router not found for request") && err.message.includes(".js.map"))
|
||||
|| (err.message.includes("Router not found for request") && err.message.includes(".css.map"))
|
||||
)) {
|
||||
// electron 6 outputs a lot of such errors which do not seem important
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ class Branch extends Entity {
|
||||
this.notePosition = maxNotePos === null ? 0 : maxNotePos + 10;
|
||||
}
|
||||
|
||||
if (!this.isExpanded) {
|
||||
this.isExpanded = false;
|
||||
}
|
||||
|
||||
if (!this.isDeleted) {
|
||||
this.isDeleted = false;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function showDialog(node) {
|
||||
$dialog.modal();
|
||||
|
||||
branchId = node.data.branchId;
|
||||
const branch = await treeCache.getBranch(branchId);
|
||||
const branch = treeCache.getBranch(branchId);
|
||||
|
||||
$treePrefixInput.val(branch.prefix);
|
||||
|
||||
|
||||
@@ -23,19 +23,18 @@ export async function showDialog() {
|
||||
// set default settings
|
||||
$maxNotesInput.val(20);
|
||||
|
||||
const note = noteDetailService.getActiveTabNote();
|
||||
|
||||
if (!note) {
|
||||
return;
|
||||
}
|
||||
|
||||
$linkMapContainer.css("height", $("body").height() - 150);
|
||||
|
||||
linkMapService = new LinkMapService(note, $linkMapContainer, getOptions());
|
||||
|
||||
linkMapService.render();
|
||||
$linkMapContainer.empty();
|
||||
|
||||
$dialog.modal();
|
||||
}
|
||||
|
||||
$dialog.on('shown.bs.modal', () => {
|
||||
const note = noteDetailService.getActiveTabNote();
|
||||
|
||||
linkMapService = new LinkMapService(note, $linkMapContainer, getOptions());
|
||||
linkMapService.render();
|
||||
});
|
||||
|
||||
$maxNotesInput.on("input", () => linkMapService.loadNotesAndRelations(getOptions()));
|
||||
|
||||
@@ -4,8 +4,8 @@ import NoteShort from './note_short.js';
|
||||
* Represents full note, specifically including note's content.
|
||||
*/
|
||||
class NoteFull extends NoteShort {
|
||||
constructor(treeCache, row) {
|
||||
super(treeCache, row);
|
||||
constructor(treeCache, row, noteShort) {
|
||||
super(treeCache, row, []);
|
||||
|
||||
/** @param {string} */
|
||||
this.content = row.content;
|
||||
@@ -21,6 +21,12 @@ class NoteFull extends NoteShort {
|
||||
|
||||
/** @param {string} */
|
||||
this.utcDateModified = row.utcDateModified;
|
||||
|
||||
/* ugly */
|
||||
this.parents = noteShort.parents;
|
||||
this.parentToBranch = noteShort.parentToBranch;
|
||||
this.children = noteShort.children;
|
||||
this.childToBranch = noteShort.childToBranch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import server from '../services/server.js';
|
||||
import Attribute from './attribute.js';
|
||||
import branches from "../services/branches.js";
|
||||
|
||||
const LABEL = 'label';
|
||||
const LABEL_DEFINITION = 'label-definition';
|
||||
@@ -13,7 +14,12 @@ const RELATION_DEFINITION = 'relation-definition';
|
||||
* This note's representation is used in note tree and is kept in TreeCache.
|
||||
*/
|
||||
class NoteShort {
|
||||
constructor(treeCache, row) {
|
||||
/**
|
||||
* @param {TreeCache} treeCache
|
||||
* @param {Object.<string, Object>} row
|
||||
* @param {Branch[]} branches - all relevant branches, i.e. where this note is either child or parent
|
||||
*/
|
||||
constructor(treeCache, row, branches) {
|
||||
this.treeCache = treeCache;
|
||||
/** @param {string} */
|
||||
this.noteId = row.noteId;
|
||||
@@ -26,9 +32,60 @@ class NoteShort {
|
||||
/** @param {string} content-type, e.g. "application/json" */
|
||||
this.mime = row.mime;
|
||||
/** @param {boolean} */
|
||||
this.isDeleted = row.isDeleted;
|
||||
/** @param {boolean} */
|
||||
this.archived = row.archived;
|
||||
/** @param {string} */
|
||||
this.cssClass = row.cssClass;
|
||||
|
||||
/** @type {string[]} */
|
||||
this.parents = [];
|
||||
/** @type {string[]} */
|
||||
this.children = [];
|
||||
|
||||
/** @type {Object.<string, string>} */
|
||||
this.parentToBranch = {};
|
||||
|
||||
/** @type {Object.<string, string>} */
|
||||
this.childToBranch = {};
|
||||
|
||||
for (const branch of branches) {
|
||||
if (this.noteId === branch.noteId) {
|
||||
this.parents.push(branch.parentNoteId);
|
||||
this.parentToBranch[branch.parentNoteId] = branch.branchId;
|
||||
}
|
||||
else if (this.noteId === branch.parentNoteId) {
|
||||
this.children.push(branch.noteId);
|
||||
this.childToBranch[branch.noteId] = branch.branchId;
|
||||
}
|
||||
else {
|
||||
throw new Error(`Unknown branch ${branch.branchId} for note ${this.noteId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addParent(parentNoteId, branchId) {
|
||||
if (!this.parents.includes(parentNoteId)) {
|
||||
this.parents.push(parentNoteId);
|
||||
}
|
||||
|
||||
this.parentToBranch[parentNoteId] = branchId;
|
||||
}
|
||||
|
||||
addChild(childNoteId, branchId) {
|
||||
if (!this.children.includes(childNoteId)) {
|
||||
this.children.push(childNoteId);
|
||||
}
|
||||
|
||||
this.childToBranch[childNoteId] = branchId;
|
||||
|
||||
const branchIdPos = {};
|
||||
|
||||
for (const branchId of Object.values(this.childToBranch)) {
|
||||
branchIdPos[branchId] = this.treeCache.getBranch(branchId).notePosition;
|
||||
}
|
||||
|
||||
this.children.sort((a, b) => branchIdPos[this.childToBranch[a]] < branchIdPos[this.childToBranch[b]] ? -1 : 1);
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
@@ -58,48 +115,42 @@ class NoteShort {
|
||||
|
||||
/** @returns {Promise<Branch[]>} */
|
||||
async getBranches() {
|
||||
const branchIds = this.treeCache.parents[this.noteId].map(
|
||||
parentNoteId => this.treeCache.getBranchIdByChildParent(this.noteId, parentNoteId));
|
||||
const branchIds = Object.values(this.parentToBranch);
|
||||
|
||||
return this.treeCache.getBranches(branchIds);
|
||||
}
|
||||
|
||||
/** @returns {boolean} */
|
||||
hasChildren() {
|
||||
return this.treeCache.children[this.noteId]
|
||||
&& this.treeCache.children[this.noteId].length > 0;
|
||||
return this.children.length > 0;
|
||||
}
|
||||
|
||||
/** @returns {Promise<Branch[]>} */
|
||||
async getChildBranches() {
|
||||
if (!this.treeCache.children[this.noteId]) {
|
||||
return [];
|
||||
}
|
||||
// don't use Object.values() to guarantee order
|
||||
const branchIds = this.children.map(childNoteId => this.childToBranch[childNoteId]);
|
||||
|
||||
const branchIds = this.treeCache.children[this.noteId].map(
|
||||
childNoteId => this.treeCache.getBranchIdByChildParent(childNoteId, this.noteId));
|
||||
|
||||
return await this.treeCache.getBranches(branchIds);
|
||||
return this.treeCache.getBranches(branchIds);
|
||||
}
|
||||
|
||||
/** @returns {string[]} */
|
||||
getParentNoteIds() {
|
||||
return this.treeCache.parents[this.noteId] || [];
|
||||
return this.parents;
|
||||
}
|
||||
|
||||
/** @returns {Promise<NoteShort[]>} */
|
||||
async getParentNotes() {
|
||||
return await this.treeCache.getNotes(this.getParentNoteIds());
|
||||
return await this.treeCache.getNotes(this.parents);
|
||||
}
|
||||
|
||||
/** @returns {string[]} */
|
||||
getChildNoteIds() {
|
||||
return this.treeCache.children[this.noteId] || [];
|
||||
return this.children;
|
||||
}
|
||||
|
||||
/** @returns {Promise<NoteShort[]>} */
|
||||
async getChildNotes() {
|
||||
return await this.treeCache.getNotes(this.getChildNoteIds());
|
||||
return await this.treeCache.getNotes(this.children);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,7 +91,7 @@ async function showTree() {
|
||||
|
||||
$detail.on("click", ".note-menu-button", async e => {
|
||||
const node = treeService.getActiveNode();
|
||||
const branch = await treeCache.getBranch(node.data.branchId);
|
||||
const branch = treeCache.getBranch(node.data.branchId);
|
||||
const note = await treeCache.getNote(node.data.noteId);
|
||||
const parentNote = await treeCache.getNote(branch.parentNoteId);
|
||||
const isNotRoot = note.noteId !== 'root';
|
||||
|
||||
@@ -221,7 +221,7 @@ class Attributes {
|
||||
.prop("title", "Remove this attribute")
|
||||
.click(async () => {
|
||||
if (valueAttr.attributeId) {
|
||||
await server.remove("notes/" + noteId + "/attributes/" + valueAttr.attributeId);
|
||||
await server.remove("notes/" + this.ctx.note.noteId + "/attributes/" + valueAttr.attributeId);
|
||||
}
|
||||
|
||||
$tr.remove();
|
||||
|
||||
@@ -26,9 +26,7 @@ async function moveBeforeNode(nodesToMove, beforeNode) {
|
||||
|
||||
await changeNode(
|
||||
node => node.moveTo(beforeNode, 'before'),
|
||||
nodeToMove,
|
||||
beforeNode.data.noteId,
|
||||
null);
|
||||
nodeToMove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +50,7 @@ async function moveAfterNode(nodesToMove, afterNode) {
|
||||
|
||||
await changeNode(
|
||||
node => node.moveTo(afterNode, 'after'),
|
||||
nodeToMove,
|
||||
null,
|
||||
afterNode.data.noteId);
|
||||
nodeToMove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +58,11 @@ async function moveToNode(nodesToMove, toNode) {
|
||||
nodesToMove = await filterRootNote(nodesToMove);
|
||||
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
if (nodeToMove.data.noteId === await hoistedNoteService.getHoistedNoteId()
|
||||
|| nodeToMove.getParent().data.noteType === 'search') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const resp = await server.put('branches/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId);
|
||||
|
||||
if (!resp.success) {
|
||||
@@ -80,6 +81,22 @@ async function moveToNode(nodesToMove, toNode) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getNextNode(nodes) {
|
||||
// following code assumes that nodes contain only top-most selected nodes - getSelectedNodes has been
|
||||
// called with stopOnParent=true
|
||||
let next = nodes[nodes.length - 1].getNextSibling();
|
||||
|
||||
if (!next) {
|
||||
next = nodes[0].getPrevSibling();
|
||||
}
|
||||
|
||||
if (!next && !await hoistedNoteService.isRootNode(nodes[0])) {
|
||||
next = nodes[0].getParent();
|
||||
}
|
||||
|
||||
return treeUtils.getNotePath(next);
|
||||
}
|
||||
|
||||
async function deleteNodes(nodes) {
|
||||
nodes = await filterRootNote(nodes);
|
||||
|
||||
@@ -130,53 +147,19 @@ async function deleteNodes(nodes) {
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteClones) {
|
||||
// if clones are also deleted we give up with targeted cleanup of the tree
|
||||
treeService.reload();
|
||||
return true;
|
||||
}
|
||||
const nextNotePath = await getNextNode(nodes);
|
||||
|
||||
// following code assumes that nodes contain only top-most selected nodes - getSelectedNodes has been
|
||||
// called with stopOnParent=true
|
||||
let next = nodes[nodes.length - 1].getNextSibling();
|
||||
const noteIds = Array.from(new Set(nodes.map(node => node.getParent().data.noteId)));
|
||||
|
||||
if (!next) {
|
||||
next = nodes[0].getPrevSibling();
|
||||
}
|
||||
|
||||
if (!next && !await hoistedNoteService.isRootNode(nodes[0])) {
|
||||
next = nodes[0].getParent();
|
||||
}
|
||||
|
||||
let activeNotePath = null;
|
||||
|
||||
if (next) {
|
||||
activeNotePath = await treeUtils.getNotePath(next);
|
||||
}
|
||||
|
||||
await treeService.loadTreeCache();
|
||||
|
||||
const parentNoteIds = Array.from(new Set(nodes.map(node => node.getParent().data.noteId)));
|
||||
|
||||
for (const node of nodes) {
|
||||
node.remove();
|
||||
}
|
||||
|
||||
await treeService.reloadNotes(parentNoteIds);
|
||||
|
||||
// activate after all the reloading
|
||||
if (activeNotePath) {
|
||||
treeService.focusTree();
|
||||
|
||||
const node = await treeService.activateNote(activeNotePath);
|
||||
node.setFocus(true);
|
||||
}
|
||||
await treeService.reloadNotes(noteIds, nextNotePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function moveNodeUpInHierarchy(node) {
|
||||
if (await hoistedNoteService.isRootNode(node) || await hoistedNoteService.isTopLevelNode(node)) {
|
||||
if (await hoistedNoteService.isRootNode(node)
|
||||
|| await hoistedNoteService.isTopLevelNode(node)
|
||||
|| node.getParent().data.noteType === 'search') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,7 +180,7 @@ async function moveNodeUpInHierarchy(node) {
|
||||
node);
|
||||
}
|
||||
|
||||
async function changeNode(func, node, beforeNoteId = null, afterNoteId = null) {
|
||||
async function changeNode(func, node) {
|
||||
utils.assertArguments(func, node);
|
||||
|
||||
const childNoteId = node.data.noteId;
|
||||
@@ -214,7 +197,7 @@ async function changeNode(func, node, beforeNoteId = null, afterNoteId = null) {
|
||||
|
||||
node.data.parentNoteId = thisNewParentNode.data.noteId;
|
||||
|
||||
await treeCache.moveNote(childNoteId, thisOldParentNode.data.noteId, thisNewParentNode.data.noteId, beforeNoteId, afterNoteId);
|
||||
await treeCache.reloadNotes([childNoteId]);
|
||||
|
||||
await treeService.checkFolderStatus(thisOldParentNode);
|
||||
await treeService.checkFolderStatus(thisNewParentNode);
|
||||
|
||||
@@ -2,6 +2,7 @@ import treeUtils from "./tree_utils.js";
|
||||
import treeChangesService from "./branches.js";
|
||||
import cloningService from "./cloning.js";
|
||||
import toastService from "./toast.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
|
||||
let clipboardIds = [];
|
||||
let clipboardMode = null;
|
||||
@@ -66,10 +67,16 @@ function copy(nodes) {
|
||||
}
|
||||
|
||||
function cut(nodes) {
|
||||
clipboardIds = nodes.map(node => node.key);
|
||||
clipboardMode = 'cut';
|
||||
clipboardIds = nodes
|
||||
.filter(node => node.data.noteId !== hoistedNoteService.getHoistedNoteNoPromise())
|
||||
.filter(node => node.getParent().data.noteType !== 'search')
|
||||
.map(node => node.data.noteId);
|
||||
|
||||
toastService.showMessage("Note(s) have been cut into clipboard.");
|
||||
if (clipboardIds.length > 0) {
|
||||
clipboardMode = 'cut';
|
||||
|
||||
toastService.showMessage("Note(s) have been cut into clipboard.");
|
||||
}
|
||||
}
|
||||
|
||||
function isEmpty() {
|
||||
|
||||
@@ -12,9 +12,7 @@ async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
|
||||
return;
|
||||
}
|
||||
|
||||
treeCache.addBranchRelationship(resp.branchId, childNoteId, parentNoteId);
|
||||
|
||||
await treeService.reloadNotes([parentNoteId]);
|
||||
await treeService.reloadNotes([childNoteId, parentNoteId]);
|
||||
}
|
||||
|
||||
// beware that first arg is noteId and second is branchId!
|
||||
@@ -26,11 +24,9 @@ async function cloneNoteAfter(noteId, afterBranchId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const afterBranch = await treeCache.getBranch(afterBranchId);
|
||||
const afterBranch = treeCache.getBranch(afterBranchId);
|
||||
|
||||
treeCache.addBranchRelationship(resp.branchId, noteId, afterBranch.parentNoteId);
|
||||
|
||||
await treeService.reloadNotes([afterBranch.parentNoteId]);
|
||||
await treeService.reloadNotes([noteId, afterBranch.parentNoteId]);
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -8,27 +8,21 @@ async function getTodayNote() {
|
||||
|
||||
/** @return {NoteShort} */
|
||||
async function getDateNote(date) {
|
||||
const note = await server.get('date-notes/date/' + date);
|
||||
|
||||
await treeCache.reloadParents(note.noteId);
|
||||
const note = await server.get('date-notes/date/' + date, {'trilium-source-id': "date-note"});
|
||||
|
||||
return await treeCache.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/** @return {NoteShort} */
|
||||
async function getMonthNote(month) {
|
||||
const note = await server.get('date-notes/month/' + month);
|
||||
|
||||
await treeCache.reloadParents(note.noteId);
|
||||
const note = await server.get('date-notes/month/' + month, {'trilium-source-id': "date-note"});
|
||||
|
||||
return await treeCache.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/** @return {NoteShort} */
|
||||
async function getYearNote(year) {
|
||||
const note = await server.get('date-notes/year/' + year);
|
||||
|
||||
await treeCache.reloadParents(note.noteId);
|
||||
const note = await server.get('date-notes/year/' + year, {'trilium-source-id': "date-note"});
|
||||
|
||||
return await treeCache.getNote(note.noteId);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import treeService from './tree.js';
|
||||
import treeChangesService from './branches.js';
|
||||
import hoistedNoteService from './hoisted_note.js';
|
||||
|
||||
const dragAndDropSetup = {
|
||||
autoExpandMS: 600,
|
||||
dragStart: (node, data) => {
|
||||
// don't allow dragging root node
|
||||
if (node.data.noteId === 'root') {
|
||||
if (node.data.noteId === hoistedNoteService.getHoistedNoteNoPromise()
|
||||
|| node.getParent().data.noteType === 'search') {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,6 +27,17 @@ const dragAndDropSetup = {
|
||||
dragEnter: (node, data) => true, // allow drop on any node
|
||||
dragOver: (node, data) => true,
|
||||
dragDrop: async (node, data) => {
|
||||
if ((data.hitMode === 'over' && node.data.noteType === 'search') ||
|
||||
(['after', 'before'].includes(data.hitMode)
|
||||
&& (node.data.noteId === hoistedNoteService.getHoistedNoteNoPromise() || node.getParent().data.noteType === 'search'))) {
|
||||
|
||||
const infoDialog = await import('../dialogs/info.js');
|
||||
|
||||
await infoDialog.info("Dropping notes into this location is not allowed.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const dataTransfer = data.dataTransfer;
|
||||
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
|
||||
@@ -212,16 +212,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
this.getNotes = async (noteIds, silentNotFoundError = false) => await treeCache.getNotes(noteIds, silentNotFoundError);
|
||||
|
||||
/**
|
||||
* @param {string} noteId
|
||||
* Update frontend tree (note) cache from the backend.
|
||||
*
|
||||
* @param {string[]} noteIds
|
||||
* @method
|
||||
*/
|
||||
this.reloadNotesAndTheirChildren = async noteId => await treeCache.reloadNotesAndTheirChildren(noteId);
|
||||
|
||||
/**
|
||||
* @param {string} noteId
|
||||
* @method
|
||||
*/
|
||||
this.reloadParents = async noteId => await treeCache.reloadParents(noteId);
|
||||
this.reloadNotes = async noteIds => await treeCache.reloadNotes(noteIds);
|
||||
|
||||
/**
|
||||
* Instance name identifies particular Trilium instance. It can be useful for scripts
|
||||
@@ -363,6 +359,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.setHoistedNoteId = hoistedNoteService.setHoistedNoteId;
|
||||
|
||||
/**
|
||||
* @method
|
||||
* @param {string} keyboardShortcut - e.g. "ctrl+shift+a"
|
||||
* @param {function} handler
|
||||
*/
|
||||
this.bindGlobalShortcut = utils.bindGlobalShortcut;
|
||||
}
|
||||
|
||||
export default FrontendScriptApi;
|
||||
@@ -3,12 +3,16 @@ import server from "./server.js";
|
||||
import tree from "./tree.js";
|
||||
import noteDetailService from "./note_detail.js";
|
||||
|
||||
let hoistedNoteId;
|
||||
let hoistedNoteId = 'root';
|
||||
|
||||
optionsService.waitForOptions().then(options => {
|
||||
hoistedNoteId = options.get('hoistedNoteId');
|
||||
});
|
||||
|
||||
function getHoistedNoteNoPromise() {
|
||||
return hoistedNoteId;
|
||||
}
|
||||
|
||||
async function getHoistedNoteId() {
|
||||
await optionsService.waitForOptions();
|
||||
|
||||
@@ -49,6 +53,7 @@ async function isRootNode(node) {
|
||||
|
||||
export default {
|
||||
getHoistedNoteId,
|
||||
getHoistedNoteNoPromise,
|
||||
setHoistedNoteId,
|
||||
unhoist,
|
||||
isTopLevelNode,
|
||||
|
||||
@@ -63,7 +63,7 @@ ws.subscribeToMessages(async message => {
|
||||
|
||||
toastService.showPersistent(toast);
|
||||
|
||||
await treeService.reloadNotes([message.parentNoteId]);
|
||||
await treeService.reloadNotes([message.result.parentNoteId]);
|
||||
|
||||
if (message.result.importedNoteId) {
|
||||
const node = await treeService.activateNote(message.result.importedNoteId);
|
||||
|
||||
@@ -119,60 +119,54 @@ export default class LinkMap {
|
||||
stop: params => {}
|
||||
});
|
||||
|
||||
|
||||
return $noteBox;
|
||||
};
|
||||
|
||||
this.renderer = new Springy.Renderer(
|
||||
layout,
|
||||
() => {},
|
||||
(edge, p1, p2) => {
|
||||
const connectionId = this.linkMapContainerId + '-' + edge.source.id + '-' + edge.target.id;
|
||||
this.renderer = new Springy.Renderer(layout);
|
||||
await this.renderer.start(500);
|
||||
|
||||
if ($("#" + connectionId).length > 0) {
|
||||
return;
|
||||
}
|
||||
layout.eachNode((node, point) => {
|
||||
const $noteBox = getNoteBox(node.id);
|
||||
const middleW = this.$linkMapContainer.width() / 2;
|
||||
const middleH = this.$linkMapContainer.height() / 2;
|
||||
|
||||
getNoteBox(edge.source.id);
|
||||
getNoteBox(edge.target.id);
|
||||
$noteBox
|
||||
.css("left", (middleW + point.p.x * 100) + "px")
|
||||
.css("top", (middleH + point.p.y * 100) + "px");
|
||||
|
||||
const connection = this.jsPlumbInstance.connect({
|
||||
source: this.noteIdToId(edge.source.id),
|
||||
target: this.noteIdToId(edge.target.id),
|
||||
type: 'link'
|
||||
});
|
||||
|
||||
if (connection) {
|
||||
$(connection.canvas)
|
||||
.prop("id", connectionId)
|
||||
.addClass('link-' + edge.source.id)
|
||||
.addClass('link-' + edge.target.id);
|
||||
}
|
||||
else {
|
||||
console.log(`connection not created for`, edge);
|
||||
}
|
||||
},
|
||||
(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");
|
||||
|
||||
if ($noteBox.hasClass("link-map-active-note")) {
|
||||
this.moveToCenterOfElement($noteBox[0]);
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
() => {},
|
||||
() => {
|
||||
this.jsPlumbInstance.repaintEverything();
|
||||
if ($noteBox.hasClass("link-map-active-note")) {
|
||||
this.moveToCenterOfElement($noteBox[0]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
this.renderer.start();
|
||||
layout.eachEdge(edge => {
|
||||
const connectionId = this.linkMapContainerId + '-' + 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'
|
||||
});
|
||||
|
||||
if (connection) {
|
||||
$(connection.canvas)
|
||||
.prop("id", connectionId)
|
||||
.addClass('link-' + edge.source.id)
|
||||
.addClass('link-' + edge.target.id);
|
||||
}
|
||||
else {
|
||||
console.log(`connection not created for`, edge);
|
||||
}
|
||||
});
|
||||
|
||||
this.jsPlumbInstance.repaintEverything();
|
||||
}
|
||||
|
||||
moveToCenterOfElement(element) {
|
||||
|
||||
@@ -250,7 +250,9 @@ async function loadNoteDetail(origNotePath, options = {}) {
|
||||
async function loadNote(noteId) {
|
||||
const row = await server.get('notes/' + noteId);
|
||||
|
||||
return new NoteFull(treeCache, row);
|
||||
const noteShort = await treeCache.getNote(noteId);
|
||||
|
||||
return new NoteFull(treeCache, row, noteShort);
|
||||
}
|
||||
|
||||
async function filterTabs(noteId) {
|
||||
|
||||
@@ -64,15 +64,16 @@ async function call(method, url, data, headers = {}) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
return await ajax(url, method, data);
|
||||
return await ajax(url, method, data, headers);
|
||||
}
|
||||
}
|
||||
|
||||
async function ajax(url, method, data) {
|
||||
async function ajax(url, method, data, headers) {
|
||||
const options = {
|
||||
url: baseApiUrl + url,
|
||||
type: method,
|
||||
headers: getHeaders()
|
||||
headers: getHeaders(headers),
|
||||
timeout: 60000
|
||||
};
|
||||
|
||||
if (data) {
|
||||
|
||||
@@ -45,12 +45,12 @@ function showPersistent(options) {
|
||||
}
|
||||
|
||||
if (options.closeAfter) {
|
||||
setTimeout(() => $toast.toast('dispose'), options.closeAfter);
|
||||
setTimeout(() => $toast.remove(), options.closeAfter);
|
||||
}
|
||||
}
|
||||
|
||||
function closePersistent(id) {
|
||||
$("#toast-persistent-" + id).toast("dispose");
|
||||
$("#toast-" + id).remove();
|
||||
}
|
||||
|
||||
function showMessage(message, delay = 2000) {
|
||||
|
||||
@@ -48,7 +48,7 @@ function getActiveNode() {
|
||||
async function getNodesByBranchId(branchId) {
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const branch = await treeCache.getBranch(branchId);
|
||||
const branch = treeCache.getBranch(branchId);
|
||||
|
||||
return getNodesByNoteId(branch.noteId).filter(node => node.data.branchId === branchId);
|
||||
}
|
||||
@@ -64,7 +64,7 @@ function getNodesByNoteId(noteId) {
|
||||
async function setPrefix(branchId, prefix) {
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const branch = await treeCache.getBranch(branchId);
|
||||
const branch = treeCache.getBranch(branchId);
|
||||
|
||||
branch.prefix = prefix;
|
||||
|
||||
@@ -75,7 +75,7 @@ async function setPrefix(branchId, prefix) {
|
||||
|
||||
async function setNodeTitleWithPrefix(node) {
|
||||
const noteTitle = await treeUtils.getNoteTitle(node.data.noteId);
|
||||
const branch = await treeCache.getBranch(node.data.branchId);
|
||||
const branch = treeCache.getBranch(node.data.branchId);
|
||||
|
||||
const prefix = branch.prefix;
|
||||
|
||||
@@ -559,14 +559,10 @@ function getHashValueFromAddress() {
|
||||
return str.split("-");
|
||||
}
|
||||
|
||||
async function loadTreeCache() {
|
||||
async function loadTree() {
|
||||
const resp = await server.get('tree');
|
||||
|
||||
treeCache.load(resp.notes, resp.branches, resp.relations);
|
||||
}
|
||||
|
||||
async function loadTree() {
|
||||
await loadTreeCache();
|
||||
treeCache.load(resp.notes, resp.branches);
|
||||
|
||||
return await treeBuilder.prepareTree();
|
||||
}
|
||||
@@ -670,10 +666,8 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
|
||||
|
||||
noteDetailService.addDetailLoadedListener(note.noteId, noteDetailService.focusAndSelectTitle);
|
||||
|
||||
const noteEntity = new NoteShort(treeCache, note);
|
||||
const branchEntity = new Branch(treeCache, branch);
|
||||
|
||||
treeCache.add(noteEntity, branchEntity);
|
||||
const noteEntity = await treeCache.getNote(note.noteId);
|
||||
const branchEntity = treeCache.getBranch(branch.branchId);
|
||||
|
||||
let newNode = {
|
||||
title: newNoteName,
|
||||
@@ -682,6 +676,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
|
||||
refKey: branchEntity.noteId,
|
||||
branchId: branchEntity.branchId,
|
||||
isProtected: extraOptions.isProtected,
|
||||
type: noteEntity.type,
|
||||
extraClasses: await treeBuilder.getExtraClasses(noteEntity),
|
||||
icon: await treeBuilder.getIcon(noteEntity),
|
||||
folder: extraOptions.type === 'search',
|
||||
@@ -826,33 +821,41 @@ async function checkFolderStatus(node) {
|
||||
|
||||
node.folder = note.type === 'search' || note.getChildNoteIds().length > 0;
|
||||
node.icon = await treeBuilder.getIcon(note);
|
||||
node.extraClasses = await treeBuilder.getExtraClasses(note);
|
||||
node.renderTitle();
|
||||
}
|
||||
|
||||
async function reloadNotes(noteIds) {
|
||||
async function reloadNotes(noteIds, activateNotePath = null) {
|
||||
if (noteIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.debug("Reloading notes", noteIds);
|
||||
await treeCache.reloadNotes(noteIds);
|
||||
|
||||
await treeCache.reloadNotesAndTheirChildren(noteIds);
|
||||
|
||||
const activeNotePath = noteDetailService.getActiveTabNotePath();
|
||||
if (!activateNotePath) {
|
||||
activateNotePath = noteDetailService.getActiveTabNotePath();
|
||||
}
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
for (const node of getNodesByNoteId(noteId)) {
|
||||
await node.load(true);
|
||||
const branch = treeCache.getBranch(node.data.branchId, true);
|
||||
|
||||
await checkFolderStatus(node);
|
||||
if (!branch) {
|
||||
node.remove();
|
||||
}
|
||||
else {
|
||||
await node.load(true);
|
||||
|
||||
await checkFolderStatus(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activeNotePath) {
|
||||
const node = await getNodeFromPath(activeNotePath);
|
||||
if (activateNotePath) {
|
||||
const node = await getNodeFromPath(activateNotePath);
|
||||
|
||||
if (node) {
|
||||
await node.setActive(true, {noEvents: true}); // this node has been already active so no need to fire events again
|
||||
await node.setActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -929,7 +932,6 @@ export default {
|
||||
getNodesByNoteId,
|
||||
checkFolderStatus,
|
||||
reloadNotes,
|
||||
loadTreeCache,
|
||||
expandToNote,
|
||||
getNodeFromPath,
|
||||
resolveNotePath,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import utils from "./utils.js";
|
||||
import Branch from "../entities/branch.js";
|
||||
import server from "./server.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
import ws from "./ws.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
@@ -11,7 +9,7 @@ async function prepareTree() {
|
||||
let hoistedBranch;
|
||||
|
||||
if (hoistedNoteId === 'root') {
|
||||
hoistedBranch = await treeCache.getBranch('root');
|
||||
hoistedBranch = treeCache.getBranch('root');
|
||||
}
|
||||
else {
|
||||
const hoistedNote = await treeCache.getNote(hoistedNoteId);
|
||||
@@ -72,6 +70,7 @@ async function prepareNode(branch) {
|
||||
parentNoteId: branch.parentNoteId,
|
||||
branchId: branch.branchId,
|
||||
isProtected: note.isProtected,
|
||||
noteType: note.type,
|
||||
title: utils.escapeHtml(title),
|
||||
extraClasses: await getExtraClasses(note),
|
||||
icon: await getIcon(note),
|
||||
@@ -110,26 +109,11 @@ async function prepareRealBranch(parentNote) {
|
||||
}
|
||||
|
||||
async function prepareSearchBranch(note) {
|
||||
const results = await server.get('search-note/' + note.noteId);
|
||||
await treeCache.reloadNotes([note.noteId]);
|
||||
|
||||
// force to load all the notes at once instead of one by one
|
||||
await treeCache.getNotes(results.map(res => res.noteId));
|
||||
const newNote = await treeCache.getNote(note.noteId);
|
||||
|
||||
for (const result of results) {
|
||||
const origBranch = await treeCache.getBranch(result.branchId);
|
||||
|
||||
const branch = new Branch(treeCache, {
|
||||
branchId: "virt" + utils.randomString(10),
|
||||
noteId: result.noteId,
|
||||
parentNoteId: note.noteId,
|
||||
prefix: origBranch.prefix,
|
||||
virtual: true
|
||||
});
|
||||
|
||||
treeCache.addBranch(branch);
|
||||
}
|
||||
|
||||
return await prepareRealBranch(note);
|
||||
return await prepareRealBranch(newNote);
|
||||
}
|
||||
|
||||
async function getExtraClasses(note) {
|
||||
|
||||
@@ -1,33 +1,22 @@
|
||||
import utils from "./utils.js";
|
||||
import Branch from "../entities/branch.js";
|
||||
import NoteShort from "../entities/note_short.js";
|
||||
import toastService from "./toast.js";
|
||||
import ws from "./ws.js";
|
||||
import server from "./server.js";
|
||||
|
||||
/**
|
||||
* TreeCache keeps a read only cache of note tree structure in frontend's memory.
|
||||
* - notes are loaded lazily when unknown noteId is requested
|
||||
* - when note is loaded, all its parent and child branches are loaded as well. For a branch to be used, it's not must be loaded before
|
||||
* - deleted notes are present in the cache as well, but they don't have any branches. As a result check for deleted branch is done by presence check - if the branch is not there even though the corresponding note has been loaded, we can infer it is deleted.
|
||||
*
|
||||
* Note and branch deletions are corner cases and usually not needed.
|
||||
*/
|
||||
class TreeCache {
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
load(noteRows, branchRows, relations) {
|
||||
this.init();
|
||||
|
||||
this.addResp(noteRows, branchRows, relations);
|
||||
}
|
||||
|
||||
init() {
|
||||
/** @type {Object.<string, string>} */
|
||||
this.parents = {};
|
||||
/** @type {Object.<string, string>} */
|
||||
this.children = {};
|
||||
|
||||
/** @type {Object.<string, string>} */
|
||||
this.childParentToBranch = {};
|
||||
|
||||
/** @type {Object.<string, NoteShort>} */
|
||||
this.notes = {};
|
||||
|
||||
@@ -35,61 +24,107 @@ class TreeCache {
|
||||
this.branches = {};
|
||||
}
|
||||
|
||||
addResp(noteRows, branchRows, relations) {
|
||||
for (const noteRow of noteRows) {
|
||||
const note = new NoteShort(this, noteRow);
|
||||
load(noteRows, branchRows) {
|
||||
this.init();
|
||||
|
||||
this.notes[note.noteId] = note;
|
||||
}
|
||||
this.addResp(noteRows, branchRows);
|
||||
}
|
||||
|
||||
addResp(noteRows, branchRows) {
|
||||
const branchesByNotes = {};
|
||||
|
||||
for (const branchRow of branchRows) {
|
||||
const branch = new Branch(this, branchRow);
|
||||
|
||||
this.addBranch(branch);
|
||||
branchesByNotes[branch.noteId] = branchesByNotes[branch.noteId] || [];
|
||||
branchesByNotes[branch.noteId].push(branch);
|
||||
|
||||
branchesByNotes[branch.parentNoteId] = branchesByNotes[branch.parentNoteId] || [];
|
||||
branchesByNotes[branch.parentNoteId].push(branch);
|
||||
}
|
||||
|
||||
for (const relation of relations) {
|
||||
this.addBranchRelationship(relation.branchId, relation.childNoteId, relation.parentNoteId);
|
||||
}
|
||||
}
|
||||
for (const noteRow of noteRows) {
|
||||
const {noteId} = noteRow;
|
||||
|
||||
/**
|
||||
* Reload notes and their children.
|
||||
*/
|
||||
async reloadNotesAndTheirChildren(noteIds) {
|
||||
// first load the data before clearing the cache
|
||||
const resp = await server.post('tree/load', { noteIds });
|
||||
const oldNote = this.notes[noteId];
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
for (const childNoteId of this.children[noteId] || []) {
|
||||
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId);
|
||||
if (oldNote) {
|
||||
for (const childNoteId of oldNote.children) {
|
||||
const childNote = this.notes[childNoteId];
|
||||
|
||||
const branchId = this.getBranchIdByChildParent(childNoteId, noteId);
|
||||
if (childNote) {
|
||||
childNote.parents = childNote.parents.filter(p => p !== noteId);
|
||||
|
||||
delete this.branches[branchId];
|
||||
delete this.childParentToBranch[childNoteId + '-' + noteId];
|
||||
delete this.branches[childNote.parentToBranch[noteId]];
|
||||
delete childNote.parentToBranch[noteId];
|
||||
}
|
||||
}
|
||||
|
||||
for (const parentNoteId of oldNote.parents) {
|
||||
const parentNote = this.notes[parentNoteId];
|
||||
|
||||
if (parentNote) {
|
||||
parentNote.children = parentNote.children.filter(p => p !== noteId);
|
||||
|
||||
delete this.branches[parentNote.childToBranch[noteId]];
|
||||
delete parentNote.childToBranch[noteId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.children[noteId] = [];
|
||||
for (const branch of branchesByNotes[noteId] || []) { // can be empty for deleted notes
|
||||
this.branches[branch.branchId] = branch;
|
||||
}
|
||||
|
||||
delete this.notes[noteId];
|
||||
const note = new NoteShort(this, noteRow, branchesByNotes[noteId] || []);
|
||||
|
||||
this.notes[note.noteId] = note;
|
||||
|
||||
for (const childNoteId of note.children) {
|
||||
const childNote = this.notes[childNoteId];
|
||||
|
||||
if (childNote) {
|
||||
childNote.addParent(noteId, note.childToBranch[childNoteId]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const parentNoteId of note.parents) {
|
||||
const parentNote = this.notes[parentNoteId];
|
||||
|
||||
if (parentNote) {
|
||||
parentNote.addChild(noteId, note.parentToBranch[parentNoteId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.addResp(resp.notes, resp.branches, resp.relations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads parents of given noteId - useful when new note is created to make sure note is loaded
|
||||
* in a correct order.
|
||||
*/
|
||||
async reloadParents(noteId) {
|
||||
// to be able to find parents we need first to make sure it is actually loaded
|
||||
await this.getNote(noteId);
|
||||
async reloadNotes(noteIds) {
|
||||
const resp = await server.post('tree/load', { noteIds });
|
||||
|
||||
await this.reloadNotesAndTheirChildren(this.parents[noteId] || []);
|
||||
this.addResp(resp.notes, resp.branches);
|
||||
|
||||
// this is done to load the new parents for the noteId
|
||||
await this.reloadNotesAndTheirChildren([noteId]);
|
||||
for (const note of resp.notes) {
|
||||
if (note.type === 'search') {
|
||||
const searchResults = await server.get('search-note/' + note.noteId);
|
||||
|
||||
// force to load all the notes at once instead of one by one
|
||||
await treeCache.getNotes(searchResults.map(res => res.noteId));
|
||||
|
||||
const branches = resp.branches.filter(b => b.noteId === note.noteId || b.parentNoteId === note.noteId);
|
||||
|
||||
searchResults.forEach((result, index) => branches.push({
|
||||
// branchId should be repeatable since sometimes we reload some notes without rerendering the tree
|
||||
branchId: "virt" + result.noteId + '-' + note.noteId,
|
||||
noteId: result.noteId,
|
||||
parentNoteId: note.noteId,
|
||||
prefix: treeCache.getBranch(result.branchId).prefix,
|
||||
notePosition: (index + 1) * 10
|
||||
}));
|
||||
|
||||
// update this note with standard (parent) branches + virtual (children) branches
|
||||
treeCache.addResp([note], branches);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {Promise<NoteShort[]>} */
|
||||
@@ -97,9 +132,7 @@ class TreeCache {
|
||||
const missingNoteIds = noteIds.filter(noteId => this.notes[noteId] === undefined);
|
||||
|
||||
if (missingNoteIds.length > 0) {
|
||||
const resp = await server.post('tree/load', { noteIds: missingNoteIds });
|
||||
|
||||
this.addResp(resp.notes, resp.branches, resp.relations);
|
||||
await this.reloadNotes(missingNoteIds);
|
||||
}
|
||||
|
||||
return noteIds.map(noteId => {
|
||||
@@ -130,113 +163,21 @@ class TreeCache {
|
||||
return (await this.getNotes([noteId], silentNotFoundError))[0];
|
||||
}
|
||||
|
||||
addBranch(branch) {
|
||||
this.branches[branch.branchId] = branch;
|
||||
|
||||
this.addBranchRelationship(branch.branchId, branch.noteId, branch.parentNoteId);
|
||||
getBranches(branchIds) {
|
||||
return branchIds
|
||||
.map(branchId => this.getBranch(branchId))
|
||||
.filter(b => b !== null);
|
||||
}
|
||||
|
||||
addBranchRelationship(branchId, childNoteId, parentNoteId) {
|
||||
if (parentNoteId === 'none') { // applies only to root element
|
||||
return;
|
||||
}
|
||||
|
||||
this.childParentToBranch[childNoteId + '-' + parentNoteId] = branchId;
|
||||
|
||||
this.parents[childNoteId] = this.parents[childNoteId] || [];
|
||||
|
||||
if (!this.parents[childNoteId].includes(parentNoteId)) {
|
||||
this.parents[childNoteId].push(parentNoteId);
|
||||
}
|
||||
|
||||
this.children[parentNoteId] = this.children[parentNoteId] || [];
|
||||
|
||||
if (!this.children[parentNoteId].includes(childNoteId)) {
|
||||
this.children[parentNoteId].push(childNoteId);
|
||||
}
|
||||
}
|
||||
|
||||
add(note, branch) {
|
||||
this.notes[note.noteId] = note;
|
||||
|
||||
this.addBranch(branch);
|
||||
}
|
||||
|
||||
async getBranches(branchIds) {
|
||||
const missingBranchIds = branchIds.filter(branchId => this.branches[branchId] === undefined);
|
||||
|
||||
if (missingBranchIds.length > 0) {
|
||||
const resp = await server.post('tree/load', { branchIds: branchIds });
|
||||
|
||||
this.addResp(resp.notes, resp.branches, resp.relations);
|
||||
}
|
||||
|
||||
return branchIds.map(branchId => {
|
||||
if (!this.branches[branchId]) {
|
||||
throw new Error(`Can't find branch ${branchId}`);
|
||||
/** @return {Branch} */
|
||||
getBranch(branchId, silentNotFoundError = false) {
|
||||
if (!(branchId in this.branches)) {
|
||||
if (!silentNotFoundError) {
|
||||
console.error(`Not existing branch ${branchId}`);
|
||||
}
|
||||
else {
|
||||
return this.branches[branchId];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @return Branch */
|
||||
async getBranch(branchId) {
|
||||
return (await this.getBranches([branchId]))[0];
|
||||
}
|
||||
|
||||
/** @return Branch */
|
||||
async getBranchByChildParent(childNoteId, parentNoteId) {
|
||||
const branchId = this.getBranchIdByChildParent(childNoteId, parentNoteId);
|
||||
|
||||
return await this.getBranch(branchId);
|
||||
}
|
||||
|
||||
getBranchIdByChildParent(childNoteId, parentNoteId) {
|
||||
const key = childNoteId + '-' + parentNoteId;
|
||||
const branchId = this.childParentToBranch[key];
|
||||
|
||||
if (!branchId) {
|
||||
toastService.throwError("Cannot find branch for child-parent=" + key);
|
||||
}
|
||||
|
||||
return branchId;
|
||||
}
|
||||
|
||||
/* Move note from one parent to another. */
|
||||
async moveNote(childNoteId, oldParentNoteId, newParentNoteId, beforeNoteId, afterNoteId) {
|
||||
utils.assertArguments(childNoteId, oldParentNoteId, newParentNoteId);
|
||||
|
||||
if (oldParentNoteId === newParentNoteId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const branchId = this.childParentToBranch[childNoteId + '-' + oldParentNoteId];
|
||||
const branch = await this.getBranch(branchId);
|
||||
branch.parentNoteId = newParentNoteId;
|
||||
|
||||
this.childParentToBranch[childNoteId + '-' + newParentNoteId] = branchId;
|
||||
delete this.childParentToBranch[childNoteId + '-' + oldParentNoteId]; // this is correct because we know that oldParentId isn't same as newParentId
|
||||
|
||||
// remove old associations
|
||||
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== oldParentNoteId);
|
||||
this.children[oldParentNoteId] = this.children[oldParentNoteId].filter(ch => ch !== childNoteId);
|
||||
|
||||
// add new associations
|
||||
this.parents[childNoteId].push(newParentNoteId);
|
||||
|
||||
const children = this.children[newParentNoteId] = this.children[newParentNoteId] || []; // this might be first child
|
||||
|
||||
// we try to put the note into precise order which might be used again by lazy-loaded nodes
|
||||
if (beforeNoteId && children.includes(beforeNoteId)) {
|
||||
children.splice(children.indexOf(beforeNoteId), 0, childNoteId);
|
||||
}
|
||||
else if (afterNoteId && children.includes(afterNoteId)) {
|
||||
children.splice(children.indexOf(afterNoteId) + 1, 0, childNoteId);
|
||||
}
|
||||
else {
|
||||
children.push(childNoteId);
|
||||
return this.branches[branchId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ class TreeContextMenu {
|
||||
}
|
||||
|
||||
async getContextMenuItems() {
|
||||
const branch = await treeCache.getBranch(this.node.data.branchId);
|
||||
const note = await treeCache.getNote(this.node.data.noteId);
|
||||
const branch = treeCache.getBranch(this.node.data.branchId);
|
||||
const parentNote = await treeCache.getNote(branch.parentNoteId);
|
||||
const isNotRoot = note.noteId !== 'root';
|
||||
const isHoisted = note.noteId === await hoistedNoteService.getHoistedNoteId();
|
||||
@@ -39,8 +39,9 @@ class TreeContextMenu {
|
||||
const noSelectedNotes = selNodes.length === 0
|
||||
|| (selNodes.length === 1 && selNodes[0] === this.node);
|
||||
|
||||
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNote.type !== 'search';
|
||||
const insertChildNoteEnabled = note.type !== 'search';
|
||||
const notSearch = note.type !== 'search';
|
||||
const parentNotSearch = parentNote.type !== 'search';
|
||||
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
|
||||
|
||||
return [
|
||||
{ title: "Open in new tab", cmd: "openInTab", uiIcon: "empty", enabled: noSelectedNotes },
|
||||
@@ -48,15 +49,15 @@ class TreeContextMenu {
|
||||
items: insertNoteAfterEnabled ? this.getNoteTypeItems("insertNoteAfter") : null,
|
||||
enabled: insertNoteAfterEnabled && noSelectedNotes },
|
||||
{ title: "Insert child note <kbd>Ctrl+P</kbd>", cmd: "insertChildNote", uiIcon: "plus",
|
||||
items: insertChildNoteEnabled ? this.getNoteTypeItems("insertChildNote") : null,
|
||||
enabled: insertChildNoteEnabled && noSelectedNotes },
|
||||
items: notSearch ? this.getNoteTypeItems("insertChildNote") : null,
|
||||
enabled: notSearch && noSelectedNotes },
|
||||
{ title: "Delete <kbd>Delete</kbd>", cmd: "delete", uiIcon: "trash",
|
||||
enabled: isNotRoot && !isHoisted && parentNote.type !== 'search' },
|
||||
enabled: isNotRoot && !isHoisted && parentNotSearch },
|
||||
{ title: "----" },
|
||||
isHoisted ? null : { title: "Hoist note <kbd>Ctrl-H</kbd>", cmd: "hoist", uiIcon: "empty", enabled: noSelectedNotes },
|
||||
isHoisted ? null : { title: "Hoist note <kbd>Ctrl-H</kbd>", cmd: "hoist", uiIcon: "empty", enabled: noSelectedNotes && notSearch },
|
||||
!isHoisted || !isNotRoot ? null : { title: "Unhoist note <kbd>Ctrl-H</kbd>", cmd: "unhoist", uiIcon: "arrow-up" },
|
||||
{ title: "Edit branch prefix <kbd>F2</kbd>", cmd: "editBranchPrefix", uiIcon: "empty",
|
||||
enabled: isNotRoot && parentNote.type !== 'search' && noSelectedNotes},
|
||||
enabled: isNotRoot && parentNotSearch && noSelectedNotes},
|
||||
{ title: "----" },
|
||||
{ title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check", enabled: noSelectedNotes },
|
||||
{ title: "Unprotect subtree", cmd: "unprotectSubtree", uiIcon: "shield-close", enabled: noSelectedNotes },
|
||||
@@ -64,22 +65,22 @@ class TreeContextMenu {
|
||||
{ title: "Copy / clone <kbd>Ctrl+C</kbd>", cmd: "copy", uiIcon: "files",
|
||||
enabled: isNotRoot },
|
||||
{ title: "Cut <kbd>Ctrl+X</kbd>", cmd: "cut", uiIcon: "scissors",
|
||||
enabled: isNotRoot },
|
||||
enabled: isNotRoot && !isHoisted && parentNotSearch },
|
||||
{ title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "clipboard",
|
||||
enabled: !clipboard.isEmpty() && note.type !== 'search' && noSelectedNotes },
|
||||
enabled: !clipboard.isEmpty() && notSearch && noSelectedNotes },
|
||||
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard",
|
||||
enabled: !clipboard.isEmpty() && isNotRoot && parentNote.type !== 'search' && noSelectedNotes },
|
||||
enabled: !clipboard.isEmpty() && isNotRoot && parentNotSearch && noSelectedNotes },
|
||||
{ title: "Duplicate note here", cmd: "duplicateNote", uiIcon: "empty",
|
||||
enabled: noSelectedNotes && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
||||
enabled: noSelectedNotes && parentNotSearch && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
||||
{ title: "----" },
|
||||
{ title: "Export", cmd: "export", uiIcon: "empty",
|
||||
enabled: note.type !== 'search' && noSelectedNotes },
|
||||
enabled: notSearch && noSelectedNotes },
|
||||
{ title: "Import into note", cmd: "importIntoNote", uiIcon: "empty",
|
||||
enabled: note.type !== 'search' && noSelectedNotes },
|
||||
enabled: notSearch && noSelectedNotes },
|
||||
{ title: "----" },
|
||||
{ title: "Collapse subtree <kbd>Alt+-</kbd>", cmd: "collapseSubtree", uiIcon: "align-justify", enabled: noSelectedNotes },
|
||||
{ title: "Force note sync", cmd: "forceNoteSync", uiIcon: "refresh", enabled: noSelectedNotes },
|
||||
{ title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "empty", enabled: noSelectedNotes }
|
||||
{ title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "empty", enabled: noSelectedNotes && notSearch }
|
||||
].filter(row => row !== null);
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ class TreeContextMenu {
|
||||
hoistedNoteService.unhoist();
|
||||
}
|
||||
else if (cmd === "duplicateNote") {
|
||||
const branch = await treeCache.getBranch(this.node.data.branchId);
|
||||
const branch = treeCache.getBranch(this.node.data.branchId);
|
||||
|
||||
treeService.duplicateNote(this.node.data.noteId, branch.parentNoteId);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import treeChangesService from "./branches.js";
|
||||
import treeService from "./tree.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
import clipboard from "./clipboard.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
|
||||
const keyBindings = {
|
||||
"del": node => {
|
||||
@@ -130,12 +131,16 @@ const keyBindings = {
|
||||
}
|
||||
},
|
||||
"ctrl+h": node => {
|
||||
hoistedNoteService.getHoistedNoteId().then(hoistedNoteId => {
|
||||
hoistedNoteService.getHoistedNoteId().then(async hoistedNoteId => {
|
||||
if (node.data.noteId === hoistedNoteId) {
|
||||
hoistedNoteService.unhoist();
|
||||
}
|
||||
else {
|
||||
hoistedNoteService.setHoistedNoteId(node.data.noteId);
|
||||
const note = await treeCache.getNote(node.data.noteId);
|
||||
|
||||
if (note.type !== 'search') {
|
||||
hoistedNoteService.setHoistedNoteId(node.data.noteId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -59,10 +59,14 @@ async function getNoteTitle(noteId, parentNoteId = null) {
|
||||
let {title} = note;
|
||||
|
||||
if (parentNoteId !== null) {
|
||||
const branch = await treeCache.getBranchByChildParent(noteId, parentNoteId);
|
||||
const branchId = note.parentToBranch[parentNoteId];
|
||||
|
||||
if (branch && branch.prefix) {
|
||||
title = branch.prefix + ' - ' + title;
|
||||
if (branchId) {
|
||||
const branch = treeCache.getBranch(branchId);
|
||||
|
||||
if (branch && branch.prefix) {
|
||||
title = branch.prefix + ' - ' + title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import utils from './utils.js';
|
||||
import toastService from "./toast.js";
|
||||
import treeService from "./tree.js";
|
||||
|
||||
const $outstandingSyncsCount = $("#outstanding-syncs-count");
|
||||
|
||||
@@ -48,14 +47,15 @@ async function handleMessage(event) {
|
||||
}
|
||||
|
||||
if (message.type === 'sync') {
|
||||
const syncRows = message.data;
|
||||
lastPingTs = Date.now();
|
||||
|
||||
$outstandingSyncsCount.html(message.outstandingSyncs);
|
||||
|
||||
if (message.data.length > 0) {
|
||||
console.debug(utils.now(), "Sync data: ", message.data);
|
||||
if (syncRows.length > 0) {
|
||||
console.debug(utils.now(), "Sync data: ", syncRows);
|
||||
|
||||
syncDataQueue.push(...message.data);
|
||||
syncDataQueue.push(...syncRows);
|
||||
|
||||
// first wait for all the preceding consumers to finish
|
||||
while (consumeQueuePromise) {
|
||||
@@ -70,6 +70,8 @@ async function handleMessage(event) {
|
||||
// finish and set to null to signal somebody else can pick it up
|
||||
consumeQueuePromise = null;
|
||||
}
|
||||
|
||||
checkSyncIdListeners();
|
||||
}
|
||||
else if (message.type === 'sync-hash-check-failed') {
|
||||
toastService.showError("Sync check failed!", 60000);
|
||||
@@ -82,8 +84,6 @@ async function handleMessage(event) {
|
||||
let syncIdReachedListeners = [];
|
||||
|
||||
function waitForSyncId(desiredSyncId) {
|
||||
console.log("Waiting for ", desiredSyncId);
|
||||
|
||||
if (desiredSyncId <= lastSyncId) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -91,13 +91,26 @@ function waitForSyncId(desiredSyncId) {
|
||||
return new Promise((res, rej) => {
|
||||
syncIdReachedListeners.push({
|
||||
desiredSyncId,
|
||||
resolvePromise: res
|
||||
resolvePromise: res,
|
||||
start: Date.now()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function checkSyncIdListeners() {
|
||||
syncIdReachedListeners
|
||||
.filter(l => l.desiredSyncId <= lastSyncId)
|
||||
.forEach(l => l.resolvePromise());
|
||||
|
||||
syncIdReachedListeners = syncIdReachedListeners
|
||||
.filter(l => l.desiredSyncId > lastSyncId);
|
||||
|
||||
syncIdReachedListeners.filter(l => Date.now() > l.start - 60000)
|
||||
.forEach(l => console.log(`Waiting for syncId ${l.desiredSyncId} while current is ${lastSyncId} for ${Math.floor((Date.now() - l.start) / 1000)}s`));
|
||||
}
|
||||
|
||||
async function consumeSyncData() {
|
||||
if (syncDataQueue.length >= 0) {
|
||||
if (syncDataQueue.length > 0) {
|
||||
const allSyncData = syncDataQueue;
|
||||
syncDataQueue = [];
|
||||
|
||||
@@ -111,13 +124,6 @@ async function consumeSyncData() {
|
||||
|
||||
lastSyncId = allSyncData[allSyncData.length - 1].id;
|
||||
}
|
||||
|
||||
syncIdReachedListeners
|
||||
.filter(l => l.desiredSyncId <= lastSyncId)
|
||||
.forEach(l => l.resolvePromise());
|
||||
|
||||
syncIdReachedListeners = syncIdReachedListeners
|
||||
.filter(l => l.desiredSyncId > lastSyncId);
|
||||
}
|
||||
|
||||
function connectWebSocket() {
|
||||
@@ -140,7 +146,7 @@ setTimeout(() => {
|
||||
|
||||
setInterval(async () => {
|
||||
if (Date.now() - lastPingTs > 30000) {
|
||||
console.log("Lost connection to server");
|
||||
console.log(utils.now(), "Lost connection to server");
|
||||
}
|
||||
|
||||
if (ws.readyState === ws.OPEN) {
|
||||
@@ -150,13 +156,28 @@ setTimeout(() => {
|
||||
}));
|
||||
}
|
||||
else if (ws.readyState === ws.CLOSED || ws.readyState === ws.CLOSING) {
|
||||
console.log("WS closed or closing, trying to reconnect");
|
||||
console.log(utils.now(), "WS closed or closing, trying to reconnect");
|
||||
|
||||
ws = connectWebSocket();
|
||||
}
|
||||
}, 1000);
|
||||
}, 0);
|
||||
|
||||
subscribeToMessages(message => {
|
||||
if (message.type === 'sync-pull-in-progress') {
|
||||
toastService.showPersistent({
|
||||
id: 'sync',
|
||||
title: "Sync status",
|
||||
message: "Sync update in progress",
|
||||
icon: "refresh"
|
||||
});
|
||||
}
|
||||
else if (message.type === 'sync-pull-finished') {
|
||||
// this gives user a chance to see the toast in case of fast sync finish
|
||||
setTimeout(() => toastService.closePersistent('sync'), 1000);
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
logError,
|
||||
subscribeToMessages,
|
||||
|
||||
@@ -32,17 +32,16 @@ class EditedNotesWidget extends StandardWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
const noteIds = editedNotes.flatMap(note => note.notePath);
|
||||
const noteIds = editedNotes.flatMap(note => note.noteId);
|
||||
|
||||
await treeCache.getNotes(noteIds, true); // preload all at once
|
||||
|
||||
const $list = $('<ul>');
|
||||
|
||||
for (const editedNote of editedNotes) {
|
||||
const note = await treeCache.getNote(editedNote.noteId, true);
|
||||
const $item = $("<li>");
|
||||
|
||||
if (!note) {
|
||||
if (editedNote.isDeleted) {
|
||||
$item.append($("<i>").text(editedNote.title + " (deleted)"));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -29,6 +29,7 @@ class LinkMapWidget extends StandardWidget {
|
||||
}
|
||||
|
||||
async doRenderBody() {
|
||||
this.$body.css('opacity', 0);
|
||||
this.$body.html(TPL);
|
||||
|
||||
const $linkMapContainer = this.$body.find('.link-map-container');
|
||||
@@ -43,6 +44,8 @@ class LinkMapWidget extends StandardWidget {
|
||||
});
|
||||
|
||||
await this.linkMapService.render();
|
||||
|
||||
this.$body.animate({opacity: 1}, 300);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -3,16 +3,14 @@
|
||||
const cloningService = require('../../services/cloning');
|
||||
|
||||
async function cloneNoteToParent(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const parentNoteId = req.params.parentNoteId;
|
||||
const prefix = req.body.prefix;
|
||||
const {noteId, parentNoteId} = req.params;
|
||||
const {prefix} = req.body;
|
||||
|
||||
return await cloningService.cloneNoteToParent(noteId, parentNoteId, prefix);
|
||||
}
|
||||
|
||||
async function cloneNoteAfter(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const afterBranchId = req.params.afterBranchId;
|
||||
const {noteId, afterBranchId} = req.params;
|
||||
|
||||
return await cloningService.cloneNoteAfter(noteId, afterBranchId);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,9 @@ async function update(name, value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
log.info(`Updating option ${name} to ${value}`);
|
||||
if (name !== 'openTabs') {
|
||||
log.info(`Updating option ${name} to ${value}`);
|
||||
}
|
||||
|
||||
await optionService.setOption(name, value);
|
||||
|
||||
|
||||
@@ -6,9 +6,17 @@ const protectedSessionService = require('../../services/protected_session');
|
||||
const noteCacheService = require('../../services/note_cache');
|
||||
|
||||
async function getNotes(noteIds) {
|
||||
// we return also deleted notes which have been specifically asked for
|
||||
const notes = await sql.getManyRows(`
|
||||
SELECT noteId, title, isProtected, type, mime
|
||||
FROM notes WHERE isDeleted = 0 AND noteId IN (???)`, noteIds);
|
||||
SELECT
|
||||
noteId,
|
||||
title,
|
||||
isProtected,
|
||||
type,
|
||||
mime,
|
||||
isDeleted
|
||||
FROM notes
|
||||
WHERE noteId IN (???)`, noteIds);
|
||||
|
||||
const cssClassLabels = await sql.getManyRows(`
|
||||
SELECT noteId, value FROM attributes WHERE isDeleted = 0 AND type = 'label'
|
||||
@@ -32,6 +40,8 @@ async function getNotes(noteIds) {
|
||||
|
||||
protectedSessionService.decryptNotes(notes);
|
||||
|
||||
await noteCacheService.loadedPromise;
|
||||
|
||||
notes.forEach(note => {
|
||||
note.isProtected = !!note.isProtected;
|
||||
note.archived = noteCacheService.isArchived(note.noteId)
|
||||
@@ -40,19 +50,31 @@ async function getNotes(noteIds) {
|
||||
return notes;
|
||||
}
|
||||
|
||||
async function getRelations(noteIds) {
|
||||
// we need to fetch both parentNoteId and noteId matches because we can have loaded child
|
||||
// of which only some of the parents has been loaded.
|
||||
// also now with note hoisting, it is possible to have the note displayed without its parent chain being loaded
|
||||
async function getNotesAndBranches(noteIds) {
|
||||
noteIds = Array.from(new Set(noteIds));
|
||||
const notes = await getNotes(noteIds);
|
||||
|
||||
const relations = await sql.getManyRows(`SELECT branchId, noteId AS 'childNoteId', parentNoteId, notePosition FROM branches WHERE isDeleted = 0
|
||||
AND (parentNoteId IN (???) OR noteId IN (???))`, noteIds);
|
||||
noteIds = notes.map(n => n.noteId);
|
||||
|
||||
// although we're fetching relations for multiple notes, ordering will stay correct for single note as well - relations are being added into tree cache in the order they were returned
|
||||
// cannot use ORDER BY because of usage of getManyRows which is not a single SQL query
|
||||
relations.sort((a, b) => a.notePosition > b.notePosition ? 1 : -1);
|
||||
const branches = await sql.getManyRows(`
|
||||
SELECT
|
||||
branches.branchId,
|
||||
branches.noteId,
|
||||
branches.parentNoteId,
|
||||
branches.notePosition,
|
||||
branches.prefix,
|
||||
branches.isExpanded
|
||||
FROM branches
|
||||
WHERE branches.isDeleted = 0
|
||||
AND (branches.noteId IN (???) OR parentNoteId IN (???))`, noteIds);
|
||||
|
||||
return relations;
|
||||
// sorting in memory is faster
|
||||
branches.sort((a, b) => a.notePosition - b.notePosition < 0 ? -1 : 1);
|
||||
|
||||
return {
|
||||
branches,
|
||||
notes
|
||||
};
|
||||
}
|
||||
|
||||
async function getTree() {
|
||||
@@ -60,7 +82,7 @@ async function getTree() {
|
||||
|
||||
// we fetch all branches of notes, even if that particular branch isn't visible
|
||||
// this allows us to e.g. detect and properly display clones
|
||||
const branches = await sql.getRows(`
|
||||
let noteIds = await sql.getColumn(`
|
||||
WITH RECURSIVE
|
||||
tree(branchId, noteId, isExpanded) AS (
|
||||
SELECT branchId, noteId, isExpanded FROM branches WHERE noteId = ?
|
||||
@@ -69,44 +91,15 @@ async function getTree() {
|
||||
JOIN tree ON branches.parentNoteId = tree.noteId
|
||||
WHERE tree.isExpanded = 1 AND branches.isDeleted = 0
|
||||
)
|
||||
SELECT branches.* FROM tree JOIN branches USING(noteId) WHERE branches.isDeleted = 0 ORDER BY branches.notePosition`, [hoistedNoteId]);
|
||||
SELECT noteId FROM tree`, [hoistedNoteId]);
|
||||
|
||||
// we also want root branch in there because all the paths start with root
|
||||
branches.push(await sql.getRow(`SELECT * FROM branches WHERE branchId = 'root'`));
|
||||
noteIds.push('root');
|
||||
|
||||
const noteIds = Array.from(new Set(branches.map(b => b.noteId)));
|
||||
|
||||
const notes = await getNotes(noteIds);
|
||||
|
||||
const relations = await getRelations(noteIds);
|
||||
|
||||
return {
|
||||
branches,
|
||||
notes,
|
||||
relations
|
||||
};
|
||||
return await getNotesAndBranches(noteIds);
|
||||
}
|
||||
|
||||
async function load(req) {
|
||||
let noteIds = req.body.noteIds;
|
||||
const branchIds = req.body.branchIds;
|
||||
|
||||
if (branchIds && branchIds.length > 0) {
|
||||
noteIds = (await sql.getManyRows(`SELECT noteId FROM branches WHERE isDeleted = 0 AND branchId IN(???)`, branchIds))
|
||||
.map(note => note.noteId);
|
||||
}
|
||||
|
||||
const branches = await sql.getManyRows(`SELECT * FROM branches WHERE isDeleted = 0 AND noteId IN (???)`, noteIds);
|
||||
|
||||
const notes = await getNotes(noteIds);
|
||||
|
||||
const relations = await getRelations(noteIds);
|
||||
|
||||
return {
|
||||
branches,
|
||||
notes,
|
||||
relations
|
||||
};
|
||||
return await getNotesAndBranches(req.body.noteIds);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2019-10-21T21:59:17+02:00", buildRevision: "132360b46bfd326d8f50d71fed04ab4af969f3cb" };
|
||||
module.exports = { buildDate:"2019-11-05T21:49:16+01:00", buildRevision: "72fda89360d924aedf7a26216fd387346254dfd3" };
|
||||
|
||||
@@ -75,7 +75,7 @@ async function cloneNoteAfter(noteId, afterBranchId) {
|
||||
|
||||
const validationResult = await treeService.validateParentChild(afterNote.parentNoteId, noteId);
|
||||
|
||||
if (!validationResult.result) {
|
||||
if (!validationResult.success) {
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ async function checkContentHashes(otherHashes) {
|
||||
|
||||
if (key !== 'recent_notes') {
|
||||
// let's not get alarmed about recent notes which get updated often and can cause failures in race conditions
|
||||
await ws.sendMessageToAllClients({type: 'sync-hash-check-failed'});
|
||||
ws.sendMessageToAllClients({type: 'sync-hash-check-failed'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ function request(req) {
|
||||
}
|
||||
}
|
||||
|
||||
if (req.url.includes(".js.map") || req.url.includes(".css.map")) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(req.method + " " + req.url);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ const hoistedNoteService = require('./hoisted_note');
|
||||
const stringSimilarity = require('string-similarity');
|
||||
|
||||
let loaded = false;
|
||||
let loadedPromiseResolve;
|
||||
/** Is resolved after the initial load */
|
||||
let loadedPromise = new Promise(res => loadedPromiseResolve = res);
|
||||
|
||||
let noteTitles = {};
|
||||
let protectedNoteTitles = {};
|
||||
let noteIds;
|
||||
@@ -24,9 +28,9 @@ async function load() {
|
||||
|
||||
prefixes = await sql.getMap(`SELECT noteId || '-' || parentNoteId, prefix FROM branches WHERE prefix IS NOT NULL AND prefix != ''`);
|
||||
|
||||
const relations = await sql.getRows(`SELECT branchId, noteId, parentNoteId FROM branches WHERE isDeleted = 0`);
|
||||
const branches = await sql.getRows(`SELECT branchId, noteId, parentNoteId FROM branches WHERE isDeleted = 0`);
|
||||
|
||||
for (const rel of relations) {
|
||||
for (const rel of branches) {
|
||||
childToParent[rel.noteId] = childToParent[rel.noteId] || [];
|
||||
childToParent[rel.noteId].push(rel.parentNoteId);
|
||||
childParentToBranchId[`${rel.noteId}-${rel.parentNoteId}`] = rel.branchId;
|
||||
@@ -43,6 +47,7 @@ async function load() {
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
loadedPromiseResolve();
|
||||
}
|
||||
|
||||
async function loadProtectedNotes() {
|
||||
@@ -98,7 +103,7 @@ async function findNotes(query) {
|
||||
let noteIds = Object.keys(noteTitles);
|
||||
|
||||
if (protectedSessionService.isProtectedSessionAvailable()) {
|
||||
noteIds = noteIds.concat(Object.keys(protectedNoteTitles));
|
||||
noteIds = [...new Set(noteIds.concat(Object.keys(protectedNoteTitles)))];
|
||||
}
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
@@ -169,34 +174,6 @@ async function findNotes(query) {
|
||||
return apiResults;
|
||||
}
|
||||
|
||||
function isNotePathArchived(notePath) {
|
||||
// if the note is archived directly
|
||||
if (archived[notePath[notePath.length - 1]] !== undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < notePath.length - 1; i++) {
|
||||
// this is going through parents so archived must be inheritable
|
||||
if (archived[notePath[i]] === 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This assumes that note is available. "archived" note means that there isn't a single non-archived note-path
|
||||
* leading to this note.
|
||||
*
|
||||
* @param noteId
|
||||
*/
|
||||
function isArchived(noteId) {
|
||||
const notePath = getSomePath(noteId);
|
||||
|
||||
return isNotePathArchived(notePath);
|
||||
}
|
||||
|
||||
function search(noteId, tokens, path, results) {
|
||||
if (tokens.length === 0) {
|
||||
const retPath = getSomePath(noteId, path);
|
||||
@@ -247,6 +224,34 @@ function search(noteId, tokens, path, results) {
|
||||
}
|
||||
}
|
||||
|
||||
function isNotePathArchived(notePath) {
|
||||
// if the note is archived directly
|
||||
if (archived[notePath[notePath.length - 1]] !== undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < notePath.length - 1; i++) {
|
||||
// this is going through parents so archived must be inheritable
|
||||
if (archived[notePath[i]] === 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This assumes that note is available. "archived" note means that there isn't a single non-archived note-path
|
||||
* leading to this note.
|
||||
*
|
||||
* @param noteId
|
||||
*/
|
||||
function isArchived(noteId) {
|
||||
const notePath = getSomePath(noteId);
|
||||
|
||||
return isNotePathArchived(notePath);
|
||||
}
|
||||
|
||||
function getNoteTitle(noteId, parentNoteId) {
|
||||
const prefix = prefixes[noteId + '-' + parentNoteId];
|
||||
|
||||
@@ -449,7 +454,10 @@ eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED
|
||||
prefixes[branch.noteId + '-' + branch.parentNoteId] = branch.prefix;
|
||||
}
|
||||
|
||||
childToParent[branch.noteId].push(branch.parentNoteId);
|
||||
if (!childToParent[branch.noteId].includes(branch.parentNoteId)) {
|
||||
childToParent[branch.noteId].push(branch.parentNoteId);
|
||||
}
|
||||
|
||||
resortChildToParent(branch.noteId);
|
||||
|
||||
childParentToBranchId[branch.noteId + '-' + branch.parentNoteId] = branch.branchId;
|
||||
@@ -476,7 +484,7 @@ eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED
|
||||
// will sort the childs so that non-archived are first and archived at the end
|
||||
// this is done so that non-archived paths are always explored as first when searching for note path
|
||||
function resortChildToParent(noteId) {
|
||||
if (!childToParent[noteId]) {
|
||||
if (!(noteId in childToParent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -494,14 +502,13 @@ function isAvailable(noteId) {
|
||||
}
|
||||
|
||||
eventService.subscribe(eventService.ENTER_PROTECTED_SESSION, () => {
|
||||
if (loaded) {
|
||||
loadProtectedNotes();
|
||||
}
|
||||
loadedPromise.then(() => loadProtectedNotes());
|
||||
});
|
||||
|
||||
sqlInit.dbReady.then(() => utils.stopWatch("Autocomplete load", load));
|
||||
sqlInit.dbReady.then(() => utils.stopWatch("Note cache load", load));
|
||||
|
||||
module.exports = {
|
||||
loadedPromise,
|
||||
findNotes,
|
||||
getNotePath,
|
||||
getNoteTitleForPath,
|
||||
|
||||
@@ -370,7 +370,7 @@ async function updateNote(noteId, noteUpdates) {
|
||||
note.isProtected = noteUpdates.isProtected;
|
||||
await note.save();
|
||||
|
||||
if (!['file', 'image'].includes(note.type)) {
|
||||
if (!['file', 'image', 'render'].includes(note.type)) {
|
||||
noteUpdates.content = await saveLinks(note, noteUpdates.content);
|
||||
|
||||
await note.setContent(noteUpdates.content);
|
||||
|
||||
@@ -14,6 +14,7 @@ const syncOptions = require('./sync_options');
|
||||
const syncMutexService = require('./sync_mutex');
|
||||
const cls = require('./cls');
|
||||
const request = require('./request');
|
||||
const ws = require('./ws');
|
||||
|
||||
let proxyToggle = true;
|
||||
|
||||
@@ -116,6 +117,8 @@ async function doLogin() {
|
||||
}
|
||||
|
||||
async function pullSync(syncContext) {
|
||||
let appliedPulls = 0;
|
||||
|
||||
while (true) {
|
||||
const lastSyncedPull = await getLastSyncedPull();
|
||||
const changesUri = '/api/sync/changed?lastSyncId=' + lastSyncedPull;
|
||||
@@ -140,16 +143,25 @@ async function pullSync(syncContext) {
|
||||
|
||||
for (const {sync, entity} of rows) {
|
||||
if (!sourceIdService.isLocalSourceId(sync.sourceId)) {
|
||||
if (appliedPulls === 0 && sync.entity !== 'recent_notes') { // send only for first
|
||||
ws.syncPullInProgress();
|
||||
|
||||
appliedPulls++;
|
||||
}
|
||||
|
||||
await syncUpdateService.updateEntity(sync, entity, syncContext.sourceId);
|
||||
}
|
||||
|
||||
stats.outstandingPulls = resp.maxSyncId - sync.id;
|
||||
|
||||
}
|
||||
|
||||
await setLastSyncedPull(rows[rows.length - 1].sync.id);
|
||||
}
|
||||
|
||||
if (appliedPulls > 0) {
|
||||
ws.syncPullFinished();
|
||||
}
|
||||
|
||||
log.info("Finished pull");
|
||||
}
|
||||
|
||||
@@ -167,9 +179,6 @@ async function pushSync(syncContext) {
|
||||
|
||||
const filteredSyncs = syncs.filter(sync => {
|
||||
if (sync.sourceId === syncContext.sourceId) {
|
||||
// too noisy
|
||||
//log.info(`Skipping push #${sync.id} ${sync.entityName} ${sync.entityId} because it originates from sync target`);
|
||||
|
||||
// this may set lastSyncedPush beyond what's actually sent (because of size limit)
|
||||
// so this is applied to the database only if there's no actual update
|
||||
// TODO: it would be better to simplify this somehow
|
||||
|
||||
@@ -25,13 +25,13 @@ class TaskContext {
|
||||
return taskContexts[taskId];
|
||||
}
|
||||
|
||||
async increaseProgressCount() {
|
||||
increaseProgressCount() {
|
||||
this.progressCount++;
|
||||
|
||||
if (Date.now() - this.lastSentCountTs >= 300) {
|
||||
this.lastSentCountTs = Date.now();
|
||||
|
||||
await ws.sendMessageToAllClients({
|
||||
ws.sendMessageToAllClients({
|
||||
type: 'task-progress-count',
|
||||
taskId: this.taskId,
|
||||
taskType: this.taskType,
|
||||
@@ -41,8 +41,8 @@ class TaskContext {
|
||||
}
|
||||
}
|
||||
|
||||
async reportError(message) {
|
||||
await ws.sendMessageToAllClients({
|
||||
reportError(message) {
|
||||
ws.sendMessageToAllClients({
|
||||
type: 'task-error',
|
||||
taskId: this.taskId,
|
||||
taskType: this.taskType,
|
||||
@@ -51,8 +51,8 @@ class TaskContext {
|
||||
});
|
||||
}
|
||||
|
||||
async taskSucceeded(result) {
|
||||
await ws.sendMessageToAllClients({
|
||||
taskSucceeded(result) {
|
||||
ws.sendMessageToAllClients({
|
||||
type: 'task-succeeded',
|
||||
taskId: this.taskId,
|
||||
taskType: this.taskType,
|
||||
|
||||
@@ -2,6 +2,7 @@ const WebSocket = require('ws');
|
||||
const utils = require('./utils');
|
||||
const log = require('./log');
|
||||
const sql = require('./sql');
|
||||
const syncMutexService = require('./sync_mutex');
|
||||
|
||||
let webSocketServer;
|
||||
|
||||
@@ -31,7 +32,7 @@ function init(httpServer, sessionParser) {
|
||||
log.error('JS Error: ' + message.error);
|
||||
}
|
||||
else if (message.type === 'ping') {
|
||||
sendPing(ws, message.lastSyncId);
|
||||
syncMutexService.doExclusively(async () => await sendPing(ws, message.lastSyncId));
|
||||
}
|
||||
else {
|
||||
log.error('Unrecognized message: ');
|
||||
@@ -41,7 +42,7 @@ function init(httpServer, sessionParser) {
|
||||
});
|
||||
}
|
||||
|
||||
async function sendMessage(client, message) {
|
||||
function sendMessage(client, message) {
|
||||
const jsonStr = JSON.stringify(message);
|
||||
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
@@ -49,7 +50,7 @@ async function sendMessage(client, message) {
|
||||
}
|
||||
}
|
||||
|
||||
async function sendMessageToAllClients(message) {
|
||||
function sendMessageToAllClients(message) {
|
||||
const jsonStr = JSON.stringify(message);
|
||||
|
||||
if (webSocketServer) {
|
||||
@@ -84,19 +85,29 @@ async function sendPing(client, lastSentSyncId) {
|
||||
|
||||
const stats = require('./sync').stats;
|
||||
|
||||
await sendMessage(client, {
|
||||
sendMessage(client, {
|
||||
type: 'sync',
|
||||
data: syncData,
|
||||
outstandingSyncs: stats.outstandingPushes + stats.outstandingPulls
|
||||
});
|
||||
}
|
||||
|
||||
async function refreshTree() {
|
||||
await sendMessageToAllClients({ type: 'refresh-tree' });
|
||||
function refreshTree() {
|
||||
sendMessageToAllClients({ type: 'refresh-tree' });
|
||||
}
|
||||
|
||||
function syncPullInProgress() {
|
||||
sendMessageToAllClients({ type: 'sync-pull-in-progress' });
|
||||
}
|
||||
|
||||
function syncPullFinished() {
|
||||
sendMessageToAllClients({ type: 'sync-pull-finished' });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init,
|
||||
sendMessageToAllClients,
|
||||
refreshTree
|
||||
refreshTree,
|
||||
syncPullInProgress,
|
||||
syncPullFinished
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="note-detail-sidebar" style="width: <%= sidebarWidthPercent %>%; min-width: <%= sidebarMinWidth %>px">
|
||||
<div class="note-detail-sidebar hide-toggle" style="width: <%= sidebarWidthPercent %>%; min-width: <%= sidebarMinWidth %>px">
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user