Compare commits

..

23 Commits

Author SHA1 Message Date
zadam 147d79c65c release 0.31.1-beta 2019-04-14 21:18:22 +02:00
zadam 77c9b64dc7 re-enable animation for expanding since it seems to fix fancytree rendering glitches 2019-04-14 19:43:44 +02:00
zadam 47cb7c7f5e not refreshing tree after sort operation because it messes with everything ... 2019-04-14 18:32:56 +02:00
zadam 1bd769827d faster opening of the date notes (no animation) 2019-04-14 18:16:15 +02:00
zadam 71916b5e28 empty icon for some menu actions do de-emphasize less important items 2019-04-14 13:51:21 +02:00
zadam b2d4330692 added button for reloading frontend 2019-04-14 12:48:50 +02:00
zadam 253a6ef081 added date note APIs to frontend script API 2019-04-14 12:24:48 +02:00
zadam e1e020c1a4 more reliable reimplementation of "create day sub note" 2019-04-14 12:18:52 +02:00
zadam 2b4413a1bd exposing tree cache methods to reload note's parents/children to frontend API 2019-04-13 22:56:45 +02:00
zadam dae674a7cd tree cache reloading 2019-04-13 22:10:16 +02:00
zadam 751bf94758 don't change sourceId for script execution which forces full tree reloads because it is annoying 2019-04-13 19:45:50 +02:00
zadam 4b934a4a81 fix sync / fulltext issue 2019-04-13 19:34:19 +02:00
zadam 7e374e795b fill sync rows to fix sync issues 2019-04-13 10:30:16 +02:00
zadam be378f71b0 sync checks for note_contents 2019-04-13 10:13:47 +02:00
zadam 27f74489fd fix login/logout redirects when not in the document root 2019-04-11 22:04:36 +02:00
zadam ae8f4ffbbe minor sync fix for fulltext 2019-04-11 21:44:35 +02:00
zadam 896776516b fix in page search in browser (didn't appear after ctrl+f) 2019-04-09 21:16:18 +02:00
zadam a27525af9e frontend API additions 2019-04-09 21:13:47 +02:00
zadam 83b4382787 missing cert and key error message 2019-04-08 20:08:29 +02:00
zadam ef1b32d586 search error handling & sanitize input for default fulltext 2019-04-02 22:52:42 +02:00
zadam fe3a0bc756 new find-in-page dialog (using electron-find) which actually works 2019-04-02 21:44:56 +02:00
zadam 2259e1d44d make sure to wait for DB connection to be up before starting ... 2019-04-02 19:42:41 +02:00
zadam 9ca4a016eb fix linux server build 2019-04-01 23:11:06 +02:00
41 changed files with 1735 additions and 213 deletions
@@ -76,7 +76,6 @@ contentHash UNINDEXED</Arguments>
<index id="31" parent="6" name="sqlite_autoindex_api_tokens_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>apiTokenId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="32" parent="6">
@@ -145,25 +144,20 @@ contentHash UNINDEXED</Arguments>
<index id="44" parent="7" name="sqlite_autoindex_attributes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>attributeId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="45" parent="7" name="IDX_attributes_noteId_index">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="46" parent="7" name="IDX_attributes_name_value">
<ColNames>name
value</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="47" parent="7" name="IDX_attributes_name_index">
<ColNames>name</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="48" parent="7" name="IDX_attributes_value_index">
<ColNames>value</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="49" parent="7">
<ColNames>attributeId</ColNames>
@@ -223,21 +217,17 @@ value</ColNames>
<index id="60" parent="8" name="sqlite_autoindex_branches_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>branchId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="61" parent="8" name="IDX_branches_noteId_parentNoteId">
<ColNames>noteId
parentNoteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="62" parent="8" name="IDX_branches_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="63" parent="8" name="IDX_branches_parentNoteId">
<ColNames>parentNoteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="64" parent="8">
<ColNames>branchId</ColNames>
@@ -265,7 +255,6 @@ parentNoteId</ColNames>
<index id="69" parent="9" name="sqlite_autoindex_event_log_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>eventId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="70" parent="9">
@@ -318,16 +307,13 @@ parentNoteId</ColNames>
<index id="79" parent="10" name="sqlite_autoindex_links_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>linkId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="80" parent="10" name="IDX_links_noteId_index">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="81" parent="10" name="IDX_links_targetNoteId_index">
<ColNames>targetNoteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="82" parent="10">
<ColNames>linkId</ColNames>
@@ -358,7 +344,6 @@ parentNoteId</ColNames>
<index id="87" parent="11" name="sqlite_autoindex_note_contents_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="88" parent="11">
@@ -376,7 +361,6 @@ parentNoteId</ColNames>
<index id="91" parent="12" name="sqlite_autoindex_note_fulltext_config_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>k</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="92" parent="12">
@@ -446,7 +430,6 @@ parentNoteId</ColNames>
<NameSurrogate>1</NameSurrogate>
<ColNames>segid
term</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="110" parent="16">
@@ -520,20 +503,16 @@ term</ColNames>
<index id="123" parent="17" name="sqlite_autoindex_note_revisions_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="124" parent="17" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="125" parent="17" name="IDX_note_revisions_dateModifiedFrom">
<ColNames>utcDateModifiedFrom</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="126" parent="17" name="IDX_note_revisions_dateModifiedTo">
<ColNames>utcDateModifiedTo</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="127" parent="17">
<ColNames>noteRevisionId</ColNames>
@@ -604,7 +583,6 @@ term</ColNames>
<index id="139" parent="18" name="sqlite_autoindex_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="140" parent="18">
@@ -646,7 +624,6 @@ term</ColNames>
<index id="147" parent="19" name="sqlite_autoindex_options_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>name</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="148" parent="19">
@@ -682,7 +659,6 @@ term</ColNames>
<index id="154" parent="20" name="sqlite_autoindex_recent_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>branchId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="155" parent="20">
@@ -703,7 +679,6 @@ term</ColNames>
<index id="158" parent="21" name="sqlite_autoindex_source_ids_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>sourceId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="159" parent="21">
@@ -766,12 +741,10 @@ term</ColNames>
<index id="172" parent="24" name="IDX_sync_entityName_entityId">
<ColNames>entityName
entityId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="173" parent="24" name="IDX_sync_utcSyncDate">
<ColNames>utcSyncDate</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="174" parent="24">
<ColNames>id</ColNames>
+2
View File
@@ -14,6 +14,8 @@ rm node-v${NODE_VERSION}-linux-x64.tar.xz
mv node-v${NODE_VERSION}-linux-x64 node
cp -r ../../node_modules/ ./
cp -r ../../images/ ./
cp -r ../../libraries/ ./
cp -r ../../src/ ./
cp -r ../../db/ ./
cp -r ../../package.json ./
BIN
View File
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
const syncTableService = require('../../src/services/sync_table');
module.exports = async () => {
await syncTableService.fillAllSyncRows();
};
+51 -51
View File
@@ -581,7 +581,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line326">line 326</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line347">line 347</a>
</li></ul></dd>
@@ -746,7 +746,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line195">line 195</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line216">line 216</a>
</li></ul></dd>
@@ -922,7 +922,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line337">line 337</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line358">line 358</a>
</li></ul></dd>
@@ -1026,7 +1026,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line624">line 624</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line645">line 645</a>
</li></ul></dd>
@@ -1126,7 +1126,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line652">line 652</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line673">line 673</a>
</li></ul></dd>
@@ -1230,7 +1230,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line638">line 638</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line659">line 659</a>
</li></ul></dd>
@@ -1334,7 +1334,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line66">line 66</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line75">line 75</a>
</li></ul></dd>
@@ -1434,7 +1434,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line513">line 513</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line534">line 534</a>
</li></ul></dd>
@@ -1665,7 +1665,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line536">line 536</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line557">line 557</a>
</li></ul></dd>
@@ -1861,7 +1861,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line574">line 574</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line595">line 595</a>
</li></ul></dd>
@@ -2057,7 +2057,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line583">line 583</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line604">line 604</a>
</li></ul></dd>
@@ -2157,7 +2157,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line90">line 90</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line111">line 111</a>
</li></ul></dd>
@@ -2306,7 +2306,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line424">line 424</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line445">line 445</a>
</li></ul></dd>
@@ -2471,7 +2471,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line220">line 220</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line241">line 241</a>
</li></ul></dd>
@@ -2636,7 +2636,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line212">line 212</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line233">line 233</a>
</li></ul></dd>
@@ -2789,7 +2789,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line436">line 436</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line457">line 457</a>
</li></ul></dd>
@@ -2897,7 +2897,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line599">line 599</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line620">line 620</a>
</li></ul></dd>
@@ -3001,7 +3001,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line617">line 617</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line638">line 638</a>
</li></ul></dd>
@@ -3101,7 +3101,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line180">line 180</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line201">line 201</a>
</li></ul></dd>
@@ -3205,7 +3205,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line664">line 664</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line685">line 685</a>
</li></ul></dd>
@@ -3358,7 +3358,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line430">line 430</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line451">line 451</a>
</li></ul></dd>
@@ -3523,7 +3523,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line236">line 236</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line257">line 257</a>
</li></ul></dd>
@@ -3688,7 +3688,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line228">line 228</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line249">line 249</a>
</li></ul></dd>
@@ -3841,7 +3841,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line448">line 448</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line469">line 469</a>
</li></ul></dd>
@@ -3997,7 +3997,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line442">line 442</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line463">line 463</a>
</li></ul></dd>
@@ -4105,7 +4105,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line590">line 590</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line611">line 611</a>
</li></ul></dd>
@@ -4205,7 +4205,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line161">line 161</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line182">line 182</a>
</li></ul></dd>
@@ -4313,7 +4313,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line608">line 608</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line629">line 629</a>
</li></ul></dd>
@@ -4413,7 +4413,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line187">line 187</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line208">line 208</a>
</li></ul></dd>
@@ -4589,7 +4589,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line317">line 317</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line338">line 338</a>
</li></ul></dd>
@@ -4693,7 +4693,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line631">line 631</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line652">line 652</a>
</li></ul></dd>
@@ -4846,7 +4846,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line412">line 412</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line433">line 433</a>
</li></ul></dd>
@@ -4999,7 +4999,7 @@
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line418">line 418</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line439">line 439</a>
</li></ul></dd>
@@ -5108,7 +5108,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line244">line 244</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line265">line 265</a>
</li></ul></dd>
@@ -5190,7 +5190,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line149">line 149</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line170">line 170</a>
</li></ul></dd>
@@ -5294,7 +5294,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line141">line 141</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line162">line 162</a>
</li></ul></dd>
@@ -5398,7 +5398,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line136">line 136</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line157">line 157</a>
</li></ul></dd>
@@ -5502,7 +5502,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line131">line 131</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line152">line 152</a>
</li></ul></dd>
@@ -5606,7 +5606,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line154">line 154</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line175">line 175</a>
</li></ul></dd>
@@ -5710,7 +5710,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line249">line 249</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line270">line 270</a>
</li></ul></dd>
@@ -5937,7 +5937,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line395">line 395</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line416">line 416</a>
</li></ul></dd>
@@ -6133,7 +6133,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line499">line 499</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line520">line 520</a>
</li></ul></dd>
@@ -6329,7 +6329,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line508">line 508</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line529">line 529</a>
</li></ul></dd>
@@ -6556,7 +6556,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line369">line 369</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line390">line 390</a>
</li></ul></dd>
@@ -6656,7 +6656,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line97">line 97</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line118">line 118</a>
</li></ul></dd>
@@ -6756,7 +6756,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line126">line 126</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line147">line 147</a>
</li></ul></dd>
@@ -6952,7 +6952,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line481">line 481</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line502">line 502</a>
</li></ul></dd>
@@ -7148,7 +7148,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line490">line 490</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line511">line 511</a>
</li></ul></dd>
@@ -7406,7 +7406,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line352">line 352</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line373">line 373</a>
</li></ul></dd>
@@ -7633,7 +7633,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line462">line 462</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line483">line 483</a>
</li></ul></dd>
@@ -7860,7 +7860,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line472">line 472</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line493">line 493</a>
</li></ul></dd>
+28 -6
View File
@@ -90,10 +90,31 @@ class Note extends Entity {
}
}
/*
* Note content has quite special handling - it's not a separate entity, but a lazily loaded
* part of Note entity with it's own sync. Reasons behind this hybrid design has been:
*
* - content can be quite large and it's not necessary to load it / fill memory for any note access even if we don't need a content, especially for bulk operations like search
* - changes in the note metadata or title should not trigger note content sync (so we keep separate utcDateModified and sync rows)
* - but to the user note content and title changes are one and the same - single dateModified (so all changes must go through Note and content is not a separate entity)
*/
/** @returns {Promise&lt;*>} */
async getContent() {
async getContent(silentNotFoundError = false) {
if (this.content === undefined) {
this.content = await sql.getValue(`SELECT content FROM note_contents WHERE noteId = ?`, [this.noteId]);
const res = await sql.getRow(`SELECT content, hash FROM note_contents WHERE noteId = ?`, [this.noteId]);
if (!res) {
if (silentNotFoundError) {
return undefined;
}
else {
throw new Error("Cannot find note content for noteId=" + this.noteId);
}
}
this.content = res.content;
this.contentHash = res.contentHash; // used only for note_fulltext consistency check
if (this.isProtected) {
if (this.isContentAvailable) {
@@ -123,6 +144,10 @@ class Note extends Entity {
/** @returns {Promise} */
async setContent(content) {
// force updating note itself so that dateChanged is represented correctly even for the content
this.forcedChange = true;
await this.save();
this.content = content;
const pojo = {
@@ -144,10 +169,6 @@ class Note extends Entity {
await sql.upsert("note_contents", "noteId", pojo);
await syncTableService.addNoteContentSync(this.noteId);
this.forcedChange = true;
await this.save();
}
/** @returns {Promise} */
@@ -736,6 +757,7 @@ class Note extends Entity {
delete pojo.isContentAvailable;
delete pojo.__attributeCache;
delete pojo.content;
delete pojo.contentHash;
}
async afterSaving() {
File diff suppressed because it is too large Load Diff
+118 -2
View File
@@ -199,7 +199,7 @@
<h4 class="name" id="utcDateCreated"><span class="type-signature"></span>utcDateCreated<span class="type-signature"></span></h4>
<h4 class="name" id="dateCreated"><span class="type-signature"></span>dateCreated<span class="type-signature"></span></h4>
@@ -257,7 +257,7 @@
<h4 class="name" id="utcDateModified"><span class="type-signature"></span>utcDateModified<span class="type-signature"></span></h4>
<h4 class="name" id="dateModified"><span class="type-signature"></span>dateModified<span class="type-signature"></span></h4>
@@ -314,6 +314,122 @@
<h4 class="name" id="utcDateCreated"><span class="type-signature"></span>utcDateCreated<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_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line20">line 20</a>
</li></ul></dd>
</dl>
<h4 class="name" id="utcDateModified"><span class="type-signature"></span>utcDateModified<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_full.js.html">entities/note_full.js</a>, <a href="entities_note_full.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
@@ -38,6 +38,12 @@ class NoteFull extends NoteShort {
/** @param {string} */
this.content = row.content;
/** @param {string} */
this.dateCreated = row.dateCreated;
/** @param {string} */
this.dateModified = row.dateModified;
/** @param {string} */
this.utcDateCreated = row.utcDateCreated;
+1 -1
View File
@@ -303,7 +303,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#line49">line 49</a>
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line53">line 53</a>
</li></ul></dd>
@@ -36,6 +36,7 @@ import noteDetailService from './note_detail.js';
import noteTypeService from './note_type.js';
import noteTooltipService from './note_tooltip.js';
import protectedSessionService from'./protected_session.js';
import dateNotesService from'./date_notes.js';
/**
* This is the main frontend API interface for scripts. It's published in the local "api" object.
@@ -53,6 +54,9 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
/** @property {object|null} entity whose event triggered this execution */
this.originEntity = originEntity;
// to keep consistency with backend API
this.dayjs = dayjs;
/**
* Activates note in the tree and in the note detail.
*
@@ -159,6 +163,14 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
}
};
/**
* Returns note by given noteId. If note is missing from cache, it's loaded.
**
* @param {string} noteId
* @return {Promise&lt;NoteShort>}
*/
this.getNote = async noteId => await treeCache.getNote(noteId);
/**
* Returns list of notes. If note is missing from cache, it's loaded.
*
@@ -171,6 +183,18 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
*/
this.getNotes = async (noteIds, silentNotFoundError = false) => await treeCache.getNotes(noteIds, silentNotFoundError);
/**
* @param {string} noteId
* @method
*/
this.reloadChildren = async noteId => await treeCache.reloadChildren(noteId);
/**
* @param {string} noteId
* @method
*/
this.reloadParents = async noteId => await treeCache.reloadParents(noteId);
/**
* Instance name identifies particular Trilium instance. It can be useful for scripts
* if some action needs to happen on only one specific instance.
@@ -238,6 +262,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
*/
this.getActiveNote = noteDetailService.getActiveNote;
/**
* @method
* @returns {string} returns note path of active note
*/
this.getActiveNotePath = treeService.getActiveNotePath;
/**
* This method checks whether user navigated away from the note from which the scripts has been started.
* This is necessary because script execution is async and by the time it is finished, the user might have
@@ -285,6 +315,41 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
* @method
*/
this.protectActiveNote = protectedSessionService.protectNoteAndSendToServer;
/**
* Returns date-note for today. If it doesn't exist, it is automatically created.
*
* @method
* @return {Promise&lt;NoteShort>}
*/
this.getTodayNote = dateNotesService.getTodayNote;
/**
* Returns date-note. If it doesn't exist, it is automatically created.
*
* @method
* @param {string} date - e.g. "2019-04-29"
* @return {Promise&lt;NoteShort>}
*/
this.getDateNote = dateNotesService.getDateNote;
/**
* Returns month-note. If it doesn't exist, it is automatically created.
*
* @method
* @param {string} month - e.g. "2019-04"
* @return {Promise&lt;NoteShort>}
*/
this.getMonthNote = dateNotesService.getMonthNote;
/**
* Returns year-note. If it doesn't exist, it is automatically created.
*
* @method
* @param {string} year - e.g. "2019"
* @return {Promise&lt;NoteShort>}
*/
this.getYearNote = dateNotesService.getYearNote;
}
export default FrontendScriptApi;</code></pre>
+3 -6
View File
@@ -30,6 +30,8 @@ function onClosed() {
}
async function createMainWindow() {
await sqlInit.dbConnection;
// if schema doesn't exist -> setup process
// if schema exists, then we need to wait until the migration process is finished
if (await sqlInit.schemaExists()) {
@@ -95,15 +97,10 @@ app.on('ready', async () => {
mainWindow = await createMainWindow();
const result = globalShortcut.register('CommandOrControl+Alt+P', cls.wrap(async () => {
const dateNoteService = require('./src/services/date_notes');
const dateUtils = require('./src/services/date_utils');
const parentNote = await dateNoteService.getDateNote(dateUtils.localNowDate());
// window may be hidden / not in focus
mainWindow.focus();
mainWindow.webContents.send('create-day-sub-note', parentNote.noteId);
mainWindow.webContents.send('create-day-sub-note');
}));
if (!result) {
+6 -1
View File
@@ -1,6 +1,6 @@
{
"name": "trilium",
"version": "0.30.7",
"version": "0.31.0-beta",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -3222,6 +3222,11 @@
}
}
},
"electron-find": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/electron-find/-/electron-find-1.0.4.tgz",
"integrity": "sha512-ZZK0PaxRJU47CGUxZgpbyLz29pr/hsQdXtMPNDJfX5q6EK1zPElSAmCwtvYleTam+URZ9326XNFGTLL5CWDwUA=="
},
"electron-in-page-search": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/electron-in-page-search/-/electron-in-page-search-1.3.2.tgz",
+2 -1
View File
@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "Trilium Notes",
"description": "Trilium Notes",
"version": "0.31.0-beta",
"version": "0.31.1-beta",
"license": "AGPL-3.0-only",
"main": "electron.js",
"bin": {
@@ -33,6 +33,7 @@
"ejs": "2.6.1",
"electron-debug": "2.1.0",
"electron-dl": "1.13.0",
"electron-find": "^1.0.4",
"electron-in-page-search": "1.3.2",
"electron-window-state": "5.0.3",
"express": "4.16.4",
+14 -5
View File
@@ -72,10 +72,19 @@ class Note extends Entity {
*/
/** @returns {Promise<*>} */
async getContent() {
async getContent(silentNotFoundError = false) {
if (this.content === undefined) {
const res = await sql.getRow(`SELECT content, hash FROM note_contents WHERE noteId = ?`, [this.noteId]);
if (!res) {
if (silentNotFoundError) {
return undefined;
}
else {
throw new Error("Cannot find note content for noteId=" + this.noteId);
}
}
this.content = res.content;
this.contentHash = res.contentHash; // used only for note_fulltext consistency check
@@ -107,6 +116,10 @@ class Note extends Entity {
/** @returns {Promise} */
async setContent(content) {
// force updating note itself so that dateChanged is represented correctly even for the content
this.forcedChange = true;
await this.save();
this.content = content;
const pojo = {
@@ -128,10 +141,6 @@ class Note extends Entity {
await sql.upsert("note_contents", "noteId", pojo);
await syncTableService.addNoteContentSync(this.noteId);
this.forcedChange = true;
await this.save();
}
/** @returns {Promise} */
+8 -13
View File
@@ -39,6 +39,7 @@ import linkService from './services/link.js';
import noteAutocompleteService from './services/note_autocomplete.js';
import macInit from './services/mac_init.js';
import cssLoader from './services/css_loader.js';
import dateNoteService from './services/date_notes.js';
// required for CKEditor image upload plugin
window.glob.getActiveNode = treeService.getActiveNode;
@@ -114,20 +115,14 @@ $("body").on("click", "a.external", function () {
});
if (utils.isElectron()) {
require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
await treeService.activateNote(parentNoteId);
require('electron').ipcRenderer.on('create-day-sub-note', async function(event) {
const todayNote = await dateNoteService.getTodayNote();
const node = await treeService.expandToNote(todayNote.noteId);
setTimeout(async () => {
const parentNode = treeService.getActiveNode();
const {note} = await treeService.createNote(parentNode, parentNode.data.noteId, 'into', {
type: "text",
isProtected: parentNode.data.isProtected
});
await treeService.activateNote(note.noteId);
}, 500);
await treeService.createNote(node, todayNote.noteId, 'into', {
type: "text",
isProtected: node.data.isProtected
});
});
}
@@ -3,7 +3,6 @@ import utils from './utils.js';
import server from './server.js';
import infoService from "./info.js";
import treeCache from "./tree_cache.js";
import treeBuilder from "./tree_builder.js";
async function moveBeforeNode(nodesToMove, beforeNode) {
nodesToMove = filterRootNote(nodesToMove);
@@ -0,0 +1,41 @@
import treeCache from "./tree_cache.js";
import server from "./server.js";
/** @return {NoteShort} */
async function getTodayNote() {
return await getDateNote(dayjs().format("YYYY-MM-DD"));
}
/** @return {NoteShort} */
async function getDateNote(date) {
const note = await server.get('date-notes/date/' + date);
await treeCache.reloadParents(note.noteId);
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);
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);
return await treeCache.getNote(note.noteId);
}
export default {
getTodayNote,
getDateNote,
getMonthNote,
getYearNote
}
+24 -17
View File
@@ -103,6 +103,7 @@ function registerEntrypoints() {
utils.bindShortcut('f5', utils.reloadApp);
$("#reload-frontend-button").click(utils.reloadApp);
utils.bindShortcut('ctrl+r', utils.reloadApp);
$("#open-dev-tools-button").toggle(utils.isElectron());
@@ -118,27 +119,33 @@ function registerEntrypoints() {
$("#open-dev-tools-button").click(openDevTools);
}
function openInPageSearch() {
if (utils.isElectron()) {
const $searchWindowWebview = $(".electron-in-page-search-window");
$searchWindowWebview.show();
let findInPage;
const searchInPage = require('electron-in-page-search').default;
const {remote} = require('electron');
if (utils.isElectron()) {
const { remote } = require('electron');
const { FindInPage } = require('electron-find');
const inPageSearch = searchInPage(remote.getCurrentWebContents(), {
searchWindowWebview: $searchWindowWebview[0],
//openDevToolsOfSearchWindow: true,
customCssPath: '/libraries/electron-in-page-search/default-style.css'
});
inPageSearch.openSearchWindow();
return false;
}
findInPage = new FindInPage(remote.getCurrentWebContents(), {
offsetTop: 10,
offsetRight: 10,
boxBgColor: 'var(--main-background-color)',
boxShadowColor: '#000',
inputColor: 'var(--input-text-color)',
inputBgColor: 'var(--input-background-color)',
inputFocusColor: '#555',
textColor: 'var(--main-text-color)',
textHoverBgColor: '#555',
caseSelectedColor: 'var(--main-border-color)'
});
}
utils.bindShortcut('ctrl+f', openInPageSearch);
if (utils.isElectron()) {
utils.bindShortcut('ctrl+f', () => {
findInPage.openFindWindow();
return false;
});
}
// FIXME: do we really need these at this point?
utils.bindShortcut("ctrl+shift+up", () => {
@@ -8,6 +8,7 @@ import noteDetailService from './note_detail.js';
import noteTypeService from './note_type.js';
import noteTooltipService from './note_tooltip.js';
import protectedSessionService from'./protected_session.js';
import dateNotesService from'./date_notes.js';
/**
* This is the main frontend API interface for scripts. It's published in the local "api" object.
@@ -25,6 +26,9 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
/** @property {object|null} entity whose event triggered this execution */
this.originEntity = originEntity;
// to keep consistency with backend API
this.dayjs = dayjs;
/**
* Activates note in the tree and in the note detail.
*
@@ -131,6 +135,14 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
}
};
/**
* Returns note by given noteId. If note is missing from cache, it's loaded.
**
* @param {string} noteId
* @return {Promise<NoteShort>}
*/
this.getNote = async noteId => await treeCache.getNote(noteId);
/**
* Returns list of notes. If note is missing from cache, it's loaded.
*
@@ -143,6 +155,18 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
*/
this.getNotes = async (noteIds, silentNotFoundError = false) => await treeCache.getNotes(noteIds, silentNotFoundError);
/**
* @param {string} noteId
* @method
*/
this.reloadChildren = async noteId => await treeCache.reloadChildren(noteId);
/**
* @param {string} noteId
* @method
*/
this.reloadParents = async noteId => await treeCache.reloadParents(noteId);
/**
* Instance name identifies particular Trilium instance. It can be useful for scripts
* if some action needs to happen on only one specific instance.
@@ -210,6 +234,12 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
*/
this.getActiveNote = noteDetailService.getActiveNote;
/**
* @method
* @returns {string} returns note path of active note
*/
this.getActiveNotePath = treeService.getActiveNotePath;
/**
* This method checks whether user navigated away from the note from which the scripts has been started.
* This is necessary because script execution is async and by the time it is finished, the user might have
@@ -257,6 +287,41 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null) {
* @method
*/
this.protectActiveNote = protectedSessionService.protectNoteAndSendToServer;
/**
* Returns date-note for today. If it doesn't exist, it is automatically created.
*
* @method
* @return {Promise<NoteShort>}
*/
this.getTodayNote = dateNotesService.getTodayNote;
/**
* Returns date-note. If it doesn't exist, it is automatically created.
*
* @method
* @param {string} date - e.g. "2019-04-29"
* @return {Promise<NoteShort>}
*/
this.getDateNote = dateNotesService.getDateNote;
/**
* Returns month-note. If it doesn't exist, it is automatically created.
*
* @method
* @param {string} month - e.g. "2019-04"
* @return {Promise<NoteShort>}
*/
this.getMonthNote = dateNotesService.getMonthNote;
/**
* Returns year-note. If it doesn't exist, it is automatically created.
*
* @method
* @param {string} year - e.g. "2019"
* @return {Promise<NoteShort>}
*/
this.getYearNote = dateNotesService.getYearNote;
}
export default FrontendScriptApi;
@@ -80,12 +80,17 @@ async function doSearch(searchText) {
return;
}
const results = await server.get('search/' + encodeURIComponent(searchText));
const response = await server.get('search/' + encodeURIComponent(searchText));
if (!response.success) {
infoService.showError("Search failed.", 3000);
return;
}
$searchResultsInner.empty();
$searchResults.show();
for (const result of results) {
for (const result of response.results) {
const link = $('<a>', {
href: 'javascript:',
text: result.title
+14 -12
View File
@@ -110,12 +110,7 @@ async function expandToNote(notePath, expandOpts) {
let node = getNode(childNoteId, parentNoteId);
if (!node && parentNoteId) {
const parents = getNodesByNoteId(parentNoteId);
for (const parent of parents) {
// force load parents. This is useful when fancytree doesn't contain recently created notes yet.
await parent.load(true);
}
await reloadNote(parentNoteId);
node = getNode(childNoteId, parentNoteId);
}
@@ -371,17 +366,21 @@ async function treeInitialized() {
const noteId = treeUtils.getNoteIdFromNotePath(startNotePath);
if (!await treeCache.getNote(noteId)) {
if (!await treeCache.noteExists(noteId)) {
// note doesn't exist so don't try to activate it
startNotePath = null;
}
if (startNotePath) {
const node = await activateNote(startNotePath);
// this is weird but it looks like even though init event has been called, but we the tree still
// can't find nodes for given path which causes double loading of data. Little timeout fixes this.
setTimeout(async () => {
const node = await activateNote(startNotePath);
// looks like this this doesn't work when triggered immediatelly after activating node
// so waiting a second helps
setTimeout(() => node.makeVisible({scrollIntoView: true}), 1000);
// looks like this this doesn't work when triggered immediatelly after activating node
// so waiting a second helps
setTimeout(() => node.makeVisible({scrollIntoView: true}), 1000);
}, 100);
}
}
@@ -760,6 +759,8 @@ async function checkFolderStatus(node) {
}
async function reloadNote(noteId) {
await treeCache.reloadChildren(noteId);
for (const node of getNodesByNoteId(noteId)) {
await node.load(true);
@@ -816,5 +817,6 @@ export default {
getNodesByNoteId,
checkFolderStatus,
reloadNote,
loadTreeCache
loadTreeCache,
expandToNote
};
+58 -1
View File
@@ -5,6 +5,9 @@ import infoService from "./info.js";
import messagingService from "./messaging.js";
import server from "./server.js";
/**
* TreeCache keeps a read only cache of note tree structure in frontend's memory.
*/
class TreeCache {
constructor() {
this.init();
@@ -17,8 +20,12 @@ class TreeCache {
}
init() {
/** @type {Object.<string, string>} */
this.parents = {};
/** @type {Object.<string, string>} */
this.children = {};
/** @type {Object.<string, string>} */
this.childParentToBranch = {};
/** @type {Object.<string, NoteShort>} */
@@ -46,6 +53,45 @@ class TreeCache {
}
}
/**
* Reload children of given noteId.
*/
async reloadChildren(noteId) {
const resp = await server.post('tree/load', { noteIds: [noteId] });
for (const childNoteId of this.children[noteId] || []) {
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId);
const branchId = this.getBranchIdByChildParent(childNoteId, noteId);
delete this.branches[branchId];
delete this.childParentToBranch[childNoteId + '-' + noteId];
}
this.children[noteId] = [];
delete this.notes[noteId];
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);
for (const parentNoteId of this.parents[noteId] || []) {
await this.reloadChildren(parentNoteId);
}
// this is done to load the new parents for the noteId
await this.reloadChildren(noteId);
}
/** @return {Promise<NoteShort[]>} */
async getNotes(noteIds, silentNotFoundError = false) {
const missingNoteIds = noteIds.filter(noteId => this.notes[noteId] === undefined);
@@ -53,6 +99,10 @@ class TreeCache {
const resp = await server.post('tree/load', { noteIds: missingNoteIds });
this.addResp(resp.notes, resp.branches, resp.relations);
for (const note of resp.notes) {
await this.reloadParents(note.noteId);
}
}
return noteIds.map(noteId => {
@@ -67,7 +117,14 @@ class TreeCache {
}).filter(note => note !== null);
}
/** @return NoteShort */
/** @return {Promise<boolean>} */
async noteExists(noteId) {
const notes = await this.getNotes([noteId], true);
return notes.length === 1;
}
/** @return {Promise<NoteShort>} */
async getNote(noteId) {
if (noteId === 'none') {
return null;
@@ -112,9 +112,9 @@ async function getTopLevelItems(event) {
{ title: "Delete <kbd>Delete</kbd>", cmd: "delete", uiIcon: "trash",
enabled: isNotRoot && parentNote.type !== 'search' },
{ title: "----" },
isHoisted ? null : { title: "Hoist note <kbd>Ctrl-H</kbd>", cmd: "hoist", uiIcon: "arrow-up" },
isHoisted ? null : { title: "Hoist note <kbd>Ctrl-H</kbd>", cmd: "hoist", uiIcon: "empty" },
!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: "pencil",
{ title: "Edit branch prefix <kbd>F2</kbd>", cmd: "editBranchPrefix", uiIcon: "empty",
enabled: isNotRoot && parentNote.type !== 'search'},
{ title: "----" },
{ title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check" },
@@ -129,14 +129,14 @@ async function getTopLevelItems(event) {
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard",
enabled: clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search' },
{ title: "----" },
{ title: "Export", cmd: "export", uiIcon: "arrow-up-right",
{ title: "Export", cmd: "export", uiIcon: "empty",
enabled: note.type !== 'search' },
{ title: "Import into note", cmd: "importIntoNote", uiIcon: "arrow-down-left",
{ title: "Import into note", cmd: "importIntoNote", uiIcon: "empty",
enabled: note.type !== 'search' },
{ title: "----" },
{ title: "Collapse subtree <kbd>Alt+-</kbd>", cmd: "collapseSubtree", uiIcon: "align-justify" },
{ title: "Force note sync", cmd: "forceNoteSync", uiIcon: "refresh" },
{ title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "arrows-v" }
{ title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "empty" }
].filter(row => row !== null);
}
+5
View File
@@ -928,4 +928,9 @@ a.external:after, a[href^="http://"]:after, a[href^="https://"]:after {
.card {
background-color: inherit !important;
border-color: var(--main-border-color) !important;
}
.jam-empty {
width: 1em;
display: inline-block;
}
+21
View File
@@ -0,0 +1,21 @@
"use strict";
const dateNoteService = require('../../services/date_notes');
async function getDateNote(req) {
return await dateNoteService.getDateNote(req.params.date);
}
async function getMonthNote(req) {
return await dateNoteService.getMonthNote(req.params.month);
}
async function getYearNote(req) {
return await dateNoteService.getYearNote(req.params.year);
}
module.exports = {
getDateNote,
getMonthNote,
getYearNote
};
+11 -1
View File
@@ -9,7 +9,17 @@ const searchService = require('../../services/search');
async function searchNotes(req) {
const noteIds = await searchService.searchForNoteIds(req.params.searchString);
return noteIds.map(noteCacheService.getNotePath).filter(res => !!res);
try {
return {
success: true,
results: noteIds.map(noteCacheService.getNotePath).filter(res => !!res)
}
}
catch {
return {
success: false
}
}
}
async function searchFromNote(req) {
+2 -2
View File
@@ -24,7 +24,7 @@ async function login(req, res) {
}
req.session.loggedIn = true;
res.redirect('/');
res.redirect('..');
});
}
else {
@@ -44,7 +44,7 @@ function logout(req, res) {
req.session.regenerate(() => {
req.session.loggedIn = false;
res.redirect('/');
res.redirect('login');
});
}
+5
View File
@@ -30,6 +30,7 @@ const scriptRoute = require('./api/script');
const senderRoute = require('./api/sender');
const filesRoute = require('./api/file_upload');
const searchRoute = require('./api/search');
const dateNotesRoute = require('./api/date_notes');
const log = require('../services/log');
const express = require('express');
@@ -153,6 +154,10 @@ function register(app) {
apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames);
apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute);
apiRoute(GET, '/api/date-notes/date/:date', dateNotesRoute.getDateNote);
apiRoute(GET, '/api/date-notes/month/:month', dateNotesRoute.getMonthNote);
apiRoute(GET, '/api/date-notes/year/:year', dateNotesRoute.getYearNote);
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.uploadImage, apiResultHandler);
+1 -1
View File
@@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 131;
const APP_DB_VERSION = 132;
const SYNC_VERSION = 8;
module.exports = {
+1 -1
View File
@@ -1 +1 @@
module.exports = { buildDate:"2019-04-01T21:50:32+02:00", buildRevision: "f47f3461e666d007668e03282f86b028012f7bef" };
module.exports = { buildDate:"2019-04-14T21:18:22+02:00", buildRevision: "77c9b64dc7a0b8f1f1e2502653269c1e8dde4e98" };
+1
View File
@@ -430,6 +430,7 @@ async function runSyncRowChecks(entityName, key) {
async function findSyncRowsIssues() {
await runSyncRowChecks("notes", "noteId");
await runSyncRowChecks("note_contents", "noteId");
await runSyncRowChecks("note_revisions", "noteRevisionId");
await runSyncRowChecks("branches", "branchId");
await runSyncRowChecks("recent_notes", "branchId");
-4
View File
@@ -1,7 +1,6 @@
const eventService = require('./events');
const scriptService = require('./script');
const treeService = require('./tree');
const messagingService = require('./messaging');
const log = require('./log');
const Attribute = require('../entities/attribute');
@@ -29,9 +28,6 @@ eventService.subscribe(eventService.NOTE_TITLE_CHANGED, async note => {
for (const parent of parents) {
if (await parent.hasLabel("sorted")) {
await treeService.sortNotesAlphabetically(parent.noteId);
messagingService.refreshTree();
break; // sending the message once is enough
}
}
}
+13 -5
View File
@@ -5,6 +5,11 @@ const html2plaintext = require('html2plaintext');
const noteIdQueue = [];
async function updateNoteFulltext(note) {
if (!note) {
// this might happen when note content is being synced before note itself
return;
}
if (note.isDeleted || note.isProtected || await note.hasLabel('archived')) {
await sql.execute(`DELETE
FROM note_fulltext
@@ -14,13 +19,16 @@ async function updateNoteFulltext(note) {
let contentHash = null;
if (['text', 'code'].includes(note.type)) {
content = await note.getContent();
content = await note.getContent(true);
if (note.type === 'text' && note.mime === 'text/html') {
content = html2plaintext(content);
// might not be available during sync before note_contents is synced
if (content) {
if (note.type === 'text' && note.mime === 'text/html') {
content = html2plaintext(content);
}
contentHash = note.contentHash;
}
contentHash = note.contentHash;
}
// optimistically try to update first ...
+5 -2
View File
@@ -45,18 +45,21 @@ function calculateSmartValue(v) {
module.exports = function (searchText) {
// if the string doesn't start with attribute then we consider it as just standard full text search
if (!searchText.trim().startsWith("@")) {
// replace with space instead of empty string since these characters are probably separators
const sanitizedSearchText = searchText.replace(/[^\w ]+/g, " ");
return [
{
relation: 'and',
name: 'text',
operator: '=',
value: searchText
value: sanitizedSearchText
},
{
relation: 'or',
name: 'noteId',
operator: '=',
value: searchText
value: sanitizedSearchText
}
]
}
-3
View File
@@ -71,9 +71,6 @@ async function executeScript(script, params, startNoteId, currentNoteId, originE
}
async function execute(ctx, script) {
// scripts run as "server" sourceId so clients recognize the changes as "foreign" and update themselves
cls.namespace.set('sourceId', sourceIdService.getCurrentSourceId());
return await (function() { return eval(`const apiContext = this;\r\n(${script}\r\n)()`); }.call(ctx));
}
+10 -3
View File
@@ -14,13 +14,19 @@ async function createConnection() {
return await sqlite.open(dataDir.DOCUMENT_PATH, {Promise});
}
const dbConnection = new Promise(async (resolve, reject) => {
// no need to create new connection now since DB stays the same all the time
const db = await createConnection();
sql.setDbConnection(db);
resolve();
});
let dbReadyResolve = null;
const dbReady = new Promise(async (resolve, reject) => {
dbReadyResolve = resolve;
// no need to create new connection now since DB stays the same all the time
const db = await createConnection();
sql.setDbConnection(db);
await dbConnection;
initDbConnection();
});
@@ -165,6 +171,7 @@ dbReady.then(async () => {
module.exports = {
dbReady,
dbConnection,
schemaExists,
isDbInitialized,
initDbConnection,
+6 -4
View File
@@ -49,7 +49,11 @@ async function sync() {
catch (e) {
proxyToggle = !proxyToggle;
if (e.message && (e.message.includes('ECONNREFUSED') || e.message.includes('ERR_CONNECTION_REFUSED'))) {
if (e.message &&
(e.message.includes('ECONNREFUSED') ||
e.message.includes('ERR_CONNECTION_REFUSED') ||
e.message.includes('Bad Gateway'))) {
log.info("No connection to sync server.");
return {
@@ -263,9 +267,7 @@ async function getEntityRow(entityName, entityId) {
const entity = await sql.getRow(`SELECT * FROM ${entityName} WHERE ${primaryKey} = ?`, [entityId]);
if (!entity) {
console.log(entityName, entityId);
console.log(`SELECT * FROM ${entityName} WHERE ${primaryKey} = '${entityId}'`);
throw new Error(`Entity ${entityName} ${entityId} not found.`);
}
if (['note_contents', 'note_revisions'].includes(entityName) && entity.content !== null) {
+2 -2
View File
@@ -78,10 +78,10 @@ async function updateNoteContent(entity, sourceId) {
await sql.replace("note_contents", entity);
await syncTableService.addNoteContentSync(entity.noteId, sourceId);
noteFulltextService.triggerNoteFulltextUpdate(entity.noteId);
});
noteFulltextService.triggerNoteFulltextUpdate(entity.noteId);
log.info("Update/sync note content for noteId=" + entity.noteId);
}
}
+13 -9
View File
@@ -61,12 +61,6 @@
Sync (<span id="outstanding-syncs-count">0</span>)
</a>
<a class="dropdown-item" id="show-help-button">
<span class="jam jam-help"></span>
Show Help
<kbd>F1</kbd>
</a>
<a class="dropdown-item" id="open-dev-tools-button">
<span class="jam jam-terminal"></span>
Open Dev Tools
@@ -79,8 +73,20 @@
<kbd>ALT+O</kbd>
</a>
<a class="dropdown-item" id="reload-frontend-button" title="Reload can help with some visual glitches without restarting the whole app.">
<span class="jam jam-empty"></span>
Reload frontend
<kbd>CTRL-R</kbd>
</a>
<a class="dropdown-item" id="show-help-button">
<span class="jam jam-help"></span>
Show Help
<kbd>F1</kbd>
</a>
<a class="dropdown-item" id="show-about-dialog-button">
<span class="jam jam-info"></span>
<span class="jam jam-empty"></span>
About Trilium Notes
</a>
@@ -241,8 +247,6 @@
<% include dialogs/note_info.ejs %>
</div>
<webview class="electron-in-page-search-window" nodeintegration disablewebsecurity src="libraries/electron-in-page-search/search-window.html"></webview>
<script type="text/javascript">
window.baseApiUrl = 'api/';
window.device = "desktop";
+8
View File
@@ -35,6 +35,14 @@ async function startTrilium() {
app.set('port', usedPort);
if (config['Network']['https']) {
if (!config['Network']['keyPath'] || !config['Network']['keyPath'].trim().length) {
throw new Error("keyPath in config.ini is required when https=true, but it's empty");
}
if (!config['Network']['certPath'] || !config['Network']['certPath'].trim().length) {
throw new Error("certPath in config.ini is required when https=true, but it's empty");
}
const options = {
key: fs.readFileSync(config['Network']['keyPath']),
cert: fs.readFileSync(config['Network']['certPath'])