mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
Merge branch 'master' into m43
This commit is contained in:
commit
83c9e6e846
18
.idea/dataSources.xml
generated
18
.idea/dataSources.xml
generated
@ -1,25 +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="SQLite - document.db" uuid="d0fd879f-1e1d-4d5c-9c21-0e5cf9ab2976">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/trilium-data/document.db</jdbc-url>
|
||||
</data-source>
|
||||
<data-source source="LOCAL" name="document" uuid="066dc5f4-4097-429e-8cf1-3adc0a9d648a">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/dist/trilium linux x64/trilium-data/document.db</jdbc-url>
|
||||
<libraries>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.16.1/xerial-sqlite-license.txt</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.16.1/sqlite-jdbc-3.16.1.jar</url>
|
||||
</library>
|
||||
</libraries>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/../trilium-data/document.db</jdbc-url>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
@ -1,692 +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.18">
|
||||
<root id="1">
|
||||
<ServerVersion>3.16.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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="39" parent="7" name="IDX_attributes_noteId_index">
|
||||
<ColNames>noteId</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="40" parent="7" name="IDX_attributes_name_value">
|
||||
<ColNames>name
|
||||
value</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="41" parent="7" name="IDX_attributes_value_index">
|
||||
<ColNames>value</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="55" parent="8" name="IDX_branches_noteId_parentNoteId">
|
||||
<ColNames>noteId
|
||||
parentNoteId</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="56" parent="8" name="IDX_branches_parentNoteId">
|
||||
<ColNames>parentNoteId</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="85" parent="11" name="IDX_note_revisions_noteId">
|
||||
<ColNames>noteId</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="86" parent="11" name="IDX_note_revisions_utcDateLastEdited">
|
||||
<ColNames>utcDateLastEdited</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="87" parent="11" name="IDX_note_revisions_utcDateCreated">
|
||||
<ColNames>utcDateCreated</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="88" parent="11" name="IDX_note_revisions_dateLastEdited">
|
||||
<ColNames>dateLastEdited</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="89" parent="11" name="IDX_note_revisions_dateCreated">
|
||||
<ColNames>dateCreated</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="106" parent="12" name="IDX_notes_title">
|
||||
<ColNames>title</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="107" parent="12" name="IDX_notes_type">
|
||||
<ColNames>type</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="108" parent="12" name="IDX_notes_isDeleted">
|
||||
<ColNames>isDeleted</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="109" parent="12" name="IDX_notes_dateCreated">
|
||||
<ColNames>dateCreated</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="110" parent="12" name="IDX_notes_dateModified">
|
||||
<ColNames>dateModified</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="111" parent="12" name="IDX_notes_utcDateCreated">
|
||||
<ColNames>utcDateCreated</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</index>
|
||||
<index id="112" parent="12" name="IDX_notes_utcDateModified">
|
||||
<ColNames>utcDateModified</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="132" parent="15" name="IDX_source_ids_utcDateCreated">
|
||||
<ColNames>utcDateCreated</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</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>integer|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>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
<Unique>1</Unique>
|
||||
</index>
|
||||
<index id="148" parent="18" name="IDX_sync_utcSyncDate">
|
||||
<ColNames>utcSyncDate</ColNames>
|
||||
<ColumnCollations></ColumnCollations>
|
||||
</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,4 +1,4 @@
|
||||
FROM node:12.16.2-alpine
|
||||
FROM node:12.16.3-alpine
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PKG_DIR=dist/trilium-linux-x64-server
|
||||
NODE_VERSION=12.16.2
|
||||
NODE_VERSION=12.16.3
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
|
@ -34,4 +34,5 @@ find $DIR/libraries -name "*.map" -type f -delete
|
||||
rm -r $DIR/src/public/app
|
||||
|
||||
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\/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
|
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
2
libraries/codemirror/mode/meta.js
vendored
2
libraries/codemirror/mode/meta.js
vendored
@ -134,7 +134,7 @@
|
||||
{name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
|
||||
{name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
|
||||
{name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
|
||||
{name: "SQLite", mime: "text/x-sqlite", mode: "sql"},
|
||||
{name: "SQLite", mimes: ["text/x-sqlite", "text/x-sqlite;schema=trilium"], mode: "sql"},
|
||||
{name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
|
||||
{name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]},
|
||||
{name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
|
||||
|
132
package-lock.json
generated
132
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.42.0-beta",
|
||||
"version": "0.42.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -1263,7 +1263,7 @@
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
}
|
||||
}
|
||||
@ -1539,7 +1539,7 @@
|
||||
},
|
||||
"uuid": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
|
||||
"integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho="
|
||||
}
|
||||
}
|
||||
@ -1573,7 +1573,7 @@
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "4.3.6",
|
||||
"resolved": "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
|
||||
"integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto="
|
||||
}
|
||||
}
|
||||
@ -1593,7 +1593,7 @@
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.5",
|
||||
@ -1853,12 +1853,12 @@
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "http://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
|
||||
"integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho="
|
||||
}
|
||||
}
|
||||
@ -1973,7 +1973,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -2148,7 +2148,7 @@
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
@ -2465,7 +2465,7 @@
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
|
||||
"requires": {
|
||||
"graceful-readlink": ">= 1.0.0"
|
||||
@ -3128,7 +3128,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -4957,7 +4957,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
},
|
||||
"getpass": {
|
||||
@ -5221,7 +5221,7 @@
|
||||
},
|
||||
"got": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "http://registry.npmjs.org/got/-/got-5.7.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz",
|
||||
"integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=",
|
||||
"requires": {
|
||||
"create-error-class": "^3.0.1",
|
||||
@ -5869,7 +5869,7 @@
|
||||
},
|
||||
"into-stream": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
|
||||
"integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
|
||||
"requires": {
|
||||
"from2": "^2.1.1",
|
||||
@ -6021,7 +6021,7 @@
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
|
||||
},
|
||||
"is-object": {
|
||||
@ -6217,9 +6217,9 @@
|
||||
}
|
||||
},
|
||||
"jest-worker": {
|
||||
"version": "25.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.4.0.tgz",
|
||||
"integrity": "sha512-ghAs/1FtfYpMmYQ0AHqxV62XPvKdUDIBBApMZfly+E9JEmYh2K45G0R5dWxx986RN12pRCxsViwQVtGl+N4whw==",
|
||||
"version": "25.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz",
|
||||
"integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"merge-stream": "^2.0.0",
|
||||
@ -6621,7 +6621,7 @@
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
@ -7130,7 +7130,7 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"minipass": {
|
||||
@ -7230,7 +7230,7 @@
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
@ -7238,7 +7238,7 @@
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
}
|
||||
}
|
||||
@ -7432,7 +7432,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
},
|
||||
"got": {
|
||||
@ -7468,7 +7468,7 @@
|
||||
},
|
||||
"p-cancelable": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "http://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz",
|
||||
"integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ=="
|
||||
},
|
||||
"p-event": {
|
||||
@ -7592,7 +7592,7 @@
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
}
|
||||
}
|
||||
@ -7617,7 +7617,7 @@
|
||||
"dependencies": {
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
},
|
||||
"pify": {
|
||||
@ -7674,7 +7674,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
||||
"integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
|
||||
"requires": {
|
||||
"object-assign": "^4.0.1",
|
||||
@ -7704,7 +7704,7 @@
|
||||
"dependencies": {
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
}
|
||||
}
|
||||
@ -7744,7 +7744,7 @@
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
|
||||
},
|
||||
"prepend-http": {
|
||||
@ -7849,7 +7849,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -8227,7 +8227,7 @@
|
||||
},
|
||||
"onetime": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="
|
||||
},
|
||||
"open": {
|
||||
@ -8379,7 +8379,7 @@
|
||||
},
|
||||
"p-is-promise": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
|
||||
"integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4="
|
||||
},
|
||||
"p-limit": {
|
||||
@ -8860,7 +8860,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
}
|
||||
}
|
||||
@ -9144,7 +9144,7 @@
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
}
|
||||
}
|
||||
@ -9169,7 +9169,7 @@
|
||||
"dependencies": {
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
},
|
||||
"pify": {
|
||||
@ -9207,7 +9207,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
}
|
||||
}
|
||||
@ -9259,7 +9259,7 @@
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
||||
"integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
|
||||
"requires": {
|
||||
"object-assign": "^4.0.1",
|
||||
@ -9289,7 +9289,7 @@
|
||||
"dependencies": {
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
}
|
||||
}
|
||||
@ -9477,7 +9477,7 @@
|
||||
},
|
||||
"query-string": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
|
||||
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
|
||||
"requires": {
|
||||
"decode-uri-component": "^0.2.0",
|
||||
@ -9616,7 +9616,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -10117,9 +10117,9 @@
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
|
||||
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz",
|
||||
"integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==",
|
||||
"dev": true
|
||||
},
|
||||
"serve-favicon": {
|
||||
@ -10272,9 +10272,9 @@
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
|
||||
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
|
||||
"version": "0.5.19",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
|
||||
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
@ -10484,7 +10484,7 @@
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
@ -10509,7 +10509,7 @@
|
||||
},
|
||||
"strip-dirs": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "http://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz",
|
||||
"integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=",
|
||||
"requires": {
|
||||
"chalk": "^1.0.0",
|
||||
@ -10709,9 +10709,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"terser": {
|
||||
"version": "4.6.11",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.11.tgz",
|
||||
"integrity": "sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==",
|
||||
"version": "4.6.13",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz",
|
||||
"integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "^2.20.0",
|
||||
@ -10728,19 +10728,19 @@
|
||||
}
|
||||
},
|
||||
"terser-webpack-plugin": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz",
|
||||
"integrity": "sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w==",
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.6.tgz",
|
||||
"integrity": "sha512-I8IDsQwZrqjdmOicNeE8L/MhwatAap3mUrtcAKJuilsemUNcX+Hier/eAzwStVqhlCxq0aG3ni9bK/0BESXkTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cacache": "^13.0.1",
|
||||
"find-cache-dir": "^3.2.0",
|
||||
"jest-worker": "^25.1.0",
|
||||
"p-limit": "^2.2.2",
|
||||
"schema-utils": "^2.6.4",
|
||||
"serialize-javascript": "^2.1.2",
|
||||
"find-cache-dir": "^3.3.1",
|
||||
"jest-worker": "^25.4.0",
|
||||
"p-limit": "^2.3.0",
|
||||
"schema-utils": "^2.6.6",
|
||||
"serialize-javascript": "^3.0.0",
|
||||
"source-map": "^0.6.1",
|
||||
"terser": "^4.4.3",
|
||||
"terser": "^4.6.12",
|
||||
"webpack-sources": "^1.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -10767,7 +10767,7 @@
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"through2": {
|
||||
@ -10786,7 +10786,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -11466,9 +11466,9 @@
|
||||
"integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA=="
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.0.0-beta.15",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.0.0-beta.15.tgz",
|
||||
"integrity": "sha512-nT+l7LteKTIzB3lmroEGL4qcCBqgHMpa3EJUvhQdfXRWjxCfWnnWdBARhp/To61omZhyNPz2Ye2J1ZEf070kWA==",
|
||||
"version": "5.0.0-beta.16",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.0.0-beta.16.tgz",
|
||||
"integrity": "sha512-O6YzI5H7XDPoXFrdC338P0GsSdhmYvz0//HL8LxVFHuRSbtHcV8mfx5U8ouWihFqwyvbfy27Bqoz2KY62kME9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.9.0",
|
||||
@ -11490,7 +11490,7 @@
|
||||
"pkg-dir": "^4.2.0",
|
||||
"schema-utils": "^2.5.0",
|
||||
"tapable": "2.0.0-beta.9",
|
||||
"terser-webpack-plugin": "^2.3.1",
|
||||
"terser-webpack-plugin": "^2.3.6",
|
||||
"watchpack": "2.0.0-beta.13",
|
||||
"webpack-sources": "2.0.0-beta.8"
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.42.0-beta",
|
||||
"version": "0.42.1",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@ -84,7 +84,7 @@
|
||||
"electron-rebuild": "1.10.1",
|
||||
"jsdoc": "3.6.4",
|
||||
"lorem-ipsum": "2.0.3",
|
||||
"webpack": "5.0.0-beta.15",
|
||||
"webpack": "5.0.0-beta.16",
|
||||
"webpack-cli": "4.0.0-beta.8"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@ -37,15 +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))
|
||||
.attr('title', 'This revision was last edited on ' + item.dateLastEdited);
|
||||
$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');
|
||||
@ -60,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', () => {
|
||||
@ -77,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 () => {
|
||||
@ -93,6 +113,8 @@ async function setContentPane() {
|
||||
});
|
||||
|
||||
$titleButtons
|
||||
.append($restoreRevisionButton)
|
||||
.append(' ')
|
||||
.append($eraseRevisionButton)
|
||||
.append(' ');
|
||||
|
||||
|
@ -68,7 +68,7 @@ export async function showDialog(ancestorNoteId) {
|
||||
}
|
||||
else {
|
||||
const note = await treeCache.getNote(change.noteId);
|
||||
const notePath = await treeService.getSomeNotePath(note);
|
||||
const notePath = treeService.getSomeNotePath(note);
|
||||
|
||||
if (notePath) {
|
||||
$noteLink = await linkService.createNoteLink(notePath, {
|
||||
|
@ -1,138 +0,0 @@
|
||||
import libraryLoader from '../services/library_loader.js';
|
||||
import server from '../services/server.js';
|
||||
import toastService from "../services/toast.js";
|
||||
import utils from "../services/utils.js";
|
||||
|
||||
const $dialog = $("#sql-console-dialog");
|
||||
const $query = $('#sql-console-query');
|
||||
const $executeButton = $('#sql-console-execute');
|
||||
const $tableSchemas = $("#sql-console-table-schemas");
|
||||
const $resultContainer = $("#result-container");
|
||||
|
||||
let codeEditor;
|
||||
|
||||
$dialog.on("shown.bs.modal", e => initEditor());
|
||||
|
||||
export async function showDialog() {
|
||||
await showTableSchemas();
|
||||
|
||||
utils.openDialog($dialog);
|
||||
}
|
||||
|
||||
async function initEditor() {
|
||||
if (!codeEditor) {
|
||||
await libraryLoader.requireLibrary(libraryLoader.CODE_MIRROR);
|
||||
|
||||
CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
|
||||
CodeMirror.keyMap.default["Tab"] = "indentMore";
|
||||
|
||||
// removing Escape binding so that Escape will propagate to the dialog (which will close on escape)
|
||||
delete CodeMirror.keyMap.basic["Esc"];
|
||||
|
||||
CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js';
|
||||
|
||||
codeEditor = CodeMirror($query[0], {
|
||||
value: "",
|
||||
viewportMargin: Infinity,
|
||||
indentUnit: 4,
|
||||
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false}
|
||||
});
|
||||
|
||||
codeEditor.setOption("mode", "text/x-sqlite");
|
||||
CodeMirror.autoLoadMode(codeEditor, "sql");
|
||||
|
||||
codeEditor.setValue(`SELECT title, isProtected, type, mime FROM notes WHERE noteId = 'root';
|
||||
---
|
||||
SELECT noteId, parentNoteId, notePosition, prefix FROM branches WHERE branchId = 'root';`);
|
||||
}
|
||||
|
||||
codeEditor.focus();
|
||||
}
|
||||
|
||||
async function execute() {
|
||||
// execute the selected text or the whole content if there's no selection
|
||||
let sqlQuery = codeEditor.getSelection();
|
||||
|
||||
if (!sqlQuery) {
|
||||
sqlQuery = codeEditor.getValue();
|
||||
}
|
||||
|
||||
const result = await server.post("sql/execute", {
|
||||
query: sqlQuery
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toastService.showError(result.error);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
toastService.showMessage("Query was executed successfully.");
|
||||
}
|
||||
|
||||
const results = result.results;
|
||||
|
||||
$resultContainer.empty();
|
||||
|
||||
for (const rows of results) {
|
||||
if (rows.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const $table = $('<table class="table table-striped">');
|
||||
$resultContainer.append($table);
|
||||
|
||||
const result = rows[0];
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<th>").html(key));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
|
||||
for (const result of rows) {
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<td>").html(result[key]));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function showTableSchemas() {
|
||||
const tables = await server.get('sql/schema');
|
||||
|
||||
$tableSchemas.empty();
|
||||
|
||||
for (const table of tables) {
|
||||
const $tableLink = $('<button class="btn">').text(table.name);
|
||||
|
||||
const $columns = $("<ul>");
|
||||
|
||||
for (const column of table.columns) {
|
||||
$columns.append(
|
||||
$("<li>")
|
||||
.append($("<span>").text(column.name))
|
||||
.append($("<span>").text(column.type))
|
||||
);
|
||||
}
|
||||
|
||||
$tableSchemas.append($tableLink).append(" ");
|
||||
|
||||
$tableLink
|
||||
.tooltip({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
boundary: 'window',
|
||||
title: $columns[0].outerHTML
|
||||
})
|
||||
.on('click', () => codeEditor.setValue("SELECT * FROM " + table.name + " LIMIT 100"));
|
||||
}
|
||||
}
|
||||
|
||||
utils.bindElShortcut($query, 'ctrl+return', execute);
|
||||
|
||||
$executeButton.on('click', execute);
|
@ -45,10 +45,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();
|
||||
@ -92,6 +94,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);
|
||||
|
@ -27,9 +27,17 @@ async function getYearNote(year) {
|
||||
return await treeCache.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/** @return {NoteShort} */
|
||||
async function createSqlConsole() {
|
||||
const note = await server.post('sql-console');
|
||||
|
||||
return await treeCache.getNote(note.noteId);
|
||||
}
|
||||
|
||||
export default {
|
||||
getTodayNote,
|
||||
getDateNote,
|
||||
getMonthNote,
|
||||
getYearNote
|
||||
getYearNote,
|
||||
createSqlConsole
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import Component from "../widgets/component.js";
|
||||
import appContext from "./app_context.js";
|
||||
import dateNoteService from "../services/date_notes.js";
|
||||
import noteCreateService from "../services/note_create.js";
|
||||
|
||||
export default class DialogCommandExecutor extends Component {
|
||||
jumpToNoteCommand() {
|
||||
@ -54,18 +56,22 @@ export default class DialogCommandExecutor extends Component {
|
||||
}
|
||||
|
||||
showOptionsCommand() {
|
||||
import("../dialogs/options.js").then(d => d.showDialog())
|
||||
import("../dialogs/options.js").then(d => d.showDialog());
|
||||
}
|
||||
|
||||
showHelpCommand() {
|
||||
import("../dialogs/help.js").then(d => d.showDialog())
|
||||
import("../dialogs/help.js").then(d => d.showDialog());
|
||||
}
|
||||
|
||||
showSQLConsoleCommand() {
|
||||
import("../dialogs/sql_console.js").then(d => d.showDialog())
|
||||
async showSQLConsoleCommand() {
|
||||
const sqlConsoleNote = await dateNoteService.createSqlConsole();
|
||||
|
||||
const tabContext = await appContext.tabManager.openTabWithNote(sqlConsoleNote.noteId, true);
|
||||
|
||||
appContext.triggerCommand('focusOnDetail', {tabId: tabContext.tabId});
|
||||
}
|
||||
|
||||
showBackendLogCommand() {
|
||||
import("../dialogs/backend_log.js").then(d => d.showDialog())
|
||||
import("../dialogs/backend_log.js").then(d => d.showDialog());
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ 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() {
|
||||
@ -199,4 +200,23 @@ export default class Entrypoints extends Component {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -38,12 +38,6 @@ export default class MainTreeExecutors extends Component {
|
||||
isProtected: activeNote.isProtected,
|
||||
saveSelection: false
|
||||
});
|
||||
|
||||
await ws.waitForMaxKnownSyncId();
|
||||
|
||||
appContext.tabManager.getActiveTabContext().setNote(note.noteId);
|
||||
|
||||
appContext.triggerCommand('focusAndSelectTitle');
|
||||
}
|
||||
|
||||
async createNoteAfterCommand() {
|
||||
@ -55,17 +49,11 @@ export default class MainTreeExecutors extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const {note} = await noteCreateService.createNote(parentNoteId, {
|
||||
await noteCreateService.createNote(parentNoteId, {
|
||||
target: 'after',
|
||||
targetBranchId: node.data.branchId,
|
||||
isProtected: isProtected,
|
||||
saveSelection: false
|
||||
});
|
||||
|
||||
await ws.waitForMaxKnownSyncId();
|
||||
|
||||
appContext.tabManager.getActiveTabContext().setNote(note.noteId);
|
||||
|
||||
appContext.triggerCommand('focusAndSelectTitle');
|
||||
}
|
||||
}
|
@ -123,6 +123,7 @@ const MIME_TYPES_DICT = [
|
||||
{ title: "Spreadsheet", mime: "text/x-spreadsheet" },
|
||||
{ default: true, title: "SQL", mime: "text/x-sql" },
|
||||
{ title: "SQLite", mime: "text/x-sqlite" },
|
||||
{ default: true, title: "SQLite (Trilium)", mime: "text/x-sqlite;schema=trilium" },
|
||||
{ title: "Squirrel", mime: "text/x-squirrel" },
|
||||
{ title: "Stylus", mime: "text/x-styl" },
|
||||
{ default: true, title: "Swift", mime: "text/x-swift" },
|
||||
|
@ -16,6 +16,7 @@ async function createNewTopLevelNote() {
|
||||
async function createNote(parentNoteId, options = {}) {
|
||||
options = Object.assign({
|
||||
activate: true,
|
||||
focus: 'title',
|
||||
target: 'into'
|
||||
}, options);
|
||||
|
||||
@ -39,7 +40,8 @@ async function createNote(parentNoteId, options = {}) {
|
||||
title: newNoteName,
|
||||
content: options.content || "",
|
||||
isProtected: options.isProtected,
|
||||
type: options.type
|
||||
type: options.type,
|
||||
mime: options.mime
|
||||
});
|
||||
|
||||
if (options.saveSelection && utils.isCKEditorInitialized()) {
|
||||
@ -49,10 +51,23 @@ async function createNote(parentNoteId, options = {}) {
|
||||
|
||||
if (options.activate) {
|
||||
const activeTabContext = appContext.tabManager.getActiveTabContext();
|
||||
activeTabContext.setNote(note.noteId);
|
||||
await activeTabContext.setNote(note.noteId);
|
||||
|
||||
if (options.focus === 'title') {
|
||||
appContext.triggerCommand('focusAndSelectTitle');
|
||||
}
|
||||
else if (options.focus === 'content') {
|
||||
appContext.triggerCommand('focusOnDetail', {tabId: this.tabId});
|
||||
}
|
||||
}
|
||||
|
||||
return {note, branch};
|
||||
const noteEntity = await treeCache.getNote(note.noteId);
|
||||
const branchEntity = treeCache.getBranchId(branch.branchId);
|
||||
|
||||
return {
|
||||
note: noteEntity,
|
||||
branch: branchEntity
|
||||
};
|
||||
}
|
||||
|
||||
/* If first element is heading, parse it out and use it as a new heading. */
|
||||
@ -86,4 +101,4 @@ export default {
|
||||
createNote,
|
||||
createNewTopLevelNote,
|
||||
duplicateNote
|
||||
};
|
||||
};
|
||||
|
@ -208,6 +208,8 @@ export default class TabManager extends Component {
|
||||
notePath: tabContext.notePath // resolved note path
|
||||
});
|
||||
}
|
||||
|
||||
return tabContext;
|
||||
}
|
||||
|
||||
async activateOrOpenNote(noteId) {
|
||||
|
@ -71,7 +71,7 @@ async function getRunPath(notePath) {
|
||||
if (parents.length > 0) {
|
||||
console.debug(utils.now(), "Available parents:", parents);
|
||||
|
||||
const someNotePath = await getSomeNotePath(parents[0]);
|
||||
const someNotePath = getSomeNotePath(parents[0]);
|
||||
|
||||
if (someNotePath) { // in case it's root the path may be empty
|
||||
const pathToRoot = someNotePath.split("/").reverse();
|
||||
@ -103,7 +103,7 @@ async function getRunPath(notePath) {
|
||||
return effectivePath.reverse();
|
||||
}
|
||||
|
||||
async function getSomeNotePath(note) {
|
||||
function getSomeNotePath(note) {
|
||||
utils.assertArguments(note);
|
||||
|
||||
const path = [];
|
||||
@ -286,4 +286,4 @@ export default {
|
||||
getNotePathTitle,
|
||||
getHashValueFromAddress,
|
||||
parseNotePath
|
||||
};
|
||||
};
|
||||
|
@ -4,7 +4,6 @@ const TPL = `
|
||||
<table class="note-info-widget-table">
|
||||
<style>
|
||||
.note-info-widget-table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -21,23 +20,25 @@ const TPL = `
|
||||
</style>
|
||||
|
||||
<tr>
|
||||
<th nowrap>Note ID:</th>
|
||||
<td nowrap colspan="3" class="note-info-note-id"></td>
|
||||
<th>Note ID:</th>
|
||||
<td class="note-info-note-id"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap>Created:</th>
|
||||
<td nowrap colspan="3" style="overflow: hidden; text-overflow: ellipsis;" class="note-info-date-created"></td>
|
||||
<th>Created:</th>
|
||||
<td class="note-info-date-created"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap>Modified:</th>
|
||||
<td nowrap colspan="3" style="overflow: hidden; text-overflow: ellipsis;" class="note-info-date-modified"></td>
|
||||
<th>Modified:</th>
|
||||
<td class="note-info-date-modified"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Type:</th>
|
||||
<td class="note-info-type"></td>
|
||||
|
||||
<th>MIME:</th>
|
||||
<td class="note-info-mime"></td>
|
||||
<td>
|
||||
<span class="note-info-type"></span>,
|
||||
|
||||
MIME:
|
||||
<span class="note-info-mime"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
`;
|
||||
@ -60,11 +61,11 @@ export default class NoteInfoWidget extends CollapsibleWidget {
|
||||
|
||||
this.$noteId.text(note.noteId);
|
||||
this.$dateCreated
|
||||
.text(noteComplement.dateCreated)
|
||||
.text(noteComplement.dateCreated.substr(0, 16))
|
||||
.attr("title", noteComplement.dateCreated);
|
||||
|
||||
this.$dateModified
|
||||
.text(noteComplement.dateModified)
|
||||
.text(noteComplement.dateModified.substr(0, 16))
|
||||
.attr("title", noteComplement.dateCreated);
|
||||
|
||||
this.$type.text(note.type);
|
||||
@ -79,4 +80,4 @@ export default class NoteInfoWidget extends CollapsibleWidget {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +18,14 @@ const WIDGET_TPL = `
|
||||
|
||||
<a data-trigger-command="collapseTree"
|
||||
title="Collapse note tree"
|
||||
data-command="collapseTree"
|
||||
class="icon-action bx bx-layer-minus"></a>
|
||||
|
||||
<a data-trigger-command="scrollToActiveNote"
|
||||
title="Scroll to active note"
|
||||
data-command="scrollToActiveNote"
|
||||
title="Scroll to active note"
|
||||
class="icon-action bx bx-crosshair"></a>
|
||||
|
||||
<a data-trigger-command="searchNotes"
|
||||
title="Search in notes"
|
||||
data-command="searchNotes"
|
||||
class="icon-action bx bx-search"></a>
|
||||
</div>
|
||||
`;
|
||||
|
@ -186,7 +186,9 @@ export default class NoteDetailWidget extends TabAwareWidget {
|
||||
const noteComplement = await this.tabContext.getNoteComplement();
|
||||
|
||||
if (note.hasLabel('readOnly') ||
|
||||
(noteComplement.content && noteComplement.content.length > 10000)) {
|
||||
(noteComplement.content
|
||||
&& noteComplement.content.length > 10000)
|
||||
&& !note.hasLabel('autoReadOnlyDisabled')) {
|
||||
type = 'read-only-text';
|
||||
}
|
||||
}
|
||||
@ -195,7 +197,9 @@ export default class NoteDetailWidget extends TabAwareWidget {
|
||||
const noteComplement = await this.tabContext.getNoteComplement();
|
||||
|
||||
if (note.hasLabel('readOnly') ||
|
||||
(noteComplement.content && noteComplement.content.length > 30000)) {
|
||||
(noteComplement.content
|
||||
&& noteComplement.content.length > 30000)
|
||||
&& !note.hasLabel('autoReadOnlyDisabled')) {
|
||||
type = 'read-only-code';
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ export default class NotePathsWidget extends TabAwareWidget {
|
||||
const activeNoteParentNoteId = pathSegments[pathSegments.length - 2]; // we know this is not root so there must be a parent
|
||||
|
||||
for (const parentNote of this.note.getParentNotes()) {
|
||||
const parentNotePath = await treeService.getSomeNotePath(parentNote);
|
||||
const parentNotePath = treeService.getSomeNotePath(parentNote);
|
||||
// this is to avoid having root notes leading '/'
|
||||
const notePath = parentNotePath ? (parentNotePath + '/' + this.noteId) : this.noteId;
|
||||
const isCurrent = activeNoteParentNoteId === parentNote.noteId;
|
||||
@ -158,4 +158,4 @@ export default class NotePathsWidget extends TabAwareWidget {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -441,6 +441,9 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
return "bx bx-note";
|
||||
}
|
||||
}
|
||||
else if (note.type === 'code' && note.mime.startsWith('text/x-sql')) {
|
||||
return "bx bx-data";
|
||||
}
|
||||
else {
|
||||
return NOTE_TYPE_ICONS[note.type];
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ import TabAwareWidget from "./tab_aware_widget.js";
|
||||
const TPL = `
|
||||
<div style="display: inline-flex;">
|
||||
<button class="btn btn-sm icon-button bx bx-play-circle render-button"
|
||||
data-trigger-command="renderActiveNote"
|
||||
title="Render"></button>
|
||||
|
||||
<button class="btn btn-sm icon-button bx bx-play-circle execute-script-button"
|
||||
title="Execute (Ctrl+Enter)"></button>
|
||||
data-trigger-command="runActiveNote"
|
||||
title="Execute"></button>
|
||||
</div>`;
|
||||
|
||||
export default class RunScriptButtonsWidget extends TabAwareWidget {
|
||||
@ -21,6 +23,12 @@ export default class RunScriptButtonsWidget extends TabAwareWidget {
|
||||
|
||||
refreshWithNote(note) {
|
||||
this.$renderButton.toggle(note.type === 'render');
|
||||
this.$executeScriptButton.toggle(note.mime.startsWith('application/javascript'));
|
||||
this.$executeScriptButton.toggle(note.type === 'code' && note.mime.startsWith('application/javascript'));
|
||||
}
|
||||
|
||||
async entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.isNoteReloaded(this.noteId)) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
@ -29,11 +29,11 @@ const TAB_TPL = `
|
||||
<div class="note-tab-wrapper">
|
||||
<div class="note-tab-title"></div>
|
||||
<div class="note-tab-drag-handle"></div>
|
||||
<div class="note-tab-close kb-in-title" title="Close tab" data-command="closeActiveTab"><span>×</span></div>
|
||||
<div class="note-tab-close" title="Close tab" data-trigger-command="closeActiveTab"><span>×</span></div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
const NEW_TAB_BUTTON_TPL = `<div class="note-new-tab kb-in-title" data-command="openNewTab" title="Add new tab">+</div>`;
|
||||
const NEW_TAB_BUTTON_TPL = `<div class="note-new-tab" data-trigger-command="openNewTab" title="Add new tab">+</div>`;
|
||||
const FILLER_TPL = `<div class="tab-row-filler">
|
||||
<div class="tab-row-border"></div>
|
||||
</div>`;
|
||||
@ -394,10 +394,13 @@ export default class TabRowWidget extends BasicWidget {
|
||||
this.setupDraggabilly();
|
||||
}
|
||||
|
||||
setTabCloseEvent($tab) {
|
||||
$tab.find('.note-tab-close')
|
||||
.on('click', _ => appContext.tabManager.removeTab($tab.attr('data-tab-id')));
|
||||
closeActiveTabCommand({$el}) {
|
||||
const tabId = $el.closest(".note-tab").attr('data-tab-id');
|
||||
|
||||
appContext.tabManager.removeTab(tabId);
|
||||
}
|
||||
|
||||
setTabCloseEvent($tab) {
|
||||
$tab.on('mousedown', e => {
|
||||
if (e.which === 2) {
|
||||
appContext.tabManager.removeTab($tab.attr('data-tab-id'));
|
||||
@ -558,8 +561,6 @@ export default class TabRowWidget extends BasicWidget {
|
||||
this.$newTab = $(NEW_TAB_BUTTON_TPL);
|
||||
|
||||
this.$tabContainer.append(this.$newTab);
|
||||
|
||||
this.$newTab.on('click', _ => this.triggerCommand('openNewTab'));
|
||||
}
|
||||
|
||||
setupFiller() {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import libraryLoader from "../../services/library_loader.js";
|
||||
import bundleService from "../../services/bundle.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
import server from "../../services/server.js";
|
||||
import keyboardActionService from "../../services/keyboard_actions.js";
|
||||
import TypeWidget from "./type_widget.js";
|
||||
import keyboardActionService from "../../services/keyboard_actions.js";
|
||||
import server from "../../services/server.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="note-detail-code note-detail-printable">
|
||||
@ -11,27 +11,75 @@ const TPL = `
|
||||
.note-detail-code {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.note-detail-code-editor {
|
||||
min-height: 500px;
|
||||
flex-basis: 200px;
|
||||
min-height: 200px;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.sql-console-table-schemas button {
|
||||
padding: 0.25rem 0.4rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 0.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.sql-console-result-wrapper {
|
||||
flex-grow: 100;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.sql-console-result-container {
|
||||
width: 100%;
|
||||
font-size: smaller;
|
||||
margin-top: 10px;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sql-console-area">
|
||||
Tables:
|
||||
<span class="sql-console-table-schemas"></span>
|
||||
</div>
|
||||
|
||||
<div class="note-detail-code-editor"></div>
|
||||
|
||||
<div class="sql-console-area sql-console-result-wrapper">
|
||||
<div style="text-align: center">
|
||||
<button class="btn btn-danger sql-console-execute">Execute query <kbd>Ctrl+Enter</kbd></button>
|
||||
</div>
|
||||
|
||||
<div class="sql-console-result-container"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
let TABLE_SCHEMA;
|
||||
|
||||
export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
static getType() { return "editable-code"; }
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$editor = this.$widget.find('.note-detail-code-editor');
|
||||
this.$executeScriptButton = this.$widget.find(".execute-script-button");
|
||||
this.$sqlConsoleArea = this.$widget.find('.sql-console-area');
|
||||
this.$sqlConsoleTableSchemas = this.$widget.find('.sql-console-table-schemas');
|
||||
this.$sqlConsoleExecuteButton = this.$widget.find('.sql-console-execute');
|
||||
this.$sqlConsoleResultContainer = this.$widget.find('.sql-console-result-container');
|
||||
|
||||
keyboardActionService.setElementActionHandler(this.$widget, 'runActiveNote', () => this.executeCurrentNote());
|
||||
keyboardActionService.setupActionsForElement('code-detail', this.$widget, this);
|
||||
|
||||
this.$executeScriptButton.on('click', () => this.executeCurrentNote());
|
||||
utils.bindElShortcut(this.$editor, 'ctrl+return', () => this.execute());
|
||||
|
||||
this.$sqlConsoleExecuteButton.on('click', () => this.execute());
|
||||
|
||||
this.initialized = this.initEditor();
|
||||
|
||||
@ -87,9 +135,103 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
}
|
||||
});
|
||||
|
||||
const isSqlConsole = note.mime === 'text/x-sqlite;schema=trilium';
|
||||
|
||||
this.$sqlConsoleArea.toggle(isSqlConsole);
|
||||
|
||||
if (isSqlConsole) {
|
||||
await this.showTableSchemas();
|
||||
}
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
async showTableSchemas() {
|
||||
if (!TABLE_SCHEMA) {
|
||||
TABLE_SCHEMA = await server.get('sql/schema');
|
||||
}
|
||||
|
||||
this.$sqlConsoleTableSchemas.empty();
|
||||
|
||||
for (const table of TABLE_SCHEMA) {
|
||||
const $tableLink = $('<button class="btn">').text(table.name);
|
||||
|
||||
const $columns = $("<ul>");
|
||||
|
||||
for (const column of table.columns) {
|
||||
$columns.append(
|
||||
$("<li>")
|
||||
.append($("<span>").text(column.name))
|
||||
.append($("<span>").text(column.type))
|
||||
);
|
||||
}
|
||||
|
||||
this.$sqlConsoleTableSchemas.append($tableLink).append(" ");
|
||||
|
||||
$tableLink
|
||||
.tooltip({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
boundary: 'window',
|
||||
title: $columns[0].outerHTML
|
||||
})
|
||||
.on('click', () => this.codeEditor.setValue("SELECT * FROM " + table.name + " LIMIT 100"));
|
||||
}
|
||||
}
|
||||
|
||||
async execute() {
|
||||
// execute the selected text or the whole content if there's no selection
|
||||
let sqlQuery = this.codeEditor.getSelection();
|
||||
|
||||
if (!sqlQuery) {
|
||||
sqlQuery = this.codeEditor.getValue();
|
||||
}
|
||||
|
||||
const result = await server.post("sql/execute", {
|
||||
query: sqlQuery
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toastService.showError(result.error);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
toastService.showMessage("Query was executed successfully.");
|
||||
}
|
||||
|
||||
const results = result.results;
|
||||
|
||||
this.$sqlConsoleResultContainer.empty();
|
||||
|
||||
for (const rows of results) {
|
||||
if (rows.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const $table = $('<table class="table table-striped">');
|
||||
this.$sqlConsoleResultContainer.append($table);
|
||||
|
||||
const result = rows[0];
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<th>").html(key));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
|
||||
for (const result of rows) {
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<td>").html(result[key]));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.$widget.show();
|
||||
|
||||
@ -106,26 +248,6 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
this.codeEditor.focus();
|
||||
}
|
||||
|
||||
async executeCurrentNote() {
|
||||
// ctrl+enter is also used elsewhere so make sure we're running only when appropriate
|
||||
if (this.note.type !== 'code') {
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure note is saved so we load latest changes
|
||||
await this.spacedUpdate.updateNowIfNecessary();
|
||||
|
||||
if (this.note.mime.endsWith("env=frontend")) {
|
||||
await bundleService.getAndExecuteBundle(this.noteId);
|
||||
}
|
||||
|
||||
if (this.note.mime.endsWith("env=backend")) {
|
||||
await server.post('script/run/' + this.noteId);
|
||||
}
|
||||
|
||||
toastService.showMessage("Note executed");
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if (this.codeEditor) {
|
||||
this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||
|
@ -4,6 +4,8 @@ import mimeTypesService from '../../services/mime_types.js';
|
||||
import utils from "../../services/utils.js";
|
||||
import keyboardActionService from "../../services/keyboard_actions.js";
|
||||
import treeCache from "../../services/tree_cache.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
import noteCreateService from "../../services/note_create.js";
|
||||
import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
|
||||
|
||||
const ENABLE_INSPECTOR = false;
|
||||
@ -15,7 +17,7 @@ const mentionSetup = {
|
||||
feed: queryText => {
|
||||
return new Promise((res, rej) => {
|
||||
noteAutocompleteService.autocompleteSource(queryText, rows => {
|
||||
if (rows.length === 1 && rows[0].title === 'No results') {
|
||||
if (rows.length === 1 && rows[0].pathTitle === 'No results') {
|
||||
rows = [];
|
||||
}
|
||||
|
||||
@ -25,6 +27,17 @@ const mentionSetup = {
|
||||
row.link = '#' + row.path;
|
||||
}
|
||||
|
||||
if (queryText.trim().length > 0) {
|
||||
rows = [
|
||||
{
|
||||
highlightedTitle: `Create and link note "<strong>${queryText}</strong>"`,
|
||||
id: 'create',
|
||||
title: queryText
|
||||
},
|
||||
...rows
|
||||
];
|
||||
}
|
||||
|
||||
res(rows);
|
||||
});
|
||||
});
|
||||
@ -256,4 +269,20 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
this.textEditor.model.insertContent(imageElement, this.textEditor.model.document.selection);
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
async createNoteForReferenceLink(title) {
|
||||
const {parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(this.notePath);
|
||||
|
||||
const {note} = await noteCreateService.createNote(parentNoteId, {
|
||||
activate: false,
|
||||
title: title,
|
||||
target: 'after',
|
||||
targetBranchId: await treeCache.getBranchId(parentNoteId, this.noteId),
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
const notePath = treeService.getSomeNotePath(note);
|
||||
|
||||
return notePath;
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,6 @@ export default class RenderTypeWidget extends TypeWidget {
|
||||
this.$widget = $(TPL);
|
||||
this.$noteDetailRenderHelp = this.$widget.find('.note-detail-render-help');
|
||||
this.$noteDetailRenderContent = this.$widget.find('.note-detail-render-content');
|
||||
this.$renderButton = this.$widget.find('.render-button');
|
||||
|
||||
this.$renderButton.on('click', () => this.refresh());
|
||||
|
||||
return this.$widget;
|
||||
}
|
||||
@ -46,4 +43,10 @@ export default class RenderTypeWidget extends TypeWidget {
|
||||
cleanup() {
|
||||
this.$noteDetailRenderContent.empty();
|
||||
}
|
||||
|
||||
renderActiveNoteEvent() {
|
||||
if (this.tabContext.isActive()) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
@ -312,14 +312,10 @@ div.ui-tooltip {
|
||||
|
||||
.CodeMirror {
|
||||
font-family: "Liberation Mono", "Lucida Console", monospace;
|
||||
height: auto;
|
||||
height: 100%;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
background-color: inherit !important;
|
||||
border-right: none;
|
||||
@ -661,12 +657,7 @@ div[data-notify="container"] {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#sql-console-table-schemas button {
|
||||
padding: 0.25rem 0.4rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 0.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
|
||||
a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href^="https://"]:not(.no-arrow):after {
|
||||
font-size: smaller;
|
||||
|
@ -101,7 +101,7 @@ async function updateNoteAttributes(req) {
|
||||
|| (attribute.type === 'relation' && attribute.value !== attributeEntity.value)) {
|
||||
|
||||
if (attribute.type !== 'relation' || !!attribute.value.trim()) {
|
||||
const newAttribute = attribute.createClone(attribute.type, attribute.name, attribute.value);
|
||||
const newAttribute = attributeEntity.createClone(attribute.type, attribute.name, attribute.value);
|
||||
await newAttribute.save();
|
||||
}
|
||||
|
||||
@ -139,6 +139,7 @@ async function updateNoteAttributes(req) {
|
||||
}
|
||||
|
||||
const note = await repository.getNote(noteId);
|
||||
note.invalidateAttributeCache();
|
||||
|
||||
return await note.getAttributes();
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
const dateNoteService = require('../../services/date_notes');
|
||||
const sql = require('../../services/sql');
|
||||
const dateUtils = require('../../services/date_utils');
|
||||
const noteService = require('../../services/notes');
|
||||
|
||||
async function getDateNote(req) {
|
||||
return await dateNoteService.getDateNote(req.params.date);
|
||||
@ -31,9 +33,28 @@ async function getDateNotesForMonth(req) {
|
||||
AND attr.value LIKE '${month}%'`);
|
||||
}
|
||||
|
||||
async function createSqlConsole() {
|
||||
const today = dateUtils.localNowDate();
|
||||
|
||||
const todayNote = await dateNoteService.getDateNote(today);
|
||||
|
||||
const {note} = await noteService.createNewNote({
|
||||
parentNoteId: todayNote.noteId,
|
||||
title: 'SQL Console',
|
||||
content: "SELECT title, isDeleted, isProtected FROM notes WHERE noteId = ''\n\n\n\n",
|
||||
type: 'code',
|
||||
mime: 'text/x-sqlite;schema=trilium'
|
||||
});
|
||||
|
||||
await note.setLabel("sqlConsole", today);
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDateNote,
|
||||
getMonthNote,
|
||||
getYearNote,
|
||||
getDateNotesForMonth
|
||||
getDateNotesForMonth,
|
||||
createSqlConsole
|
||||
};
|
@ -3,6 +3,7 @@
|
||||
const repository = require('../../services/repository');
|
||||
const noteCacheService = require('../../services/note_cache');
|
||||
const protectedSessionService = require('../../services/protected_session');
|
||||
const noteRevisionService = require('../../services/note_revisions');
|
||||
const utils = require('../../services/utils');
|
||||
const path = require('path');
|
||||
|
||||
@ -109,6 +110,20 @@ async function eraseNoteRevision(req) {
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreNoteRevision(req) {
|
||||
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
|
||||
|
||||
if (noteRevision && !noteRevision.isErased) {
|
||||
const note = await noteRevision.getNote();
|
||||
|
||||
await noteRevisionService.createNoteRevision(note);
|
||||
|
||||
note.title = noteRevision.title;
|
||||
await note.setContent(await noteRevision.getContent());
|
||||
await note.save();
|
||||
}
|
||||
}
|
||||
|
||||
async function getEditedNotesOnDate(req) {
|
||||
const date = utils.sanitizeSql(req.params.date);
|
||||
|
||||
@ -141,5 +156,6 @@ module.exports = {
|
||||
downloadNoteRevision,
|
||||
getEditedNotesOnDate,
|
||||
eraseAllNoteRevisions,
|
||||
eraseNoteRevision
|
||||
eraseNoteRevision,
|
||||
restoreNoteRevision
|
||||
};
|
@ -145,6 +145,7 @@ function register(app) {
|
||||
apiRoute(GET, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.getNoteRevision);
|
||||
apiRoute(DELETE, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.eraseNoteRevision);
|
||||
route(GET, '/api/notes/:noteId/revisions/:noteRevisionId/download', [auth.checkApiAuthOrElectron], noteRevisionsApiRoute.downloadNoteRevision);
|
||||
apiRoute(PUT, '/api/notes/:noteId/restore-revision/:noteRevisionId', noteRevisionsApiRoute.restoreNoteRevision);
|
||||
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
|
||||
apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle);
|
||||
apiRoute(POST, '/api/notes/:noteId/duplicate/:parentNoteId', notesApiRoute.duplicateNote);
|
||||
@ -180,6 +181,7 @@ function register(app) {
|
||||
apiRoute(GET, '/api/date-notes/month/:month', dateNotesRoute.getMonthNote);
|
||||
apiRoute(GET, '/api/date-notes/year/:year', dateNotesRoute.getYearNote);
|
||||
apiRoute(GET, '/api/date-notes/notes-for-month/:month', dateNotesRoute.getDateNotesForMonth);
|
||||
apiRoute(POST, '/api/sql-console', dateNotesRoute.createSqlConsole);
|
||||
|
||||
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
|
||||
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.uploadImage, apiResultHandler);
|
||||
|
@ -6,9 +6,8 @@ const utils = require('../services/utils');
|
||||
|
||||
async function setupPage(req, res) {
|
||||
if (await sqlInit.isDbInitialized()) {
|
||||
const windowService = require('../services/window');
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const windowService = require('../services/window');
|
||||
await windowService.createMainWindow();
|
||||
windowService.closeSetupWindow();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ const BUILTIN_ATTRIBUTES = [
|
||||
{ type: 'label', name: 'appTheme' },
|
||||
{ type: 'label', name: 'hidePromotedAttributes' },
|
||||
{ type: 'label', name: 'readOnly' },
|
||||
{ type: 'label', name: 'autoReadOnlyDisabled' },
|
||||
{ type: 'label', name: 'cssClass' },
|
||||
{ type: 'label', name: 'iconClass' },
|
||||
{ type: 'label', name: 'keyboardShortcut' },
|
||||
|
@ -1 +1 @@
|
||||
module.exports = { buildDate:"2020-05-04T21:59:14+02:00", buildRevision: "cafcb67a8a3a1943acac829590b34ff729b57e09" };
|
||||
module.exports = { buildDate:"2020-05-06T23:24:13+02:00", buildRevision: "54ecd2ee75d1177cedadf9fee10319687feee5f0" };
|
||||
|
@ -293,15 +293,11 @@ async function downloadImages(noteId, content) {
|
||||
if (!url.includes('api/images/')
|
||||
// this is and exception for the web clipper's "imageId"
|
||||
&& (url.length !== 20 || url.toLowerCase().startsWith('http'))) {
|
||||
if (url in downloadImagePromises) {
|
||||
// download is already in progress
|
||||
continue;
|
||||
}
|
||||
|
||||
if (url in imageUrlToNoteIdMapping) {
|
||||
const imageNote = await repository.getNote(imageUrlToNoteIdMapping[url]);
|
||||
|
||||
if (imageNote || imageNote.isDeleted) {
|
||||
if (!imageNote || imageNote.isDeleted) {
|
||||
delete imageUrlToNoteIdMapping[url];
|
||||
}
|
||||
else {
|
||||
@ -322,6 +318,11 @@ async function downloadImages(noteId, content) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (url in downloadImagePromises) {
|
||||
// download is already in progress
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is done asynchronously, it would be too slow to wait for the download
|
||||
// given that save can be triggered very often
|
||||
downloadImagePromises[url] = downloadImage(noteId, url);
|
||||
@ -338,28 +339,30 @@ async function downloadImages(noteId, content) {
|
||||
// are downloaded and the IMG references are not updated. For this occassion we have this code
|
||||
// which upon the download of all the images will update the note if the links have not been fixed before
|
||||
|
||||
const imageNotes = await repository.getNotes(Object.values(imageUrlToNoteIdMapping));
|
||||
await sql.transactional(async () => {
|
||||
const imageNotes = await repository.getNotes(Object.values(imageUrlToNoteIdMapping));
|
||||
|
||||
const origNote = await repository.getNote(noteId);
|
||||
const origContent = await origNote.getContent();
|
||||
let updatedContent = origContent;
|
||||
const origNote = await repository.getNote(noteId);
|
||||
const origContent = await origNote.getContent();
|
||||
let updatedContent = origContent;
|
||||
|
||||
for (const url in imageUrlToNoteIdMapping) {
|
||||
const imageNote = imageNotes.find(note => note.noteId === imageUrlToNoteIdMapping[url]);
|
||||
for (const url in imageUrlToNoteIdMapping) {
|
||||
const imageNote = imageNotes.find(note => note.noteId === imageUrlToNoteIdMapping[url]);
|
||||
|
||||
if (imageNote && !imageNote.isDeleted) {
|
||||
updatedContent = replaceUrl(updatedContent, url, imageNote);
|
||||
if (imageNote && !imageNote.isDeleted) {
|
||||
updatedContent = replaceUrl(updatedContent, url, imageNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update only if the links have not been already fixed.
|
||||
if (updatedContent !== origContent) {
|
||||
await origNote.setContent(updatedContent);
|
||||
// update only if the links have not been already fixed.
|
||||
if (updatedContent !== origContent) {
|
||||
await origNote.setContent(updatedContent);
|
||||
|
||||
await scanForLinks(origNote);
|
||||
await scanForLinks(origNote);
|
||||
|
||||
console.log(`Fixed the image links for note ${noteId} to the offline saved.`);
|
||||
}
|
||||
console.log(`Fixed the image links for note ${noteId} to the offline saved.`);
|
||||
}
|
||||
});
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ const defaultOptions = [
|
||||
{ name: 'imageMaxWidthHeight', value: '1200', isSynced: true },
|
||||
{ name: 'imageJpegQuality', value: '75', isSynced: true },
|
||||
{ name: 'autoFixConsistencyIssues', value: 'true', isSynced: false },
|
||||
{ name: 'codeNotesMimeTypes', value: '["text/x-csrc","text/x-c++src","text/x-csharp","text/css","text/x-go","text/x-groovy","text/x-haskell","text/html","message/http","text/x-java","application/javascript;env=frontend","application/javascript;env=backend","application/json","text/x-kotlin","text/x-markdown","text/x-perl","text/x-php","text/x-python","text/x-ruby",null,"text/x-sql","text/x-swift","text/xml","text/x-yaml"]', isSynced: true },
|
||||
{ name: 'codeNotesMimeTypes', value: '["text/x-csrc","text/x-c++src","text/x-csharp","text/css","text/x-go","text/x-groovy","text/x-haskell","text/html","message/http","text/x-java","application/javascript;env=frontend","application/javascript;env=backend","application/json","text/x-kotlin","text/x-markdown","text/x-perl","text/x-php","text/x-python","text/x-ruby",null,"text/x-sql","text/x-sqlite;schema=trilium","text/x-swift","text/xml","text/x-yaml"]', isSynced: true },
|
||||
{ name: 'leftPaneWidth', value: '25', isSynced: false },
|
||||
{ name: 'leftPaneVisible', value: 'true', isSynced: false },
|
||||
{ name: 'rightPaneWidth', value: '25', isSynced: false },
|
||||
|
@ -165,6 +165,5 @@ module.exports = {
|
||||
createMainWindow,
|
||||
createSetupWindow,
|
||||
closeSetupWindow,
|
||||
createExtraWindow,
|
||||
registerGlobalShortcuts
|
||||
};
|
@ -25,7 +25,6 @@
|
||||
<%- include('dialogs/options.ejs') %>
|
||||
<%- include('dialogs/protected_session_password.ejs') %>
|
||||
<%- include('dialogs/recent_changes.ejs') %>
|
||||
<%- include('dialogs/sql_console.ejs') %>
|
||||
<%- include('dialogs/info.ejs') %>
|
||||
<%- include('dialogs/prompt.ejs') %>
|
||||
<%- include('dialogs/confirm.ejs') %>
|
||||
|
@ -1,27 +0,0 @@
|
||||
<div id="sql-console-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-dialog-scrollable modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">SQL console</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
Tables:
|
||||
<span id="sql-console-table-schemas"></span>
|
||||
</div>
|
||||
|
||||
<div id="sql-console-query"></div>
|
||||
|
||||
<div style="text-align: center">
|
||||
<button class="btn btn-danger" id="sql-console-execute">Execute <kbd>CTRL+ENTER</kbd></button>
|
||||
</div>
|
||||
|
||||
<div id="result-container" style="width: 100%; font-size: smaller; margin-top: 10px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -210,7 +210,7 @@
|
||||
|
||||
<script src="libraries/knockout.min.js"></script>
|
||||
|
||||
<script src="app-dist/setup.js" crossorigin type="module"></script>
|
||||
<script src="app/setup.js" crossorigin type="module"></script>
|
||||
<link href="stylesheets/themes.css" rel="stylesheet">
|
||||
</body>
|
||||
</html>
|
||||
|
@ -6,6 +6,7 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/public" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/public/app-dist" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user