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>
<td class="name"><code>dateCreated</code></td>
@ -396,7 +419,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#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>
@ -583,7 +606,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#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>
@ -750,7 +773,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#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>
@ -928,7 +951,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#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>
@ -1034,7 +1057,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#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>
@ -1136,7 +1159,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#line706">line 706</a>
</li></ul></dd>
@ -1242,7 +1265,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#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>
@ -1348,7 +1371,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#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>
@ -1450,7 +1473,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#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>
@ -1683,7 +1706,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#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>
@ -1881,7 +1904,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#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>
@ -2079,7 +2102,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#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>
@ -2181,7 +2204,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#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>
@ -2332,7 +2355,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#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>
@ -2499,7 +2522,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#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>
@ -2666,7 +2689,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#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>
@ -2821,7 +2844,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#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>
@ -2933,7 +2956,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#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>
@ -3035,7 +3058,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#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>
@ -3143,7 +3166,7 @@ This method can be significantly faster than the getAttribute()
<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#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>
@ -3251,7 +3274,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -3406,7 +3429,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line490">line 490</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line495">line 495</a>
</li></ul></dd>
@ -3573,7 +3596,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -3740,7 +3763,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -3895,7 +3918,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line508">line 508</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line513">line 513</a>
</li></ul></dd>
@ -4065,7 +4088,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -4216,7 +4239,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -4326,7 +4349,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -4428,7 +4451,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line180">line 180</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line177">line 177</a>
</li></ul></dd>
@ -4534,7 +4557,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -4712,7 +4735,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -4818,7 +4841,7 @@ This method can be significantly faster than the getAttributes()
<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#line685">line 685</a>
</li></ul></dd>
@ -4973,7 +4996,7 @@ This method can be significantly faster than the getAttributes()
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line472">line 472</a>
<a href="entities_note.js.html">entities/note.js</a>, <a href="entities_note.js.html#line477">line 477</a>
</li></ul></dd>
@ -5128,7 +5151,7 @@ This method can be significantly faster than the getAttributes()
<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#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>
@ -5239,7 +5262,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#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>
@ -5323,7 +5346,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#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>
@ -5429,7 +5452,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#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>
@ -5535,7 +5558,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#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>
@ -5641,7 +5664,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#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>
@ -5747,7 +5770,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#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>
@ -5853,7 +5876,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#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>
@ -6082,7 +6105,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#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>
@ -6280,7 +6303,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#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>
@ -6478,7 +6501,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#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>
@ -6540,7 +6563,7 @@ Cache is note instance scoped.
<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>
@ -6707,7 +6730,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#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>
@ -6809,7 +6832,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#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>
@ -6911,7 +6934,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#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>
@ -6973,7 +6996,7 @@ Cache is note instance scoped.
<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>
@ -7109,7 +7132,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#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>
@ -7171,7 +7194,7 @@ Cache is note instance scoped.
<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>
@ -7307,7 +7330,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#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>
@ -7567,7 +7590,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#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>
@ -7796,7 +7819,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#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>
@ -8025,7 +8048,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#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>

View File

@ -28,7 +28,7 @@
<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>
@ -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>
</tr>
@ -246,7 +223,7 @@
<tr>
<td class="name"><code>dateModifiedFrom</code></td>
<td class="name"><code>dateLastEdited</code></td>
<td class="type">
@ -269,7 +246,7 @@
<tr>
<td class="name"><code>dateModifiedTo</code></td>
<td class="name"><code>dateCreated</code></td>
<td class="type">
@ -292,7 +269,7 @@
<tr>
<td class="name"><code>utcDateModifiedFrom</code></td>
<td class="name"><code>utcDateLastEdited</code></td>
<td class="type">
@ -315,7 +292,30 @@
<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">
@ -372,7 +372,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#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>
@ -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_DEFINITION = 'relation-definition';
const STRING_MIME_TYPES = ["application/x-javascript"];
/**
* 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 {boolean} isProtected - true if note is protected
* @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} dateModified - local date time (with offset)
* @property {string} utcDateCreated
@ -72,7 +71,7 @@ class Note extends Entity {
super(row);
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) */
this.isContentAvailable = true;
@ -81,7 +80,7 @@ class Note extends Entity {
this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
if (this.isContentAvailable) {
protectedSessionService.decryptNote(this);
this.title = protectedSessionService.decryptString(this.title);
}
else {
this.title = "[protected]";
@ -116,7 +115,7 @@ class Note extends Entity {
if (this.isProtected) {
if (this.isContentAvailable) {
protectedSessionService.decryptNoteContent(this);
this.content = this.content === null ? null : protectedSessionService.decrypt(this.content);
}
else {
this.content = "";
@ -142,7 +141,7 @@ class Note extends Entity {
/** @returns {Promise} */
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;
await this.save();
@ -157,7 +156,7 @@ class Note extends Entity {
if (this.isProtected) {
if (this.isContentAvailable) {
protectedSessionService.encryptNoteContent(pojo);
pojo.content = protectedSessionService.encrypt(pojo.content);
}
else {
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) */
isStringNote() {
return ["text", "code", "relation-map", "search"].includes(this.type)
|| this.mime.startsWith('text/')
|| STRING_MIME_TYPES.includes(this.mime);
return utils.isStringNote(this.type, this.mime);
}
/** @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} name - attribute name
@ -456,9 +453,17 @@ class Note extends Entity {
*/
async setAttribute(type, name, value) {
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({
noteId: this.noteId,
type: type,
@ -560,7 +565,7 @@ class Note extends Entity {
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} [value] - label value
@ -569,7 +574,7 @@ class Note extends Entity {
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} [value] - relation value (noteId)
@ -774,7 +779,7 @@ class Note extends Entity {
updatePojo(pojo) {
if (pojo.isProtected) {
if (this.isContentAvailable) {
protectedSessionService.encryptNote(pojo);
pojo.title = protectedSessionService.encrypt(pojo.title);
}
else {
// updating protected note outside of protected session means we will keep original ciphertexts

View File

@ -31,6 +31,10 @@
const Entity = require('./entity');
const protectedSessionService = require('../services/protected_session');
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.
@ -40,19 +44,19 @@ const repository = require('../services/repository');
* @param {string} type
* @param {string} mime
* @param {string} title
* @param {string} content
* @param {string} isProtected
* @param {string} dateModifiedFrom
* @param {string} dateModifiedTo
* @param {string} utcDateModifiedFrom
* @param {string} utcDateModifiedTo
* @param {string} dateLastEdited
* @param {string} dateCreated
* @param {string} utcDateLastEdited
* @param {string} utcDateCreated
* @param {string} utcDateModified
*
* @extends Entity
*/
class NoteRevision extends Entity {
static get entityName() { return "note_revisions"; }
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) {
super(row);
@ -60,7 +64,12 @@ class NoteRevision extends Entity {
this.isProtected = !!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]);
}
beforeSaving() {
if (this.isProtected) {
protectedSessionService.encryptNoteRevision(this);
/** @returns {boolean} true if the note has string content (not binary) */
isStringNote() {
return utils.isStringNote(this.type, this.mime);
}
super.beforeSaving();
/*
* 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");
}
}
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>
<div class="class-description">FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache.
Attribute cache should be limited to "transaction".
This note's representation is used in note tree and is kept in TreeCache.</div>
<div class="class-description">This note's representation is used in note tree and is kept in TreeCache.</div>
</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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -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>
<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>
@ -4476,7 +4473,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#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>
@ -4560,7 +4557,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#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>

View File

@ -28,7 +28,6 @@
<article>
<pre class="prettyprint source linenums"><code>import server from '../services/server.js';
import Attribute from './attribute.js';
import branches from "../services/branches.js";
const LABEL = 'label';
const LABEL_DEFINITION = 'label-definition';
@ -36,9 +35,6 @@ const RELATION = 'relation';
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.
*/
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>

View File

@ -100,7 +100,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
/**
* @typedef {Object} ToolbarButtonOptions
* @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 {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);
if (opts.icon) {
button.append($("&lt;span>").addClass("jam jam-" + opts.icon))
button.append($("&lt;span>").addClass("bx bx-" + opts.icon))
.append("&amp;nbsp;");
}

6
package-lock.json generated
View File

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

View File

@ -27,7 +27,7 @@
"commonmark": "0.29.0",
"cookie-parser": "1.4.4",
"csurf": "1.10.0",
"dayjs": "1.8.16",
"dayjs": "1.8.17",
"debug": "4.1.1",
"ejs": "2.7.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} name - attribute name
@ -425,9 +425,17 @@ class Note extends Entity {
*/
async setAttribute(type, name, value) {
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({
noteId: this.noteId,
type: type,
@ -529,7 +537,7 @@ class Note extends Entity {
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} [value] - label value
@ -538,7 +546,7 @@ class Note extends Entity {
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} [value] - relation value (noteId)

View File

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

View File

@ -1,6 +1,7 @@
import utils from "./utils.js";
import toastService from "./toast.js";
import server from "./server.js";
import noteDetailService from "./note_detail.js";
class NoteDetailImage {
/**
@ -12,14 +13,16 @@ class NoteDetailImage {
this.$imageWrapper = ctx.$tabContent.find('.note-detail-image-wrapper');
this.$imageView = ctx.$tabContent.find('.note-detail-image-view');
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.$fileType = ctx.$tabContent.find(".image-filetype");
this.$fileSize = ctx.$tabContent.find(".image-filesize");
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');
try {
@ -39,6 +42,34 @@ class NoteDetailImage {
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() {
@ -51,7 +82,9 @@ class NoteDetailImage {
this.$fileSize.text((attributeMap.fileSize || "?") + " bytes");
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) {

View File

@ -82,7 +82,7 @@ async function addImagesToNote(images, note, content) {
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({
noteId: note.noteId,

View File

@ -25,8 +25,8 @@ async function returnImage(req, res) {
}
async function uploadImage(req) {
const noteId = req.query.noteId;
const file = req.file;
const {noteId} = req.query;
const {file} = req;
const note = await repository.getNote(noteId);
@ -38,7 +38,7 @@ async function uploadImage(req) {
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 {
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 = {
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 {noteId} = await imageService.saveImage(file.buffer, originalName, parentNote.noteId, true);
const {noteId} = await imageService.saveImage(parentNote.noteId, file.buffer, originalName, true);
return {
noteId: noteId

View File

@ -171,6 +171,7 @@ function register(app) {
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
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);

View File

@ -13,38 +13,62 @@ const jimp = require('jimp');
const imageType = require('image-type');
const sanitizeFilename = require('sanitize-filename');
async function saveImage(buffer, originalName, parentNoteId, shrinkImageSwitch) {
const origImageFormat = imageType(buffer);
async function processImage(uploadBuffer, originalName, shrinkImageSwitch) {
const origImageFormat = imageType(uploadBuffer);
if (origImageFormat.ext === "webp") {
// JIMP does not support webp at the moment: https://github.com/oliver-moran/jimp/issues/144
shrinkImageSwitch = false;
}
const finalImageBuffer = shrinkImageSwitch ? await shrinkImage(buffer, originalName) : buffer;
const finalImageBuffer = shrinkImageSwitch ? await shrinkImage(uploadBuffer, originalName) : uploadBuffer;
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 {note} = await noteService.createNote(parentNoteId, fileName, finalImageBuffer, {
const parentNote = await repository.getNote(parentNoteId);
const {note} = await noteService.createNote(parentNoteId, fileName, buffer, {
target: 'into',
type: 'image',
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
mime: 'image/' + imageFormat.ext.toLowerCase(),
attributes: [
{ 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 {
fileName,
note,
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 = {
saveImage
saveImage,
updateImage
};

View File

@ -255,7 +255,7 @@ async function importEnex(taskContext, file, parentNote) {
try {
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}">`;

View File

@ -32,7 +32,7 @@ async function importSingleFile(taskContext, file, parentNote) {
}
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();

View File

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

View File

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