uploading new image revisions, WIP

This commit is contained in:
zadam 2019-11-08 22:34:30 +01:00
parent 3149dff880
commit 712f67e983
22 changed files with 736 additions and 217 deletions

View File

@ -270,6 +270,29 @@
<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> <tr>
<td class="name"><code>dateCreated</code></td> <td class="name"><code>dateCreated</code></td>
@ -396,7 +419,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line43">line 43</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line42">line 42</a>
</li></ul></dd> </li></ul></dd>
@ -583,7 +606,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line386">line 386</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line383">line 383</a>
</li></ul></dd> </li></ul></dd>
@ -750,7 +773,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line240">line 240</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line237">line 237</a>
</li></ul></dd> </li></ul></dd>
@ -928,7 +951,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line397">line 397</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line394">line 394</a>
</li></ul></dd> </li></ul></dd>
@ -1034,7 +1057,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line673">line 673</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line678">line 678</a>
</li></ul></dd> </li></ul></dd>
@ -1136,7 +1159,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line706">line 706</a>
</li></ul></dd> </li></ul></dd>
@ -1242,7 +1265,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line687">line 687</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line692">line 692</a>
</li></ul></dd> </li></ul></dd>
@ -1348,7 +1371,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line74">line 74</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line73">line 73</a>
</li></ul></dd> </li></ul></dd>
@ -1450,7 +1473,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line573">line 573</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line578">line 578</a>
</li></ul></dd> </li></ul></dd>
@ -1683,7 +1706,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line601">line 601</a>
</li></ul></dd> </li></ul></dd>
@ -1881,7 +1904,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line634">line 634</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line639">line 639</a>
</li></ul></dd> </li></ul></dd>
@ -2079,7 +2102,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line643">line 643</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line648">line 648</a>
</li></ul></dd> </li></ul></dd>
@ -2181,7 +2204,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line109">line 109</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line108">line 108</a>
</li></ul></dd> </li></ul></dd>
@ -2332,7 +2355,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line484">line 484</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line489">line 489</a>
</li></ul></dd> </li></ul></dd>
@ -2499,7 +2522,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line265">line 265</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line262">line 262</a>
</li></ul></dd> </li></ul></dd>
@ -2666,7 +2689,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line257">line 257</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line254">line 254</a>
</li></ul></dd> </li></ul></dd>
@ -2821,7 +2844,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line496">line 496</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line501">line 501</a>
</li></ul></dd> </li></ul></dd>
@ -2933,7 +2956,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line660">line 660</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line665">line 665</a>
</li></ul></dd> </li></ul></dd>
@ -3035,7 +3058,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line223">line 223</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line220">line 220</a>
</li></ul></dd> </li></ul></dd>
@ -3143,7 +3166,7 @@ This method can be significantly faster than the getAttribute()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line201">line 201</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line198">line 198</a>
</li></ul></dd> </li></ul></dd>
@ -3251,7 +3274,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line713">line 713</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line718">line 718</a>
</li></ul></dd> </li></ul></dd>
@ -3406,7 +3429,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line490">line 490</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line495">line 495</a>
</li></ul></dd> </li></ul></dd>
@ -3573,7 +3596,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line296">line 296</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line293">line 293</a>
</li></ul></dd> </li></ul></dd>
@ -3740,7 +3763,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line273">line 273</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line270">line 270</a>
</li></ul></dd> </li></ul></dd>
@ -3895,7 +3918,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line508">line 508</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line513">line 513</a>
</li></ul></dd> </li></ul></dd>
@ -4065,7 +4088,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line281">line 281</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line278">line 278</a>
</li></ul></dd> </li></ul></dd>
@ -4216,7 +4239,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line502">line 502</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line507">line 507</a>
</li></ul></dd> </li></ul></dd>
@ -4326,7 +4349,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line650">line 650</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line655">line 655</a>
</li></ul></dd> </li></ul></dd>
@ -4428,7 +4451,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line180">line 180</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line177">line 177</a>
</li></ul></dd> </li></ul></dd>
@ -4534,7 +4557,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line232">line 232</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line229">line 229</a>
</li></ul></dd> </li></ul></dd>
@ -4712,7 +4735,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line377">line 377</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line374">line 374</a>
</li></ul></dd> </li></ul></dd>
@ -4818,7 +4841,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line685">line 685</a>
</li></ul></dd> </li></ul></dd>
@ -4973,7 +4996,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line472">line 472</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line477">line 477</a>
</li></ul></dd> </li></ul></dd>
@ -5128,7 +5151,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line478">line 478</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line483">line 483</a>
</li></ul></dd> </li></ul></dd>
@ -5239,7 +5262,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line304">line 304</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line301">line 301</a>
</li></ul></dd> </li></ul></dd>
@ -5323,7 +5346,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line168">line 168</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line167">line 167</a>
</li></ul></dd> </li></ul></dd>
@ -5429,7 +5452,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line160">line 160</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line159">line 159</a>
</li></ul></dd> </li></ul></dd>
@ -5535,7 +5558,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line155">line 155</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line154">line 154</a>
</li></ul></dd> </li></ul></dd>
@ -5641,7 +5664,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line150">line 150</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line149">line 149</a>
</li></ul></dd> </li></ul></dd>
@ -5747,7 +5770,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line173">line 173</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line172">line 172</a>
</li></ul></dd> </li></ul></dd>
@ -5853,7 +5876,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line309">line 309</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line306">line 306</a>
</li></ul></dd> </li></ul></dd>
@ -6082,7 +6105,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line455">line 455</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line460">line 460</a>
</li></ul></dd> </li></ul></dd>
@ -6280,7 +6303,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line559">line 559</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line564">line 564</a>
</li></ul></dd> </li></ul></dd>
@ -6478,7 +6501,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line568">line 568</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line573">line 573</a>
</li></ul></dd> </li></ul></dd>
@ -6540,7 +6563,7 @@ Cache is note instance scoped.
<div class="description"> <div class="description">
Creates given attribute name-value pair if it doesn't exist. Update's given attribute's value or creates it if it doesn't exist
</div> </div>
@ -6707,7 +6730,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line429">line 429</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line426">line 426</a>
</li></ul></dd> </li></ul></dd>
@ -6809,7 +6832,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line116">line 116</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line115">line 115</a>
</li></ul></dd> </li></ul></dd>
@ -6911,7 +6934,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line145">line 145</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line144">line 144</a>
</li></ul></dd> </li></ul></dd>
@ -6973,7 +6996,7 @@ Cache is note instance scoped.
<div class="description"> <div class="description">
Create label name-value pair if it doesn't exist yet. Update's given label's value or creates it if it doesn't exist
</div> </div>
@ -7109,7 +7132,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line541">line 541</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line546">line 546</a>
</li></ul></dd> </li></ul></dd>
@ -7171,7 +7194,7 @@ Cache is note instance scoped.
<div class="description"> <div class="description">
Create relation name-value pair if it doesn't exist yet. Update's given relation's value or creates it if it doesn't exist
</div> </div>
@ -7307,7 +7330,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line550">line 550</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line555">line 555</a>
</li></ul></dd> </li></ul></dd>
@ -7567,7 +7590,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line409">line 409</a>
</li></ul></dd> </li></ul></dd>
@ -7796,7 +7819,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line522">line 522</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line527">line 527</a>
</li></ul></dd> </li></ul></dd>
@ -8025,7 +8048,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line532">line 532</a> <a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line537">line 537</a>
</li></ul></dd> </li></ul></dd>

View File

@ -28,7 +28,7 @@
<header> <header>
<h2><span class="attribs"><span class="type-signature"></span></span>NoteRevision<span class="signature">(noteRevisionId, noteId, type, mime, title, content, isProtected, dateModifiedFrom, dateModifiedTo, utcDateModifiedFrom, utcDateModifiedTo)</span><span class="type-signature"></span></h2> <h2><span class="attribs"><span class="type-signature"></span></span>NoteRevision<span class="signature">(noteRevisionId, noteId, type, mime, title, isProtected, dateLastEdited, dateCreated, utcDateLastEdited, utcDateCreated, utcDateModified)</span><span class="type-signature"></span></h2>
<div class="class-description">NoteRevision represents snapshot of note's title and content at some point in the past. It's used for seamless note versioning.</div> <div class="class-description">NoteRevision represents snapshot of note's title and content at some point in the past. It's used for seamless note versioning.</div>
@ -45,7 +45,7 @@
<h4 class="name" id="NoteRevision"><span class="type-signature"></span>new NoteRevision<span class="signature">(noteRevisionId, noteId, type, mime, title, content, isProtected, dateModifiedFrom, dateModifiedTo, utcDateModifiedFrom, utcDateModifiedTo)</span><span class="type-signature"></span></h4> <h4 class="name" id="NoteRevision"><span class="type-signature"></span>new NoteRevision<span class="signature">(noteRevisionId, noteId, type, mime, title, isProtected, dateLastEdited, dateCreated, utcDateLastEdited, utcDateCreated, utcDateModified)</span><span class="type-signature"></span></h4>
@ -193,29 +193,6 @@
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>content</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last"></td> <td class="description last"></td>
</tr> </tr>
@ -246,7 +223,7 @@
<tr> <tr>
<td class="name"><code>dateModifiedFrom</code></td> <td class="name"><code>dateLastEdited</code></td>
<td class="type"> <td class="type">
@ -269,7 +246,7 @@
<tr> <tr>
<td class="name"><code>dateModifiedTo</code></td> <td class="name"><code>dateCreated</code></td>
<td class="type"> <td class="type">
@ -292,7 +269,7 @@
<tr> <tr>
<td class="name"><code>utcDateModifiedFrom</code></td> <td class="name"><code>utcDateLastEdited</code></td>
<td class="type"> <td class="type">
@ -315,7 +292,30 @@
<tr> <tr>
<td class="name"><code>utcDateModifiedTo</code></td> <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>
<td class="type"> <td class="type">
@ -372,7 +372,7 @@
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line29">line 29</a> <a href="entities_note_revision.js.html">entities/note_revision.js</a>, <a href="entities_note_revision.js.html#line33">line 33</a>
</li></ul></dd> </li></ul></dd>
@ -431,6 +431,320 @@
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="getContent"><span class="type-signature">(async) </span>getContent<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;*>}</span></h4>
<dl class="details">
<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#line67">line 67</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise.&lt;*></span>
</dd>
</dl>
<h4 class="name" id="isStringNote"><span class="type-signature"></span>isStringNote<span class="signature">()</span><span class="type-signature"> &rarr; {boolean}</span></h4>
<dl class="details">
<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#line53">line 53</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
true if the note has string content (not binary)
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">boolean</span>
</dd>
</dl>
<h4 class="name" id="setContent"><span class="type-signature">(async) </span>setContent<span class="signature">()</span><span class="type-signature"> &rarr; {Promise}</span></h4>
<dl class="details">
<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#line102">line 102</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Promise</span>
</dd>
</dl>

View File

@ -42,8 +42,6 @@ const LABEL_DEFINITION = 'label-definition';
const RELATION = 'relation'; const RELATION = 'relation';
const RELATION_DEFINITION = 'relation-definition'; const RELATION_DEFINITION = 'relation-definition';
const STRING_MIME_TYPES = ["application/x-javascript"];
/** /**
* This represents a Note which is a central object in the Trilium Notes project. * This represents a Note which is a central object in the Trilium Notes project.
* *
@ -53,6 +51,7 @@ const STRING_MIME_TYPES = ["application/x-javascript"];
* @property {string} title - note title * @property {string} title - note title
* @property {boolean} isProtected - true if note is protected * @property {boolean} isProtected - true if note is protected
* @property {boolean} isDeleted - true if note is deleted * @property {boolean} isDeleted - true if note is deleted
* @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} dateCreated - local date time (with offset)
* @property {string} dateModified - local date time (with offset) * @property {string} dateModified - local date time (with offset)
* @property {string} utcDateCreated * @property {string} utcDateCreated
@ -72,7 +71,7 @@ class Note extends Entity {
super(row); super(row);
this.isProtected = !!this.isProtected; this.isProtected = !!this.isProtected;
/* true if content (meaning any kind of potentially encrypted content) is either not encrypted /* true if content is either not encrypted
* or encrypted, but with available protected session (so effectively decrypted) */ * or encrypted, but with available protected session (so effectively decrypted) */
this.isContentAvailable = true; this.isContentAvailable = true;
@ -81,7 +80,7 @@ class Note extends Entity {
this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable(); this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
if (this.isContentAvailable) { if (this.isContentAvailable) {
protectedSessionService.decryptNote(this); this.title = protectedSessionService.decryptString(this.title);
} }
else { else {
this.title = "[protected]"; this.title = "[protected]";
@ -116,7 +115,7 @@ class Note extends Entity {
if (this.isProtected) { if (this.isProtected) {
if (this.isContentAvailable) { if (this.isContentAvailable) {
protectedSessionService.decryptNoteContent(this); this.content = this.content === null ? null : protectedSessionService.decrypt(this.content);
} }
else { else {
this.content = ""; this.content = "";
@ -142,7 +141,7 @@ class Note extends Entity {
/** @returns {Promise} */ /** @returns {Promise} */
async setContent(content) { async setContent(content) {
// force updating note itself so that dateChanged is represented correctly even for the content // force updating note itself so that dateModified is represented correctly even for the content
this.forcedChange = true; this.forcedChange = true;
await this.save(); await this.save();
@ -157,7 +156,7 @@ class Note extends Entity {
if (this.isProtected) { if (this.isProtected) {
if (this.isContentAvailable) { if (this.isContentAvailable) {
protectedSessionService.encryptNoteContent(pojo); pojo.content = protectedSessionService.encrypt(pojo.content);
} }
else { else {
throw new Error(`Cannot update content of noteId=${this.noteId} since we're out of protected session.`); throw new Error(`Cannot update content of noteId=${this.noteId} since we're out of protected session.`);
@ -199,9 +198,7 @@ class Note extends Entity {
/** @returns {boolean} true if the note has string content (not binary) */ /** @returns {boolean} true if the note has string content (not binary) */
isStringNote() { isStringNote() {
return ["text", "code", "relation-map", "search"].includes(this.type) return utils.isStringNote(this.type, this.mime);
|| this.mime.startsWith('text/')
|| STRING_MIME_TYPES.includes(this.mime);
} }
/** @returns {string} JS script environment - either "frontend" or "backend" */ /** @returns {string} JS script environment - either "frontend" or "backend" */
@ -447,7 +444,7 @@ class Note extends Entity {
} }
/** /**
* Creates given attribute name-value pair if it doesn't exist. * Update's given attribute's value or creates it if it doesn't exist
* *
* @param {string} type - attribute type (label, relation, etc.) * @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name * @param {string} name - attribute name
@ -456,9 +453,17 @@ class Note extends Entity {
*/ */
async setAttribute(type, name, value) { async setAttribute(type, name, value) {
const attributes = await this.getOwnedAttributes(); const attributes = await this.getOwnedAttributes();
let attr = attributes.find(attr => attr.type === type &amp;&amp; (value === undefined || attr.value === value)); let attr = attributes.find(attr => attr.type === type &amp;&amp; attr.name === name);
if (!attr) { if (attr) {
if (attr.value !== value) {
attr.value = value;
await attr.save();
this.invalidateAttributeCache();
}
}
else {
attr = new Attribute({ attr = new Attribute({
noteId: this.noteId, noteId: this.noteId,
type: type, type: type,
@ -560,7 +565,7 @@ class Note extends Entity {
async toggleRelation(enabled, name, value) { return await this.toggleAttribute(RELATION, enabled, name, value); } async toggleRelation(enabled, name, value) { return await this.toggleAttribute(RELATION, enabled, name, value); }
/** /**
* Create label name-value pair if it doesn't exist yet. * Update's given label's value or creates it if it doesn't exist
* *
* @param {string} name - label name * @param {string} name - label name
* @param {string} [value] - label value * @param {string} [value] - label value
@ -569,7 +574,7 @@ class Note extends Entity {
async setLabel(name, value) { return await this.setAttribute(LABEL, name, value); } async setLabel(name, value) { return await this.setAttribute(LABEL, name, value); }
/** /**
* Create relation name-value pair if it doesn't exist yet. * Update's given relation's value or creates it if it doesn't exist
* *
* @param {string} name - relation name * @param {string} name - relation name
* @param {string} [value] - relation value (noteId) * @param {string} [value] - relation value (noteId)
@ -774,7 +779,7 @@ class Note extends Entity {
updatePojo(pojo) { updatePojo(pojo) {
if (pojo.isProtected) { if (pojo.isProtected) {
if (this.isContentAvailable) { if (this.isContentAvailable) {
protectedSessionService.encryptNote(pojo); pojo.title = protectedSessionService.encrypt(pojo.title);
} }
else { else {
// updating protected note outside of protected session means we will keep original ciphertexts // updating protected note outside of protected session means we will keep original ciphertexts

View File

@ -31,6 +31,10 @@
const Entity = require('./entity'); const Entity = require('./entity');
const protectedSessionService = require('../services/protected_session'); const protectedSessionService = require('../services/protected_session');
const repository = require('../services/repository'); const repository = require('../services/repository');
const utils = require('../services/utils');
const sql = require('../services/sql');
const dateUtils = require('../services/date_utils');
const syncTableService = require('../services/sync_table');
/** /**
* NoteRevision represents snapshot of note's title and content at some point in the past. It's used for seamless note versioning. * NoteRevision represents snapshot of note's title and content at some point in the past. It's used for seamless note versioning.
@ -40,19 +44,19 @@ const repository = require('../services/repository');
* @param {string} type * @param {string} type
* @param {string} mime * @param {string} mime
* @param {string} title * @param {string} title
* @param {string} content
* @param {string} isProtected * @param {string} isProtected
* @param {string} dateModifiedFrom * @param {string} dateLastEdited
* @param {string} dateModifiedTo * @param {string} dateCreated
* @param {string} utcDateModifiedFrom * @param {string} utcDateLastEdited
* @param {string} utcDateModifiedTo * @param {string} utcDateCreated
* @param {string} utcDateModified
* *
* @extends Entity * @extends Entity
*/ */
class NoteRevision extends Entity { class NoteRevision extends Entity {
static get entityName() { return "note_revisions"; } static get entityName() { return "note_revisions"; }
static get primaryKeyName() { return "noteRevisionId"; } static get primaryKeyName() { return "noteRevisionId"; }
static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "content", "isProtected", "dateModifiedFrom", "dateModifiedTo", "utcDateModifiedFrom", "utcDateModifiedTo"]; } static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "contentLength", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; }
constructor(row) { constructor(row) {
super(row); super(row);
@ -60,7 +64,12 @@ class NoteRevision extends Entity {
this.isProtected = !!this.isProtected; this.isProtected = !!this.isProtected;
if (this.isProtected) { if (this.isProtected) {
protectedSessionService.decryptNoteRevision(this); if (protectedSessionService.isProtectedSessionAvailable()) {
this.title = protectedSessionService.decryptString(this.title);
}
else {
this.title = "[Protected]";
}
} }
} }
@ -68,12 +77,98 @@ class NoteRevision extends Entity {
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
} }
beforeSaving() { /** @returns {boolean} true if the note has string content (not binary) */
if (this.isProtected) { isStringNote() {
protectedSessionService.encryptNoteRevision(this); return utils.isStringNote(this.type, this.mime);
}
/*
* Note revision content has quite special handling - it's not a separate entity, but a lazily loaded
* part of NoteRevision entity with it's own sync. Reason behind this hybrid design is that
* content can be quite large and it's not necessary to load it / fill memory for any note access even
* if we don't need a content, especially for bulk operations like search.
*
* This is the same approach as is used for Note's content.
*/
/** @returns {Promise&lt;*>} */
async getContent(silentNotFoundError = false) {
if (this.content === undefined) {
const res = await sql.getRow(`SELECT content, hash FROM note_revision_contents WHERE noteRevisionId = ?`, [this.noteRevisionId]);
if (!res) {
if (silentNotFoundError) {
return undefined;
}
else {
throw new Error("Cannot find note revision content for noteRevisionId=" + this.noteRevisionId);
}
}
this.content = res.content;
if (this.isProtected) {
if (protectedSessionService.isProtectedSessionAvailable()) {
this.content = protectedSessionService.decrypt(this.content);
}
else {
this.content = "";
}
}
if (this.isStringNote()) {
this.content = this.content === null
? ""
: this.content.toString("UTF-8");
}
} }
super.beforeSaving(); return this.content;
}
/** @returns {Promise} */
async setContent(content) {
// force updating note itself so that utcDateModified is represented correctly even for the content
this.forcedChange = true;
this.contentLength = content.length;
await this.save();
this.content = content;
const pojo = {
noteRevisionId: this.noteRevisionId,
content: content,
utcDateModified: dateUtils.utcNowDateTime(),
hash: utils.hash(this.noteRevisionId + "|" + content)
};
if (this.isProtected) {
if (protectedSessionService.isProtectedSessionAvailable()) {
pojo.content = protectedSessionService.encrypt(pojo.content);
}
else {
throw new Error(`Cannot update content of noteRevisionId=${this.noteRevisionId} since we're out of protected session.`);
}
}
await sql.upsert("note_revision_contents", "noteRevisionId", pojo);
await syncTableService.addNoteRevisionContentSync(this.noteRevisionId);
}
// cannot be static!
updatePojo(pojo) {
if (pojo.isProtected) {
if (protectedSessionService.isProtectedSessionAvailable()) {
pojo.title = protectedSessionService.encrypt(pojo.title);
}
else {
// updating protected note outside of protected session means we will keep original ciphertexts
delete pojo.title;
}
}
delete pojo.content;
} }
} }

View File

@ -30,10 +30,7 @@
<h2><span class="attribs"><span class="type-signature"></span></span>NoteShort<span class="signature">(treeCache, row, branches)</span><span class="type-signature"></span></h2> <h2><span class="attribs"><span class="type-signature"></span></span>NoteShort<span class="signature">(treeCache, row, branches)</span><span class="type-signature"></span></h2>
<div class="class-description">FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache. <div class="class-description">This note's representation is used in note tree and is kept in TreeCache.</div>
Attribute cache should be limited to "transaction".
This note's representation is used in note tree and is kept in TreeCache.</div>
</header> </header>
@ -191,7 +188,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line18">line 18</a>
</li></ul></dd> </li></ul></dd>
@ -281,7 +278,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line37">line 37</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> </li></ul></dd>
@ -349,7 +346,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line44">line 44</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line40">line 40</a>
</li></ul></dd> </li></ul></dd>
@ -417,7 +414,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line50">line 50</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line46">line 46</a>
</li></ul></dd> </li></ul></dd>
@ -475,7 +472,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line39">line 39</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line35">line 35</a>
</li></ul></dd> </li></ul></dd>
@ -533,7 +530,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line35">line 35</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line31">line 31</a>
</li></ul></dd> </li></ul></dd>
@ -591,7 +588,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line29">line 29</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line25">line 25</a>
</li></ul></dd> </li></ul></dd>
@ -649,7 +646,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line29">line 29</a>
</li></ul></dd> </li></ul></dd>
@ -707,7 +704,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line21">line 21</a>
</li></ul></dd> </li></ul></dd>
@ -775,7 +772,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line42">line 42</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line38">line 38</a>
</li></ul></dd> </li></ul></dd>
@ -843,7 +840,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line43">line 43</a>
</li></ul></dd> </li></ul></dd>
@ -901,7 +898,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line27">line 27</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line23">line 23</a>
</li></ul></dd> </li></ul></dd>
@ -959,7 +956,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line31">line 31</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line27">line 27</a>
</li></ul></dd> </li></ul></dd>
@ -1107,7 +1104,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line220">line 220</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line216">line 216</a>
</li></ul></dd> </li></ul></dd>
@ -1274,7 +1271,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line160">line 160</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line156">line 156</a>
</li></ul></dd> </li></ul></dd>
@ -1448,7 +1445,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line231">line 231</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line227">line 227</a>
</li></ul></dd> </li></ul></dd>
@ -1554,7 +1551,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line117">line 117</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line113">line 113</a>
</li></ul></dd> </li></ul></dd>
@ -1656,7 +1653,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line129">line 129</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@ -1758,7 +1755,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line147">line 147</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line143">line 143</a>
</li></ul></dd> </li></ul></dd>
@ -1860,7 +1857,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line152">line 152</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line148">line 148</a>
</li></ul></dd> </li></ul></dd>
@ -2011,7 +2008,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line249">line 249</a>
</li></ul></dd> </li></ul></dd>
@ -2178,7 +2175,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line186">line 186</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line182">line 182</a>
</li></ul></dd> </li></ul></dd>
@ -2345,7 +2342,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line178">line 178</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line174">line 174</a>
</li></ul></dd> </li></ul></dd>
@ -2500,7 +2497,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line265">line 265</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line261">line 261</a>
</li></ul></dd> </li></ul></dd>
@ -2606,7 +2603,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line137">line 137</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line133">line 133</a>
</li></ul></dd> </li></ul></dd>
@ -2708,7 +2705,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line142">line 142</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line138">line 138</a>
</li></ul></dd> </li></ul></dd>
@ -2859,7 +2856,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line259">line 259</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line255">line 255</a>
</li></ul></dd> </li></ul></dd>
@ -3026,7 +3023,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line202">line 202</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line198">line 198</a>
</li></ul></dd> </li></ul></dd>
@ -3193,7 +3190,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line194">line 194</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line190">line 190</a>
</li></ul></dd> </li></ul></dd>
@ -3348,7 +3345,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line277">line 277</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line273">line 273</a>
</li></ul></dd> </li></ul></dd>
@ -3518,7 +3515,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line283">line 283</a>
</li></ul></dd> </li></ul></dd>
@ -3669,7 +3666,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line271">line 271</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line267">line 267</a>
</li></ul></dd> </li></ul></dd>
@ -3779,7 +3776,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line311">line 311</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line307">line 307</a>
</li></ul></dd> </li></ul></dd>
@ -3953,7 +3950,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line211">line 211</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line207">line 207</a>
</li></ul></dd> </li></ul></dd>
@ -4059,7 +4056,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line124">line 124</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line120">line 120</a>
</li></ul></dd> </li></ul></dd>
@ -4210,7 +4207,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line241">line 241</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line237">line 237</a>
</li></ul></dd> </li></ul></dd>
@ -4365,7 +4362,7 @@ This note's representation is used in note tree and is kept in TreeCache.</div>
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line247">line 247</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line243">line 243</a>
</li></ul></dd> </li></ul></dd>
@ -4476,7 +4473,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line302">line 302</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line298">line 298</a>
</li></ul></dd> </li></ul></dd>
@ -4560,7 +4557,7 @@ Cache is note instance scoped.
<dt class="tag-source">Source:</dt> <dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li> <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#line92">line 92</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line88">line 88</a>
</li></ul></dd> </li></ul></dd>

View File

@ -28,7 +28,6 @@
<article> <article>
<pre class="prettyprint source linenums"><code>import server from '../services/server.js'; <pre class="prettyprint source linenums"><code>import server from '../services/server.js';
import Attribute from './attribute.js'; import Attribute from './attribute.js';
import branches from "../services/branches.js";
const LABEL = 'label'; const LABEL = 'label';
const LABEL_DEFINITION = 'label-definition'; const LABEL_DEFINITION = 'label-definition';
@ -36,9 +35,6 @@ const RELATION = 'relation';
const RELATION_DEFINITION = 'relation-definition'; const RELATION_DEFINITION = 'relation-definition';
/** /**
* FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache.
* Attribute cache should be limited to "transaction".
*
* This note's representation is used in note tree and is kept in TreeCache. * This note's representation is used in note tree and is kept in TreeCache.
*/ */
class NoteShort { class NoteShort {

View File

@ -204,7 +204,7 @@
<td class="description last">name of the JAM icon to be used (e.g. "clock" for "jam-clock" icon)</td> <td class="description last">name of the boxicon to be used (e.g. "time" for "bx-time" icon)</td>
</tr> </tr>

View File

@ -100,7 +100,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
/** /**
* @typedef {Object} ToolbarButtonOptions * @typedef {Object} ToolbarButtonOptions
* @property {string} title * @property {string} title
* @property {string} [icon] - name of the JAM icon to be used (e.g. "clock" for "jam-clock" icon) * @property {string} [icon] - name of the boxicon to be used (e.g. "time" for "bx-time" icon)
* @property {function} action - callback handling the click on the button * @property {function} action - callback handling the click on the button
* @property {string} [shortcut] - keyboard shortcut for the button, e.g. "alt+t" * @property {string} [shortcut] - keyboard shortcut for the button, e.g. "alt+t"
*/ */
@ -118,7 +118,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
.click(opts.action); .click(opts.action);
if (opts.icon) { if (opts.icon) {
button.append($("&lt;span>").addClass("jam jam-" + opts.icon)) button.append($("&lt;span>").addClass("bx bx-" + opts.icon))
.append("&amp;nbsp;"); .append("&amp;nbsp;");
} }

6
package-lock.json generated
View File

@ -2411,9 +2411,9 @@
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI="
}, },
"dayjs": { "dayjs": {
"version": "1.8.16", "version": "1.8.17",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.16.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.17.tgz",
"integrity": "sha512-XPmqzWz/EJiaRHjBqSJ2s6hE/BUoCIHKgdS2QPtTQtKcS9E4/Qn0WomoH1lXanWCzri+g7zPcuNV4aTZ8PMORQ==" "integrity": "sha512-47VY/htqYqr9GHd7HW/h56PpQzRBSJcxIQFwqL3P20bMF/3az5c3PWdVY3LmPXFl6cQCYHL7c79b9ov+2bOBbw=="
}, },
"debug": { "debug": {
"version": "4.1.1", "version": "4.1.1",

View File

@ -27,7 +27,7 @@
"commonmark": "0.29.0", "commonmark": "0.29.0",
"cookie-parser": "1.4.4", "cookie-parser": "1.4.4",
"csurf": "1.10.0", "csurf": "1.10.0",
"dayjs": "1.8.16", "dayjs": "1.8.17",
"debug": "4.1.1", "debug": "4.1.1",
"ejs": "2.7.1", "ejs": "2.7.1",
"electron-debug": "3.0.1", "electron-debug": "3.0.1",

View File

@ -416,7 +416,7 @@ class Note extends Entity {
} }
/** /**
* Creates given attribute name-value pair if it doesn't exist. * Update's given attribute's value or creates it if it doesn't exist
* *
* @param {string} type - attribute type (label, relation, etc.) * @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name * @param {string} name - attribute name
@ -425,9 +425,17 @@ class Note extends Entity {
*/ */
async setAttribute(type, name, value) { async setAttribute(type, name, value) {
const attributes = await this.getOwnedAttributes(); const attributes = await this.getOwnedAttributes();
let attr = attributes.find(attr => attr.type === type && (value === undefined || attr.value === value)); let attr = attributes.find(attr => attr.type === type && attr.name === name);
if (!attr) { if (attr) {
if (attr.value !== value) {
attr.value = value;
await attr.save();
this.invalidateAttributeCache();
}
}
else {
attr = new Attribute({ attr = new Attribute({
noteId: this.noteId, noteId: this.noteId,
type: type, type: type,
@ -529,7 +537,7 @@ class Note extends Entity {
async toggleRelation(enabled, name, value) { return await this.toggleAttribute(RELATION, enabled, name, value); } async toggleRelation(enabled, name, value) { return await this.toggleAttribute(RELATION, enabled, name, value); }
/** /**
* Create label name-value pair if it doesn't exist yet. * Update's given label's value or creates it if it doesn't exist
* *
* @param {string} name - label name * @param {string} name - label name
* @param {string} [value] - label value * @param {string} [value] - label value
@ -538,7 +546,7 @@ class Note extends Entity {
async setLabel(name, value) { return await this.setAttribute(LABEL, name, value); } async setLabel(name, value) { return await this.setAttribute(LABEL, name, value); }
/** /**
* Create relation name-value pair if it doesn't exist yet. * Update's given relation's value or creates it if it doesn't exist
* *
* @param {string} name - relation name * @param {string} name - relation name
* @param {string} [value] - relation value (noteId) * @param {string} [value] - relation value (noteId)

View File

@ -1,6 +1,5 @@
import server from '../services/server.js'; import server from '../services/server.js';
import Attribute from './attribute.js'; import Attribute from './attribute.js';
import branches from "../services/branches.js";
const LABEL = 'label'; const LABEL = 'label';
const LABEL_DEFINITION = 'label-definition'; const LABEL_DEFINITION = 'label-definition';

View File

@ -1,6 +1,7 @@
import utils from "./utils.js"; import utils from "./utils.js";
import toastService from "./toast.js"; import toastService from "./toast.js";
import server from "./server.js"; import server from "./server.js";
import noteDetailService from "./note_detail.js";
class NoteDetailImage { class NoteDetailImage {
/** /**
@ -12,14 +13,16 @@ class NoteDetailImage {
this.$imageWrapper = ctx.$tabContent.find('.note-detail-image-wrapper'); this.$imageWrapper = ctx.$tabContent.find('.note-detail-image-wrapper');
this.$imageView = ctx.$tabContent.find('.note-detail-image-view'); this.$imageView = ctx.$tabContent.find('.note-detail-image-view');
this.$copyToClipboardButton = ctx.$tabContent.find(".image-copy-to-clipboard"); this.$copyToClipboardButton = ctx.$tabContent.find(".image-copy-to-clipboard");
this.$uploadNewRevisionButton = ctx.$tabContent.find(".image-upload-new-revision");
this.$uploadNewRevisionInput = ctx.$tabContent.find(".image-upload-new-revision-input");
this.$fileName = ctx.$tabContent.find(".image-filename"); this.$fileName = ctx.$tabContent.find(".image-filename");
this.$fileType = ctx.$tabContent.find(".image-filetype"); this.$fileType = ctx.$tabContent.find(".image-filetype");
this.$fileSize = ctx.$tabContent.find(".image-filesize"); this.$fileSize = ctx.$tabContent.find(".image-filesize");
this.$imageDownloadButton = ctx.$tabContent.find(".image-download"); this.$imageDownloadButton = ctx.$tabContent.find(".image-download");
this.$imageDownloadButton.click(() => utils.download(this.getFileUrl())); this.$imageDownloadButton.on('click', () => utils.download(this.getFileUrl()));
this.$copyToClipboardButton.click(() => { this.$copyToClipboardButton.on('click',() => {
this.$imageWrapper.attr('contenteditable','true'); this.$imageWrapper.attr('contenteditable','true');
try { try {
@ -39,6 +42,34 @@ class NoteDetailImage {
this.$imageWrapper.removeAttr('contenteditable'); this.$imageWrapper.removeAttr('contenteditable');
} }
}); });
this.$uploadNewRevisionButton.on("click", () => {
this.$uploadNewRevisionInput.trigger("click");
});
this.$uploadNewRevisionInput.on('change', async () => {
const formData = new FormData();
formData.append('upload', this.$uploadNewRevisionInput[0].files[0]);
const result = await $.ajax({
url: baseApiUrl + 'images/' + this.ctx.note.noteId,
headers: server.getHeaders(),
data: formData,
type: 'PUT',
timeout: 60 * 60 * 1000,
contentType: false, // NEEDED, DON'T REMOVE THIS
processData: false, // NEEDED, DON'T REMOVE THIS
});
if (result.uploaded) {
toastService.showMessage("New revision of the image has been uploaded.")
await noteDetailService.reload();
}
else {
toastService.showError("Could not upload new revision of the image: " + result.message);
}
});
} }
async render() { async render() {
@ -51,7 +82,9 @@ class NoteDetailImage {
this.$fileSize.text((attributeMap.fileSize || "?") + " bytes"); this.$fileSize.text((attributeMap.fileSize || "?") + " bytes");
this.$fileType.text(this.ctx.note.mime); this.$fileType.text(this.ctx.note.mime);
this.$imageView.prop("src", `api/images/${this.ctx.note.noteId}/${this.ctx.note.title}`); const imageHash = this.ctx.note.utcDateModified.replace(" ", "_");
this.$imageView.prop("src", `api/images/${this.ctx.note.noteId}/${this.ctx.note.title}?${imageHash}`);
} }
selectImage(element) { selectImage(element) {

View File

@ -82,7 +82,7 @@ async function addImagesToNote(images, note, content) {
const buffer = Buffer.from(dataUrl.split(",")[1], 'base64'); const buffer = Buffer.from(dataUrl.split(",")[1], 'base64');
const {note: imageNote, url} = await imageService.saveImage(buffer, filename, note.noteId, true); const {note: imageNote, url} = await imageService.saveImage(note.noteId, buffer, filename, true);
await new Attribute({ await new Attribute({
noteId: note.noteId, noteId: note.noteId,

View File

@ -25,8 +25,8 @@ async function returnImage(req, res) {
} }
async function uploadImage(req) { async function uploadImage(req) {
const noteId = req.query.noteId; const {noteId} = req.query;
const file = req.file; const {file} = req;
const note = await repository.getNote(noteId); const note = await repository.getNote(noteId);
@ -38,7 +38,7 @@ async function uploadImage(req) {
return [400, "Unknown image type: " + file.mimetype]; return [400, "Unknown image type: " + file.mimetype];
} }
const {url} = await imageService.saveImage(file.buffer, file.originalname, noteId, true); const {url} = await imageService.saveImage(noteId, file.buffer, file.originalname, true);
return { return {
uploaded: true, uploaded: true,
@ -46,7 +46,30 @@ async function uploadImage(req) {
}; };
} }
async function updateImage(req) {
const {noteId} = req.params;
const {file} = req;
const note = await repository.getNote(noteId);
if (!note) {
return [404, `Note ${noteId} doesn't exist.`];
}
if (!["image/png", "image/jpeg", "image/gif", "image/webp"].includes(file.mimetype)) {
return {
uploaded: false,
message: "Unknown image type: " + file.mimetype
};
}
await imageService.updateImage(noteId, file.buffer, file.originalname);
return { uploaded: true };
}
module.exports = { module.exports = {
returnImage, returnImage,
uploadImage uploadImage,
updateImage
}; };

View File

@ -16,7 +16,7 @@ async function uploadImage(req) {
const parentNote = await dateNoteService.getDateNote(req.headers['x-local-date']); const parentNote = await dateNoteService.getDateNote(req.headers['x-local-date']);
const {noteId} = await imageService.saveImage(file.buffer, originalName, parentNote.noteId, true); const {noteId} = await imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
return { return {
noteId: noteId noteId: noteId

View File

@ -171,6 +171,7 @@ function register(app) {
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.uploadImage, apiResultHandler); route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.uploadImage, apiResultHandler);
route(PUT, '/api/images/:noteId', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.updateImage, apiResultHandler);
apiRoute(GET, '/api/recent-changes', recentChangesApiRoute.getRecentChanges); apiRoute(GET, '/api/recent-changes', recentChangesApiRoute.getRecentChanges);

View File

@ -13,38 +13,62 @@ const jimp = require('jimp');
const imageType = require('image-type'); const imageType = require('image-type');
const sanitizeFilename = require('sanitize-filename'); const sanitizeFilename = require('sanitize-filename');
async function saveImage(buffer, originalName, parentNoteId, shrinkImageSwitch) { async function processImage(uploadBuffer, originalName, shrinkImageSwitch) {
const origImageFormat = imageType(buffer); const origImageFormat = imageType(uploadBuffer);
if (origImageFormat.ext === "webp") { if (origImageFormat.ext === "webp") {
// JIMP does not support webp at the moment: https://github.com/oliver-moran/jimp/issues/144 // JIMP does not support webp at the moment: https://github.com/oliver-moran/jimp/issues/144
shrinkImageSwitch = false; shrinkImageSwitch = false;
} }
const finalImageBuffer = shrinkImageSwitch ? await shrinkImage(buffer, originalName) : buffer; const finalImageBuffer = shrinkImageSwitch ? await shrinkImage(uploadBuffer, originalName) : uploadBuffer;
const imageFormat = imageType(finalImageBuffer); const imageFormat = imageType(finalImageBuffer);
const parentNote = await repository.getNote(parentNoteId); return {
buffer: finalImageBuffer,
imageFormat
};
}
async function updateImage(noteId, uploadBuffer, originalName) {
const {buffer, imageFormat} = await processImage(uploadBuffer, originalName, true);
const note = await repository.getNote(noteId);
note.mime = 'image/' + imageFormat.ext.toLowerCase();
await note.setContent(buffer);
await note.setLabel('originalFileName', originalName);
await note.setLabel('fileSize', buffer.byteLength);
}
async function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSwitch) {
const {buffer, imageFormat} = await processImage(uploadBuffer, originalName, shrinkImageSwitch);
const fileName = sanitizeFilename(originalName); const fileName = sanitizeFilename(originalName);
const {note} = await noteService.createNote(parentNoteId, fileName, finalImageBuffer, { const parentNote = await repository.getNote(parentNoteId);
const {note} = await noteService.createNote(parentNoteId, fileName, buffer, {
target: 'into', target: 'into',
type: 'image', type: 'image',
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(), isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
mime: 'image/' + imageFormat.ext.toLowerCase(), mime: 'image/' + imageFormat.ext.toLowerCase(),
attributes: [ attributes: [
{ type: 'label', name: 'originalFileName', value: originalName }, { type: 'label', name: 'originalFileName', value: originalName },
{ type: 'label', name: 'fileSize', value: finalImageBuffer.byteLength } { type: 'label', name: 'fileSize', value: buffer.byteLength }
] ]
}); });
const imageHash = note.utcDateModified.replace(" ", "_");
return { return {
fileName, fileName,
note, note,
noteId: note.noteId, noteId: note.noteId,
url: `api/images/${note.noteId}/${fileName}` url: `api/images/${note.noteId}/${fileName}?${imageHash}`
}; };
} }
@ -107,5 +131,6 @@ async function optimize(buffer) {
} }
module.exports = { module.exports = {
saveImage saveImage,
updateImage
}; };

View File

@ -255,7 +255,7 @@ async function importEnex(taskContext, file, parentNote) {
try { try {
const originalName = "image." + resource.mime.substr(6); const originalName = "image." + resource.mime.substr(6);
const {url} = await imageService.saveImage(resource.content, originalName, noteEntity.noteId, taskContext.data.shrinkImages); const {url} = await imageService.saveImage(noteEntity.noteId, resource.content, originalName, taskContext.data.shrinkImages);
const imageLink = `<img src="${url}">`; const imageLink = `<img src="${url}">`;

View File

@ -32,7 +32,7 @@ async function importSingleFile(taskContext, file, parentNote) {
} }
async function importImage(file, parentNote, taskContext) { async function importImage(file, parentNote, taskContext) {
const {note} = await imageService.saveImage(file.buffer, file.originalname, parentNote.noteId, taskContext.data.shrinkImages); const {note} = await imageService.saveImage(parentNote.noteId, file.buffer, file.originalname, taskContext.data.shrinkImages);
taskContext.increaseProgressCount(); taskContext.increaseProgressCount();

View File

@ -373,15 +373,11 @@ async function updateNote(noteId, noteUpdates) {
note.isProtected = noteUpdates.isProtected; note.isProtected = noteUpdates.isProtected;
await note.save(); await note.save();
// this might be simplified to just !== undefined if (noteUpdates.content !== undefined && noteUpdates.content !== null) {
if (!['file', 'image', 'render'].includes(note.type)) {
noteUpdates.content = await saveLinks(note, noteUpdates.content); noteUpdates.content = await saveLinks(note, noteUpdates.content);
await note.setContent(noteUpdates.content); await note.setContent(noteUpdates.content);
} }
else if (noteUpdates.content) {
await note.setContent(noteUpdates.content);
}
if (noteTitleChanged) { if (noteTitleChanged) {
await triggerNoteTitleChanged(note); await triggerNoteTitleChanged(note);

View File

@ -1,28 +1,32 @@
<div class="note-detail-image note-detail-component"> <div class="note-detail-image note-detail-component">
<strong>Original file name:</strong> <div style="display: flex; justify-content: space-evenly; margin: 10px;">
<span class="image-filename"></span> <button class="image-download btn btn-primary" type="button">Download</button>
&nbsp; &nbsp; <button class="image-copy-to-clipboard btn btn-primary" type="button">Copy to clipboard</button>
<strong>File type:</strong> <button class="image-upload-new-revision btn btn-primary" type="button">Upload new revision</button>
<span class="image-filetype"></span> </div>
&nbsp; &nbsp;
<strong>File size:</strong>
<span class="image-filesize"></span>
<br/><br/>
<button class="image-download btn btn-primary" type="button">Download</button>
&nbsp; &nbsp;
<button class="image-copy-to-clipboard btn btn-primary" type="button">Copy to clipboard</button>
<br/><br/>
<div class="note-detail-image-wrapper"> <div class="note-detail-image-wrapper">
<img class="note-detail-image-view" /> <img class="note-detail-image-view" />
</div> </div>
</div>
<div style="display: flex; justify-content: space-evenly; margin: 10px;">
<span>
<strong>Original file name:</strong>
<span class="image-filename"></span>
</span>
<span>
<strong>File type:</strong>
<span class="image-filetype"></span>
</span>
<span>
<strong>File size:</strong>
<span class="image-filesize"></span>
</span>
</div>
</div>
<input type="file" class="image-upload-new-revision-input" style="display: none">