mirror of
https://github.com/zadam/trilium.git
synced 2025-10-28 08:46:43 +01:00
Compare commits
184 Commits
v0.41.1-be
...
v0.43.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47a22f6e8d | ||
|
|
17d7ff3ff1 | ||
|
|
3582013a33 | ||
|
|
95bbdb3b6b | ||
|
|
8a57960c6e | ||
|
|
5f4a84d967 | ||
|
|
099e90ed64 | ||
|
|
3d324b954d | ||
|
|
443f389d73 | ||
|
|
08edc521e4 | ||
|
|
f54f6d09b0 | ||
|
|
3219441fdf | ||
|
|
1b0a2b41da | ||
|
|
582429e762 | ||
|
|
238df0fb40 | ||
|
|
89356918f1 | ||
|
|
263b65997c | ||
|
|
2b757bfccd | ||
|
|
c78ca4c9db | ||
|
|
a0395e9866 | ||
|
|
89aa4fbc73 | ||
|
|
74a7802088 | ||
|
|
a89b6711d1 | ||
|
|
b2549b2834 | ||
|
|
959c4cbe64 | ||
|
|
d03d3603d2 | ||
|
|
e1c2573778 | ||
|
|
2af2b45062 | ||
|
|
eabe4775bd | ||
|
|
da9b321aa0 | ||
|
|
c18d8d2d1b | ||
|
|
5f2361ebd5 | ||
|
|
9791dab97d | ||
|
|
85d986534d | ||
|
|
00faf758e8 | ||
|
|
6ba2e5cf73 | ||
|
|
fb3876d28b | ||
|
|
fb975849b9 | ||
|
|
16fef78344 | ||
|
|
e0b4b369dc | ||
|
|
0df7851214 | ||
|
|
5d47c2b23e | ||
|
|
d09b021487 | ||
|
|
910bda860c | ||
|
|
2d92b4931a | ||
|
|
212b719ee9 | ||
|
|
1db892d22f | ||
|
|
535dcb6d12 | ||
|
|
4426362799 | ||
|
|
2c609e8136 | ||
|
|
11b73b79ed | ||
|
|
e70c862e72 | ||
|
|
b3e66d5a83 | ||
|
|
e8cd821e57 | ||
|
|
be7ac74235 | ||
|
|
58fa0832f6 | ||
|
|
1502b9ce66 | ||
|
|
7307ca385f | ||
|
|
c1fd9825aa | ||
|
|
9de7d3fc53 | ||
|
|
3c5db844ba | ||
|
|
e7330c1104 | ||
|
|
ec4586b164 | ||
|
|
91e5f24798 | ||
|
|
38723e0189 | ||
|
|
8c88ce6f65 | ||
|
|
4d22959e28 | ||
|
|
50a28d8c51 | ||
|
|
e25b633ec4 | ||
|
|
75bd395669 | ||
|
|
5e353a5612 | ||
|
|
6b359b7796 | ||
|
|
13f9d037dc | ||
|
|
1911d64c1c | ||
|
|
d4c3f1b3f2 | ||
|
|
3db84daf94 | ||
|
|
2526715aa4 | ||
|
|
04c573e212 | ||
|
|
58f4f5d1e6 | ||
|
|
fa5d982a55 | ||
|
|
108afe8896 | ||
|
|
37da0adb8a | ||
|
|
4f50864ec8 | ||
|
|
30b9ef8604 | ||
|
|
b063b4c528 | ||
|
|
e08b0141a4 | ||
|
|
9d8b8e26a1 | ||
|
|
cb70109ee7 | ||
|
|
e541abbd60 | ||
|
|
940a70adc5 | ||
|
|
88e8eb7e9c | ||
|
|
b365c186a1 | ||
|
|
64c9734f05 | ||
|
|
48c843c087 | ||
|
|
0e4eec10b9 | ||
|
|
a3661cb763 | ||
|
|
115879ec4a | ||
|
|
df11b076bc | ||
|
|
54ecd2ee75 | ||
|
|
2369bcf9fc | ||
|
|
5d8808a2ad | ||
|
|
62b993f06f | ||
|
|
8aa5608085 | ||
|
|
b452d7e5c5 | ||
|
|
9b9d6d86d0 | ||
|
|
7f2755d4a0 | ||
|
|
3b268cc8eb | ||
|
|
6dfe335707 | ||
|
|
c7125d2b50 | ||
|
|
e8a33a5ee7 | ||
|
|
deb0b24c4c | ||
|
|
cafcb67a8a | ||
|
|
4c6e9480e4 | ||
|
|
109bead1c7 | ||
|
|
ae1220b970 | ||
|
|
b89a2df462 | ||
|
|
8b5536ee3a | ||
|
|
647790885d | ||
|
|
227c3e4dcc | ||
|
|
4eb2407c73 | ||
|
|
43e12fbea2 | ||
|
|
2a3091f788 | ||
|
|
742df25bc2 | ||
|
|
9be1d1f697 | ||
|
|
ed52f93bbb | ||
|
|
3466a19397 | ||
|
|
fe53e2351c | ||
|
|
5c35b870eb | ||
|
|
90d091aedb | ||
|
|
0a05a40186 | ||
|
|
7482ed063b | ||
|
|
70e343f2fc | ||
|
|
358f3a7291 | ||
|
|
6161b1c193 | ||
|
|
94b57dadd7 | ||
|
|
81fbefb9cd | ||
|
|
6d6695e3a9 | ||
|
|
4c308ad68f | ||
|
|
989a003d2f | ||
|
|
ccdb41841e | ||
|
|
0a94622413 | ||
|
|
5769587305 | ||
|
|
ffbfccb701 | ||
|
|
56ce23fc36 | ||
|
|
cba7e5a59f | ||
|
|
86cf8f3202 | ||
|
|
907cdd8fcb | ||
|
|
7ea53d468e | ||
|
|
586d6b4557 | ||
|
|
8f68ff1932 | ||
|
|
a1ea2c9115 | ||
|
|
e8ce81a133 | ||
|
|
aff12950f0 | ||
|
|
75c58cbf79 | ||
|
|
87a1e98fa2 | ||
|
|
d1eacbb574 | ||
|
|
71d248cd87 | ||
|
|
ac608b9334 | ||
|
|
32020d78b5 | ||
|
|
ff853c7d0a | ||
|
|
8526cb2315 | ||
|
|
dc89f72e75 | ||
|
|
657ff16267 | ||
|
|
ed759f5585 | ||
|
|
a86177bb59 | ||
|
|
9f1b3cc892 | ||
|
|
8473f72ec8 | ||
|
|
666d202a3a | ||
|
|
988fae50cb | ||
|
|
98bbd17920 | ||
|
|
dadcc93ae3 | ||
|
|
48e19d0149 | ||
|
|
f97c9e3619 | ||
|
|
61167f6646 | ||
|
|
29cec8112e | ||
|
|
48aadc8309 | ||
|
|
b2508db9af | ||
|
|
87510fd72b | ||
|
|
339f212e4c | ||
|
|
3c311cd2a4 | ||
|
|
b5bf581bd9 | ||
|
|
242f139be4 | ||
|
|
6c76d862d2 | ||
|
|
62bc05134e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
src/public/app-dist/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
*.db
|
||||
|
||||
4
.idea/dataSources.xml
generated
4
.idea/dataSources.xml
generated
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="document.db" uuid="a2c75661-f9e2-478f-a69f-6a9409e69997">
|
||||
<data-source source="LOCAL" name="document.db" uuid="b0b03187-36c8-4ec1-bdab-fd4273cd692e">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/../trilium-data/document.db</jdbc-url>
|
||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/trilium-data/document.db</jdbc-url>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,662 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<dataSource name="document.db">
|
||||
<database-model serializer="dbm" dbms="SQLITE" family-id="SQLITE" format-version="4.17">
|
||||
<root id="1">
|
||||
<ServerVersion>3.25.1</ServerVersion>
|
||||
</root>
|
||||
<schema id="2" parent="1" name="main">
|
||||
<Current>1</Current>
|
||||
</schema>
|
||||
<collation id="3" parent="1" name="BINARY"/>
|
||||
<collation id="4" parent="1" name="NOCASE"/>
|
||||
<collation id="5" parent="1" name="RTRIM"/>
|
||||
<table id="6" parent="2" name="api_tokens"/>
|
||||
<table id="7" parent="2" name="attributes"/>
|
||||
<table id="8" parent="2" name="branches"/>
|
||||
<table id="9" parent="2" name="note_contents"/>
|
||||
<table id="10" parent="2" name="note_revision_contents"/>
|
||||
<table id="11" parent="2" name="note_revisions"/>
|
||||
<table id="12" parent="2" name="notes"/>
|
||||
<table id="13" parent="2" name="options"/>
|
||||
<table id="14" parent="2" name="recent_notes"/>
|
||||
<table id="15" parent="2" name="source_ids"/>
|
||||
<table id="16" parent="2" name="sqlite_master">
|
||||
<System>1</System>
|
||||
</table>
|
||||
<table id="17" parent="2" name="sqlite_sequence">
|
||||
<System>1</System>
|
||||
</table>
|
||||
<table id="18" parent="2" name="sync"/>
|
||||
<column id="19" parent="6" name="apiTokenId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="20" parent="6" name="token">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="21" parent="6" name="utcDateCreated">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="22" parent="6" name="isDeleted">
|
||||
<Position>4</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="23" parent="6" name="hash">
|
||||
<Position>5</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<index id="24" parent="6" name="sqlite_autoindex_api_tokens_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>apiTokenId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<key id="25" parent="6">
|
||||
<ColNames>apiTokenId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_api_tokens_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="26" parent="7" name="attributeId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="27" parent="7" name="noteId">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="28" parent="7" name="type">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="29" parent="7" name="name">
|
||||
<Position>4</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="30" parent="7" name="value">
|
||||
<Position>5</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>''</DefaultExpression>
|
||||
</column>
|
||||
<column id="31" parent="7" name="position">
|
||||
<Position>6</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="32" parent="7" name="utcDateCreated">
|
||||
<Position>7</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="33" parent="7" name="utcDateModified">
|
||||
<Position>8</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="34" parent="7" name="isDeleted">
|
||||
<Position>9</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="35" parent="7" name="deleteId">
|
||||
<Position>10</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<DefaultExpression>NULL</DefaultExpression>
|
||||
</column>
|
||||
<column id="36" parent="7" name="hash">
|
||||
<Position>11</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<column id="37" parent="7" name="isInheritable">
|
||||
<Position>12</Position>
|
||||
<DataType>int|0s</DataType>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<index id="38" parent="7" name="sqlite_autoindex_attributes_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>attributeId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="39" parent="7" name="IDX_attributes_noteId_index">
|
||||
<ColNames>noteId</ColNames>
|
||||
</index>
|
||||
<index id="40" parent="7" name="IDX_attributes_name_value">
|
||||
<ColNames>name
|
||||
value</ColNames>
|
||||
</index>
|
||||
<index id="41" parent="7" name="IDX_attributes_value_index">
|
||||
<ColNames>value</ColNames>
|
||||
</index>
|
||||
<key id="42" parent="7">
|
||||
<ColNames>attributeId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_attributes_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="43" parent="8" name="branchId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="44" parent="8" name="noteId">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="45" parent="8" name="parentNoteId">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="46" parent="8" name="notePosition">
|
||||
<Position>4</Position>
|
||||
<DataType>INTEGER|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="47" parent="8" name="prefix">
|
||||
<Position>5</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
</column>
|
||||
<column id="48" parent="8" name="isExpanded">
|
||||
<Position>6</Position>
|
||||
<DataType>INTEGER|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="49" parent="8" name="isDeleted">
|
||||
<Position>7</Position>
|
||||
<DataType>INTEGER|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="50" parent="8" name="deleteId">
|
||||
<Position>8</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<DefaultExpression>NULL</DefaultExpression>
|
||||
</column>
|
||||
<column id="51" parent="8" name="utcDateModified">
|
||||
<Position>9</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="52" parent="8" name="utcDateCreated">
|
||||
<Position>10</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="53" parent="8" name="hash">
|
||||
<Position>11</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<index id="54" parent="8" name="sqlite_autoindex_branches_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>branchId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="55" parent="8" name="IDX_branches_noteId_parentNoteId">
|
||||
<ColNames>noteId
|
||||
parentNoteId</ColNames>
|
||||
</index>
|
||||
<index id="56" parent="8" name="IDX_branches_parentNoteId">
|
||||
<ColNames>parentNoteId</ColNames>
|
||||
</index>
|
||||
<key id="57" parent="8">
|
||||
<ColNames>branchId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="58" parent="9" name="noteId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="59" parent="9" name="content">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<DefaultExpression>NULL</DefaultExpression>
|
||||
</column>
|
||||
<column id="60" parent="9" name="hash">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<column id="61" parent="9" name="utcDateModified">
|
||||
<Position>4</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<index id="62" parent="9" name="sqlite_autoindex_note_contents_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>noteId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<key id="63" parent="9">
|
||||
<ColNames>noteId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_note_contents_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="64" parent="10" name="noteRevisionId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="65" parent="10" name="content">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
</column>
|
||||
<column id="66" parent="10" name="hash">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>''</DefaultExpression>
|
||||
</column>
|
||||
<column id="67" parent="10" name="utcDateModified">
|
||||
<Position>4</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<index id="68" parent="10" name="sqlite_autoindex_note_revision_contents_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>noteRevisionId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<key id="69" parent="10">
|
||||
<ColNames>noteRevisionId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_note_revision_contents_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="70" parent="11" name="noteRevisionId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="71" parent="11" name="noteId">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="72" parent="11" name="title">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
</column>
|
||||
<column id="73" parent="11" name="contentLength">
|
||||
<Position>4</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="74" parent="11" name="isErased">
|
||||
<Position>5</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="75" parent="11" name="isProtected">
|
||||
<Position>6</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="76" parent="11" name="utcDateLastEdited">
|
||||
<Position>7</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="77" parent="11" name="utcDateCreated">
|
||||
<Position>8</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="78" parent="11" name="utcDateModified">
|
||||
<Position>9</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="79" parent="11" name="dateLastEdited">
|
||||
<Position>10</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="80" parent="11" name="dateCreated">
|
||||
<Position>11</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="81" parent="11" name="type">
|
||||
<Position>12</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>''</DefaultExpression>
|
||||
</column>
|
||||
<column id="82" parent="11" name="mime">
|
||||
<Position>13</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>''</DefaultExpression>
|
||||
</column>
|
||||
<column id="83" parent="11" name="hash">
|
||||
<Position>14</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>''</DefaultExpression>
|
||||
</column>
|
||||
<index id="84" parent="11" name="sqlite_autoindex_note_revisions_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>noteRevisionId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="85" parent="11" name="IDX_note_revisions_noteId">
|
||||
<ColNames>noteId</ColNames>
|
||||
</index>
|
||||
<index id="86" parent="11" name="IDX_note_revisions_utcDateLastEdited">
|
||||
<ColNames>utcDateLastEdited</ColNames>
|
||||
</index>
|
||||
<index id="87" parent="11" name="IDX_note_revisions_utcDateCreated">
|
||||
<ColNames>utcDateCreated</ColNames>
|
||||
</index>
|
||||
<index id="88" parent="11" name="IDX_note_revisions_dateLastEdited">
|
||||
<ColNames>dateLastEdited</ColNames>
|
||||
</index>
|
||||
<index id="89" parent="11" name="IDX_note_revisions_dateCreated">
|
||||
<ColNames>dateCreated</ColNames>
|
||||
</index>
|
||||
<key id="90" parent="11">
|
||||
<ColNames>noteRevisionId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="91" parent="12" name="noteId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="92" parent="12" name="title">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>"note"</DefaultExpression>
|
||||
</column>
|
||||
<column id="93" parent="12" name="contentLength">
|
||||
<Position>3</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="94" parent="12" name="isProtected">
|
||||
<Position>4</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="95" parent="12" name="type">
|
||||
<Position>5</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>'text'</DefaultExpression>
|
||||
</column>
|
||||
<column id="96" parent="12" name="mime">
|
||||
<Position>6</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>'text/html'</DefaultExpression>
|
||||
</column>
|
||||
<column id="97" parent="12" name="hash">
|
||||
<Position>7</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<column id="98" parent="12" name="isDeleted">
|
||||
<Position>8</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="99" parent="12" name="deleteId">
|
||||
<Position>9</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<DefaultExpression>NULL</DefaultExpression>
|
||||
</column>
|
||||
<column id="100" parent="12" name="isErased">
|
||||
<Position>10</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="101" parent="12" name="dateCreated">
|
||||
<Position>11</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="102" parent="12" name="dateModified">
|
||||
<Position>12</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="103" parent="12" name="utcDateCreated">
|
||||
<Position>13</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="104" parent="12" name="utcDateModified">
|
||||
<Position>14</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<index id="105" parent="12" name="sqlite_autoindex_notes_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>noteId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="106" parent="12" name="IDX_notes_title">
|
||||
<ColNames>title</ColNames>
|
||||
</index>
|
||||
<index id="107" parent="12" name="IDX_notes_type">
|
||||
<ColNames>type</ColNames>
|
||||
</index>
|
||||
<index id="108" parent="12" name="IDX_notes_isDeleted">
|
||||
<ColNames>isDeleted</ColNames>
|
||||
</index>
|
||||
<index id="109" parent="12" name="IDX_notes_dateCreated">
|
||||
<ColNames>dateCreated</ColNames>
|
||||
</index>
|
||||
<index id="110" parent="12" name="IDX_notes_dateModified">
|
||||
<ColNames>dateModified</ColNames>
|
||||
</index>
|
||||
<index id="111" parent="12" name="IDX_notes_utcDateCreated">
|
||||
<ColNames>utcDateCreated</ColNames>
|
||||
</index>
|
||||
<index id="112" parent="12" name="IDX_notes_utcDateModified">
|
||||
<ColNames>utcDateModified</ColNames>
|
||||
</index>
|
||||
<key id="113" parent="12">
|
||||
<ColNames>noteId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="114" parent="13" name="name">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="115" parent="13" name="value">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
</column>
|
||||
<column id="116" parent="13" name="isSynced">
|
||||
<Position>3</Position>
|
||||
<DataType>INTEGER|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="117" parent="13" name="hash">
|
||||
<Position>4</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<column id="118" parent="13" name="utcDateCreated">
|
||||
<Position>5</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="119" parent="13" name="utcDateModified">
|
||||
<Position>6</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<index id="120" parent="13" name="sqlite_autoindex_options_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>name</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<key id="121" parent="13">
|
||||
<ColNames>name</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="122" parent="14" name="noteId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="123" parent="14" name="notePath">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="124" parent="14" name="hash">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>""</DefaultExpression>
|
||||
</column>
|
||||
<column id="125" parent="14" name="utcDateCreated">
|
||||
<Position>4</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="126" parent="14" name="isDeleted">
|
||||
<Position>5</Position>
|
||||
<DataType>INT|0s</DataType>
|
||||
</column>
|
||||
<index id="127" parent="14" name="sqlite_autoindex_recent_notes_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>noteId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<key id="128" parent="14">
|
||||
<ColNames>noteId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="129" parent="15" name="sourceId">
|
||||
<Position>1</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="130" parent="15" name="utcDateCreated">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<index id="131" parent="15" name="sqlite_autoindex_source_ids_1">
|
||||
<NameSurrogate>1</NameSurrogate>
|
||||
<ColNames>sourceId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="132" parent="15" name="IDX_source_ids_utcDateCreated">
|
||||
<ColNames>utcDateCreated</ColNames>
|
||||
</index>
|
||||
<key id="133" parent="15">
|
||||
<ColNames>sourceId</ColNames>
|
||||
<Primary>1</Primary>
|
||||
<UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
|
||||
</key>
|
||||
<column id="134" parent="16" name="type">
|
||||
<Position>1</Position>
|
||||
<DataType>text|0s</DataType>
|
||||
</column>
|
||||
<column id="135" parent="16" name="name">
|
||||
<Position>2</Position>
|
||||
<DataType>text|0s</DataType>
|
||||
</column>
|
||||
<column id="136" parent="16" name="tbl_name">
|
||||
<Position>3</Position>
|
||||
<DataType>text|0s</DataType>
|
||||
</column>
|
||||
<column id="137" parent="16" name="rootpage">
|
||||
<Position>4</Position>
|
||||
<DataType>int|0s</DataType>
|
||||
</column>
|
||||
<column id="138" parent="16" name="sql">
|
||||
<Position>5</Position>
|
||||
<DataType>text|0s</DataType>
|
||||
</column>
|
||||
<column id="139" parent="17" name="name">
|
||||
<Position>1</Position>
|
||||
</column>
|
||||
<column id="140" parent="17" name="seq">
|
||||
<Position>2</Position>
|
||||
</column>
|
||||
<column id="141" parent="18" name="id">
|
||||
<Position>1</Position>
|
||||
<DataType>INTEGER|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<SequenceIdentity>1</SequenceIdentity>
|
||||
</column>
|
||||
<column id="142" parent="18" name="entityName">
|
||||
<Position>2</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="143" parent="18" name="entityId">
|
||||
<Position>3</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="144" parent="18" name="sourceId">
|
||||
<Position>4</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<column id="145" parent="18" name="isSynced">
|
||||
<Position>5</Position>
|
||||
<DataType>INTEGER|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
<DefaultExpression>0</DefaultExpression>
|
||||
</column>
|
||||
<column id="146" parent="18" name="utcSyncDate">
|
||||
<Position>6</Position>
|
||||
<DataType>TEXT|0s</DataType>
|
||||
<NotNull>1</NotNull>
|
||||
</column>
|
||||
<index id="147" parent="18" name="IDX_sync_entityName_entityId">
|
||||
<ColNames>entityName
|
||||
entityId</ColNames>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="148" parent="18" name="IDX_sync_utcSyncDate">
|
||||
<ColNames>utcSyncDate</ColNames>
|
||||
</index>
|
||||
<key id="149" parent="18">
|
||||
<ColNames>id</ColNames>
|
||||
<Primary>1</Primary>
|
||||
</key>
|
||||
</database-model>
|
||||
</dataSource>
|
||||
@@ -1,2 +0,0 @@
|
||||
#n:main
|
||||
!<md> [0, 0, null, null, -2147483648, -2147483648]
|
||||
1
.idea/inspectionProfiles/Project_Default.xml
generated
1
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,6 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="JSUnfilteredForInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
|
||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:12.16.1-alpine
|
||||
FROM node:12.16.3-alpine
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
@@ -8,7 +8,7 @@ Trilium Notes is a hierarchical note taking application with focus on building l
|
||||
## Features
|
||||
|
||||
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://github.com/zadam/trilium/wiki/Cloning-notes))
|
||||
* Rich WYSIWYG note editing including e.g. tables and images with markdown [autoformat](https://github.com/zadam/trilium/wiki/Text-editor#autoformat)
|
||||
* Rich WYSIWYG note editing including e.g. tables and images with markdown [autoformat](https://github.com/zadam/trilium/wiki/Text-notes#autoformat)
|
||||
* Support for editing [notes with source code](https://github.com/zadam/trilium/wiki/Code-notes), including syntax highlighting
|
||||
* Fast and easy [navigation between notes](https://github.com/zadam/trilium/wiki/Note-navigation), full text search and [note hoisting](https://github.com/zadam/trilium/wiki/Note-hoisting)
|
||||
* Seamless [note versioning](https://github.com/zadam/trilium/wiki/Note-revisions)
|
||||
|
||||
@@ -12,6 +12,8 @@ echo "Copying required linux-x64 binaries"
|
||||
rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
|
||||
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
|
||||
|
||||
cp -r bin/deps/linux-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/linux-x64/image/pngquant $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
|
||||
@@ -27,6 +29,9 @@ cp images/app-icons/png/128x128.png $BUILD_DIR/icon.png
|
||||
# removing software WebGL binaries because they are pretty huge and not necessary
|
||||
rm -r $BUILD_DIR/swiftshader
|
||||
|
||||
cp bin/tpl/portable-trilium.sh $BUILD_DIR/
|
||||
chmod 755 $BUILD_DIR/portable-trilium.sh
|
||||
|
||||
echo "Packaging linux x64 electron distribution..."
|
||||
VERSION=`jq -r ".version" package.json`
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ cp bin/deps/mac-x64/image/cjpeg $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/mac-x64/image/pngquant $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/mac-x64/image/gifsicle $SRC_DIR/node_modules/giflossy/vendor/
|
||||
|
||||
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
|
||||
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns
|
||||
|
||||
BUILD_DIR=./dist/trilium-mac-x64
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PKG_DIR=dist/trilium-linux-x64-server
|
||||
NODE_VERSION=12.16.1
|
||||
NODE_VERSION=12.16.3
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
|
||||
@@ -19,6 +19,8 @@ cp bin/deps/win-x64/image/cjpeg.exe $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/win-x64/image/pngquant.exe $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/win-x64/image/gifsicle.exe $SRC_DIR/node_modules/giflossy/vendor/
|
||||
|
||||
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
|
||||
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico
|
||||
|
||||
BUILD_DIR=./dist/trilium-windows-x64
|
||||
@@ -29,6 +31,8 @@ mv "./dist/Trilium Notes-win32-x64" $BUILD_DIR
|
||||
# removing software WebGL binaries because they are pretty huge and not necessary
|
||||
rm -r $BUILD_DIR/swiftshader
|
||||
|
||||
cp bin/tpl/portable-trilium.bat $BUILD_DIR/
|
||||
|
||||
echo "Zipping windows x64 electron distribution..."
|
||||
VERSION=`jq -r ".version" package.json`
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ if [[ $# -eq 0 ]] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
npm run webpack
|
||||
|
||||
DIR=$1
|
||||
|
||||
rm -rf $DIR
|
||||
@@ -22,8 +24,18 @@ cp -r README.md $DIR/
|
||||
cp -r LICENSE $DIR/
|
||||
cp -r config-sample.ini $DIR/
|
||||
cp -r electron.js $DIR/
|
||||
cp webpack-* $DIR/
|
||||
|
||||
# run in subshell (so we return to original dir)
|
||||
(cd $DIR && npm install --only=prod)
|
||||
|
||||
find $DIR/libraries -name "*.map" -type f -delete
|
||||
find $DIR/libraries -name "*.map" -type f -delete
|
||||
|
||||
rm -r $DIR/src/public/app
|
||||
|
||||
rm -r $DIR/node_modules/sqlite3/build
|
||||
rm -r $DIR/node_modules/sqlite3/deps
|
||||
|
||||
sed -i -e 's/app\/desktop.js/app-dist\/desktop.js/g' $DIR/src/views/desktop.ejs
|
||||
sed -i -e 's/app\/mobile.js/app-dist\/mobile.js/g' $DIR/src/views/mobile.ejs
|
||||
sed -i -e 's/app\/setup.js/app-dist\/setup.js/g' $DIR/src/views/setup.ejs
|
||||
|
||||
4
bin/tpl/portable-trilium.bat
Normal file
4
bin/tpl/portable-trilium.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
SET DIR=%~dp0
|
||||
SET TRILIUM_DATA_DIR=%DIR%\trilium-data
|
||||
cd %DIR%
|
||||
start trilium.exe
|
||||
7
bin/tpl/portable-trilium.sh
Executable file
7
bin/tpl/portable-trilium.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
DIR=`dirname "$0"`
|
||||
export TRILIUM_DATA_DIR="$DIR/trilium-data"
|
||||
|
||||
"$DIR/trilium"
|
||||
|
||||
BIN
db/demo.zip
BIN
db/demo.zip
Binary file not shown.
4
db/migrations/0159__fix_isSynced_in_sync_rows.sql
Normal file
4
db/migrations/0159__fix_isSynced_in_sync_rows.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
UPDATE sync SET isSynced = 1 WHERE entityName != 'options' OR (
|
||||
entityName = 'options'
|
||||
AND 1 = (SELECT isSynced FROM options WHERE name = sync.entityId)
|
||||
)
|
||||
@@ -879,7 +879,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -5483,7 +5483,7 @@ Typical use case is when new note has been created, we should wait until it is s
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -507,7 +507,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -6813,7 +6813,7 @@ Cache is note instance scoped.
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -79,7 +79,7 @@ export default Attribute;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -81,7 +81,7 @@ export default Branch;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -61,7 +61,7 @@ export default NoteComplement;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -493,7 +493,7 @@ export default NoteShort;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -95,6 +95,275 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="decorateWidget"><span class="type-signature"></span>decorateWidget<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
for overriding
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line93">line 93</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="doRenderBody"><span class="type-signature">(async) </span>doRenderBody<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
for overriding
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line96">line 96</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="widgetCollapsedStateChangedEvent"><span class="type-signature"></span>widgetCollapsedStateChangedEvent<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
This event is used to synchronize collapsed state of all the tab-cached widgets since they are all rendered
|
||||
separately but should behave uniformly for the user.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="widgets_collapsible_widget.js.html">widgets/collapsible_widget.js</a>, <a href="widgets_collapsible_widget.js.html#line86">line 86</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -333,7 +602,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@@ -443,7 +443,7 @@ export default FrontendScriptApi;</code></pre>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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><a href="global.html">Global</a></h3>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
151
docs/frontend_api/widgets_collapsible_widget.js.html
Normal file
151
docs/frontend_api/widgets_collapsible_widget.js.html
Normal file
@@ -0,0 +1,151 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: widgets/collapsible_widget.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: widgets/collapsible_widget.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import TabAwareWidget from "./tab_aware_widget.js";
|
||||
import options from "../services/options.js";
|
||||
|
||||
const WIDGET_TPL = `
|
||||
<div class="card widget">
|
||||
<div class="card-header">
|
||||
<div>
|
||||
<button class="btn btn-sm widget-title" data-toggle="collapse" data-target="#[to be set]">
|
||||
Collapsible Group Item
|
||||
</button>
|
||||
|
||||
<a class="widget-help external no-arrow bx bx-info-circle"></a>
|
||||
</div>
|
||||
|
||||
<div class="widget-header-actions"></div>
|
||||
</div>
|
||||
|
||||
<div id="[to be set]" class="collapse body-wrapper" style="transition: none; ">
|
||||
<div class="card-body"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
export default class CollapsibleWidget extends TabAwareWidget {
|
||||
get widgetTitle() { return "Untitled widget"; }
|
||||
|
||||
get headerActions() { return []; }
|
||||
|
||||
get help() { return {}; }
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(WIDGET_TPL);
|
||||
this.$widget.find('[data-target]').attr('data-target', "#" + this.componentId);
|
||||
|
||||
this.$bodyWrapper = this.$widget.find('.body-wrapper');
|
||||
this.$bodyWrapper.attr('id', this.componentId); // for toggle to work we need id
|
||||
|
||||
this.widgetName = this.constructor.name;
|
||||
|
||||
if (!options.is(this.widgetName + 'Collapsed')) {
|
||||
this.$bodyWrapper.collapse("show");
|
||||
}
|
||||
|
||||
// using immediate variants of the event so that the previous collapse is not caught
|
||||
this.$bodyWrapper.on('hide.bs.collapse', () => this.saveCollapsed(true));
|
||||
this.$bodyWrapper.on('show.bs.collapse', () => this.saveCollapsed(false));
|
||||
|
||||
this.$body = this.$bodyWrapper.find('.card-body');
|
||||
|
||||
this.$title = this.$widget.find('.widget-title');
|
||||
this.$title.text(this.widgetTitle);
|
||||
|
||||
this.$help = this.$widget.find('.widget-help');
|
||||
|
||||
if (this.help.title) {
|
||||
this.$help.attr("title", this.help.title);
|
||||
this.$help.attr("href", this.help.url || "javascript:");
|
||||
|
||||
if (!this.help.url) {
|
||||
this.$help.addClass('no-link');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.$help.hide();
|
||||
}
|
||||
|
||||
this.$headerActions = this.$widget.find('.widget-header-actions');
|
||||
this.$headerActions.append(...this.headerActions);
|
||||
|
||||
this.initialized = this.doRenderBody();
|
||||
|
||||
this.decorateWidget();
|
||||
|
||||
return this.$widget;
|
||||
}
|
||||
|
||||
saveCollapsed(collapse) {
|
||||
options.save(this.widgetName + 'Collapsed', collapse.toString());
|
||||
|
||||
this.triggerEvent(`widgetCollapsedStateChanged`, {widgetName: this.widgetName, collapse});
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is used to synchronize collapsed state of all the tab-cached widgets since they are all rendered
|
||||
* separately but should behave uniformly for the user.
|
||||
*/
|
||||
widgetCollapsedStateChangedEvent({widgetName, collapse}) {
|
||||
if (widgetName === this.widgetName) {
|
||||
this.$bodyWrapper.toggleClass('show', !collapse);
|
||||
}
|
||||
}
|
||||
|
||||
/** for overriding */
|
||||
decorateWidget() {}
|
||||
|
||||
/** for overriding */
|
||||
async doRenderBody() {}
|
||||
|
||||
isExpanded() {
|
||||
return this.$bodyWrapper.hasClass("show");
|
||||
}
|
||||
}</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><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#decorateWidget">decorateWidget</a></li><li><a href="global.html#doRenderBody">doRenderBody</a></li><li><a href="global.html#widgetCollapsedStateChangedEvent">widgetCollapsedStateChangedEvent</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.4</a>
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
For bug reports, please mention **version of the application** and include **log files** from following location:
|
||||
For bug reports, **PLEASE mention version of Trilium you're using** and also include **log files** from following location:
|
||||
|
||||
* `/home/[user]/.local/share/trilium-data/log` for Linux
|
||||
* `C:\Users\[user]\AppData\Roaming\trilium-data\log` for Windows Vista and up
|
||||
|
||||
@@ -1,167 +1,20 @@
|
||||
/*
|
||||
* !!!!!!! This stylesheet is heavily modified compared to the original for similarity with in-editor look !!!!!!!
|
||||
* This is used for printing and tar HTML export
|
||||
|
||||
* CKEditor 5 (v17.0.0) content styles.
|
||||
* Generated on Fri, 13 Mar 2020 13:27:10 GMT.
|
||||
* CKEditor 5 (v19.1.1) content styles.
|
||||
* Generated on Fri, 19 Jun 2020 01:26:44 GMT.
|
||||
* For more information, check out https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/content-styles.html
|
||||
*/
|
||||
|
||||
:root {
|
||||
--ck-highlight-marker-blue: #72cdfd;
|
||||
--ck-highlight-marker-green: #63f963;
|
||||
--ck-highlight-marker-pink: #fc7999;
|
||||
--ck-highlight-marker-yellow: #fdfd77;
|
||||
--ck-highlight-pen-green: #118800;
|
||||
--ck-highlight-pen-red: #e91313;
|
||||
--ck-highlight-marker-blue: hsl(201, 97%, 72%);
|
||||
--ck-highlight-marker-green: hsl(120, 93%, 68%);
|
||||
--ck-highlight-marker-pink: hsl(345, 96%, 73%);
|
||||
--ck-highlight-marker-yellow: hsl(60, 97%, 73%);
|
||||
--ck-highlight-pen-green: hsl(112, 100%, 27%);
|
||||
--ck-highlight-pen-red: hsl(0, 85%, 49%);
|
||||
--ck-image-style-spacing: 1.5em;
|
||||
--ck-todo-list-checkmark-size: 16px;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized img {
|
||||
width: 100%;
|
||||
}
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized > figcaption {
|
||||
display: block;
|
||||
}
|
||||
/* ckeditor5-basic-styles/theme/code.css */
|
||||
.ck-content code {
|
||||
background-color: hsla(0, 0%, 78%, 0.3);
|
||||
padding: .15em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image {
|
||||
display: table;
|
||||
clear: both;
|
||||
text-align: center;
|
||||
margin: 1em auto;
|
||||
}
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image > img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
min-width: 50px;
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-side,
|
||||
.ck-content .image-style-align-left,
|
||||
.ck-content .image-style-align-center,
|
||||
.ck-content .image-style-align-right {
|
||||
max-width: 50%;
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-side {
|
||||
float: right;
|
||||
margin-left: var(--ck-image-style-spacing);
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-left {
|
||||
float: left;
|
||||
margin-right: var(--ck-image-style-spacing);
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-right {
|
||||
float: right;
|
||||
margin-left: var(--ck-image-style-spacing);
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break {
|
||||
position: relative;
|
||||
clear: both;
|
||||
padding: 5px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-bottom: 2px dashed hsl(0, 0%, 77%);
|
||||
width: 100%;
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break__label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: .3em .6em;
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
border: 1px solid hsl(0, 0%, 77%);
|
||||
border-radius: 2px;
|
||||
font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
color: hsl(0, 0%, 20%);
|
||||
background: #fff;
|
||||
box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15);
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||
.ck-content blockquote {
|
||||
overflow: hidden;
|
||||
padding-right: 1.5em;
|
||||
padding-left: 1.5em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
font-style: italic;
|
||||
border-left: solid 5px hsl(0, 0%, 80%);
|
||||
}
|
||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||
.ck-content[dir="rtl"] blockquote {
|
||||
border-left: 0;
|
||||
border-right: solid 5px hsl(0, 0%, 80%);
|
||||
}
|
||||
/* ckeditor5-media-embed/theme/mediaembed.css */
|
||||
.ck-content .media {
|
||||
clear: both;
|
||||
margin: 1em 0;
|
||||
display: block;
|
||||
min-width: 15em;
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table {
|
||||
margin: 1em auto;
|
||||
display: table;
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px double hsl(0, 0%, 70%);
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table td,
|
||||
.ck-content .table table th {
|
||||
min-width: 2em;
|
||||
padding: .4em;
|
||||
border-color: hsl(0, 0%, 75%);
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table th {
|
||||
font-weight: bold;
|
||||
background: hsla(0, 0%, 0%, 5%);
|
||||
}
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list {
|
||||
list-style: none;
|
||||
@@ -229,6 +82,95 @@
|
||||
.ck-content .todo-list .todo-list__label .todo-list__label__description {
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* ckeditor5-media-embed/theme/mediaembed.css */
|
||||
.ck-content .media {
|
||||
clear: both;
|
||||
margin: 1em 0;
|
||||
display: block;
|
||||
min-width: 15em;
|
||||
}
|
||||
/* ckeditor5-basic-styles/theme/code.css */
|
||||
.ck-content code {
|
||||
background-color: hsla(0, 0%, 78%, 0.3);
|
||||
padding: .15em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||
.ck-content blockquote {
|
||||
overflow: hidden;
|
||||
padding-right: 1.5em;
|
||||
padding-left: 1.5em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
font-style: italic;
|
||||
border-left: solid 5px hsl(0, 0%, 80%);
|
||||
}
|
||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||
.ck-content[dir="rtl"] blockquote {
|
||||
border-left: 0;
|
||||
border-right: solid 5px hsl(0, 0%, 80%);
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table {
|
||||
margin: 1em auto;
|
||||
display: table;
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px double hsl(0, 0%, 70%);
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table td,
|
||||
.ck-content .table table th {
|
||||
min-width: 2em;
|
||||
padding: .4em;
|
||||
border: 1px solid hsl(0, 0%, 75%);
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table th {
|
||||
font-weight: bold;
|
||||
background: hsla(0, 0%, 0%, 5%);
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content[dir="rtl"] .table th {
|
||||
text-align: right;
|
||||
}
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content[dir="ltr"] .table th {
|
||||
text-align: left;
|
||||
}
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized img {
|
||||
width: 100%;
|
||||
}
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized > figcaption {
|
||||
display: block;
|
||||
}
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image {
|
||||
display: table;
|
||||
clear: both;
|
||||
text-align: center;
|
||||
margin: 1em auto;
|
||||
}
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
min-width: 50px;
|
||||
}
|
||||
/* ckeditor5-image/theme/imagecaption.css */
|
||||
.ck-content .image > figcaption {
|
||||
display: table-caption;
|
||||
@@ -266,17 +208,89 @@
|
||||
color: var(--ck-highlight-pen-green);
|
||||
background-color: transparent;
|
||||
}
|
||||
/* ckeditor5-horizontal-line/theme/horizontalline.css */
|
||||
.ck-content hr {
|
||||
border-width: 1px 0 0;
|
||||
border-style: solid;
|
||||
border-color: hsl(0, 0%, 37%);
|
||||
margin: 0;
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-side,
|
||||
.ck-content .image-style-align-left,
|
||||
.ck-content .image-style-align-center,
|
||||
.ck-content .image-style-align-right {
|
||||
max-width: 50%;
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-side {
|
||||
float: right;
|
||||
margin-left: var(--ck-image-style-spacing);
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-left {
|
||||
float: left;
|
||||
margin-right: var(--ck-image-style-spacing);
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-right {
|
||||
float: right;
|
||||
margin-left: var(--ck-image-style-spacing);
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break {
|
||||
position: relative;
|
||||
clear: both;
|
||||
padding: 5px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-bottom: 2px dashed hsl(0, 0%, 77%);
|
||||
width: 100%;
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break__label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: .3em .6em;
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
border: 1px solid hsl(0, 0%, 77%);
|
||||
border-radius: 2px;
|
||||
font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
color: hsl(0, 0%, 20%);
|
||||
background: hsl(0, 0%, 100%);
|
||||
box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15);
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-tiny {
|
||||
font-size: .7em;
|
||||
}
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-small {
|
||||
font-size: .85em;
|
||||
}
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-big {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-huge {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
/* ckeditor5-code-block/theme/codeblock.css */
|
||||
.ck-content pre {
|
||||
padding: 1em;
|
||||
color: #353535;
|
||||
color: hsl(0, 0%, 20.8%);
|
||||
background: hsla(0, 0%, 78%, 0.3);
|
||||
border: 1px solid hsl(0, 0%, 77%);
|
||||
border-radius: 2px;
|
||||
@@ -293,6 +307,13 @@
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
/* ckeditor5-horizontal-line/theme/horizontalline.css */
|
||||
.ck-content hr {
|
||||
margin: 15px 0;
|
||||
height: 4px;
|
||||
background: hsl(0, 0%, 87%);
|
||||
border: 0;
|
||||
}
|
||||
@media print {
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break {
|
||||
@@ -302,4 +323,10 @@
|
||||
.ck-content .page-break::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* !!!!!! TRILIUM CUSTOM CHANGES !!!!!! */
|
||||
|
||||
.ck-widget__type-around { /* gets rid of triangles: https://github.com/zadam/trilium/issues/1129 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
2
libraries/ckeditor/ckeditor.js
vendored
2
libraries/ckeditor/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2986,7 +2986,7 @@ var uniqueId = $.fn.extend( {
|
||||
self = this,
|
||||
wasExpanded = this.isExpanded();
|
||||
|
||||
_assert(this.isLazy(), "load() requires a lazy node");
|
||||
//_assert(this.isLazy(), "load() requires a lazy node");
|
||||
// _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" );
|
||||
if (!forceReload && !this.isUndefined()) {
|
||||
return _getResolvedPromise(this);
|
||||
|
||||
2473
package-lock.json
generated
2473
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.41.1-beta",
|
||||
"version": "0.43.3",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@@ -16,27 +16,28 @@
|
||||
"start-server": "TRILIUM_ENV=dev node ./src/www",
|
||||
"start-electron": "TRILIUM_ENV=dev electron .",
|
||||
"build-backend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js",
|
||||
"build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/javascripts/entities/*.js src/public/javascripts/services/frontend_script_api.js",
|
||||
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs"
|
||||
"build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js",
|
||||
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
|
||||
"webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-mutex": "0.2.1",
|
||||
"async-mutex": "0.2.2",
|
||||
"axios": "0.19.2",
|
||||
"body-parser": "1.19.0",
|
||||
"cls-hooked": "4.2.2",
|
||||
"commonmark": "0.29.1",
|
||||
"cookie-parser": "1.4.5",
|
||||
"csurf": "1.11.0",
|
||||
"dayjs": "1.8.23",
|
||||
"dayjs": "1.8.26",
|
||||
"debug": "4.1.1",
|
||||
"ejs": "3.0.2",
|
||||
"ejs": "3.1.2",
|
||||
"electron-debug": "3.0.1",
|
||||
"electron-dl": "3.0.0",
|
||||
"electron-find": "1.0.6",
|
||||
"electron-window-state": "5.0.3",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.0",
|
||||
"file-type": "14.1.4",
|
||||
"express-session": "1.17.1",
|
||||
"file-type": "14.3.0",
|
||||
"fs-extra": "9.0.0",
|
||||
"helmet": "3.22.0",
|
||||
"html": "1.0.0",
|
||||
@@ -50,10 +51,10 @@
|
||||
"imagemin-pngquant": "8.0.0",
|
||||
"ini": "1.3.5",
|
||||
"is-svg": "4.2.1",
|
||||
"jimp": "0.10.1",
|
||||
"mime-types": "2.1.26",
|
||||
"jimp": "0.10.3",
|
||||
"mime-types": "2.1.27",
|
||||
"multer": "1.4.2",
|
||||
"node-abi": "2.15.0",
|
||||
"node-abi": "2.16.0",
|
||||
"open": "7.0.3",
|
||||
"portscanner": "2.2.0",
|
||||
"rand-token": "1.0.1",
|
||||
@@ -61,28 +62,30 @@
|
||||
"rimraf": "3.0.2",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"sax": "1.2.4",
|
||||
"semver": "7.2.1",
|
||||
"semver": "7.3.2",
|
||||
"serve-favicon": "2.5.0",
|
||||
"session-file-store": "1.4.0",
|
||||
"simple-node-logger": "18.12.24",
|
||||
"sqlite": "3.0.6",
|
||||
"sqlite": "4.0.7",
|
||||
"sqlite3": "4.1.1",
|
||||
"string-similarity": "4.0.1",
|
||||
"tar-stream": "2.1.2",
|
||||
"turndown": "6.0.0",
|
||||
"turndown-plugin-gfm": "1.0.2",
|
||||
"unescape": "1.0.1",
|
||||
"ws": "7.2.3",
|
||||
"ws": "7.2.5",
|
||||
"yauzl": "^2.10.0",
|
||||
"yazl": "^2.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "9.0.0-beta.14",
|
||||
"electron-builder": "22.4.1",
|
||||
"electron": "9.0.5",
|
||||
"electron-builder": "22.6.0",
|
||||
"electron-packager": "14.2.1",
|
||||
"electron-rebuild": "1.10.1",
|
||||
"jsdoc": "3.6.4",
|
||||
"lorem-ipsum": "2.0.3"
|
||||
"lorem-ipsum": "2.0.3",
|
||||
"webpack": "5.0.0-beta.16",
|
||||
"webpack-cli": "4.0.0-beta.8"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"electron-installer-debian": "2.0.1"
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
const anonymizationService = require('./services/anonymization');
|
||||
const backupService = require('./services/backup');
|
||||
const sqlInit = require('./services/sql_init');
|
||||
require('./entities/entity_constructor');
|
||||
|
||||
anonymizationService.anonymize().then(filePath => {
|
||||
console.log("Anonymized file has been saved to:", filePath);
|
||||
sqlInit.dbReady.then(async () => {
|
||||
try {
|
||||
console.log("Starting anonymization...");
|
||||
|
||||
process.exit(0);
|
||||
});
|
||||
const resp = await backupService.anonymize();
|
||||
|
||||
if (resp.success) {
|
||||
console.log("Anonymized file has been saved to: " + resp.anonymizedFilePath);
|
||||
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log("Anonymization failed.");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e.message, e.stack);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
13
src/app.js
13
src/app.js
@@ -28,17 +28,6 @@ app.use((req, res, next) => {
|
||||
next();
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
cls.namespace.bindEmitter(req);
|
||||
cls.namespace.bindEmitter(res);
|
||||
|
||||
cls.init(() => {
|
||||
cls.namespace.set("Hi");
|
||||
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
app.use(bodyParser.json({limit: '500mb'}));
|
||||
app.use(bodyParser.urlencoded({extended: false}));
|
||||
app.use(cookieParser());
|
||||
@@ -120,4 +109,4 @@ require('./services/scheduler');
|
||||
module.exports = {
|
||||
app,
|
||||
sessionParser
|
||||
};
|
||||
};
|
||||
|
||||
@@ -105,8 +105,7 @@ class Attribute extends Entity {
|
||||
|
||||
// cannot be static!
|
||||
updatePojo(pojo) {
|
||||
delete pojo.isOwned;
|
||||
delete pojo.__note;
|
||||
delete pojo.__note; // FIXME: probably note necessary anymore
|
||||
}
|
||||
|
||||
createClone(type, name, value) {
|
||||
@@ -124,4 +123,4 @@ class Attribute extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Attribute;
|
||||
module.exports = Attribute;
|
||||
|
||||
@@ -411,10 +411,6 @@ class Note extends Entity {
|
||||
}
|
||||
});
|
||||
|
||||
for (const attr of filteredAttributes) {
|
||||
attr.isOwned = attr.noteId === this.noteId;
|
||||
}
|
||||
|
||||
this.__attributeCache = filteredAttributes;
|
||||
}
|
||||
|
||||
@@ -545,12 +541,13 @@ class Note extends Entity {
|
||||
/**
|
||||
* @return {Promise<Attribute>}
|
||||
*/
|
||||
async addAttribute(type, name, value = "") {
|
||||
async addAttribute(type, name, value = "", isInheritable = false) {
|
||||
const attr = new Attribute({
|
||||
noteId: this.noteId,
|
||||
type: type,
|
||||
name: name,
|
||||
value: value
|
||||
value: value,
|
||||
isInheritable: isInheritable
|
||||
});
|
||||
|
||||
await attr.save();
|
||||
@@ -560,12 +557,12 @@ class Note extends Entity {
|
||||
return attr;
|
||||
}
|
||||
|
||||
async addLabel(name, value = "") {
|
||||
return await this.addAttribute(LABEL, name, value);
|
||||
async addLabel(name, value = "", isInheritable = false) {
|
||||
return await this.addAttribute(LABEL, name, value, isInheritable);
|
||||
}
|
||||
|
||||
async addRelation(name, targetNoteId) {
|
||||
return await this.addAttribute(RELATION, name, targetNoteId);
|
||||
async addRelation(name, targetNoteId, isInheritable = false) {
|
||||
return await this.addAttribute(RELATION, name, targetNoteId, isInheritable);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -946,4 +943,4 @@ class Note extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Note;
|
||||
module.exports = Note;
|
||||
|
||||
@@ -1,76 +1,19 @@
|
||||
import glob from './services/glob.js';
|
||||
import link from './services/link.js';
|
||||
import ws from './services/ws.js';
|
||||
import noteType from './widgets/note_type.js';
|
||||
import protectedSessionService from './services/protected_session.js';
|
||||
import protectedSessionHolder from './services/protected_session_holder.js';
|
||||
import FrontendScriptApi from './services/frontend_script_api.js';
|
||||
import ScriptContext from './services/script_context.js';
|
||||
import sync from './services/sync.js';
|
||||
import treeService from './services/tree.js';
|
||||
import branchService from './services/branches.js';
|
||||
import appContext from "./services/app_context.js";
|
||||
import utils from './services/utils.js';
|
||||
import server from './services/server.js';
|
||||
import Entrypoints from './services/entrypoints.js';
|
||||
import noteTooltipService from './services/note_tooltip.js';
|
||||
import bundle from "./services/bundle.js";
|
||||
import treeCache from "./services/tree_cache.js";
|
||||
import libraryLoader from "./services/library_loader.js";
|
||||
import hoistedNoteService from './services/hoisted_note.js';
|
||||
import noteTypeService from './widgets/note_type.js';
|
||||
import linkService from './services/link.js';
|
||||
import bundleService from "./services/bundle.js";
|
||||
import noteAutocompleteService from './services/note_autocomplete.js';
|
||||
import macInit from './services/mac_init.js';
|
||||
import dateNoteService from './services/date_notes.js';
|
||||
import importService from './services/import.js';
|
||||
import keyboardActionService from "./services/keyboard_actions.js";
|
||||
import splitService from "./services/split.js";
|
||||
import options from "./services/options.js";
|
||||
import noteContentRenderer from "./services/note_content_renderer.js";
|
||||
import appContext from "./services/app_context.js";
|
||||
import FlexContainer from "./widgets/flex_container.js";
|
||||
import GlobalMenuWidget from "./widgets/global_menu.js";
|
||||
import TabRowWidget from "./widgets/tab_row.js";
|
||||
import TitleBarButtonsWidget from "./widgets/title_bar_buttons.js";
|
||||
import StandardTopWidget from "./widgets/standard_top_widget.js";
|
||||
import SidePaneContainer from "./widgets/side_pane_container.js";
|
||||
import GlobalButtonsWidget from "./widgets/global_buttons.js";
|
||||
import SearchBoxWidget from "./widgets/search_box.js";
|
||||
import SearchResultsWidget from "./widgets/search_results.js";
|
||||
import NoteTreeWidget from "./widgets/note_tree.js";
|
||||
import TabCachingWidget from "./widgets/tab_caching_widget.js";
|
||||
import NotePathsWidget from "./widgets/note_paths.js";
|
||||
import NoteTitleWidget from "./widgets/note_title.js";
|
||||
import RunScriptButtonsWidget from "./widgets/run_script_buttons.js";
|
||||
import ProtectedNoteSwitchWidget from "./widgets/protected_note_switch.js";
|
||||
import NoteTypeWidget from "./widgets/note_type.js";
|
||||
import NoteActionsWidget from "./widgets/note_actions.js";
|
||||
import PromotedAttributesWidget from "./widgets/promoted_attributes.js";
|
||||
import NoteDetailWidget from "./widgets/note_detail.js";
|
||||
import NoteInfoWidget from "./widgets/note_info.js";
|
||||
import CalendarWidget from "./widgets/calendar.js";
|
||||
import AttributesWidget from "./widgets/attributes.js";
|
||||
import LinkMapWidget from "./widgets/link_map.js";
|
||||
import NoteRevisionsWidget from "./widgets/note_revisions.js";
|
||||
import SimilarNotesWidget from "./widgets/similar_notes.js";
|
||||
import WhatLinksHereWidget from "./widgets/what_links_here.js";
|
||||
import SidePaneToggles from "./widgets/side_pane_toggles.js";
|
||||
import EmptyTypeWidget from "./widgets/type_widgets/empty.js";
|
||||
import TextTypeWidget from "./widgets/type_widgets/editable_text.js";
|
||||
import CodeTypeWidget from "./widgets/type_widgets/code.js";
|
||||
import FileTypeWidget from "./widgets/type_widgets/file.js";
|
||||
import ImageTypeWidget from "./widgets/type_widgets/image.js";
|
||||
import SearchTypeWidget from "./widgets/type_widgets/search.js";
|
||||
import RenderTypeWidget from "./widgets/type_widgets/render.js";
|
||||
import RelationMapTypeWidget from "./widgets/type_widgets/relation_map.js";
|
||||
import ProtectedSessionTypeWidget from "./widgets/type_widgets/protected_session.js";
|
||||
import BookTypeWidget from "./widgets/type_widgets/book.js";
|
||||
import contextMenu from "./services/context_menu.js";
|
||||
import DesktopLayout from "./widgets/desktop_layout.js";
|
||||
import bundleService from "./services/bundle.js";
|
||||
import DesktopMainWindowLayout from "./layouts/desktop_main_window_layout.js";
|
||||
import glob from "./services/glob.js";
|
||||
import DesktopExtraWindowLayout from "./layouts/desktop_extra_window_layout.js";
|
||||
import zoomService from './services/zoom.js';
|
||||
|
||||
glob.setupGlobs();
|
||||
|
||||
if (utils.isElectron()) {
|
||||
require('electron').ipcRenderer.on('globalShortcut', async function(event, actionName) {
|
||||
utils.dynamicRequire('electron').ipcRenderer.on('globalShortcut', async function(event, actionName) {
|
||||
appContext.triggerCommand(actionName);
|
||||
});
|
||||
}
|
||||
@@ -82,9 +25,11 @@ $('[data-toggle="tooltip"]').tooltip({
|
||||
macInit.init();
|
||||
|
||||
bundleService.getWidgetBundlesByParent().then(widgetBundles => {
|
||||
const desktopLayout = new DesktopLayout(widgetBundles);
|
||||
const layout = window.glob.isMainWindow
|
||||
? new DesktopMainWindowLayout(widgetBundles)
|
||||
: new DesktopExtraWindowLayout(widgetBundles);
|
||||
|
||||
appContext.setLayout(desktopLayout);
|
||||
appContext.setLayout(layout);
|
||||
appContext.start();
|
||||
});
|
||||
|
||||
@@ -93,7 +38,7 @@ noteTooltipService.setupGlobalTooltip();
|
||||
noteAutocompleteService.init();
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const electron = require('electron');
|
||||
const electron = utils.dynamicRequire('electron');
|
||||
const {webContents} = electron.remote.getCurrentWindow();
|
||||
|
||||
webContents.on('context-menu', (event, params) => {
|
||||
@@ -141,7 +86,7 @@ if (utils.isElectron()) {
|
||||
});
|
||||
}
|
||||
|
||||
if (params.linkURL.length !== 0 && params.mediaType === 'none') {
|
||||
if (!["", "javascript:", "about:blank#blocked"].includes(params.linkURL) && params.mediaType === 'none') {
|
||||
items.push({
|
||||
title: `Copy link`,
|
||||
uiIcon: "copy",
|
||||
@@ -189,9 +134,11 @@ if (utils.isElectron()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const zoomLevel = zoomService.getCurrentZoom();
|
||||
|
||||
contextMenu.show({
|
||||
x: params.x,
|
||||
y: params.y,
|
||||
x: params.x / zoomLevel,
|
||||
y: params.y / zoomLevel,
|
||||
items,
|
||||
selectMenuItemHandler: ({command, spellingSuggestion}) => {
|
||||
if (command === 'replaceMisspelling') {
|
||||
@@ -200,4 +147,4 @@ if (utils.isElectron()) {
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,18 @@ export async function showDialog(widget) {
|
||||
|
||||
$addLinkTitleSettings.toggle(!textTypeWidget.hasSelection());
|
||||
|
||||
updateTitleFormGroupVisibility();
|
||||
$addLinkTitleSettings.find('input[type=radio]').on('change', updateTitleFormGroupVisibility);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
updateTitleFormGroupVisibility();
|
||||
|
||||
utils.openDialog($dialog);
|
||||
|
||||
$autoComplete.val('').trigger('focus');
|
||||
@@ -81,4 +90,4 @@ $form.on('submit', () => {
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -59,8 +59,8 @@ function AttributesModel() {
|
||||
});
|
||||
};
|
||||
|
||||
async function showAttributes(attributes) {
|
||||
const ownedAttributes = attributes.filter(attr => attr.isOwned);
|
||||
async function showAttributes(noteId, attributes) {
|
||||
const ownedAttributes = attributes.filter(attr => attr.noteId === noteId);
|
||||
|
||||
for (const attr of ownedAttributes) {
|
||||
attr.labelValue = attr.type === 'label' ? attr.value : '';
|
||||
@@ -86,7 +86,7 @@ function AttributesModel() {
|
||||
|
||||
addLastEmptyRow();
|
||||
|
||||
const inheritedAttributes = attributes.filter(attr => !attr.isOwned);
|
||||
const inheritedAttributes = attributes.filter(attr => attr.noteId !== noteId);
|
||||
|
||||
self.inheritedAttributes(inheritedAttributes);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ function AttributesModel() {
|
||||
|
||||
const attributes = await server.get('notes/' + noteId + '/attributes');
|
||||
|
||||
await showAttributes(attributes);
|
||||
await showAttributes(noteId, attributes);
|
||||
|
||||
// attribute might not be rendered immediatelly so could not focus
|
||||
setTimeout(() => $(".attribute-type-select:last").trigger('focus'), 1000);
|
||||
@@ -152,10 +152,10 @@ function AttributesModel() {
|
||||
attr.value = treeService.getNoteIdFromNotePath(attr.selectedPath);
|
||||
}
|
||||
else if (attr.type === 'label-definition') {
|
||||
attr.value = attr.labelDefinition;
|
||||
attr.value = JSON.stringify(attr.labelDefinition);
|
||||
}
|
||||
else if (attr.type === 'relation-definition') {
|
||||
attr.value = attr.relationDefinition;
|
||||
attr.value = JSON.stringify(attr.relationDefinition);
|
||||
}
|
||||
|
||||
delete attr.labelValue;
|
||||
@@ -166,7 +166,7 @@ function AttributesModel() {
|
||||
|
||||
const attributes = await server.put('notes/' + noteId + '/attributes', attributesToSave);
|
||||
|
||||
await showAttributes(attributes);
|
||||
await showAttributes(noteId, attributes);
|
||||
|
||||
toastService.showMessage("Attributes have been saved.");
|
||||
};
|
||||
@@ -311,4 +311,4 @@ $dialog.on('focus', '.label-value', function (e) {
|
||||
$el: $(this),
|
||||
open: true
|
||||
})
|
||||
});
|
||||
});
|
||||
@@ -39,13 +39,14 @@ export async function showDialog(noteIds) {
|
||||
}
|
||||
|
||||
async function cloneNotesTo(notePath) {
|
||||
const targetNoteId = treeService.getNoteIdFromNotePath(notePath);
|
||||
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
|
||||
const targetBranchId = await treeCache.getBranchId(parentNoteId, noteId);
|
||||
|
||||
for (const cloneNoteId of clonedNoteIds) {
|
||||
await branchService.cloneNoteTo(cloneNoteId, targetNoteId, $clonePrefix.val());
|
||||
await branchService.cloneNoteTo(cloneNoteId, targetBranchId, $clonePrefix.val());
|
||||
|
||||
const clonedNote = await treeCache.getNote(cloneNoteId);
|
||||
const targetNote = await treeCache.getNote(targetNoteId);
|
||||
const targetNote = await treeCache.getBranch(targetBranchId).getNote();
|
||||
|
||||
toastService.showMessage(`Note "${clonedNote.title}" has been cloned into ${targetNote.title}`);
|
||||
}
|
||||
@@ -64,4 +65,4 @@ $form.on('submit', () => {
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -25,13 +25,15 @@ async function includeNote(notePath) {
|
||||
const noteId = treeService.getNoteIdFromNotePath(notePath);
|
||||
const note = await treeCache.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);
|
||||
textTypeWidget.addIncludeNote(noteId, boxSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export async function importMarkdownInline() {
|
||||
}
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const {clipboard} = require('electron');
|
||||
const {clipboard} = utils.dynamicRequire('electron');
|
||||
const text = clipboard.readText();
|
||||
|
||||
convertMarkdownToHtml(text);
|
||||
@@ -32,10 +32,11 @@ export async function showDialog(branchIds) {
|
||||
noteAutocompleteService.showRecentNotes($noteAutoComplete);
|
||||
}
|
||||
|
||||
async function moveNotesTo(parentNoteId) {
|
||||
await branchService.moveToParentNote(movedBranchIds, parentNoteId);
|
||||
async function moveNotesTo(parentBranchId) {
|
||||
await branchService.moveToParentNote(movedBranchIds, parentBranchId);
|
||||
|
||||
const parentNote = await treeCache.getNote(parentNoteId);
|
||||
const parentBranch = treeCache.getBranch(parentBranchId);
|
||||
const parentNote = await parentBranch.getNote();
|
||||
|
||||
toastService.showMessage(`Selected notes have been moved into ${parentNote.title}`);
|
||||
}
|
||||
@@ -46,13 +47,12 @@ $form.on('submit', () => {
|
||||
if (notePath) {
|
||||
$dialog.modal('hide');
|
||||
|
||||
const noteId = treeService.getNoteIdFromNotePath(notePath);
|
||||
|
||||
moveNotesTo(noteId);
|
||||
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(notePath);
|
||||
treeCache.getBranchId(parentNoteId, noteId).then(branchId => moveNotesTo(branchId));
|
||||
}
|
||||
else {
|
||||
console.error("No path to move to.");
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -37,14 +37,18 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
|
||||
async function loadNoteRevisions(noteId, noteRevId) {
|
||||
$list.empty();
|
||||
$content.empty();
|
||||
$titleButtons.empty();
|
||||
|
||||
note = appContext.tabManager.getActiveTabNote();
|
||||
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));
|
||||
$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');
|
||||
@@ -59,6 +63,8 @@ async function loadNoteRevisions(noteId, noteRevId) {
|
||||
$title.text("No revisions for this note yet...");
|
||||
noteRevisionId = null;
|
||||
}
|
||||
|
||||
$eraseAllRevisionsButton.toggle(revisionItems.length > 0);
|
||||
}
|
||||
|
||||
$dialog.on('shown.bs.modal', () => {
|
||||
@@ -76,6 +82,21 @@ async function setContentPane() {
|
||||
|
||||
$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 () => {
|
||||
@@ -92,6 +113,8 @@ async function setContentPane() {
|
||||
});
|
||||
|
||||
$titleButtons
|
||||
.append($restoreRevisionButton)
|
||||
.append(' ')
|
||||
.append($eraseRevisionButton)
|
||||
.append(' ');
|
||||
|
||||
@@ -17,12 +17,18 @@ const TPL = `
|
||||
|
||||
<button id="find-and-fix-consistency-issues-button" class="btn">Find and fix consistency issues</button><br/><br/>
|
||||
|
||||
<h4>Debugging</h4>
|
||||
<h4>Anonymize database</h4>
|
||||
|
||||
<p>This action will create a new copy of the database and anonymise it (remove all note content and leave only structure and some non-sensitive metadata)
|
||||
for sharing online for debugging purposes without fear of leaking your personal data.</p>
|
||||
|
||||
<button id="anonymize-button" class="btn">Save anonymized database</button><br/><br/>
|
||||
|
||||
<p>This action will create a new copy of the database and anonymise it (remove all note content and leave only structure and metadata)
|
||||
for sharing online for debugging purposes without fear of leaking your personal data.</p>
|
||||
<h4>Backup database</h4>
|
||||
|
||||
<p>Trilium has automatic backup (daily, weekly, monthly), but you can also trigger backup manually here.</p>
|
||||
|
||||
<button id="backup-database-button" class="btn">Backup database now</button><br/><br/>
|
||||
|
||||
<h4>Vacuum database</h4>
|
||||
|
||||
@@ -37,6 +43,7 @@ export default class AdvancedOptions {
|
||||
this.$forceFullSyncButton = $("#force-full-sync-button");
|
||||
this.$fillSyncRowsButton = $("#fill-sync-rows-button");
|
||||
this.$anonymizeButton = $("#anonymize-button");
|
||||
this.$backupDatabaseButton = $("#backup-database-button");
|
||||
this.$vacuumDatabaseButton = $("#vacuum-database-button");
|
||||
this.$findAndFixConsistencyIssuesButton = $("#find-and-fix-consistency-issues-button");
|
||||
|
||||
@@ -53,21 +60,32 @@ export default class AdvancedOptions {
|
||||
});
|
||||
|
||||
this.$anonymizeButton.on('click', async () => {
|
||||
await server.post('anonymization/anonymize');
|
||||
const resp = await server.post('database/anonymize');
|
||||
|
||||
toastService.showMessage("Created anonymized database");
|
||||
if (!resp.success) {
|
||||
toastService.showError("Could not create anonymized database, check backend logs for details");
|
||||
}
|
||||
else {
|
||||
toastService.showMessage(`Created anonymized database in ${resp.anonymizedFilePath}`, 10000);
|
||||
}
|
||||
});
|
||||
|
||||
this.$backupDatabaseButton.on('click', async () => {
|
||||
const {backupFile} = await server.post('database/backup-database');
|
||||
|
||||
toastService.showMessage("Database has been backed up to " + backupFile, 10000);
|
||||
});
|
||||
|
||||
this.$vacuumDatabaseButton.on('click', async () => {
|
||||
await server.post('cleanup/vacuum-database');
|
||||
await server.post('database/vacuum-database');
|
||||
|
||||
toastService.showMessage("Database has been vacuumed");
|
||||
});
|
||||
|
||||
this.$findAndFixConsistencyIssuesButton.on('click', async () => {
|
||||
await server.post('cleanup/find-and-fix-consistency-issues');
|
||||
await server.post('database/find-and-fix-consistency-issues');
|
||||
|
||||
toastService.showMessage("Consistency issues should be fixed.");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import optionsService from "../../services/options.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import server from "../../services/server.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
|
||||
@@ -20,7 +20,9 @@ const TPL = `
|
||||
<input type="text" class="form-control" id="spell-check-language-code" placeholder="for example "en-US", "de-AT"">
|
||||
</div>
|
||||
|
||||
<p>Multiple languages can be separated by comman. Changes to the spell check options will take effect after application restart.</p>
|
||||
<p>Multiple languages can be separated by comma, e.g. <code>en-US, de-DE, cs</code>. Changes to the spell check options will take effect after application restart.</p>
|
||||
|
||||
<p><strong>Available language codes: </strong> <span id="available-language-codes"></span></p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -95,6 +97,14 @@ export default class ProtectedSessionOptions {
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$availableLanguageCodes = $("#available-language-codes");
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const {webContents} = utils.dynamicRequire('electron').remote.getCurrentWindow();
|
||||
|
||||
this.$availableLanguageCodes.text(webContents.session.availableSpellCheckerLanguages.join(', '));
|
||||
}
|
||||
|
||||
this.$eraseNotesAfterTimeInSeconds = $("#erase-notes-after-time-in-seconds");
|
||||
|
||||
this.$eraseNotesAfterTimeInSeconds.on('change', () => {
|
||||
@@ -16,26 +16,26 @@ export async function showDialog(ancestorNoteId) {
|
||||
ancestorNoteId = hoistedNoteService.getHoistedNoteId();
|
||||
}
|
||||
|
||||
const result = await server.get('recent-changes/' + ancestorNoteId);
|
||||
const recentChangesRows = await server.get('recent-changes/' + ancestorNoteId);
|
||||
|
||||
// preload all notes into cache
|
||||
await treeCache.getNotes(result.map(r => r.noteId), true);
|
||||
await treeCache.getNotes(recentChangesRows.map(r => r.noteId), true);
|
||||
|
||||
$content.empty();
|
||||
|
||||
if (result.length === 0) {
|
||||
if (recentChangesRows.length === 0) {
|
||||
$content.append("No changes yet ...");
|
||||
}
|
||||
|
||||
const groupedByDate = groupByDate(result);
|
||||
const groupedByDate = groupByDate(recentChangesRows);
|
||||
|
||||
for (const [dateDay, dayChanges] of groupedByDate) {
|
||||
const $changesList = $('<ul>');
|
||||
|
||||
const dayEl = $('<div>').append($('<b>').html(utils.formatDate(dateDay))).append($changesList);
|
||||
const dayEl = $('<div>').append($('<b>').text(dateDay)).append($changesList);
|
||||
|
||||
for (const change of dayChanges) {
|
||||
const formattedTime = utils.formatTime(utils.parseDate(change.date));
|
||||
const formattedTime = change.date.substr(11, 5);
|
||||
|
||||
let $noteLink;
|
||||
|
||||
@@ -82,7 +82,12 @@ export async function showDialog(ancestorNoteId) {
|
||||
}
|
||||
|
||||
$changesList.append($('<li>')
|
||||
.append(formattedTime + ' - ')
|
||||
.append(
|
||||
$("<span>")
|
||||
.text(formattedTime)
|
||||
.attr("title", change.date)
|
||||
)
|
||||
.append(' - ')
|
||||
.append($noteLink));
|
||||
}
|
||||
|
||||
@@ -90,25 +95,11 @@ export async function showDialog(ancestorNoteId) {
|
||||
}
|
||||
}
|
||||
|
||||
function groupByDate(result) {
|
||||
function groupByDate(rows) {
|
||||
const groupedByDate = new Map();
|
||||
const dayCache = {};
|
||||
|
||||
for (const row of result) {
|
||||
let dateDay = utils.parseDate(row.date);
|
||||
dateDay.setHours(0);
|
||||
dateDay.setMinutes(0);
|
||||
dateDay.setSeconds(0);
|
||||
dateDay.setMilliseconds(0);
|
||||
|
||||
// this stupidity is to make sure that we always use the same day object because Map uses only
|
||||
// reference equality
|
||||
if (dayCache[dateDay]) {
|
||||
dateDay = dayCache[dateDay];
|
||||
}
|
||||
else {
|
||||
dayCache[dateDay] = dateDay;
|
||||
}
|
||||
for (const row of rows) {
|
||||
const dateDay = row.date.substr(0, 10);
|
||||
|
||||
if (!groupedByDate.has(dateDay)) {
|
||||
groupedByDate.set(dateDay, []);
|
||||
86
src/public/app/entities/attribute.js
Normal file
86
src/public/app/entities/attribute.js
Normal file
@@ -0,0 +1,86 @@
|
||||
class Attribute {
|
||||
constructor(treeCache, row) {
|
||||
this.treeCache = treeCache;
|
||||
|
||||
this.update(row);
|
||||
}
|
||||
|
||||
update(row) {
|
||||
/** @param {string} attributeId */
|
||||
this.attributeId = row.attributeId;
|
||||
/** @param {string} noteId */
|
||||
this.noteId = row.noteId;
|
||||
/** @param {string} type */
|
||||
this.type = row.type;
|
||||
/** @param {string} name */
|
||||
this.name = row.name;
|
||||
/** @param {string} value */
|
||||
this.value = row.value;
|
||||
/** @param {int} position */
|
||||
this.position = row.position;
|
||||
/** @param {boolean} isInheritable */
|
||||
this.isInheritable = row.isInheritable;
|
||||
}
|
||||
|
||||
/** @returns {NoteShort} */
|
||||
getNote() {
|
||||
return this.treeCache.notes[this.noteId];
|
||||
}
|
||||
|
||||
get targetNoteId() { // alias
|
||||
return this.type === 'relation' ? this.value : undefined;
|
||||
}
|
||||
|
||||
get jsonValue() {
|
||||
try {
|
||||
return JSON.parse(this.value);
|
||||
}
|
||||
catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
get toString() {
|
||||
return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name}, value=${this.value})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} - returns true if this attribute has the potential to influence the note in the argument.
|
||||
* That can happen in multiple ways:
|
||||
* 1. attribute is owned by the note
|
||||
* 2. attribute is owned by the template of the note
|
||||
* 3. attribute is owned by some note's ancestor and is inheritable
|
||||
*/
|
||||
isAffecting(affectedNote) {
|
||||
if (!affectedNote) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const attrNote = this.getNote();
|
||||
|
||||
if (!attrNote) {
|
||||
// the note (owner of the attribute) is not even loaded into the cache so it should not affect anything else
|
||||
return false;
|
||||
}
|
||||
|
||||
const owningNotes = [affectedNote, ...affectedNote.getTemplateNotes()];
|
||||
|
||||
for (const owningNote of owningNotes) {
|
||||
if (owningNote.noteId === attrNote.noteId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isInheritable) {
|
||||
for (const owningNote of owningNotes) {
|
||||
if (owningNote.hasAncestor(attrNote)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default Attribute;
|
||||
@@ -1,5 +1,6 @@
|
||||
import server from '../services/server.js';
|
||||
import Attribute from './attribute.js';
|
||||
import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
|
||||
const LABEL = 'label';
|
||||
const LABEL_DEFINITION = 'label-definition';
|
||||
@@ -7,6 +8,8 @@ const RELATION = 'relation';
|
||||
const RELATION_DEFINITION = 'relation-definition';
|
||||
|
||||
/**
|
||||
* FIXME: since there's no "full note" anymore we can rename this to Note
|
||||
*
|
||||
* This note's representation is used in note tree and is kept in TreeCache.
|
||||
*/
|
||||
class NoteShort {
|
||||
@@ -156,9 +159,9 @@ class NoteShort {
|
||||
getOwnedAttributes(type, name) {
|
||||
const attrs = this.attributes
|
||||
.map(attributeId => this.treeCache.attributes[attributeId])
|
||||
.filter(attr => !!attr);
|
||||
.filter(Boolean); // filter out nulls;
|
||||
|
||||
return this.__filterAttrs(attrs, type, name)
|
||||
return this.__filterAttrs(attrs, type, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,48 +170,62 @@ class NoteShort {
|
||||
* @returns {Attribute[]} all note's attributes, including inherited ones
|
||||
*/
|
||||
getAttributes(type, name) {
|
||||
const ownedAttributes = this.getOwnedAttributes();
|
||||
return this.__filterAttrs(this.__getCachedAttributes([]), type, name);
|
||||
}
|
||||
|
||||
const attrArrs = [
|
||||
ownedAttributes
|
||||
];
|
||||
|
||||
for (const templateAttr of ownedAttributes.filter(oa => oa.type === 'relation' && oa.name === 'template')) {
|
||||
const templateNote = this.treeCache.getNoteFromCache(templateAttr.value);
|
||||
|
||||
if (templateNote) {
|
||||
attrArrs.push(templateNote.getAttributes());
|
||||
}
|
||||
__getCachedAttributes(path) {
|
||||
// notes/clones cannot form tree cycles, it is possible to create attribute inheritance cycle via templates
|
||||
// when template instance is a parent of template itself
|
||||
if (path.includes(this.noteId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (this.noteId !== 'root') {
|
||||
for (const parentNote of this.getParentNotes()) {
|
||||
// these virtual parent-child relationships are also loaded into frontend tree cache
|
||||
if (parentNote.type !== 'search') {
|
||||
attrArrs.push(parentNote.getInheritableAttributes());
|
||||
if (!(this.noteId in noteAttributeCache)) {
|
||||
const ownedAttributes = this.getOwnedAttributes();
|
||||
|
||||
const attrArrs = [
|
||||
ownedAttributes
|
||||
];
|
||||
|
||||
const newPath = [...path, this.noteId];
|
||||
|
||||
for (const templateAttr of ownedAttributes.filter(oa => oa.type === 'relation' && oa.name === 'template')) {
|
||||
const templateNote = this.treeCache.notes[templateAttr.value];
|
||||
|
||||
if (templateNote && templateNote.noteId !== this.noteId) {
|
||||
attrArrs.push(templateNote.__getCachedAttributes(newPath));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.noteId !== 'root') {
|
||||
for (const parentNote of this.getParentNotes()) {
|
||||
// these virtual parent-child relationships are also loaded into frontend tree cache
|
||||
if (parentNote.type !== 'search') {
|
||||
attrArrs.push(parentNote.__getInheritableAttributes(newPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
noteAttributeCache.attributes[this.noteId] = attrArrs.flat();
|
||||
}
|
||||
|
||||
const attributes = attrArrs.flat();
|
||||
|
||||
return this.__filterAttrs(attributes, type, name);
|
||||
return noteAttributeCache.attributes[this.noteId];
|
||||
}
|
||||
|
||||
__filterAttrs(attributes, type, name) {
|
||||
if (type && name) {
|
||||
if (!type && !name) {
|
||||
return attributes;
|
||||
} else if (type && name) {
|
||||
return attributes.filter(attr => attr.type === type && attr.name === name);
|
||||
} else if (type) {
|
||||
return attributes.filter(attr => attr.type === type);
|
||||
} else if (name) {
|
||||
return attributes.filter(attr => attr.name === name);
|
||||
} else {
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
|
||||
getInheritableAttributes() {
|
||||
const attrs = this.getAttributes();
|
||||
__getInheritableAttributes(path) {
|
||||
const attrs = this.__getCachedAttributes(path);
|
||||
|
||||
return attrs.filter(attr => attr.isInheritable);
|
||||
}
|
||||
@@ -420,6 +437,35 @@ class NoteShort {
|
||||
return targets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {NoteShort[]}
|
||||
*/
|
||||
getTemplateNotes() {
|
||||
const relations = this.getRelations('template');
|
||||
|
||||
return relations.map(rel => this.treeCache.notes[rel.value]);
|
||||
}
|
||||
|
||||
hasAncestor(ancestorNote) {
|
||||
if (this.noteId === ancestorNote.noteId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const templateNote of this.getTemplateNotes()) {
|
||||
if (templateNote.hasAncestor(ancestorNote)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const parentNote of this.getParentNotes()) {
|
||||
if (parentNote.hasAncestor(ancestorNote)) {console.log(parentNote);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear note's attributes cache to force fresh reload for next attribute request.
|
||||
* Cache is note instance scoped.
|
||||
@@ -438,6 +484,15 @@ class NoteShort {
|
||||
.map(attributeId => this.treeCache.attributes[attributeId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return note complement which is most importantly note's content
|
||||
*
|
||||
* @return {Promise<NoteComplement>}
|
||||
*/
|
||||
async getNoteComplement() {
|
||||
return await this.treeCache.getNoteComplement(this.noteId);
|
||||
}
|
||||
|
||||
get toString() {
|
||||
return `Note(noteId=${this.noteId}, title=${this.title})`;
|
||||
}
|
||||
@@ -455,4 +510,4 @@ class NoteShort {
|
||||
}
|
||||
}
|
||||
|
||||
export default NoteShort;
|
||||
export default NoteShort;
|
||||
46
src/public/app/layouts/desktop_extra_window_layout.js
Normal file
46
src/public/app/layouts/desktop_extra_window_layout.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import FlexContainer from "../widgets/flex_container.js";
|
||||
import GlobalMenuWidget from "../widgets/global_menu.js";
|
||||
import TabRowWidget from "../widgets/tab_row.js";
|
||||
import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import TabCachingWidget from "../widgets/tab_caching_widget.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import RunScriptButtonsWidget from "../widgets/run_script_buttons.js";
|
||||
import NoteTypeWidget from "../widgets/note_type.js";
|
||||
import NoteActionsWidget from "../widgets/note_actions.js";
|
||||
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
|
||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||
|
||||
export default class DesktopExtraWindowLayout {
|
||||
constructor(customWidgets) {
|
||||
this.customWidgets = customWidgets;
|
||||
}
|
||||
|
||||
getRootWidget(appContext) {
|
||||
appContext.mainTreeWidget = new NoteTreeWidget();
|
||||
|
||||
return new FlexContainer('column')
|
||||
.setParent(appContext)
|
||||
.id('root-widget')
|
||||
.css('height', '100vh')
|
||||
.child(new FlexContainer('row')
|
||||
.child(new GlobalMenuWidget())
|
||||
.child(new TabRowWidget())
|
||||
.child(new TitleBarButtonsWidget()))
|
||||
.child(new FlexContainer('row')
|
||||
.collapsible()
|
||||
.child(new FlexContainer('column').id('center-pane').css('flex-grow', '1')
|
||||
.child(new FlexContainer('row').class('title-row')
|
||||
.cssBlock('.title-row > * { margin: 5px; }')
|
||||
.child(new NoteTitleWidget())
|
||||
.child(new RunScriptButtonsWidget().hideInZenMode())
|
||||
.child(new NoteTypeWidget().hideInZenMode())
|
||||
.child(new NoteActionsWidget().hideInZenMode())
|
||||
)
|
||||
.child(new TabCachingWidget(() => new PromotedAttributesWidget()))
|
||||
.child(new TabCachingWidget(() => new NoteDetailWidget()))
|
||||
.child(...this.customWidgets.get('center-pane'))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,30 @@
|
||||
import FlexContainer from "./flex_container.js";
|
||||
import GlobalMenuWidget from "./global_menu.js";
|
||||
import TabRowWidget from "./tab_row.js";
|
||||
import TitleBarButtonsWidget from "./title_bar_buttons.js";
|
||||
import StandardTopWidget from "./standard_top_widget.js";
|
||||
import SidePaneContainer from "./side_pane_container.js";
|
||||
import GlobalButtonsWidget from "./global_buttons.js";
|
||||
import SearchBoxWidget from "./search_box.js";
|
||||
import SearchResultsWidget from "./search_results.js";
|
||||
import NoteTreeWidget from "./note_tree.js";
|
||||
import TabCachingWidget from "./tab_caching_widget.js";
|
||||
import NotePathsWidget from "./note_paths.js";
|
||||
import NoteTitleWidget from "./note_title.js";
|
||||
import RunScriptButtonsWidget from "./run_script_buttons.js";
|
||||
import ProtectedNoteSwitchWidget from "./protected_note_switch.js";
|
||||
import NoteTypeWidget from "./note_type.js";
|
||||
import NoteActionsWidget from "./note_actions.js";
|
||||
import PromotedAttributesWidget from "./promoted_attributes.js";
|
||||
import NoteDetailWidget from "./note_detail.js";
|
||||
import NoteInfoWidget from "./note_info.js";
|
||||
import CalendarWidget from "./calendar.js";
|
||||
import AttributesWidget from "./attributes.js";
|
||||
import LinkMapWidget from "./link_map.js";
|
||||
import NoteRevisionsWidget from "./note_revisions.js";
|
||||
import SimilarNotesWidget from "./similar_notes.js";
|
||||
import WhatLinksHereWidget from "./what_links_here.js";
|
||||
import SidePaneToggles from "./side_pane_toggles.js";
|
||||
import appContext from "../services/app_context.js";
|
||||
import FlexContainer from "../widgets/flex_container.js";
|
||||
import GlobalMenuWidget from "../widgets/global_menu.js";
|
||||
import TabRowWidget from "../widgets/tab_row.js";
|
||||
import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
|
||||
import StandardTopWidget from "../widgets/standard_top_widget.js";
|
||||
import SidePaneContainer from "../widgets/side_pane_container.js";
|
||||
import GlobalButtonsWidget from "../widgets/global_buttons.js";
|
||||
import SearchBoxWidget from "../widgets/search_box.js";
|
||||
import SearchResultsWidget from "../widgets/search_results.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import TabCachingWidget from "../widgets/tab_caching_widget.js";
|
||||
import NotePathsWidget from "../widgets/note_paths.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import RunScriptButtonsWidget from "../widgets/run_script_buttons.js";
|
||||
import NoteTypeWidget from "../widgets/note_type.js";
|
||||
import NoteActionsWidget from "../widgets/note_actions.js";
|
||||
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
|
||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||
import NoteInfoWidget from "../widgets/collapsible_widgets/note_info.js";
|
||||
import CalendarWidget from "../widgets/collapsible_widgets/calendar.js";
|
||||
import AttributesWidget from "../widgets/collapsible_widgets/attributes.js";
|
||||
import LinkMapWidget from "../widgets/collapsible_widgets/link_map.js";
|
||||
import NoteRevisionsWidget from "../widgets/collapsible_widgets/note_revisions.js";
|
||||
import SimilarNotesWidget from "../widgets/collapsible_widgets/similar_notes.js";
|
||||
import WhatLinksHereWidget from "../widgets/collapsible_widgets/what_links_here.js";
|
||||
import SidePaneToggles from "../widgets/side_pane_toggles.js";
|
||||
import EditedNotesWidget from "../widgets/collapsible_widgets/edited_notes.js";
|
||||
|
||||
const RIGHT_PANE_CSS = `
|
||||
<style>
|
||||
@@ -98,13 +97,13 @@ const RIGHT_PANE_CSS = `
|
||||
}
|
||||
</style>`;
|
||||
|
||||
export default class DesktopLayout {
|
||||
export default class DesktopMainWindowLayout {
|
||||
constructor(customWidgets) {
|
||||
this.customWidgets = customWidgets;
|
||||
}
|
||||
|
||||
getRootWidget(appContext) {
|
||||
appContext.mainTreeWidget = new NoteTreeWidget();
|
||||
appContext.mainTreeWidget = new NoteTreeWidget("main");
|
||||
|
||||
return new FlexContainer('column')
|
||||
.setParent(appContext)
|
||||
@@ -118,6 +117,7 @@ export default class DesktopLayout {
|
||||
.hideInZenMode())
|
||||
.child(new FlexContainer('row')
|
||||
.collapsible()
|
||||
.filling()
|
||||
.child(new SidePaneContainer('left')
|
||||
.hideInZenMode()
|
||||
.child(new GlobalButtonsWidget())
|
||||
@@ -132,7 +132,6 @@ export default class DesktopLayout {
|
||||
.cssBlock('.title-row > * { margin: 5px; }')
|
||||
.child(new NoteTitleWidget())
|
||||
.child(new RunScriptButtonsWidget().hideInZenMode())
|
||||
.child(new ProtectedNoteSwitchWidget().hideInZenMode())
|
||||
.child(new NoteTypeWidget().hideInZenMode())
|
||||
.child(new NoteActionsWidget().hideInZenMode())
|
||||
)
|
||||
@@ -145,6 +144,7 @@ export default class DesktopLayout {
|
||||
.hideInZenMode()
|
||||
.child(new NoteInfoWidget())
|
||||
.child(new TabCachingWidget(() => new CalendarWidget()))
|
||||
.child(new TabCachingWidget(() => new EditedNotesWidget()))
|
||||
.child(new TabCachingWidget(() => new AttributesWidget()))
|
||||
.child(new TabCachingWidget(() => new LinkMapWidget()))
|
||||
.child(new TabCachingWidget(() => new NoteRevisionsWidget()))
|
||||
@@ -155,4 +155,4 @@ export default class DesktopLayout {
|
||||
.child(new SidePaneToggles().hideInZenMode())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import FlexContainer from "./flex_container.js";
|
||||
import NoteTitleWidget from "./note_title.js";
|
||||
import NoteDetailWidget from "./note_detail.js";
|
||||
import NoteTreeWidget from "./note_tree.js";
|
||||
import MobileGlobalButtonsWidget from "./mobile_global_buttons.js";
|
||||
import CloseDetailButtonWidget from "./close_detail_button.js";
|
||||
import MobileDetailMenuWidget from "./mobile_detail_menu.js";
|
||||
import ScreenContainer from "./screen_container.js";
|
||||
import FlexContainer from "../widgets/flex_container.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import MobileGlobalButtonsWidget from "../widgets/mobile_widgets/mobile_global_buttons.js";
|
||||
import CloseDetailButtonWidget from "../widgets/mobile_widgets/close_detail_button.js";
|
||||
import MobileDetailMenuWidget from "../widgets/mobile_widgets/mobile_detail_menu.js";
|
||||
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
|
||||
|
||||
const MOBILE_CSS = `
|
||||
<style>
|
||||
@@ -73,7 +73,7 @@ export default class MobileLayout {
|
||||
.child(new ScreenContainer("tree", 'column')
|
||||
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-5 col-md-4 col-lg-4 col-xl-4")
|
||||
.child(new MobileGlobalButtonsWidget())
|
||||
.child(new NoteTreeWidget().cssBlock(FANCYTREE_CSS)))
|
||||
.child(new NoteTreeWidget("main").cssBlock(FANCYTREE_CSS)))
|
||||
.child(new ScreenContainer("detail", "column")
|
||||
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-8")
|
||||
.child(new FlexContainer('row')
|
||||
8
src/public/app/mobile.js
Normal file
8
src/public/app/mobile.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import appContext from "./services/app_context.js";
|
||||
import MobileLayout from "./layouts/mobile_layout.js";
|
||||
import glob from "./services/glob.js";
|
||||
|
||||
glob.setupGlobs();
|
||||
|
||||
appContext.setLayout(new MobileLayout());
|
||||
appContext.start();
|
||||
@@ -4,15 +4,22 @@ import DialogCommandExecutor from "./dialog_command_executor.js";
|
||||
import Entrypoints from "./entrypoints.js";
|
||||
import options from "./options.js";
|
||||
import utils from "./utils.js";
|
||||
import ZoomService from "./zoom.js";
|
||||
import zoomService from "./zoom.js";
|
||||
import TabManager from "./tab_manager.js";
|
||||
import treeService from "./tree.js";
|
||||
import Component from "../widgets/component.js";
|
||||
import keyboardActionsService from "./keyboard_actions.js";
|
||||
import MobileScreenSwitcherExecutor from "../widgets/mobile_screen_switcher.js";
|
||||
import MobileScreenSwitcherExecutor from "../widgets/mobile_widgets/mobile_screen_switcher.js";
|
||||
import MainTreeExecutors from "./main_tree_executors.js";
|
||||
|
||||
class AppContext extends Component {
|
||||
constructor(isMainWindow) {
|
||||
super();
|
||||
|
||||
this.isMainWindow = isMainWindow;
|
||||
this.executors = [];
|
||||
}
|
||||
|
||||
setLayout(layout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
@@ -20,11 +27,15 @@ class AppContext extends Component {
|
||||
async start() {
|
||||
await Promise.all([treeCache.initializedPromise, options.initializedPromise]);
|
||||
|
||||
$("#loading-indicator").hide();
|
||||
|
||||
this.showWidgets();
|
||||
|
||||
this.tabManager.loadTabs();
|
||||
|
||||
setTimeout(() => bundleService.executeStartupBundles(), 2000);
|
||||
if (utils.isDesktop()) {
|
||||
setTimeout(() => bundleService.executeStartupBundles(), 2000);
|
||||
}
|
||||
}
|
||||
|
||||
showWidgets() {
|
||||
@@ -35,10 +46,12 @@ class AppContext extends Component {
|
||||
|
||||
$("body").append($renderedWidget);
|
||||
|
||||
$renderedWidget.on('click', "[data-trigger-command]", e => {
|
||||
const commandName = $(e.target).attr('data-trigger-command');
|
||||
$renderedWidget.on('click', "[data-trigger-command]", function() {
|
||||
const commandName = $(this).attr('data-trigger-command');
|
||||
const $component = $(this).closest(".component");
|
||||
const component = $component.prop("component");
|
||||
|
||||
this.triggerCommand(commandName);
|
||||
component.triggerCommand(commandName, {$el: $(this)});
|
||||
});
|
||||
|
||||
this.tabManager = new TabManager();
|
||||
@@ -61,7 +74,7 @@ class AppContext extends Component {
|
||||
}
|
||||
|
||||
if (utils.isElectron()) {
|
||||
this.child(new ZoomService());
|
||||
this.child(zoomService);
|
||||
}
|
||||
|
||||
this.triggerEvent('initialRenderComplete');
|
||||
@@ -82,6 +95,8 @@ class AppContext extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
// this might hint at error but sometimes this is used by components which are at different places
|
||||
// in the component tree to communicate with each other
|
||||
console.debug(`Unhandled command ${name}, converting to event.`);
|
||||
|
||||
return this.triggerEvent(name, data);
|
||||
@@ -90,15 +105,9 @@ class AppContext extends Component {
|
||||
getComponentByEl(el) {
|
||||
return $(el).closest(".component").prop('component');
|
||||
}
|
||||
|
||||
async protectedSessionStartedEvent() {
|
||||
await treeCache.loadInitialTree();
|
||||
|
||||
this.triggerEvent('treeCacheReloaded');
|
||||
}
|
||||
}
|
||||
|
||||
const appContext = new AppContext();
|
||||
const appContext = new AppContext(window.glob.isMainWindow);
|
||||
|
||||
// we should save all outstanding changes before the page/app is closed
|
||||
$(window).on('beforeunload', () => {
|
||||
@@ -126,4 +135,4 @@ $(window).on('hashchange', function() {
|
||||
}
|
||||
});
|
||||
|
||||
export default appContext;
|
||||
export default appContext;
|
||||
@@ -45,7 +45,7 @@ async function moveAfterBranch(branchIdsToMove, afterBranchId) {
|
||||
}
|
||||
}
|
||||
|
||||
async function moveToParentNote(branchIdsToMove, newParentNoteId) {
|
||||
async function moveToParentNote(branchIdsToMove, newParentBranchId) {
|
||||
branchIdsToMove = filterRootNote(branchIdsToMove);
|
||||
|
||||
for (const branchIdToMove of branchIdsToMove) {
|
||||
@@ -56,7 +56,7 @@ async function moveToParentNote(branchIdsToMove, newParentNoteId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const resp = await server.put(`branches/${branchIdToMove}/move-to/${newParentNoteId}`);
|
||||
const resp = await server.put(`branches/${branchIdToMove}/move-to/${newParentBranchId}`);
|
||||
|
||||
if (!resp.success) {
|
||||
alert(resp.message);
|
||||
@@ -198,8 +198,8 @@ ws.subscribeToMessages(async message => {
|
||||
}
|
||||
});
|
||||
|
||||
async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
|
||||
const resp = await server.put('notes/' + childNoteId + '/clone-to/' + parentNoteId, {
|
||||
async function cloneNoteTo(childNoteId, parentBranchId, prefix) {
|
||||
const resp = await server.put(`notes/${childNoteId}/clone-to/${parentBranchId}`, {
|
||||
prefix: prefix
|
||||
});
|
||||
|
||||
@@ -225,4 +225,4 @@ export default {
|
||||
moveNodeUpInHierarchy,
|
||||
cloneNoteAfter,
|
||||
cloneNoteTo
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import ScriptContext from "./script_context.js";
|
||||
import server from "./server.js";
|
||||
import toastService from "./toast.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
|
||||
async function getAndExecuteBundle(noteId, originEntity = null) {
|
||||
const bundle = await server.get('script/bundle/' + noteId);
|
||||
@@ -77,4 +76,4 @@ export default {
|
||||
getAndExecuteBundle,
|
||||
executeStartupBundles,
|
||||
getWidgetBundlesByParent
|
||||
}
|
||||
}
|
||||
@@ -33,13 +33,13 @@ async function pasteAfter(afterBranchId) {
|
||||
}
|
||||
}
|
||||
|
||||
async function pasteInto(parentNoteId) {
|
||||
async function pasteInto(parentBranchId) {
|
||||
if (isClipboardEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clipboardMode === 'cut') {
|
||||
await branchService.moveToParentNote(clipboardBranchIds, parentNoteId);
|
||||
await branchService.moveToParentNote(clipboardBranchIds, parentBranchId);
|
||||
|
||||
clipboardBranchIds = [];
|
||||
clipboardMode = null;
|
||||
@@ -50,7 +50,7 @@ async function pasteInto(parentNoteId) {
|
||||
for (const clipboardBranch of clipboardBranches) {
|
||||
const clipboardNote = await clipboardBranch.getNote();
|
||||
|
||||
await branchService.cloneNoteTo(clipboardNote.noteId, parentNoteId);
|
||||
await branchService.cloneNoteTo(clipboardNote.noteId, parentBranchId);
|
||||
}
|
||||
|
||||
// copy will keep clipboardBranchIds and clipboardMode so it's possible to paste into multiple places
|
||||
@@ -89,4 +89,4 @@ export default {
|
||||
cut,
|
||||
copy,
|
||||
isClipboardEmpty
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
import utils from "./utils.js";
|
||||
import treeService from "./tree.js";
|
||||
import dateNoteService from "./date_notes.js";
|
||||
import hoistedNoteService from "./hoisted_note.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
import server from "./server.js";
|
||||
import appContext from "./app_context.js";
|
||||
import Component from "../widgets/component.js";
|
||||
import toastService from "./toast.js";
|
||||
import noteCreateService from "./note_create.js";
|
||||
import ws from "./ws.js";
|
||||
import bundleService from "./bundle.js";
|
||||
|
||||
export default class Entrypoints extends Component {
|
||||
constructor() {
|
||||
@@ -36,7 +35,7 @@ export default class Entrypoints extends Component {
|
||||
|
||||
openDevToolsCommand() {
|
||||
if (utils.isElectron()) {
|
||||
require('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
utils.dynamicRequire('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +44,8 @@ export default class Entrypoints extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const {remote} = require('electron');
|
||||
const {FindInPage} = require('electron-find');
|
||||
const {remote} = utils.dynamicRequire('electron');
|
||||
const {FindInPage} = utils.dynamicRequire('electron-find');
|
||||
const findInPage = new FindInPage(remote.getCurrentWebContents(), {
|
||||
offsetTop: 10,
|
||||
offsetRight: 10,
|
||||
@@ -98,7 +97,7 @@ export default class Entrypoints extends Component {
|
||||
|
||||
toggleFullscreenCommand() {
|
||||
if (utils.isElectron()) {
|
||||
const win = require('electron').remote.getCurrentWindow();
|
||||
const win = utils.dynamicRequire('electron').remote.getCurrentWindow();
|
||||
|
||||
if (win.isFullScreenable()) {
|
||||
win.setFullScreen(!win.isFullScreen());
|
||||
@@ -139,7 +138,7 @@ export default class Entrypoints extends Component {
|
||||
backInNoteHistoryCommand() {
|
||||
if (utils.isElectron()) {
|
||||
// standard JS version does not work completely correctly in electron
|
||||
const webContents = require('electron').remote.getCurrentWebContents();
|
||||
const webContents = utils.dynamicRequire('electron').remote.getCurrentWebContents();
|
||||
const activeIndex = parseInt(webContents.getActiveIndex());
|
||||
|
||||
webContents.goToIndex(activeIndex - 1);
|
||||
@@ -152,7 +151,7 @@ export default class Entrypoints extends Component {
|
||||
forwardInNoteHistoryCommand() {
|
||||
if (utils.isElectron()) {
|
||||
// standard JS version does not work completely correctly in electron
|
||||
const webContents = require('electron').remote.getCurrentWebContents();
|
||||
const webContents = utils.dynamicRequire('electron').remote.getCurrentWebContents();
|
||||
const activeIndex = parseInt(webContents.getActiveIndex());
|
||||
|
||||
webContents.goToIndex(activeIndex + 1);
|
||||
@@ -184,4 +183,40 @@ export default class Entrypoints extends Component {
|
||||
}
|
||||
|
||||
createTopLevelNoteCommand() { noteCreateService.createNewTopLevelNote(); }
|
||||
|
||||
async openInWindowCommand({notePath}) {
|
||||
if (utils.isElectron()) {
|
||||
const {ipcRenderer} = utils.dynamicRequire('electron');
|
||||
|
||||
ipcRenderer.send('create-extra-window', {notePath});
|
||||
}
|
||||
else {
|
||||
const url = window.location.protocol + '//' + window.location.host + window.location.pathname + '?extra=1#' + notePath;
|
||||
|
||||
window.open(url, '', 'width=1000,height=800');
|
||||
}
|
||||
}
|
||||
|
||||
async openNewWindowCommand() {
|
||||
this.openInWindowCommand({notePath: ''});
|
||||
}
|
||||
|
||||
async runActiveNoteCommand() {
|
||||
const note = appContext.tabManager.getActiveTabNote();
|
||||
|
||||
// ctrl+enter is also used elsewhere so make sure we're running only when appropriate
|
||||
if (!note || note.type !== 'code') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (note.mime.endsWith("env=frontend")) {
|
||||
await bundleService.getAndExecuteBundle(note.noteId);
|
||||
}
|
||||
|
||||
if (note.mime.endsWith("env=backend")) {
|
||||
await server.post('script/run/' + note.noteId);
|
||||
}
|
||||
|
||||
toastService.showMessage("Note executed");
|
||||
}
|
||||
}
|
||||
@@ -403,6 +403,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
||||
* @method
|
||||
*/
|
||||
this.waitUntilSynced = ws.waitForMaxKnownSyncId;
|
||||
|
||||
/**
|
||||
* This will refresh all currently opened notes which have included note specified in the parameter
|
||||
*
|
||||
* @param includedNoteId - noteId of the included note
|
||||
*/
|
||||
this.refreshIncludedNote = includedNoteId => appContext.triggerEvent('refreshIncludedNote', {noteId: includedNoteId});
|
||||
}
|
||||
|
||||
export default FrontendScriptApi;
|
||||
export default FrontendScriptApi;
|
||||
91
src/public/app/services/glob.js
Normal file
91
src/public/app/services/glob.js
Normal file
@@ -0,0 +1,91 @@
|
||||
import utils from "./utils.js";
|
||||
import appContext from "./app_context.js";
|
||||
import server from "./server.js";
|
||||
import libraryLoader from "./library_loader.js";
|
||||
import ws from "./ws.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
|
||||
function setupGlobs() {
|
||||
window.glob.PROFILING_LOG = false;
|
||||
|
||||
window.glob.isDesktop = utils.isDesktop;
|
||||
window.glob.isMobile = utils.isMobile;
|
||||
|
||||
window.glob.getComponentByEl = el => appContext.getComponentByEl(el);
|
||||
window.glob.getHeaders = server.getHeaders;
|
||||
|
||||
// required for ESLint plugin and CKEditor
|
||||
window.glob.getActiveTabNote = () => appContext.tabManager.getActiveTabNote();
|
||||
window.glob.requireLibrary = libraryLoader.requireLibrary;
|
||||
window.glob.ESLINT = libraryLoader.ESLINT;
|
||||
window.glob.appContext = appContext; // for debugging
|
||||
window.glob.treeCache = treeCache;
|
||||
|
||||
// for CKEditor integration (button on block toolbar)
|
||||
window.glob.importMarkdownInline = async () => {
|
||||
const dialog = await import("../dialogs/markdown_import.js");
|
||||
|
||||
dialog.importMarkdownInline();
|
||||
};
|
||||
|
||||
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>
|
||||
<p>
|
||||
<ul>
|
||||
<li>Just enter any text for full text search</li>
|
||||
<li><code>@abc</code> - returns notes with label abc</li>
|
||||
<li><code>@year=2019</code> - matches notes with label <code>year</code> having value <code>2019</code></li>
|
||||
<li><code>@rock @pop</code> - matches notes which have both <code>rock</code> and <code>pop</code> labels</li>
|
||||
<li><code>@rock or @pop</code> - only one of the labels must be present</li>
|
||||
<li><code>@year<=2000</code> - numerical comparison (also >, >=, <).</li>
|
||||
<li><code>@dateCreated>=MONTH-1</code> - notes created in the last month</li>
|
||||
<li><code>=handler</code> - will execute script defined in <code>handler</code> relation to get results</li>
|
||||
</ul>
|
||||
</p>`;
|
||||
|
||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
const string = msg.toLowerCase();
|
||||
|
||||
let message = "Uncaught error: ";
|
||||
|
||||
if (string.includes("script error")) {
|
||||
message += 'No details available';
|
||||
} else {
|
||||
message += [
|
||||
'Message: ' + msg,
|
||||
'URL: ' + url,
|
||||
'Line: ' + lineNo,
|
||||
'Column: ' + columnNo,
|
||||
'Error object: ' + JSON.stringify(error),
|
||||
'Stack: ' + error && error.stack
|
||||
].join(', ');
|
||||
}
|
||||
|
||||
ws.logError(message);
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
protectedSessionHolder.setProtectedSessionId(null);
|
||||
|
||||
for (const appCssNoteId of glob.appCssNoteIds || []) {
|
||||
libraryLoader.requireCss(`api/notes/download/${appCssNoteId}`);
|
||||
}
|
||||
|
||||
const wikiBaseUrl = "https://github.com/zadam/trilium/wiki/";
|
||||
|
||||
$(document).on("click", "button[data-help-page]", e => {
|
||||
const $button = $(e.target);
|
||||
|
||||
window.open(wikiBaseUrl + $button.attr("data-help-page"), '_blank');
|
||||
});
|
||||
|
||||
$("body").on("click", "a.external", function () {
|
||||
window.open($(this).attr("href"), '_blank');
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
setupGlobs
|
||||
}
|
||||
@@ -93,8 +93,8 @@ function updateDisplayedShortcuts($container) {
|
||||
}
|
||||
});
|
||||
|
||||
$container.find('button[data-command],a.icon-action[data-command],.kb-in-title').each(async (i, el) => {
|
||||
const actionName = $(el).attr('data-command');
|
||||
$container.find('[data-trigger-command]').each(async (i, el) => {
|
||||
const actionName = $(el).attr('data-trigger-command');
|
||||
const action = await getAction(actionName, true);
|
||||
|
||||
if (action) {
|
||||
@@ -81,24 +81,29 @@ function goToLink(e) {
|
||||
}
|
||||
else if (e.which === 1) {
|
||||
const activeTabContext = appContext.tabManager.getActiveTabContext();
|
||||
activeTabContext.setNote(notePath)
|
||||
activeTabContext.setNote(notePath);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const address = $link.attr('href');
|
||||
if (e.which === 1) {
|
||||
const address = $link.attr('href');
|
||||
|
||||
if (address && address.startsWith('http')) {
|
||||
window.open(address, '_blank');
|
||||
if (address && address.startsWith('http')) {
|
||||
window.open(address, '_blank');
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function newTabContextMenu(e) {
|
||||
function linkContextMenu(e) {
|
||||
const $link = $(e.target).closest("a");
|
||||
|
||||
const notePath = getNotePathFromLink($link);
|
||||
@@ -113,12 +118,16 @@ function newTabContextMenu(e) {
|
||||
x: e.pageX,
|
||||
y: e.pageY,
|
||||
items: [
|
||||
{title: "Open note in new tab", command: "openNoteInNewTab", uiIcon: "arrow-up-right"}
|
||||
{title: "Open note in new tab", command: "openNoteInNewTab", uiIcon: "empty"},
|
||||
{title: "Open note in new window", command: "openNoteInNewWindow", uiIcon: "window-open"}
|
||||
],
|
||||
selectMenuItemHandler: ({command}) => {
|
||||
if (command === 'openNoteInNewTab') {
|
||||
appContext.tabManager.openTabWithNote(notePath);
|
||||
}
|
||||
else if (command === 'openNoteInNewWindow') {
|
||||
appContext.openInNewWindow(notePath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -128,7 +137,7 @@ function newTabContextMenu(e) {
|
||||
$(document).on('mousedown', "a[data-action='note']", goToLink);
|
||||
$(document).on('mousedown', 'div.popover-content a, div.ui-tooltip-content a', goToLink);
|
||||
$(document).on('dblclick', '.note-detail-text a', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-text a', function (e) {
|
||||
$(document).on('mousedown', '.note-detail-text a:not(.reference-link)', function (e) {
|
||||
const $link = $(e.target).closest("a");
|
||||
const notePath = getNotePathFromLink($link);
|
||||
|
||||
@@ -151,20 +160,26 @@ $(document).on('mousedown', '.note-detail-text a', function (e) {
|
||||
|
||||
$(document).on('mousedown', '.note-detail-book a', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-render a', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-text.ck-read-only a,.note-detail-text a.reference-link', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-text a.reference-link', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-readonly-text a.reference-link', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-readonly-text a', goToLink);
|
||||
$(document).on('mousedown', 'a.ck-link-actions__preview', goToLink);
|
||||
$(document).on('click', 'section.include-note a', goToLink);
|
||||
$(document).on('click', 'a.ck-link-actions__preview', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$(document).on('contextmenu', 'a.ck-link-actions__preview', newTabContextMenu);
|
||||
$(document).on('contextmenu', '.note-detail-text a', newTabContextMenu);
|
||||
$(document).on('contextmenu', "a[data-action='note']", newTabContextMenu);
|
||||
$(document).on('contextmenu', ".note-detail-render a", newTabContextMenu);
|
||||
$(document).on('contextmenu', 'a.ck-link-actions__preview', linkContextMenu);
|
||||
$(document).on('contextmenu', '.note-detail-text a', linkContextMenu);
|
||||
$(document).on('contextmenu', '.note-detail-readonly-text a', linkContextMenu);
|
||||
$(document).on('contextmenu', "a[data-action='note']", linkContextMenu);
|
||||
$(document).on('contextmenu', ".note-detail-render a", linkContextMenu);
|
||||
$(document).on('contextmenu', ".note-paths-widget a", linkContextMenu);
|
||||
$(document).on('contextmenu', "section.include-note a", linkContextMenu);
|
||||
|
||||
export default {
|
||||
getNotePathFromUrl,
|
||||
createNoteLink,
|
||||
goToLink
|
||||
};
|
||||
};
|
||||
@@ -4,7 +4,7 @@ export default class LoadResults {
|
||||
|
||||
this.noteIdToSourceId = {};
|
||||
this.sourceIdToNoteIds = {};
|
||||
|
||||
|
||||
this.branches = [];
|
||||
|
||||
this.attributes = [];
|
||||
@@ -54,8 +54,9 @@ export default class LoadResults {
|
||||
this.attributes.push({attributeId, sourceId});
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
getAttributes(sourceId = 'none') {
|
||||
return this.attributes
|
||||
.filter(row => row.sourceId !== sourceId)
|
||||
.map(row => this.treeCache.attributes[row.attributeId])
|
||||
.filter(attr => !!attr);
|
||||
}
|
||||
@@ -101,6 +102,15 @@ export default class LoadResults {
|
||||
this.options.includes(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} true if there are changes which could affect the attributes (including inherited ones)
|
||||
* notably changes in note itself should not have any effect on attributes
|
||||
*/
|
||||
hasAttributeRelatedChanges() {
|
||||
return this.branches.length === 0
|
||||
&& this.attributes.length === 0;
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return Object.keys(this.noteIdToSourceId).length === 0
|
||||
&& this.branches.length === 0
|
||||
@@ -110,4 +120,4 @@ export default class LoadResults {
|
||||
&& this.contentNoteIdToSourceId.length === 0
|
||||
&& this.options.length === 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user