Compare commits

...

108 Commits

Author SHA1 Message Date
zadam
67e69f1940 release 0.53.0-beta 2022-06-19 14:49:48 +02:00
zadam
046db503d3 added excalidraw to the demo document 2022-06-19 14:27:25 +02:00
zadam
9827e30a61 simple dedicated health check endpoint for docker 2022-06-19 14:15:31 +02:00
zadam
e21a1b56fa Merge pull request #2928 from bill88t/master
Add a very basic docker health check
2022-06-19 14:14:22 +02:00
zadam
08e12e7349 no need to create template relation if there is already one owned 2022-06-19 14:06:00 +02:00
zadam
5ed1631a35 resort attributes for display 2022-06-19 12:18:13 +02:00
Bill Sideris
8ac776f305 Slowly making it an oneliner, added line check 2022-06-19 12:39:20 +03:00
zadam
981fac8e50 #template label is not inherited through template since it's meant to mark the template note only 2022-06-19 11:36:29 +02:00
Bill Sideris
8bb8ab96f1 a bit better 2022-06-19 12:23:00 +03:00
Bill Sideris
0b0d1b59b9 update it to check for login 200 2022-06-18 17:21:41 +03:00
Bill Sideris
57609a5952 Add docker health check 2022-06-18 17:10:26 +03:00
zadam
4f86d769be web view fixes + disclaimer 2022-06-18 15:52:09 +02:00
zadam
6cb5144c09 add score to note title matches as opposed to note path, #2927 2022-06-18 14:45:41 +02:00
zadam
aee350b07b small bulk action fixes 2022-06-17 23:12:52 +02:00
zadam
5ca7e39852 fix putting new attribute correctly into becca 2022-06-17 23:04:46 +02:00
zadam
540aba39db vertical navigation in options 2022-06-16 23:00:40 +02:00
zadam
9a8e677baf converted options dialog to new pattern 2022-06-16 22:53:11 +02:00
zadam
c5bc23d511 fixed confirmDeleteNoteBoxWithNote 2022-06-16 21:30:05 +02:00
zadam
7ac8dc6785 converted prompt dialog to new pattern 2022-06-16 21:13:09 +02:00
zadam
049261a8ee scope dialog CSS 2022-06-16 20:20:56 +02:00
zadam
1d037d3f0f converted confirm dialog to new pattern 2022-06-16 20:19:26 +02:00
zadam
b45df29937 prevent pasting notes into search parent note 2022-06-16 20:02:40 +02:00
zadam
ec087ed328 converted info dialog to new pattern 2022-06-16 19:53:33 +02:00
zadam
9707094686 converted delete notes dialog to new pattern 2022-06-16 19:41:29 +02:00
zadam
eb8e5eafb6 converted note revisions to new pattern 2022-06-16 19:29:18 +02:00
zadam
e140daa952 converted protected session password dialog to new pattern 2022-06-16 15:28:51 +02:00
zadam
3255607b09 converted markdown import dialog to new pattern 2022-06-16 15:15:42 +02:00
zadam
36c210d0dd converted export dialog to new pattern 2022-06-16 15:04:57 +02:00
zadam
595e16cc6f converted import dialog to new pattern 2022-06-16 14:21:24 +02:00
zadam
40bbe380d3 converted move to dialog to new pattern 2022-06-16 14:08:33 +02:00
zadam
683b4ac73a converted clone to dialog to new pattern 2022-06-16 14:02:43 +02:00
zadam
e0ad256194 fix add link + note type chooser combo 2022-06-16 13:21:27 +02:00
zadam
0468ca6814 converted add link dialog to new pattern 2022-06-16 11:03:04 +02:00
zadam
6ebf7ae94e converted jump to note dialog to new pattern 2022-06-16 10:42:49 +02:00
zadam
5ccaf8b3b9 fix multiple parents indication on note tree 2022-06-15 23:07:09 +02:00
zadam
0e01c19414 don't show hidden notes in search results 2022-06-15 22:50:22 +02:00
zadam
1347d3fcc2 converted note type chooser dialog to new pattern 2022-06-15 00:10:32 +02:00
zadam
ebd715ca1b converted include note dialog to new pattern 2022-06-14 23:51:16 +02:00
zadam
73574ac890 converted password not set dialog to new pattern 2022-06-14 23:32:16 +02:00
zadam
ca44edd48c converted sort by dialog to new pattern 2022-06-14 23:19:41 +02:00
zadam
312ffc110a converted branch prefix dialog to new pattern 2022-06-14 23:07:42 +02:00
zadam
bc87bf12cf converted backend log dialog to new pattern 2022-06-14 23:00:24 +02:00
zadam
11412a258b converted recent changes dialog to new pattern 2022-06-14 22:55:07 +02:00
zadam
bc35efd565 Merge branch 'stable' 2022-06-14 22:46:58 +02:00
zadam
416a723160 Merge remote-tracking branch 'origin/master' 2022-06-14 22:46:52 +02:00
zadam
10322c5d0f Merge pull request #2920 from st3iny/fix/2919/docker-image-clean-exit
Fix docker image not exiting cleanly
2022-06-14 22:24:18 +02:00
Richard Steinmetz
7775d90b9a Fix docker image not exiting cleanly
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2022-06-14 10:34:07 +02:00
zadam
fac9fef652 release 0.52.3 2022-06-13 23:41:52 +02:00
zadam
f0ab1fb5a1 Merge pull request #2917 from bill88t/master
Added the USER_UID & USER_GID env variables
2022-06-13 23:23:30 +02:00
zadam
f86fb129b6 Merge remote-tracking branch 'origin/master' 2022-06-13 23:18:57 +02:00
zadam
63cabb13b6 Merge pull request #2917 from bill88t/master
Added the USER_UID & USER_GID env variables
2022-06-13 23:17:59 +02:00
zadam
d3ee0aa8a8 Merge branch 'stable'
# Conflicts:
#	src/routes/api/files.js
#	src/routes/api/note_revisions.js
#	src/routes/api/notes.js
#	src/services/image.js
2022-06-13 23:04:54 +02:00
zadam
6256bcde2d note revisions and file properties buttons respect protected session 2022-06-13 23:03:56 +02:00
zadam
df3fdb59c5 fix saving note revisions, closes #2915 2022-06-13 22:54:08 +02:00
zadam
4cec856e21 simplified updating note content 2022-06-13 22:38:59 +02:00
Bill Sideris
8a43688a65 Added the USER_UID & USER_GID env variables 2022-06-13 12:43:10 +03:00
zadam
7edcd5d746 Merge remote-tracking branch 'origin/master' 2022-06-13 00:00:24 +02:00
zadam
ec6d93b34f converted help dialog to new pattern 2022-06-13 00:00:15 +02:00
zadam
0c6efb0cb7 Merge pull request #2914 from st3iny/enh/noid/trilium-data-dir-docker-start
Fix TRILIUM_DATA_DIR permissions in start-docker.sh
2022-06-12 23:31:15 +02:00
zadam
f8fd8e47a9 added rename note bulk action 2022-06-12 23:29:11 +02:00
Richard Steinmetz
566111ce82 Fix TRILIUM_DATA_DIR permissions in start-docker.sh
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2022-06-12 23:25:33 +02:00
zadam
7ba619c71d converted note source dialog to new pattern 2022-06-12 19:38:28 +02:00
zadam
b678d87c80 converted about dialog to new pattern 2022-06-12 14:03:59 +02:00
zadam
4aaa0f8d8c change tree node icon for selected notes to quickly bring up bulk action dialog 2022-06-12 13:57:22 +02:00
zadam
1bfc5fb77f calculate affected counts and take into account includeDescendants when executing 2022-06-12 10:35:30 +02:00
zadam
63f0e441b9 trigger execute bulk actions 2022-06-12 00:05:46 +02:00
zadam
041b4ea442 Merge remote-tracking branch 'origin/master' 2022-06-11 23:29:59 +02:00
zadam
2115b76047 bulk action dialog converted to widget 2022-06-11 23:29:52 +02:00
zadam
117db9f1cc Merge pull request #2910 from sigaloid/master
Add toast messages prior to possibly long operations
2022-06-11 22:15:34 +02:00
sigaloid
b530bc548f Add messages prior to possibly long operations 2022-06-11 13:27:41 -04:00
zadam
8e23c15763 Merge branch 'next53'
# Conflicts:
#	src/services/builtin_attributes.js
2022-06-10 23:02:51 +02:00
zadam
23e9bcfdc5 release 0.52.2 2022-06-09 23:39:48 +02:00
zadam
96c4934c00 new default keyboard shortcuts alt+up/down/left/right for moving notes on Mac 2022-06-09 23:38:07 +02:00
zadam
31fb02f810 titleTemplate should be sanitized on import 2022-06-09 21:01:02 +02:00
zadam
5fdb462ed5 fix activating ribbon tabs after note switch 2022-06-08 23:44:43 +02:00
zadam
7d76fb8bf5 merge fix 2022-06-08 22:52:17 +02:00
zadam
0f7fa7a7b7 Merge branch 'master' into next53
# Conflicts:
#	package-lock.json
#	src/routes/api/search.js
2022-06-08 22:51:18 +02:00
zadam
e206d9cc68 fix selected note text color 2022-06-08 22:27:36 +02:00
zadam
2d33f570f4 fix bulk/search action delete 2022-06-08 22:25:00 +02:00
zadam
15f8173add fix ugly hover close button 2022-06-07 20:11:43 +02:00
zadam
51bbc23270 Merge branch 'master' into next53 2022-06-06 22:27:21 +02:00
zadam
7609bc78ec allow ignoring DB version for skipping uncritical migrations in case of a downgrade 2022-06-06 22:27:06 +02:00
zadam
b4ac41eff8 fix handlers import, closes #2900 2022-06-06 21:59:44 +02:00
zadam
f9bee7cd4e introduced bulk action groups 2022-06-05 23:36:46 +02:00
zadam
f272238dde fix backend implementation of bulk actions 2022-06-05 23:13:09 +02:00
zadam
433003cf38 fix migration 2022-06-05 22:50:02 +02:00
zadam
773cefe21d refactorings of search actions to bulk actions 2022-06-05 22:46:37 +02:00
zadam
88fa51a34e refactorings of search actions to bulk actions 2022-06-05 22:32:23 +02:00
zadam
4211d0feda Merge branch 'master' into next53 2022-06-05 22:25:14 +02:00
zadam
de1c76ee3c typo 2022-06-05 21:24:52 +02:00
zadam
9ce3e7e7d2 bulk actions WIP 2022-06-03 17:29:08 +02:00
zadam
e1cd09df36 implement shift-click to select notes in between clicked and active note, closes #2647 2022-06-03 09:42:35 +02:00
zadam
27b55eb3ee make openOnFocus=false explicit 2022-06-03 08:07:27 +02:00
zadam
ab0f0c5ced fix debounce webpack 2022-06-02 23:25:59 +02:00
zadam
4837dd050b fix bug when giving focus again to autocomplete input when coming back from note type chooser 2022-06-02 23:21:17 +02:00
zadam
c0c38a4b49 Merge branch 'master' into next53 2022-06-02 22:32:29 +02:00
zadam
93f0596b16 select template when creating note, closes #2813 2022-06-02 14:16:49 +02:00
zadam
b204014a11 create note from template WIP 2022-05-31 23:27:45 +02:00
zadam
98b579524c create note from template WIP 2022-05-31 22:45:57 +02:00
zadam
88586b0f25 Merge branch 'master' into next53 2022-05-31 22:21:29 +02:00
zadam
f252badba6 skeleton for bulk assign attributes 2022-05-30 22:43:20 +02:00
zadam
fe27c80078 added enter/leave protected session into the mobile frontend 2022-05-30 22:32:15 +02:00
zadam
8052574950 rename iframe to web view 2022-05-30 20:59:54 +02:00
zadam
f19adf3ee0 add the ability to sort notes by folders first, closes #2649 2022-05-30 20:50:53 +02:00
zadam
dcf31f8f95 toc fixes 2022-05-30 17:45:59 +02:00
zadam
cce3f9a700 TOC widget WIP 2022-05-29 21:44:26 +02:00
zadam
01155ad535 use webview instead of iframe 2022-05-29 17:42:09 +02:00
zadam
ee217d6306 added iframe note type 2022-05-28 22:19:29 +02:00
208 changed files with 9982 additions and 4216 deletions

2
.idea/misc.xml generated
View File

@@ -3,7 +3,7 @@
<component name="JavaScriptSettings"> <component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" /> <option name="languageLevel" value="ES6" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="openjdk-18" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

6
DockerHealthcheck.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
if wget --spider -S "127.0.0.1:8080/api/health-check" 2>&1 | awk 'NR==2' | grep -w "HTTP/1.1 200 OK" ; then
exit 0
else
exit 1
fi

View File

@@ -22,7 +22,7 @@ RUN set -x \
&& apk del .build-dependencies && apk del .build-dependencies
# Some setup tools need to be kept # Some setup tools need to be kept
RUN apk add --no-cache su-exec RUN apk add --no-cache su-exec shadow
# Bundle app source # Bundle app source
COPY . . COPY . .
@@ -33,3 +33,5 @@ RUN adduser -s /bin/false node; exit 0
# Start the application # Start the application
EXPOSE 8080 EXPOSE 8080
CMD [ "./start-docker.sh" ] CMD [ "./start-docker.sh" ]
HEALTHCHECK CMD sh DockerHealthcheck.sh

Binary file not shown.

View File

@@ -0,0 +1,2 @@
UPDATE attributes SET value = replace(value, 'setLabelValue', 'updateLabelValue') WHERE name = 'action' AND type = 'label';
UPDATE attributes SET value = replace(value, 'setRelationTarget', 'updateRelationTarget') WHERE name = 'action' AND type = 'label';

View File

@@ -139,10 +139,576 @@
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -267,7 +833,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -355,7 +921,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -223,6 +223,69 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="isInheritable"><span class="type-signature"></span>isInheritable<span class="type-signature"> :boolean</span></h4> <h4 class="name" id="isInheritable"><span class="type-signature"></span>isInheritable<span class="type-signature"> :boolean</span></h4>
@@ -703,6 +766,362 @@ and relation (representing named relationship between source and target note)</d
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
@@ -757,7 +1176,7 @@ and relation (representing named relationship between source and target note)</d
<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="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line114">line 114</a> <a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line115">line 115</a>
</li></ul></dd> </li></ul></dd>
@@ -808,6 +1227,95 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
@@ -862,7 +1370,7 @@ and relation (representing named relationship between source and target note)</d
<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="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line121">line 121</a> <a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line122">line 122</a>
</li></ul></dd> </li></ul></dd>
@@ -913,6 +1421,95 @@ and relation (representing named relationship between source and target note)</d
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -967,7 +1564,7 @@ and relation (representing named relationship between source and target note)</d
<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="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line136">line 136</a> <a href="becca_entities_attribute.js.html">becca/entities/attribute.js</a>, <a href="becca_entities_attribute.js.html#line137">line 137</a>
</li></ul></dd> </li></ul></dd>
@@ -1144,7 +1741,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -1237,7 +1834,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -155,6 +155,69 @@ parents.</div>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="branchId"><span class="type-signature"></span>branchId<span class="type-signature"> :string</span></h4> <h4 class="name" id="branchId"><span class="type-signature"></span>branchId<span class="type-signature"> :string</span></h4>
@@ -751,6 +814,184 @@ parents.</div>
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
@@ -955,6 +1196,362 @@ parents.</div>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -1084,7 +1681,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -1177,7 +1774,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -160,6 +160,69 @@ from tokenHash and token.</div>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="etapiTokenId"><span class="type-signature"></span>etapiTokenId<span class="type-signature"> :string</span></h4> <h4 class="name" id="etapiTokenId"><span class="type-signature"></span>etapiTokenId<span class="type-signature"> :string</span></h4>
@@ -572,6 +635,540 @@ from tokenHash and token.</div>
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -701,7 +1298,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -794,7 +1391,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

File diff suppressed because it is too large Load Diff

View File

@@ -155,6 +155,69 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="contentLength"><span class="type-signature"></span>contentLength<span class="type-signature"> :number</span></h4> <h4 class="name" id="contentLength"><span class="type-signature"></span>contentLength<span class="type-signature"> :number</span></h4>
@@ -975,6 +1038,362 @@ It's used for seamless note versioning.</div>
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
@@ -1179,6 +1598,184 @@ It's used for seamless note versioning.</div>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -1414,7 +2011,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -1507,7 +2104,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -154,6 +154,69 @@
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="isSynced"><span class="type-signature"></span>isSynced<span class="type-signature"> :boolean</span></h4> <h4 class="name" id="isSynced"><span class="type-signature"></span>isSynced<span class="type-signature"> :boolean</span></h4>
@@ -430,6 +493,540 @@
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -559,7 +1156,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -652,7 +1249,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -154,6 +154,69 @@
<h4 class="name" id="becca"><span class="type-signature">(protected) </span>becca<span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#becca">AbstractEntity#becca</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line50">line 50</a>
</li></ul></dd>
</dl>
<h4 class="name" id="noteId"><span class="type-signature"></span>noteId<span class="type-signature"> :string</span></h4> <h4 class="name" id="noteId"><span class="type-signature"></span>noteId<span class="type-signature"> :string</span></h4>
@@ -362,6 +425,540 @@
<h3 class="subsection-title">Methods</h3> <h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addEntityChange"><span class="type-signature">(protected) </span>addEntityChange<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#addEntityChange">AbstractEntity#addEntityChange</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line59">line 59</a>
</li></ul></dd>
</dl>
<h4 class="name" id="beforeSaving"><span class="type-signature">(protected) </span>beforeSaving<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#beforeSaving">AbstractEntity#beforeSaving</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line18">line 18</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateHash"><span class="type-signature">(protected) </span>generateHash<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateHash">AbstractEntity#generateHash</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line30">line 30</a>
</li></ul></dd>
</dl>
<h4 class="name" id="generateIdIfNecessary"><span class="type-signature">(protected) </span>generateIdIfNecessary<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#generateIdIfNecessary">AbstractEntity#generateIdIfNecessary</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getPojoToSave"><span class="type-signature">(protected) </span>getPojoToSave<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getPojoToSave">AbstractEntity#getPojoToSave</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
<h4 class="name" id="getUtcDateChanged"><span class="type-signature">(protected) </span>getUtcDateChanged<span class="signature">()</span><span class="type-signature"></span></h4>
<dl class="details">
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides"><ul class="dummy"><li>
<a href="AbstractEntity.html#getUtcDateChanged">AbstractEntity#getUtcDateChanged</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line45">line 45</a>
</li></ul></dd>
</dl>
@@ -491,7 +1088,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line118">line 118</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line125">line 125</a>
</li></ul></dd> </li></ul></dd>
@@ -584,7 +1181,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
<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="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line73">line 73</a> <a href="becca_entities_abstract_entity.js.html">becca/entities/abstract_entity.js</a>, <a href="becca_entities_abstract_entity.js.html#line80">line 80</a>
</li></ul></dd> </li></ul></dd>

View File

@@ -42,16 +42,19 @@ let becca = null;
* Base class for all backend entities. * Base class for all backend entities.
*/ */
class AbstractEntity { class AbstractEntity {
/** @protected */
beforeSaving() { beforeSaving() {
this.generateIdIfNecessary(); this.generateIdIfNecessary();
} }
/** @protected */
generateIdIfNecessary() { generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) { if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId(); this[this.constructor.primaryKeyName] = utils.newEntityId();
} }
} }
/** @protected */
generateHash(isDeleted = false) { generateHash(isDeleted = false) {
let contentToHash = ""; let contentToHash = "";
@@ -66,10 +69,12 @@ class AbstractEntity {
return utils.hash(contentToHash).substr(0, 10); return utils.hash(contentToHash).substr(0, 10);
} }
/** @protected */
getUtcDateChanged() { getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated; return this.utcDateModified || this.utcDateCreated;
} }
/** @protected */
get becca() { get becca() {
if (!becca) { if (!becca) {
becca = require('../becca'); becca = require('../becca');
@@ -78,6 +83,7 @@ class AbstractEntity {
return becca; return becca;
} }
/** @protected */
addEntityChange(isDeleted = false) { addEntityChange(isDeleted = false) {
entityChangesService.addEntityChange({ entityChangesService.addEntityChange({
entityName: this.constructor.entityName, entityName: this.constructor.entityName,
@@ -89,6 +95,7 @@ class AbstractEntity {
}); });
} }
/** @protected */
getPojoToSave() { getPojoToSave() {
return this.getPojo(); return this.getPojo();
} }

View File

@@ -90,6 +90,7 @@ class Attribute extends AbstractEntity {
return this; return this;
} }
init() { init() {
if (this.attributeId) { if (this.attributeId) {
this.becca.attributes[this.attributeId] = this; this.becca.attributes[this.attributeId] = this;

View File

@@ -33,9 +33,9 @@ const AbstractEntity = require("./abstract_entity");
const sql = require("../../services/sql"); const sql = require("../../services/sql");
const dateUtils = require("../../services/date_utils"); const dateUtils = require("../../services/date_utils");
const utils = require("../../services/utils.js"); const utils = require("../../services/utils.js");
const TaskContext = require("../../services/task_context.js"); const TaskContext = require("../../services/task_context");
const cls = require("../../services/cls.js"); const cls = require("../../services/cls");
const log = require("../../services/log.js"); const log = require("../../services/log");
/** /**
* Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple * Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple
@@ -165,6 +165,18 @@ class Branch extends AbstractEntity {
taskContext.increaseProgressCount(); taskContext.increaseProgressCount();
const note = this.getNote();
if (!taskContext.noteDeletionHandlerTriggered) {
const parentBranches = note.getParentBranches();
if (parentBranches.length === 1 &amp;&amp; parentBranches[0] === this) {
// needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(note, 'runOnNoteDeletion', note);
}
}
if (this.branchId === 'root' if (this.branchId === 'root'
|| this.noteId === 'root' || this.noteId === 'root'
|| this.noteId === cls.getHoistedNoteId()) { || this.noteId === cls.getHoistedNoteId()) {
@@ -174,7 +186,6 @@ class Branch extends AbstractEntity {
this.markAsDeleted(deleteId); this.markAsDeleted(deleteId);
const note = this.getNote();
const notDeletedBranches = note.getParentBranches(); const notDeletedBranches = note.getParentBranches();
if (notDeletedBranches.length === 0) { if (notDeletedBranches.length === 0) {

View File

@@ -36,9 +36,10 @@ const dateUtils = require('../../services/date_utils');
const entityChangesService = require('../../services/entity_changes'); const entityChangesService = require('../../services/entity_changes');
const AbstractEntity = require("./abstract_entity"); const AbstractEntity = require("./abstract_entity");
const NoteRevision = require("./note_revision"); const NoteRevision = require("./note_revision");
const TaskContext = require("../../services/task_context.js"); const TaskContext = require("../../services/task_context");
const optionService = require("../../services/options.js"); const dayjs = require("dayjs");
const noteRevisionService = require("../../services/note_revisions.js"); const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const LABEL = 'label'; const LABEL = 'label';
const RELATION = 'relation'; const RELATION = 'relation';
@@ -114,13 +115,17 @@ class Note extends AbstractEntity {
} }
init() { init() {
/** @type {Branch[]} */ /** @type {Branch[]}
* @private */
this.parentBranches = []; this.parentBranches = [];
/** @type {Note[]} */ /** @type {Note[]}
* @private */
this.parents = []; this.parents = [];
/** @type {Note[]} */ /** @type {Note[]}
* @private*/
this.children = []; this.children = [];
/** @type {Attribute[]} */ /** @type {Attribute[]}
* @private */
this.ownedAttributes = []; this.ownedAttributes = [];
/** @type {Attribute[]|null} /** @type {Attribute[]|null}
@@ -130,7 +135,8 @@ class Note extends AbstractEntity {
* @private*/ * @private*/
this.inheritableAttributeCache = null; this.inheritableAttributeCache = null;
/** @type {Attribute[]} */ /** @type {Attribute[]}
* @private*/
this.targetRelations = []; this.targetRelations = [];
this.becca.addNote(this.noteId, this); this.becca.addNote(this.noteId, this);
@@ -144,16 +150,19 @@ class Note extends AbstractEntity {
/** /**
* size of the content in bytes * size of the content in bytes
* @type {int|null} * @type {int|null}
* @private
*/ */
this.contentSize = null; this.contentSize = null;
/** /**
* size of the content and note revision contents in bytes * size of the content and note revision contents in bytes
* @type {int|null} * @type {int|null}
* @private
*/ */
this.noteSize = null; this.noteSize = null;
/** /**
* number of note revisions for this note * number of note revisions for this note
* @type {int|null} * @type {int|null}
* @private
*/ */
this.revisionCount = null; this.revisionCount = null;
} }
@@ -255,6 +264,22 @@ class Note extends AbstractEntity {
WHERE noteId = ?`, [this.noteId]); WHERE noteId = ?`, [this.noteId]);
} }
get dateCreatedObj() {
return this.dateCreated === null ? null : dayjs(this.dateCreated);
}
get utcDateCreatedObj() {
return this.utcDateCreated === null ? null : dayjs.utc(this.utcDateCreated);
}
get dateModifiedObj() {
return this.dateModified === null ? null : dayjs(this.dateModified);
}
get utcDateModifiedObj() {
return this.utcDateModified === null ? null : dayjs.utc(this.utcDateModified);
}
/** @returns {*} */ /** @returns {*} */
getJsonContent() { getJsonContent() {
const content = this.getContent(); const content = this.getContent();
@@ -380,6 +405,7 @@ class Note extends AbstractEntity {
} }
} }
/** @private */
__getAttributes(path) { __getAttributes(path) {
if (path.includes(this.noteId)) { if (path.includes(this.noteId)) {
return []; return [];
@@ -402,7 +428,11 @@ class Note extends AbstractEntity {
const templateNote = this.becca.notes[ownedAttr.value]; const templateNote = this.becca.notes[ownedAttr.value];
if (templateNote) { if (templateNote) {
templateAttributes.push(...templateNote.__getAttributes(newPath)); templateAttributes.push(
...templateNote.__getAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' &amp;&amp; attr.name === 'template'))
);
} }
} }
} }
@@ -431,7 +461,10 @@ class Note extends AbstractEntity {
return this.__attributeCache; return this.__attributeCache;
} }
/** @returns {Attribute[]} */ /**
* @private
* @returns {Attribute[]}
*/
__getInheritableAttributes(path) { __getInheritableAttributes(path) {
if (path.includes(this.noteId)) { if (path.includes(this.noteId)) {
return []; return [];
@@ -444,8 +477,12 @@ class Note extends AbstractEntity {
return this.inheritableAttributeCache; return this.inheritableAttributeCache;
} }
hasAttribute(type, name) { hasAttribute(type, name, value) {
return !!this.getAttributes().find(attr => attr.type === type &amp;&amp; attr.name === name); return !!this.getAttributes().find(attr =>
attr.type === type
&amp;&amp; attr.name === name
&amp;&amp; (value === undefined || value === null || attr.value === value)
);
} }
getAttributeCaseInsensitive(type, name, value) { getAttributeCaseInsensitive(type, name, value) {
@@ -466,27 +503,31 @@ class Note extends AbstractEntity {
/** /**
* @param {string} name - label name * @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (including inherited) * @returns {boolean} true if label exists (including inherited)
*/ */
hasLabel(name) { return this.hasAttribute(LABEL, name); } hasLabel(name, value) { return this.hasAttribute(LABEL, name, value); }
/** /**
* @param {string} name - label name * @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (excluding inherited) * @returns {boolean} true if label exists (excluding inherited)
*/ */
hasOwnedLabel(name) { return this.hasOwnedAttribute(LABEL, name); } hasOwnedLabel(name, value) { return this.hasOwnedAttribute(LABEL, name, value); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (including inherited) * @returns {boolean} true if relation exists (including inherited)
*/ */
hasRelation(name) { return this.hasAttribute(RELATION, name); } hasRelation(name, value) { return this.hasAttribute(RELATION, name, value); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (excluding inherited) * @returns {boolean} true if relation exists (excluding inherited)
*/ */
hasOwnedRelation(name) { return this.hasOwnedAttribute(RELATION, name); } hasOwnedRelation(name, value) { return this.hasOwnedAttribute(RELATION, name, value); }
/** /**
* @param {string} name - label name * @param {string} name - label name
@@ -539,10 +580,11 @@ class Note extends AbstractEntity {
/** /**
* @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
* @param {string} [value] - attribute value
* @returns {boolean} true if note has an attribute with given type and name (excluding inherited) * @returns {boolean} true if note has an attribute with given type and name (excluding inherited)
*/ */
hasOwnedAttribute(type, name) { hasOwnedAttribute(type, name, value) {
return !!this.getOwnedAttribute(type, name); return !!this.getOwnedAttribute(type, name, value);
} }
/** /**
@@ -629,15 +671,19 @@ class Note extends AbstractEntity {
/** /**
* @param {string} [type] - (optional) attribute type to filter * @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter * @param {string} [name] - (optional) attribute name to filter
* @param {string} [value] - (optional) attribute value to filter
* @returns {Attribute[]} note's "owned" attributes - excluding inherited ones * @returns {Attribute[]} note's "owned" attributes - excluding inherited ones
*/ */
getOwnedAttributes(type, name) { getOwnedAttributes(type, name, value) {
// it's a common mistake to include # or ~ into attribute name // it's a common mistake to include # or ~ into attribute name
if (name &amp;&amp; ["#", "~"].includes(name[0])) { if (name &amp;&amp; ["#", "~"].includes(name[0])) {
name = name.substr(1); name = name.substr(1);
} }
if (type &amp;&amp; name) { if (type &amp;&amp; name &amp;&amp; value !== undefined &amp;&amp; value !== null) {
return this.ownedAttributes.filter(attr => attr.type === type &amp;&amp; attr.name === name &amp;&amp; attr.value === value);
}
else if (type &amp;&amp; name) {
return this.ownedAttributes.filter(attr => attr.type === type &amp;&amp; attr.name === name); return this.ownedAttributes.filter(attr => attr.type === type &amp;&amp; attr.name === name);
} }
else if (type) { else if (type) {
@@ -656,8 +702,8 @@ class Note extends AbstractEntity {
* *
* This method can be significantly faster than the getAttribute() * This method can be significantly faster than the getAttribute()
*/ */
getOwnedAttribute(type, name) { getOwnedAttribute(type, name, value) {
const attrs = this.getOwnedAttributes(type, name); const attrs = this.getOwnedAttributes(type, name, value);
return attrs.length > 0 ? attrs[0] : null; return attrs.length > 0 ? attrs[0] : null;
} }
@@ -1163,6 +1209,10 @@ class Note extends AbstractEntity {
* @param {TaskContext} [taskContext] * @param {TaskContext} [taskContext]
*/ */
deleteNote(deleteId, taskContext) { deleteNote(deleteId, taskContext) {
if (this.isDeleted) {
return;
}
if (!deleteId) { if (!deleteId) {
deleteId = utils.randomString(10); deleteId = utils.randomString(10);
} }
@@ -1171,6 +1221,11 @@ class Note extends AbstractEntity {
taskContext = new TaskContext('no-progress-reporting'); taskContext = new TaskContext('no-progress-reporting');
} }
// needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
taskContext.noteDeletionHandlerTriggered = true;
for (const branch of this.getParentBranches()) { for (const branch of this.getParentBranches()) {
branch.deleteBranch(deleteId, taskContext); branch.deleteBranch(deleteId, taskContext);
} }
@@ -1212,7 +1267,7 @@ class Note extends AbstractEntity {
title: this.title, title: this.title,
type: this.type, type: this.type,
mime: this.mime, mime: this.mime,
isProtected: false, // will be fixed in the protectNoteRevisions() call isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified ? this.utcDateModified
: contentMetadata.utcDateModified, : contentMetadata.utcDateModified,

View File

@@ -270,9 +270,9 @@ function transactional(func) {
return ret; return ret;
} }
catch (e) { catch (e) {
const entityChanges = cls.getAndClearEntityChangeIds(); const entityChangeIds = cls.getAndClearEntityChangeIds();
if (entityChanges.length > 0) { if (entityChangeIds.length > 0) {
log.info("Transaction rollback dirtied the becca, forcing reload."); log.info("Transaction rollback dirtied the becca, forcing reload.");
require('../becca/becca_loader').load(); require('../becca/becca_loader').load();

View File

@@ -742,7 +742,7 @@ and relation (representing named relationship between source and target note)</d
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -1056,7 +1056,7 @@ parents.</div>
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -8009,7 +8009,7 @@ Typical use case is when new note has been created, we should wait until it is s
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -775,7 +775,7 @@
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -167,7 +167,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line28">line 28</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>
@@ -267,7 +267,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line38">line 38</a>
</li></ul></dd> </li></ul></dd>
@@ -335,7 +335,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line45">line 45</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>
@@ -403,7 +403,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line51">line 51</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line52">line 52</a>
</li></ul></dd> </li></ul></dd>
@@ -471,7 +471,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line62">line 62</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line63">line 63</a>
</li></ul></dd> </li></ul></dd>
@@ -543,7 +543,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line72">line 72</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line73">line 73</a>
</li></ul></dd> </li></ul></dd>
@@ -611,7 +611,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line58">line 58</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line59">line 59</a>
</li></ul></dd> </li></ul></dd>
@@ -679,7 +679,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line43">line 43</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line44">line 44</a>
</li></ul></dd> </li></ul></dd>
@@ -747,7 +747,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line48">line 48</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line49">line 49</a>
</li></ul></dd> </li></ul></dd>
@@ -815,7 +815,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line40">line 40</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line41">line 41</a>
</li></ul></dd> </li></ul></dd>
@@ -883,7 +883,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line60">line 60</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line61">line 61</a>
</li></ul></dd> </li></ul></dd>
@@ -955,7 +955,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line67">line 67</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line68">line 68</a>
</li></ul></dd> </li></ul></dd>
@@ -1103,7 +1103,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line499">line 499</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line504">line 504</a>
</li></ul></dd> </li></ul></dd>
@@ -1303,7 +1303,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line237">line 237</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line238">line 238</a>
</li></ul></dd> </li></ul></dd>
@@ -1481,7 +1481,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line521">line 521</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line526">line 526</a>
</li></ul></dd> </li></ul></dd>
@@ -1589,7 +1589,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line162">line 162</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line163">line 163</a>
</li></ul></dd> </li></ul></dd>
@@ -1693,7 +1693,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line145">line 145</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line146">line 146</a>
</li></ul></dd> </li></ul></dd>
@@ -1795,7 +1795,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line172">line 172</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line173">line 173</a>
</li></ul></dd> </li></ul></dd>
@@ -1897,7 +1897,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line210">line 210</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line211">line 211</a>
</li></ul></dd> </li></ul></dd>
@@ -1999,7 +1999,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line215">line 215</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>
@@ -2150,7 +2150,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line561">line 561</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line566">line 566</a>
</li></ul></dd> </li></ul></dd>
@@ -2317,7 +2317,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line385">line 385</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line390">line 390</a>
</li></ul></dd> </li></ul></dd>
@@ -2472,7 +2472,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line585">line 585</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line590">line 590</a>
</li></ul></dd> </li></ul></dd>
@@ -2582,7 +2582,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line707">line 707</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line717">line 717</a>
</li></ul></dd> </li></ul></dd>
@@ -2756,7 +2756,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line488">line 488</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line493">line 493</a>
</li></ul></dd> </li></ul></dd>
@@ -2956,7 +2956,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line224">line 224</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line225">line 225</a>
</li></ul></dd> </li></ul></dd>
@@ -3134,7 +3134,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line510">line 510</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line515">line 515</a>
</li></ul></dd> </li></ul></dd>
@@ -3289,7 +3289,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line555">line 555</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line560">line 560</a>
</li></ul></dd> </li></ul></dd>
@@ -3456,7 +3456,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line377">line 377</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line382">line 382</a>
</li></ul></dd> </li></ul></dd>
@@ -3611,7 +3611,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line579">line 579</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line584">line 584</a>
</li></ul></dd> </li></ul></dd>
@@ -3766,7 +3766,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line567">line 567</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line572">line 572</a>
</li></ul></dd> </li></ul></dd>
@@ -3933,7 +3933,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line453">line 453</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line458">line 458</a>
</li></ul></dd> </li></ul></dd>
@@ -4088,7 +4088,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line591">line 591</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line596">line 596</a>
</li></ul></dd> </li></ul></dd>
@@ -4194,7 +4194,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line153">line 153</a>
</li></ul></dd> </li></ul></dd>
@@ -4296,7 +4296,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line138">line 138</a>
</li></ul></dd> </li></ul></dd>
@@ -4398,7 +4398,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line180">line 180</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line181">line 181</a>
</li></ul></dd> </li></ul></dd>
@@ -4500,7 +4500,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line185">line 185</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line186">line 186</a>
</li></ul></dd> </li></ul></dd>
@@ -4651,7 +4651,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line573">line 573</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line578">line 578</a>
</li></ul></dd> </li></ul></dd>
@@ -4818,7 +4818,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line461">line 461</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line466">line 466</a>
</li></ul></dd> </li></ul></dd>
@@ -4973,7 +4973,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line603">line 603</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line608">line 608</a>
</li></ul></dd> </li></ul></dd>
@@ -5143,7 +5143,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line613">line 613</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line618">line 618</a>
</li></ul></dd> </li></ul></dd>
@@ -5294,7 +5294,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line597">line 597</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line602">line 602</a>
</li></ul></dd> </li></ul></dd>
@@ -5400,7 +5400,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line751">line 751</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line761">line 761</a>
</li></ul></dd> </li></ul></dd>
@@ -5513,7 +5513,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line686">line 686</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line696">line 696</a>
</li></ul></dd> </li></ul></dd>
@@ -5619,7 +5619,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line696">line 696</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line706">line 706</a>
</li></ul></dd> </li></ul></dd>
@@ -5721,7 +5721,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line627">line 627</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line632">line 632</a>
</li></ul></dd> </li></ul></dd>
@@ -5895,7 +5895,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line470">line 470</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line475">line 475</a>
</li></ul></dd> </li></ul></dd>
@@ -6001,7 +6001,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line167">line 167</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line168">line 168</a>
</li></ul></dd> </li></ul></dd>
@@ -6152,7 +6152,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line537">line 537</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line542">line 542</a>
</li></ul></dd> </li></ul></dd>
@@ -6330,7 +6330,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line479">line 479</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line484">line 484</a>
</li></ul></dd> </li></ul></dd>
@@ -6485,7 +6485,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line531">line 531</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line536">line 536</a>
</li></ul></dd> </li></ul></dd>
@@ -6640,7 +6640,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line543">line 543</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line548">line 548</a>
</li></ul></dd> </li></ul></dd>
@@ -6795,7 +6795,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line549">line 549</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line554">line 554</a>
</li></ul></dd> </li></ul></dd>
@@ -6903,7 +6903,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line679">line 679</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line689">line 689</a>
</li></ul></dd> </li></ul></dd>
@@ -6987,7 +6987,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line746">line 746</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line756">line 756</a>
</li></ul></dd> </li></ul></dd>
@@ -7093,7 +7093,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line738">line 738</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line748">line 748</a>
</li></ul></dd> </li></ul></dd>
@@ -7199,7 +7199,7 @@ This note's representation is used in note tree and is kept in Froca.</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#line110">line 110</a> <a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line111">line 111</a>
</li></ul></dd> </li></ul></dd>
@@ -7263,7 +7263,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -104,7 +104,7 @@ export default Attribute;
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -93,7 +93,7 @@ export default Branch;
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -76,7 +76,7 @@ export default NoteComplement;
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -45,7 +45,8 @@ const NOTE_TYPE_ICONS = {
"book": "bx bx-book", "book": "bx bx-book",
"note-map": "bx bx-map-alt", "note-map": "bx bx-map-alt",
"mermaid": "bx bx-selection", "mermaid": "bx bx-selection",
"canvas": "bx bx-pen" "canvas": "bx bx-pen",
"web-view": "bx bx-globe-alt"
}; };
/** /**
@@ -290,7 +291,11 @@ class NoteShort {
const templateNote = this.froca.notes[templateAttr.value]; const templateNote = this.froca.notes[templateAttr.value];
if (templateNote &amp;&amp; templateNote.noteId !== this.noteId) { if (templateNote &amp;&amp; templateNote.noteId !== this.noteId) {
attrArrs.push(templateNote.__getCachedAttributes(newPath)); attrArrs.push(
templateNote.__getCachedAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' &amp;&amp; attr.name === 'template'))
);
} }
} }
@@ -663,13 +668,18 @@ class NoteShort {
return []; return [];
} }
return this.getAttributes() const promotedAttrs = this.getAttributes()
.filter(attr => attr.isDefinition()) .filter(attr => attr.isDefinition())
.filter(attr => { .filter(attr => {
const def = attr.getDefinition(); const def = attr.getDefinition();
return def &amp;&amp; def.isPromoted; return def &amp;&amp; def.isPromoted;
}); });
// attrs are not resorted if position changes after initial load
promotedAttrs.sort((a, b) => a.position &lt; b.position ? -1 : 1);
return promotedAttrs;
} }
hasAncestor(ancestorNoteId, visitedNoteIds = null) { hasAncestor(ancestorNoteId, visitedNoteIds = null) {
@@ -843,7 +853,7 @@ export default NoteShort;
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -156,7 +156,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="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line34">line 34</a> <a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line37">line 37</a>
</li></ul></dd> </li></ul></dd>
@@ -425,7 +425,7 @@
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -50,7 +50,7 @@
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -635,7 +635,7 @@ export default FrontendScriptApi;
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

View File

@@ -37,6 +37,9 @@ const WIDGET_TPL = `
&lt;/div> &lt;/div>
&lt;/div>`; &lt;/div>`;
/**
* TODO: rename, it's not collapsible anymore
*/
export default class CollapsibleWidget extends NoteContextAwareWidget { export default class CollapsibleWidget extends NoteContextAwareWidget {
get widgetTitle() { return "Untitled widget"; } get widgetTitle() { return "Untitled widget"; }
@@ -60,10 +63,6 @@ export default class CollapsibleWidget extends NoteContextAwareWidget {
/** for overriding */ /** for overriding */
async doRenderBody() {} async doRenderBody() {}
isExpanded() {
return this.$bodyWrapper.hasClass("show");
}
} }
</code></pre> </code></pre>
</article> </article>
@@ -75,7 +74,7 @@ export default class CollapsibleWidget extends NoteContextAwareWidget {
</div> </div>
<nav> <nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Attribute.html">Attribute</a></li><li><a href="Branch.html">Branch</a></li><li><a href="FrontendScriptApi.html">FrontendScriptApi</a></li><li><a href="module.exports.html">exports</a></li><li><a href="NoteComplement.html">NoteComplement</a></li><li><a href="NoteShort.html">NoteShort</a></li></ul><h3>Global</h3><ul><li><a href="global.html#doRenderBody">doRenderBody</a></li></ul>
</nav> </nav>
<br class="clear"> <br class="clear">

512
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "trilium", "name": "trilium",
"version": "0.51.2", "version": "0.52.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "trilium", "name": "trilium",
"version": "0.51.2", "version": "0.52.3",
"hasInstallScript": true, "hasInstallScript": true,
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"dependencies": { "dependencies": {
@@ -21,7 +21,8 @@
"commonmark": "0.30.0", "commonmark": "0.30.0",
"cookie-parser": "1.4.6", "cookie-parser": "1.4.6",
"csurf": "1.11.0", "csurf": "1.11.0",
"dayjs": "1.11.2", "dayjs": "1.11.3",
"dayjs-plugin-utc": "^0.1.2",
"ejs": "3.1.8", "ejs": "3.1.8",
"electron-debug": "3.2.0", "electron-debug": "3.2.0",
"electron-dl": "3.3.1", "electron-dl": "3.3.1",
@@ -44,8 +45,8 @@
"joplin-turndown-plugin-gfm": "1.0.12", "joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "19.0.0", "jsdom": "19.0.0",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.4", "multer": "1.4.5-lts.1",
"node-abi": "3.21.0", "node-abi": "3.22.0",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"open": "8.4.0", "open": "8.4.0",
"portscanner": "2.2.0", "portscanner": "2.2.0",
@@ -65,7 +66,7 @@
"tmp": "0.2.1", "tmp": "0.2.1",
"turndown": "7.1.1", "turndown": "7.1.1",
"unescape": "1.0.1", "unescape": "1.0.1",
"ws": "8.6.0", "ws": "8.8.0",
"yauzl": "2.10.0" "yauzl": "2.10.0"
}, },
"bin": { "bin": {
@@ -78,12 +79,12 @@
"electron-packager": "15.5.1", "electron-packager": "15.5.1",
"electron-rebuild": "3.2.7", "electron-rebuild": "3.2.7",
"esm": "3.2.25", "esm": "3.2.25",
"jasmine": "4.1.0", "jasmine": "4.2.0",
"jsdoc": "3.6.10", "jsdoc": "3.6.10",
"lorem-ipsum": "2.0.4", "lorem-ipsum": "2.0.8",
"rcedit": "3.0.1", "rcedit": "3.0.1",
"webpack": "5.72.1", "webpack": "5.73.0",
"webpack-cli": "4.9.2" "webpack-cli": "4.10.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"electron-installer-debian": "3.1.0" "electron-installer-debian": "3.1.0"
@@ -1130,9 +1131,9 @@
} }
}, },
"node_modules/@webpack-cli/configtest": { "node_modules/@webpack-cli/configtest": {
"version": "1.1.1", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
"integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
"dev": true, "dev": true,
"peerDependencies": { "peerDependencies": {
"webpack": "4.x.x || 5.x.x", "webpack": "4.x.x || 5.x.x",
@@ -1140,9 +1141,9 @@
} }
}, },
"node_modules/@webpack-cli/info": { "node_modules/@webpack-cli/info": {
"version": "1.4.1", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
"integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"envinfo": "^7.7.3" "envinfo": "^7.7.3"
@@ -1152,9 +1153,9 @@
} }
}, },
"node_modules/@webpack-cli/serve": { "node_modules/@webpack-cli/serve": {
"version": "1.6.1", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
"integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
"dev": true, "dev": true,
"peerDependencies": { "peerDependencies": {
"webpack-cli": "4.x.x" "webpack-cli": "4.x.x"
@@ -2161,38 +2162,16 @@
} }
}, },
"node_modules/busboy": { "node_modules/busboy": {
"version": "0.2.14", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dependencies": { "dependencies": {
"dicer": "0.2.5", "streamsearch": "^1.1.0"
"readable-stream": "1.1.x"
}, },
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=10.16.0"
} }
}, },
"node_modules/busboy/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/busboy/node_modules/readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/busboy/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"node_modules/bytes": { "node_modules/bytes": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -3115,9 +3094,14 @@
} }
}, },
"node_modules/dayjs": { "node_modules/dayjs": {
"version": "1.11.2", "version": "1.11.3",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz",
"integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A=="
},
"node_modules/dayjs-plugin-utc": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dayjs-plugin-utc/-/dayjs-plugin-utc-0.1.2.tgz",
"integrity": "sha512-ExERH5o3oo6jFOdkvMP3gytTCQ9Ksi5PtylclJWghr7k7m3o2U5QrwtdiJkOxLOH4ghr0EKhpqGefzGz1VvVJg=="
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
@@ -3267,39 +3251,6 @@
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
"optional": true "optional": true
}, },
"node_modules/dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"dependencies": {
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/dicer/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/dicer/node_modules/readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/dicer/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"node_modules/dir-compare": { "node_modules/dir-compare": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz",
@@ -4728,47 +4679,6 @@
"node": ">=0.8.x" "node": ">=0.8.x"
} }
}, },
"node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.0",
"human-signals": "^2.1.0",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^4.0.1",
"onetime": "^5.1.2",
"signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/execa/node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/execa/node_modules/signal-exit": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz",
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==",
"dev": true
},
"node_modules/exif-parser": { "node_modules/exif-parser": {
"version": "0.1.12", "version": "0.1.12",
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
@@ -5917,15 +5827,6 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true,
"engines": {
"node": ">=10.17.0"
}
},
"node_modules/humanize-ms": { "node_modules/humanize-ms": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
@@ -6272,18 +6173,6 @@
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
}, },
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-svg": { "node_modules/is-svg": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.2.tgz", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.2.tgz",
@@ -6392,22 +6281,22 @@
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g=="
}, },
"node_modules/jasmine": { "node_modules/jasmine": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.2.0.tgz",
"integrity": "sha512-4VhjbUgwfNS9CBnUMoSWr9tdNgOoOhNIjAD8YRxTn+PmOf4qTSC0Uqhk66dWGnz2vJxtNIU0uBjiwnsp4Ud9VA==", "integrity": "sha512-6SQRXHs5O++mp52PkoJoi9zuLYqp1IaqepRNmAQn5rUBo9VUnckpkkXQQD5PAuCCVVB1ULDImvWYCPV/ZVnaGQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"glob": "^7.1.6", "glob": "^7.1.6",
"jasmine-core": "^4.1.0" "jasmine-core": "^4.2.0"
}, },
"bin": { "bin": {
"jasmine": "bin/jasmine.js" "jasmine": "bin/jasmine.js"
} }
}, },
"node_modules/jasmine-core": { "node_modules/jasmine-core": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.2.0.tgz",
"integrity": "sha512-8E8BiffCL8sBwK1zU9cbavLe8xpJAgOduSJ6N8PJVv8VosQ/nxVTuXj2kUeHxTlZBVvh24G19ga7xdiaxlceKg==", "integrity": "sha512-OcFpBrIhnbmb9wfI8cqPSJ50pv3Wg4/NSgoZIqHzIwO/2a9qivJWzv8hUvaREIMYYJBas6AvfXATFdVuzzCqVw==",
"dev": true "dev": true
}, },
"node_modules/jest-worker": { "node_modules/jest-worker": {
@@ -6910,12 +6799,12 @@
} }
}, },
"node_modules/lorem-ipsum": { "node_modules/lorem-ipsum": {
"version": "2.0.4", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.4.tgz", "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz",
"integrity": "sha512-TD+ERYfxjYiUfOyaKU6OH4euumNVeKoo3BxIhokb7bGmoCULsME48onF9NVxYK3CU1z9L5ALnkDkW8lIkHvMNQ==", "integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"commander": "^2.17.1" "commander": "^9.3.0"
}, },
"bin": { "bin": {
"lorem-ipsum": "dist/bin/lorem-ipsum.bin.js" "lorem-ipsum": "dist/bin/lorem-ipsum.bin.js"
@@ -6926,10 +6815,13 @@
} }
}, },
"node_modules/lorem-ipsum/node_modules/commander": { "node_modules/lorem-ipsum/node_modules/commander": {
"version": "2.20.3", "version": "9.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true "dev": true,
"engines": {
"node": "^12.20.0 || >=14"
}
}, },
"node_modules/lowercase-keys": { "node_modules/lowercase-keys": {
"version": "1.0.1", "version": "1.0.1",
@@ -7359,21 +7251,20 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}, },
"node_modules/multer": { "node_modules/multer": {
"version": "1.4.4", "version": "1.4.5-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
"integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
"dependencies": { "dependencies": {
"append-field": "^1.0.0", "append-field": "^1.0.0",
"busboy": "^0.2.11", "busboy": "^1.0.0",
"concat-stream": "^1.5.2", "concat-stream": "^1.5.2",
"mkdirp": "^0.5.4", "mkdirp": "^0.5.4",
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
"on-finished": "^2.3.0",
"type-is": "^1.6.4", "type-is": "^1.6.4",
"xtend": "^4.0.0" "xtend": "^4.0.0"
}, },
"engines": { "engines": {
"node": ">= 0.10.0" "node": ">= 6.0.0"
} }
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
@@ -7407,9 +7298,9 @@
"dev": true "dev": true
}, },
"node_modules/node-abi": { "node_modules/node-abi": {
"version": "3.21.0", "version": "3.22.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.21.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
"integrity": "sha512-0ChvtQmmNYzXju0fjG0Vfg72q2D8FxUhluvV9uqivtXsKblSekJE2juxfg+9HoSgqPMqCmVEC/GHHtGzi4xYTg==", "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
"dependencies": { "dependencies": {
"semver": "^7.3.5" "semver": "^7.3.5"
}, },
@@ -7652,18 +7543,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dev": true,
"dependencies": {
"path-key": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/npmlog": { "node_modules/npmlog": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
@@ -9463,11 +9342,11 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}, },
"node_modules/streamsearch": { "node_modules/streamsearch": {
"version": "0.1.2", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=10.0.0"
} }
}, },
"node_modules/string_decoder": { "node_modules/string_decoder": {
@@ -9516,15 +9395,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/strip-json-comments": { "node_modules/strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@@ -10252,9 +10122,9 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.72.1", "version": "5.73.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
"integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
@@ -10299,18 +10169,18 @@
} }
}, },
"node_modules/webpack-cli": { "node_modules/webpack-cli": {
"version": "4.9.2", "version": "4.10.0",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
"integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@discoveryjs/json-ext": "^0.5.0", "@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/configtest": "^1.1.1", "@webpack-cli/configtest": "^1.2.0",
"@webpack-cli/info": "^1.4.1", "@webpack-cli/info": "^1.5.0",
"@webpack-cli/serve": "^1.6.1", "@webpack-cli/serve": "^1.7.0",
"colorette": "^2.0.14", "colorette": "^2.0.14",
"commander": "^7.0.0", "commander": "^7.0.0",
"execa": "^5.0.0", "cross-spawn": "^7.0.3",
"fastest-levenshtein": "^1.0.12", "fastest-levenshtein": "^1.0.12",
"import-local": "^3.0.2", "import-local": "^3.0.2",
"interpret": "^2.2.0", "interpret": "^2.2.0",
@@ -10323,6 +10193,10 @@
"engines": { "engines": {
"node": ">=10.13.0" "node": ">=10.13.0"
}, },
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": { "peerDependencies": {
"webpack": "4.x.x || 5.x.x" "webpack": "4.x.x || 5.x.x"
}, },
@@ -10594,9 +10468,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.6.0", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },
@@ -11713,25 +11587,25 @@
} }
}, },
"@webpack-cli/configtest": { "@webpack-cli/configtest": {
"version": "1.1.1", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
"integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"@webpack-cli/info": { "@webpack-cli/info": {
"version": "1.4.1", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
"integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"envinfo": "^7.7.3" "envinfo": "^7.7.3"
} }
}, },
"@webpack-cli/serve": { "@webpack-cli/serve": {
"version": "1.6.1", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
"integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
@@ -12550,35 +12424,11 @@
} }
}, },
"busboy": { "busboy": {
"version": "0.2.14", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"requires": { "requires": {
"dicer": "0.2.5", "streamsearch": "^1.1.0"
"readable-stream": "1.1.x"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
} }
}, },
"bytes": { "bytes": {
@@ -13271,9 +13121,14 @@
} }
}, },
"dayjs": { "dayjs": {
"version": "1.11.2", "version": "1.11.3",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz",
"integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A=="
},
"dayjs-plugin-utc": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dayjs-plugin-utc/-/dayjs-plugin-utc-0.1.2.tgz",
"integrity": "sha512-ExERH5o3oo6jFOdkvMP3gytTCQ9Ksi5PtylclJWghr7k7m3o2U5QrwtdiJkOxLOH4ghr0EKhpqGefzGz1VvVJg=="
}, },
"debug": { "debug": {
"version": "4.3.4", "version": "4.3.4",
@@ -13383,38 +13238,6 @@
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
"optional": true "optional": true
}, },
"dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"dir-compare": { "dir-compare": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz",
@@ -14489,37 +14312,6 @@
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"dev": true "dev": true
}, },
"execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.0",
"human-signals": "^2.1.0",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^4.0.1",
"onetime": "^5.1.2",
"signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
},
"dependencies": {
"get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
"dev": true
},
"signal-exit": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz",
"integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==",
"dev": true
}
}
},
"exif-parser": { "exif-parser": {
"version": "0.1.12", "version": "0.1.12",
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
@@ -15417,12 +15209,6 @@
"debug": "4" "debug": "4"
} }
}, },
"human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true
},
"humanize-ms": { "humanize-ms": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
@@ -15675,12 +15461,6 @@
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
}, },
"is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true
},
"is-svg": { "is-svg": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.2.tgz", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.2.tgz",
@@ -15761,19 +15541,19 @@
} }
}, },
"jasmine": { "jasmine": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.2.0.tgz",
"integrity": "sha512-4VhjbUgwfNS9CBnUMoSWr9tdNgOoOhNIjAD8YRxTn+PmOf4qTSC0Uqhk66dWGnz2vJxtNIU0uBjiwnsp4Ud9VA==", "integrity": "sha512-6SQRXHs5O++mp52PkoJoi9zuLYqp1IaqepRNmAQn5rUBo9VUnckpkkXQQD5PAuCCVVB1ULDImvWYCPV/ZVnaGQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"glob": "^7.1.6", "glob": "^7.1.6",
"jasmine-core": "^4.1.0" "jasmine-core": "^4.2.0"
} }
}, },
"jasmine-core": { "jasmine-core": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.2.0.tgz",
"integrity": "sha512-8E8BiffCL8sBwK1zU9cbavLe8xpJAgOduSJ6N8PJVv8VosQ/nxVTuXj2kUeHxTlZBVvh24G19ga7xdiaxlceKg==", "integrity": "sha512-OcFpBrIhnbmb9wfI8cqPSJ50pv3Wg4/NSgoZIqHzIwO/2a9qivJWzv8hUvaREIMYYJBas6AvfXATFdVuzzCqVw==",
"dev": true "dev": true
}, },
"jest-worker": { "jest-worker": {
@@ -16187,18 +15967,18 @@
} }
}, },
"lorem-ipsum": { "lorem-ipsum": {
"version": "2.0.4", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.4.tgz", "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz",
"integrity": "sha512-TD+ERYfxjYiUfOyaKU6OH4euumNVeKoo3BxIhokb7bGmoCULsME48onF9NVxYK3CU1z9L5ALnkDkW8lIkHvMNQ==", "integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==",
"dev": true, "dev": true,
"requires": { "requires": {
"commander": "^2.17.1" "commander": "^9.3.0"
}, },
"dependencies": { "dependencies": {
"commander": { "commander": {
"version": "2.20.3", "version": "9.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true "dev": true
} }
} }
@@ -16530,16 +16310,15 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}, },
"multer": { "multer": {
"version": "1.4.4", "version": "1.4.5-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
"integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
"requires": { "requires": {
"append-field": "^1.0.0", "append-field": "^1.0.0",
"busboy": "^0.2.11", "busboy": "^1.0.0",
"concat-stream": "^1.5.2", "concat-stream": "^1.5.2",
"mkdirp": "^0.5.4", "mkdirp": "^0.5.4",
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
"on-finished": "^2.3.0",
"type-is": "^1.6.4", "type-is": "^1.6.4",
"xtend": "^4.0.0" "xtend": "^4.0.0"
} }
@@ -16566,9 +16345,9 @@
"dev": true "dev": true
}, },
"node-abi": { "node-abi": {
"version": "3.21.0", "version": "3.22.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.21.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
"integrity": "sha512-0ChvtQmmNYzXju0fjG0Vfg72q2D8FxUhluvV9uqivtXsKblSekJE2juxfg+9HoSgqPMqCmVEC/GHHtGzi4xYTg==", "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
"requires": { "requires": {
"semver": "^7.3.5" "semver": "^7.3.5"
} }
@@ -16758,15 +16537,6 @@
} }
} }
}, },
"npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dev": true,
"requires": {
"path-key": "^3.0.0"
}
},
"npmlog": { "npmlog": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
@@ -18169,9 +17939,9 @@
} }
}, },
"streamsearch": { "streamsearch": {
"version": "0.1.2", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
}, },
"string_decoder": { "string_decoder": {
"version": "1.1.1", "version": "1.1.1",
@@ -18210,12 +17980,6 @@
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"dev": true "dev": true
}, },
"strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true
},
"strip-json-comments": { "strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@@ -18776,9 +18540,9 @@
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
}, },
"webpack": { "webpack": {
"version": "5.72.1", "version": "5.73.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
"integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/eslint-scope": "^3.7.3", "@types/eslint-scope": "^3.7.3",
@@ -18808,18 +18572,18 @@
} }
}, },
"webpack-cli": { "webpack-cli": {
"version": "4.9.2", "version": "4.10.0",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
"integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@discoveryjs/json-ext": "^0.5.0", "@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/configtest": "^1.1.1", "@webpack-cli/configtest": "^1.2.0",
"@webpack-cli/info": "^1.4.1", "@webpack-cli/info": "^1.5.0",
"@webpack-cli/serve": "^1.6.1", "@webpack-cli/serve": "^1.7.0",
"colorette": "^2.0.14", "colorette": "^2.0.14",
"commander": "^7.0.0", "commander": "^7.0.0",
"execa": "^5.0.0", "cross-spawn": "^7.0.3",
"fastest-levenshtein": "^1.0.12", "fastest-levenshtein": "^1.0.12",
"import-local": "^3.0.2", "import-local": "^3.0.2",
"interpret": "^2.2.0", "interpret": "^2.2.0",
@@ -19028,9 +18792,9 @@
} }
}, },
"ws": { "ws": {
"version": "8.6.0", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
"requires": {} "requires": {}
}, },
"xdg-basedir": { "xdg-basedir": {

View File

@@ -2,7 +2,7 @@
"name": "trilium", "name": "trilium",
"productName": "Trilium Notes", "productName": "Trilium Notes",
"description": "Trilium Notes", "description": "Trilium Notes",
"version": "0.52.1-beta", "version": "0.53.0-beta",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"main": "electron.js", "main": "electron.js",
"bin": { "bin": {
@@ -36,7 +36,8 @@
"commonmark": "0.30.0", "commonmark": "0.30.0",
"cookie-parser": "1.4.6", "cookie-parser": "1.4.6",
"csurf": "1.11.0", "csurf": "1.11.0",
"dayjs": "1.11.2", "dayjs": "1.11.3",
"dayjs-plugin-utc": "^0.1.2",
"ejs": "3.1.8", "ejs": "3.1.8",
"electron-debug": "3.2.0", "electron-debug": "3.2.0",
"electron-dl": "3.3.1", "electron-dl": "3.3.1",
@@ -59,8 +60,8 @@
"joplin-turndown-plugin-gfm": "1.0.12", "joplin-turndown-plugin-gfm": "1.0.12",
"jsdom": "19.0.0", "jsdom": "19.0.0",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.4", "multer": "1.4.5-lts.1",
"node-abi": "3.21.0", "node-abi": "3.22.0",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"open": "8.4.0", "open": "8.4.0",
"portscanner": "2.2.0", "portscanner": "2.2.0",
@@ -80,7 +81,7 @@
"tmp": "0.2.1", "tmp": "0.2.1",
"turndown": "7.1.1", "turndown": "7.1.1",
"unescape": "1.0.1", "unescape": "1.0.1",
"ws": "8.6.0", "ws": "8.8.0",
"yauzl": "2.10.0" "yauzl": "2.10.0"
}, },
"devDependencies": { "devDependencies": {
@@ -90,12 +91,12 @@
"electron-packager": "15.5.1", "electron-packager": "15.5.1",
"electron-rebuild": "3.2.7", "electron-rebuild": "3.2.7",
"esm": "3.2.25", "esm": "3.2.25",
"jasmine": "4.1.0", "jasmine": "4.2.0",
"jsdoc": "3.6.10", "jsdoc": "3.6.10",
"lorem-ipsum": "2.0.4", "lorem-ipsum": "2.0.8",
"rcedit": "3.0.1", "rcedit": "3.0.1",
"webpack": "5.72.1", "webpack": "5.73.0",
"webpack-cli": "4.9.2" "webpack-cli": "4.10.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"electron-installer-debian": "3.1.0" "electron-installer-debian": "3.1.0"

View File

@@ -14,16 +14,19 @@ let becca = null;
* Base class for all backend entities. * Base class for all backend entities.
*/ */
class AbstractEntity { class AbstractEntity {
/** @protected */
beforeSaving() { beforeSaving() {
this.generateIdIfNecessary(); this.generateIdIfNecessary();
} }
/** @protected */
generateIdIfNecessary() { generateIdIfNecessary() {
if (!this[this.constructor.primaryKeyName]) { if (!this[this.constructor.primaryKeyName]) {
this[this.constructor.primaryKeyName] = utils.newEntityId(); this[this.constructor.primaryKeyName] = utils.newEntityId();
} }
} }
/** @protected */
generateHash(isDeleted = false) { generateHash(isDeleted = false) {
let contentToHash = ""; let contentToHash = "";
@@ -38,10 +41,12 @@ class AbstractEntity {
return utils.hash(contentToHash).substr(0, 10); return utils.hash(contentToHash).substr(0, 10);
} }
/** @protected */
getUtcDateChanged() { getUtcDateChanged() {
return this.utcDateModified || this.utcDateCreated; return this.utcDateModified || this.utcDateCreated;
} }
/** @protected */
get becca() { get becca() {
if (!becca) { if (!becca) {
becca = require('../becca'); becca = require('../becca');
@@ -50,6 +55,7 @@ class AbstractEntity {
return becca; return becca;
} }
/** @protected */
addEntityChange(isDeleted = false) { addEntityChange(isDeleted = false) {
entityChangesService.addEntityChange({ entityChangesService.addEntityChange({
entityName: this.constructor.entityName, entityName: this.constructor.entityName,
@@ -61,6 +67,7 @@ class AbstractEntity {
}); });
} }
/** @protected */
getPojoToSave() { getPojoToSave() {
return this.getPojo(); return this.getPojo();
} }

View File

@@ -62,6 +62,7 @@ class Attribute extends AbstractEntity {
return this; return this;
} }
init() { init() {
if (this.attributeId) { if (this.attributeId) {
this.becca.attributes[this.attributeId] = this; this.becca.attributes[this.attributeId] = this;

View File

@@ -9,7 +9,9 @@ const entityChangesService = require('../../services/entity_changes');
const AbstractEntity = require("./abstract_entity"); const AbstractEntity = require("./abstract_entity");
const NoteRevision = require("./note_revision"); const NoteRevision = require("./note_revision");
const TaskContext = require("../../services/task_context"); const TaskContext = require("../../services/task_context");
const handlers = require("../../services/handlers"); const dayjs = require("dayjs");
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
const LABEL = 'label'; const LABEL = 'label';
const RELATION = 'relation'; const RELATION = 'relation';
@@ -85,13 +87,17 @@ class Note extends AbstractEntity {
} }
init() { init() {
/** @type {Branch[]} */ /** @type {Branch[]}
* @private */
this.parentBranches = []; this.parentBranches = [];
/** @type {Note[]} */ /** @type {Note[]}
* @private */
this.parents = []; this.parents = [];
/** @type {Note[]} */ /** @type {Note[]}
* @private*/
this.children = []; this.children = [];
/** @type {Attribute[]} */ /** @type {Attribute[]}
* @private */
this.ownedAttributes = []; this.ownedAttributes = [];
/** @type {Attribute[]|null} /** @type {Attribute[]|null}
@@ -101,7 +107,8 @@ class Note extends AbstractEntity {
* @private*/ * @private*/
this.inheritableAttributeCache = null; this.inheritableAttributeCache = null;
/** @type {Attribute[]} */ /** @type {Attribute[]}
* @private*/
this.targetRelations = []; this.targetRelations = [];
this.becca.addNote(this.noteId, this); this.becca.addNote(this.noteId, this);
@@ -115,16 +122,19 @@ class Note extends AbstractEntity {
/** /**
* size of the content in bytes * size of the content in bytes
* @type {int|null} * @type {int|null}
* @private
*/ */
this.contentSize = null; this.contentSize = null;
/** /**
* size of the content and note revision contents in bytes * size of the content and note revision contents in bytes
* @type {int|null} * @type {int|null}
* @private
*/ */
this.noteSize = null; this.noteSize = null;
/** /**
* number of note revisions for this note * number of note revisions for this note
* @type {int|null} * @type {int|null}
* @private
*/ */
this.revisionCount = null; this.revisionCount = null;
} }
@@ -226,6 +236,22 @@ class Note extends AbstractEntity {
WHERE noteId = ?`, [this.noteId]); WHERE noteId = ?`, [this.noteId]);
} }
get dateCreatedObj() {
return this.dateCreated === null ? null : dayjs(this.dateCreated);
}
get utcDateCreatedObj() {
return this.utcDateCreated === null ? null : dayjs.utc(this.utcDateCreated);
}
get dateModifiedObj() {
return this.dateModified === null ? null : dayjs(this.dateModified);
}
get utcDateModifiedObj() {
return this.utcDateModified === null ? null : dayjs.utc(this.utcDateModified);
}
/** @returns {*} */ /** @returns {*} */
getJsonContent() { getJsonContent() {
const content = this.getContent(); const content = this.getContent();
@@ -351,6 +377,7 @@ class Note extends AbstractEntity {
} }
} }
/** @private */
__getAttributes(path) { __getAttributes(path) {
if (path.includes(this.noteId)) { if (path.includes(this.noteId)) {
return []; return [];
@@ -373,7 +400,11 @@ class Note extends AbstractEntity {
const templateNote = this.becca.notes[ownedAttr.value]; const templateNote = this.becca.notes[ownedAttr.value];
if (templateNote) { if (templateNote) {
templateAttributes.push(...templateNote.__getAttributes(newPath)); templateAttributes.push(
...templateNote.__getAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' && attr.name === 'template'))
);
} }
} }
} }
@@ -402,7 +433,10 @@ class Note extends AbstractEntity {
return this.__attributeCache; return this.__attributeCache;
} }
/** @returns {Attribute[]} */ /**
* @private
* @returns {Attribute[]}
*/
__getInheritableAttributes(path) { __getInheritableAttributes(path) {
if (path.includes(this.noteId)) { if (path.includes(this.noteId)) {
return []; return [];
@@ -415,8 +449,18 @@ class Note extends AbstractEntity {
return this.inheritableAttributeCache; return this.inheritableAttributeCache;
} }
hasAttribute(type, name) { /**
return !!this.getAttributes().find(attr => attr.type === type && attr.name === name); * @param type
* @param name
* @param [value]
* @returns {boolean}
*/
hasAttribute(type, name, value) {
return !!this.getAttributes().find(attr =>
attr.type === type
&& attr.name === name
&& (value === undefined || value === null || attr.value === value)
);
} }
getAttributeCaseInsensitive(type, name, value) { getAttributeCaseInsensitive(type, name, value) {
@@ -437,27 +481,31 @@ class Note extends AbstractEntity {
/** /**
* @param {string} name - label name * @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (including inherited) * @returns {boolean} true if label exists (including inherited)
*/ */
hasLabel(name) { return this.hasAttribute(LABEL, name); } hasLabel(name, value) { return this.hasAttribute(LABEL, name, value); }
/** /**
* @param {string} name - label name * @param {string} name - label name
* @param {string} [value] - label value
* @returns {boolean} true if label exists (excluding inherited) * @returns {boolean} true if label exists (excluding inherited)
*/ */
hasOwnedLabel(name) { return this.hasOwnedAttribute(LABEL, name); } hasOwnedLabel(name, value) { return this.hasOwnedAttribute(LABEL, name, value); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (including inherited) * @returns {boolean} true if relation exists (including inherited)
*/ */
hasRelation(name) { return this.hasAttribute(RELATION, name); } hasRelation(name, value) { return this.hasAttribute(RELATION, name, value); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @param {string} [value] - relation value
* @returns {boolean} true if relation exists (excluding inherited) * @returns {boolean} true if relation exists (excluding inherited)
*/ */
hasOwnedRelation(name) { return this.hasOwnedAttribute(RELATION, name); } hasOwnedRelation(name, value) { return this.hasOwnedAttribute(RELATION, name, value); }
/** /**
* @param {string} name - label name * @param {string} name - label name
@@ -510,10 +558,11 @@ class Note extends AbstractEntity {
/** /**
* @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
* @param {string} [value] - attribute value
* @returns {boolean} true if note has an attribute with given type and name (excluding inherited) * @returns {boolean} true if note has an attribute with given type and name (excluding inherited)
*/ */
hasOwnedAttribute(type, name) { hasOwnedAttribute(type, name, value) {
return !!this.getOwnedAttribute(type, name); return !!this.getOwnedAttribute(type, name, value);
} }
/** /**
@@ -600,15 +649,19 @@ class Note extends AbstractEntity {
/** /**
* @param {string} [type] - (optional) attribute type to filter * @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter * @param {string} [name] - (optional) attribute name to filter
* @param {string} [value] - (optional) attribute value to filter
* @returns {Attribute[]} note's "owned" attributes - excluding inherited ones * @returns {Attribute[]} note's "owned" attributes - excluding inherited ones
*/ */
getOwnedAttributes(type, name) { getOwnedAttributes(type, name, value) {
// it's a common mistake to include # or ~ into attribute name // it's a common mistake to include # or ~ into attribute name
if (name && ["#", "~"].includes(name[0])) { if (name && ["#", "~"].includes(name[0])) {
name = name.substr(1); name = name.substr(1);
} }
if (type && name) { if (type && name && value !== undefined && value !== null) {
return this.ownedAttributes.filter(attr => attr.type === type && attr.name === name && attr.value === value);
}
else if (type && name) {
return this.ownedAttributes.filter(attr => attr.type === type && attr.name === name); return this.ownedAttributes.filter(attr => attr.type === type && attr.name === name);
} }
else if (type) { else if (type) {
@@ -627,8 +680,8 @@ class Note extends AbstractEntity {
* *
* This method can be significantly faster than the getAttribute() * This method can be significantly faster than the getAttribute()
*/ */
getOwnedAttribute(type, name) { getOwnedAttribute(type, name, value) {
const attrs = this.getOwnedAttributes(type, name); const attrs = this.getOwnedAttributes(type, name, value);
return attrs.length > 0 ? attrs[0] : null; return attrs.length > 0 ? attrs[0] : null;
} }
@@ -1134,6 +1187,10 @@ class Note extends AbstractEntity {
* @param {TaskContext} [taskContext] * @param {TaskContext} [taskContext]
*/ */
deleteNote(deleteId, taskContext) { deleteNote(deleteId, taskContext) {
if (this.isDeleted) {
return;
}
if (!deleteId) { if (!deleteId) {
deleteId = utils.randomString(10); deleteId = utils.randomString(10);
} }
@@ -1143,6 +1200,7 @@ class Note extends AbstractEntity {
} }
// needs to be run before branches and attributes are deleted and thus attached relations disappear // needs to be run before branches and attributes are deleted and thus attached relations disappear
const handlers = require("../../services/handlers");
handlers.runAttachedRelations(this, 'runOnNoteDeletion', this); handlers.runAttachedRelations(this, 'runOnNoteDeletion', this);
taskContext.noteDeletionHandlerTriggered = true; taskContext.noteDeletionHandlerTriggered = true;
@@ -1187,7 +1245,7 @@ class Note extends AbstractEntity {
title: this.title, title: this.title,
type: this.type, type: this.type,
mime: this.mime, mime: this.mime,
isProtected: false, // will be fixed in the protectNoteRevisions() call isProtected: this.isProtected,
utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified utcDateLastEdited: this.utcDateModified > contentMetadata.utcDateModified
? this.utcDateModified ? this.utcDateModified
: contentMetadata.utcDateModified, : contentMetadata.utcDateModified,

View File

@@ -52,13 +52,13 @@ if (utils.isElectron()) {
title: suggestion, title: suggestion,
command: "replaceMisspelling", command: "replaceMisspelling",
spellingSuggestion: suggestion, spellingSuggestion: suggestion,
uiIcon: "empty" uiIcon: "bx bx-empty"
}); });
} }
items.push({ items.push({
title: `Add "${params.misspelledWord}" to dictionary`, title: `Add "${params.misspelledWord}" to dictionary`,
uiIcon: "plus", uiIcon: "bx bx-plus",
handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord) handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
}); });
@@ -69,7 +69,7 @@ if (utils.isElectron()) {
items.push({ items.push({
enabled: editFlags.canCut && hasText, enabled: editFlags.canCut && hasText,
title: `Cut <kbd>${platformModifier}+X`, title: `Cut <kbd>${platformModifier}+X`,
uiIcon: "cut", uiIcon: "bx bx-cut",
handler: () => webContents.cut() handler: () => webContents.cut()
}); });
} }
@@ -78,7 +78,7 @@ if (utils.isElectron()) {
items.push({ items.push({
enabled: editFlags.canCopy && hasText, enabled: editFlags.canCopy && hasText,
title: `Copy <kbd>${platformModifier}+C`, title: `Copy <kbd>${platformModifier}+C`,
uiIcon: "copy", uiIcon: "bx bx-copy",
handler: () => webContents.copy() handler: () => webContents.copy()
}); });
} }
@@ -86,7 +86,7 @@ if (utils.isElectron()) {
if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === 'none') { if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === 'none') {
items.push({ items.push({
title: `Copy link`, title: `Copy link`,
uiIcon: "copy", uiIcon: "bx bx-copy",
handler: () => { handler: () => {
electron.clipboard.write({ electron.clipboard.write({
bookmark: params.linkText, bookmark: params.linkText,
@@ -100,7 +100,7 @@ if (utils.isElectron()) {
items.push({ items.push({
enabled: editFlags.canPaste, enabled: editFlags.canPaste,
title: `Paste <kbd>${platformModifier}+V`, title: `Paste <kbd>${platformModifier}+V`,
uiIcon: "paste", uiIcon: "bx bx-paste",
handler: () => webContents.paste() handler: () => webContents.paste()
}); });
} }
@@ -109,7 +109,7 @@ if (utils.isElectron()) {
items.push({ items.push({
enabled: editFlags.canPaste, enabled: editFlags.canPaste,
title: `Paste as plain text <kbd>${platformModifier}+Shift+V`, title: `Paste as plain text <kbd>${platformModifier}+Shift+V`,
uiIcon: "paste", uiIcon: "bx bx-paste",
handler: () => webContents.pasteAndMatchStyle() handler: () => webContents.pasteAndMatchStyle()
}); });
} }
@@ -122,7 +122,7 @@ if (utils.isElectron()) {
items.push({ items.push({
enabled: editFlags.canPaste, enabled: editFlags.canPaste,
title: `Search for "${shortenedSelection}" with DuckDuckGo`, title: `Search for "${shortenedSelection}" with DuckDuckGo`,
uiIcon: "search-alt", uiIcon: "bx bx-search-alt",
handler: () => electron.shell.openExternal(`https://duckduckgo.com/?q=${encodeURIComponent(params.selectionText)}`) handler: () => electron.shell.openExternal(`https://duckduckgo.com/?q=${encodeURIComponent(params.selectionText)}`)
}); });
} }

View File

@@ -1,24 +0,0 @@
import server from "../services/server.js";
import utils from "../services/utils.js";
const $dialog = $("#about-dialog");
const $appVersion = $("#app-version");
const $dbVersion = $("#db-version");
const $syncVersion = $("#sync-version");
const $buildDate = $("#build-date");
const $buildRevision = $("#build-revision");
const $dataDirectory = $("#data-directory");
export async function showDialog() {
const appInfo = await server.get('app-info');
$appVersion.text(appInfo.appVersion);
$dbVersion.text(appInfo.dbVersion);
$syncVersion.text(appInfo.syncVersion);
$buildDate.text(appInfo.buildDate);
$buildRevision.text(appInfo.buildRevision);
$buildRevision.attr('href', 'https://github.com/zadam/trilium/commit/' + appInfo.buildRevision);
$dataDirectory.text(appInfo.dataDirectory);
utils.openDialog($dialog);
}

View File

@@ -1,131 +0,0 @@
import treeService from '../services/tree.js';
import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
const $dialog = $("#add-link-dialog");
const $form = $("#add-link-form");
const $autoComplete = $("#add-link-note-autocomplete");
const $linkTitle = $("#link-title");
const $addLinkTitleSettings = $("#add-link-title-settings");
const $addLinkTitleRadios = $(".add-link-title-radios");
const $addLinkTitleFormGroup = $("#add-link-title-form-group");
/** @var TextTypeWidget */
let textTypeWidget;
export async function showDialog(widget, text = '') {
textTypeWidget = widget;
$addLinkTitleSettings.toggle(!textTypeWidget.hasSelection());
$addLinkTitleSettings.find('input[type=radio]').on('change', updateTitleSettingsVisibility);
// with selection hyper link is implied
if (textTypeWidget.hasSelection()) {
$addLinkTitleSettings.find("input[value='hyper-link']").prop("checked", true);
}
else {
$addLinkTitleSettings.find("input[value='reference-link']").prop("checked", true);
}
updateTitleSettingsVisibility();
utils.openDialog($dialog);
$autoComplete.val('');
$linkTitle.val('');
async function setDefaultLinkTitle(noteId) {
const noteTitle = await treeService.getNoteTitle(noteId);
$linkTitle.val(noteTitle);
}
noteAutocompleteService.initNoteAutocomplete($autoComplete, {
allowExternalLinks: true,
allowCreatingNotes: true
});
$autoComplete.on('autocomplete:noteselected', (event, suggestion, dataset) => {
if (!suggestion.notePath) {
return false;
}
updateTitleSettingsVisibility();
const noteId = treeService.getNoteIdFromNotePath(suggestion.notePath);
if (noteId) {
setDefaultLinkTitle(noteId);
}
});
$autoComplete.on('autocomplete:externallinkselected', (event, suggestion, dataset) => {
if (!suggestion.externalLink) {
return false;
}
updateTitleSettingsVisibility();
$linkTitle.val(suggestion.externalLink);
});
$autoComplete.on('autocomplete:cursorchanged', function(event, suggestion, dataset) {
if (suggestion.externalLink) {
$linkTitle.val(suggestion.externalLink)
}
else {
const noteId = treeService.getNoteIdFromNotePath(suggestion.notePath);
if (noteId) {
setDefaultLinkTitle(noteId);
}
}
});
if (text && text.trim()) {
noteAutocompleteService.setText($autoComplete, text);
}
else {
noteAutocompleteService.showRecentNotes($autoComplete);
}
$autoComplete
.trigger('focus')
.trigger('select'); // to be able to quickly remove entered text
}
function getLinkType() {
if ($autoComplete.getSelectedExternalLink()) {
return 'external-link';
}
return $addLinkTitleSettings.find('input[type=radio]:checked').val();
}
function updateTitleSettingsVisibility() {
const linkType = getLinkType();
$addLinkTitleFormGroup.toggle(linkType !== 'reference-link');
$addLinkTitleRadios.toggle(linkType !== 'external-link')
}
$form.on('submit', () => {
if ($autoComplete.getSelectedNotePath()) {
$dialog.modal('hide');
const linkTitle = getLinkType() === 'reference-link' ? null : $linkTitle.val();
textTypeWidget.addLink($autoComplete.getSelectedNotePath(), linkTitle);
}
else if ($autoComplete.getSelectedExternalLink()) {
$dialog.modal('hide');
textTypeWidget.addLink($autoComplete.getSelectedExternalLink(), $linkTitle.val());
}
else {
logError("No link to add.");
}
return false;
});

View File

@@ -1,28 +0,0 @@
import server from "../services/server.js";
import utils from "../services/utils.js";
const $dialog = $("#backend-log-dialog");
const $backendLogTextArea = $("#backend-log-textarea");
const $refreshBackendLog = $("#refresh-backend-log-button");
export async function showDialog() {
utils.openDialog($dialog);
load();
}
function scrollToBottom() {
$backendLogTextArea.scrollTop($backendLogTextArea[0].scrollHeight);
}
async function load() {
const backendLog = await server.get('backend-log');
$backendLogTextArea.text(backendLog);
scrollToBottom();
}
$refreshBackendLog.on('click', load);
$dialog.on('shown.bs.modal', scrollToBottom);

View File

@@ -1,59 +0,0 @@
import treeService from '../services/tree.js';
import server from '../services/server.js';
import froca from "../services/froca.js";
import toastService from "../services/toast.js";
import utils from "../services/utils.js";
const $dialog = $("#branch-prefix-dialog");
const $form = $("#branch-prefix-form");
const $treePrefixInput = $("#branch-prefix-input");
const $noteTitle = $('#branch-prefix-note-title');
let branchId;
export async function showDialog(notePath) {
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
if (!noteId || !parentNoteId) {
return;
}
branchId = await froca.getBranchId(parentNoteId, noteId);
const branch = froca.getBranch(branchId);
if (!branch || branch.noteId === 'root') {
return;
}
const parentNote = await froca.getNote(branch.parentNoteId);
if (parentNote.type === 'search') {
return;
}
utils.openDialog($dialog);
$treePrefixInput.val(branch.prefix);
const noteTitle = await treeService.getNoteTitle(noteId);
$noteTitle.text(" - " + noteTitle);
}
async function savePrefix() {
const prefix = $treePrefixInput.val();
await server.put('branches/' + branchId + '/set-prefix', { prefix: prefix });
$dialog.modal('hide');
toastService.showMessage("Branch prefix has been saved.");
}
$form.on('submit', () => {
savePrefix();
return false;
});
$dialog.on('shown.bs.modal', () => $treePrefixInput.trigger('focus'));

View File

@@ -1,73 +0,0 @@
import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
import treeService from "../services/tree.js";
import toastService from "../services/toast.js";
import froca from "../services/froca.js";
import branchService from "../services/branches.js";
import appContext from "../services/app_context.js";
const $dialog = $("#clone-to-dialog");
const $form = $("#clone-to-form");
const $noteAutoComplete = $("#clone-to-note-autocomplete");
const $clonePrefix = $("#clone-prefix");
const $noteList = $("#clone-to-note-list");
let clonedNoteIds;
export async function showDialog(noteIds) {
if (!noteIds || noteIds.length === 0) {
noteIds = [ appContext.tabManager.getActiveContextNoteId() ];
}
clonedNoteIds = [];
for (const noteId of noteIds) {
if (!clonedNoteIds.includes(noteId)) {
clonedNoteIds.push(noteId);
}
}
utils.openDialog($dialog);
$noteAutoComplete.val('').trigger('focus');
$noteList.empty();
for (const noteId of clonedNoteIds) {
const note = await froca.getNote(noteId);
$noteList.append($("<li>").text(note.title));
}
noteAutocompleteService.initNoteAutocomplete($noteAutoComplete);
noteAutocompleteService.showRecentNotes($noteAutoComplete);
}
async function cloneNotesTo(notePath) {
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
const targetBranchId = await froca.getBranchId(parentNoteId, noteId);
for (const cloneNoteId of clonedNoteIds) {
await branchService.cloneNoteToBranch(cloneNoteId, targetBranchId, $clonePrefix.val());
const clonedNote = await froca.getNote(cloneNoteId);
const targetNote = await froca.getBranch(targetBranchId).getNote();
toastService.showMessage(`Note "${clonedNote.title}" has been cloned into ${targetNote.title}`);
}
}
$form.on('submit', () => {
const notePath = $noteAutoComplete.getSelectedNotePath();
if (notePath) {
$dialog.modal('hide');
cloneNotesTo(notePath);
}
else {
logError("No path to clone to.");
}
return false;
});

View File

@@ -1,80 +0,0 @@
const $dialog = $("#confirm-dialog");
const $confirmContent = $("#confirm-dialog-content");
const $okButton = $("#confirm-dialog-ok-button");
const $cancelButton = $("#confirm-dialog-cancel-button");
const $custom = $("#confirm-dialog-custom");
const DELETE_NOTE_BUTTON_ID = "confirm-dialog-delete-note";
let resolve;
let $originallyFocused; // element focused before the dialog was opened so we can return to it afterwards
export function confirm(message) {
$originallyFocused = $(':focus');
$custom.hide();
glob.activeDialog = $dialog;
if (typeof message === 'string') {
message = $("<div>").text(message);
}
$confirmContent.empty().append(message);
$dialog.modal();
return new Promise((res, rej) => { resolve = res; });
}
export function confirmDeleteNoteBoxWithNote(title) {
glob.activeDialog = $dialog;
$confirmContent.text(`Are you sure you want to remove the note "${title}" from relation map?`);
$custom.empty()
.append("<br/>")
.append($("<div>").addClass("form-check")
.append($("<input>")
.attr("id", DELETE_NOTE_BUTTON_ID)
.attr("type", "checkbox")
.addClass("form-check-input"))
.append($("<label>")
.attr("for", DELETE_NOTE_BUTTON_ID)
.addClass("form-check-label")
.attr("style", "text-decoration: underline dotted black")
.attr("title", "If you don't check this, note will be only removed from relation map, but will stay as a note.")
.html("Also delete note")));
$custom.show();
$dialog.modal();
return new Promise((res, rej) => { resolve = res; });
}
export function isDeleteNoteChecked() {
return $("#" + DELETE_NOTE_BUTTON_ID + ":checked").length > 0;
}
$dialog.on('shown.bs.modal', () => $okButton.trigger("focus"));
$dialog.on("hidden.bs.modal", () => {
if (resolve) {
resolve(false);
}
if ($originallyFocused) {
$originallyFocused.trigger('focus');
$originallyFocused = null;
}
});
function doResolve(ret) {
resolve(ret);
resolve = null;
$dialog.modal("hide");
}
$cancelButton.on('click', () => doResolve(false));
$okButton.on('click', () => doResolve(true));

View File

@@ -1,99 +0,0 @@
import server from "../services/server.js";
import froca from "../services/froca.js";
import linkService from "../services/link.js";
import utils from "../services/utils.js";
const $dialog = $("#delete-notes-dialog");
const $okButton = $("#delete-notes-dialog-ok-button");
const $cancelButton = $("#delete-notes-dialog-cancel-button");
const $deleteNotesList = $("#delete-notes-list");
const $brokenRelationsList = $("#broken-relations-list");
const $deletedNotesCount = $("#deleted-notes-count");
const $noNoteToDeleteWrapper = $("#no-note-to-delete-wrapper");
const $deleteNotesListWrapper = $("#delete-notes-list-wrapper");
const $brokenRelationsListWrapper = $("#broken-relations-wrapper");
const $brokenRelationsCount = $("#broke-relations-count");
const $deleteAllClones = $("#delete-all-clones");
const $eraseNotes = $("#erase-notes");
let branchIds = null;
let resolve = null;
async function renderDeletePreview() {
const response = await server.post('delete-notes-preview', {
branchIdsToDelete: branchIds,
deleteAllClones: isDeleteAllClonesChecked()
});
$deleteNotesList.empty();
$brokenRelationsList.empty();
$deleteNotesListWrapper.toggle(response.noteIdsToBeDeleted.length > 0);
$noNoteToDeleteWrapper.toggle(response.noteIdsToBeDeleted.length === 0);
for (const note of await froca.getNotes(response.noteIdsToBeDeleted)) {
$deleteNotesList.append(
$("<li>").append(
await linkService.createNoteLink(note.noteId, {showNotePath: true})
)
);
}
$deletedNotesCount.text(response.noteIdsToBeDeleted.length);
$brokenRelationsListWrapper.toggle(response.brokenRelations.length > 0);
$brokenRelationsCount.text(response.brokenRelations.length);
await froca.getNotes(response.brokenRelations.map(br => br.noteId));
for (const attr of response.brokenRelations) {
$brokenRelationsList.append(
$("<li>")
.append(`Note `)
.append(await linkService.createNoteLink(attr.value))
.append(` (to be deleted) is referenced by relation <code>${attr.name}</code> originating from `)
.append(await linkService.createNoteLink(attr.noteId))
);
}
}
export async function showDialog(branchIdsToDelete) {
branchIds = branchIdsToDelete;
await renderDeletePreview();
utils.openDialog($dialog);
$deleteAllClones.prop("checked", false);
$eraseNotes.prop("checked", false);
return new Promise((res, rej) => resolve = res);
}
export function isDeleteAllClonesChecked() {
return $deleteAllClones.is(":checked");
}
export function isEraseNotesChecked() {
return $eraseNotes.is(":checked");
}
$dialog.on('shown.bs.modal', () => $okButton.trigger("focus"));
$cancelButton.on('click', () => {
utils.closeActiveDialog();
resolve({proceed: false});
});
$okButton.on('click', () => {
utils.closeActiveDialog();
resolve({
proceed: true,
deleteAllClones: isDeleteAllClonesChecked(),
eraseNotes: isEraseNotesChecked()
});
});
$deleteAllClones.on('click', () => renderDeletePreview());

View File

@@ -1,137 +0,0 @@
import treeService from "../services/tree.js";
import utils from "../services/utils.js";
import ws from "../services/ws.js";
import toastService from "../services/toast.js";
import froca from "../services/froca.js";
import openService from "../services/open.js";
const $dialog = $("#export-dialog");
const $form = $("#export-form");
const $noteTitle = $dialog.find(".export-note-title");
const $subtreeFormats = $("#export-subtree-formats");
const $singleFormats = $("#export-single-formats");
const $subtreeType = $("#export-type-subtree");
const $singleType = $("#export-type-single");
const $exportButton = $("#export-button");
const $opmlVersions = $("#opml-versions");
let taskId = '';
let branchId = null;
export async function showDialog(notePath, defaultType) {
// each opening of the dialog resets the taskId so we don't associate it with previous exports anymore
taskId = '';
$exportButton.removeAttr("disabled");
if (defaultType === 'subtree') {
$subtreeType.prop("checked", true).trigger('change');
// to show/hide OPML versions
$("input[name=export-subtree-format]:checked").trigger('change');
}
else if (defaultType === 'single') {
$singleType.prop("checked", true).trigger('change');
}
else {
throw new Error("Unrecognized type " + defaultType);
}
$("#opml-v2").prop("checked", true); // setting default
utils.openDialog($dialog);
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
branchId = await froca.getBranchId(parentNoteId, noteId);
const noteTitle = await treeService.getNoteTitle(noteId);
$noteTitle.html(noteTitle);
}
$form.on('submit', () => {
$dialog.modal('hide');
const exportType = $dialog.find("input[name='export-type']:checked").val();
if (!exportType) {
// this shouldn't happen as we always choose default export type
alert("Choose export type first please");
return;
}
const exportFormat = exportType === 'subtree'
? $("input[name=export-subtree-format]:checked").val()
: $("input[name=export-single-format]:checked").val();
const exportVersion = exportFormat === 'opml' ? $dialog.find("input[name='opml-version']:checked").val() : "1.0";
exportBranch(branchId, exportType, exportFormat, exportVersion);
return false;
});
function exportBranch(branchId, type, format, version) {
taskId = utils.randomString(10);
const url = openService.getUrlForDownload(`api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`);
openService.download(url);
}
$('input[name=export-type]').on('change', function () {
if (this.value === 'subtree') {
if ($("input[name=export-subtree-format]:checked").length === 0) {
$("input[name=export-subtree-format]:first").prop("checked", true);
}
$subtreeFormats.slideDown();
$singleFormats.slideUp();
}
else {
if ($("input[name=export-single-format]:checked").length === 0) {
$("input[name=export-single-format]:first").prop("checked", true);
}
$subtreeFormats.slideUp();
$singleFormats.slideDown();
}
});
$('input[name=export-subtree-format]').on('change', function () {
if (this.value === 'opml') {
$opmlVersions.slideDown();
}
else {
$opmlVersions.slideUp();
}
});
function makeToast(id, message) {
return {
id: id,
title: "Export status",
message: message,
icon: "arrow-square-up-right"
};
}
ws.subscribeToMessages(async message => {
if (message.taskType !== 'export') {
return;
}
if (message.type === 'taskError') {
toastService.closePersistent(message.taskId);
toastService.showError(message.message);
}
else if (message.type === 'taskProgressCount') {
toastService.showPersistent(makeToast(message.taskId, "Export in progress: " + message.progressCount));
}
else if (message.type === 'taskSucceeded') {
const toast = makeToast(message.taskId, "Export finished successfully.");
toast.closeAfter = 5000;
toastService.showPersistent(toast);
}
});

View File

@@ -1,7 +0,0 @@
import utils from "../services/utils.js";
const $dialog = $("#help-dialog");
export async function showDialog() {
utils.openDialog($dialog);
}

View File

@@ -1,76 +0,0 @@
import utils from '../services/utils.js';
import treeService from "../services/tree.js";
import importService from "../services/import.js";
import options from "../services/options.js";
const $dialog = $("#import-dialog");
const $form = $("#import-form");
const $noteTitle = $dialog.find(".import-note-title");
const $fileUploadInput = $("#import-file-upload-input");
const $importButton = $("#import-button");
const $safeImportCheckbox = $("#safe-import-checkbox");
const $shrinkImagesWrapper = $("shrink-images-wrapper");
const $shrinkImagesCheckbox = $("#shrink-images-checkbox");
const $textImportedAsTextCheckbox = $("#text-imported-as-text-checkbox");
const $codeImportedAsCodeCheckbox = $("#code-imported-as-code-checkbox");
const $explodeArchivesCheckbox = $("#explode-archives-checkbox");
const $replaceUnderscoresWithSpacesCheckbox = $("#replace-underscores-with-spaces-checkbox");
const $csrf = $("#import-csrf");
let parentNoteId = null;
export async function showDialog(noteId) {
$fileUploadInput.val('').trigger('change'); // to trigger Import button disabling listener below
$safeImportCheckbox.prop("checked", true);
$shrinkImagesCheckbox.prop("checked", options.is('compressImages'));
$textImportedAsTextCheckbox.prop("checked", true);
$codeImportedAsCodeCheckbox.prop("checked", true);
$explodeArchivesCheckbox.prop("checked", true);
$replaceUnderscoresWithSpacesCheckbox.prop("checked", true);
parentNoteId = noteId;
$noteTitle.text(await treeService.getNoteTitle(parentNoteId));
utils.openDialog($dialog);
}
$form.on('submit', () => {
// disabling so that import is not triggered again.
$importButton.attr("disabled", "disabled");
importIntoNote(parentNoteId);
return false;
});
async function importIntoNote(parentNoteId) {
const files = Array.from($fileUploadInput[0].files); // shallow copy since we're resetting the upload button below
const options = {
safeImport: boolToString($safeImportCheckbox),
shrinkImages: boolToString($shrinkImagesCheckbox),
textImportedAsText: boolToString($textImportedAsTextCheckbox),
codeImportedAsCode: boolToString($codeImportedAsCodeCheckbox),
explodeArchives: boolToString($explodeArchivesCheckbox),
replaceUnderscoresWithSpaces: boolToString($replaceUnderscoresWithSpacesCheckbox)
};
$dialog.modal('hide');
await importService.uploadFiles(parentNoteId, files, options);
}
function boolToString($el) {
return $el.is(":checked") ? "true" : "false";
}
$fileUploadInput.on('change', () => {
if ($fileUploadInput.val()) {
$importButton.removeAttr("disabled");
}
else {
$importButton.attr("disabled", "disabled");
}
});

View File

@@ -1,56 +0,0 @@
import treeService from '../services/tree.js';
import noteAutocompleteService from '../services/note_autocomplete.js';
import utils from "../services/utils.js";
import froca from "../services/froca.js";
const $dialog = $("#include-note-dialog");
const $form = $("#include-note-form");
const $autoComplete = $("#include-note-autocomplete");
/** @var TextTypeWidget */
let textTypeWidget;
export async function showDialog(widget) {
textTypeWidget = widget;
$autoComplete.val('');
utils.openDialog($dialog);
noteAutocompleteService.initNoteAutocomplete($autoComplete, {
hideGoToSelectedNoteButton: true,
allowCreatingNotes: true
});
noteAutocompleteService.showRecentNotes($autoComplete);
}
async function includeNote(notePath) {
const noteId = treeService.getNoteIdFromNotePath(notePath);
const note = await froca.getNote(noteId);
const boxSize = $("input[name='include-note-box-size']:checked").val();
if (note.type === 'image') {
// there's no benefit to use insert note functionlity for images
// so we'll just add an IMG tag
textTypeWidget.addImage(noteId);
}
else {
textTypeWidget.addIncludeNote(noteId, boxSize);
}
}
$form.on('submit', () => {
const notePath = $autoComplete.getSelectedNotePath();
if (notePath) {
$dialog.modal('hide');
includeNote(notePath);
}
else {
logError("No noteId to include.");
}
return false;
});

View File

@@ -1,33 +0,0 @@
import utils from "../services/utils.js";
const $dialog = $("#info-dialog");
const $infoContent = $("#info-dialog-content");
const $okButton = $("#info-dialog-ok-button");
let resolve;
let $originallyFocused; // element focused before the dialog was opened so we can return to it afterwards
export function info(message) {
$originallyFocused = $(':focus');
$infoContent.text(message);
utils.openDialog($dialog);
return new Promise((res, rej) => { resolve = res; });
}
$dialog.on('shown.bs.modal', () => $okButton.trigger("focus"));
$dialog.on("hidden.bs.modal", () => {
if (resolve) {
resolve();
}
if ($originallyFocused) {
$originallyFocused.trigger('focus');
$originallyFocused = null;
}
});
$okButton.on('click', () => $dialog.modal("hide"));

View File

@@ -1,60 +0,0 @@
import noteAutocompleteService from '../services/note_autocomplete.js';
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
const $dialog = $("#jump-to-note-dialog");
const $autoComplete = $("#jump-to-note-autocomplete");
const $showInFullTextButton = $("#show-in-full-text-button");
let lastOpenedTs = 0;
const KEEP_LAST_SEARCH_FOR_X_SECONDS = 120;
export async function showDialog() {
utils.openDialog($dialog);
noteAutocompleteService.initNoteAutocomplete($autoComplete, { hideGoToSelectedNoteButton: true })
// clear any event listener added in previous invocation of this function
.off('autocomplete:noteselected')
.on('autocomplete:noteselected', function(event, suggestion, dataset) {
if (!suggestion.notePath) {
return false;
}
appContext.tabManager.getActiveContext().setNote(suggestion.notePath);
});
// if you open the Jump To dialog soon after using it previously it can often mean that you
// actually want to search for the same thing (e.g. you opened the wrong note at first try)
// so we'll keep the content.
// if it's outside of this time limit then we assume it's a completely new search and show recent notes instead.
if (Date.now() - lastOpenedTs > KEEP_LAST_SEARCH_FOR_X_SECONDS * 1000) {
noteAutocompleteService.showRecentNotes($autoComplete);
}
else {
$autoComplete
// hack, the actual search value is stored in <pre> element next to the search input
// this is important because the search input value is replaced with the suggestion note's title
.autocomplete("val", $autoComplete.next().text())
.trigger('focus')
.trigger('select');
}
lastOpenedTs = Date.now();
}
function showInFullText(e) {
// stop from propagating upwards (dangerous especially with ctrl+enter executable javascript notes)
e.preventDefault();
e.stopPropagation();
const searchString = $autoComplete.val();
appContext.triggerCommand('searchNotes', {searchString});
$dialog.modal('hide');
}
$showInFullTextButton.on('click', showInFullText);
utils.bindElShortcut($dialog, 'ctrl+return', showInFullText);

View File

@@ -1,62 +0,0 @@
import libraryLoader from "../services/library_loader.js";
import toastService from "../services/toast.js";
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
const $dialog = $('#markdown-import-dialog');
const $importTextarea = $('#markdown-import-textarea');
const $importButton = $('#markdown-import-button');
async function convertMarkdownToHtml(text) {
await libraryLoader.requireLibrary(libraryLoader.COMMONMARK);
const reader = new commonmark.Parser();
const writer = new commonmark.HtmlRenderer();
const parsed = reader.parse(text);
const result = writer.render(parsed);
appContext.triggerCommand('executeWithTextEditor', {
callback: textEditor => {
const viewFragment = textEditor.data.processor.toView(result);
const modelFragment = textEditor.data.toModel(viewFragment);
textEditor.model.insertContent(modelFragment, textEditor.model.document.selection);
toastService.showMessage("Markdown content has been imported into the document.");
},
ntxId: this.ntxId
});
}
export async function importMarkdownInline() {
if (appContext.tabManager.getActiveContextNoteType() !== 'text') {
return;
}
if (utils.isElectron()) {
const {clipboard} = utils.dynamicRequire('electron');
const text = clipboard.readText();
convertMarkdownToHtml(text);
}
else {
utils.openDialog($dialog);
}
}
async function sendForm() {
const text = $importTextarea.val();
$dialog.modal('hide');
await convertMarkdownToHtml(text);
$importTextarea.val('');
}
$importButton.on('click', sendForm);
$dialog.on('shown.bs.modal', () => $importTextarea.trigger('focus'));
utils.bindElShortcut($dialog, 'ctrl+return', sendForm);

View File

@@ -1,58 +0,0 @@
import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
import toastService from "../services/toast.js";
import froca from "../services/froca.js";
import branchService from "../services/branches.js";
import treeService from "../services/tree.js";
const $dialog = $("#move-to-dialog");
const $form = $("#move-to-form");
const $noteAutoComplete = $("#move-to-note-autocomplete");
const $noteList = $("#move-to-note-list");
let movedBranchIds;
export async function showDialog(branchIds) {
movedBranchIds = branchIds;
utils.openDialog($dialog);
$noteAutoComplete.val('').trigger('focus');
$noteList.empty();
for (const branchId of movedBranchIds) {
const branch = froca.getBranch(branchId);
const note = await froca.getNote(branch.noteId);
$noteList.append($("<li>").text(note.title));
}
noteAutocompleteService.initNoteAutocomplete($noteAutoComplete);
noteAutocompleteService.showRecentNotes($noteAutoComplete);
}
async function moveNotesTo(parentBranchId) {
await branchService.moveToParentNote(movedBranchIds, parentBranchId);
const parentBranch = froca.getBranch(parentBranchId);
const parentNote = await parentBranch.getNote();
toastService.showMessage(`Selected notes have been moved into ${parentNote.title}`);
}
$form.on('submit', () => {
const notePath = $noteAutoComplete.getSelectedNotePath();
if (notePath) {
$dialog.modal('hide');
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
froca.getBranchId(parentNoteId, noteId).then(branchId => moveNotesTo(branchId));
}
else {
logError("No path to move to.");
}
return false;
});

View File

@@ -1,225 +0,0 @@
import utils from '../services/utils.js';
import server from '../services/server.js';
import toastService from "../services/toast.js";
import appContext from "../services/app_context.js";
import libraryLoader from "../services/library_loader.js";
import openService from "../services/open.js";
const $dialog = $("#note-revisions-dialog");
const $list = $("#note-revision-list");
const $listDropdown = $("#note-revision-list-dropdown");
const $content = $("#note-revision-content");
const $title = $("#note-revision-title");
const $titleButtons = $("#note-revision-title-buttons");
const $eraseAllRevisionsButton = $("#note-revisions-erase-all-revisions-button");
$listDropdown.dropdown();
$listDropdown.parent().on('hide.bs.dropdown', e => {
// prevent closing dropdown by clicking outside
if (e.clickEvent) {
e.preventDefault();
}
});
let revisionItems = [];
let note;
let noteRevisionId;
export async function showCurrentNoteRevisions() {
await showNoteRevisionsDialog(appContext.tabManager.getActiveContextNoteId());
}
export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
utils.openDialog($dialog);
await loadNoteRevisions(noteId, noteRevisionId);
}
async function loadNoteRevisions(noteId, noteRevId) {
$list.empty();
$content.empty();
$titleButtons.empty();
note = appContext.tabManager.getActiveContextNote();
revisionItems = await server.get(`notes/${noteId}/revisions`);
for (const item of revisionItems) {
$list.append(
$('<a class="dropdown-item" tabindex="0">')
.text(item.dateLastEdited.substr(0, 16) + ` (${item.contentLength} bytes)`)
.attr('data-note-revision-id', item.noteRevisionId)
.attr('title', 'This revision was last edited on ' + item.dateLastEdited)
);
}
$listDropdown.dropdown('show');
noteRevisionId = noteRevId;
if (revisionItems.length > 0) {
if (!noteRevisionId) {
noteRevisionId = revisionItems[0].noteRevisionId;
}
} else {
$title.text("No revisions for this note yet...");
noteRevisionId = null;
}
$eraseAllRevisionsButton.toggle(revisionItems.length > 0);
}
$dialog.on('shown.bs.modal', () => {
$list.find(`[data-note-revision-id="${noteRevisionId}"]`)
.trigger('focus');
});
async function setContentPane() {
const noteRevisionId = $list.find(".active").attr('data-note-revision-id');
const revisionItem = revisionItems.find(r => r.noteRevisionId === noteRevisionId);
$titleButtons.empty();
$content.empty();
$title.html(revisionItem.title);
const $restoreRevisionButton = $('<button class="btn btn-sm" type="button">Restore this revision</button>');
$restoreRevisionButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to restore this revision? This will overwrite current title/content of the note with this revision.';
if (await confirmDialog.confirm(text)) {
await server.put(`notes/${revisionItem.noteId}/restore-revision/${revisionItem.noteRevisionId}`);
$dialog.modal('hide');
toastService.showMessage('Note revision has been restored.');
}
});
const $eraseRevisionButton = $('<button class="btn btn-sm" type="button">Delete this revision</button>');
$eraseRevisionButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to delete this revision? This action will delete revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
loadNoteRevisions(revisionItem.noteId);
toastService.showMessage('Note revision has been deleted.');
}
});
$titleButtons
.append($restoreRevisionButton)
.append(' &nbsp; ')
.append($eraseRevisionButton)
.append(' &nbsp; ');
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
$downloadButton.on('click', () => openService.downloadNoteRevision(revisionItem.noteId, revisionItem.noteRevisionId));
$titleButtons.append($downloadButton);
const fullNoteRevision = await server.get(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
if (revisionItem.type === 'text') {
$content.html(fullNoteRevision.content);
if ($content.find('span.math-tex').length > 0) {
await libraryLoader.requireLibrary(libraryLoader.KATEX);
renderMathInElement($content[0], {trust: true});
}
}
else if (revisionItem.type === 'code') {
$content.html($("<pre>").text(fullNoteRevision.content));
}
else if (revisionItem.type === 'image') {
$content.html($("<img>")
// reason why we put this inline as base64 is that we do not want to let user to copy this
// as a URL to be used in a note. Instead if they copy and paste it into a note, it will be a uploaded as a new note
.attr("src", `data:${note.mime};base64,` + fullNoteRevision.content)
.css("max-width", "100%")
.css("max-height", "100%"));
}
else if (revisionItem.type === 'file') {
const $table = $("<table cellpadding='10'>")
.append($("<tr>").append(
$("<th>").text("MIME: "),
$("<td>").text(revisionItem.mime)
))
.append($("<tr>").append(
$("<th>").text("File size:"),
$("<td>").text(revisionItem.contentLength + " bytes")
));
if (fullNoteRevision.content) {
$table.append($("<tr>").append(
$('<td colspan="2">').append(
$('<div style="font-weight: bold;">').text("Preview:"),
$('<pre class="file-preview-content"></pre>')
.text(fullNoteRevision.content)
)
));
}
$content.html($table);
}
else if (revisionItem.type === 'canvas') {
/**
* FIXME: We load a font called Virgil.wof2, which originates from excalidraw.com
* REMOVE external dependency!!!! This is defined in the svg in defs.style
*/
const content = fullNoteRevision.content;
try {
const data = JSON.parse(content)
const svg = data.svg || "no svg present."
/**
* maxWidth: 100% use full width of container but do not enlarge!
* height:auto to ensure that height scales with width
*/
const $svgHtml = $(svg).css({maxWidth: "100%", height: "auto"});
$content.html($('<div>').append($svgHtml));
} catch(err) {
console.error("error parsing fullNoteRevision.content as JSON", fullNoteRevision.content, err);
$content.html($("<div>").text("Error parsing content. Please check console.error() for more details."));
}
}
else {
$content.text("Preview isn't available for this note type.");
}
}
$eraseAllRevisionsButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to delete all revisions of this note? This action will erase revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${note.noteId}/revisions`);
$dialog.modal('hide');
toastService.showMessage('Note revisions has been deleted.');
}
});
$list.on('click', '.dropdown-item', e => {
e.preventDefault();
return false;
});
$list.on('focus', '.dropdown-item', e => {
$list.find('.dropdown-item').each((i, el) => {
$(el).toggleClass('active', el === e.target);
});
setContentPane();
});

View File

@@ -1,40 +0,0 @@
import appContext from "../services/app_context.js";
import utils from "../services/utils.js";
const $dialog = $("#note-source-dialog");
const $noteSource = $("#note-source");
export async function showDialog() {
utils.openDialog($dialog);
const noteCompletement = await appContext.tabManager.getActiveContext().getNoteComplement();
$noteSource.text(formatHtml(noteCompletement.content));
}
function formatHtml(str) {
const div = document.createElement('div');
div.innerHTML = str.trim();
return formatNode(div, 0).innerHTML.trim();
}
function formatNode(node, level) {
const indentBefore = new Array(level++ + 1).join(' ');
const indentAfter = new Array(level - 1).join(' ');
let textNode;
for (let i = 0; i < node.children.length; i++) {
textNode = document.createTextNode('\n' + indentBefore);
node.insertBefore(textNode, node.children[i]);
formatNode(node.children[i], level);
if (node.lastElementChild === node.children[i]) {
textNode = document.createTextNode('\n' + indentAfter);
node.appendChild(textNode);
}
}
return node;
}

View File

@@ -1,34 +0,0 @@
"use strict";
import server from '../services/server.js';
import utils from "../services/utils.js";
const $dialog = $("#options-dialog");
export async function showDialog(openTab) {
const options = await server.get('options');
utils.openDialog($dialog);
(await Promise.all([
import('./options/appearance.js'),
import('./options/shortcuts.js'),
import('./options/code_notes.js'),
import('./options/password.js'),
import('./options/etapi.js'),
import('./options/backup.js'),
import('./options/sync.js'),
import('./options/other.js'),
import('./options/advanced.js')
]))
.map(m => new m.default)
.forEach(tab => {
if (tab.optionsLoaded) {
tab.optionsLoaded(options)
}
});
if (openTab) {
$(`.nav-link[href='#options-${openTab}']`).trigger("click");
}
}

View File

@@ -1,13 +0,0 @@
import utils from "../services/utils.js";
import appContext from "../services/app_context.js";
export function show() {
const $dialog = $("#password-not-set-dialog");
const $openPasswordOptionsButton = $("#open-password-options-button");
utils.openDialog($dialog);
$openPasswordOptionsButton.on("click", () => {
appContext.triggerCommand("showOptions", { openTab: 'password' });
});
}

View File

@@ -1,59 +0,0 @@
import utils from "../services/utils.js";
const $dialog = $("#prompt-dialog");
const $dialogBody = $dialog.find(".modal-body");
let $question;
let $answer;
const $form = $("#prompt-dialog-form");
let resolve;
let shownCb;
export function ask({ title, message, defaultValue, shown }) {
shownCb = shown;
$("#prompt-title").text(title || "Prompt");
$question = $("<label>")
.prop("for", "prompt-dialog-answer")
.text(message);
$answer = $("<input>")
.prop("type", "text")
.prop("id", "prompt-dialog-answer")
.addClass("form-control")
.val(defaultValue || "");
$dialogBody.empty().append(
$("<div>")
.addClass("form-group")
.append($question)
.append($answer));
utils.openDialog($dialog, false);
return new Promise((res, rej) => { resolve = res; });
}
$dialog.on('shown.bs.modal', () => {
if (shownCb) {
shownCb({ $dialog, $question, $answer, $form });
}
$answer.trigger('focus').select();
});
$dialog.on("hidden.bs.modal", () => {
if (resolve) {
resolve(null);
}
});
$form.on('submit', e => {
e.preventDefault();
resolve($answer.val());
$dialog.modal('hide');
});

View File

@@ -1,29 +0,0 @@
import protectedSessionService from "../services/protected_session.js";
import utils from "../services/utils.js";
const $dialog = $("#protected-session-password-dialog");
const $passwordForm = $dialog.find(".protected-session-password-form");
const $passwordInput = $dialog.find(".protected-session-password");
export function show() {
utils.openDialog($dialog);
$passwordInput.trigger('focus');
}
export function close() {
// this may fail if the dialog has not been previously opened (not sure if still true with Bootstrap modal)
try {
$dialog.modal('hide');
}
catch (e) {}
}
$passwordForm.on('submit', () => {
const password = $passwordInput.val();
$passwordInput.val("");
protectedSessionService.setupProtectedSession(password);
return false;
});

View File

@@ -1,112 +0,0 @@
import linkService from '../services/link.js';
import utils from '../services/utils.js';
import server from '../services/server.js';
import treeService from "../services/tree.js";
import froca from "../services/froca.js";
import appContext from "../services/app_context.js";
import hoistedNoteService from "../services/hoisted_note.js";
const $dialog = $("#recent-changes-dialog");
const $content = $("#recent-changes-content");
export async function showDialog(ancestorNoteId) {
utils.openDialog($dialog);
if (!ancestorNoteId) {
ancestorNoteId = hoistedNoteService.getHoistedNoteId();
}
const recentChangesRows = await server.get('recent-changes/' + ancestorNoteId);
// preload all notes into cache
await froca.getNotes(recentChangesRows.map(r => r.noteId), true);
$content.empty();
if (recentChangesRows.length === 0) {
$content.append("No changes yet ...");
}
const groupedByDate = groupByDate(recentChangesRows);
for (const [dateDay, dayChanges] of groupedByDate) {
const $changesList = $('<ul>');
const dayEl = $('<div>').append($('<b>').text(dateDay)).append($changesList);
for (const change of dayChanges) {
const formattedTime = change.date.substr(11, 5);
let $noteLink;
if (change.current_isDeleted) {
$noteLink = $("<span>").text(change.current_title);
if (change.canBeUndeleted) {
const $undeleteLink = $(`<a href="javascript:">`)
.text("undelete")
.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to undelete this note and its sub-notes?';
if (await confirmDialog.confirm(text)) {
await server.put(`notes/${change.noteId}/undelete`);
$dialog.modal('hide');
await froca.reloadNotes([change.noteId]);
appContext.tabManager.getActiveContext().setNote(change.noteId);
}
});
$noteLink
.append(' (')
.append($undeleteLink)
.append(')');
}
}
else {
const note = await froca.getNote(change.noteId);
const notePath = treeService.getSomeNotePath(note);
if (notePath) {
$noteLink = await linkService.createNoteLink(notePath, {
title: change.title,
showNotePath: true
});
}
else {
$noteLink = $("<span>").text(note.title);
}
}
$changesList.append($('<li>')
.append(
$("<span>")
.text(formattedTime)
.attr("title", change.date)
)
.append(' - ')
.append($noteLink));
}
$content.append(dayEl);
}
}
function groupByDate(rows) {
const groupedByDate = new Map();
for (const row of rows) {
const dateDay = row.date.substr(0, 10);
if (!groupedByDate.has(dateDay)) {
groupedByDate.set(dateDay, []);
}
groupedByDate.get(dateDay).push(row);
}
return groupedByDate;
}

View File

@@ -1,24 +0,0 @@
import server from "../services/server.js";
import utils from "../services/utils.js";
const $dialog = $("#sort-child-notes-dialog");
const $form = $("#sort-child-notes-form");
let parentNoteId = null;
$form.on('submit', async () => {
const sortBy = $form.find("input[name='sort-by']:checked").val();
const sortDirection = $form.find("input[name='sort-direction']:checked").val();
await server.put(`notes/${parentNoteId}/sort-children`, {sortBy, sortDirection});
utils.closeActiveDialog();
});
export async function showDialog(noteId) {
parentNoteId = noteId;
utils.openDialog($dialog);
$form.find('input:first').focus();
}

View File

@@ -17,7 +17,8 @@ const NOTE_TYPE_ICONS = {
"book": "bx bx-book", "book": "bx bx-book",
"note-map": "bx bx-map-alt", "note-map": "bx bx-map-alt",
"mermaid": "bx bx-selection", "mermaid": "bx bx-selection",
"canvas": "bx bx-pen" "canvas": "bx bx-pen",
"web-view": "bx bx-globe-alt"
}; };
/** /**
@@ -262,7 +263,11 @@ class NoteShort {
const templateNote = this.froca.notes[templateAttr.value]; const templateNote = this.froca.notes[templateAttr.value];
if (templateNote && templateNote.noteId !== this.noteId) { if (templateNote && templateNote.noteId !== this.noteId) {
attrArrs.push(templateNote.__getCachedAttributes(newPath)); attrArrs.push(
templateNote.__getCachedAttributes(newPath)
// template attr is used as a marker for templates, but it's not meant to be inherited
.filter(attr => !(attr.type === 'label' && attr.name === 'template'))
);
} }
} }
@@ -635,13 +640,18 @@ class NoteShort {
return []; return [];
} }
return this.getAttributes() const promotedAttrs = this.getAttributes()
.filter(attr => attr.isDefinition()) .filter(attr => attr.isDefinition())
.filter(attr => { .filter(attr => {
const def = attr.getDefinition(); const def = attr.getDefinition();
return def && def.isPromoted; return def && def.isPromoted;
}); });
// attrs are not resorted if position changes after initial load
promotedAttrs.sort((a, b) => a.position < b.position ? -1 : 1);
return promotedAttrs;
} }
hasAncestor(ancestorNoteId, visitedNoteIds = null) { hasAncestor(ancestorNoteId, visitedNoteIds = null) {

View File

@@ -49,6 +49,32 @@ import NoteWrapperWidget from "../widgets/note_wrapper.js";
import BacklinksWidget from "../widgets/backlinks.js"; import BacklinksWidget from "../widgets/backlinks.js";
import SharedInfoWidget from "../widgets/shared_info.js"; import SharedInfoWidget from "../widgets/shared_info.js";
import FindWidget from "../widgets/find.js"; import FindWidget from "../widgets/find.js";
import TocWidget from "../widgets/toc.js";
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
import AboutDialog from "../widgets/dialogs/about.js";
import NoteSourceDialog from "../widgets/dialogs/note_source.js";
import HelpDialog from "../widgets/dialogs/help.js";
import RecentChangesDialog from "../widgets/dialogs/recent_changes.js";
import BackendLogDialog from "../widgets/dialogs/backend_log.js";
import BranchPrefixDialog from "../widgets/dialogs/branch_prefix.js";
import SortChildNotesDialog from "../widgets/dialogs/sort_child_notes.js";
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
import IncludeNoteDialog from "../widgets/dialogs/include_note.js";
import NoteTypeChooserDialog from "../widgets/dialogs/note_type_chooser.js";
import JumpToNoteDialog from "../widgets/dialogs/jump_to_note.js";
import AddLinkDialog from "../widgets/dialogs/add_link.js";
import CloneToDialog from "../widgets/dialogs/clone_to.js";
import MoveToDialog from "../widgets/dialogs/move_to.js";
import ImportDialog from "../widgets/dialogs/import.js";
import ExportDialog from "../widgets/dialogs/export.js";
import MarkdownImportDialog from "../widgets/dialogs/markdown_import.js";
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
import NoteRevisionsDialog from "../widgets/dialogs/note_revisions.js";
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
import InfoDialog from "../widgets/dialogs/info.js";
import ConfirmDialog from "../widgets/dialogs/confirm.js";
import PromptDialog from "../widgets/dialogs/prompt.js";
import OptionsDialog from "../widgets/dialogs/options.js";
export default class DesktopLayout { export default class DesktopLayout {
constructor(customWidgets) { constructor(customWidgets) {
@@ -169,9 +195,35 @@ export default class DesktopLayout {
.child(...this.customWidgets.get('center-pane')) .child(...this.customWidgets.get('center-pane'))
) )
.child(new RightPaneContainer() .child(new RightPaneContainer()
.child(new TocWidget())
.child(...this.customWidgets.get('right-pane')) .child(...this.customWidgets.get('right-pane'))
) )
) )
); )
.child(new BulkActionsDialog())
.child(new AboutDialog())
.child(new NoteSourceDialog())
.child(new HelpDialog())
.child(new RecentChangesDialog())
.child(new BackendLogDialog())
.child(new BranchPrefixDialog())
.child(new SortChildNotesDialog())
.child(new PasswordNoteSetDialog())
.child(new IncludeNoteDialog())
.child(new NoteTypeChooserDialog())
.child(new JumpToNoteDialog())
.child(new AddLinkDialog())
.child(new CloneToDialog())
.child(new MoveToDialog())
.child(new ImportDialog())
.child(new ExportDialog())
.child(new MarkdownImportDialog())
.child(new ProtectedSessionPasswordDialog())
.child(new NoteRevisionsDialog())
.child(new DeleteNotesDialog())
.child(new InfoDialog())
.child(new ConfirmDialog())
.child(new PromptDialog())
.child(new OptionsDialog());
} }
} }

View File

@@ -8,6 +8,8 @@ import CloseDetailButtonWidget from "../widgets/mobile_widgets/close_detail_butt
import MobileDetailMenuWidget from "../widgets/mobile_widgets/mobile_detail_menu.js"; import MobileDetailMenuWidget from "../widgets/mobile_widgets/mobile_detail_menu.js";
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js"; import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
import ScrollingContainer from "../widgets/containers/scrolling_container.js"; import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
import ConfirmDialog from "../widgets/dialogs/confirm.js";
const MOBILE_CSS = ` const MOBILE_CSS = `
<style> <style>
@@ -128,6 +130,8 @@ export default class MobileLayout {
.css('padding', '5px 20px 10px 0') .css('padding', '5px 20px 10px 0')
) )
) )
); )
.child(new ProtectedSessionPasswordDialog())
.child(new ConfirmDialog());
} }
} }

View File

@@ -4,6 +4,7 @@ import toastService from "./toast.js";
import froca from "./froca.js"; import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js"; import hoistedNoteService from "./hoisted_note.js";
import ws from "./ws.js"; import ws from "./ws.js";
import appContext from "./app_context.js";
async function moveBeforeBranch(branchIdsToMove, beforeBranchId) { async function moveBeforeBranch(branchIdsToMove, beforeBranchId) {
branchIdsToMove = filterRootNote(branchIdsToMove); branchIdsToMove = filterRootNote(branchIdsToMove);
@@ -81,8 +82,8 @@ async function deleteNotes(branchIdsToDelete) {
deleteAllClones = false; deleteAllClones = false;
} }
else { else {
const deleteNotesDialog = await import("../dialogs/delete_notes.js"); ({proceed, deleteAllClones, eraseNotes} = await new Promise(res =>
({proceed, deleteAllClones, eraseNotes} = await deleteNotesDialog.showDialog(branchIdsToDelete)); appContext.triggerCommand('showDeleteNotesDialog', {branchIdsToDelete, callback: res})));
} }
if (!proceed) { if (!proceed) {

View File

@@ -0,0 +1,94 @@
import server from "./server.js";
import ws from "./ws.js";
import MoveNoteBulkAction from "../widgets/bulk_actions/note/move_note.js";
import DeleteNoteBulkAction from "../widgets/bulk_actions/note/delete_note.js";
import DeleteNoteRevisionsBulkAction from "../widgets/bulk_actions/note/delete_note_revisions.js";
import DeleteLabelBulkAction from "../widgets/bulk_actions/label/delete_label.js";
import DeleteRelationBulkAction from "../widgets/bulk_actions/relation/delete_relation.js";
import RenameLabelBulkAction from "../widgets/bulk_actions/label/rename_label.js";
import RenameRelationBulkAction from "../widgets/bulk_actions/relation/rename_relation.js";
import UpdateLabelValueBulkAction from "../widgets/bulk_actions/label/update_label_value.js";
import UpdateRelationTargetBulkAction from "../widgets/bulk_actions/relation/update_relation_target.js";
import ExecuteScriptBulkAction from "../widgets/bulk_actions/execute_script.js";
import AddLabelBulkAction from "../widgets/bulk_actions/label/add_label.js";
import AddRelationBulkAction from "../widgets/bulk_actions/relation/add_relation.js";
import RenameNoteBulkAction from "../widgets/bulk_actions/note/rename_note.js";
const ACTION_GROUPS = [
{
title: 'Labels',
actions: [AddLabelBulkAction, UpdateLabelValueBulkAction, RenameLabelBulkAction, DeleteLabelBulkAction]
},
{
title: 'Relations',
actions: [AddRelationBulkAction, UpdateRelationTargetBulkAction, RenameRelationBulkAction, DeleteRelationBulkAction]
},
{
title: 'Notes',
actions: [RenameNoteBulkAction, MoveNoteBulkAction, DeleteNoteBulkAction, DeleteNoteRevisionsBulkAction],
},
{
title: 'Other',
actions: [ExecuteScriptBulkAction]
}
];
const ACTION_CLASSES = [
RenameNoteBulkAction,
MoveNoteBulkAction,
DeleteNoteBulkAction,
DeleteNoteRevisionsBulkAction,
DeleteLabelBulkAction,
DeleteRelationBulkAction,
RenameLabelBulkAction,
RenameRelationBulkAction,
AddLabelBulkAction,
AddRelationBulkAction,
UpdateLabelValueBulkAction,
UpdateRelationTargetBulkAction,
ExecuteScriptBulkAction
];
async function addAction(noteId, actionName) {
await server.post(`notes/${noteId}/attributes`, {
type: 'label',
name: 'action',
value: JSON.stringify({
name: actionName
})
});
await ws.waitForMaxKnownEntityChangeId();
}
function parseActions(note) {
const actionLabels = note.getLabels('action');
return actionLabels.map(actionAttr => {
let actionDef;
try {
actionDef = JSON.parse(actionAttr.value);
} catch (e) {
logError(`Parsing of attribute: '${actionAttr.value}' failed with error: ${e.message}`);
return null;
}
const ActionClass = ACTION_CLASSES.find(actionClass => actionClass.actionName === actionDef.name);
if (!ActionClass) {
logError(`No action class for '${actionDef.name}' found.`);
return null;
}
return new ActionClass(actionAttr, actionDef);
})
.filter(action => !!action);
}
export default {
addAction,
parseActions,
ACTION_CLASSES,
ACTION_GROUPS
};

View File

@@ -82,7 +82,7 @@ class ContextMenu {
const $icon = $("<span>"); const $icon = $("<span>");
if (item.uiIcon) { if (item.uiIcon) {
$icon.addClass("bx bx-" + item.uiIcon); $icon.addClass(item.uiIcon);
} else { } else {
$icon.append("&nbsp;"); $icon.append("&nbsp;");
} }

View File

@@ -5,7 +5,6 @@ import server from "./server.js";
import appContext from "./app_context.js"; import appContext from "./app_context.js";
import Component from "../widgets/component.js"; import Component from "../widgets/component.js";
import toastService from "./toast.js"; import toastService from "./toast.js";
import noteCreateService from "./note_create.js";
import ws from "./ws.js"; import ws from "./ws.js";
import bundleService from "./bundle.js"; import bundleService from "./bundle.js";
@@ -19,18 +18,6 @@ export default class Entrypoints extends Component {
jQuery.hotkeys.options.filterContentEditable = false; jQuery.hotkeys.options.filterContentEditable = false;
jQuery.hotkeys.options.filterTextInputs = false; jQuery.hotkeys.options.filterTextInputs = false;
} }
$(document).on('click', "a[data-action='note-revision']", async event => {
const linkEl = $(event.target);
const noteId = linkEl.attr('data-note-path');
const noteRevisionId = linkEl.attr('data-note-revision-id');
const attributesDialog = await import("../dialogs/note_revisions.js");
attributesDialog.showNoteRevisionsDialog(noteId, noteRevisionId);
return false;
});
} }
openDevToolsCommand() { openDevToolsCommand() {

View File

@@ -23,11 +23,7 @@ function setupGlobs() {
window.glob.treeCache = froca; // compatibility for CKEditor builds for a while window.glob.treeCache = froca; // compatibility for CKEditor builds for a while
// for CKEditor integration (button on block toolbar) // for CKEditor integration (button on block toolbar)
window.glob.importMarkdownInline = async () => { window.glob.importMarkdownInline = async () => appContext.triggerCommand("importMarkdownInline");
const dialog = await import("../dialogs/markdown_import.js");
dialog.importMarkdownInline();
};
window.glob.SEARCH_HELP_TEXT = ` window.glob.SEARCH_HELP_TEXT = `
<strong>Search tips</strong> - also see <button class="btn btn-sm" type="button" data-help-page="Search">complete help on search</button> <strong>Search tips</strong> - also see <button class="btn btn-sm" type="button" data-help-page="Search">complete help on search</button>

View File

@@ -1,5 +1,6 @@
import appContext from "./app_context.js"; import appContext from "./app_context.js";
import treeService from "./tree.js"; import treeService from "./tree.js";
import dialogService from "../widgets/dialog.js";
function getHoistedNoteId() { function getHoistedNoteId() {
const activeNoteContext = appContext.tabManager.getActiveContext(); const activeNoteContext = appContext.tabManager.getActiveContext();
@@ -36,9 +37,7 @@ async function checkNoteAccess(notePath, noteContext) {
const hoistedNoteId = noteContext.hoistedNoteId; const hoistedNoteId = noteContext.hoistedNoteId;
if (!resolvedNotePath.includes(hoistedNoteId) && !resolvedNotePath.includes("hidden")) { if (!resolvedNotePath.includes(hoistedNoteId) && !resolvedNotePath.includes("hidden")) {
const confirmDialog = await import('../dialogs/confirm.js'); if (!await dialogService.confirm("Requested note is outside of hoisted note subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?")) {
if (!await confirmDialog.confirm("Requested note is outside of hoisted note subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?")) {
return false; return false;
} }

View File

@@ -6,9 +6,9 @@ function openContextMenu(notePath, e) {
x: e.pageX, x: e.pageX,
y: e.pageY, y: e.pageY,
items: [ items: [
{title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "empty"}, {title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "bx bx-empty"},
{title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "dock-right"}, {title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right"},
{title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "window-open"} {title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "bx bx-window-open"}
], ],
selectMenuItemHandler: ({command}) => { selectMenuItemHandler: ({command}) => {
if (command === 'openNoteInNewTab') { if (command === 'openNoteInNewTab') {

View File

@@ -140,7 +140,9 @@ function initNoteAutocomplete($el, options) {
appendTo: document.querySelector('body'), appendTo: document.querySelector('body'),
hint: false, hint: false,
autoselect: true, autoselect: true,
openOnFocus: true, // openOnFocus has to be false, otherwise re-focus (after return from note type chooser dialog) forces
// re-querying of the autocomplete source which then changes currently selected suggestion
openOnFocus: false,
minLength: 0, minLength: 0,
tabAutocomplete: false tabAutocomplete: false
}, [ }, [
@@ -170,9 +172,17 @@ function initNoteAutocomplete($el, options) {
} }
if (suggestion.action === 'create-note') { if (suggestion.action === 'create-note') {
const {success, noteType, templateNoteId} = await noteCreateService.chooseNoteType();
if (!success) {
return;
}
const {note} = await noteCreateService.createNote(suggestion.parentNoteId, { const {note} = await noteCreateService.createNote(suggestion.parentNoteId, {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: false activate: false,
type: noteType,
templateNoteId: templateNoteId
}); });
suggestion.notePath = treeService.getSomeNotePath(note); suggestion.notePath = treeService.getSomeNotePath(note);
@@ -261,7 +271,6 @@ function init() {
} }
export default { export default {
autocompleteSource,
autocompleteSourceForCKEditor, autocompleteSourceForCKEditor,
initNoteAutocomplete, initNoteAutocomplete,
showRecentNotes, showRecentNotes,

View File

@@ -43,7 +43,8 @@ async function createNote(parentNotePath, options = {}) {
content: options.content || "", content: options.content || "",
isProtected: options.isProtected, isProtected: options.isProtected,
type: options.type, type: options.type,
mime: options.mime mime: options.mime,
templateNoteId: options.templateNoteId
}); });
if (options.saveSelection) { if (options.saveSelection) {
@@ -74,6 +75,25 @@ async function createNote(parentNotePath, options = {}) {
}; };
} }
async function chooseNoteType() {
return new Promise(res => {
appContext.triggerCommand("chooseNoteType", {callback: res});
});
}
async function createNoteWithTypePrompt(parentNotePath, options = {}) {
const {success, noteType, templateNoteId} = await chooseNoteType();
if (!success) {
return;
}
options.type = noteType;
options.templateNoteId = templateNoteId;
return await createNote(parentNotePath, options);
}
/* If first element is heading, parse it out and use it as a new heading. */ /* If first element is heading, parse it out and use it as a new heading. */
function parseSelectedHtml(selectedHtml) { function parseSelectedHtml(selectedHtml) {
const dom = $.parseHTML(selectedHtml); const dom = $.parseHTML(selectedHtml);
@@ -105,5 +125,7 @@ async function duplicateSubtree(noteId, parentNotePath) {
export default { export default {
createNote, createNote,
duplicateSubtree createNoteWithTypePrompt,
duplicateSubtree,
chooseNoteType
}; };

View File

@@ -22,8 +22,7 @@ async function mouseEnterHandler() {
const $link = $(this); const $link = $(this);
if ($link.hasClass("no-tooltip-preview") if ($link.hasClass("no-tooltip-preview")
|| $link.hasClass("disabled") || $link.hasClass("disabled")) {
|| $link.attr("data-action") === 'note-revision') {
return; return;
} }

View File

@@ -0,0 +1,40 @@
import server from "./server.js";
import froca from "./froca.js";
async function getNoteTypeItems(command) {
const items = [
{ title: "Text", command: command, type: "text", uiIcon: "bx bx-note" },
{ title: "Code", command: command, type: "code", uiIcon: "bx bx-code" },
{ title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" },
{ title: "Relation Map", command: command, type: "relation-map", uiIcon: "bx bx-map-alt" },
{ title: "Note Map", command: command, type: "note-map", uiIcon: "bx bx-map-alt" },
{ title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" },
{ title: "Book", command: command, type: "book", uiIcon: "bx bx-book" },
{ title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" },
{ title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" },
{ title: "Web View", command: command, type: "web-view", uiIcon: "bx bx-globe-alt" },
];
const templateNoteIds = await server.get("search-templates");
const templateNotes = await froca.getNotes(templateNoteIds);
if (templateNotes.length > 0) {
items.push({ title: "----" });
for (const templateNote of templateNotes) {
items.push({
title: templateNote.title,
uiIcon: templateNote.getIcon(),
command: command,
type: templateNote.type,
templateNoteId: templateNote.noteId
});
}
}
return items;
}
export default {
getNoteTypeItems
}

View File

@@ -20,7 +20,7 @@ function enterProtectedSession() {
const dfd = $.Deferred(); const dfd = $.Deferred();
if (!options.is("isPasswordSet")) { if (!options.is("isPasswordSet")) {
import("../dialogs/password_not_set.js").then(dialog => dialog.show()); appContext.triggerCommand("showPasswordNotSet");
return dfd; return dfd;
} }
@@ -31,7 +31,7 @@ function enterProtectedSession() {
// using deferred instead of promise because it allows resolving from outside // using deferred instead of promise because it allows resolving from outside
protectedSessionDeferred = dfd; protectedSessionDeferred = dfd;
import("../dialogs/protected_session.js").then(dialog => dialog.show()); appContext.triggerCommand("showProtectedSessionPasswordDialog");
} }
return dfd.promise(); return dfd.promise();
@@ -61,13 +61,13 @@ ws.subscribeToMessages(async message => {
if (message.type === 'protectedSessionLogin') { if (message.type === 'protectedSessionLogin') {
await reloadData(); await reloadData();
await appContext.triggerEvent('frocaReloaded'); await appContext.triggerEvent('frocaReloaded');
appContext.triggerEvent('protectedSessionStarted'); appContext.triggerEvent('protectedSessionStarted');
if (protectedSessionDeferred !== null) { appContext.triggerCommand("closeProtectedSessionPasswordDialog");
import("../dialogs/protected_session.js").then(dialog => dialog.close());
if (protectedSessionDeferred !== null) {
protectedSessionDeferred.resolve(true); protectedSessionDeferred.resolve(true);
protectedSessionDeferred = null; protectedSessionDeferred = null;
} }

View File

@@ -8,35 +8,6 @@ import options from "./options.js";
import froca from "./froca.js"; import froca from "./froca.js";
export default class RootCommandExecutor extends Component { export default class RootCommandExecutor extends Component {
jumpToNoteCommand() {
import("../dialogs/jump_to_note.js").then(d => d.showDialog());
}
showRecentChangesCommand() {
import("../dialogs/recent_changes.js").then(d => d.showDialog());
}
showNoteRevisionsCommand() {
import("../dialogs/note_revisions.js").then(d => d.showCurrentNoteRevisions());
}
showNoteSourceCommand() {
import("../dialogs/note_source.js").then(d => d.showDialog());
}
pasteMarkdownIntoTextCommand() {
import("../dialogs/markdown_import.js").then(d => d.importMarkdownInline());
}
async editBranchPrefixCommand() {
const notePath = appContext.tabManager.getActiveContextNotePath();
if (notePath) {
const editBranchPrefixDialog = await import("../dialogs/branch_prefix.js");
editBranchPrefixDialog.showDialog(notePath);
}
}
editReadOnlyNoteCommand() { editReadOnlyNoteCommand() {
const noteContext = appContext.tabManager.getActiveContext(); const noteContext = appContext.tabManager.getActiveContext();
noteContext.readOnlyTemporarilyDisabled = true; noteContext.readOnlyTemporarilyDisabled = true;
@@ -44,24 +15,6 @@ export default class RootCommandExecutor extends Component {
appContext.triggerEvent("readOnlyTemporarilyDisabled", { noteContext }); appContext.triggerEvent("readOnlyTemporarilyDisabled", { noteContext });
} }
async cloneNoteIdsToCommand({noteIds}) {
const d = await import("../dialogs/clone_to.js");
d.showDialog(noteIds);
}
async moveBranchIdsToCommand({branchIds}) {
const d = await import("../dialogs/move_to.js");
d.showDialog(branchIds);
}
showOptionsCommand({openTab}) {
import("../dialogs/options.js").then(d => d.showDialog(openTab));
}
showHelpCommand() {
import("../dialogs/help.js").then(d => d.showDialog());
}
async showSQLConsoleCommand() { async showSQLConsoleCommand() {
const sqlConsoleNote = await dateNoteService.createSqlConsole(); const sqlConsoleNote = await dateNoteService.createSqlConsole();
@@ -90,10 +43,6 @@ export default class RootCommandExecutor extends Component {
this.searchNotesCommand({ancestorNoteId: noteId}); this.searchNotesCommand({ancestorNoteId: noteId});
} }
showBackendLogCommand() {
import("../dialogs/backend_log.js").then(d => d.showDialog());
}
openNoteExternallyCommand() { openNoteExternallyCommand() {
const noteId = appContext.tabManager.getActiveContextNoteId(); const noteId = appContext.tabManager.getActiveContextNoteId();

View File

@@ -4,6 +4,7 @@ import clipboard from './clipboard.js';
import noteCreateService from "./note_create.js"; import noteCreateService from "./note_create.js";
import contextMenu from "./context_menu.js"; import contextMenu from "./context_menu.js";
import appContext from "./app_context.js"; import appContext from "./app_context.js";
import noteTypesService from "./note_types.js";
class TreeContextMenu { class TreeContextMenu {
/** /**
@@ -24,20 +25,6 @@ class TreeContextMenu {
}) })
} }
getNoteTypeItems(command) {
return [
{ title: "Text", command: command, type: "text", uiIcon: "note" },
{ title: "Code", command: command, type: "code", uiIcon: "code" },
{ title: "Saved search", command: command, type: "search", uiIcon: "file-find" },
{ title: "Relation Map", command: command, type: "relation-map", uiIcon: "map-alt" },
{ title: "Note Map", command: command, type: "note-map", uiIcon: "map-alt" },
{ title: "Render HTML note", command: command, type: "render", uiIcon: "extension" },
{ title: "Book", command: command, type: "book", uiIcon: "book" },
{ title: "Mermaid diagram", command: command, type: "mermaid", uiIcon: "selection" },
{ title: "Canvas", command: command, type: "canvas", uiIcon: "pen" },
];
}
async getMenuItems() { async getMenuItems() {
const note = await froca.getNote(this.node.data.noteId); const note = await froca.getNote(this.node.data.noteId);
const branch = froca.getBranch(this.node.data.branchId); const branch = froca.getBranch(this.node.data.branchId);
@@ -57,58 +44,59 @@ class TreeContextMenu {
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch; const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
return [ return [
{ title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "empty", enabled: noSelectedNotes }, { title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes },
{ title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "dock-right", enabled: noSelectedNotes }, { title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "plus", { title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? this.getNoteTypeItems("insertNoteAfter") : null, items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes }, enabled: insertNoteAfterEnabled && noSelectedNotes },
{ title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "plus", { title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus",
items: notSearch ? this.getNoteTypeItems("insertChildNote") : null, items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes }, enabled: notSearch && noSelectedNotes },
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "trash", { title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash",
enabled: isNotRoot && !isHoisted && parentNotSearch }, enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: "----" }, { title: "----" },
{ title: 'Search in subtree <kbd data-command="searchInSubtree"></kbd>', command: "searchInSubtree", uiIcon: "search", { title: 'Search in subtree <kbd data-command="searchInSubtree"></kbd>', command: "searchInSubtree", uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes }, enabled: notSearch && noSelectedNotes },
isHoisted ? null : { title: 'Hoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "empty", enabled: noSelectedNotes && notSearch }, isHoisted ? null : { title: 'Hoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
!isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "door-open" }, !isHoisted || !isNotRoot ? null : { title: 'Unhoist note <kbd data-command="toggleNoteHoisting"></kbd>', command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: 'Edit branch prefix <kbd data-command="editBranchPrefix"></kbd>', command: "editBranchPrefix", uiIcon: "empty", { title: 'Edit branch prefix <kbd data-command="editBranchPrefix"></kbd>', command: "editBranchPrefix", uiIcon: "bx bx-empty",
enabled: isNotRoot && parentNotSearch && noSelectedNotes}, enabled: isNotRoot && parentNotSearch && noSelectedNotes},
{ title: "Advanced", uiIcon: "empty", enabled: true, items: [ { title: "Advanced", uiIcon: "bx bx-empty", enabled: true, items: [
{ title: 'Expand subtree <kbd data-command="expandSubtree"></kbd>', command: "expandSubtree", uiIcon: "expand", enabled: noSelectedNotes }, { title: 'Expand subtree <kbd data-command="expandSubtree"></kbd>', command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "collapse", enabled: noSelectedNotes }, { title: 'Collapse subtree <kbd data-command="collapseSubtree"></kbd>', command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: "Force note sync", command: "forceNoteSync", uiIcon: "refresh", enabled: noSelectedNotes }, { title: "Force note sync", command: "forceNoteSync", uiIcon: "bx bx-refresh", enabled: noSelectedNotes },
{ title: 'Sort by ... <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "empty", enabled: noSelectedNotes && notSearch }, { title: 'Sort by ... <kbd data-command="sortChildNotes"></kbd>', command: "sortChildNotes", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
{ title: 'Recent changes in subtree', command: "recentChangesInSubtree", uiIcon: "history", enabled: noSelectedNotes } { title: 'Recent changes in subtree', command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes }
] }, ] },
{ title: "----" }, { title: "----" },
{ title: "Protect subtree", command: "protectSubtree", uiIcon: "check-shield", enabled: noSelectedNotes }, { title: "Protect subtree", command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: "Unprotect subtree", command: "unprotectSubtree", uiIcon: "shield", enabled: noSelectedNotes }, { title: "Unprotect subtree", command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: "----" }, { title: "----" },
{ title: 'Copy / clone <kbd data-command="copyNotesToClipboard"></kbd>', command: "copyNotesToClipboard", uiIcon: "copy", { title: 'Copy / clone <kbd data-command="copyNotesToClipboard"></kbd>', command: "copyNotesToClipboard", uiIcon: "bx bx-copy",
enabled: isNotRoot && !isHoisted }, enabled: isNotRoot && !isHoisted },
{ title: 'Clone to ... <kbd data-command="cloneNotesTo"></kbd>', command: "cloneNotesTo", uiIcon: "empty", { title: 'Clone to ... <kbd data-command="cloneNotesTo"></kbd>', command: "cloneNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted }, enabled: isNotRoot && !isHoisted },
{ title: 'Cut <kbd data-command="cutNotesToClipboard"></kbd>', command: "cutNotesToClipboard", uiIcon: "cut", { title: 'Cut <kbd data-command="cutNotesToClipboard"></kbd>', command: "cutNotesToClipboard", uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch }, enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: 'Move to ... <kbd data-command="moveNotesTo"></kbd>', command: "moveNotesTo", uiIcon: "empty", { title: 'Move to ... <kbd data-command="moveNotesTo"></kbd>', command: "moveNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted && parentNotSearch }, enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: 'Paste into <kbd data-command="pasteNotesFromClipboard"></kbd>', command: "pasteNotesFromClipboard", uiIcon: "paste", { title: 'Paste into <kbd data-command="pasteNotesFromClipboard"></kbd>', command: "pasteNotesFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes }, enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes },
{ title: 'Paste after', command: "pasteNotesAfterFromClipboard", uiIcon: "paste", { title: 'Paste after', command: "pasteNotesAfterFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes }, enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes },
{ title: `Duplicate subtree <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "empty", { title: `Duplicate subtree <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
enabled: parentNotSearch && isNotRoot && !isHoisted }, enabled: parentNotSearch && isNotRoot && !isHoisted },
{ title: "----" }, { title: "----" },
{ title: "Export", command: "exportNote", uiIcon: "empty", { title: "Export", command: "exportNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes }, enabled: notSearch && noSelectedNotes },
{ title: "Import into note", command: "importIntoNote", uiIcon: "empty", { title: "Import into note", command: "importIntoNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes } enabled: notSearch && noSelectedNotes },
{ title: "Apply bulk actions", command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus",
enabled: true }
].filter(row => row !== null); ].filter(row => row !== null);
} }
async selectMenuItemHandler({command, type}) { async selectMenuItemHandler({command, type, templateNoteId}) {
const noteId = this.node.data.noteId;
const notePath = treeService.getNotePath(this.node); const notePath = treeService.getNotePath(this.node);
if (command === 'openInTab') { if (command === 'openInTab') {
@@ -122,7 +110,8 @@ class TreeContextMenu {
target: 'after', target: 'after',
targetBranchId: this.node.data.branchId, targetBranchId: this.node.data.branchId,
type: type, type: type,
isProtected: isProtected isProtected: isProtected,
templateNoteId: templateNoteId
}); });
} }
else if (command === "insertChildNote") { else if (command === "insertChildNote") {
@@ -130,7 +119,8 @@ class TreeContextMenu {
noteCreateService.createNote(parentNotePath, { noteCreateService.createNote(parentNotePath, {
type: type, type: type,
isProtected: this.node.data.isProtected isProtected: this.node.data.isProtected,
templateNoteId: templateNoteId
}); });
} }
else if (command === 'openNoteInSplit') { else if (command === 'openNoteInSplit') {
@@ -140,7 +130,12 @@ class TreeContextMenu {
this.treeWidget.triggerCommand("openNewNoteSplit", {ntxId, notePath}); this.treeWidget.triggerCommand("openNewNoteSplit", {ntxId, notePath});
} }
else { else {
this.treeWidget.triggerCommand(command, {node: this.node, notePath: notePath}); this.treeWidget.triggerCommand(command, {
node: this.node,
notePath: notePath,
selectedOrActiveBranchIds: this.treeWidget.getSelectedOrActiveBranchIds(this.node),
selectedOrActiveNoteIds: this.treeWidget.getSelectedOrActiveNoteIds(this.node)
});
} }
} }
} }

View File

@@ -280,7 +280,7 @@ function isHtmlEmpty(html) {
async function clearBrowserCache() { async function clearBrowserCache() {
if (isElectron()) { if (isElectron()) {
const win = utils.dynamicRequire('@electron/remote').getCurrentWindow(); const win = dynamicRequire('@electron/remote').getCurrentWindow();
await win.webContents.session.clearCache(); await win.webContents.session.clearCache();
} }
} }

View File

@@ -235,7 +235,7 @@ const ATTR_HELP = {
"runOnNoteChange": "executes when note is changed (includes note creation as well)", "runOnNoteChange": "executes when note is changed (includes note creation as well)",
"runOnNoteDeletion": "executes when note is being deleted", "runOnNoteDeletion": "executes when note is being deleted",
"runOnBranchCreation": "executes when a branch is created. Branch is a link between parent note and child note and is created e.g. when cloning or moving note.", "runOnBranchCreation": "executes when a branch is created. Branch is a link between parent note and child note and is created e.g. when cloning or moving note.",
"runOnBranchDeletion": "executes when a branch is delete. Branch is a link between parent note and child note and is deleted e.g. when moving note (old branch/link is deleted).", "runOnBranchDeletion": "executes when a branch is deleted. Branch is a link between parent note and child note and is deleted e.g. when moving note (old branch/link is deleted).",
"runOnChildNoteCreation": "executes when new note is created under this note", "runOnChildNoteCreation": "executes when new note is created under this note",
"runOnAttributeCreation": "executes when new attribute is created under this note", "runOnAttributeCreation": "executes when new attribute is created under this note",
"runOnAttributeChange": "executes when attribute is changed under this note", "runOnAttributeChange": "executes when attribute is changed under this note",

View File

@@ -217,11 +217,11 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
y: e.pageY, y: e.pageY,
orientation: 'left', orientation: 'left',
items: [ items: [
{title: `Add new label <kbd data-command="addNewLabel"></kbd>`, command: "addNewLabel", uiIcon: "hash"}, {title: `Add new label <kbd data-command="addNewLabel"></kbd>`, command: "addNewLabel", uiIcon: "bx bx-hash"},
{title: `Add new relation <kbd data-command="addNewRelation"></kbd>`, command: "addNewRelation", uiIcon: "transfer"}, {title: `Add new relation <kbd data-command="addNewRelation"></kbd>`, command: "addNewRelation", uiIcon: "bx bx-transfer"},
{title: "----"}, {title: "----"},
{title: "Add new label definition", command: "addNewLabelDefinition", uiIcon: "empty"}, {title: "Add new label definition", command: "addNewLabelDefinition", uiIcon: "bx bx-empty"},
{title: "Add new relation definition", command: "addNewRelationDefinition", uiIcon: "empty"}, {title: "Add new relation definition", command: "addNewRelationDefinition", uiIcon: "bx bx-empty"},
], ],
selectMenuItemHandler: ({command}) => this.handleAddNewAttributeCommand(command) selectMenuItemHandler: ({command}) => this.handleAddNewAttributeCommand(command)
}); });
@@ -468,6 +468,8 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
async renderOwnedAttributes(ownedAttributes, saved) { async renderOwnedAttributes(ownedAttributes, saved) {
ownedAttributes = ownedAttributes.filter(oa => !oa.isDeleted); ownedAttributes = ownedAttributes.filter(oa => !oa.isDeleted);
// attrs are not resorted if position changes after initial load
ownedAttributes.sort((a, b) => a.position < b.position ? -1 : 1);
let htmlAttrs = (await attributeRenderer.renderAttributes(ownedAttributes, true)).html(); let htmlAttrs = (await attributeRenderer.renderAttributes(ownedAttributes, true)).html();
@@ -485,7 +487,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
} }
async createNoteForReferenceLink(title) { async createNoteForReferenceLink(title) {
const {note} = await noteCreateService.createNote(this.notePath, { const {note} = await noteCreateService.createNoteWithTypePrompt(this.notePath, {
activate: false, activate: false,
title: title title: title
}); });

View File

@@ -103,10 +103,22 @@ class BasicWidget extends Component {
this.$widget.toggleClass('hidden-int', !show); this.$widget.toggleClass('hidden-int', !show);
} }
isHiddenInt() {
return this.$widget.hasClass('hidden-int');
}
toggleExt(show) { toggleExt(show) {
this.$widget.toggleClass('hidden-ext', !show); this.$widget.toggleClass('hidden-ext', !show);
} }
isHiddenExt() {
return this.$widget.hasClass('hidden-ext');
}
canBeShown() {
return !this.isHiddenInt() && !this.isHiddenExt();
}
isVisible() { isVisible() {
return this.$widget.is(":visible"); return this.$widget.is(":visible");
} }

View File

@@ -1,12 +1,9 @@
import server from "../../services/server.js"; import server from "../../services/server.js";
import ws from "../../services/ws.js"; import ws from "../../services/ws.js";
import Component from "../component.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
export default class AbstractSearchAction extends Component { export default class AbstractBulkAction {
constructor(attribute, actionDef) { constructor(attribute, actionDef) {
super();
this.attribute = attribute; this.attribute = attribute;
this.actionDef = actionDef; this.actionDef = actionDef;
} }
@@ -50,6 +47,6 @@ export default class AbstractSearchAction extends Component {
await ws.waitForMaxKnownEntityChangeId(); await ws.waitForMaxKnownEntityChangeId();
await this.triggerCommand('refreshSearchDefinition'); //await this.triggerCommand('refreshSearchDefinition');
} }
} }

View File

@@ -1,5 +1,5 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "./abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
@@ -33,8 +33,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class ExecuteScriptSearchAction extends AbstractSearchAction { export default class ExecuteScriptBulkAction extends AbstractBulkAction {
static get actionName() { return "executeScript"; } static get actionName() { return "executeScript"; }
static get actionTitle() { return "Execute script"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);
@@ -43,7 +44,7 @@ export default class ExecuteScriptSearchAction extends AbstractSearchAction {
const spacedUpdate = new SpacedUpdate(async () => { const spacedUpdate = new SpacedUpdate(async () => {
await this.saveAction({ script: $script.val() }); await this.saveAction({ script: $script.val() });
}, 1000) }, 1000);
$script.on('input', () => spacedUpdate.scheduleUpdate()); $script.on('input', () => spacedUpdate.scheduleUpdate());

View File

@@ -1,11 +1,11 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<div style="margin-right: 10px;" class="text-nowrap">Set label</div> <div style="margin-right: 10px;" class="text-nowrap">Add label</div>
<input type="text" <input type="text"
class="form-control label-name" class="form-control label-name"
@@ -37,8 +37,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class SetLabelValueSearchAction extends AbstractSearchAction { export default class AddLabelBulkAction extends AbstractBulkAction {
static get actionName() { return "setLabelValue"; } static get actionName() { return "addLabel"; }
static get actionTitle() { return "Add label"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);
@@ -54,7 +55,7 @@ export default class SetLabelValueSearchAction extends AbstractSearchAction {
labelName: $labelName.val(), labelName: $labelName.val(),
labelValue: $labelValue.val() labelValue: $labelValue.val()
}); });
}, 1000) }, 1000);
$labelName.on('input', () => spacedUpdate.scheduleUpdate()); $labelName.on('input', () => spacedUpdate.scheduleUpdate());
$labelValue.on('input', () => spacedUpdate.scheduleUpdate()); $labelValue.on('input', () => spacedUpdate.scheduleUpdate());

View File

@@ -1,5 +1,5 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
@@ -18,8 +18,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class DeleteLabelSearchAction extends AbstractSearchAction { export default class DeleteLabelBulkAction extends AbstractBulkAction {
static get actionName() { return "deleteLabel"; } static get actionName() { return "deleteLabel"; }
static get actionTitle() { return "Delete label"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);

View File

@@ -1,11 +1,11 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<div style="margin-right: 10px;">Rename label from:</div> <div style="margin-right: 10px; flex-shrink: 0;">Rename label from:</div>
<input type="text" <input type="text"
class="form-control old-label-name" class="form-control old-label-name"
@@ -27,8 +27,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class RenameLabelSearchAction extends AbstractSearchAction { export default class RenameLabelBulkAction extends AbstractBulkAction {
static get actionName() { return "renameLabel"; } static get actionName() { return "renameLabel"; }
static get actionTitle() { return "Rename label"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);
@@ -44,7 +45,7 @@ export default class RenameLabelSearchAction extends AbstractSearchAction {
oldLabelName: $oldLabelName.val(), oldLabelName: $oldLabelName.val(),
newLabelName: $newLabelName.val() newLabelName: $newLabelName.val()
}); });
}, 1000) }, 1000);
$oldLabelName.on('input', () => spacedUpdate.scheduleUpdate()); $oldLabelName.on('input', () => spacedUpdate.scheduleUpdate());
$newLabelName.on('input', () => spacedUpdate.scheduleUpdate()); $newLabelName.on('input', () => spacedUpdate.scheduleUpdate());

View File

@@ -0,0 +1,60 @@
import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = `
<tr>
<td colspan="2">
<div style="display: flex; align-items: center">
<div style="margin-right: 10px;" class="text-nowrap">Update label value</div>
<input type="text"
class="form-control label-name"
placeholder="label name"
pattern="[\\p{L}\\p{N}_:]+"
title="Alphanumeric characters, underscore and colon are allowed characters."/>
<div style="margin-right: 10px; margin-left: 10px;" class="text-nowrap">to value</div>
<input type="text" class="form-control label-value" placeholder="new value"/>
</div>
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<p>On all matched notes, change value of the existing label.</p>
<p>You can also call this method without value, in such case label will be assigned to the note without value.</p>
</div>
</div>
<span class="bx bx-x icon-action action-conf-del"></span>
</td>
</tr>`;
export default class UpdateLabelValueBulkAction extends AbstractBulkAction {
static get actionName() { return "updateLabelValue"; }
static get actionTitle() { return "Update label value"; }
doRender() {
const $action = $(TPL);
const $labelName = $action.find('.label-name');
$labelName.val(this.actionDef.labelName || "");
const $labelValue = $action.find('.label-value');
$labelValue.val(this.actionDef.labelValue || "");
const spacedUpdate = new SpacedUpdate(async () => {
await this.saveAction({
labelName: $labelName.val(),
labelValue: $labelValue.val()
});
}, 1000)
$labelName.on('input', () => spacedUpdate.scheduleUpdate());
$labelValue.on('input', () => spacedUpdate.scheduleUpdate());
return $action;
}
}

View File

@@ -0,0 +1,33 @@
import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = `
<tr>
<td colspan="2">
<span class="bx bx-trash"></span>
Delete matched notes
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<p>This will delete matched notes.</p>
<p>After the deletion, it's possible to undelete them from <span class="bx bx-history"></span> Recent Notes dialog.</p>
<p>To erase notes permanently, you can go after the deletion to the Option -> Other and click the "Erase deleted notes now" button.</p>
</div>
</div>
<span class="bx bx-x icon-action action-conf-del"></span>
</td>
</tr>`;
export default class DeleteNoteBulkAction extends AbstractBulkAction {
static get actionName() { return "deleteNote"; }
static get actionTitle() { return "Delete note"; }
doRender() {
return $(TPL);
}
}

View File

@@ -1,4 +1,4 @@
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
@@ -19,8 +19,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class DeleteNoteRevisionsSearchAction extends AbstractSearchAction { export default class DeleteNoteRevisionsBulkAction extends AbstractBulkAction {
static get actionName() { return "deleteNoteRevisions"; } static get actionName() { return "deleteNoteRevisions"; }
static get actionTitle() { return "Delete note revisions"; }
doRender() { doRender() {
return $(TPL); return $(TPL);

View File

@@ -1,6 +1,6 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
import noteAutocompleteService from "../../services/note_autocomplete.js"; import noteAutocompleteService from "../../../services/note_autocomplete.js";
const TPL = ` const TPL = `
<tr> <tr>
@@ -33,8 +33,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class MoveNoteSearchAction extends AbstractSearchAction { export default class MoveNoteBulkAction extends AbstractBulkAction {
static get actionName() { return "moveNote"; } static get actionName() { return "moveNote"; }
static get actionTitle() { return "Move note"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);

View File

@@ -0,0 +1,56 @@
import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = `
<tr>
<td colspan="2">
<div style="display: flex; align-items: center">
<div style="margin-right: 10px; flex-shrink: 0;">Rename note title to:</div>
<input type="text"
class="form-control new-title"
placeholder="new note title"
title="Click help icon on the right to see all the options"/>
</div>
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<p>The given value is evaluated as JavaScript string and thus can be enriched with dynamic content via the injected <code>note</code> variable (note being renamed). Examples:</p>
<ul>
<li><code>Note</code> - all matched notes are renamed to "Note"</li>
<li><code>NEW: \${note.title}</code> - matched notes titles are prefixed with "NEW: "</li>
<li><code>\${note.dateCreatedObj.format('MM-DD:')}: \${note.title}</code> - matched notes are prefixed with note's creation month-date</li>
</ul>
See API docs for <a href="https://zadam.github.io/trilium/backend_api/Note.html">note</a> and its <a href="https://day.js.org/docs/en/display/format">dateCreatedObj / utcDateCreatedObj properties</a> for details.
</div>
</div>
<span class="bx bx-x icon-action action-conf-del"></span>
</td>
</tr>`;
export default class RenameNoteBulkAction extends AbstractBulkAction {
static get actionName() { return "renameNote"; }
static get actionTitle() { return "Rename note"; }
doRender() {
const $action = $(TPL);
const $newTitle = $action.find('.new-title');
$newTitle.val(this.actionDef.newTitle || "");
const spacedUpdate = new SpacedUpdate(async () => {
await this.saveAction({
newTitle: $newTitle.val(),
});
}, 1000);
$newTitle.on('input', () => spacedUpdate.scheduleUpdate());
return $action;
}
}

View File

@@ -0,0 +1,65 @@
import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractBulkAction from "../abstract_bulk_action.js";
import noteAutocompleteService from "../../../services/note_autocomplete.js";
const TPL = `
<tr>
<td colspan="2">
<div style="display: flex; align-items: center">
<div style="margin-right: 10px;" class="text-nowrap">Add relation</div>
<input type="text"
class="form-control relation-name"
placeholder="relation name"
pattern="[\\p{L}\\p{N}_:]+"
style="flex-shrink: 3"
title="Alphanumeric characters, underscore and colon are allowed characters."/>
<div style="margin-right: 10px; margin-left: 10px;" class="text-nowrap">to</div>
<div class="input-group" style="flex-shrink: 2">
<input type="text" class="form-control target-note" placeholder="target note"/>
</div>
</div>
</td>
<td class="button-column">
<div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4">
<p>On all matched notes create given relation.</p>
</div>
</div>
<span class="bx bx-x icon-action action-conf-del"></span>
</td>
</tr>`;
export default class AddRelationBulkAction extends AbstractBulkAction {
static get actionName() { return "addRelation"; }
static get actionTitle() { return "Add relation"; }
doRender() {
const $action = $(TPL);
const $relationName = $action.find('.relation-name');
$relationName.val(this.actionDef.relationName || "");
const $targetNote = $action.find('.target-note');
noteAutocompleteService.initNoteAutocomplete($targetNote);
$targetNote.setNote(this.actionDef.targetNoteId);
$targetNote.on('autocomplete:closed', () => spacedUpdate.scheduleUpdate());
const spacedUpdate = new SpacedUpdate(async () => {
await this.saveAction({
relationName: $relationName.val(),
targetNoteId: $targetNote.getSelectedNoteId()
});
}, 1000)
$relationName.on('input', () => spacedUpdate.scheduleUpdate());
$targetNote.on('input', () => spacedUpdate.scheduleUpdate());
return $action;
}
}

View File

@@ -1,5 +1,5 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
@@ -20,8 +20,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class DeleteRelationSearchAction extends AbstractSearchAction { export default class DeleteRelationBulkAction extends AbstractBulkAction {
static get actionName() { return "deleteRelation"; } static get actionName() { return "deleteRelation"; }
static get actionTitle() { return "Delete relation"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);

View File

@@ -1,11 +1,11 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
const TPL = ` const TPL = `
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<div style="margin-right: 10px;">Rename relation from:</div> <div style="margin-right: 10px; flex-shrink: 0;">Rename relation from:</div>
<input type="text" <input type="text"
class="form-control old-relation-name" class="form-control old-relation-name"
@@ -27,8 +27,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class RenameRelationSearchAction extends AbstractSearchAction { export default class RenameRelationBulkAction extends AbstractBulkAction {
static get actionName() { return "renameRelation"; } static get actionName() { return "renameRelation"; }
static get actionTitle() { return "Rename relation"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);

View File

@@ -1,12 +1,12 @@
import SpacedUpdate from "../../services/spaced_update.js"; import SpacedUpdate from "../../../services/spaced_update.js";
import AbstractSearchAction from "./abstract_search_action.js"; import AbstractBulkAction from "../abstract_bulk_action.js";
import noteAutocompleteService from "../../services/note_autocomplete.js"; import noteAutocompleteService from "../../../services/note_autocomplete.js";
const TPL = ` const TPL = `
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<div style="margin-right: 10px;" class="text-nowrap">Set relation</div> <div style="margin-right: 10px;" class="text-nowrap">Update relation</div>
<input type="text" <input type="text"
class="form-control relation-name" class="form-control relation-name"
@@ -39,8 +39,9 @@ const TPL = `
</td> </td>
</tr>`; </tr>`;
export default class SetRelationTargetSearchAction extends AbstractSearchAction { export default class UpdateRelationTargetBulkAction extends AbstractBulkAction {
static get actionName() { return "setRelationTarget"; } static get actionName() { return "updateRelationTarget"; }
static get actionTitle() { return "Update relation target"; }
doRender() { doRender() {
const $action = $(TPL); const $action = $(TPL);

View File

@@ -132,8 +132,7 @@ export default class GlobalMenuWidget extends BasicWidget {
$button.tooltip({ trigger: "hover" }); $button.tooltip({ trigger: "hover" });
$button.on("click", () => $button.tooltip("hide")); $button.on("click", () => $button.tooltip("hide"));
this.$widget.find(".show-about-dialog-button").on('click', this.$widget.find(".show-about-dialog-button").on('click', () => this.triggerCommand("openAboutDialog"));
() => import("../../dialogs/about.js").then(d => d.showDialog()));
const isElectron = utils.isElectron(); const isElectron = utils.isElectron();

View File

@@ -26,7 +26,7 @@ const TPL = `
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
<a data-trigger-command="renderActiveNote" class="dropdown-item render-note-button"><kbd data-command="renderActiveNote"></kbd> Re-render note</a> <a data-trigger-command="renderActiveNote" class="dropdown-item render-note-button"><kbd data-command="renderActiveNote"></kbd> Re-render note</a>
<a data-trigger-command="findInText" class="dropdown-item find-in-text-button">Search in note <kbd data-command="findInText"></a> <a data-trigger-command="findInText" class="dropdown-item find-in-text-button">Search in note <kbd data-command="findInText"></a>
<a data-trigger-command="showNoteSource" class="dropdown-item show-source-button"><kbd data-command="showNoteSource"></kbd> Note source</a> <a data-trigger-command="openNoteSourceDialog" class="dropdown-item show-source-button"><kbd data-command="showNoteSource"></kbd> Note source</a>
<a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a> <a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a>
<a class="dropdown-item import-files-button">Import files</a> <a class="dropdown-item import-files-button">Import files</a>
<a class="dropdown-item export-note-button">Export note</a> <a class="dropdown-item export-note-button">Export note</a>
@@ -53,11 +53,14 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
return; return;
} }
import('../../dialogs/export.js').then(d => d.showDialog(this.noteContext.notePath, 'single')); this.triggerCommand("showExportDialog", {
notePath: this.noteContext.notePath,
defaultType: "single"
});
}); });
this.$importNoteButton = this.$widget.find('.import-files-button'); this.$importNoteButton = this.$widget.find('.import-files-button');
this.$importNoteButton.on("click", () => import('../../dialogs/import.js').then(d => d.showDialog(this.noteId))); this.$importNoteButton.on("click", () => this.triggerCommand("showImportDialog", {noteId: this.noteId}));
this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle')); this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle'));

View File

@@ -10,7 +10,7 @@ export default class ShowNoteSourceButton extends ButtonWidget {
this.icon('bx bx-code') this.icon('bx bx-code')
.title("Show Note Source") .title("Show Note Source")
.command("showNoteSource") .command("openNoteSourceDialog")
.titlePlacement("bottom"); .titlePlacement("bottom");
} }
} }

View File

@@ -9,6 +9,9 @@ const WIDGET_TPL = `
</div> </div>
</div>`; </div>`;
/**
* TODO: rename, it's not collapsible anymore
*/
export default class CollapsibleWidget extends NoteContextAwareWidget { export default class CollapsibleWidget extends NoteContextAwareWidget {
get widgetTitle() { return "Untitled widget"; } get widgetTitle() { return "Untitled widget"; }
@@ -32,8 +35,4 @@ export default class CollapsibleWidget extends NoteContextAwareWidget {
/** for overriding */ /** for overriding */
async doRenderBody() {} async doRenderBody() {}
isExpanded() {
return this.$bodyWrapper.hasClass("show");
}
} }

View File

@@ -195,6 +195,12 @@ export default class RibbonContainer extends NoteContextAwareWidget {
} }
} }
async noteSwitched() {
this.lastActiveComponentId = null;
await super.noteSwitched();
}
async refreshWithNote(note, noExplicitActivation = false) { async refreshWithNote(note, noExplicitActivation = false) {
this.lastNoteType = note.type; this.lastNoteType = note.type;

Some files were not shown because too many files have changed in this diff Show More