mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
#126, added skeleton of note relations, copied from similar concept of labels
This commit is contained in:
parent
4d6eda8fe6
commit
8a95afd756
@ -21,533 +21,529 @@
|
|||||||
<table id="13" parent="2" name="notes"/>
|
<table id="13" parent="2" name="notes"/>
|
||||||
<table id="14" parent="2" name="options"/>
|
<table id="14" parent="2" name="options"/>
|
||||||
<table id="15" parent="2" name="recent_notes"/>
|
<table id="15" parent="2" name="recent_notes"/>
|
||||||
<table id="16" parent="2" name="source_ids"/>
|
<table id="16" parent="2" name="relations"/>
|
||||||
<table id="17" parent="2" name="sqlite_master">
|
<table id="17" parent="2" name="source_ids"/>
|
||||||
|
<table id="18" parent="2" name="sqlite_master">
|
||||||
<System>1</System>
|
<System>1</System>
|
||||||
</table>
|
</table>
|
||||||
<table id="18" parent="2" name="sqlite_sequence">
|
<table id="19" parent="2" name="sqlite_sequence">
|
||||||
<System>1</System>
|
<System>1</System>
|
||||||
</table>
|
</table>
|
||||||
<table id="19" parent="2" name="sync"/>
|
<table id="20" parent="2" name="sync"/>
|
||||||
<column id="20" parent="6" name="apiTokenId">
|
<column id="21" parent="6" name="apiTokenId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="21" parent="6" name="token">
|
<column id="22" parent="6" name="token">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="22" parent="6" name="dateCreated">
|
<column id="23" parent="6" name="dateCreated">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="23" parent="6" name="isDeleted">
|
<column id="24" parent="6" name="isDeleted">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="24" parent="6" name="hash">
|
<column id="25" parent="6" name="hash">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="25" parent="6" name="sqlite_autoindex_api_tokens_1">
|
<index id="26" parent="6" name="sqlite_autoindex_api_tokens_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>apiTokenId</ColNames>
|
<ColNames>apiTokenId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<key id="26" parent="6">
|
<key id="27" parent="6">
|
||||||
<ColNames>apiTokenId</ColNames>
|
<ColNames>apiTokenId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_api_tokens_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_api_tokens_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="27" parent="7" name="branchId">
|
<column id="28" parent="7" name="branchId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="28" parent="7" name="noteId">
|
<column id="29" parent="7" name="noteId">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="29" parent="7" name="parentNoteId">
|
<column id="30" parent="7" name="parentNoteId">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="30" parent="7" name="notePosition">
|
<column id="31" parent="7" name="notePosition">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>INTEGER|0s</DataType>
|
<DataType>INTEGER|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="31" parent="7" name="prefix">
|
<column id="32" parent="7" name="prefix">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="32" parent="7" name="isExpanded">
|
<column id="33" parent="7" name="isExpanded">
|
||||||
<Position>6</Position>
|
<Position>6</Position>
|
||||||
<DataType>BOOLEAN|0s</DataType>
|
<DataType>BOOLEAN|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="33" parent="7" name="isDeleted">
|
<column id="34" parent="7" name="isDeleted">
|
||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
<DataType>INTEGER|0s</DataType>
|
<DataType>INTEGER|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="34" parent="7" name="dateModified">
|
<column id="35" parent="7" name="dateModified">
|
||||||
<Position>8</Position>
|
<Position>8</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="35" parent="7" name="hash">
|
<column id="36" parent="7" name="hash">
|
||||||
<Position>9</Position>
|
<Position>9</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="36" parent="7" name="dateCreated">
|
<column id="37" parent="7" name="dateCreated">
|
||||||
<Position>10</Position>
|
<Position>10</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
|
<DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="37" parent="7" name="sqlite_autoindex_branches_1">
|
<index id="38" parent="7" name="sqlite_autoindex_branches_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>branchId</ColNames>
|
<ColNames>branchId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<index id="38" parent="7" name="IDX_branches_noteId_parentNoteId">
|
<index id="39" parent="7" name="IDX_branches_noteId_parentNoteId">
|
||||||
<ColNames>noteId
|
<ColNames>noteId
|
||||||
parentNoteId</ColNames>
|
parentNoteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="39" parent="7" name="IDX_branches_noteId">
|
<index id="40" parent="7" name="IDX_branches_noteId">
|
||||||
<ColNames>noteId</ColNames>
|
<ColNames>noteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="40" parent="7" name="IDX_branches_parentNoteId">
|
<index id="41" parent="7" name="IDX_branches_parentNoteId">
|
||||||
<ColNames>parentNoteId</ColNames>
|
<ColNames>parentNoteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<key id="41" parent="7">
|
<key id="42" parent="7">
|
||||||
<ColNames>branchId</ColNames>
|
<ColNames>branchId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="42" parent="8" name="eventId">
|
<column id="43" parent="8" name="eventId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="43" parent="8" name="noteId">
|
<column id="44" parent="8" name="noteId">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="44" parent="8" name="comment">
|
<column id="45" parent="8" name="comment">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="45" parent="8" name="dateCreated">
|
<column id="46" parent="8" name="dateCreated">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<index id="46" parent="8" name="sqlite_autoindex_event_log_1">
|
<index id="47" parent="8" name="sqlite_autoindex_event_log_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>eventId</ColNames>
|
<ColNames>eventId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<key id="47" parent="8">
|
<key id="48" parent="8">
|
||||||
<ColNames>eventId</ColNames>
|
<ColNames>eventId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_event_log_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_event_log_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="48" parent="9" name="imageId">
|
<column id="49" parent="9" name="imageId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="49" parent="9" name="format">
|
<column id="50" parent="9" name="format">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="50" parent="9" name="checksum">
|
<column id="51" parent="9" name="checksum">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="51" parent="9" name="name">
|
<column id="52" parent="9" name="name">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="52" parent="9" name="data">
|
<column id="53" parent="9" name="data">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>BLOB|0s</DataType>
|
<DataType>BLOB|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="53" parent="9" name="isDeleted">
|
<column id="54" parent="9" name="isDeleted">
|
||||||
<Position>6</Position>
|
<Position>6</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="54" parent="9" name="dateModified">
|
<column id="55" parent="9" name="dateModified">
|
||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="55" parent="9" name="dateCreated">
|
<column id="56" parent="9" name="dateCreated">
|
||||||
<Position>8</Position>
|
<Position>8</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="56" parent="9" name="hash">
|
<column id="57" parent="9" name="hash">
|
||||||
<Position>9</Position>
|
<Position>9</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="57" parent="9" name="sqlite_autoindex_images_1">
|
<index id="58" parent="9" name="sqlite_autoindex_images_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>imageId</ColNames>
|
<ColNames>imageId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<key id="58" parent="9">
|
<key id="59" parent="9">
|
||||||
<ColNames>imageId</ColNames>
|
<ColNames>imageId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_images_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_images_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="59" parent="10" name="labelId">
|
<column id="60" parent="10" name="labelId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="60" parent="10" name="noteId">
|
<column id="61" parent="10" name="noteId">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="61" parent="10" name="name">
|
<column id="62" parent="10" name="name">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="62" parent="10" name="value">
|
<column id="63" parent="10" name="value">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>''</DefaultExpression>
|
<DefaultExpression>''</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="63" parent="10" name="position">
|
<column id="64" parent="10" name="position">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="64" parent="10" name="dateCreated">
|
<column id="65" parent="10" name="dateCreated">
|
||||||
<Position>6</Position>
|
<Position>6</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="65" parent="10" name="dateModified">
|
<column id="66" parent="10" name="dateModified">
|
||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="66" parent="10" name="isDeleted">
|
<column id="67" parent="10" name="isDeleted">
|
||||||
<Position>8</Position>
|
<Position>8</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="67" parent="10" name="hash">
|
<column id="68" parent="10" name="hash">
|
||||||
<Position>9</Position>
|
<Position>9</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="68" parent="10" name="sqlite_autoindex_labels_1">
|
<index id="69" parent="10" name="sqlite_autoindex_labels_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>labelId</ColNames>
|
<ColNames>labelId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<index id="69" parent="10" name="IDX_labels_noteId">
|
<index id="70" parent="10" name="IDX_labels_noteId">
|
||||||
<ColNames>noteId</ColNames>
|
<ColNames>noteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="70" parent="10" name="IDX_labels_name_value">
|
<index id="71" parent="10" name="IDX_labels_name_value">
|
||||||
<ColNames>name
|
<ColNames>name
|
||||||
value</ColNames>
|
value</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<key id="71" parent="10">
|
<key id="72" parent="10">
|
||||||
<ColNames>labelId</ColNames>
|
<ColNames>labelId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_labels_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_labels_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="72" parent="11" name="noteImageId">
|
<column id="73" parent="11" name="noteImageId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="73" parent="11" name="noteId">
|
<column id="74" parent="11" name="noteId">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="74" parent="11" name="imageId">
|
<column id="75" parent="11" name="imageId">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="75" parent="11" name="isDeleted">
|
<column id="76" parent="11" name="isDeleted">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="76" parent="11" name="dateModified">
|
<column id="77" parent="11" name="dateModified">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="77" parent="11" name="dateCreated">
|
<column id="78" parent="11" name="dateCreated">
|
||||||
<Position>6</Position>
|
<Position>6</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="78" parent="11" name="hash">
|
<column id="79" parent="11" name="hash">
|
||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="79" parent="11" name="sqlite_autoindex_note_images_1">
|
<index id="80" parent="11" name="sqlite_autoindex_note_images_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>noteImageId</ColNames>
|
<ColNames>noteImageId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<index id="80" parent="11" name="IDX_note_images_noteId_imageId">
|
<index id="81" parent="11" name="IDX_note_images_noteId_imageId">
|
||||||
<ColNames>noteId
|
<ColNames>noteId
|
||||||
imageId</ColNames>
|
imageId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="81" parent="11" name="IDX_note_images_noteId">
|
<index id="82" parent="11" name="IDX_note_images_noteId">
|
||||||
<ColNames>noteId</ColNames>
|
<ColNames>noteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="82" parent="11" name="IDX_note_images_imageId">
|
<index id="83" parent="11" name="IDX_note_images_imageId">
|
||||||
<ColNames>imageId</ColNames>
|
<ColNames>imageId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<key id="83" parent="11">
|
<key id="84" parent="11">
|
||||||
<ColNames>noteImageId</ColNames>
|
<ColNames>noteImageId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_note_images_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_note_images_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="84" parent="12" name="noteRevisionId">
|
<column id="85" parent="12" name="noteRevisionId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="85" parent="12" name="noteId">
|
<column id="86" parent="12" name="noteId">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="86" parent="12" name="title">
|
<column id="87" parent="12" name="title">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="87" parent="12" name="content">
|
<column id="88" parent="12" name="content">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="88" parent="12" name="isProtected">
|
<column id="89" parent="12" name="isProtected">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="89" parent="12" name="dateModifiedFrom">
|
<column id="90" parent="12" name="dateModifiedFrom">
|
||||||
<Position>6</Position>
|
<Position>6</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="90" parent="12" name="dateModifiedTo">
|
<column id="91" parent="12" name="dateModifiedTo">
|
||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="91" parent="12" name="type">
|
<column id="92" parent="12" name="type">
|
||||||
<Position>8</Position>
|
<Position>8</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>''</DefaultExpression>
|
<DefaultExpression>''</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="92" parent="12" name="mime">
|
<column id="93" parent="12" name="mime">
|
||||||
<Position>9</Position>
|
<Position>9</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>''</DefaultExpression>
|
<DefaultExpression>''</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="93" parent="12" name="hash">
|
<column id="94" parent="12" name="hash">
|
||||||
<Position>10</Position>
|
<Position>10</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="94" parent="12" name="sqlite_autoindex_note_revisions_1">
|
<index id="95" parent="12" name="sqlite_autoindex_note_revisions_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>noteRevisionId</ColNames>
|
<ColNames>noteRevisionId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<index id="95" parent="12" name="IDX_note_revisions_noteId">
|
<index id="96" parent="12" name="IDX_note_revisions_noteId">
|
||||||
<ColNames>noteId</ColNames>
|
<ColNames>noteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="96" parent="12" name="IDX_note_revisions_dateModifiedFrom">
|
<index id="97" parent="12" name="IDX_note_revisions_dateModifiedFrom">
|
||||||
<ColNames>dateModifiedFrom</ColNames>
|
<ColNames>dateModifiedFrom</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<index id="97" parent="12" name="IDX_note_revisions_dateModifiedTo">
|
<index id="98" parent="12" name="IDX_note_revisions_dateModifiedTo">
|
||||||
<ColNames>dateModifiedTo</ColNames>
|
<ColNames>dateModifiedTo</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<key id="98" parent="12">
|
<key id="99" parent="12">
|
||||||
<ColNames>noteRevisionId</ColNames>
|
<ColNames>noteRevisionId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="99" parent="13" name="noteId">
|
<column id="100" parent="13" name="noteId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="100" parent="13" name="title">
|
<column id="101" parent="13" name="title">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>"unnamed"</DefaultExpression>
|
<DefaultExpression>"unnamed"</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="101" parent="13" name="content">
|
<column id="102" parent="13" name="content">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="102" parent="13" name="isProtected">
|
<column id="103" parent="13" name="isProtected">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="103" parent="13" name="isDeleted">
|
<column id="104" parent="13" name="isDeleted">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="104" parent="13" name="dateCreated">
|
<column id="105" parent="13" name="dateCreated">
|
||||||
<Position>6</Position>
|
<Position>6</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="105" parent="13" name="dateModified">
|
<column id="106" parent="13" name="dateModified">
|
||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="106" parent="13" name="type">
|
<column id="107" parent="13" name="type">
|
||||||
<Position>8</Position>
|
<Position>8</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>'text'</DefaultExpression>
|
<DefaultExpression>'text'</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="107" parent="13" name="mime">
|
<column id="108" parent="13" name="mime">
|
||||||
<Position>9</Position>
|
<Position>9</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>'text/html'</DefaultExpression>
|
<DefaultExpression>'text/html'</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="108" parent="13" name="hash">
|
<column id="109" parent="13" name="hash">
|
||||||
<Position>10</Position>
|
<Position>10</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="109" parent="13" name="sqlite_autoindex_notes_1">
|
<index id="110" parent="13" name="sqlite_autoindex_notes_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>noteId</ColNames>
|
<ColNames>noteId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<index id="110" parent="13" name="IDX_notes_type">
|
<index id="111" parent="13" name="IDX_notes_type">
|
||||||
<ColNames>type</ColNames>
|
<ColNames>type</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<key id="111" parent="13">
|
<key id="112" parent="13">
|
||||||
<ColNames>noteId</ColNames>
|
<ColNames>noteId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="112" parent="14" name="optionId">
|
<column id="113" parent="14" name="name">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="113" parent="14" name="name">
|
|
||||||
<Position>2</Position>
|
|
||||||
<DataType>TEXT|0s</DataType>
|
|
||||||
<NotNull>1</NotNull>
|
|
||||||
</column>
|
|
||||||
<column id="114" parent="14" name="value">
|
<column id="114" parent="14" name="value">
|
||||||
<Position>3</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="115" parent="14" name="dateModified">
|
<column id="115" parent="14" name="dateModified">
|
||||||
<Position>4</Position>
|
<Position>3</Position>
|
||||||
<DataType>INT|0s</DataType>
|
<DataType>INT|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="116" parent="14" name="isSynced">
|
<column id="116" parent="14" name="isSynced">
|
||||||
<Position>5</Position>
|
<Position>4</Position>
|
||||||
<DataType>INTEGER|0s</DataType>
|
<DataType>INTEGER|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>0</DefaultExpression>
|
<DefaultExpression>0</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="117" parent="14" name="hash">
|
<column id="117" parent="14" name="hash">
|
||||||
<Position>6</Position>
|
<Position>5</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>""</DefaultExpression>
|
<DefaultExpression>""</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<column id="118" parent="14" name="dateCreated">
|
<column id="118" parent="14" name="dateCreated">
|
||||||
<Position>7</Position>
|
<Position>6</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
|
<DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression>
|
||||||
</column>
|
</column>
|
||||||
<index id="119" parent="14" name="sqlite_autoindex_options_1">
|
<index id="119" parent="14" name="sqlite_autoindex_options_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>optionId</ColNames>
|
<ColNames>name</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<key id="120" parent="14">
|
<key id="120" parent="14">
|
||||||
<ColNames>optionId</ColNames>
|
<ColNames>name</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
@ -587,90 +583,156 @@ imageId</ColNames>
|
|||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="128" parent="16" name="sourceId">
|
<column id="128" parent="16" name="relationId">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="129" parent="16" name="dateCreated">
|
<column id="129" parent="16" name="sourceNoteId">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<index id="130" parent="16" name="sqlite_autoindex_source_ids_1">
|
<column id="130" parent="16" name="name">
|
||||||
|
<Position>3</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<column id="131" parent="16" name="targetNoteId">
|
||||||
|
<Position>4</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<column id="132" parent="16" name="position">
|
||||||
|
<Position>5</Position>
|
||||||
|
<DataType>INT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
<DefaultExpression>0</DefaultExpression>
|
||||||
|
</column>
|
||||||
|
<column id="133" parent="16" name="dateCreated">
|
||||||
|
<Position>6</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<column id="134" parent="16" name="dateModified">
|
||||||
|
<Position>7</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<column id="135" parent="16" name="isDeleted">
|
||||||
|
<Position>8</Position>
|
||||||
|
<DataType>INT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<column id="136" parent="16" name="hash">
|
||||||
|
<Position>9</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
<DefaultExpression>""</DefaultExpression>
|
||||||
|
</column>
|
||||||
|
<index id="137" parent="16" name="sqlite_autoindex_relations_1">
|
||||||
|
<NameSurrogate>1</NameSurrogate>
|
||||||
|
<ColNames>relationId</ColNames>
|
||||||
|
<ColumnCollations></ColumnCollations>
|
||||||
|
<Unique>1</Unique>
|
||||||
|
</index>
|
||||||
|
<index id="138" parent="16" name="IDX_relation_sourceNoteId">
|
||||||
|
<ColNames>sourceNoteId</ColNames>
|
||||||
|
<ColumnCollations></ColumnCollations>
|
||||||
|
</index>
|
||||||
|
<index id="139" parent="16" name="IDX_relation_targetNoteId">
|
||||||
|
<ColNames>targetNoteId</ColNames>
|
||||||
|
<ColumnCollations></ColumnCollations>
|
||||||
|
</index>
|
||||||
|
<key id="140" parent="16">
|
||||||
|
<ColNames>relationId</ColNames>
|
||||||
|
<Primary>1</Primary>
|
||||||
|
<UnderlyingIndexName>sqlite_autoindex_relations_1</UnderlyingIndexName>
|
||||||
|
</key>
|
||||||
|
<column id="141" parent="17" name="sourceId">
|
||||||
|
<Position>1</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<column id="142" parent="17" name="dateCreated">
|
||||||
|
<Position>2</Position>
|
||||||
|
<DataType>TEXT|0s</DataType>
|
||||||
|
<NotNull>1</NotNull>
|
||||||
|
</column>
|
||||||
|
<index id="143" parent="17" name="sqlite_autoindex_source_ids_1">
|
||||||
<NameSurrogate>1</NameSurrogate>
|
<NameSurrogate>1</NameSurrogate>
|
||||||
<ColNames>sourceId</ColNames>
|
<ColNames>sourceId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<key id="131" parent="16">
|
<key id="144" parent="17">
|
||||||
<ColNames>sourceId</ColNames>
|
<ColNames>sourceId</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
<UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
|
<UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
|
||||||
</key>
|
</key>
|
||||||
<column id="132" parent="17" name="type">
|
<column id="145" parent="18" name="type">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>text|0s</DataType>
|
<DataType>text|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="133" parent="17" name="name">
|
<column id="146" parent="18" name="name">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>text|0s</DataType>
|
<DataType>text|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="134" parent="17" name="tbl_name">
|
<column id="147" parent="18" name="tbl_name">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>text|0s</DataType>
|
<DataType>text|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="135" parent="17" name="rootpage">
|
<column id="148" parent="18" name="rootpage">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>integer|0s</DataType>
|
<DataType>integer|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="136" parent="17" name="sql">
|
<column id="149" parent="18" name="sql">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>text|0s</DataType>
|
<DataType>text|0s</DataType>
|
||||||
</column>
|
</column>
|
||||||
<column id="137" parent="18" name="name">
|
<column id="150" parent="19" name="name">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
</column>
|
</column>
|
||||||
<column id="138" parent="18" name="seq">
|
<column id="151" parent="19" name="seq">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
</column>
|
</column>
|
||||||
<column id="139" parent="19" name="id">
|
<column id="152" parent="20" name="id">
|
||||||
<Position>1</Position>
|
<Position>1</Position>
|
||||||
<DataType>INTEGER|0s</DataType>
|
<DataType>INTEGER|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<SequenceIdentity>1</SequenceIdentity>
|
<SequenceIdentity>1</SequenceIdentity>
|
||||||
</column>
|
</column>
|
||||||
<column id="140" parent="19" name="entityName">
|
<column id="153" parent="20" name="entityName">
|
||||||
<Position>2</Position>
|
<Position>2</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="141" parent="19" name="entityId">
|
<column id="154" parent="20" name="entityId">
|
||||||
<Position>3</Position>
|
<Position>3</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="142" parent="19" name="sourceId">
|
<column id="155" parent="20" name="sourceId">
|
||||||
<Position>4</Position>
|
<Position>4</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<column id="143" parent="19" name="syncDate">
|
<column id="156" parent="20" name="syncDate">
|
||||||
<Position>5</Position>
|
<Position>5</Position>
|
||||||
<DataType>TEXT|0s</DataType>
|
<DataType>TEXT|0s</DataType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
</column>
|
</column>
|
||||||
<index id="144" parent="19" name="IDX_sync_entityName_entityId">
|
<index id="157" parent="20" name="IDX_sync_entityName_entityId">
|
||||||
<ColNames>entityName
|
<ColNames>entityName
|
||||||
entityId</ColNames>
|
entityId</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
<Unique>1</Unique>
|
<Unique>1</Unique>
|
||||||
</index>
|
</index>
|
||||||
<index id="145" parent="19" name="IDX_sync_syncDate">
|
<index id="158" parent="20" name="IDX_sync_syncDate">
|
||||||
<ColNames>syncDate</ColNames>
|
<ColNames>syncDate</ColNames>
|
||||||
<ColumnCollations></ColumnCollations>
|
<ColumnCollations></ColumnCollations>
|
||||||
</index>
|
</index>
|
||||||
<key id="146" parent="19">
|
<key id="159" parent="20">
|
||||||
<ColNames>id</ColNames>
|
<ColNames>id</ColNames>
|
||||||
<Primary>1</Primary>
|
<Primary>1</Primary>
|
||||||
</key>
|
</key>
|
||||||
|
15
db/migrations/0106__add_relations_table.sql
Normal file
15
db/migrations/0106__add_relations_table.sql
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
CREATE TABLE relations
|
||||||
|
(
|
||||||
|
relationId TEXT not null primary key,
|
||||||
|
sourceNoteId TEXT not null,
|
||||||
|
name TEXT not null,
|
||||||
|
targetNoteId TEXT not null,
|
||||||
|
position INT default 0 not null,
|
||||||
|
dateCreated TEXT not null,
|
||||||
|
dateModified TEXT not null,
|
||||||
|
isDeleted INT not null
|
||||||
|
, hash TEXT DEFAULT "" NOT NULL);
|
||||||
|
CREATE INDEX IDX_relation_sourceNoteId
|
||||||
|
on relations (sourceNoteId);
|
||||||
|
CREATE INDEX IDX_relation_targetNoteId
|
||||||
|
on relations (targetNoteId);
|
@ -4,6 +4,7 @@ const Image = require('../entities/image');
|
|||||||
const NoteImage = require('../entities/note_image');
|
const NoteImage = require('../entities/note_image');
|
||||||
const Branch = require('../entities/branch');
|
const Branch = require('../entities/branch');
|
||||||
const Label = require('../entities/label');
|
const Label = require('../entities/label');
|
||||||
|
const Relation = require('../entities/relation');
|
||||||
const RecentNote = require('../entities/recent_note');
|
const RecentNote = require('../entities/recent_note');
|
||||||
const ApiToken = require('../entities/api_token');
|
const ApiToken = require('../entities/api_token');
|
||||||
const Option = require('../entities/option');
|
const Option = require('../entities/option');
|
||||||
@ -15,6 +16,9 @@ function createEntityFromRow(row) {
|
|||||||
if (row.labelId) {
|
if (row.labelId) {
|
||||||
entity = new Label(row);
|
entity = new Label(row);
|
||||||
}
|
}
|
||||||
|
else if (row.relationId) {
|
||||||
|
entity = new Relation(row);
|
||||||
|
}
|
||||||
else if (row.noteRevisionId) {
|
else if (row.noteRevisionId) {
|
||||||
entity = new NoteRevision(row);
|
entity = new NoteRevision(row);
|
||||||
}
|
}
|
||||||
|
40
src/entities/relation.js
Normal file
40
src/entities/relation.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Entity = require('./entity');
|
||||||
|
const repository = require('../services/repository');
|
||||||
|
const dateUtils = require('../services/date_utils');
|
||||||
|
const sql = require('../services/sql');
|
||||||
|
|
||||||
|
class Relation extends Entity {
|
||||||
|
static get tableName() { return "relations"; }
|
||||||
|
static get primaryKeyName() { return "relationId"; }
|
||||||
|
static get hashedProperties() { return ["relationId", "sourceNoteId", "name", "targetNoteId", "dateModified", "dateCreated"]; }
|
||||||
|
|
||||||
|
async getSourceNote() {
|
||||||
|
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.sourceNoteId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTargetNote() {
|
||||||
|
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.targetNoteId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async beforeSaving() {
|
||||||
|
super.beforeSaving();
|
||||||
|
|
||||||
|
if (this.position === undefined) {
|
||||||
|
this.position = 1 + await sql.getValue(`SELECT COALESCE(MAX(position), 0) FROM relations WHERE sourceNoteId = ?`, [this.sourceNoteId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isDeleted) {
|
||||||
|
this.isDeleted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.dateCreated) {
|
||||||
|
this.dateCreated = dateUtils.nowDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dateModified = dateUtils.nowDate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Relation;
|
222
src/public/javascripts/dialogs/relations.js
Normal file
222
src/public/javascripts/dialogs/relations.js
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import noteDetailService from '../services/note_detail.js';
|
||||||
|
import server from '../services/server.js';
|
||||||
|
import infoService from "../services/info.js";
|
||||||
|
|
||||||
|
const $dialog = $("#relations-dialog");
|
||||||
|
const $saveRelationsButton = $("#save-relations-button");
|
||||||
|
const $relationsBody = $('#relations-table tbody');
|
||||||
|
|
||||||
|
const relationsModel = new RelationsModel();
|
||||||
|
let relationNames = [];
|
||||||
|
|
||||||
|
function RelationsModel() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
this.relations = ko.observableArray();
|
||||||
|
|
||||||
|
this.updateRelationPositions = function() {
|
||||||
|
let position = 0;
|
||||||
|
|
||||||
|
// we need to update positions by searching in the DOM, because order of the
|
||||||
|
// relations in the viewmodel (self.relations()) stays the same
|
||||||
|
$relationsBody.find('input[name="position"]').each(function() {
|
||||||
|
const relation = self.getTargetRelation(this);
|
||||||
|
|
||||||
|
relation().position = position++;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.loadRelations = async function() {
|
||||||
|
const noteId = noteDetailService.getCurrentNoteId();
|
||||||
|
|
||||||
|
const relations = await server.get('notes/' + noteId + '/relations');
|
||||||
|
|
||||||
|
self.relations(relations.map(ko.observable));
|
||||||
|
|
||||||
|
addLastEmptyRow();
|
||||||
|
|
||||||
|
relationNames = await server.get('relations/names');
|
||||||
|
|
||||||
|
// relation might not be rendered immediatelly so could not focus
|
||||||
|
setTimeout(() => $(".relation-name:last").focus(), 100);
|
||||||
|
|
||||||
|
$relationsBody.sortable({
|
||||||
|
handle: '.handle',
|
||||||
|
containment: $relationsBody,
|
||||||
|
update: this.updateRelationPositions
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.deleteRelation = function(data, event) {
|
||||||
|
const relation = self.getTargetRelation(event.target);
|
||||||
|
const relationData = relation();
|
||||||
|
|
||||||
|
if (relationData) {
|
||||||
|
relationData.isDeleted = 1;
|
||||||
|
|
||||||
|
relation(relationData);
|
||||||
|
|
||||||
|
addLastEmptyRow();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function isValid() {
|
||||||
|
for (let relations = self.relations(), i = 0; i < relations.length; i++) {
|
||||||
|
if (self.isEmptyName(i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.save = async function() {
|
||||||
|
// we need to defocus from input (in case of enter-triggered save) because value is updated
|
||||||
|
// on blur event (because of conflict with jQuery UI Autocomplete). Without this, input would
|
||||||
|
// stay in focus, blur wouldn't be triggered and change wouldn't be updated in the viewmodel.
|
||||||
|
$saveRelationsButton.focus();
|
||||||
|
|
||||||
|
if (!isValid()) {
|
||||||
|
alert("Please fix all validation errors and try saving again.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updateRelationPositions();
|
||||||
|
|
||||||
|
const noteId = noteDetailService.getCurrentNoteId();
|
||||||
|
|
||||||
|
const relationsToSave = self.relations()
|
||||||
|
.map(relation => relation())
|
||||||
|
.filter(relation => relation.relationId !== "" || relation.name !== "");
|
||||||
|
|
||||||
|
const relations = await server.put('notes/' + noteId + '/relations', relationsToSave);
|
||||||
|
|
||||||
|
self.relations(relations.map(ko.observable));
|
||||||
|
|
||||||
|
addLastEmptyRow();
|
||||||
|
|
||||||
|
infoService.showMessage("Relations have been saved.");
|
||||||
|
|
||||||
|
noteDetailService.loadRelationList();
|
||||||
|
};
|
||||||
|
|
||||||
|
function addLastEmptyRow() {
|
||||||
|
const relations = self.relations().filter(attr => attr().isDeleted === 0);
|
||||||
|
const last = relations.length === 0 ? null : relations[relations.length - 1]();
|
||||||
|
|
||||||
|
if (!last || last.name.trim() !== "" || last.value !== "") {
|
||||||
|
self.relations.push(ko.observable({
|
||||||
|
relationId: '',
|
||||||
|
name: '',
|
||||||
|
value: '',
|
||||||
|
isDeleted: 0,
|
||||||
|
position: 0
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.relationChanged = function (data, event) {
|
||||||
|
addLastEmptyRow();
|
||||||
|
|
||||||
|
const relation = self.getTargetRelation(event.target);
|
||||||
|
|
||||||
|
relation.valueHasMutated();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isNotUnique = function(index) {
|
||||||
|
const cur = self.relations()[index]();
|
||||||
|
|
||||||
|
if (cur.name.trim() === "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let relations = self.relations(), i = 0; i < relations.length; i++) {
|
||||||
|
const relation = relations[i]();
|
||||||
|
|
||||||
|
if (index !== i && cur.name === relation.name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isEmptyName = function(index) {
|
||||||
|
const cur = self.relations()[index]();
|
||||||
|
|
||||||
|
return cur.name.trim() === "" && (cur.relationId !== "" || cur.value !== "");
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getTargetRelation = function(target) {
|
||||||
|
const context = ko.contextFor(target);
|
||||||
|
const index = context.$index();
|
||||||
|
|
||||||
|
return self.relations()[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function showDialog() {
|
||||||
|
glob.activeDialog = $dialog;
|
||||||
|
|
||||||
|
await relationsModel.loadRelations();
|
||||||
|
|
||||||
|
$dialog.dialog({
|
||||||
|
modal: true,
|
||||||
|
width: 800,
|
||||||
|
height: 500
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ko.applyBindings(relationsModel, document.getElementById('relations-dialog'));
|
||||||
|
|
||||||
|
$(document).on('focus', '.relation-name', function (e) {
|
||||||
|
if (!$(this).hasClass("ui-autocomplete-input")) {
|
||||||
|
$(this).autocomplete({
|
||||||
|
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
||||||
|
// because we have overriden filter() function in autocomplete.js
|
||||||
|
source: relationNames.map(relation => {
|
||||||
|
return {
|
||||||
|
relation: relation,
|
||||||
|
value: relation
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
minLength: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).autocomplete("search", $(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('focus', '.relation-value', async function (e) {
|
||||||
|
if (!$(this).hasClass("ui-autocomplete-input")) {
|
||||||
|
const relationName = $(this).parent().parent().find('.relation-name').val();
|
||||||
|
|
||||||
|
if (relationName.trim() === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const relationValues = await server.get('relations/values/' + encodeURIComponent(relationName));
|
||||||
|
|
||||||
|
if (relationValues.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).autocomplete({
|
||||||
|
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
||||||
|
// because we have overriden filter() function in autocomplete.js
|
||||||
|
source: relationValues.map(relation => {
|
||||||
|
return {
|
||||||
|
label: relation,
|
||||||
|
value: relation
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
minLength: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).autocomplete("search", $(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
showDialog
|
||||||
|
};
|
@ -12,6 +12,7 @@ import recentChangesDialog from "../dialogs/recent_changes.js";
|
|||||||
import sqlConsoleDialog from "../dialogs/sql_console.js";
|
import sqlConsoleDialog from "../dialogs/sql_console.js";
|
||||||
import searchNotesService from "./search_notes.js";
|
import searchNotesService from "./search_notes.js";
|
||||||
import labelsDialog from "../dialogs/labels.js";
|
import labelsDialog from "../dialogs/labels.js";
|
||||||
|
import relationsDialog from "../dialogs/relations.js";
|
||||||
import protectedSessionService from "./protected_session.js";
|
import protectedSessionService from "./protected_session.js";
|
||||||
|
|
||||||
function registerEntrypoints() {
|
function registerEntrypoints() {
|
||||||
@ -40,6 +41,9 @@ function registerEntrypoints() {
|
|||||||
$(".show-labels-button").click(labelsDialog.showDialog);
|
$(".show-labels-button").click(labelsDialog.showDialog);
|
||||||
utils.bindShortcut('alt+l', labelsDialog.showDialog);
|
utils.bindShortcut('alt+l', labelsDialog.showDialog);
|
||||||
|
|
||||||
|
$(".show-relations-button").click(relationsDialog.showDialog);
|
||||||
|
utils.bindShortcut('alt+r', relationsDialog.showDialog);
|
||||||
|
|
||||||
$("#options-button").click(optionsDialog.showDialog);
|
$("#options-button").click(optionsDialog.showDialog);
|
||||||
|
|
||||||
utils.bindShortcut('alt+o', sqlConsoleDialog.showDialog);
|
utils.bindShortcut('alt+o', sqlConsoleDialog.showDialog);
|
||||||
|
63
src/routes/api/relations.js
Normal file
63
src/routes/api/relations.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const sql = require('../../services/sql');
|
||||||
|
const relationService = require('../../services/relations');
|
||||||
|
const repository = require('../../services/repository');
|
||||||
|
const Relation = require('../../entities/relation');
|
||||||
|
|
||||||
|
async function getNoteRelations(req) {
|
||||||
|
const noteId = req.params.noteId;
|
||||||
|
|
||||||
|
return await repository.getEntities("SELECT * FROM relations WHERE isDeleted = 0 AND sourceNoteId = ? ORDER BY position, dateCreated", [noteId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateNoteRelations(req) {
|
||||||
|
const noteId = req.params.noteId;
|
||||||
|
const relations = req.body;
|
||||||
|
|
||||||
|
for (const relation of relations) {
|
||||||
|
let relationEntity;
|
||||||
|
|
||||||
|
if (relation.labelId) {
|
||||||
|
relationEntity = await repository.getRelation(relation.relationId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if it was "created" and then immediatelly deleted, we just don't create it at all
|
||||||
|
if (relation.isDeleted) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
relationEntity = new Relation();
|
||||||
|
relationEntity.sourceNoteId = noteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
relationEntity.name = relation.name;
|
||||||
|
relationEntity.targetNoteId = relation.targetNoteId;
|
||||||
|
relationEntity.position = relation.position;
|
||||||
|
relationEntity.isDeleted = relation.isDeleted;
|
||||||
|
|
||||||
|
await relationEntity.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return await repository.getEntities("SELECT * FROM relations WHERE isDeleted = 0 AND sourceNoteId = ? ORDER BY position, dateCreated", [noteId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllRelationNames() {
|
||||||
|
const names = await sql.getColumn("SELECT DISTINCT name FROM relations WHERE isDeleted = 0");
|
||||||
|
|
||||||
|
for (const relationName of relationService.BUILTIN_RELATIONS) {
|
||||||
|
if (!names.includes(relationName)) {
|
||||||
|
names.push(relationName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
names.sort();
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getNoteRelations,
|
||||||
|
updateNoteRelations,
|
||||||
|
getAllRelationNames
|
||||||
|
};
|
@ -26,6 +26,7 @@ const anonymizationRoute = require('./api/anonymization');
|
|||||||
const cleanupRoute = require('./api/cleanup');
|
const cleanupRoute = require('./api/cleanup');
|
||||||
const imageRoute = require('./api/image');
|
const imageRoute = require('./api/image');
|
||||||
const labelsRoute = require('./api/labels');
|
const labelsRoute = require('./api/labels');
|
||||||
|
const relationsRoute = require('./api/relations');
|
||||||
const scriptRoute = require('./api/script');
|
const scriptRoute = require('./api/script');
|
||||||
const senderRoute = require('./api/sender');
|
const senderRoute = require('./api/sender');
|
||||||
const filesRoute = require('./api/file_upload');
|
const filesRoute = require('./api/file_upload');
|
||||||
@ -137,6 +138,10 @@ function register(app) {
|
|||||||
apiRoute(GET, '/api/labels/names', labelsRoute.getAllLabelNames);
|
apiRoute(GET, '/api/labels/names', labelsRoute.getAllLabelNames);
|
||||||
apiRoute(GET, '/api/labels/values/:labelName', labelsRoute.getValuesForLabel);
|
apiRoute(GET, '/api/labels/values/:labelName', labelsRoute.getValuesForLabel);
|
||||||
|
|
||||||
|
apiRoute(GET, '/api/notes/:noteId/relations', relationsRoute.getNoteRelations);
|
||||||
|
apiRoute(PUT, '/api/notes/:noteId/relations', relationsRoute.updateNoteRelations);
|
||||||
|
apiRoute(GET, '/api/relations/names', relationsRoute.getAllRelationNames);
|
||||||
|
|
||||||
route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
|
route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
|
||||||
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware], imageRoute.uploadImage, apiResultHandler);
|
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware], imageRoute.uploadImage, apiResultHandler);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const build = require('./build');
|
const build = require('./build');
|
||||||
const packageJson = require('../../package');
|
const packageJson = require('../../package');
|
||||||
|
|
||||||
const APP_DB_VERSION = 105;
|
const APP_DB_VERSION = 106;
|
||||||
const SYNC_VERSION = 1;
|
const SYNC_VERSION = 1;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
44
src/services/relations.js
Normal file
44
src/services/relations.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const repository = require('./repository');
|
||||||
|
const Relation = require('../entities/relation');
|
||||||
|
|
||||||
|
const BUILTIN_RELATIONS = [
|
||||||
|
'exampleBuiltIn'
|
||||||
|
];
|
||||||
|
|
||||||
|
async function getNotesWithRelation(name, targetNoteId) {
|
||||||
|
let notes;
|
||||||
|
|
||||||
|
if (targetNoteId !== undefined) {
|
||||||
|
notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN relations ON notes.noteId = relations.sourceNoteId
|
||||||
|
WHERE notes.isDeleted = 0 AND relations.isDeleted = 0 AND relations.name = ? AND relations.targetNoteId = ?`, [name, targetNoteId]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN relations ON notes.noteId = relations.sourceNoteId
|
||||||
|
WHERE notes.isDeleted = 0 AND relations.isDeleted = 0 AND relations.name = ?`, [name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getNoteWithRelation(name, value) {
|
||||||
|
const notes = await getNotesWithRelation(name, value);
|
||||||
|
|
||||||
|
return notes.length > 0 ? notes[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createRelation(sourceNoteId, name, targetNoteId) {
|
||||||
|
return await new Relation({
|
||||||
|
sourceNoteId: sourceNoteId,
|
||||||
|
name: name,
|
||||||
|
targetNoteId: targetNoteId
|
||||||
|
}).save();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getNotesWithRelation,
|
||||||
|
getNoteWithRelation,
|
||||||
|
createRelation,
|
||||||
|
BUILTIN_RELATIONS
|
||||||
|
};
|
@ -41,6 +41,10 @@ async function getLabel(labelId) {
|
|||||||
return await getEntity("SELECT * FROM labels WHERE labelId = ?", [labelId]);
|
return await getEntity("SELECT * FROM labels WHERE labelId = ?", [labelId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getRelation(relationId) {
|
||||||
|
return await getEntity("SELECT * FROM relations WHERE relationId = ?", [relationId]);
|
||||||
|
}
|
||||||
|
|
||||||
async function getOption(name) {
|
async function getOption(name) {
|
||||||
return await getEntity("SELECT * FROM options WHERE name = ?", [name]);
|
return await getEntity("SELECT * FROM options WHERE name = ?", [name]);
|
||||||
}
|
}
|
||||||
@ -72,6 +76,7 @@ module.exports = {
|
|||||||
getBranch,
|
getBranch,
|
||||||
getImage,
|
getImage,
|
||||||
getLabel,
|
getLabel,
|
||||||
|
getRelation,
|
||||||
getOption,
|
getOption,
|
||||||
updateEntity,
|
updateEntity,
|
||||||
setEntityConstructor
|
setEntityConstructor
|
||||||
|
@ -236,6 +236,7 @@ const primaryKeys = {
|
|||||||
"images": "imageId",
|
"images": "imageId",
|
||||||
"note_images": "noteImageId",
|
"note_images": "noteImageId",
|
||||||
"labels": "labelId",
|
"labels": "labelId",
|
||||||
|
"relations": "relationId",
|
||||||
"api_tokens": "apiTokenId",
|
"api_tokens": "apiTokenId",
|
||||||
"options": "name"
|
"options": "name"
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,10 @@ async function addLabelSync(labelId, sourceId) {
|
|||||||
await addEntitySync("labels", labelId, sourceId);
|
await addEntitySync("labels", labelId, sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addRelationSync(relationId, sourceId) {
|
||||||
|
await addEntitySync("relations", relationId, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
async function addApiTokenSync(apiTokenId, sourceId) {
|
async function addApiTokenSync(apiTokenId, sourceId) {
|
||||||
await addEntitySync("api_tokens", apiTokenId, sourceId);
|
await addEntitySync("api_tokens", apiTokenId, sourceId);
|
||||||
}
|
}
|
||||||
@ -101,6 +105,7 @@ async function fillAllSyncRows() {
|
|||||||
await fillSyncRows("images", "imageId");
|
await fillSyncRows("images", "imageId");
|
||||||
await fillSyncRows("note_images", "noteImageId");
|
await fillSyncRows("note_images", "noteImageId");
|
||||||
await fillSyncRows("labels", "labelId");
|
await fillSyncRows("labels", "labelId");
|
||||||
|
await fillSyncRows("relations", "relationId");
|
||||||
await fillSyncRows("api_tokens", "apiTokenId");
|
await fillSyncRows("api_tokens", "apiTokenId");
|
||||||
await fillSyncRows("options", "name", 'isSynced = 1');
|
await fillSyncRows("options", "name", 'isSynced = 1');
|
||||||
}
|
}
|
||||||
@ -115,6 +120,7 @@ module.exports = {
|
|||||||
addImageSync,
|
addImageSync,
|
||||||
addNoteImageSync,
|
addNoteImageSync,
|
||||||
addLabelSync,
|
addLabelSync,
|
||||||
|
addRelationSync,
|
||||||
addApiTokenSync,
|
addApiTokenSync,
|
||||||
addEntitySync,
|
addEntitySync,
|
||||||
cleanupSyncRowsForMissingEntities,
|
cleanupSyncRowsForMissingEntities,
|
||||||
|
@ -33,6 +33,9 @@ async function updateEntity(sync, entity, sourceId) {
|
|||||||
else if (entityName === 'labels') {
|
else if (entityName === 'labels') {
|
||||||
await updateLabel(entity, sourceId);
|
await updateLabel(entity, sourceId);
|
||||||
}
|
}
|
||||||
|
else if (entityName === 'relations') {
|
||||||
|
await updateRelation(entity, sourceId);
|
||||||
|
}
|
||||||
else if (entityName === 'api_tokens') {
|
else if (entityName === 'api_tokens') {
|
||||||
await updateApiToken(entity, sourceId);
|
await updateApiToken(entity, sourceId);
|
||||||
}
|
}
|
||||||
@ -185,6 +188,20 @@ async function updateLabel(entity, sourceId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateRelation(entity, sourceId) {
|
||||||
|
const origRelation = await sql.getRow("SELECT * FROM relations WHERE relationId = ?", [entity.relationId]);
|
||||||
|
|
||||||
|
if (!origRelation || origRelation.dateModified <= entity.dateModified) {
|
||||||
|
await sql.transactional(async () => {
|
||||||
|
await sql.replace("relations", entity);
|
||||||
|
|
||||||
|
await syncTableService.addRelationSync(entity.relationId, sourceId);
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("Update/sync relation " + entity.relationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function updateApiToken(entity, sourceId) {
|
async function updateApiToken(entity, sourceId) {
|
||||||
const apiTokenId = await sql.getRow("SELECT * FROM api_tokens WHERE apiTokenId = ?", [entity.apiTokenId]);
|
const apiTokenId = await sql.getRow("SELECT * FROM api_tokens WHERE apiTokenId = ?", [entity.apiTokenId]);
|
||||||
|
|
||||||
|
@ -170,6 +170,7 @@
|
|||||||
<ul class="dropdown-menu dropdown-menu-right">
|
<ul class="dropdown-menu dropdown-menu-right">
|
||||||
<li><a id="show-note-revisions-button">Note revisions</a></li>
|
<li><a id="show-note-revisions-button">Note revisions</a></li>
|
||||||
<li><a class="show-labels-button"><kbd>Alt+L</kbd> Labels</a></li>
|
<li><a class="show-labels-button"><kbd>Alt+L</kbd> Labels</a></li>
|
||||||
|
<li><a class="show-relations-button"><kbd>Alt+R</kbd> Relations</a></li>
|
||||||
<li><a id="show-source-button">HTML source</a></li>
|
<li><a id="show-source-button">HTML source</a></li>
|
||||||
<li><a id="upload-file-button">Upload file</a></li>
|
<li><a id="upload-file-button">Upload file</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -587,6 +588,50 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="relations-dialog" title="Note relations" style="display: none; padding: 20px;">
|
||||||
|
<form data-bind="submit: save">
|
||||||
|
<div style="text-align: center">
|
||||||
|
<button class="btn btn-large" style="width: 200px;" id="save-relations-button" type="submit">Save changes <kbd>enter</kbd></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="height: 97%; overflow: auto">
|
||||||
|
<table id="relations-table" class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Relation name</th>
|
||||||
|
<th>Target note</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-bind="foreach: relations">
|
||||||
|
<tr data-bind="if: isDeleted == 0">
|
||||||
|
<td class="handle">
|
||||||
|
<span class="glyphicon glyphicon-resize-vertical"></span>
|
||||||
|
<input type="hidden" name="position" data-bind="value: position"/>
|
||||||
|
</td>
|
||||||
|
<!-- ID column has specific width because if it's empty its size can be deformed when dragging -->
|
||||||
|
<td data-bind="text: relationId" style="width: 150px;"></td>
|
||||||
|
<td>
|
||||||
|
<!-- Change to valueUpdate: blur is necessary because jQuery UI autocomplete hijacks change event -->
|
||||||
|
<input type="text" class="relation-name" data-bind="value: name, valueUpdate: 'blur', event: { blur: $parent.relationChanged }"/>
|
||||||
|
<div style="color: yellowgreen" data-bind="if: $parent.isNotUnique($index())"><span class="glyphicon glyphicon-info-sign"></span> Duplicate relation.</div>
|
||||||
|
<div style="color: red" data-bind="if: $parent.isEmptyName($index())">Relation name can't be empty.</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" class="relation-value" data-bind="value: value, valueUpdate: 'blur', event: { blur: $parent.relationChanged }" style="width: 300px"/>
|
||||||
|
</td>
|
||||||
|
<td title="Delete" style="padding: 13px;">
|
||||||
|
<span class="glyphicon glyphicon-trash" data-bind="click: $parent.deleteRelation"></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="tooltip" style="display: none;"></div>
|
<div id="tooltip" style="display: none;"></div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user