mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	Compare commits
	
		
			73 Commits
		
	
	
		
			v0.46.0-be
			...
			v0.46.3-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 50c84e0f5f | ||
|  | f27370d44f | ||
|  | c6c9202c00 | ||
|  | 2cafda5f66 | ||
|  | 873953cbaf | ||
|  | d51744ce19 | ||
|  | 7df8c940b6 | ||
|  | 9bac2a4819 | ||
|  | 88147f7a0a | ||
|  | ca77211b38 | ||
|  | 4606e8d118 | ||
|  | 9f002fa802 | ||
|  | 060d4fc27b | ||
|  | bf0fbe201e | ||
|  | 721e5da672 | ||
|  | 8192b51b8a | ||
|  | 73514a63d8 | ||
|  | f8c310eb8f | ||
|  | b9422b0efd | ||
|  | 14ced949a9 | ||
|  | 5b5c2a2dbb | ||
|  | 2c958eaacb | ||
|  | 4aa27b6033 | ||
|  | 89a0c5a1c9 | ||
|  | 78e48095e6 | ||
|  | 02016ed031 | ||
|  | cb91dadeca | ||
|  | 2c755bcc38 | ||
|  | 3c7a6bc1e4 | ||
|  | 3fe87259e2 | ||
|  | d476dfc53b | ||
|  | 19821b634f | ||
|  | cde41b268e | ||
|  | 1c59bc4d3c | ||
|  | cb6d35236c | ||
|  | 7572ee284b | ||
|  | d0eaf623a8 | ||
|  | 25c2db6c3a | ||
|  | 5a173ff14e | ||
|  | 7fab75b085 | ||
|  | 0f065536d0 | ||
|  | d0747abded | ||
|  | f62b4a581e | ||
|  | dcf1c62ec1 | ||
|  | 93d55b3e7b | ||
|  | 90c6852423 | ||
|  | 208baa56e9 | ||
|  | ddf8438b22 | ||
|  | 6008dc891f | ||
|  | cc887a00f2 | ||
|  | fbbd51d0b1 | ||
|  | 081b8b126a | ||
|  | 7a6bb81345 | ||
|  | 1d5714c411 | ||
|  | 56506d33a7 | ||
|  | c94fb7a62d | ||
|  | 4160da70be | ||
|  | 2cfd093cae | ||
|  | 859465841d | ||
|  | 0c9a11db6f | ||
|  | 4cbf9c2e86 | ||
|  | 1f7997eeed | ||
|  | 8e730c6ecf | ||
|  | 600a312b2a | ||
|  | ec2e973165 | ||
|  | faeb55bc90 | ||
|  | 23ebe360a6 | ||
|  | d905335935 | ||
|  | f49f510459 | ||
|  | e78b495bd3 | ||
|  | 5542c9dc57 | ||
|  | 2388da7cfb | ||
|  | 3b4fa0c5fc | 
| @@ -55,3 +55,7 @@ npm run start-server | ||||
| * [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) | ||||
|  | ||||
| ## License | ||||
|  | ||||
| This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. | ||||
|   | ||||
| @@ -15,6 +15,8 @@ module.exports = () => { | ||||
| 
 | ||||
|             note.mime = 'text/plain'; | ||||
|             note.save(); | ||||
| 
 | ||||
|             console.log(`Migrated search note ${note.noteId}`); | ||||
|         } | ||||
|         catch (e) { | ||||
|             console.log(`Changing note content for note ${note.noteId} failed with: ${e.message} ${e.stack}`); | ||||
| @@ -298,29 +298,6 @@ | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>utcDateCreated</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">string</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last"></td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>utcDateModified</code></td> | ||||
| @@ -378,7 +355,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line26">line 26</a> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line25">line 25</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -493,7 +470,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line40">line 40</a> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line43">line 43</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -598,7 +575,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line47">line 47</a> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line50">line 50</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -703,7 +680,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line62">line 62</a> | ||||
|         <a href="entities_attribute.js.html">entities/attribute.js</a>, <a href="entities_attribute.js.html#line65">line 65</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -619,7 +619,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line205">line 205</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line207">line 207</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -782,7 +782,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line232">line 232</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line234">line 234</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1068,7 +1068,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line260">line 260</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line262">line 262</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1273,7 +1273,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line189">line 189</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line191">line 191</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1451,7 +1451,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line160">line 160</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line162">line 162</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1652,7 +1652,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line150">line 150</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line152">line 152</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1754,7 +1754,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line397">line 397</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line399">line 399</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2224,7 +2224,7 @@ JSON MIME type. See also createNewNote() for more options. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line318">line 318</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line320">line 320</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2847,7 +2847,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line345">line 345</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line347">line 347</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3202,7 +3202,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line129">line 129</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line131">line 131</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3400,7 +3400,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line139">line 139</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line141">line 141</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3509,7 +3509,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line309">line 309</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line311">line 311</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3618,7 +3618,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line326">line 326</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line328">line 328</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3799,7 +3799,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line336">line 336</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line338">line 338</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3957,7 +3957,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line354">line 354</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line356">line 356</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4110,7 +4110,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line301">line 301</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line303">line 303</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4196,7 +4196,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line392">line 392</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line394">line 394</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4334,7 +4334,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_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line115">line 115</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line117">line 117</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4391,7 +4391,7 @@ if some action needs to happen on only one specific instance. | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="searchForNotes"><span class="type-signature"></span>searchForNotes<span class="signature">(query, searchContext<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {Array.<<a href="Note.html">Note</a>>}</span></h4> | ||||
|     <h4 class="name" id="searchForNotes"><span class="type-signature"></span>searchForNotes<span class="signature">(query, searchParams<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {Array.<<a href="Note.html">Note</a>>}</span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
| @@ -4469,13 +4469,13 @@ if some action needs to happen on only one specific instance. | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>searchContext</code></td> | ||||
|                 <td class="name"><code>searchParams</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">SearchContext</span> | ||||
| <span class="param-type">Object</span> | ||||
|  | ||||
|  | ||||
|              | ||||
| @@ -4745,7 +4745,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line374">line 374</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line376">line 376</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4878,7 +4878,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line360">line 360</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line362">line 362</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5084,7 +5084,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line172">line 172</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line174">line 174</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5240,7 +5240,7 @@ exists, then we'll use that transaction. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line384">line 384</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line386">line 386</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -296,29 +296,6 @@ | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>isErased</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">boolean</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last">true if note's content is erased after it has been deleted</td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>dateCreated</code></td> | ||||
| @@ -445,7 +422,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#line32">line 32</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line31">line 31</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -560,7 +537,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#line531">line 531</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line537">line 537</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -662,7 +639,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#line855">line 855</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line861">line 861</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -840,7 +817,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#line436">line 436</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1040,7 +1017,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#line268">line 268</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line274">line 274</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1218,7 +1195,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#line441">line 441</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line447">line 447</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1327,7 +1304,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#line801">line 801</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line807">line 807</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1429,7 +1406,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#line829">line 829</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line835">line 835</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1535,7 +1512,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#line815">line 815</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line821">line 821</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1641,7 +1618,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#line71">line 71</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line70">line 70</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1743,7 +1720,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#line107">line 107</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line106">line 106</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1845,7 +1822,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#line701">line 701</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line707">line 707</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2078,7 +2055,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#line724">line 724</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line730">line 730</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2276,7 +2253,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#line762">line 762</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line768">line 768</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2474,7 +2451,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#line771">line 771</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line777">line 777</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2576,7 +2553,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#line118">line 118</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line117">line 117</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2727,7 +2704,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#line584">line 584</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line590">line 590</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2897,7 +2874,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#line291">line 291</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line297">line 297</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3052,7 +3029,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#line614">line 614</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3167,7 +3144,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#line788">line 788</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line794">line 794</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3269,7 +3246,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#line250">line 250</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line256">line 256</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3476,7 +3453,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line226">line 226</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line232">line 232</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3654,7 +3631,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line452">line 452</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line458">line 458</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3812,7 +3789,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line596">line 596</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3982,7 +3959,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line299">line 299</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line305">line 305</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4137,7 +4114,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line614">line 614</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line620">line 620</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4295,7 +4272,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line602">line 602</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line608">line 608</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4465,7 +4442,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line315">line 315</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line321">line 321</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4620,7 +4597,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line642">line 642</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line648">line 648</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4778,7 +4755,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line626">line 626</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line632">line 632</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4887,7 +4864,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line841">line 841</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line847">line 847</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5042,7 +5019,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line596">line 596</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line602">line 602</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5212,7 +5189,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line307">line 307</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line313">line 313</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5367,7 +5344,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line632">line 632</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line638">line 638</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5537,7 +5514,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line323">line 323</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line329">line 329</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5688,7 +5665,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line620">line 620</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line626">line 626</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5801,7 +5778,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line778">line 778</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line784">line 784</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5903,7 +5880,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line197">line 197</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line203">line 203</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6009,7 +5986,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line259">line 259</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line265">line 265</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6187,7 +6164,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line418">line 418</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6293,7 +6270,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line808">line 808</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line814">line 814</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6448,7 +6425,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line560">line 560</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line566">line 566</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6626,7 +6603,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line421">line 421</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line427">line 427</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6781,7 +6758,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line566">line 566</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line572">line 572</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6936,7 +6913,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line578">line 578</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line584">line 584</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7091,7 +7068,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati | ||||
|      | ||||
|     <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#line572">line 572</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line578">line 578</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7202,7 +7179,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#line338">line 338</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line344">line 344</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7330,7 +7307,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#line886">line 886</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line892">line 892</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7436,7 +7413,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#line187">line 187</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line193">line 193</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7542,7 +7519,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#line179">line 179</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line185">line 185</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7648,7 +7625,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#line174">line 174</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line180">line 180</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7754,7 +7731,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#line169">line 169</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line175">line 175</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -7860,7 +7837,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#line192">line 192</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line198">line 198</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -8093,7 +8070,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#line515">line 515</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line521">line 521</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -8273,7 +8250,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#line688">line 688</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line694">line 694</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -8453,7 +8430,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#line696">line 696</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line702">line 702</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -8664,7 +8641,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#line482">line 482</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line488">line 488</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -8844,7 +8821,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#line672">line 672</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line678">line 678</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -9024,7 +9001,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#line680">line 680</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line686">line 686</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -9266,7 +9243,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#line466">line 466</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line472">line 472</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -9477,7 +9454,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#line655">line 655</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line661">line 661</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -9688,7 +9665,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#line664">line 664</a> | ||||
|         <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line670">line 670</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -198,29 +198,6 @@ | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last"></td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>isErased</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">boolean</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last"></td> | ||||
|         </tr> | ||||
|  | ||||
| @@ -398,7 +375,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line28">line 28</a> | ||||
|         <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line27">line 27</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -513,7 +490,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line68">line 68</a> | ||||
|         <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line66">line 66</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -615,7 +592,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line54">line 54</a> | ||||
|         <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line52">line 52</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -136,30 +136,7 @@ | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>isDeleted</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">boolean</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last"></td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>utcDateModified</code></td> | ||||
|                 <td class="name"><code>utcDateCreated</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
| @@ -214,7 +191,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_recent_note.js.html">entities/recent_note.js</a>, <a href="entities_recent_note.js.html#line16">line 16</a> | ||||
|         <a href="entities_recent_note.js.html">entities/recent_note.js</a>, <a href="entities_recent_note.js.html#line15">line 15</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -46,7 +46,6 @@ const promotedAttributeDefinitionParser = require("../services/promoted_attribut | ||||
|  * @property {boolean} isInheritable - immutable | ||||
|  * @property {boolean} isDeleted | ||||
|  * @property {string|null} deleteId - ID identifying delete transaction | ||||
|  * @property {string} utcDateCreated | ||||
|  * @property {string} utcDateModified | ||||
|  * | ||||
|  * @extends Entity | ||||
| @@ -54,7 +53,7 @@ const promotedAttributeDefinitionParser = require("../services/promoted_attribut | ||||
| class Attribute extends Entity { | ||||
|     static get entityName() { return "attributes"; } | ||||
|     static get primaryKeyName() { return "attributeId"; } | ||||
|     static get hashedProperties() { return ["attributeId", "noteId", "type", "name", "value", "isInheritable", "isDeleted", "utcDateCreated"]; } | ||||
|     static get hashedProperties() { return ["attributeId", "noteId", "type", "name", "value", "isInheritable", "isDeleted"]; } | ||||
|  | ||||
|     constructor(row) { | ||||
|         super(row); | ||||
| @@ -62,6 +61,10 @@ class Attribute extends Entity { | ||||
|         this.isInheritable = !!this.isInheritable; | ||||
|     } | ||||
|  | ||||
|     isAutoLink() { | ||||
|         return this.type === 'relation' && ['internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink'].includes(this.name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @returns {Note|null} | ||||
|      */ | ||||
| @@ -127,16 +130,10 @@ class Attribute extends Entity { | ||||
|             this.isDeleted = false; | ||||
|         } | ||||
|  | ||||
|         if (!this.utcDateCreated) { | ||||
|             this.utcDateCreated = dateUtils.utcNowDateTime(); | ||||
|         } | ||||
|  | ||||
|         super.beforeSaving(); | ||||
|  | ||||
|         if (this.isChanged) { | ||||
|         this.utcDateModified = dateUtils.utcNowDateTime(); | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     createClone(type, name, value, isInheritable) { | ||||
|         return new Attribute({ | ||||
| @@ -147,7 +144,6 @@ class Attribute extends Entity { | ||||
|             position: this.position, | ||||
|             isInheritable: isInheritable, | ||||
|             isDeleted: false, | ||||
|             utcDateCreated: this.utcDateCreated, | ||||
|             utcDateModified: this.utcDateModified | ||||
|         }); | ||||
|     } | ||||
|   | ||||
| @@ -66,7 +66,7 @@ class Branch extends Entity { | ||||
|     } | ||||
|  | ||||
|     beforeSaving() { | ||||
|         if (this.notePosition === undefined) { | ||||
|         if (this.notePosition === undefined || this.notePosition === null) { | ||||
|             const maxNotePos = sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [this.parentNoteId]); | ||||
|             this.notePosition = maxNotePos === null ? 0 : maxNotePos + 10; | ||||
|         } | ||||
| @@ -85,10 +85,8 @@ class Branch extends Entity { | ||||
|  | ||||
|         super.beforeSaving(); | ||||
|  | ||||
|         if (this.isChanged) { | ||||
|         this.utcDateModified = dateUtils.utcNowDateTime(); | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     createClone(parentNoteId, notePosition) { | ||||
|         return new Branch({ | ||||
|   | ||||
| @@ -43,18 +43,13 @@ class Entity { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ('isDeleted' in this) { | ||||
|         if ('isDeleted' in this && this.constructor.entityName !== 'recent_notes') { | ||||
|             this.isDeleted = !!this.isDeleted; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     beforeSaving() { | ||||
|         this.generateIdIfNecessary(); | ||||
|  | ||||
|         const origHash = this.hash; | ||||
|  | ||||
|         this.hash = this.generateHash(); | ||||
|         this.isChanged = origHash !== this.hash; | ||||
|     } | ||||
|  | ||||
|     generateIdIfNecessary() { | ||||
| @@ -73,6 +68,10 @@ class Entity { | ||||
|         return utils.hash(contentToHash).substr(0, 10); | ||||
|     } | ||||
|  | ||||
|     getUtcDateChanged() { | ||||
|         return this.utcDateModified; | ||||
|     } | ||||
|  | ||||
|     get repository() { | ||||
|         if (!repo) { | ||||
|             repo = require('../services/repository'); | ||||
|   | ||||
| @@ -49,7 +49,6 @@ const RELATION = 'relation'; | ||||
|  * @property {boolean} isProtected - true if note is protected | ||||
|  * @property {boolean} isDeleted - true if note is deleted | ||||
|  * @property {string|null} deleteId - ID identifying delete transaction | ||||
|  * @property {boolean} isErased - true if note's content is erased after it has been deleted | ||||
|  * @property {string} dateCreated - local date time (with offset) | ||||
|  * @property {string} dateModified - local date time (with offset) | ||||
|  * @property {string} utcDateCreated | ||||
| @@ -98,9 +97,9 @@ class Note extends Entity { | ||||
|     /** @returns {*} */ | ||||
|     getContent(silentNotFoundError = false) { | ||||
|         if (this.content === undefined) { | ||||
|             const res = sql.getRow(`SELECT content, hash FROM note_contents WHERE noteId = ?`, [this.noteId]); | ||||
|             const row = sql.getRow(`SELECT content FROM note_contents WHERE noteId = ?`, [this.noteId]); | ||||
|  | ||||
|             if (!res) { | ||||
|             if (!row) { | ||||
|                 if (silentNotFoundError) { | ||||
|                     return undefined; | ||||
|                 } | ||||
| @@ -109,7 +108,7 @@ class Note extends Entity { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             this.content = res.content; | ||||
|             this.content = row.content; | ||||
|  | ||||
|             if (this.isProtected) { | ||||
|                 if (this.isContentAvailable) { | ||||
| @@ -171,8 +170,7 @@ class Note extends Entity { | ||||
|             noteId: this.noteId, | ||||
|             content: content, | ||||
|             dateModified: dateUtils.localNowDateTime(), | ||||
|             utcDateModified: dateUtils.utcNowDateTime(), | ||||
|             hash: utils.hash(this.noteId + "|" + content.toString()) | ||||
|             utcDateModified: dateUtils.utcNowDateTime() | ||||
|         }; | ||||
|  | ||||
|         if (this.isProtected) { | ||||
| @@ -186,7 +184,15 @@ class Note extends Entity { | ||||
|  | ||||
|         sql.upsert("note_contents", "noteId", pojo); | ||||
|  | ||||
|         entityChangesService.addNoteContentEntityChange(this.noteId); | ||||
|         const hash = utils.hash(this.noteId + "|" + content.toString()); | ||||
|  | ||||
|         entityChangesService.addEntityChange({ | ||||
|             entityName: 'note_contents', | ||||
|             entityId: this.noteId, | ||||
|             hash: hash, | ||||
|             isErased: false, | ||||
|             utcDateChanged: this.getUtcDateChanged() | ||||
|         }, null); | ||||
|     } | ||||
|  | ||||
|     setJsonContent(content) { | ||||
| @@ -834,7 +840,7 @@ class Note extends Entity { | ||||
|      * @returns {boolean} - true if note has children | ||||
|      */ | ||||
|     hasChildren() { | ||||
|         return (this.getChildNotes()).length > 0; | ||||
|         return this.getChildNotes().length > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -932,11 +938,9 @@ class Note extends Entity { | ||||
|  | ||||
|         super.beforeSaving(); | ||||
|  | ||||
|         if (this.isChanged) { | ||||
|         this.dateModified = dateUtils.localNowDateTime(); | ||||
|         this.utcDateModified = dateUtils.utcNowDateTime(); | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     // cannot be static! | ||||
|     updatePojo(pojo) { | ||||
|   | ||||
| @@ -43,7 +43,6 @@ const entityChangesService = require('../services/entity_changes.js'); | ||||
|  * @property {string} type | ||||
|  * @property {string} mime | ||||
|  * @property {string} title | ||||
|  * @property {boolean} isErased | ||||
|  * @property {boolean} isProtected | ||||
|  * @property {string} dateLastEdited | ||||
|  * @property {string} dateCreated | ||||
| @@ -56,12 +55,11 @@ const entityChangesService = require('../services/entity_changes.js'); | ||||
| class NoteRevision extends Entity { | ||||
|     static get entityName() { return "note_revisions"; } | ||||
|     static get primaryKeyName() { return "noteRevisionId"; } | ||||
|     static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "isErased", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; } | ||||
|     static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; } | ||||
|  | ||||
|     constructor(row) { | ||||
|         super(row); | ||||
|  | ||||
|         this.isErased = !!this.isErased; | ||||
|         this.isProtected = !!this.isProtected; | ||||
|  | ||||
|         if (this.isProtected) { | ||||
| @@ -95,7 +93,7 @@ class NoteRevision extends Entity { | ||||
|     /** @returns {*} */ | ||||
|     getContent(silentNotFoundError = false) { | ||||
|         if (this.content === undefined) { | ||||
|             const res = sql.getRow(`SELECT content, hash FROM note_revision_contents WHERE noteRevisionId = ?`, [this.noteRevisionId]); | ||||
|             const res = sql.getRow(`SELECT content FROM note_revision_contents WHERE noteRevisionId = ?`, [this.noteRevisionId]); | ||||
|  | ||||
|             if (!res) { | ||||
|                 if (silentNotFoundError) { | ||||
| @@ -107,7 +105,6 @@ class NoteRevision extends Entity { | ||||
|             } | ||||
|  | ||||
|             this.content = res.content; | ||||
|  | ||||
|             if (this.isProtected) { | ||||
|                 if (protectedSessionService.isProtectedSessionAvailable()) { | ||||
|                     this.content = protectedSessionService.decrypt(this.content); | ||||
| @@ -134,8 +131,7 @@ class NoteRevision extends Entity { | ||||
|         const pojo = { | ||||
|             noteRevisionId: this.noteRevisionId, | ||||
|             content: content, | ||||
|             utcDateModified: dateUtils.utcNowDateTime(), | ||||
|             hash: utils.hash(this.noteRevisionId + "|" + content) | ||||
|             utcDateModified: dateUtils.utcNowDateTime() | ||||
|         }; | ||||
|  | ||||
|         if (this.isProtected) { | ||||
| @@ -149,16 +145,22 @@ class NoteRevision extends Entity { | ||||
|  | ||||
|         sql.upsert("note_revision_contents", "noteRevisionId", pojo); | ||||
|  | ||||
|         entityChangesService.addNoteRevisionContentEntityChange(this.noteRevisionId); | ||||
|         const hash = utils.hash(this.noteRevisionId + "|" + content); | ||||
|  | ||||
|         entityChangesService.addEntityChange({ | ||||
|             entityName: 'note_revision_contents', | ||||
|             entityId: this.noteRevisionId, | ||||
|             hash: hash, | ||||
|             isErased: false, | ||||
|             utcDateChanged: this.getUtcDateChanged() | ||||
|         }, null); | ||||
|     } | ||||
|  | ||||
|     beforeSaving() { | ||||
|         super.beforeSaving(); | ||||
|  | ||||
|         if (this.isChanged) { | ||||
|         this.utcDateModified = dateUtils.utcNowDateTime(); | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     // cannot be static! | ||||
|     updatePojo(pojo) { | ||||
|   | ||||
| @@ -60,13 +60,12 @@ class Option extends Entity { | ||||
|  | ||||
|         super.beforeSaving(); | ||||
|  | ||||
|         if (this.isChanged) { | ||||
|         this.utcDateModified = dateUtils.utcNowDateTime(); | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | ||||
| module.exports = Option;</code></pre> | ||||
| module.exports = Option; | ||||
| </code></pre> | ||||
|         </article> | ||||
|     </section> | ||||
|  | ||||
|   | ||||
| @@ -36,21 +36,15 @@ const dateUtils = require('../services/date_utils'); | ||||
|  * | ||||
|  * @property {string} noteId | ||||
|  * @property {string} notePath | ||||
|  * @property {boolean} isDeleted | ||||
|  * @property {string} utcDateModified | ||||
|  * @property {string} utcDateCreated | ||||
|  * | ||||
|  * @extends Entity | ||||
|  */ | ||||
| class RecentNote extends Entity { | ||||
|     static get entityName() { return "recent_notes"; } | ||||
|     static get primaryKeyName() { return "noteId"; } | ||||
|     static get hashedProperties() { return ["noteId", "notePath", "utcDateCreated", "isDeleted"]; } | ||||
|  | ||||
|     beforeSaving() { | ||||
|         if (!this.isDeleted) { | ||||
|             this.isDeleted = false; | ||||
|         } | ||||
|  | ||||
|         if (!this.utcDateCreated) { | ||||
|             this.utcDateCreated = dateUtils.utcNowDateTime(); | ||||
|         } | ||||
| @@ -59,7 +53,8 @@ class RecentNote extends Entity { | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = RecentNote;</code></pre> | ||||
| module.exports = RecentNote; | ||||
| </code></pre> | ||||
|         </article> | ||||
|     </section> | ||||
|  | ||||
|   | ||||
| @@ -391,7 +391,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line213">line 213</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line215">line 215</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -579,7 +579,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line174">line 174</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line176">line 176</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -767,7 +767,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line234">line 234</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line236">line 236</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1053,7 +1053,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line241">line 241</a> | ||||
|         <a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line243">line 243</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -120,13 +120,15 @@ function BackendScriptApi(currentNote, apiParams) { | ||||
|      * | ||||
|      * @method | ||||
|      * @param {string} query | ||||
|      * @param {SearchContext} [searchContext] | ||||
|      * @param {Object} [searchParams] | ||||
|      * @returns {Note[]} | ||||
|      */ | ||||
|     this.searchForNotes = (query, searchContext) => { | ||||
|         searchContext = searchContext || new SearchContext(); | ||||
|     this.searchForNotes = (query, searchParams = {}) => { | ||||
|         if (searchParams.includeArchivedNotes === undefined) { | ||||
|             searchParams.includeArchivedNotes = true; | ||||
|         } | ||||
|  | ||||
|         const noteIds = searchService.findNotesWithQuery(query, searchContext) | ||||
|         const noteIds = searchService.findNotesWithQuery(query, new SearchContext(searchParams)) | ||||
|             .map(sr => sr.noteId); | ||||
|  | ||||
|         return repository.getNotes(noteIds); | ||||
|   | ||||
| @@ -201,7 +201,7 @@ | ||||
|  | ||||
|          | ||||
|              | ||||
| <h4 class="name" id="isDeleted"><span class="type-signature"></span>isDeleted<span class="type-signature"></span></h4> | ||||
| <h4 class="name" id="fromSearchNote"><span class="type-signature"></span>fromSearchNote<span class="type-signature"></span></h4> | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -259,6 +259,64 @@ | ||||
|  | ||||
|          | ||||
|              | ||||
| <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_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line25">line 25</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
| </dl> | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|          | ||||
|              | ||||
| <h4 class="name" id="isExpanded"><span class="type-signature"></span>isExpanded<span class="type-signature"></span></h4> | ||||
|  | ||||
|  | ||||
| @@ -607,7 +665,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line27">line 27</a> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line29">line 29</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -709,7 +767,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line32">line 32</a> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line34">line 34</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -811,7 +869,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line37">line 37</a> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line39">line 39</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -913,7 +971,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line42">line 42</a> | ||||
|         <a href="entities_branch.js.html">entities/branch.js</a>, <a href="entities_branch.js.html#line44">line 44</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -81,7 +81,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#line24">line 24</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line22">line 22</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -223,7 +223,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#line28">line 28</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line26">line 26</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -329,7 +329,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#line50">line 50</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line48">line 48</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -435,7 +435,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#line41">line 41</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line39">line 39</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -545,7 +545,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#line33">line 33</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line31">line 31</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -658,7 +658,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#line35">line 35</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line33">line 33</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -768,7 +768,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#line31">line 31</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line29">line 29</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -874,7 +874,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#line44">line 44</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line42">line 42</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -980,7 +980,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#line47">line 47</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line45">line 45</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1109,7 +1109,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#line69">line 69</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line67">line 67</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1264,7 +1264,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#line59">line 59</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line57">line 57</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1419,7 +1419,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#line89">line 89</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line101">line 101</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1556,7 +1556,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#line287">line 287</a> | ||||
|         <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> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1712,7 +1712,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#line392">line 392</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line413">line 413</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1748,7 +1748,7 @@ | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="createNoteLink"><span class="type-signature"></span>createNoteLink<span class="signature">(notePath, noteTitle<span class="signature-attributes">opt</span>)</span><span class="type-signature"></span></h4> | ||||
|     <h4 class="name" id="createNoteLink"><span class="type-signature"></span>createNoteLink<span class="signature">(notePath, params<span class="signature-attributes">opt</span>, title=<span class="signature-attributes">opt</span>)</span><span class="type-signature"></span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
| @@ -1825,7 +1825,148 @@ | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>noteTitle</code></td> | ||||
|                 <td class="name"><code>params</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">object</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|                 <td class="attributes"> | ||||
|                  | ||||
|                     <optional><br> | ||||
|                  | ||||
|  | ||||
|                  | ||||
|  | ||||
|                  | ||||
|                 </td> | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last"> | ||||
|                 <h6>Properties</h6> | ||||
|                  | ||||
|  | ||||
| <table class="params"> | ||||
|     <thead> | ||||
|     <tr> | ||||
|          | ||||
|         <th>Name</th> | ||||
|          | ||||
|  | ||||
|         <th>Type</th> | ||||
|  | ||||
|          | ||||
|         <th>Attributes</th> | ||||
|          | ||||
|  | ||||
|          | ||||
|         <th>Default</th> | ||||
|          | ||||
|  | ||||
|         <th class="last">Description</th> | ||||
|     </tr> | ||||
|     </thead> | ||||
|  | ||||
|     <tbody> | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>showTooltip</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">boolean</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|                 <td class="attributes"> | ||||
|                  | ||||
|                     <optional><br> | ||||
|                  | ||||
|  | ||||
|                  | ||||
|  | ||||
|                  | ||||
|                 </td> | ||||
|              | ||||
|  | ||||
|              | ||||
|                 <td class="default"> | ||||
|                  | ||||
|                     true | ||||
|                  | ||||
|                 </td> | ||||
|              | ||||
|  | ||||
|             <td class="description last">enable/disable tooltip on the link</td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>showNotePath</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">boolean</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|                 <td class="attributes"> | ||||
|                  | ||||
|                     <optional><br> | ||||
|                  | ||||
|  | ||||
|                  | ||||
|  | ||||
|                  | ||||
|                 </td> | ||||
|              | ||||
|  | ||||
|              | ||||
|                 <td class="default"> | ||||
|                  | ||||
|                     false | ||||
|                  | ||||
|                 </td> | ||||
|              | ||||
|  | ||||
|             <td class="description last">show also whole note's path as part of the link</td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|     </tbody> | ||||
| </table> | ||||
|  | ||||
|             </td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>title=</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
| @@ -1851,7 +1992,7 @@ | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last">if not present we'll use note title</td> | ||||
|             <td class="description last">custom link tile with note's title as default</td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
| @@ -1892,7 +2033,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#line294">line 294</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2025,7 +2166,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#line241">line 241</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line253">line 253</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2131,7 +2272,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#line293">line 293</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line308">line 308</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2237,7 +2378,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#line307">line 307</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line322">line 322</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2391,7 +2532,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#line301">line 301</a> | ||||
|         <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> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2528,7 +2669,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#line358">line 358</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line373">line 373</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2635,7 +2776,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#line234">line 234</a> | ||||
|         <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> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2790,7 +2931,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#line367">line 367</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line382">line 382</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2946,7 +3087,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#line206">line 206</a> | ||||
|         <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> | ||||
|      | ||||
|  | ||||
| @@ -3147,7 +3288,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#line218">line 218</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line230">line 230</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3253,7 +3394,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#line349">line 349</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line364">line 364</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3408,7 +3549,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#line376">line 376</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line391">line 391</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3462,6 +3603,184 @@ otherwise (by e.g. createNoteLink()) | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="openTabWithNote"><span class="type-signature"></span>openTabWithNote<span class="signature">(notePath, activate)</span><span class="type-signature"> → {Promise.<void>}</span></h4> | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|  | ||||
|  | ||||
| <div class="description"> | ||||
|     Open a note in a new tab. | ||||
| </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>notePath</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">string</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last">(or noteId)</td> | ||||
|         </tr> | ||||
|  | ||||
|      | ||||
|  | ||||
|         <tr> | ||||
|              | ||||
|                 <td class="name"><code>activate</code></td> | ||||
|              | ||||
|  | ||||
|             <td class="type"> | ||||
|              | ||||
|                  | ||||
| <span class="param-type">boolean</span> | ||||
|  | ||||
|  | ||||
|              | ||||
|             </td> | ||||
|  | ||||
|              | ||||
|  | ||||
|              | ||||
|  | ||||
|             <td class="description last">set to true to activate the new tab, false to stay on the current tab</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#line81">line 81</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
| </dl> | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| <h5>Returns:</h5> | ||||
|  | ||||
|          | ||||
|  | ||||
|  | ||||
| <dl> | ||||
|     <dt> | ||||
|         Type | ||||
|     </dt> | ||||
|     <dd> | ||||
|          | ||||
| <span class="param-type">Promise.<void></span> | ||||
|  | ||||
|  | ||||
|     </dd> | ||||
| </dl> | ||||
|  | ||||
|      | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|          | ||||
|              | ||||
|  | ||||
|      | ||||
|  | ||||
|      | ||||
|     <h4 class="name" id="parseDate"><span class="type-signature"></span>parseDate<span class="signature">(str)</span><span class="type-signature"> → {Date}</span></h4> | ||||
|      | ||||
|  | ||||
| @@ -3559,7 +3878,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#line248">line 248</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line260">line 260</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3667,7 +3986,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#line319">line 319</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> | ||||
|      | ||||
|  | ||||
| @@ -3823,7 +4142,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#line330">line 330</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line345">line 345</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3979,7 +4298,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#line339">line 339</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line354">line 354</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4111,7 +4430,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#line410">line 410</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line431">line 431</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4197,7 +4516,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#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#line282">line 282</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4334,7 +4653,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#line226">line 226</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line238">line 238</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4495,7 +4814,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#line139">line 139</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line151">line 151</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4603,7 +4922,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#line168">line 168</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line180">line 180</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4741,7 +5060,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#line194">line 194</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line206">line 206</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4897,7 +5216,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#line178">line 178</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line190">line 190</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4959,7 +5278,7 @@ Internally this serializes the anonymous function into string and sends it to ba | ||||
|  | ||||
|  | ||||
| <div class="description"> | ||||
|     Hoist note. See https://github.com/zadam/trilium/wiki/Note-hoisting | ||||
|     Hoist note in the current tab. See https://github.com/zadam/trilium/wiki/Note-hoisting | ||||
| </div> | ||||
|  | ||||
|  | ||||
| @@ -5052,7 +5371,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#line385">line 385</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line400">line 400</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5203,7 +5522,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#line313">line 313</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line328">line 328</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5340,7 +5659,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#line264">line 264</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line276">line 276</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5477,7 +5796,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#line256">line 256</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line268">line 268</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5569,7 +5888,7 @@ Typical use case is when new note has been created, we should wait until it is s | ||||
|      | ||||
|     <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#line403">line 403</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line424">line 424</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -167,7 +167,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#line13">line 13</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line24">line 24</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -267,7 +267,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#line22">line 22</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> | ||||
|      | ||||
|  | ||||
| @@ -335,7 +335,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#line30">line 30</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line41">line 41</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -403,7 +403,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#line36">line 36</a> | ||||
|         <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> | ||||
|      | ||||
|  | ||||
| @@ -461,7 +461,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#line53">line 53</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line64">line 64</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -519,7 +519,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#line47">line 47</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line58">line 58</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -577,7 +577,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#line51">line 51</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line62">line 62</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -635,7 +635,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#line43">line 43</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line54">line 54</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -703,7 +703,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#line28">line 28</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> | ||||
|      | ||||
|  | ||||
| @@ -771,7 +771,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#line33">line 33</a> | ||||
|         <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> | ||||
|      | ||||
|  | ||||
| @@ -839,7 +839,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#line36">line 36</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -897,7 +897,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#line45">line 45</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line56">line 56</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -955,7 +955,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#line49">line 49</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line60">line 60</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1103,7 +1103,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#line307">line 307</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line377">line 377</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1303,7 +1303,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#line176">line 176</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line189">line 189</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1481,7 +1481,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#line329">line 329</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line399">line 399</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1587,7 +1587,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#line119">line 119</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line132">line 132</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1689,7 +1689,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#line114">line 114</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line127">line 127</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1791,7 +1791,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#line131">line 131</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line144">line 144</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1893,7 +1893,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#line149">line 149</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line162">line 162</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -1995,7 +1995,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#line154">line 154</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line167">line 167</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2146,7 +2146,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#line369">line 369</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line439">line 439</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2313,7 +2313,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#line253">line 253</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line266">line 266</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2468,7 +2468,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#line393">line 393</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line463">line 463</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2578,7 +2578,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#line495">line 495</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line588">line 588</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2752,7 +2752,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#line296">line 296</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line366">line 366</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -2952,7 +2952,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#line163">line 163</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line176">line 176</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3130,7 +3130,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#line318">line 318</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line388">line 388</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3285,7 +3285,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#line363">line 363</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line433">line 433</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3452,7 +3452,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#line245">line 245</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line258">line 258</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3607,7 +3607,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#line387">line 387</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line457">line 457</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3762,7 +3762,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#line375">line 375</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line445">line 445</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -3929,7 +3929,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#line261">line 261</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line331">line 331</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4084,7 +4084,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#line399">line 399</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line469">line 469</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4190,7 +4190,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#line139">line 139</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> | ||||
|      | ||||
|  | ||||
| @@ -4292,7 +4292,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#line144">line 144</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line157">line 157</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4443,7 +4443,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#line381">line 381</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line451">line 451</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4610,7 +4610,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#line269">line 269</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line339">line 339</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4765,7 +4765,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#line411">line 411</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line481">line 481</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -4935,7 +4935,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#line421">line 421</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line491">line 491</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5086,7 +5086,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#line405">line 405</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line475">line 475</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5196,7 +5196,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#line474">line 474</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line567">line 567</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5302,7 +5302,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#line484">line 484</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line577">line 577</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5404,7 +5404,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#line435">line 435</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line505">line 505</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5578,7 +5578,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#line278">line 278</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line348">line 348</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5684,7 +5684,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#line126">line 126</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line139">line 139</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -5835,7 +5835,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#line345">line 345</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line415">line 415</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6013,7 +6013,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#line287">line 287</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line357">line 357</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6168,7 +6168,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#line339">line 339</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line409">line 409</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6323,7 +6323,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#line351">line 351</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line421">line 421</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6478,7 +6478,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#line357">line 357</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line427">line 427</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6589,7 +6589,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#line465">line 465</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line558">line 558</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -6673,7 +6673,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#line89">line 89</a> | ||||
|         <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line102">line 102</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -50,6 +50,8 @@ class Attribute { | ||||
|         this.position = row.position; | ||||
|         /** @param {boolean} isInheritable */ | ||||
|         this.isInheritable = !!row.isInheritable; | ||||
|         /** @param {boolean} */ | ||||
|         this.isDeleted = !!row.isDeleted; | ||||
|     } | ||||
|  | ||||
|     /** @returns {NoteShort} */ | ||||
| @@ -114,6 +116,17 @@ class Attribute { | ||||
|     getDefinition() { | ||||
|         return promotedAttributeDefinitionParser.parse(this.value); | ||||
|     } | ||||
|  | ||||
|     isDefinitionFor(attr) { | ||||
|         return this.type === 'label' && this.name === `${attr.type}:${attr.name}`; | ||||
|     } | ||||
|  | ||||
|     get dto() { | ||||
|         const dto = Object.assign({}, this); | ||||
|         delete dto.treeCache; | ||||
|  | ||||
|         return dto; | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default Attribute; | ||||
|   | ||||
| @@ -48,6 +48,8 @@ class Branch { | ||||
|         /** @param {boolean} */ | ||||
|         this.isExpanded = !!row.isExpanded; | ||||
|         /** @param {boolean} */ | ||||
|         this.fromSearchNote = !!row.fromSearchNote; | ||||
|         /** @param {boolean} */ | ||||
|         this.isDeleted = !!row.isDeleted; | ||||
|     } | ||||
|  | ||||
| @@ -76,7 +78,8 @@ class Branch { | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default Branch;</code></pre> | ||||
| export default Branch; | ||||
| </code></pre> | ||||
|         </article> | ||||
|     </section> | ||||
|  | ||||
|   | ||||
| @@ -27,12 +27,23 @@ | ||||
|     <section> | ||||
|         <article> | ||||
|             <pre class="prettyprint source linenums"><code>import server from '../services/server.js'; | ||||
| import Attribute from './attribute.js'; | ||||
| import noteAttributeCache from "../services/note_attribute_cache.js"; | ||||
| import ws from "../services/ws.js"; | ||||
| import options from "../services/options.js"; | ||||
|  | ||||
| const LABEL = 'label'; | ||||
| const RELATION = 'relation'; | ||||
|  | ||||
| const NOTE_TYPE_ICONS = { | ||||
|     "file": "bx bx-file", | ||||
|     "image": "bx bx-image", | ||||
|     "code": "bx bx-code", | ||||
|     "render": "bx bx-extension", | ||||
|     "search": "bx bx-file-find", | ||||
|     "relation-map": "bx bx-map-alt", | ||||
|     "book": "bx bx-book" | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * FIXME: since there's no "full note" anymore we can rename this to Note | ||||
|  * | ||||
| @@ -78,7 +89,7 @@ class NoteShort { | ||||
|         /** @param {string} content-type, e.g. "application/json" */ | ||||
|         this.mime = row.mime; | ||||
|         /** @param {boolean} */ | ||||
|         this.isDeleted = row.isDeleted; | ||||
|         this.isDeleted = !!row.isDeleted; | ||||
|     } | ||||
|  | ||||
|     addParent(parentNoteId, branchId) { | ||||
| @@ -93,15 +104,17 @@ class NoteShort { | ||||
|         this.parentToBranch[parentNoteId] = branchId; | ||||
|     } | ||||
|  | ||||
|     addChild(childNoteId, branchId) { | ||||
|         if (!this.children.includes(childNoteId)) { | ||||
|     addChild(childNoteId, branchId, sort = true) { | ||||
|         if (!(childNoteId in this.childToBranch)) { | ||||
|             this.children.push(childNoteId); | ||||
|         } | ||||
|  | ||||
|         this.childToBranch[childNoteId] = branchId; | ||||
|  | ||||
|         if (sort) { | ||||
|             this.sortChildren(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     sortChildren() { | ||||
|         const branchIdPos = {}; | ||||
| @@ -282,6 +295,63 @@ class NoteShort { | ||||
|         return this.getAttributes(LABEL, name); | ||||
|     } | ||||
|  | ||||
|     getIcon() { | ||||
|         const iconClassLabels = this.getLabels('iconClass'); | ||||
|         const workspaceIconClass = this.getWorkspaceIconClass(); | ||||
|  | ||||
|         if (iconClassLabels.length > 0) { | ||||
|             return iconClassLabels.map(l => l.value).join(' '); | ||||
|         } | ||||
|         else if (workspaceIconClass) { | ||||
|             return workspaceIconClass; | ||||
|         } | ||||
|         else if (this.noteId === 'root') { | ||||
|             return "bx bx-chevrons-right"; | ||||
|         } | ||||
|         else if (this.type === 'text') { | ||||
|             if (this.isFolder()) { | ||||
|                 return "bx bx-folder"; | ||||
|             } | ||||
|             else { | ||||
|                 return "bx bx-note"; | ||||
|             } | ||||
|         } | ||||
|         else if (this.type === 'code' && this.mime.startsWith('text/x-sql')) { | ||||
|             return "bx bx-data"; | ||||
|         } | ||||
|         else { | ||||
|             return NOTE_TYPE_ICONS[this.type]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     isFolder() { | ||||
|         return this.type === 'search' | ||||
|             || this.getFilteredChildBranches().length > 0; | ||||
|     } | ||||
|  | ||||
|     getFilteredChildBranches() { | ||||
|         let childBranches = this.getChildBranches(); | ||||
|  | ||||
|         if (!childBranches) { | ||||
|             ws.logError(`No children for ${parentNote}. This shouldn't happen.`); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (options.is("hideIncludedImages_main")) { | ||||
|             const imageLinks = this.getRelations('imageLink'); | ||||
|  | ||||
|             // image is already visible in the parent note so no need to display it separately in the book | ||||
|             childBranches = childBranches.filter(branch => !imageLinks.find(rel => rel.value === branch.noteId)); | ||||
|         } | ||||
|  | ||||
|         // we're not checking hideArchivedNotes since that would mean we need to lazy load the child notes | ||||
|         // which would seriously slow down everything. | ||||
|         // we check this flag only once user chooses to expand the parent. This has the negative consequence that | ||||
|         // note may appear as folder but not contain any children when all of them are archived | ||||
|  | ||||
|         return childBranches; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param {string} [name] - relation name to filter | ||||
|      * @returns {Attribute[]} all note's relations (attributes with type relation), including inherited ones | ||||
| @@ -466,19 +536,42 @@ class NoteShort { | ||||
|         return relations.map(rel => this.treeCache.notes[rel.value]); | ||||
|     } | ||||
|  | ||||
|     hasAncestor(ancestorNote) { | ||||
|     getPromotedDefinitionAttributes() { | ||||
|         if (this.hasLabel('hidePromotedAttributes')) { | ||||
|             return []; | ||||
|         } | ||||
|  | ||||
|         return this.getAttributes() | ||||
|             .filter(attr => attr.isDefinition()) | ||||
|             .filter(attr => { | ||||
|                 const def = attr.getDefinition(); | ||||
|  | ||||
|                 return def && def.isPromoted; | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     hasAncestor(ancestorNote, visitedNoteIds) { | ||||
|         if (this.noteId === ancestorNote.noteId) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         if (!visitedNoteIds) { | ||||
|             visitedNoteIds = new Set(); | ||||
|         } else if (visitedNoteIds.has(this.noteId)) { | ||||
|             // to avoid infinite cycle when template is descendent of the instance | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         visitedNoteIds.add(this.noteId); | ||||
|  | ||||
|         for (const templateNote of this.getTemplateNotes()) { | ||||
|             if (templateNote.hasAncestor(ancestorNote)) { | ||||
|             if (templateNote.hasAncestor(ancestorNote, visitedNoteIds)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (const parentNote of this.getParentNotes()) { | ||||
|             if (parentNote.hasAncestor(ancestorNote)) { | ||||
|             if (parentNote.hasAncestor(ancestorNote, visitedNoteIds)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
| @@ -539,6 +632,16 @@ class NoteShort { | ||||
|         const labels = this.getLabels('cssClass'); | ||||
|         return labels.map(l => l.value).join(' '); | ||||
|     } | ||||
|  | ||||
|     getWorkspaceIconClass() { | ||||
|         const labels = this.getLabels('workspaceIconClass'); | ||||
|         return labels.length > 0 ? labels[0].value : ""; | ||||
|     } | ||||
|  | ||||
|     getWorkspaceTabBackgroundColor() { | ||||
|         const labels = this.getLabels('workspaceTabBackgroundColor'); | ||||
|         return labels.length > 0 ? labels[0].value : ""; | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default NoteShort; | ||||
|   | ||||
| @@ -156,7 +156,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line93">line 93</a> | ||||
|         <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line124">line 124</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -244,7 +244,7 @@ | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line96">line 96</a> | ||||
|         <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line127">line 127</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -333,7 +333,7 @@ separately but should behave uniformly for the user. | ||||
|      | ||||
|     <dt class="tag-source">Source:</dt> | ||||
|     <dd class="tag-source"><ul class="dummy"><li> | ||||
|         <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line86">line 86</a> | ||||
|         <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line117">line 117</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
| @@ -572,7 +572,7 @@ separately but should behave uniformly for the user. | ||||
|      | ||||
|     <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#line76">line 76</a> | ||||
|         <a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line88">line 88</a> | ||||
|     </li></ul></dd> | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -26,8 +26,7 @@ | ||||
|      | ||||
|     <section> | ||||
|         <article> | ||||
|             <pre class="prettyprint source linenums"><code>import treeService from './tree.js'; | ||||
| import server from './server.js'; | ||||
|             <pre class="prettyprint source linenums"><code>import server from './server.js'; | ||||
| import utils from './utils.js'; | ||||
| import toastService from './toast.js'; | ||||
| import linkService from './link.js'; | ||||
| @@ -37,7 +36,6 @@ import protectedSessionService from './protected_session.js'; | ||||
| import dateNotesService from './date_notes.js'; | ||||
| import CollapsibleWidget from '../widgets/collapsible_widget.js'; | ||||
| import ws from "./ws.js"; | ||||
| import hoistedNoteService from "./hoisted_note.js"; | ||||
| import appContext from "./app_context.js"; | ||||
| import TabAwareWidget from "../widgets/tab_aware_widget.js"; | ||||
| import TabCachingWidget from "../widgets/tab_caching_widget.js"; | ||||
| @@ -101,6 +99,20 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|         appContext.triggerEvent('focusAndSelectTitle'); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Open a note in a new tab. | ||||
|      * | ||||
|      * @param {string} notePath (or noteId) | ||||
|      * @param {boolean} activate - set to true to activate the new tab, false to stay on the current tab | ||||
|      * @return {Promise<void>} | ||||
|      */ | ||||
|     this.openTabWithNote = async (notePath, activate) => { | ||||
|         await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|         await appContext.tabManager.openTabWithNote(notePath, activate); | ||||
|         appContext.triggerEvent('focusAndSelectTitle'); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @typedef {Object} ToolbarButtonOptions | ||||
|      * @property {string} title | ||||
| @@ -117,7 +129,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|     this.addButtonToToolbar = opts => { | ||||
|         const buttonId = "toolbar-button-" + opts.title.replace(/\s/g, "-"); | ||||
|  | ||||
|         const button = $('<button>') | ||||
|         const button = $('<button class="noborder">') | ||||
|             .addClass("btn btn-sm") | ||||
|             .on('click', opts.action); | ||||
|  | ||||
| @@ -302,7 +314,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|      * | ||||
|      * @method | ||||
|      * @param {string} notePath (or noteId) | ||||
|      * @param {string} [noteTitle] - if not present we'll use note title | ||||
|      * @param {object} [params] | ||||
|      * @param {boolean} [params.showTooltip=true] - enable/disable tooltip on the link | ||||
|      * @param {boolean} [params.showNotePath=false] - show also whole note's path as part of the link | ||||
|      * @param {string} [title=] - custom link tile with note's title as default | ||||
|      */ | ||||
|     this.createNoteLink = linkService.createNoteLink; | ||||
|  | ||||
| @@ -404,13 +419,19 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|     this.getYearNote = dateNotesService.getYearNote; | ||||
|  | ||||
|     /** | ||||
|      * Hoist note. See https://github.com/zadam/trilium/wiki/Note-hoisting | ||||
|      * Hoist note in the current tab. See https://github.com/zadam/trilium/wiki/Note-hoisting | ||||
|      * | ||||
|      * @method | ||||
|      * @param {string} noteId - set hoisted note. 'root' will effectively unhoist | ||||
|      * @return {Promise} | ||||
|      */ | ||||
|     this.setHoistedNoteId = hoistedNoteService.setHoistedNoteId; | ||||
|     this.setHoistedNoteId = (noteId) => { | ||||
|         const activeTabContext = appContext.tabManager.getActiveTabContext(); | ||||
|  | ||||
|         if (activeTabContext) { | ||||
|             activeTabContext.setHoistedNoteId(noteId); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @method | ||||
|   | ||||
| @@ -33,14 +33,23 @@ const WIDGET_TPL = ` | ||||
| <div class="card widget"> | ||||
|     <div class="card-header">     | ||||
|         <div>            | ||||
|             <button class="btn btn-sm widget-title" data-toggle="collapse" data-target="#[to be set]"> | ||||
|                 Collapsible Group Item | ||||
|             </button> | ||||
|             <a class="widget-toggle-button no-arrow"  | ||||
|                 title="Minimize/maximize widget" | ||||
|                 data-toggle="collapse" data-target="#[to be set]"> | ||||
|                  | ||||
|             <a class="widget-help external no-arrow bx bx-info-circle"></a> | ||||
|                 <span class="widget-toggle-icon bx"></span> | ||||
|                  | ||||
|                 <span class="widget-title"> | ||||
|                     Collapsible Group Item | ||||
|                 </span>     | ||||
|             </a> | ||||
|          | ||||
|             <span class="widget-header-actions"></span> | ||||
|         </div> | ||||
|          | ||||
|         <div class="widget-header-actions"></div> | ||||
|         <div> | ||||
|             <a class="widget-help external no-arrow bx bx-info-circle"></a> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div id="[to be set]" class="collapse body-wrapper" style="transition: none; "> | ||||
| @@ -66,13 +75,19 @@ export default class CollapsibleWidget extends TabAwareWidget { | ||||
|         // not using constructor name because of webpack mangling class names ... | ||||
|         this.widgetName = this.widgetTitle.replace(/[^[a-zA-Z0-9]/g, "_"); | ||||
|  | ||||
|         if (!options.is(this.widgetName + 'Collapsed')) { | ||||
|         this.$toggleButton = this.$widget.find('.widget-toggle-button'); | ||||
|         this.$toggleIcon = this.$widget.find('.widget-toggle-icon'); | ||||
|  | ||||
|         const collapsed = options.is(this.widgetName + 'Collapsed'); | ||||
|         if (!collapsed) { | ||||
|             this.$bodyWrapper.collapse("show"); | ||||
|         } | ||||
|  | ||||
|         this.updateToggleIcon(collapsed); | ||||
|  | ||||
|         // using immediate variants of the event so that the previous collapse is not caught | ||||
|         this.$bodyWrapper.on('hide.bs.collapse', () => this.saveCollapsed(true)); | ||||
|         this.$bodyWrapper.on('show.bs.collapse', () => this.saveCollapsed(false)); | ||||
|         this.$bodyWrapper.on('hide.bs.collapse', () => this.toggleCollapsed(true)); | ||||
|         this.$bodyWrapper.on('show.bs.collapse', () => this.toggleCollapsed(false)); | ||||
|  | ||||
|         this.$body = this.$bodyWrapper.find('.card-body'); | ||||
|  | ||||
| @@ -94,19 +109,35 @@ export default class CollapsibleWidget extends TabAwareWidget { | ||||
|         } | ||||
|  | ||||
|         this.$headerActions = this.$widget.find('.widget-header-actions'); | ||||
|         this.$headerActions.append(...this.headerActions); | ||||
|         this.$headerActions.append(this.headerActions); | ||||
|  | ||||
|         this.initialized = this.doRenderBody(); | ||||
|  | ||||
|         this.decorateWidget(); | ||||
|     } | ||||
|  | ||||
|     saveCollapsed(collapse) { | ||||
|     toggleCollapsed(collapse) { | ||||
|         this.updateToggleIcon(collapse); | ||||
|  | ||||
|         options.save(this.widgetName + 'Collapsed', collapse.toString()); | ||||
|  | ||||
|         this.triggerEvent(`widgetCollapsedStateChanged`, {widgetName: this.widgetName, collapse}); | ||||
|     } | ||||
|  | ||||
|     updateToggleIcon(collapse) { | ||||
|         if (collapse) { | ||||
|             this.$toggleIcon | ||||
|                 .addClass("bx-chevron-right") | ||||
|                 .removeClass("bx-chevron-down") | ||||
|                 .attr("title", "Show"); | ||||
|         } else { | ||||
|             this.$toggleIcon | ||||
|                 .addClass("bx-chevron-down") | ||||
|                 .removeClass("bx-chevron-right") | ||||
|                 .attr("title", "Hide"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This event is used to synchronize collapsed state of all the tab-cached widgets since they are all rendered | ||||
|      * separately but should behave uniformly for the user. | ||||
|   | ||||
							
								
								
									
										984
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										984
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								package.json
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
|   "name": "trilium", | ||||
|   "productName": "Trilium Notes", | ||||
|   "description": "Trilium Notes", | ||||
|   "version": "0.46.0-beta", | ||||
|   "version": "0.46.3-beta", | ||||
|   "license": "AGPL-3.0-only", | ||||
|   "main": "electron.js", | ||||
|   "bin": { | ||||
| @@ -24,7 +24,7 @@ | ||||
|     "test-all": "npm run test && npm run test-es6" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "async-mutex": "0.3.0", | ||||
|     "async-mutex": "0.3.1", | ||||
|     "axios": "0.21.1", | ||||
|     "better-sqlite3": "7.1.2", | ||||
|     "body-parser": "1.19.0", | ||||
| @@ -35,7 +35,7 @@ | ||||
|     "dayjs": "1.10.4", | ||||
|     "ejs": "3.1.6", | ||||
|     "electron-debug": "3.2.0", | ||||
|     "electron-dl": "3.0.3", | ||||
|     "electron-dl": "3.2.0", | ||||
|     "electron-find": "1.0.6", | ||||
|     "electron-window-state": "5.0.3", | ||||
|     "express": "4.17.1", | ||||
| @@ -51,11 +51,11 @@ | ||||
|     "is-animated": "^2.0.1", | ||||
|     "is-svg": "4.2.1", | ||||
|     "jimp": "0.16.1", | ||||
|     "jsdom": "^16.4.0", | ||||
|     "mime-types": "2.1.28", | ||||
|     "jsdom": "16.5.0", | ||||
|     "mime-types": "2.1.29", | ||||
|     "multer": "1.4.2", | ||||
|     "node-abi": "2.19.3", | ||||
|     "open": "7.4.1", | ||||
|     "node-abi": "2.21.0", | ||||
|     "open": "7.4.2", | ||||
|     "portscanner": "2.2.0", | ||||
|     "rand-token": "1.0.1", | ||||
|     "request": "^2.88.2", | ||||
| @@ -70,16 +70,16 @@ | ||||
|     "striptags": "3.1.1", | ||||
|     "tmp": "^0.2.1", | ||||
|     "turndown": "7.0.0", | ||||
|     "turndown-plugin-gfm": "1.0.2", | ||||
|     "joplin-turndown-plugin-gfm": "1.0.12", | ||||
|     "unescape": "1.0.1", | ||||
|     "ws": "7.4.3", | ||||
|     "ws": "7.4.4", | ||||
|     "yauzl": "2.10.0", | ||||
|     "yazl": "2.5.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "cross-env": "7.0.3", | ||||
|     "electron": "9.4.3", | ||||
|     "electron-builder": "22.9.1", | ||||
|     "electron": "9.4.4", | ||||
|     "electron-builder": "22.10.5", | ||||
|     "electron-packager": "15.2.0", | ||||
|     "electron-rebuild": "2.3.5", | ||||
|     "esm": "3.2.25", | ||||
| @@ -87,7 +87,7 @@ | ||||
|     "jsdoc": "3.6.6", | ||||
|     "lorem-ipsum": "2.0.3", | ||||
|     "rcedit": "3.0.0", | ||||
|     "webpack": "5.21.2", | ||||
|     "webpack": "5.24.4", | ||||
|     "webpack-cli": "4.5.0" | ||||
|   }, | ||||
|   "optionalDependencies": { | ||||
|   | ||||
| @@ -41,7 +41,7 @@ class Entity { | ||||
|     } | ||||
|  | ||||
|     getUtcDateChanged() { | ||||
|         return this.utcDateModified; | ||||
|         return this.utcDateModified || this.utcDateCreated; | ||||
|     } | ||||
|  | ||||
|     get repository() { | ||||
|   | ||||
| @@ -681,7 +681,7 @@ class Note extends Entity { | ||||
|      * Update's given relation's value or creates it if it doesn't exist | ||||
|      * | ||||
|      * @param {string} name - relation name | ||||
|      * @param {string} [value] - relation value (noteId) | ||||
|      * @param {string} value - relation value (noteId) | ||||
|      */ | ||||
|     setRelation(name, value) { return this.setAttribute(RELATION, name, value); } | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,10 @@ export async function showDialog(widget, text = '') { | ||||
|         $linkTitle.val(noteTitle); | ||||
|     } | ||||
|  | ||||
|     noteAutocompleteService.initNoteAutocomplete($autoComplete, { allowExternalLinks: true }); | ||||
|     noteAutocompleteService.initNoteAutocomplete($autoComplete, { | ||||
|         allowExternalLinks: true, | ||||
|         allowCreatingNotes: true | ||||
|     }); | ||||
|  | ||||
|     $autoComplete.on('autocomplete:noteselected', (event, suggestion, dataset) => { | ||||
|         if (!suggestion.notePath) { | ||||
|   | ||||
| @@ -129,7 +129,7 @@ ws.subscribeToMessages(async message => { | ||||
|         toastService.showPersistent(makeToast(message.taskId, "Export in progress: " + message.progressCount)); | ||||
|     } | ||||
|     else if (message.type === 'task-succeeded') { | ||||
|         const toast = makeToast(message.taskId, "Import finished successfully."); | ||||
|         const toast = makeToast(message.taskId, "Export finished successfully."); | ||||
|         toast.closeAfter = 5000; | ||||
|  | ||||
|         toastService.showPersistent(toast); | ||||
|   | ||||
| @@ -17,7 +17,10 @@ export async function showDialog(widget) { | ||||
|  | ||||
|     utils.openDialog($dialog); | ||||
|  | ||||
|     noteAutocompleteService.initNoteAutocomplete($autoComplete, { hideGoToSelectedNoteButton: true }); | ||||
|     noteAutocompleteService.initNoteAutocomplete($autoComplete, { | ||||
|         hideGoToSelectedNoteButton: true, | ||||
|         allowCreatingNotes: true | ||||
|     }); | ||||
|     noteAutocompleteService.showRecentNotes($autoComplete); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -29,7 +29,7 @@ const TPL = ` | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <p>Zooming can be controlled with CTRL-+ and CTRL-= shortcuts as well.</p> | ||||
|     <p>Zooming can be controlled with CTRL+- and CTRL+= shortcuts as well.</p> | ||||
|  | ||||
|     <h4>Font sizes</h4> | ||||
|  | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/public/app/dialogs/sort_child_notes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/public/app/dialogs/sort_child_notes.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| import server from "../services/server.js"; | ||||
| import utils from "../services/utils.js"; | ||||
|  | ||||
| const $dialog = $("#sort-child-notes-dialog"); | ||||
| const $form = $("#sort-child-notes-form"); | ||||
|  | ||||
| let parentNoteId = null; | ||||
|  | ||||
| $form.on('submit', async () => { | ||||
|     const sortBy = $form.find("input[name='sort-by']:checked").val(); | ||||
|     const sortDirection = $form.find("input[name='sort-direction']:checked").val(); | ||||
|  | ||||
|     await server.put(`notes/${parentNoteId}/sort-children`, {sortBy, sortDirection}); | ||||
|  | ||||
|     utils.closeActiveDialog(); | ||||
| }); | ||||
|  | ||||
| export async function showDialog(noteId) { | ||||
|     parentNoteId = noteId; | ||||
|  | ||||
|     utils.openDialog($dialog); | ||||
|  | ||||
|     $form.find('input:first').focus(); | ||||
| } | ||||
| @@ -2,6 +2,7 @@ import server from '../services/server.js'; | ||||
| import noteAttributeCache from "../services/note_attribute_cache.js"; | ||||
| import ws from "../services/ws.js"; | ||||
| import options from "../services/options.js"; | ||||
| import treeCache from "../services/tree_cache.js"; | ||||
|  | ||||
| const LABEL = 'label'; | ||||
| const RELATION = 'relation'; | ||||
| @@ -158,6 +159,26 @@ class NoteShort { | ||||
|         return this.treeCache.getNotesFromCache(this.parents); | ||||
|     } | ||||
|  | ||||
|     // will sort the parents so that non-search & non-archived are first and archived at the end | ||||
|     // this is done so that non-search & non-archived paths are always explored as first when looking for note path | ||||
|     resortParents() { | ||||
|         this.parents.sort((aNoteId, bNoteId) => { | ||||
|             const aBranchId = this.parentToBranch[aNoteId]; | ||||
|  | ||||
|             if (aBranchId && aBranchId.startsWith('virt-')) { | ||||
|                 return 1; | ||||
|             } | ||||
|  | ||||
|             const aNote = this.treeCache.getNoteFromCache([aNoteId]); | ||||
|  | ||||
|             if (aNote.hasLabel('archived')) { | ||||
|                 return 1; | ||||
|             } | ||||
|  | ||||
|             return -1; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** @returns {string[]} */ | ||||
|     getChildNoteIds() { | ||||
|         return this.children; | ||||
| @@ -233,6 +254,55 @@ class NoteShort { | ||||
|         return noteAttributeCache.attributes[this.noteId]; | ||||
|     } | ||||
|  | ||||
|     getAllNotePaths() { | ||||
|         if (this.noteId === 'root') { | ||||
|             return [['root']]; | ||||
|         } | ||||
|  | ||||
|         const parentNotes = this.getParentNotes(); | ||||
|         let paths; | ||||
|  | ||||
|         if (parentNotes.length === 1) { // optimization for the most common case | ||||
|             paths = parentNotes[0].getAllNotePaths(); | ||||
|         } | ||||
|         else { | ||||
|             paths = []; | ||||
|  | ||||
|             for (const parentNote of parentNotes) { | ||||
|                 paths.push(...parentNote.getAllNotePaths()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (const path of paths) { | ||||
|             path.push(this.noteId); | ||||
|         } | ||||
|  | ||||
|         return paths; | ||||
|     } | ||||
|  | ||||
|     getSortedNotePaths(hoistedNotePath = 'root') { | ||||
|         const notePaths = this.getAllNotePaths().map(path => ({ | ||||
|             notePath: path, | ||||
|             isInHoistedSubTree: path.includes(hoistedNotePath), | ||||
|             isArchived: path.find(noteId => treeCache.notes[noteId].hasLabel('archived')), | ||||
|             isSearch: path.find(noteId => treeCache.notes[noteId].type === 'search') | ||||
|         })); | ||||
|  | ||||
|         notePaths.sort((a, b) => { | ||||
|             if (a.isInHoistedSubTree !== b.isInHoistedSubTree) { | ||||
|                 return a.isInHoistedSubTree ? -1 : 1; | ||||
|             } else if (a.isSearch !== b.isSearch) { | ||||
|                 return a.isSearch ? 1 : -1; | ||||
|             } else if (a.isArchived !== b.isArchived) { | ||||
|                 return a.isArchived ? 1 : -1; | ||||
|             } else { | ||||
|                 return a.notePath.length - b.notePath.length; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         return notePaths; | ||||
|     } | ||||
|  | ||||
|     __filterAttrs(attributes, type, name) { | ||||
|         if (!type && !name) { | ||||
|             return attributes; | ||||
| @@ -522,7 +592,7 @@ class NoteShort { | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     hasAncestor(ancestorNote, visitedNoteIds) { | ||||
|     hasAncestor(ancestorNote, visitedNoteIds = null) { | ||||
|         if (this.noteId === ancestorNote.noteId) { | ||||
|             return true; | ||||
|         } | ||||
|   | ||||
| @@ -22,6 +22,7 @@ import ImagePropertiesWidget from "../widgets/type_property_widgets/image_proper | ||||
| import NotePropertiesWidget from "../widgets/type_property_widgets/note_properties.js"; | ||||
| import NoteIconWidget from "../widgets/note_icon.js"; | ||||
| import NotePathsWidget from "../widgets/note_paths.js"; | ||||
| import SearchResultWidget from "../widgets/search_result.js"; | ||||
|  | ||||
| export default class DesktopExtraWindowLayout { | ||||
|     constructor(customWidgets) { | ||||
| @@ -69,6 +70,7 @@ export default class DesktopExtraWindowLayout { | ||||
|                         .child(new TabCachingWidget(() => new SqlTableSchemasWidget())) | ||||
|                         .child(new TabCachingWidget(() => new NoteDetailWidget())) | ||||
|                         .child(new TabCachingWidget(() => new NoteListWidget())) | ||||
|                         .child(new TabCachingWidget(() => new SearchResultWidget())) | ||||
|                         .child(new TabCachingWidget(() => new SqlResultWidget())) | ||||
|                     ) | ||||
|                     .child(...this.customWidgets.get('center-pane')) | ||||
|   | ||||
| @@ -32,6 +32,7 @@ import FilePropertiesWidget from "../widgets/type_property_widgets/file_properti | ||||
| import ImagePropertiesWidget from "../widgets/type_property_widgets/image_properties.js"; | ||||
| import NotePropertiesWidget from "../widgets/type_property_widgets/note_properties.js"; | ||||
| import NoteIconWidget from "../widgets/note_icon.js"; | ||||
| import SearchResultWidget from "../widgets/search_result.js"; | ||||
|  | ||||
| const RIGHT_PANE_CSS = ` | ||||
| <style> | ||||
| @@ -179,6 +180,7 @@ export default class DesktopMainWindowLayout { | ||||
|                         .child(new TabCachingWidget(() => new SqlTableSchemasWidget())) | ||||
|                         .child(new TabCachingWidget(() => new NoteDetailWidget())) | ||||
|                         .child(new TabCachingWidget(() => new NoteListWidget())) | ||||
|                         .child(new TabCachingWidget(() => new SearchResultWidget())) | ||||
|                         .child(new TabCachingWidget(() => new SqlResultWidget())) | ||||
|                     ) | ||||
|                     .child(new TabCachingWidget(() => new SimilarNotesWidget())) | ||||
|   | ||||
| @@ -12,6 +12,7 @@ import keyboardActionsService from "./keyboard_actions.js"; | ||||
| import MobileScreenSwitcherExecutor from "../widgets/mobile_widgets/mobile_screen_switcher.js"; | ||||
| import MainTreeExecutors from "./main_tree_executors.js"; | ||||
| import protectedSessionHolder from "./protected_session_holder.js"; | ||||
| import toast from "./toast.js"; | ||||
|  | ||||
| class AppContext extends Component { | ||||
|     constructor(isMainWindow) { | ||||
| @@ -19,6 +20,7 @@ class AppContext extends Component { | ||||
|  | ||||
|         this.isMainWindow = isMainWindow; | ||||
|         this.executors = []; | ||||
|         this.beforeUnloadListeners = []; | ||||
|     } | ||||
|  | ||||
|     setLayout(layout) { | ||||
| @@ -104,6 +106,15 @@ class AppContext extends Component { | ||||
|     getComponentByEl(el) { | ||||
|         return $(el).closest(".component").prop('component'); | ||||
|     } | ||||
|  | ||||
|     addBeforeUnloadListener(obj) { | ||||
|         if (typeof WeakRef !== "function") { | ||||
|             // older browsers don't support WeakRef | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.beforeUnloadListeners.push(new WeakRef(obj)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| const appContext = new AppContext(window.glob.isMainWindow); | ||||
| @@ -112,7 +123,29 @@ const appContext = new AppContext(window.glob.isMainWindow); | ||||
| $(window).on('beforeunload', () => { | ||||
|     protectedSessionHolder.resetSessionCookie(); | ||||
|  | ||||
|     appContext.triggerEvent('beforeUnload'); | ||||
|     let allSaved = true; | ||||
|  | ||||
|     appContext.beforeUnloadListeners = appContext.beforeUnloadListeners.filter(wr => !!wr.deref()); | ||||
|  | ||||
|     for (const weakRef of appContext.beforeUnloadListeners) { | ||||
|         const component = weakRef.deref(); | ||||
|  | ||||
|         if (!component) { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         if (!component.beforeUnloadEvent()) { | ||||
|             console.log(`Component ${component.componentId} is not finished saving its state.`); | ||||
|  | ||||
|             toast.showMessage("Please wait for a couple of seconds for the save to finish, then you can try again.", 10000); | ||||
|  | ||||
|             allSaved = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!allSaved) { | ||||
|         return "some string"; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function isNotePathInAddress() { | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| import utils from "./utils.js"; | ||||
|  | ||||
| function lex(str) { | ||||
|     str = str.trim(); | ||||
|  | ||||
| @@ -105,14 +107,12 @@ function lex(str) { | ||||
|     return tokens; | ||||
| } | ||||
|  | ||||
| const attrNameMatcher = new RegExp("^[\\p{L}\\p{N}_:]+$", "u"); | ||||
|  | ||||
| function checkAttributeName(attrName) { | ||||
|     if (attrName.length === 0) { | ||||
|         throw new Error("Attribute name is empty, please fill the name."); | ||||
|     } | ||||
|  | ||||
|     if (!attrNameMatcher.test(attrName)) { | ||||
|     if (!utils.isValidAttributeName(attrName)) { | ||||
|         throw new Error(`Attribute name "${attrName}" contains disallowed characters, only alphanumeric characters, colon and underscore are allowed.`); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ws from "./ws.js"; | ||||
|  | ||||
| async function moveBeforeBranch(branchIdsToMove, beforeBranchId) { | ||||
|     branchIdsToMove = filterRootNote(branchIdsToMove); | ||||
|     branchIdsToMove = filterSearchBranches(branchIdsToMove); | ||||
|  | ||||
|     if (beforeBranchId === 'root') { | ||||
|         alert('Cannot move notes before root note.'); | ||||
| @@ -25,6 +26,7 @@ async function moveBeforeBranch(branchIdsToMove, beforeBranchId) { | ||||
|  | ||||
| async function moveAfterBranch(branchIdsToMove, afterBranchId) { | ||||
|     branchIdsToMove = filterRootNote(branchIdsToMove); | ||||
|     branchIdsToMove = filterSearchBranches(branchIdsToMove); | ||||
|  | ||||
|     const afterNote = await treeCache.getBranch(afterBranchId).getNote(); | ||||
|  | ||||
| @@ -123,7 +125,7 @@ async function deleteNotes(branchIdsToDelete) { | ||||
| } | ||||
|  | ||||
| async function moveNodeUpInHierarchy(node) { | ||||
|     if (hoistedNoteService.isRootNode(node) | ||||
|     if (hoistedNoteService.isHoistedNode(node) | ||||
|         || hoistedNoteService.isTopLevelNode(node) | ||||
|         || node.getParent().data.noteType === 'search') { | ||||
|         return; | ||||
| @@ -142,6 +144,10 @@ async function moveNodeUpInHierarchy(node) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| function filterSearchBranches(branchIds) { | ||||
|     return branchIds.filter(branchId => !branchId.startsWith('virt-')); | ||||
| } | ||||
|  | ||||
| function filterRootNote(branchIds) { | ||||
|     const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,8 @@ async function getTodayNote() { | ||||
| async function getDateNote(date) { | ||||
|     const note = await server.get('date-notes/date/' + date, "date-note"); | ||||
|  | ||||
|     await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|     return await treeCache.getNote(note.noteId); | ||||
| } | ||||
|  | ||||
| @@ -25,6 +27,8 @@ async function getDateNote(date) { | ||||
| async function getMonthNote(month) { | ||||
|     const note = await server.get('date-notes/month/' + month, "date-note"); | ||||
|  | ||||
|     await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|     return await treeCache.getNote(note.noteId); | ||||
| } | ||||
|  | ||||
| @@ -32,6 +36,8 @@ async function getMonthNote(month) { | ||||
| async function getYearNote(year) { | ||||
|     const note = await server.get('date-notes/year/' + year, "date-note"); | ||||
|  | ||||
|     await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|     return await treeCache.getNote(note.noteId); | ||||
| } | ||||
|  | ||||
| @@ -39,21 +45,14 @@ async function getYearNote(year) { | ||||
| async function createSqlConsole() { | ||||
|     const note = await server.post('sql-console'); | ||||
|  | ||||
|     await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|     return await treeCache.getNote(note.noteId); | ||||
| } | ||||
|  | ||||
| /** @return {NoteShort} */ | ||||
| async function createSearchNote(opts = {}) { | ||||
|     const note = await server.post('search-note'); | ||||
|  | ||||
|     const attrsToUpdate = [ | ||||
|         opts.ancestorNoteId ? { type: 'relation', name: 'ancestor', value: opts.ancestorNoteId } : undefined, | ||||
|         { type: 'label', name: 'searchString', value: opts.searchString } | ||||
|     ].filter(attr => !!attr); | ||||
|  | ||||
|     if (attrsToUpdate.length > 0) { | ||||
|         await server.put(`notes/${note.noteId}/attributes`, attrsToUpdate); | ||||
|     } | ||||
|     const note = await server.post('search-note', opts); | ||||
|  | ||||
|     await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|   | ||||
| @@ -182,8 +182,6 @@ export default class Entrypoints extends Component { | ||||
|         utils.reloadApp(); | ||||
|     } | ||||
|  | ||||
|     createTopLevelNoteCommand() { noteCreateService.createNewTopLevelNote(); } | ||||
|  | ||||
|     async openInWindowCommand({notePath, hoistedNoteId}) { | ||||
|         if (!hoistedNoteId) { | ||||
|             hoistedNoteId = 'root'; | ||||
|   | ||||
| @@ -71,6 +71,23 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|         appContext.triggerEvent('focusAndSelectTitle'); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Open a note in a new tab. | ||||
|      * | ||||
|      * @param {string} notePath (or noteId) | ||||
|      * @param {boolean} activate - set to true to activate the new tab, false to stay on the current tab | ||||
|      * @return {Promise<void>} | ||||
|      */ | ||||
|     this.openTabWithNote = async (notePath, activate) => { | ||||
|         await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|         await appContext.tabManager.openTabWithNote(notePath, activate); | ||||
|  | ||||
|         if (activate) { | ||||
|             appContext.triggerEvent('focusAndSelectTitle'); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @typedef {Object} ToolbarButtonOptions | ||||
|      * @property {string} title | ||||
| @@ -149,8 +166,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain | ||||
|         }, "script"); | ||||
|  | ||||
|         if (ret.success) { | ||||
|             // wait until all the changes done in the script has been synced to frontend before continuing | ||||
|             await ws.waitForEntityChangeId(ret.maxEntityChangeId); | ||||
|             await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|             return ret.executionResult; | ||||
|         } | ||||
|   | ||||
| @@ -16,10 +16,10 @@ async function unhoist() { | ||||
| } | ||||
|  | ||||
| function isTopLevelNode(node) { | ||||
|     return isRootNode(node.getParent()); | ||||
|     return isHoistedNode(node.getParent()); | ||||
| } | ||||
|  | ||||
| function isRootNode(node) { | ||||
| function isHoistedNode(node) { | ||||
|     // even though check for 'root' should not be necessary, we keep it just in case | ||||
|     return node.data.noteId === "root" | ||||
|         || node.data.noteId === getHoistedNoteId(); | ||||
| @@ -55,6 +55,6 @@ export default { | ||||
|     getHoistedNoteId, | ||||
|     unhoist, | ||||
|     isTopLevelNode, | ||||
|     isRootNode, | ||||
|     isHoistedNode, | ||||
|     checkNoteAccess | ||||
| } | ||||
|   | ||||
| @@ -117,7 +117,8 @@ export default class LinkMap { | ||||
|  | ||||
|             const $noteBox = $("<div>") | ||||
|                 .addClass("note-box") | ||||
|                 .prop("id", noteBoxId); | ||||
|                 .prop("id", noteBoxId) | ||||
|                 .addClass(note.getCssClass()); | ||||
|  | ||||
|             const $link = $linkTitles[noteId]; | ||||
|  | ||||
|   | ||||
| @@ -27,28 +27,28 @@ export default class MainTreeExecutors extends Component { | ||||
|     } | ||||
|  | ||||
|     async createNoteIntoCommand() { | ||||
|         const activeNote = appContext.tabManager.getActiveTabNote(); | ||||
|         const activeTabContext = appContext.tabManager.getActiveTabContext(); | ||||
|  | ||||
|         if (!activeNote) { | ||||
|         if (!activeTabContext) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         await noteCreateService.createNote(activeNote.noteId, { | ||||
|             isProtected: activeNote.isProtected, | ||||
|         await noteCreateService.createNote(activeTabContext.notePath, { | ||||
|             isProtected: activeTabContext.note.isProtected, | ||||
|             saveSelection: false | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     async createNoteAfterCommand() { | ||||
|         const node = this.tree.getActiveNode(); | ||||
|         const parentNoteId = node.data.parentNoteId; | ||||
|         const parentNotePath = treeService.getNotePath(node.getParent()); | ||||
|         const isProtected = await treeService.getParentProtectedStatus(node); | ||||
|  | ||||
|         if (node.data.noteId === 'root' || node.data.noteId === hoistedNoteService.getHoistedNoteId()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         await noteCreateService.createNote(parentNoteId, { | ||||
|         await noteCreateService.createNote(parentNotePath, { | ||||
|             target: 'after', | ||||
|             targetBranchId: node.data.branchId, | ||||
|             isProtected: isProtected, | ||||
|   | ||||
| @@ -1,19 +1,13 @@ | ||||
| import hoistedNoteService from "./hoisted_note.js"; | ||||
| import appContext from "./app_context.js"; | ||||
| import utils from "./utils.js"; | ||||
| import protectedSessionHolder from "./protected_session_holder.js"; | ||||
| import server from "./server.js"; | ||||
| import ws from "./ws.js"; | ||||
| import treeCache from "./tree_cache.js"; | ||||
| import treeService from "./tree.js"; | ||||
| import toastService from "./toast.js"; | ||||
|  | ||||
| async function createNewTopLevelNote() { | ||||
|     const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); | ||||
|  | ||||
|     await createNote(hoistedNoteId); | ||||
| } | ||||
|  | ||||
| async function createNote(parentNoteId, options = {}) { | ||||
| async function createNote(parentNotePath, options = {}) { | ||||
|     options = Object.assign({ | ||||
|         activate: true, | ||||
|         focus: 'title', | ||||
| @@ -36,6 +30,8 @@ async function createNote(parentNoteId, options = {}) { | ||||
|  | ||||
|     const newNoteName = options.title || "new note"; | ||||
|  | ||||
|     const parentNoteId = treeService.getNoteIdFromNotePath(parentNotePath); | ||||
|  | ||||
|     const {note, branch} = await server.post(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId}`, { | ||||
|         title: newNoteName, | ||||
|         content: options.content || "", | ||||
| @@ -53,7 +49,7 @@ async function createNote(parentNoteId, options = {}) { | ||||
|  | ||||
|     if (options.activate) { | ||||
|         const activeTabContext = appContext.tabManager.getActiveTabContext(); | ||||
|         await activeTabContext.setNote(note.noteId); | ||||
|         await activeTabContext.setNote(`${parentNotePath}/${note.noteId}`); | ||||
|  | ||||
|         if (options.focus === 'title') { | ||||
|             appContext.triggerEvent('focusAndSelectTitle'); | ||||
| @@ -88,12 +84,13 @@ function parseSelectedHtml(selectedHtml) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function duplicateSubtree(noteId, parentNoteId) { | ||||
| async function duplicateSubtree(noteId, parentNotePath) { | ||||
|     const parentNoteId = treeService.getNoteIdFromNotePath(parentNotePath); | ||||
|     const {note} = await server.post(`notes/${noteId}/duplicate/${parentNoteId}`); | ||||
|  | ||||
|     await ws.waitForMaxKnownEntityChangeId(); | ||||
|  | ||||
|     await appContext.tabManager.activateOrOpenNote(note.noteId); | ||||
|     await appContext.tabManager.activateOrOpenNote(`${parentNotePath}/${note.noteId}`); | ||||
|  | ||||
|     const origNote = await treeCache.getNote(noteId); | ||||
|     toastService.showMessage(`Note "${origNote.title}" has been duplicated`); | ||||
| @@ -101,6 +98,5 @@ async function duplicateSubtree(noteId, parentNoteId) { | ||||
|  | ||||
| export default { | ||||
|     createNote, | ||||
|     createNewTopLevelNote, | ||||
|     duplicateSubtree | ||||
| }; | ||||
|   | ||||
| @@ -56,6 +56,14 @@ const TPL = ` | ||||
|      | ||||
|     .note-book-title { | ||||
|         margin-bottom: 0; | ||||
|         word-break: break-all; | ||||
|     } | ||||
|      | ||||
|     /* not-expanded title is limited to one line only */ | ||||
|     .note-book-card:not(.expanded) .note-book-title { | ||||
|         overflow: hidden; | ||||
|         white-space: nowrap; | ||||
|         text-overflow: ellipsis; | ||||
|     } | ||||
|      | ||||
|     .note-book-title .rendered-note-attributes { | ||||
| @@ -148,7 +156,7 @@ class NoteListRenderer { | ||||
|     /* | ||||
|      * We're using noteIds so that it's not necessary to load all notes at once when paging | ||||
|      */ | ||||
|     constructor($parent, parentNote, noteIds) { | ||||
|     constructor($parent, parentNote, noteIds, showNotePath = false) { | ||||
|         this.$noteList = $(TPL); | ||||
|  | ||||
|         // note list must be added to the DOM immediatelly, otherwise some functionality scripting (canvas) won't work | ||||
| @@ -200,6 +208,8 @@ class NoteListRenderer { | ||||
|  | ||||
|             await this.renderList(); | ||||
|         }); | ||||
|  | ||||
|         this.showNotePath = showNotePath; | ||||
|     } | ||||
|  | ||||
|     /** @return {Set<string>} list of noteIds included (images, included notes) into a parent note and which | ||||
| @@ -298,7 +308,7 @@ class NoteListRenderer { | ||||
|             .append( | ||||
|                 $('<h5 class="note-book-title">') | ||||
|                     .append($expander) | ||||
|                     .append(await linkService.createNoteLink(note.noteId, {showTooltip: false})) | ||||
|                     .append(await linkService.createNoteLink(note.noteId, {showTooltip: false, showNotePath: this.showNotePath})) | ||||
|                     .append($renderedAttributes) | ||||
|             ); | ||||
|  | ||||
|   | ||||
| @@ -15,9 +15,25 @@ export default class SpacedUpdate { | ||||
|  | ||||
|     async updateNowIfNecessary() { | ||||
|         if (this.changed) { | ||||
|             this.changed = false; | ||||
|             this.changed = false; // optimistic... | ||||
|  | ||||
|             try { | ||||
|                 await this.updater(); | ||||
|             } | ||||
|             catch (e) { | ||||
|                 this.changed = true; | ||||
|  | ||||
|                 throw e; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     isAllSavedAndTriggerUpdate() { | ||||
|         const allSaved = !this.changed; | ||||
|  | ||||
|         this.updateNowIfNecessary(); | ||||
|  | ||||
|         return allSaved; | ||||
|     } | ||||
|  | ||||
|     triggerUpdate() { | ||||
|   | ||||
| @@ -79,7 +79,7 @@ class TabContext extends Component { | ||||
|             return inputNotePath; | ||||
|         } | ||||
|  | ||||
|         const resolvedNotePath = await treeService.resolveNotePath(inputNotePath); | ||||
|         const resolvedNotePath = await treeService.resolveNotePath(inputNotePath, this.hoistedNoteId); | ||||
|  | ||||
|         if (!resolvedNotePath) { | ||||
|             logError(`Cannot resolve note path ${inputNotePath}`); | ||||
|   | ||||
| @@ -27,6 +27,8 @@ export default class TabManager extends Component { | ||||
|                 openTabs: JSON.stringify(openTabs) | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         appContext.addBeforeUnloadListener(this); | ||||
|     } | ||||
|  | ||||
|     /** @type {TabContext[]} */ | ||||
| @@ -203,7 +205,7 @@ export default class TabManager extends Component { | ||||
|         let hoistedNoteId = 'root'; | ||||
|  | ||||
|         if (tabContext) { | ||||
|             const resolvedNotePath = await treeService.resolveNotePath(notePath); | ||||
|             const resolvedNotePath = await treeService.resolveNotePath(notePath, tabContext.hoistedNoteId); | ||||
|  | ||||
|             if (resolvedNotePath.includes(tabContext.hoistedNoteId)) { | ||||
|                 hoistedNoteId = tabContext.hoistedNoteId; | ||||
| @@ -329,6 +331,8 @@ export default class TabManager extends Component { | ||||
|  | ||||
|     beforeUnloadEvent() { | ||||
|         this.tabsUpdate.updateNowIfNecessary(); | ||||
|  | ||||
|         return true; // don't block closing the tab, this metadata is not that important | ||||
|     } | ||||
|  | ||||
|     openNewTabCommand() { | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import appContext from "./app_context.js"; | ||||
| /** | ||||
|  * @return {string|null} | ||||
|  */ | ||||
| async function resolveNotePath(notePath) { | ||||
|     const runPath = await resolveNotePathToSegments(notePath); | ||||
| async function resolveNotePath(notePath, hoistedNoteId = 'root') { | ||||
|     const runPath = await resolveNotePathToSegments(notePath, hoistedNoteId); | ||||
|  | ||||
|     return runPath ? runPath.join("/") : null; | ||||
| } | ||||
| @@ -21,7 +21,7 @@ async function resolveNotePath(notePath) { | ||||
|  * | ||||
|  * @return {string[]} | ||||
|  */ | ||||
| async function resolveNotePathToSegments(notePath, logErrors = true) { | ||||
| async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logErrors = true) { | ||||
|     utils.assertArguments(notePath); | ||||
|  | ||||
|     // we might get notePath with the tabId suffix, remove it if present | ||||
| @@ -56,6 +56,8 @@ async function resolveNotePathToSegments(notePath, logErrors = true) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             child.resortParents(); | ||||
|  | ||||
|             const parents = child.getParentNotes(); | ||||
|  | ||||
|             if (!parents.length) { | ||||
| @@ -73,10 +75,10 @@ async function resolveNotePathToSegments(notePath, logErrors = true) { | ||||
|                     console.log(utils.now(), `Did not find parent ${parentNoteId} (${parent ? parent.title : 'n/a'}) for child ${childNoteId} (${child.title}), available parents: ${parents.map(p => `${p.noteId} (${p.title})`)}`); | ||||
|                 } | ||||
|  | ||||
|                 const someNotePath = getSomeNotePath(parents[0]); | ||||
|                 const someNotePath = getSomeNotePath(child, hoistedNoteId); | ||||
|  | ||||
|                 if (someNotePath) { // in case it's root the path may be empty | ||||
|                     const pathToRoot = someNotePath.split("/").reverse(); | ||||
|                     const pathToRoot = someNotePath.split("/").reverse().slice(1); | ||||
|  | ||||
|                     for (const noteId of pathToRoot) { | ||||
|                         effectivePath.push(noteId); | ||||
| @@ -94,29 +96,18 @@ async function resolveNotePathToSegments(notePath, logErrors = true) { | ||||
|     return effectivePath.reverse(); | ||||
| } | ||||
|  | ||||
| function getSomeNotePath(note) { | ||||
| function getSomeNotePathSegments(note, hoistedNotePath = 'root') { | ||||
|     utils.assertArguments(note); | ||||
|  | ||||
|     const path = []; | ||||
|     const notePaths = note.getSortedNotePaths(hoistedNotePath); | ||||
|  | ||||
|     let cur = note; | ||||
|  | ||||
|     while (cur.noteId !== 'root') { | ||||
|         path.push(cur.noteId); | ||||
|  | ||||
|         const parents = cur.getParentNotes().filter(note => note.type !== 'search'); | ||||
|  | ||||
|         if (!parents.length) { | ||||
|             logError(`Can't find parents for note ${cur.noteId}`); | ||||
|             return; | ||||
|     return notePaths[0].notePath; | ||||
| } | ||||
|  | ||||
|         cur = parents[0]; | ||||
|     } | ||||
| function getSomeNotePath(note, hoistedNotePath = 'root') { | ||||
|     const notePath = getSomeNotePathSegments(note, hoistedNotePath); | ||||
|  | ||||
|     path.push('root'); | ||||
|  | ||||
|     return path.reverse().join('/'); | ||||
|     return notePath.join('/'); | ||||
| } | ||||
|  | ||||
| async function sortAlphabetically(noteId) { | ||||
| @@ -136,7 +127,7 @@ ws.subscribeToMessages(message => { | ||||
| }); | ||||
|  | ||||
| function getParentProtectedStatus(node) { | ||||
|     return hoistedNoteService.isRootNode(node) ? 0 : node.getParent().data.isProtected; | ||||
|     return hoistedNoteService.isHoistedNode(node) ? 0 : node.getParent().data.isProtected; | ||||
| } | ||||
|  | ||||
| function getNoteIdFromNotePath(notePath) { | ||||
| @@ -196,7 +187,7 @@ function getNotePath(node) { | ||||
|  | ||||
|     const path = []; | ||||
|  | ||||
|     while (node && !hoistedNoteService.isRootNode(node)) { | ||||
|     while (node) { | ||||
|         if (node.data.noteId) { | ||||
|             path.push(node.data.noteId); | ||||
|         } | ||||
| @@ -204,10 +195,6 @@ function getNotePath(node) { | ||||
|         node = node.getParent(); | ||||
|     } | ||||
|  | ||||
|     if (node) { // null node can happen directly after unhoisting when tree is still hoisted but option has been changed already | ||||
|         path.push(node.data.noteId); // root or hoisted noteId | ||||
|     } | ||||
|  | ||||
|     return path.reverse().join("/"); | ||||
| } | ||||
|  | ||||
| @@ -311,6 +298,7 @@ export default { | ||||
|     resolveNotePath, | ||||
|     resolveNotePathToSegments, | ||||
|     getSomeNotePath, | ||||
|     getSomeNotePathSegments, | ||||
|     getParentProtectedStatus, | ||||
|     getNotePath, | ||||
|     getNoteIdFromNotePath, | ||||
|   | ||||
| @@ -195,6 +195,8 @@ class TreeCache { | ||||
|                     branches, | ||||
|                     attributes: [] | ||||
|                 }); | ||||
|  | ||||
|                 treeCache.notes[note.noteId].searchResultsLoaded = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -75,7 +75,7 @@ class TreeContextMenu { | ||||
|                     { title: 'Expand subtree <kbd data-command="expandSubtree"></kbd>', command: "expandSubtree", uiIcon: "expand", enabled: noSelectedNotes }, | ||||
|                     { title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "collapse", enabled: noSelectedNotes }, | ||||
|                     { title: "Force note sync", command: "forceNoteSync", uiIcon: "refresh", enabled: noSelectedNotes }, | ||||
|                     { title: 'Sort alphabetically <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "empty", enabled: noSelectedNotes && notSearch }, | ||||
|                     { title: 'Sort by ... <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "empty", enabled: noSelectedNotes && notSearch }, | ||||
|                     { title: 'Recent changes in subtree', command: "recentChangesInSubtree", uiIcon: "history", enabled: noSelectedNotes } | ||||
|                 ] }, | ||||
|             { title: "----" }, | ||||
| @@ -112,10 +112,10 @@ class TreeContextMenu { | ||||
|             appContext.tabManager.openTabWithNoteWithHoisting(notePath); | ||||
|         } | ||||
|         else if (command === "insertNoteAfter") { | ||||
|             const parentNoteId = this.node.data.parentNoteId; | ||||
|             const parentNotePath = treeService.getNotePath(this.node.getParent()); | ||||
|             const isProtected = await treeService.getParentProtectedStatus(this.node); | ||||
|  | ||||
|             noteCreateService.createNote(parentNoteId, { | ||||
|             noteCreateService.createNote(parentNotePath, { | ||||
|                 target: 'after', | ||||
|                 targetBranchId: this.node.data.branchId, | ||||
|                 type: type, | ||||
| @@ -123,14 +123,14 @@ class TreeContextMenu { | ||||
|             }); | ||||
|         } | ||||
|         else if (command === "insertChildNote") { | ||||
|             noteCreateService.createNote(noteId, { | ||||
|             const parentNotePath = treeService.getNotePath(this.node); | ||||
|  | ||||
|             noteCreateService.createNote(parentNotePath, { | ||||
|                 type: type, | ||||
|                 isProtected: this.node.data.isProtected | ||||
|             }); | ||||
|         } | ||||
|         else { | ||||
|             console.log("Triggering", command, notePath); | ||||
|  | ||||
|             this.treeWidget.triggerCommand(command, {node: this.node, notePath: notePath}); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -193,6 +193,10 @@ function getNoteTypeClass(type) { | ||||
| } | ||||
|  | ||||
| function getMimeTypeClass(mime) { | ||||
|     if (!mime) { | ||||
|         return ""; | ||||
|     } | ||||
|  | ||||
|     const semicolonIdx = mime.indexOf(';'); | ||||
|  | ||||
|     if (semicolonIdx !== -1) { | ||||
| @@ -296,9 +300,13 @@ function dynamicRequire(moduleName) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| function timeLimit(promise, limitMs) { | ||||
| function timeLimit(promise, limitMs, errorMessage) { | ||||
|     if (!promise || !promise.then) { // it's not actually a promise | ||||
|         return promise; | ||||
|     } | ||||
|  | ||||
|     // better stack trace if created outside of promise | ||||
|     const error = new Error('Process exceeded time limit ' + limitMs); | ||||
|     const error = new Error(errorMessage || `Process exceeded time limit ${limitMs}`); | ||||
|  | ||||
|     return new Promise((res, rej) => { | ||||
|         let resolved = false; | ||||
| @@ -334,6 +342,16 @@ function initHelpButtons($el) { | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function filterAttributeName(name) { | ||||
|     return name.replace(/[^\p{L}\p{N}_:]/ug, ""); | ||||
| } | ||||
|  | ||||
| const ATTR_NAME_MATCHER = new RegExp("^[\\p{L}\\p{N}_:]+$", "u"); | ||||
|  | ||||
| function isValidAttributeName(name) { | ||||
|     return ATTR_NAME_MATCHER.test(name); | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     reloadApp, | ||||
|     parseDate, | ||||
| @@ -374,5 +392,7 @@ export default { | ||||
|     dynamicRequire, | ||||
|     timeLimit, | ||||
|     initHelpDropdown, | ||||
|     initHelpButtons | ||||
|     initHelpButtons, | ||||
|     filterAttributeName, | ||||
|     isValidAttributeName | ||||
| }; | ||||
|   | ||||
| @@ -43,7 +43,6 @@ const processedEntityChangeIds = new Set(); | ||||
| function logRows(entityChanges) { | ||||
|     const filteredRows = entityChanges.filter(row => | ||||
|         !processedEntityChangeIds.has(row.id) | ||||
|         && row.entityName !== 'recent_notes' | ||||
|         && (row.entityName !== 'options' || row.entityId !== 'openTabs')); | ||||
|  | ||||
|     if (filteredRows.length > 0) { | ||||
| @@ -103,7 +102,7 @@ function waitForEntityChangeId(desiredEntityChangeId) { | ||||
|         return Promise.resolve(); | ||||
|     } | ||||
|  | ||||
|     console.debug("Waiting for", desiredEntityChangeId, 'current is', lastProcessedEntityChangeId); | ||||
|     console.debug(`Waiting for ${desiredEntityChangeId}, last processed is ${lastProcessedEntityChangeId}, last accepted ${lastAcceptedEntityChangeId}`); | ||||
|  | ||||
|     return new Promise((res, rej) => { | ||||
|         entityChangeIdReachedListeners.push({ | ||||
| @@ -127,7 +126,7 @@ function checkEntityChangeIdListeners() { | ||||
|         .filter(l => l.desiredEntityChangeId > lastProcessedEntityChangeId); | ||||
|  | ||||
|     entityChangeIdReachedListeners.filter(l => Date.now() > l.start - 60000) | ||||
|         .forEach(l => console.log(`Waiting for entityChangeId ${l.desiredEntityChangeId} while current is ${lastProcessedEntityChangeId} for ${Math.floor((Date.now() - l.start) / 1000)}s`)); | ||||
|         .forEach(l => console.log(`Waiting for entityChangeId ${l.desiredEntityChangeId} while last processed is ${lastProcessedEntityChangeId} (last accepted ${lastAcceptedEntityChangeId}) for ${Math.floor((Date.now() - l.start) / 1000)}s`)); | ||||
| } | ||||
|  | ||||
| async function runSafely(syncHandler, syncData) { | ||||
| @@ -230,25 +229,6 @@ subscribeToMessages(message => { | ||||
| }); | ||||
|  | ||||
| async function processEntityChanges(entityChanges) { | ||||
|     const missingNoteIds = []; | ||||
|  | ||||
|     for (const {entityName, entity} of entityChanges) { | ||||
|         if (entityName === 'branches' && !(entity.parentNoteId in treeCache.notes)) { | ||||
|             missingNoteIds.push(entity.parentNoteId); | ||||
|         } | ||||
|         else if (entityName === 'attributes' | ||||
|               && entity.type === 'relation' | ||||
|               && entity.name === 'template' | ||||
|               && !(entity.noteId in treeCache.notes)) { | ||||
|  | ||||
|             missingNoteIds.push(entity.value); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (missingNoteIds.length > 0) { | ||||
|         await treeCache.reloadNotes(missingNoteIds); | ||||
|     } | ||||
|  | ||||
|     const loadResults = new LoadResults(treeCache); | ||||
|  | ||||
|     for (const ec of entityChanges.filter(ec => ec.entityName === 'notes')) { | ||||
| @@ -391,6 +371,25 @@ async function processEntityChanges(entityChanges) { | ||||
|         loadResults.addOption(ec.entity.name); | ||||
|     } | ||||
|  | ||||
|     const missingNoteIds = []; | ||||
|  | ||||
|     for (const {entityName, entity} of entityChanges) { | ||||
|         if (entityName === 'branches' && !(entity.parentNoteId in treeCache.notes)) { | ||||
|             missingNoteIds.push(entity.parentNoteId); | ||||
|         } | ||||
|         else if (entityName === 'attributes' | ||||
|             && entity.type === 'relation' | ||||
|             && entity.name === 'template' | ||||
|             && !(entity.value in treeCache.notes)) { | ||||
|  | ||||
|             missingNoteIds.push(entity.value); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (missingNoteIds.length > 0) { | ||||
|         await treeCache.reloadNotes(missingNoteIds); | ||||
|     } | ||||
|  | ||||
|     if (!loadResults.isEmpty()) { | ||||
|         if (loadResults.hasAttributeRelatedChanges()) { | ||||
|             noteAttributeCache.invalidate(); | ||||
|   | ||||
| @@ -172,8 +172,6 @@ const ATTR_TITLES = { | ||||
|     "relation-definition": "Relation definition detail" | ||||
| }; | ||||
|  | ||||
| const ATTR_NAME_MATCHER = new RegExp("^[\\p{L}\\p{N}_:]+$", "u"); | ||||
|  | ||||
| const ATTR_HELP = { | ||||
|     "label": { | ||||
|         "disableVersioning": "disables auto-versioning. Useful for e.g. large, but unimportant notes - e.g. large JS libraries used for scripting", | ||||
| @@ -281,7 +279,7 @@ export default class AttributeDetailWidget extends TabAwareWidget { | ||||
|         this.$rowTargetNote = this.$widget.find('.attr-row-target-note'); | ||||
|         this.$inputTargetNote = this.$widget.find('.attr-input-target-note'); | ||||
|  | ||||
|         noteAutocompleteService.initNoteAutocomplete(this.$inputTargetNote) | ||||
|         noteAutocompleteService.initNoteAutocomplete(this.$inputTargetNote, {allowCreatingNotes: true}) | ||||
|             .on('autocomplete:noteselected', (event, suggestion, dataset) => { | ||||
|                 if (!suggestion.notePath) { | ||||
|                     return false; | ||||
| @@ -573,9 +571,9 @@ export default class AttributeDetailWidget extends TabAwareWidget { | ||||
|     updateAttributeInEditor() { | ||||
|         let attrName = this.$inputName.val(); | ||||
|  | ||||
|         if (!ATTR_NAME_MATCHER.test(attrName)) { | ||||
|         if (!utils.isValidAttributeName(attrName)) { | ||||
|             // invalid characters are simply ignored (from user perspective they are not even entered) | ||||
|             attrName = attrName.replace(/[^\p{L}\p{N}_:]/ug, ""); | ||||
|             attrName = utils.filterAttributeName(attrName); | ||||
|  | ||||
|             this.$inputName.val(attrName); | ||||
|         } | ||||
|   | ||||
| @@ -491,7 +491,7 @@ export default class AttributeEditorWidget extends TabAwareWidget { | ||||
|     } | ||||
|  | ||||
|     async createNoteForReferenceLink(title) { | ||||
|         const {note} = await noteCreateService.createNote(this.noteId, { | ||||
|         const {note} = await noteCreateService.createNote(this.notePath, { | ||||
|             activate: false, | ||||
|             title: title | ||||
|         }); | ||||
|   | ||||
| @@ -122,7 +122,7 @@ export default class CollapsibleSectionContainer extends TabAwareWidget { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note) { | ||||
|     async refreshWithNote(note, noExplicitActivation = false) { | ||||
|         let $sectionToActivate, $lastActiveSection; | ||||
|  | ||||
|         this.$titleContainer.empty().append('<div class="section-title section-title-empty">'); | ||||
| @@ -141,7 +141,7 @@ export default class CollapsibleSectionContainer extends TabAwareWidget { | ||||
|             this.$titleContainer.append($sectionTitle); | ||||
|             this.$titleContainer.append('<div class="section-title section-title-empty">'); | ||||
|  | ||||
|             if (ret.activate && !$sectionToActivate) { | ||||
|             if (ret.activate && !$sectionToActivate && !noExplicitActivation) { | ||||
|                 $sectionToActivate = $sectionTitle; | ||||
|             } | ||||
|  | ||||
| @@ -161,4 +161,8 @@ export default class CollapsibleSectionContainer extends TabAwareWidget { | ||||
|             this.$bodyContainer.find('.section-body').removeClass("active"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     refreshSectionContainerCommand() { | ||||
|         this.refreshWithNote(this.note, true); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -12,6 +12,10 @@ const TPL = ` | ||||
|             text-overflow: ellipsis; | ||||
|         } | ||||
|     </style> | ||||
|      | ||||
|     <div class="no-edited-notes-found">No edited notes on this day yet ...</div> | ||||
|      | ||||
|     <div class="edited-notes-list"></div> | ||||
| </div> | ||||
| `; | ||||
|  | ||||
| @@ -31,18 +35,20 @@ export default class EditedNotesWidget extends CollapsibleWidget { | ||||
|  | ||||
|     async doRenderBody() { | ||||
|         this.$body.html(TPL); | ||||
|         this.$editedNotes = this.$body.find('.edited-notes-widget'); | ||||
|         this.$list = this.$body.find('.edited-notes-list'); | ||||
|         this.$noneFound = this.$body.find('.no-edited-notes-found'); | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note) { | ||||
|         // remember which title was when we found the similar notes | ||||
|         this.title = note.title; | ||||
|         let editedNotes = await server.get('edited-notes/' + note.getLabelValue("dateNote")); | ||||
|  | ||||
|         editedNotes = editedNotes.filter(n => n.noteId !== note.noteId); | ||||
|  | ||||
|         this.$list.empty(); | ||||
|         this.$noneFound.hide(); | ||||
|  | ||||
|         if (editedNotes.length === 0) { | ||||
|             this.$body.text("No edited notes on this day yet ..."); | ||||
|             this.$noneFound.show(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -50,8 +56,6 @@ export default class EditedNotesWidget extends CollapsibleWidget { | ||||
|  | ||||
|         await treeCache.getNotes(noteIds, true); // preload all at once | ||||
|  | ||||
|         const $list = $('<div>'); // not using <ul> because it's difficult to style correctly with text-overflow | ||||
|  | ||||
|         for (const editedNote of editedNotes) { | ||||
|             const $item = $('<div class="edited-note-line">'); | ||||
|  | ||||
| @@ -67,9 +71,7 @@ export default class EditedNotesWidget extends CollapsibleWidget { | ||||
|                 $item.append(editedNote.notePath ? await linkService.createNoteLink(editedNote.notePath.join("/"), {showNotePath: true}) : editedNote.title); | ||||
|             } | ||||
|  | ||||
|             $list.append($item); | ||||
|         } | ||||
|  | ||||
|         this.$editedNotes.empty().append($list); | ||||
|             this.$list.append($item); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -91,7 +91,13 @@ export default class Component { | ||||
|             console.log(`Call to ${fun.name} in ${this.componentId} took ${took}ms`); | ||||
|         } | ||||
|  | ||||
|         if (glob.isDev) { | ||||
|             await utils.timeLimit(promise, 20000, `Time limit failed on ${this.constructor.name} with ${fun.name}`); | ||||
|         } | ||||
|         else { | ||||
|             // cheaper and in non-dev the extra reporting is lost anyway through reload | ||||
|             await promise; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|   | ||||
| @@ -26,7 +26,7 @@ class MobileDetailMenuWidget extends BasicWidget { | ||||
|                 ], | ||||
|                 selectMenuItemHandler: async ({command}) => { | ||||
|                     if (command === "insertChildNote") { | ||||
|                         noteCreateService.createNote(note.noteId); | ||||
|                         noteCreateService.createNote(appContext.tabManager.getActiveTabNotePath()); | ||||
|                     } | ||||
|                     else if (command === "delete") { | ||||
|                         const notePath = appContext.tabManager.getActiveTabNotePath(); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ const WIDGET_TPL = ` | ||||
|     } | ||||
|     </style> | ||||
|  | ||||
|     <a data-trigger-command="createTopLevelNote" title="Create new top level note" class="icon-action bx bx-folder-plus"></a> | ||||
|     <a data-trigger-command="createNoteIntoInbox" title="New note" class="icon-action bx bx-folder-plus"></a> | ||||
|  | ||||
|     <a data-trigger-command="collapseTree" title="Collapse note tree" class="icon-action bx bx-layer-minus"></a> | ||||
|  | ||||
|   | ||||
| @@ -65,6 +65,8 @@ export default class NoteDetailWidget extends TabAwareWidget { | ||||
|  | ||||
|             await server.put('notes/' + noteId, dto, this.componentId); | ||||
|         }); | ||||
|  | ||||
|         appContext.addBeforeUnloadListener(this); | ||||
|     } | ||||
|  | ||||
|     isEnabled() { | ||||
| @@ -276,7 +278,7 @@ export default class NoteDetailWidget extends TabAwareWidget { | ||||
|  | ||||
|             const label = attrs.find(attr => | ||||
|                 attr.type === 'label' | ||||
|                 && ['readOnly', 'autoReadOnlyDisabled', 'cssClass', 'bookZoomLevel'].includes(attr.name) | ||||
|                 && ['readOnly', 'autoReadOnlyDisabled', 'cssClass', 'bookZoomLevel', 'displayRelations'].includes(attr.name) | ||||
|                 && attr.isAffecting(this.note)); | ||||
|  | ||||
|             const relation = attrs.find(attr => | ||||
| @@ -293,7 +295,7 @@ export default class NoteDetailWidget extends TabAwareWidget { | ||||
|     } | ||||
|  | ||||
|     beforeUnloadEvent() { | ||||
|         this.spacedUpdate.updateNowIfNecessary(); | ||||
|         return this.spacedUpdate.isAllSavedAndTriggerUpdate(); | ||||
|     } | ||||
|  | ||||
|     textPreviewDisabledEvent({tabContext}) { | ||||
| @@ -316,7 +318,7 @@ export default class NoteDetailWidget extends TabAwareWidget { | ||||
|         } | ||||
|  | ||||
|         // without await as this otherwise causes deadlock through component mutex | ||||
|         noteCreateService.createNote(note.noteId, { | ||||
|         noteCreateService.createNote(appContext.tabManager.getActiveTabNotePath(), { | ||||
|             isProtected: note.isProtected, | ||||
|             saveSelection: true | ||||
|         }); | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import TabAwareWidget from "./tab_aware_widget.js"; | ||||
| import server from "../services/server.js"; | ||||
| import attributeService from "../services/attributes.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| @@ -11,14 +10,16 @@ const TPL = ` | ||||
|         margin-right: 0; | ||||
|     } | ||||
|      | ||||
|     .note-icon-container button { | ||||
|     .note-icon-container button.note-icon { | ||||
|         font-size: 180%; | ||||
|         background: transparent; | ||||
|         border: 1px solid transparent; | ||||
|         cursor: pointer; | ||||
|         padding: 6px; | ||||
|         color: var(--main-text-color); | ||||
|     } | ||||
|      | ||||
|     .note-icon-container button:hover { | ||||
|     .note-icon-container button.note-icon:hover { | ||||
|         border: 1px solid var(--main-border-color); | ||||
|     } | ||||
|      | ||||
| @@ -47,7 +48,6 @@ const TPL = ` | ||||
|     .note-icon-container .icon-list { | ||||
|         height: 500px; | ||||
|         overflow: auto; | ||||
|         font-size: 180%; | ||||
|     } | ||||
|      | ||||
|     .note-icon-container .icon-list span { | ||||
| @@ -55,6 +55,7 @@ const TPL = ` | ||||
|         padding: 10px; | ||||
|         cursor: pointer; | ||||
|         border: 1px solid transparent; | ||||
|         font-size: 180%; | ||||
|     } | ||||
|      | ||||
|     .note-icon-container .icon-list span:hover { | ||||
| @@ -62,7 +63,7 @@ const TPL = ` | ||||
|     } | ||||
|     </style> | ||||
|      | ||||
|     <button class="btn dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Change note icon"></button> | ||||
|     <button class="btn dropdown-toggle note-icon" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Change note icon"></button> | ||||
|     <div class="dropdown-menu" aria-labelledby="note-path-list-button" style="width: 610px;"> | ||||
|         <div class="filter-row"> | ||||
|             <span>Category:</span> <select name="icon-category" class="form-control"></select> | ||||
| @@ -74,14 +75,11 @@ const TPL = ` | ||||
|     </div> | ||||
| </div>`; | ||||
|  | ||||
| let icons = []; | ||||
| let categories = []; | ||||
|  | ||||
| export default class NoteIconWidget extends TabAwareWidget { | ||||
|     doRender() { | ||||
|         this.$widget = $(TPL); | ||||
|         this.overflowing(); | ||||
|         this.$icon = this.$widget.find('button'); | ||||
|         this.$icon = this.$widget.find('button.note-icon'); | ||||
|         this.$iconList = this.$widget.find('.icon-list'); | ||||
|         this.$iconList.on('click', 'span', async e => { | ||||
|             const clazz = $(e.target).attr('class'); | ||||
| @@ -120,7 +118,7 @@ export default class NoteIconWidget extends TabAwareWidget { | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note) { | ||||
|         this.$icon.removeClass().addClass(note.getIcon()); | ||||
|         this.$icon.removeClass().addClass(note.getIcon() + " note-icon"); | ||||
|     } | ||||
|  | ||||
|     async entitiesReloadedEvent({loadResults}) { | ||||
| @@ -145,6 +143,18 @@ export default class NoteIconWidget extends TabAwareWidget { | ||||
|     async renderDropdown(categoryId, search) { | ||||
|         this.$iconList.empty(); | ||||
|  | ||||
|         if (this.getIconLabels().length > 0) { | ||||
|             this.$iconList.append( | ||||
|                 $(`<div style="text-align: center">`) | ||||
|                     .append( | ||||
|                         $('<button class="btn btn-sm">Reset to default icon</button>') | ||||
|                             .on('click', () => this.getIconLabels() | ||||
|                                 .forEach(label => attributeService.removeAttributeById(this.noteId, label.attributeId)) | ||||
|                             ) | ||||
|                     ) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         const {icons} = (await import('./icon_list.js')).default; | ||||
|  | ||||
|         for (const icon of icons) { | ||||
| @@ -164,6 +174,11 @@ export default class NoteIconWidget extends TabAwareWidget { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     getIconLabels() { | ||||
|         return this.note.getOwnedLabels() | ||||
|             .filter(label => ['workspaceIconClass', 'iconClass'].includes(label.name)); | ||||
|     } | ||||
|  | ||||
|     getIconClass(icon) { | ||||
|         if (icon.type_of_icon === 'LOGO') { | ||||
|             return "bx bxl-" + icon.name; | ||||
|   | ||||
| @@ -23,11 +23,9 @@ const TPL = ` | ||||
| export default class NoteListWidget extends TabAwareWidget { | ||||
|     isEnabled() { | ||||
|         return super.isEnabled() | ||||
|             && ['book', 'text', 'code'].includes(this.note.type) | ||||
|             && this.note.mime !== 'text/x-sqlite;schema=trilium' | ||||
|             && ( | ||||
|                 ['book', 'search', 'code'].includes(this.note.type) | ||||
|                 || (this.note.type === 'text' && this.note.hasChildren()) | ||||
|             ) | ||||
|             && this.note.hasChildren() | ||||
|             && !this.note.hasLabel('hideChildrenOverview'); | ||||
|     } | ||||
|  | ||||
| @@ -89,17 +87,6 @@ export default class NoteListWidget extends TabAwareWidget { | ||||
|         setTimeout(() => this.checkRenderStatus(), 100); | ||||
|     } | ||||
|  | ||||
|     searchRefreshedEvent({tabId}) { | ||||
|         if (!this.isTab(tabId)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.noteIdRefreshed = this.noteId; | ||||
|         this.shownNoteId = null; | ||||
|  | ||||
|         this.checkRenderStatus(); | ||||
|     } | ||||
|  | ||||
|     notesReloadedEvent({noteIds}) { | ||||
|         if (noteIds.includes(this.noteId)) { | ||||
|             this.refresh(); | ||||
|   | ||||
| @@ -15,9 +15,21 @@ const TPL = ` | ||||
|     } | ||||
|      | ||||
|     .note-path-list { | ||||
|         max-height: 600px; | ||||
|         max-height: 700px; | ||||
|         overflow-y: auto; | ||||
|     } | ||||
|      | ||||
|     .note-path-list .path-current { | ||||
|         font-weight: bold; | ||||
|     } | ||||
|      | ||||
|     .note-path-list .path-archived { | ||||
|         color: var(--muted-text-color) !important; | ||||
|     } | ||||
|      | ||||
|     .note-path-list .path-search { | ||||
|         font-style: italic; | ||||
|     } | ||||
|     </style> | ||||
|      | ||||
|     <button class="btn dropdown-toggle note-path-list-button bx bx-collection" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Note paths"></button> | ||||
| @@ -43,20 +55,12 @@ export default class NotePathsWidget extends TabAwareWidget { | ||||
|         ); | ||||
|  | ||||
|         if (this.noteId === 'root') { | ||||
|             await this.addPath('root', true); | ||||
|             await this.addPath('root'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const pathSegments = treeService.parseNotePath(this.notePath); | ||||
|         const activeNoteParentNoteId = pathSegments[pathSegments.length - 2]; // we know this is not root so there must be a parent | ||||
|  | ||||
|         for (const parentNote of this.note.getParentNotes()) { | ||||
|             const parentNotePath = treeService.getSomeNotePath(parentNote); | ||||
|             // this is to avoid having root notes leading '/' | ||||
|             const notePath = parentNotePath ? (parentNotePath + '/' + this.noteId) : this.noteId; | ||||
|             const isCurrent = activeNoteParentNoteId === parentNote.noteId; | ||||
|  | ||||
|             await this.addPath(notePath, isCurrent); | ||||
|         for (const notePathRecord of this.note.getSortedNotePaths(this.hoistedNoteId)) { | ||||
|             await this.addPath(notePathRecord); | ||||
|         } | ||||
|  | ||||
|         const cloneLink = $("<div>") | ||||
| @@ -70,7 +74,9 @@ export default class NotePathsWidget extends TabAwareWidget { | ||||
|         this.$notePathList.append(cloneLink); | ||||
|     } | ||||
|  | ||||
|     async addPath(notePath, isCurrent) { | ||||
|     async addPath(notePathRecord) { | ||||
|         const notePath = notePathRecord.notePath.join('/'); | ||||
|  | ||||
|         const title = await treeService.getNotePathTitle(notePath); | ||||
|  | ||||
|         const $noteLink = await linkService.createNoteLink(notePath, {title}); | ||||
| @@ -82,8 +88,33 @@ export default class NotePathsWidget extends TabAwareWidget { | ||||
|             .find('a') | ||||
|             .addClass("no-tooltip-preview"); | ||||
|  | ||||
|         if (isCurrent) { | ||||
|             $noteLink.addClass("current"); | ||||
|         const comments = []; | ||||
|  | ||||
|         if (this.notePath === notePath) { | ||||
|             $noteLink.addClass("path-current"); | ||||
|         } | ||||
|  | ||||
|         if (notePathRecord.isInHoistedSubTree) { | ||||
|             $noteLink.addClass("path-in-hoisted-subtree"); | ||||
|         } | ||||
|         else { | ||||
|             comments.push("outside of hoisting"); | ||||
|         } | ||||
|  | ||||
|         if (notePathRecord.isArchived) { | ||||
|             $noteLink.addClass("path-archived"); | ||||
|  | ||||
|             comments.push("archived"); | ||||
|         } | ||||
|  | ||||
|         if (notePathRecord.isSearch) { | ||||
|             $noteLink.addClass("path-search"); | ||||
|  | ||||
|             comments.push("search"); | ||||
|         } | ||||
|  | ||||
|         if (comments.length > 0) { | ||||
|             $noteLink.append(` (${comments.join(', ')})`); | ||||
|         } | ||||
|  | ||||
|         this.$notePathList.append($noteLink); | ||||
| @@ -96,4 +127,10 @@ export default class NotePathsWidget extends TabAwareWidget { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async refresh() { | ||||
|         await super.refresh(); | ||||
|  | ||||
|         this.$widget.find('.dropdown-toggle').dropdown('hide'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import utils from "../services/utils.js"; | ||||
| import protectedSessionHolder from "../services/protected_session_holder.js"; | ||||
| import server from "../services/server.js"; | ||||
| import SpacedUpdate from "../services/spaced_update.js"; | ||||
| import appContext from "../services/app_context.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="note-title-container"> | ||||
| @@ -37,6 +38,8 @@ export default class NoteTitleWidget extends TabAwareWidget { | ||||
|  | ||||
|             await server.put(`notes/${this.noteId}/change-title`, {title}); | ||||
|         }); | ||||
|  | ||||
|         appContext.addBeforeUnloadListener(this); | ||||
|     } | ||||
|  | ||||
|     doRender() { | ||||
| @@ -101,6 +104,6 @@ export default class NoteTitleWidget extends TabAwareWidget { | ||||
|     } | ||||
|  | ||||
|     beforeUnloadEvent() { | ||||
|         this.spacedUpdate.updateNowIfNecessary(); | ||||
|         return this.spacedUpdate.isAllSavedAndTriggerUpdate(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -203,8 +203,9 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|         this.$tree.on("mousedown", ".refresh-search-button", e => this.refreshSearch(e)); | ||||
|         this.$tree.on("mousedown", ".add-note-button", e => { | ||||
|             const node = $.ui.fancytree.getNode(e); | ||||
|             const parentNotePath = treeService.getNotePath(node); | ||||
|  | ||||
|             noteCreateService.createNote(node.data.noteId, { | ||||
|             noteCreateService.createNote(parentNotePath, { | ||||
|                 isProtected: node.data.isProtected | ||||
|             }); | ||||
|         }); | ||||
| @@ -392,12 +393,6 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|                 autoExpandMS: 600, | ||||
|                 preventLazyParents: false, | ||||
|                 dragStart: (node, data) => { | ||||
|                     // don't allow dragging root node | ||||
|                     if (node.data.noteId === hoistedNoteService.getHoistedNoteId() | ||||
|                         || node.getParent().data.noteType === 'search') { | ||||
|                         return false; | ||||
|                     } | ||||
|  | ||||
|                     const notes = this.getSelectedOrActiveNodes(node).map(node => ({ | ||||
|                         noteId: node.data.noteId, | ||||
|                         branchId: node.data.branchId, | ||||
| @@ -482,7 +477,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|  | ||||
|                         let childNoteIds = note.getChildNoteIds(); | ||||
|  | ||||
|                         if (childNoteIds.length > MAX_SEARCH_RESULTS_IN_TREE) { | ||||
|                         if (note.type === 'search' && childNoteIds.length > MAX_SEARCH_RESULTS_IN_TREE) { | ||||
|                             childNoteIds = childNoteIds.slice(0, MAX_SEARCH_RESULTS_IN_TREE); | ||||
|                         } | ||||
|  | ||||
| @@ -600,7 +595,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|  | ||||
|         let childBranches = parentNote.getFilteredChildBranches(); | ||||
|  | ||||
|         if (childBranches.length > MAX_SEARCH_RESULTS_IN_TREE) { | ||||
|         if (parentNote.type === 'search' && childBranches.length > MAX_SEARCH_RESULTS_IN_TREE) { | ||||
|             childBranches = childBranches.slice(0, MAX_SEARCH_RESULTS_IN_TREE); | ||||
|         } | ||||
|  | ||||
| @@ -624,6 +619,17 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|     updateNode(node) { | ||||
|         const note = treeCache.getNoteFromCache(node.data.noteId); | ||||
|         const branch = treeCache.getBranch(node.data.branchId); | ||||
|  | ||||
|         if (!note) { | ||||
|             console.log(`Node update not possible because note ${node.data.noteId} was not found.`); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!branch) { | ||||
|             console.log(`Node update not possible because branch ${node.data.branchId} was not found.`); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title; | ||||
|  | ||||
|         node.data.isProtected = note.isProtected; | ||||
| @@ -759,7 +765,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|         await this.setExpandedStatusForSubtree(node, false); | ||||
|     } | ||||
|  | ||||
|     collapseTreeCommand() { this.collapseTree(); } | ||||
|     collapseTreeEvent() { this.collapseTree(); } | ||||
|  | ||||
|     /** | ||||
|      * @return {FancytreeNode|null} | ||||
| @@ -783,7 +789,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     async scrollToActiveNoteCommand() { | ||||
|     async scrollToActiveNoteEvent() { | ||||
|         const activeContext = appContext.tabManager.getActiveTabContext(); | ||||
|  | ||||
|         if (activeContext && activeContext.notePath) { | ||||
| @@ -792,19 +798,17 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|             const node = await this.expandToNote(activeContext.notePath); | ||||
|  | ||||
|             await node.makeVisible({scrollIntoView: true}); | ||||
|             node.setFocus(true); | ||||
|             node.setActive(true, {noEvents: true, noFocus: false}); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** @return {FancytreeNode} */ | ||||
|     async getNodeFromPath(notePath, expand = false, logErrors = true) { | ||||
|         utils.assertArguments(notePath); | ||||
|         /** @let {FancytreeNode} */ | ||||
|         let parentNode = this.getNodesByNoteId('root')[0]; | ||||
|  | ||||
|         const hoistedNoteId = hoistedNoteService.getHoistedNoteId(); | ||||
|         /** @const {FancytreeNode} */ | ||||
|         let parentNode = null; | ||||
|  | ||||
|         const resolvedNotePathSegments = await treeService.resolveNotePathToSegments(notePath, logErrors); | ||||
|         let resolvedNotePathSegments = await treeService.resolveNotePathToSegments(notePath, this.hoistedNoteId, logErrors); | ||||
|  | ||||
|         if (!resolvedNotePathSegments) { | ||||
|             if (logErrors) { | ||||
| @@ -814,14 +818,9 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         resolvedNotePathSegments = resolvedNotePathSegments.slice(1); | ||||
|  | ||||
|         for (const childNoteId of resolvedNotePathSegments) { | ||||
|             if (childNoteId === hoistedNoteId) { | ||||
|                 // there must be exactly one node with given hoistedNoteId | ||||
|                 parentNode = this.getNodesByNoteId(childNoteId)[0]; | ||||
|  | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // we expand only after hoisted note since before then nodes are not actually present in the tree | ||||
|             if (parentNode) { | ||||
|                 if (!parentNode.isLoaded()) { | ||||
| @@ -852,7 +851,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|                             // these are real notes with real notePath, user can display them in a detail | ||||
|                             // but they don't have a node in the tree | ||||
|  | ||||
|                             ws.logError(`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteId}, requested path is ${notePath}`); | ||||
|                             ws.logError(`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteService.getHoistedNoteId()}, requested path is ${notePath}`); | ||||
|                         } | ||||
|  | ||||
|                         return; | ||||
| @@ -994,6 +993,9 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|         const activeNodeFocused = activeNode && activeNode.hasFocus(); | ||||
|         const nextNode = activeNode ? (activeNode.getNextSibling() || activeNode.getPrevSibling() || activeNode.getParent()) : null; | ||||
|         const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null; | ||||
|  | ||||
|         console.log(activeNotePath, activeNodeFocused); | ||||
|  | ||||
|         const nextNotePath = nextNode ? treeService.getNotePath(nextNode) : null; | ||||
|         const activeNoteId = activeNode ? activeNode.data.noteId : null; | ||||
|  | ||||
| @@ -1025,6 +1027,9 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|         } | ||||
|  | ||||
|         for (const branch of loadResults.getBranches()) { | ||||
|             // adding noteId itself to update all potential clones | ||||
|             noteIdsToUpdate.add(branch.noteId); | ||||
|  | ||||
|             for (const node of this.getNodesByBranchId(branch.branchId)) { | ||||
|                 if (branch.isDeleted) { | ||||
|                     if (node.isActive()) { | ||||
| @@ -1043,9 +1048,6 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|  | ||||
|                     noteIdsToUpdate.add(branch.parentNoteId); | ||||
|                 } | ||||
|                 else { | ||||
|                     noteIdsToUpdate.add(branch.noteId); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (!branch.isDeleted) { | ||||
| @@ -1114,22 +1116,27 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|             } | ||||
|  | ||||
|             if (node) { | ||||
|                 node.setActive(true, {noEvents: true, noFocus: true}); | ||||
|                 node.setActive(true, {noEvents: true, noFocus: !activeNodeFocused}); | ||||
|             } | ||||
|             else { | ||||
|                 // this is used when original note has been deleted and we want to move the focus to the note above/below | ||||
|                 node = await this.expandToNote(nextNotePath, false); | ||||
|  | ||||
|                 if (node) { | ||||
|                     await appContext.tabManager.getActiveTabContext().setNote(nextNotePath); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|                     // FIXME: this is conceptually wrong | ||||
|                     //        here note tree is responsible for updating global state of the application | ||||
|                     //        this should be done by tabcontext / tabmanager and note tree should only listen to | ||||
|                     //        changes in active note and just set the "active" state | ||||
|                     // We don't await since that can bring up infinite cycles when e.g. custom widget does some backend requests which wait for max sync ID processed | ||||
|                     appContext.tabManager.getActiveTabContext().setNote(nextNotePath).then(() => { | ||||
|                         const newActiveNode = this.getActiveNode(); | ||||
|  | ||||
|                         // return focus if the previously active node was also focused | ||||
|             if (newActiveNode && activeNodeFocused) { | ||||
|                 await newActiveNode.setFocus(true); | ||||
|                         if (newActiveNode && activeNodeFocused) {console.log("FOCUSING!!!"); | ||||
|                             newActiveNode.setFocus(true); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -1197,13 +1204,20 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     filterHoistedBranch() { | ||||
|     async filterHoistedBranch() { | ||||
|         if (this.tabContext) { | ||||
|             // make sure the hoisted node is loaded (can be unloaded e.g. after tree collapse in another tab) | ||||
|             const hoistedNotePath = await treeService.resolveNotePath(this.tabContext.hoistedNoteId); | ||||
|             await this.getNodeFromPath(hoistedNotePath); | ||||
|  | ||||
|             if (this.tabContext.hoistedNoteId === 'root') { | ||||
|                 this.tree.clearFilter(); | ||||
|             } | ||||
|             else { | ||||
|                 this.tree.filterBranches(node => node.data.noteId === this.tabContext.hoistedNoteId); | ||||
|                 // hack when hoisted note is cloned then it could be filtered multiple times while we want only 1 | ||||
|                 this.tree.filterBranches(node => | ||||
|                     node.data.noteId === this.tabContext.hoistedNoteId // optimization to not having always resolve the node path | ||||
|                     && treeService.getNotePath(node) === hoistedNotePath); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -1241,7 +1255,12 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|     } | ||||
|  | ||||
|     async deleteNotesCommand({node}) { | ||||
|         const branchIds = this.getSelectedOrActiveBranchIds(node); | ||||
|         const branchIds = this.getSelectedOrActiveBranchIds(node) | ||||
|             .filter(branchId => !branchId.startsWith('virt-')); // search results can't be deleted | ||||
|  | ||||
|         if (!branchIds.length) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         await branchService.deleteNotes(branchIds); | ||||
|  | ||||
| @@ -1355,7 +1374,7 @@ export default class NoteTreeWidget extends TabAwareWidget { | ||||
|     } | ||||
|  | ||||
|     sortChildNotesCommand({node}) { | ||||
|         treeService.sortAlphabetically(node.data.noteId); | ||||
|         import("../dialogs/sort_child_notes.js").then(d => d.showDialog(node.data.noteId)); | ||||
|     } | ||||
|  | ||||
|     async recentChangesInSubtreeCommand({node}) { | ||||
|   | ||||
| @@ -49,7 +49,11 @@ export default class QuickSearchWidget extends BasicWidget { | ||||
|         this.$widget.find('.input-group-append').on('shown.bs.dropdown', () => this.search()); | ||||
|  | ||||
|         utils.bindElShortcut(this.$searchString, 'return', () => { | ||||
|             if (this.$dropdownMenu.is(":visible")) { | ||||
|                 this.search(); // just update already visible dropdown | ||||
|             } else { | ||||
|                 this.$dropdownToggle.dropdown('show'); | ||||
|             } | ||||
|  | ||||
|             this.$searchString.focus(); | ||||
|         }); | ||||
| @@ -90,12 +94,18 @@ export default class QuickSearchWidget extends BasicWidget { | ||||
|             const $link = await linkService.createNoteLink(note.noteId, {showNotePath: true}); | ||||
|             $link.addClass('dropdown-item'); | ||||
|             $link.attr("tabIndex", "0"); | ||||
|             $link.on('click', () => this.$dropdownToggle.dropdown("hide")); | ||||
|             utils.bindElShortcut($link, 'return', () => { | ||||
|                 $link.find('a').trigger({ | ||||
|                     type: 'click', | ||||
|                     which: 1 // left click | ||||
|             $link.on('click', e => { | ||||
|                 this.$dropdownToggle.dropdown("hide"); | ||||
|  | ||||
|                 if (!e.target || e.target.nodeName !== 'A') { | ||||
|                     // click on the link is handled by link handling but we want the whole item clickable | ||||
|                     appContext.tabManager.getActiveTabContext().setNote(note.noteId); | ||||
|                 } | ||||
|             }); | ||||
|             utils.bindElShortcut($link, 'return', () => { | ||||
|                 this.$dropdownToggle.dropdown("hide"); | ||||
|  | ||||
|                 appContext.tabManager.getActiveTabContext().setNote(note.noteId); | ||||
|             }); | ||||
|  | ||||
|             this.$dropdownMenu.append($link); | ||||
| @@ -110,17 +120,21 @@ export default class QuickSearchWidget extends BasicWidget { | ||||
|  | ||||
|         this.$dropdownMenu.append($showInFullButton); | ||||
|  | ||||
|         utils.bindElShortcut($showInFullButton, 'return', async () => { | ||||
|             const searchNote = await dateNotesService.createSearchNote({searchString: this.$searchString.val()}); | ||||
|         $showInFullButton.on('click', () => this.showInFullSearch()); | ||||
|  | ||||
|             await appContext.tabManager.getActiveTabContext().setNote(searchNote.noteId); | ||||
|         }); | ||||
|         utils.bindElShortcut($showInFullButton, 'return', () => this.showInFullSearch()); | ||||
|  | ||||
|         utils.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus()); | ||||
|  | ||||
|         this.$dropdownToggle.dropdown('update'); | ||||
|     } | ||||
|  | ||||
|     async showInFullSearch() { | ||||
|         const searchNote = await dateNotesService.createSearchNote({searchString: this.$searchString.val()}); | ||||
|  | ||||
|         await appContext.tabManager.getActiveTabContext().setNote(searchNote.noteId); | ||||
|     } | ||||
|  | ||||
|     quickSearchEvent() { | ||||
|         this.$searchString.focus(); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										35
									
								
								src/public/app/widgets/search_options/debug.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/public/app/widgets/search_options/debug.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| import AbstractSearchOption from "./abstract_search_option.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <tr data-search-option-conf="debug"> | ||||
|     <td colSpan="2"> | ||||
|         <span class="bx bx-bug"></span> | ||||
|  | ||||
|         Debug | ||||
|     </td> | ||||
|     <td class="button-column"> | ||||
|         <div class="dropdown help-dropdown"> | ||||
|             <span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> | ||||
|             <div class="dropdown-menu dropdown-menu-right p-4"> | ||||
|                 <p>Debug will print extra debugging information into the console to aid in debugging complex queries.</p> | ||||
|                  | ||||
|                 <p>To access the debug information, execute query and click on "Show backend log" in top left corner.</p>  | ||||
|             </div> | ||||
|         </div> | ||||
|      | ||||
|         <span class="bx bx-x icon-action search-option-del"></span> | ||||
|     </td> | ||||
| </tr>`; | ||||
|  | ||||
| export default class Debug extends AbstractSearchOption { | ||||
|     static get optionName() { return "debug" }; | ||||
|     static get attributeType() { return "label" }; | ||||
|  | ||||
|     static async create(noteId) { | ||||
|         await AbstractSearchOption.setAttribute(noteId,'label', 'debug'); | ||||
|     } | ||||
|  | ||||
|     doRender() { | ||||
|         return $(TPL); | ||||
|     } | ||||
| } | ||||
| @@ -16,6 +16,11 @@ const TPL = ` | ||||
|             <option value="contentSize">Note content size</option> | ||||
|             <option value="noteSize">Note content size including revisions</option> | ||||
|             <option value="revisionCount">Number of revisions</option> | ||||
|             <option value="childrenCount">Number of children notes</option> | ||||
|             <option value="parentCount">Number of clones</option> | ||||
|             <option value="ownedLabelCount">Number of labels</option> | ||||
|             <option value="ownedRelationCount">Number of relations</option> | ||||
|             <option value="targetRelationCount">Number of relations targeting the note</option> | ||||
|         </select> | ||||
|          | ||||
|         <select name="orderDirection" class="form-control w-auto d-inline"> | ||||
|   | ||||
| @@ -50,7 +50,7 @@ export default class SearchScript extends AbstractSearchOption { | ||||
|     doRender() { | ||||
|         const $option = $(TPL); | ||||
|         const $searchScript = $option.find('.search-script'); | ||||
|         noteAutocompleteService.initNoteAutocomplete($searchScript); | ||||
|         noteAutocompleteService.initNoteAutocomplete($searchScript, {allowCreatingNotes: true}); | ||||
|  | ||||
|         $searchScript.on('autocomplete:closed', async () => { | ||||
|             const searchScriptNoteId = $searchScript.getSelectedNoteId(); | ||||
|   | ||||
							
								
								
									
										72
									
								
								src/public/app/widgets/search_result.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/public/app/widgets/search_result.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| import TabAwareWidget from "./tab_aware_widget.js"; | ||||
| import NoteListRenderer from "../services/note_list_renderer.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="search-result-widget"> | ||||
|     <style> | ||||
|     .search-result-widget { | ||||
|         flex-grow: 100000; | ||||
|         flex-shrink: 100000; | ||||
|         min-height: 0; | ||||
|         overflow: auto; | ||||
|     } | ||||
|      | ||||
|     .search-result-widget .note-list { | ||||
|         padding: 10px; | ||||
|     } | ||||
|      | ||||
|     .search-no-results, .search-not-executed-yet { | ||||
|         margin: 20px; | ||||
|         padding: 20px; | ||||
|     } | ||||
|     </style> | ||||
|      | ||||
|     <div class="search-no-results alert alert-info"> | ||||
|         No notes have been found for given search parameters. | ||||
|     </div> | ||||
|      | ||||
|     <div class="search-not-executed-yet alert alert-info"> | ||||
|         Search has not been executed yet. Click on "Search" button above to see the results. | ||||
|     </div> | ||||
|      | ||||
|     <div class="search-result-widget-content"> | ||||
|     </div> | ||||
| </div>`; | ||||
|  | ||||
| export default class SearchResultWidget extends TabAwareWidget { | ||||
|     isEnabled() { | ||||
|         return super.isEnabled() | ||||
|             && this.note.type === 'search'; | ||||
|     } | ||||
|  | ||||
|     doRender() { | ||||
|         this.$widget = $(TPL); | ||||
|         this.$content = this.$widget.find('.search-result-widget-content'); | ||||
|         this.$noResults = this.$widget.find('.search-no-results'); | ||||
|         this.$notExecutedYet = this.$widget.find('.search-not-executed-yet'); | ||||
|         this.contentSized(); | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note) { | ||||
|         this.$content.empty(); | ||||
|         this.$noResults.toggle(note.getChildNoteIds().length === 0 && !!note.searchResultsLoaded); | ||||
|         this.$notExecutedYet.toggle(!note.searchResultsLoaded); | ||||
|  | ||||
|         const noteListRenderer = new NoteListRenderer(this.$content, note, note.getChildNoteIds(), true); | ||||
|         await noteListRenderer.renderList(); | ||||
|     } | ||||
|  | ||||
|     searchRefreshedEvent({tabId}) { | ||||
|         if (!this.isTab(tabId)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.refresh(); | ||||
|     } | ||||
|  | ||||
|     notesReloadedEvent({noteIds}) { | ||||
|         if (noteIds.includes(this.noteId)) { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -22,6 +22,10 @@ export default class TabAwareWidget extends BasicWidget { | ||||
|         return this.tabContext && this.tabContext.notePath; | ||||
|     } | ||||
|  | ||||
|     get hoistedNoteId() { | ||||
|         return this.tabContext && this.tabContext.hoistedNoteId; | ||||
|     } | ||||
|  | ||||
|     isEnabled() { | ||||
|         return !!this.note; | ||||
|     } | ||||
|   | ||||
| @@ -83,4 +83,10 @@ export default class InheritedAttributesWidget extends TabAwareWidget { | ||||
|     getInheritedAttributes(note) { | ||||
|         return note.getAttributes().filter(attr => attr.noteId !== this.noteId); | ||||
|     } | ||||
|  | ||||
|     entitiesReloadedEvent({loadResults}) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -210,7 +210,7 @@ export default class PromotedAttributesWidget extends TabAwareWidget { | ||||
|             } | ||||
|  | ||||
|             // no need to wait for this | ||||
|             noteAutocompleteService.initNoteAutocomplete($input); | ||||
|             noteAutocompleteService.initNoteAutocomplete($input, {allowCreatingNotes: true}); | ||||
|  | ||||
|             $input.on('autocomplete:noteselected', (event, suggestion, dataset) => { | ||||
|                 this.promotedAttributeChanged(event); | ||||
| @@ -293,6 +293,7 @@ export default class PromotedAttributesWidget extends TabAwareWidget { | ||||
|             this.refresh(); | ||||
|  | ||||
|             this.renderTitle(this.note); | ||||
|             this.triggerCommand('refreshSectionContainer'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -20,6 +20,7 @@ import OrderBy from "../search_options/order_by.js"; | ||||
| import SearchScript from "../search_options/search_script.js"; | ||||
| import Limit from "../search_options/limit.js"; | ||||
| import DeleteNoteRevisionsSearchAction from "../search_actions/delete_note_revisions.js"; | ||||
| import Debug from "../search_options/debug.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="search-definition-widget"> | ||||
| @@ -113,6 +114,11 @@ const TPL = ` | ||||
|                         limit | ||||
|                     </button> | ||||
|                      | ||||
|                     <button type="button" class="btn btn-sm" data-search-option-add="debug" title="Debug will print extra debugging information into the console to aid in debugging complex queries"> | ||||
|                         <span class="bx bx-bug"></span> | ||||
|                         debug | ||||
|                     </button> | ||||
|                      | ||||
|                     <div class="dropdown" style="display: inline-block;"> | ||||
|                       <button class="btn btn-sm dropdown-toggle action-add-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | ||||
|                         <span class="bx bxs-zap"></span> | ||||
| @@ -173,7 +179,8 @@ const OPTION_CLASSES = [ | ||||
|     FastSearch, | ||||
|     IncludeArchivedNotes, | ||||
|     OrderBy, | ||||
|     Limit | ||||
|     Limit, | ||||
|     Debug | ||||
| ]; | ||||
|  | ||||
| const ACTION_CLASSES = {}; | ||||
|   | ||||
| @@ -274,7 +274,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||
|     } | ||||
|  | ||||
|     async createNoteForReferenceLink(title) { | ||||
|         const {note} = await noteCreateService.createNote(this.noteId, { | ||||
|         const {note} = await noteCreateService.createNote(this.notePath, { | ||||
|             activate: false, | ||||
|             title: title | ||||
|         }); | ||||
|   | ||||
| @@ -22,7 +22,10 @@ export default class EmptyTypeWidget extends TypeWidget { | ||||
|         this.contentSized(); | ||||
|         this.$autoComplete = this.$widget.find(".note-autocomplete"); | ||||
|  | ||||
|         noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, { hideGoToSelectedNoteButton: true }) | ||||
|         noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, { | ||||
|             hideGoToSelectedNoteButton: true, | ||||
|             allowCreatingNotes: true | ||||
|         }) | ||||
|             .on('autocomplete:noteselected', function(event, suggestion, dataset) { | ||||
|                 if (!suggestion.notePath) { | ||||
|                     return false; | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import attributeAutocompleteService from "../../services/attribute_autocomplete. | ||||
| import TypeWidget from "./type_widget.js"; | ||||
| import appContext from "../../services/app_context.js"; | ||||
| import utils from "../../services/utils.js"; | ||||
| import treeCache from "../../services/tree_cache.js"; | ||||
|  | ||||
| const uniDirectionalOverlays = [ | ||||
|     [ "Arrow", { | ||||
| @@ -285,7 +286,7 @@ export default class RelationMapTypeWidget extends TypeWidget { | ||||
|  | ||||
|     async loadNotesAndRelations() { | ||||
|         const noteIds = this.mapData.notes.map(note => note.noteId); | ||||
|         const data = await server.post("notes/relation-map", {noteIds}); | ||||
|         const data = await server.post("notes/relation-map", {noteIds, relationMapNoteId: this.noteId}); | ||||
|  | ||||
|         this.relations = []; | ||||
|  | ||||
| @@ -471,14 +472,22 @@ export default class RelationMapTypeWidget extends TypeWidget { | ||||
|         } | ||||
|  | ||||
|         const promptDialog = await import("../../dialogs/prompt.js"); | ||||
|         const name = await promptDialog.ask({ | ||||
|             message: "Specify new relation name:", | ||||
|             shown: ({ $answer }) => | ||||
|         let name = await promptDialog.ask({ | ||||
|             message: "Specify new relation name (allowed characters: alphanumeric, colon and underscore):", | ||||
|             shown: ({ $answer }) => { | ||||
|                 $answer.on('keyup', () => { | ||||
|                     // invalid characters are simply ignored (from user perspective they are not even entered) | ||||
|                     const attrName = utils.filterAttributeName($answer.val()); | ||||
|  | ||||
|                     $answer.val(attrName); | ||||
|                 }); | ||||
|  | ||||
|                 attributeAutocompleteService.initAttributeNameAutocomplete({ | ||||
|                     $el: $answer, | ||||
|                     attributeType: "relation", | ||||
|                     open: true | ||||
|                 }) | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         if (!name || !name.trim()) { | ||||
| @@ -487,6 +496,8 @@ export default class RelationMapTypeWidget extends TypeWidget { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         name = utils.filterAttributeName(name); | ||||
|  | ||||
|         const targetNoteId = this.idToNoteId(connection.target.id); | ||||
|         const sourceNoteId = this.idToNoteId(connection.source.id); | ||||
|  | ||||
| @@ -521,8 +532,11 @@ export default class RelationMapTypeWidget extends TypeWidget { | ||||
|             linkService.goToLink(e); | ||||
|         }); | ||||
|  | ||||
|         const note = await treeCache.getNote(noteId); | ||||
|  | ||||
|         const $noteBox = $("<div>") | ||||
|             .addClass("note-box") | ||||
|             .addClass(note.getCssClass()) | ||||
|             .prop("id", this.noteIdToId(noteId)) | ||||
|             .append($("<span>").addClass("title").append($link)) | ||||
|             .append($("<div>").addClass("endpoint").attr("title", "Start dragging relations from here and drop them on another note.")) | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| .note-detail-relation-map { | ||||
|     height: 100%; | ||||
|     overflow: hidden !important; | ||||
|     padding-top: 10px; | ||||
|     padding: 10px; | ||||
|     position: relative; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -54,9 +54,17 @@ function moveBranchBeforeNote(req) { | ||||
|     const {branchId, beforeBranchId} = req.params; | ||||
|  | ||||
|     const branchToMove = repository.getBranch(branchId); | ||||
|     const beforeNote = repository.getBranch(beforeBranchId); | ||||
|     const beforeBranch = repository.getBranch(beforeBranchId); | ||||
|  | ||||
|     const validationResult = treeService.validateParentChild(beforeNote.parentNoteId, branchToMove.noteId, branchId); | ||||
|     if (!branchToMove) { | ||||
|         return [404, `Can't find branch ${branchId}`]; | ||||
|     } | ||||
|  | ||||
|     if (!beforeBranch) { | ||||
|         return [404, `Can't find branch ${beforeBranchId}`]; | ||||
|     } | ||||
|  | ||||
|     const validationResult = treeService.validateParentChild(beforeBranch.parentNoteId, branchToMove.noteId, branchId); | ||||
|  | ||||
|     if (!validationResult.success) { | ||||
|         return [200, validationResult]; | ||||
| @@ -65,16 +73,16 @@ function moveBranchBeforeNote(req) { | ||||
|     // we don't change utcDateModified so other changes are prioritized in case of conflict | ||||
|     // also we would have to sync all those modified branches otherwise hash checks would fail | ||||
|     sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0", | ||||
|         [beforeNote.parentNoteId, beforeNote.notePosition]); | ||||
|         [beforeBranch.parentNoteId, beforeBranch.notePosition]); | ||||
|  | ||||
|     entityChangesService.addNoteReorderingEntityChange(beforeNote.parentNoteId); | ||||
|     entityChangesService.addNoteReorderingEntityChange(beforeBranch.parentNoteId); | ||||
|  | ||||
|     if (branchToMove.parentNoteId === beforeNote.parentNoteId) { | ||||
|         branchToMove.notePosition = beforeNote.notePosition; | ||||
|     if (branchToMove.parentNoteId === beforeBranch.parentNoteId) { | ||||
|         branchToMove.notePosition = beforeBranch.notePosition; | ||||
|         branchToMove.save(); | ||||
|     } | ||||
|     else { | ||||
|         const newBranch = branchToMove.createClone(beforeNote.parentNoteId, beforeNote.notePosition); | ||||
|         const newBranch = branchToMove.createClone(beforeBranch.parentNoteId, beforeBranch.notePosition); | ||||
|         newBranch.save(); | ||||
|  | ||||
|         branchToMove.isDeleted = true; | ||||
|   | ||||
| @@ -5,6 +5,8 @@ const sql = require('../../services/sql'); | ||||
| const dateUtils = require('../../services/date_utils'); | ||||
| const noteService = require('../../services/notes'); | ||||
| const attributeService = require('../../services/attributes'); | ||||
| const cls = require('../../services/cls'); | ||||
| const repository = require('../../services/repository'); | ||||
|  | ||||
| function getInboxNote(req) { | ||||
|     return attributeService.getNoteWithLabel('inbox') | ||||
| @@ -59,21 +61,54 @@ function createSqlConsole() { | ||||
|     return note; | ||||
| } | ||||
|  | ||||
| function createSearchNote() { | ||||
| function createSearchNote(req) { | ||||
|     const params = req.body; | ||||
|     const searchString = params.searchString || ""; | ||||
|     let ancestorNoteId = params.ancestorNoteId; | ||||
|  | ||||
|     const hoistedNote = cls.getHoistedNoteId() && cls.getHoistedNoteId() !== 'root' | ||||
|         ? repository.getNote(cls.getHoistedNoteId()) | ||||
|         : null; | ||||
|  | ||||
|     let searchHome; | ||||
|  | ||||
|     if (hoistedNote) { | ||||
|         ([searchHome] = hoistedNote.getDescendantNotesWithLabel('hoistedSearchHome')); | ||||
|     } | ||||
|  | ||||
|     if (!searchHome) { | ||||
|         const today = dateUtils.localNowDate(); | ||||
|  | ||||
|     const searchHome = | ||||
|         attributeService.getNoteWithLabel('searchHome') | ||||
|         searchHome = attributeService.getNoteWithLabel('searchHome') | ||||
|                   || dateNoteService.getDateNote(today); | ||||
|     } | ||||
|  | ||||
|     if (hoistedNote) { | ||||
|  | ||||
|         if (!hoistedNote.getDescendantNoteIds().includes(searchHome.noteId)) { | ||||
|             // otherwise the note would be saved outside of the hoisted context which is weird | ||||
|             searchHome = hoistedNote; | ||||
|         } | ||||
|  | ||||
|         if (!ancestorNoteId) { | ||||
|             ancestorNoteId = hoistedNote.noteId; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const {note} = noteService.createNewNote({ | ||||
|         parentNoteId: searchHome.noteId, | ||||
|         title: 'Search: ', | ||||
|         title: 'Search: ' + searchString, | ||||
|         content: "", | ||||
|         type: 'search', | ||||
|         mime: 'application/json' | ||||
|     }); | ||||
|  | ||||
|     note.setLabel('searchString', searchString); | ||||
|  | ||||
|     if (ancestorNoteId) { | ||||
|         note.setRelation('ancestor', ancestorNoteId); | ||||
|     } | ||||
|  | ||||
|     return note; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -42,6 +42,9 @@ async function importToBranch(req) { | ||||
|     // and may produce unintended consequences | ||||
|     cls.disableEntityEvents(); | ||||
|  | ||||
|     // eliminate flickering during import | ||||
|     cls.ignoreEntityChanges(); | ||||
|  | ||||
|     let note; // typically root of the import - client can show it after finishing the import | ||||
|  | ||||
|     const taskContext = TaskContext.getInstance(taskId, 'import', options); | ||||
|   | ||||
| @@ -4,6 +4,7 @@ const noteService = require('../../services/notes'); | ||||
| const treeService = require('../../services/tree'); | ||||
| const repository = require('../../services/repository'); | ||||
| const utils = require('../../services/utils'); | ||||
| const log = require('../../services/log'); | ||||
| const TaskContext = require('../../services/task_context'); | ||||
|  | ||||
| function getNote(req) { | ||||
| @@ -85,10 +86,20 @@ function undeleteNote(req) { | ||||
|     taskContext.taskSucceeded(); | ||||
| } | ||||
|  | ||||
| function sortNotes(req) { | ||||
| function sortChildNotes(req) { | ||||
|     const noteId = req.params.noteId; | ||||
|     const {sortBy, sortDirection} = req.body; | ||||
|  | ||||
|     treeService.sortNotesAlphabetically(noteId); | ||||
|     log.info(`Sorting ${noteId} children with ${sortBy} ${sortDirection}`); | ||||
|  | ||||
|     const reverse = sortDirection === 'desc'; | ||||
|  | ||||
|     if (sortBy === 'title') { | ||||
|         treeService.sortNotesByTitle(noteId, false, reverse); | ||||
|     } | ||||
|     else { | ||||
|         treeService.sortNotes(noteId, sortBy, reverse); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function protectNote(req) { | ||||
| @@ -117,7 +128,8 @@ function setNoteTypeMime(req) { | ||||
| } | ||||
|  | ||||
| function getRelationMap(req) { | ||||
|     const noteIds = req.body.noteIds; | ||||
|     const {relationMapNoteId, noteIds} = req.body; | ||||
|  | ||||
|     const resp = { | ||||
|         // noteId => title | ||||
|         noteTitles: {}, | ||||
| @@ -134,12 +146,23 @@ function getRelationMap(req) { | ||||
|  | ||||
|     const questionMarks = noteIds.map(noteId => '?').join(','); | ||||
|  | ||||
|     const relationMapNote = repository.getNote(relationMapNoteId); | ||||
|  | ||||
|     const displayRelationsVal = relationMapNote.getLabelValue('displayRelations'); | ||||
|     const displayRelations = !displayRelationsVal ? [] : displayRelationsVal | ||||
|         .split(",") | ||||
|         .map(token => token.trim()); | ||||
|  | ||||
|     console.log("displayRelations", displayRelations); | ||||
|  | ||||
|     const notes = repository.getEntities(`SELECT * FROM notes WHERE isDeleted = 0 AND noteId IN (${questionMarks})`, noteIds); | ||||
|  | ||||
|     for (const note of notes) { | ||||
|         resp.noteTitles[note.noteId] = note.title; | ||||
|  | ||||
|         resp.relations = resp.relations.concat(note.getRelations() | ||||
|             .filter(relation => !relation.isAutoLink() || displayRelations.includes(relation.name)) | ||||
|             .filter(relation => displayRelations.length === 0 || displayRelations.includes(relation.name)) | ||||
|             .filter(relation => noteIds.includes(relation.value)) | ||||
|             .map(relation => ({ | ||||
|                 attributeId: relation.attributeId, | ||||
| @@ -203,7 +226,7 @@ module.exports = { | ||||
|     deleteNote, | ||||
|     undeleteNote, | ||||
|     createNote, | ||||
|     sortNotes, | ||||
|     sortChildNotes, | ||||
|     protectNote, | ||||
|     setNoteTypeMime, | ||||
|     getRelationMap, | ||||
|   | ||||
| @@ -24,6 +24,7 @@ async function search(note) { | ||||
|             orderBy: note.getLabelValue('orderBy'), | ||||
|             orderDirection: note.getLabelValue('orderDirection'), | ||||
|             limit: note.getLabelValue('limit'), | ||||
|             debug: note.hasLabel('debug'), | ||||
|             fuzzyAttributeSearch: false | ||||
|         }); | ||||
|  | ||||
| @@ -232,7 +233,9 @@ function getRelatedNotes(req) { | ||||
|  | ||||
|     const results = []; | ||||
|  | ||||
|     for (const record of matchingNameAndValue.concat(matchingName)) { | ||||
|     const allResults = matchingNameAndValue.concat(matchingName); | ||||
|  | ||||
|     for (const record of allResults) { | ||||
|         if (results.length >= 20) { | ||||
|             break; | ||||
|         } | ||||
| @@ -245,7 +248,7 @@ function getRelatedNotes(req) { | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         count: matchingName.length, | ||||
|         count: allResults.length, | ||||
|         results | ||||
|     }; | ||||
| } | ||||
| @@ -266,6 +269,10 @@ function formatAttrForSearch(attr, searchWithValue) { | ||||
|     searchStr += attr.name; | ||||
|  | ||||
|     if (searchWithValue && attr.value) { | ||||
|         if (attr.type === 'relation') { | ||||
|             searchStr += ".noteId"; | ||||
|         } | ||||
|  | ||||
|         searchStr += '='; | ||||
|         searchStr += formatValue(attr.value); | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const noteCache = require('../../services/note_cache/note_cache'); | ||||
| const log = require('../../services/log'); | ||||
|  | ||||
| function getNotesAndBranchesAndAttributes(noteIds) { | ||||
|     noteIds = new Set(noteIds); | ||||
| @@ -76,6 +77,11 @@ function getNotesAndBranchesAndAttributes(noteIds) { | ||||
|     for (const branchId of collectedBranchIds) { | ||||
|         const branch = noteCache.branches[branchId]; | ||||
|  | ||||
|         if (!branch) { | ||||
|             log.error(`Could not find branch for branchId=${branchId}`); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         branches.push({ | ||||
|             branchId: branch.branchId, | ||||
|             noteId: branch.noteId, | ||||
| @@ -129,6 +135,10 @@ function getTree(req) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!(subTreeNoteId in noteCache.notes)) { | ||||
|         return [404, `Note ${subTreeNoteId} not found in the cache`]; | ||||
|     } | ||||
|  | ||||
|     collect(noteCache.notes[subTreeNoteId]); | ||||
|  | ||||
|     return getNotesAndBranchesAndAttributes(collectedNoteIds); | ||||
|   | ||||
| @@ -150,7 +150,7 @@ function register(app) { | ||||
|     apiRoute(DELETE, '/api/notes/:noteId', notesApiRoute.deleteNote); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/undelete', notesApiRoute.undeleteNote); | ||||
|     apiRoute(POST, '/api/notes/:parentNoteId/children', notesApiRoute.createNote); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/sort', notesApiRoute.sortNotes); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/sort-children', notesApiRoute.sortChildNotes); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectNote); | ||||
|     apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime); | ||||
|     apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions); | ||||
|   | ||||
| @@ -4,7 +4,7 @@ const build = require('./build'); | ||||
| const packageJson = require('../../package'); | ||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||
|  | ||||
| const APP_DB_VERSION = 182; | ||||
| const APP_DB_VERSION = 183; | ||||
| const SYNC_VERSION = 20; | ||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||
|  | ||||
|   | ||||
| @@ -38,6 +38,7 @@ const BUILTIN_ATTRIBUTES = [ | ||||
|     { type: 'label', name: 'workspaceIconClass' }, | ||||
|     { type: 'label', name: 'workspaceTabBackgroundColor' }, | ||||
|     { type: 'label', name: 'searchHome' }, | ||||
|     { type: 'label', name: 'hoistedSearchHome' }, | ||||
|     { type: 'label', name: 'sqlConsoleHome' }, | ||||
|     { type: 'label', name: 'datePattern' }, | ||||
|  | ||||
|   | ||||
| @@ -359,7 +359,7 @@ function BackendScriptApi(currentNote, apiParams) { | ||||
|      * @method | ||||
|      * @param {string} parentNoteId - this note's child notes will be sorted | ||||
|      */ | ||||
|     this.sortNotesAlphabetically = treeService.sortNotesAlphabetically; | ||||
|     this.sortNotesByTitle = treeService.sortNotesByTitle; | ||||
|  | ||||
|     /** | ||||
|      * This method finds note by its noteId and prefix and either sets it to the given parentNoteId | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| module.exports = { buildDate:"2021-02-15T22:29:35+01:00", buildRevision: "c0edcc1bfe621eff7fbc976172fd0897bc065f6c" }; | ||||
| module.exports = { buildDate:"2021-03-08T23:11:11+01:00", buildRevision: "f27370d44f08afaa22d4cd86cba489584f9c878b" }; | ||||
|   | ||||
| @@ -53,6 +53,10 @@ function getAndClearEntityChanges() { | ||||
| } | ||||
|  | ||||
| function addEntityChange(entityChange) { | ||||
|     if (namespace.get('ignoreEntityChanges')) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     const entityChanges = namespace.get('entityChanges') || []; | ||||
|  | ||||
|     entityChanges.push(entityChange); | ||||
| @@ -69,7 +73,11 @@ function getEntityFromCache(entityName, entityId) { | ||||
| } | ||||
|  | ||||
| function setEntityToCache(entityName, entityId, entity) { | ||||
|     return namespace.set(entityName + '-' + entityId, entity); | ||||
|     namespace.set(entityName + '-' + entityId, entity); | ||||
| } | ||||
|  | ||||
| function ignoreEntityChanges() { | ||||
|     namespace.set('ignoreEntityChanges', true); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
| @@ -87,5 +95,6 @@ module.exports = { | ||||
|     getAndClearEntityChanges, | ||||
|     addEntityChange, | ||||
|     getEntityFromCache, | ||||
|     setEntityToCache | ||||
|     setEntityToCache, | ||||
|     ignoreEntityChanges | ||||
| }; | ||||
|   | ||||
| @@ -152,12 +152,11 @@ function getDateNoteTitle(rootNote, dayNumber, dateObj) { | ||||
| function getDateNote(dateStr) { | ||||
|     const rootNote = getRootCalendarNote(); | ||||
|  | ||||
|     const dayNumber = dateStr.substr(8, 2); | ||||
|  | ||||
|     let dateNote = attributeService.getNoteWithLabel(DATE_LABEL, dateStr); | ||||
|  | ||||
|     if (!dateNote) { | ||||
|         const monthNote = getMonthNote(dateStr, rootNote); | ||||
|         const dayNumber = dateStr.substr(8, 2); | ||||
|  | ||||
|         dateNote = getNoteStartingWith(monthNote.noteId, dayNumber); | ||||
|  | ||||
|   | ||||
| @@ -30,6 +30,23 @@ function addEntityChange(entityChange, sourceId, isSynced) { | ||||
|     cls.addEntityChange(localEntityChange); | ||||
| } | ||||
|  | ||||
| function addNoteReorderingEntityChange(parentNoteId, sourceId) { | ||||
|     addEntityChange({ | ||||
|         entityName: "note_reordering", | ||||
|         entityId: parentNoteId, | ||||
|         hash: 'N/A', | ||||
|         isErased: false, | ||||
|         utcDateChanged: dateUtils.utcNowDateTime() | ||||
|     }, sourceId); | ||||
|  | ||||
|     const eventService = require('./events'); | ||||
|  | ||||
|     eventService.emit(eventService.ENTITY_CHANGED, { | ||||
|         entityName: 'note_reordering', | ||||
|         entity: sql.getMap(`SELECT branchId, notePosition FROM branches WHERE isDeleted = 0 AND parentNoteId = ?`, [parentNoteId]) | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function moveEntityChangeToTop(entityName, entityId) { | ||||
|     const [hash, isSynced] = sql.getRow(`SELECT * FROM entity_changes WHERE entityName = ? AND entityId = ?`, [entityName, entityId]); | ||||
|  | ||||
| @@ -121,13 +138,7 @@ function fillAllEntityChanges() { | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     addNoteReorderingEntityChange: (parentNoteId, sourceId) => addEntityChange({ | ||||
|         entityName: "note_reordering", | ||||
|         entityId: parentNoteId, | ||||
|         hash: 'N/A', | ||||
|         isErased: false, | ||||
|         utcDateChanged: dateUtils.utcNowDateTime() | ||||
|     }, sourceId), | ||||
|     addNoteReorderingEntityChange, | ||||
|     moveEntityChangeToTop, | ||||
|     addEntityChange, | ||||
|     fillAllEntityChanges, | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const TurndownService = require('turndown'); | ||||
| const turndownPluginGfm = require('turndown-plugin-gfm'); | ||||
| const turndownPluginGfm = require('joplin-turndown-plugin-gfm'); | ||||
|  | ||||
| let instance = null; | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,7 @@ eventService.subscribe(eventService.NOTE_TITLE_CHANGED, note => { | ||||
|  | ||||
|         for (const parentNote of noteFromCache.parents) { | ||||
|             if (parentNote.hasLabel("sorted")) { | ||||
|                 treeService.sortNotesAlphabetically(parentNote.noteId); | ||||
|                 treeService.sortNotesByTitle(parentNote.noteId); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -53,23 +53,19 @@ eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => | ||||
|         if (entity.type === 'relation' && entity.name === 'template') { | ||||
|             const note = repository.getNote(entity.noteId); | ||||
|  | ||||
|             if (!note.isStringNote()) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const content = note.getContent(); | ||||
|  | ||||
|             if (content && content.trim().length > 0) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const templateNote = repository.getNote(entity.value); | ||||
|  | ||||
|             if (!templateNote) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (templateNote.isStringNote()) { | ||||
|             const content = note.getContent(); | ||||
|  | ||||
|             if (!["text", "code"].includes(note.type) | ||||
|                 // if the note has already content we're not going to overwrite it with template's one | ||||
|                 && (!content || content.trim().length === 0) | ||||
|                 && templateNote.isStringNote()) { | ||||
|  | ||||
|                 const templateNoteContent = templateNote.getContent(); | ||||
|  | ||||
|                 if (templateNoteContent) { | ||||
| @@ -81,17 +77,21 @@ eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => | ||||
|                 note.save(); | ||||
|             } | ||||
|  | ||||
|             // we'll copy the children notes only if there's none so far | ||||
|             // this protects against e.g. multiple assignment of template relation resulting in having multiple copies of the subtree | ||||
|             if (note.getChildNotes().length === 0 && !note.isDescendantOfNote(templateNote.noteId)) { | ||||
|                 noteService.duplicateSubtreeWithoutRoot(templateNote.noteId, note.noteId); | ||||
|             } | ||||
|         } | ||||
|         else if (entity.type === 'label' && entity.name === 'sorted') { | ||||
|             treeService.sortNotesAlphabetically(entity.noteId); | ||||
|             treeService.sortNotesByTitle(entity.noteId); | ||||
|  | ||||
|             if (entity.isInheritable) { | ||||
|                 const note = noteCache.notes[entity.noteId]; | ||||
|  | ||||
|                 if (note) { | ||||
|                     for (const noteId of note.subtreeNoteIds) { | ||||
|                         treeService.sortNotesAlphabetically(noteId); | ||||
|                         treeService.sortNotesByTitle(noteId); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -148,19 +148,15 @@ eventService.subscribe(eventService.ENTITY_DELETED, ({ entityName, entity }) => | ||||
|     processInverseRelations(entityName, entity, (definition, note, targetNote) => { | ||||
|         // if one inverse attribute is deleted then the other should be deleted as well | ||||
|         const relations = targetNote.getOwnedRelations(definition.inverseRelation); | ||||
|         let deletedSomething = false; | ||||
|  | ||||
|         for (const relation of relations) { | ||||
|             if (relation.value === note.noteId) { | ||||
|                 note.invalidateAttributeCache(); | ||||
|                 targetNote.invalidateAttributeCache(); | ||||
|  | ||||
|                 relation.isDeleted = true; | ||||
|                 relation.save(); | ||||
|  | ||||
|                 deletedSomething = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (deletedSomething) { | ||||
|             targetNote.invalidateAttributeCache(); | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -355,7 +355,9 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|                 mime, | ||||
|                 prefix: noteMeta ? noteMeta.prefix : '', | ||||
|                 isExpanded: noteMeta ? noteMeta.isExpanded : false, | ||||
|                 notePosition: noteMeta ? noteMeta.notePosition : false, | ||||
|                 // root notePosition should be ignored since it relates to original document | ||||
|                 // now import root should be placed after existing notes into new parent | ||||
|                 notePosition: (noteMeta && firstNote) ? noteMeta.notePosition : undefined, | ||||
|                 isProtected: importRootNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), | ||||
|             })); | ||||
|  | ||||
| @@ -461,7 +463,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|         if (!metaFile) { | ||||
|             // if there's no meta file then the notes are created based on the order in that tar file but that | ||||
|             // is usually quite random so we sort the notes in the way they would appear in the file manager | ||||
|             treeService.sortNotesAlphabetically(noteId, true); | ||||
|             treeService.sortNotesByTitle(noteId, true); | ||||
|         } | ||||
|  | ||||
|         taskContext.increaseProgressCount(); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user