erasing note revisions

This commit is contained in:
zadam 2019-11-09 15:21:14 +01:00
parent 7cd75cebfc
commit 9b24ae0600
10 changed files with 213 additions and 92 deletions

View File

@ -309,359 +309,365 @@ parentNoteId</ColNames>
<DataType>INT|0s</DataType> <DataType>INT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="74" parent="11" name="isProtected"> <column id="74" parent="11" name="isErased">
<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="75" parent="11" name="utcDateLastEdited"> <column id="75" parent="11" name="isProtected">
<Position>6</Position> <Position>6</Position>
<DataType>TEXT|0s</DataType> <DataType>INT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column> </column>
<column id="76" parent="11" name="utcDateCreated"> <column id="76" parent="11" name="utcDateLastEdited">
<Position>7</Position> <Position>7</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="77" parent="11" name="utcDateModified"> <column id="77" parent="11" name="utcDateCreated">
<Position>8</Position> <Position>8</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="78" parent="11" name="dateLastEdited"> <column id="78" parent="11" name="utcDateModified">
<Position>9</Position> <Position>9</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="79" parent="11" name="dateCreated"> <column id="79" parent="11" name="dateLastEdited">
<Position>10</Position> <Position>10</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="80" parent="11" name="type"> <column id="80" parent="11" name="dateCreated">
<Position>11</Position> <Position>11</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column> </column>
<column id="81" parent="11" name="mime"> <column id="81" parent="11" name="type">
<Position>12</Position> <Position>12</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression> <DefaultExpression>&apos;&apos;</DefaultExpression>
</column> </column>
<column id="82" parent="11" name="hash"> <column id="82" parent="11" name="mime">
<Position>13</Position> <Position>13</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression> <DefaultExpression>&apos;&apos;</DefaultExpression>
</column> </column>
<index id="83" parent="11" name="sqlite_autoindex_note_revisions_1"> <column id="83" parent="11" name="hash">
<Position>14</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<index id="84" parent="11" 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="84" parent="11" name="IDX_note_revisions_noteId"> <index id="85" parent="11" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames> <ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="85" parent="11" name="IDX_note_revisions_utcDateLastEdited"> <index id="86" parent="11" name="IDX_note_revisions_utcDateLastEdited">
<ColNames>utcDateLastEdited</ColNames> <ColNames>utcDateLastEdited</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="86" parent="11" name="IDX_note_revisions_utcDateCreated"> <index id="87" parent="11" name="IDX_note_revisions_utcDateCreated">
<ColNames>utcDateCreated</ColNames> <ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="87" parent="11" name="IDX_note_revisions_dateLastEdited"> <index id="88" parent="11" name="IDX_note_revisions_dateLastEdited">
<ColNames>dateLastEdited</ColNames> <ColNames>dateLastEdited</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="88" parent="11" name="IDX_note_revisions_dateCreated"> <index id="89" parent="11" name="IDX_note_revisions_dateCreated">
<ColNames>dateCreated</ColNames> <ColNames>dateCreated</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<key id="89" parent="11"> <key id="90" parent="11">
<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="90" parent="12" name="noteId"> <column id="91" parent="12" 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="91" parent="12" name="title"> <column id="92" parent="12" name="title">
<Position>2</Position> <Position>2</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&quot;note&quot;</DefaultExpression> <DefaultExpression>&quot;note&quot;</DefaultExpression>
</column> </column>
<column id="92" parent="12" name="contentLength"> <column id="93" parent="12" name="contentLength">
<Position>3</Position> <Position>3</Position>
<DataType>INT|0s</DataType> <DataType>INT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="93" parent="12" name="isProtected"> <column id="94" parent="12" 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="94" parent="12" name="type"> <column id="95" parent="12" name="type">
<Position>5</Position> <Position>5</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&apos;text&apos;</DefaultExpression> <DefaultExpression>&apos;text&apos;</DefaultExpression>
</column> </column>
<column id="95" parent="12" name="mime"> <column id="96" parent="12" name="mime">
<Position>6</Position> <Position>6</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&apos;text/html&apos;</DefaultExpression> <DefaultExpression>&apos;text/html&apos;</DefaultExpression>
</column> </column>
<column id="96" parent="12" name="hash"> <column id="97" parent="12" name="hash">
<Position>7</Position> <Position>7</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression> <DefaultExpression>&quot;&quot;</DefaultExpression>
</column> </column>
<column id="97" parent="12" name="isDeleted"> <column id="98" parent="12" name="isDeleted">
<Position>8</Position> <Position>8</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="98" parent="12" name="isErased"> <column id="99" parent="12" name="isErased">
<Position>9</Position> <Position>9</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="99" parent="12" name="dateCreated"> <column id="100" parent="12" name="dateCreated">
<Position>10</Position> <Position>10</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="100" parent="12" name="dateModified"> <column id="101" parent="12" name="dateModified">
<Position>11</Position> <Position>11</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="101" parent="12" name="utcDateCreated"> <column id="102" parent="12" name="utcDateCreated">
<Position>12</Position> <Position>12</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="102" parent="12" name="utcDateModified"> <column id="103" parent="12" name="utcDateModified">
<Position>13</Position> <Position>13</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<index id="103" parent="12" name="sqlite_autoindex_notes_1"> <index id="104" parent="12" 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="104" parent="12" name="IDX_notes_title"> <index id="105" parent="12" name="IDX_notes_title">
<ColNames>title</ColNames> <ColNames>title</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="105" parent="12" name="IDX_notes_type"> <index id="106" parent="12" name="IDX_notes_type">
<ColNames>type</ColNames> <ColNames>type</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="106" parent="12" name="IDX_notes_isDeleted"> <index id="107" parent="12" name="IDX_notes_isDeleted">
<ColNames>isDeleted</ColNames> <ColNames>isDeleted</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="107" parent="12" name="IDX_notes_dateCreated"> <index id="108" parent="12" name="IDX_notes_dateCreated">
<ColNames>dateCreated</ColNames> <ColNames>dateCreated</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="108" parent="12" name="IDX_notes_dateModified"> <index id="109" parent="12" name="IDX_notes_dateModified">
<ColNames>dateModified</ColNames> <ColNames>dateModified</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="109" parent="12" name="IDX_notes_utcDateCreated"> <index id="110" parent="12" name="IDX_notes_utcDateCreated">
<ColNames>utcDateCreated</ColNames> <ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<index id="110" parent="12" name="IDX_notes_utcDateModified"> <index id="111" parent="12" name="IDX_notes_utcDateModified">
<ColNames>utcDateModified</ColNames> <ColNames>utcDateModified</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<key id="111" parent="12"> <key id="112" parent="12">
<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="13" name="name"> <column id="113" parent="13" 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="13" name="value"> <column id="114" parent="13" name="value">
<Position>2</Position> <Position>2</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
</column> </column>
<column id="114" parent="13" name="isSynced"> <column id="115" parent="13" name="isSynced">
<Position>3</Position> <Position>3</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="115" parent="13" name="hash"> <column id="116" parent="13" name="hash">
<Position>4</Position> <Position>4</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression> <DefaultExpression>&quot;&quot;</DefaultExpression>
</column> </column>
<column id="116" parent="13" name="utcDateCreated"> <column id="117" parent="13" name="utcDateCreated">
<Position>5</Position> <Position>5</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="117" parent="13" name="utcDateModified"> <column id="118" parent="13" name="utcDateModified">
<Position>6</Position> <Position>6</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<index id="118" parent="13" name="sqlite_autoindex_options_1"> <index id="119" parent="13" name="sqlite_autoindex_options_1">
<NameSurrogate>1</NameSurrogate> <NameSurrogate>1</NameSurrogate>
<ColNames>name</ColNames> <ColNames>name</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
<Unique>1</Unique> <Unique>1</Unique>
</index> </index>
<key id="119" parent="13"> <key id="120" parent="13">
<ColNames>name</ColNames> <ColNames>name</ColNames>
<Primary>1</Primary> <Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName> <UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
</key> </key>
<column id="120" parent="14" name="noteId"> <column id="121" parent="14" 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="121" parent="14" name="notePath"> <column id="122" parent="14" name="notePath">
<Position>2</Position> <Position>2</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="122" parent="14" name="hash"> <column id="123" parent="14" name="hash">
<Position>3</Position> <Position>3</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression> <DefaultExpression>&quot;&quot;</DefaultExpression>
</column> </column>
<column id="123" parent="14" name="utcDateCreated"> <column id="124" parent="14" name="utcDateCreated">
<Position>4</Position> <Position>4</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="124" parent="14" name="isDeleted"> <column id="125" parent="14" name="isDeleted">
<Position>5</Position> <Position>5</Position>
<DataType>INT|0s</DataType> <DataType>INT|0s</DataType>
</column> </column>
<index id="125" parent="14" name="sqlite_autoindex_recent_notes_1"> <index id="126" parent="14" name="sqlite_autoindex_recent_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>
<key id="126" parent="14"> <key id="127" parent="14">
<ColNames>noteId</ColNames> <ColNames>noteId</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="127" parent="15" name="sourceId"> <column id="128" parent="15" name="sourceId">
<Position>1</Position> <Position>1</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<column id="128" parent="15" name="utcDateCreated"> <column id="129" parent="15" name="utcDateCreated">
<Position>2</Position> <Position>2</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<index id="129" parent="15" name="sqlite_autoindex_source_ids_1"> <index id="130" parent="15" 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="130" parent="15"> <key id="131" parent="15">
<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="131" parent="16" name="type"> <column id="132" parent="16" name="type">
<Position>1</Position> <Position>1</Position>
<DataType>text|0s</DataType> <DataType>text|0s</DataType>
</column> </column>
<column id="132" parent="16" name="name"> <column id="133" parent="16" name="name">
<Position>2</Position> <Position>2</Position>
<DataType>text|0s</DataType> <DataType>text|0s</DataType>
</column> </column>
<column id="133" parent="16" name="tbl_name"> <column id="134" parent="16" name="tbl_name">
<Position>3</Position> <Position>3</Position>
<DataType>text|0s</DataType> <DataType>text|0s</DataType>
</column> </column>
<column id="134" parent="16" name="rootpage"> <column id="135" parent="16" name="rootpage">
<Position>4</Position> <Position>4</Position>
<DataType>int|0s</DataType> <DataType>int|0s</DataType>
</column> </column>
<column id="135" parent="16" name="sql"> <column id="136" parent="16" name="sql">
<Position>5</Position> <Position>5</Position>
<DataType>text|0s</DataType> <DataType>text|0s</DataType>
</column> </column>
<column id="136" parent="17" name="name"> <column id="137" parent="17" name="name">
<Position>1</Position> <Position>1</Position>
</column> </column>
<column id="137" parent="17" name="seq"> <column id="138" parent="17" name="seq">
<Position>2</Position> <Position>2</Position>
</column> </column>
<column id="138" parent="18" name="id"> <column id="139" parent="18" 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="139" parent="18" name="entityName"> <column id="140" parent="18" 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="140" parent="18" name="entityId"> <column id="141" parent="18" 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="141" parent="18" name="sourceId"> <column id="142" parent="18" 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="142" parent="18" name="utcSyncDate"> <column id="143" parent="18" name="utcSyncDate">
<Position>5</Position> <Position>5</Position>
<DataType>TEXT|0s</DataType> <DataType>TEXT|0s</DataType>
<NotNull>1</NotNull> <NotNull>1</NotNull>
</column> </column>
<index id="143" parent="18" name="IDX_sync_entityName_entityId"> <index id="144" parent="18" 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="144" parent="18" name="IDX_sync_utcSyncDate"> <index id="145" parent="18" name="IDX_sync_utcSyncDate">
<ColNames>utcSyncDate</ColNames> <ColNames>utcSyncDate</ColNames>
<ColumnCollations></ColumnCollations> <ColumnCollations></ColumnCollations>
</index> </index>
<key id="145" parent="18"> <key id="146" parent="18">
<ColNames>id</ColNames> <ColNames>id</ColNames>
<Primary>1</Primary> <Primary>1</Primary>
</key> </key>

View File

@ -0,0 +1,26 @@
CREATE TABLE IF NOT EXISTS "note_revisions_mig" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
`noteId` TEXT NOT NULL,
`title` TEXT,
`contentLength` INT NOT NULL,
`isErased` INT NOT NULL DEFAULT 0,
`isProtected` INT NOT NULL DEFAULT 0,
`utcDateLastEdited` TEXT NOT NULL,
`utcDateCreated` TEXT NOT NULL,
`utcDateModified` TEXT NOT NULL,
`dateLastEdited` TEXT NOT NULL,
`dateCreated` TEXT NOT NULL,
type TEXT DEFAULT '' NOT NULL,
mime TEXT DEFAULT '' NOT NULL,
hash TEXT DEFAULT '' NOT NULL);
INSERT INTO note_revisions_mig (noteRevisionId, noteId, title, contentLength, isErased, isProtected, utcDateLastEdited, utcDateCreated, utcDateModified, dateLastEdited, dateCreated, type, mime, hash)
SELECT noteRevisionId, noteId, title, contentLength, 0, isProtected, utcDateLastEdited, utcDateCreated, utcDateModified, dateLastEdited, dateCreated, type, mime, hash FROM note_revisions;
DROP TABLE note_revisions;
ALTER TABLE note_revisions_mig RENAME TO note_revisions;
CREATE INDEX `IDX_note_revisions_noteId` ON `note_revisions` (`noteId`);
CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCreated`);
CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`);
CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`);
CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`);

View File

@ -16,8 +16,9 @@ const syncTableService = require('../services/sync_table');
* @property {string} type * @property {string} type
* @property {string} mime * @property {string} mime
* @property {string} title * @property {string} title
* @property {int} contentLength - length of content * @property {int} contentLength
* @property {string} isProtected * @property {boolean} isErased
* @property {boolean} isProtected
* @property {string} dateLastEdited * @property {string} dateLastEdited
* @property {string} dateCreated * @property {string} dateCreated
* @property {string} utcDateLastEdited * @property {string} utcDateLastEdited
@ -29,7 +30,7 @@ const syncTableService = require('../services/sync_table');
class NoteRevision extends Entity { class NoteRevision extends Entity {
static get entityName() { return "note_revisions"; } static get entityName() { return "note_revisions"; }
static get primaryKeyName() { return "noteRevisionId"; } static get primaryKeyName() { return "noteRevisionId"; }
static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "contentLength", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; } static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "contentLength", "isErased", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; }
constructor(row) { constructor(row) {
super(row); super(row);
@ -103,7 +104,7 @@ class NoteRevision extends Entity {
async setContent(content) { async setContent(content) {
// force updating note itself so that utcDateModified is represented correctly even for the content // force updating note itself so that utcDateModified is represented correctly even for the content
this.forcedChange = true; this.forcedChange = true;
this.contentLength = content.length; this.contentLength = content === null ? 0 : content.length;
await this.save(); await this.save();
this.content = content; this.content = content;

View File

@ -1,12 +1,14 @@
import noteDetailService from '../services/note_detail.js'; import noteDetailService from '../services/note_detail.js';
import utils from '../services/utils.js'; import utils from '../services/utils.js';
import server from '../services/server.js'; import server from '../services/server.js';
import toastService from "../services/toast.js";
const $dialog = $("#note-revisions-dialog"); const $dialog = $("#note-revisions-dialog");
const $list = $("#note-revision-list"); const $list = $("#note-revision-list");
const $content = $("#note-revision-content"); const $content = $("#note-revision-content");
const $title = $("#note-revision-title"); const $title = $("#note-revision-title");
const $titleButtons = $("#note-revision-title-buttons"); const $titleButtons = $("#note-revision-title-buttons");
const $eraseAllRevisionsButton = $("#note-revisions-erase-all-revisions-button");
let revisionItems = []; let revisionItems = [];
let note; let note;
@ -22,6 +24,10 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
$dialog.modal(); $dialog.modal();
await loadNoteRevisions(noteId, noteRevisionId);
}
async function loadNoteRevisions(noteId, noteRevisionId) {
$list.empty(); $list.empty();
$content.empty(); $content.empty();
@ -31,7 +37,7 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
for (const item of revisionItems) { for (const item of revisionItems) {
$list.append($('<option>', { $list.append($('<option>', {
value: item.noteRevisionId, value: item.noteRevisionId,
text: item.dateLastEdited text: item.dateLastEdited.substr(0, 16) + (item.isErased ? ' (erased)' : '')
})); }));
} }
@ -41,8 +47,7 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
} }
$list.val(noteRevisionId).trigger('change'); $list.val(noteRevisionId).trigger('change');
} } else {
else {
$title.text("No revisions for this note yet..."); $title.text("No revisions for this note yet...");
} }
} }
@ -52,15 +57,42 @@ $list.on('change', async () => {
const revisionItem = revisionItems.find(r => r.noteRevisionId === optVal); const revisionItem = revisionItems.find(r => r.noteRevisionId === optVal);
$titleButtons.empty();
$content.empty();
if (revisionItem.isErased) {
$title.text('This revision has been erased');
return;
}
$title.html(revisionItem.title); $title.html(revisionItem.title);
const $eraseRevisionButton = $('<button class="btn btn-sm" type="button">Erase this revision</button>');
$eraseRevisionButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to erase this revision? This action will erase revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
loadNoteRevisions(revisionItem.noteId);
toastService.showMessage('Note revision has been erased.');
}
});
$titleButtons
.append($eraseRevisionButton)
.append(' &nbsp; ');
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>'); const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
$downloadButton.on('click', () => { $downloadButton.on('click', () => {
utils.download(utils.getHost() + `/api/notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}/download`); utils.download(utils.getHost() + `/api/notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}/download`);
}); });
$titleButtons.html($downloadButton); $titleButtons.append($downloadButton);
const fullNoteRevision = await server.get(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`); const fullNoteRevision = await server.get(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
@ -104,3 +136,16 @@ $list.on('change', async () => {
$content.text("Preview isn't available for this note type."); $content.text("Preview isn't available for this note type.");
} }
}); });
$eraseAllRevisionsButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to erase all revision of this note? This action will erase revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${note.noteId}/revisions`);
$dialog.modal('hide');
toastService.showMessage('Note revisions has been erased.');
}
});

View File

@ -7,13 +7,10 @@ const utils = require('../../services/utils');
const path = require('path'); const path = require('path');
async function getNoteRevisions(req) { async function getNoteRevisions(req) {
const {noteId} = req.params;
return await repository.getEntities(` return await repository.getEntities(`
SELECT note_revisions.* SELECT * FROM note_revisions
FROM note_revisions WHERE noteId = ? AND isErased = 0
WHERE noteId = ? ORDER BY utcDateCreated DESC`, [req.params.noteId]);
ORDER BY utcDateCreated DESC`, [noteId]);
} }
async function getNoteRevision(req) { async function getNoteRevision(req) {
@ -86,6 +83,31 @@ async function downloadNoteRevision(req, res) {
res.send(await noteRevision.getContent()); res.send(await noteRevision.getContent());
} }
async function eraseOneNoteRevision(noteRevision) {
noteRevision.isErased = true;
noteRevision.title = null;
await noteRevision.setContent(null);
await noteRevision.save();
}
async function eraseAllNoteRevisions(req) {
const noteRevisionsToErase = await repository.getEntities(
'SELECT * FROM note_revisions WHERE isErased = 0 AND noteId = ?',
[req.params.noteId]);
for (const noteRevision of noteRevisionsToErase) {
await eraseOneNoteRevision(noteRevision);
}
}
async function eraseNoteRevision(req) {
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
if (noteRevision && !noteRevision.isErased) {
await eraseOneNoteRevision(noteRevision);
}
}
async function getEditedNotesOnDate(req) { async function getEditedNotesOnDate(req) {
const date = req.params.date; const date = req.params.date;
@ -110,5 +132,7 @@ module.exports = {
getNoteRevisions, getNoteRevisions,
getNoteRevision, getNoteRevision,
downloadNoteRevision, downloadNoteRevision,
getEditedNotesOnDate getEditedNotesOnDate,
eraseAllNoteRevisions,
eraseNoteRevision
}; };

View File

@ -132,7 +132,9 @@ function register(app) {
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree); apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree);
apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime); apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime);
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions); apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions);
apiRoute(GET, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.getNoteRevision); 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); route(GET, '/api/notes/:noteId/revisions/:noteRevisionId/download', [auth.checkApiAuthOrElectron], noteRevisionsApiRoute.downloadNoteRevision);
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap); apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle); apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle);

View File

@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package'); const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir'); const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 152; const APP_DB_VERSION = 153;
const SYNC_VERSION = 11; const SYNC_VERSION = 11;
const CLIPPER_PROTOCOL_VERSION = "1.0"; const CLIPPER_PROTOCOL_VERSION = "1.0";

View File

@ -470,11 +470,20 @@ async function eraseDeletedNotes() {
utcDateModified = '${utcNowDateTime}' utcDateModified = '${utcNowDateTime}'
WHERE noteId IN (???)`, noteIdsToErase); WHERE noteId IN (???)`, noteIdsToErase);
// deleting first contents since the WHERE relies on isErased = 0
await sql.executeMany(` await sql.executeMany(`
UPDATE note_revisions UPDATE note_revision_contents
SET content = NULL, SET content = NULL,
utcDateModified = '${utcNowDateTime}' utcDateModified = '${utcNowDateTime}'
WHERE noteId IN (???)`, noteIdsToErase); WHERE noteRevisionId IN
(SELECT noteRevisionId FROM note_revisions WHERE isErased = 0 AND noteId IN ((???)))`, noteIdsToErase);
await sql.executeMany(`
UPDATE note_revisions
SET isErased = 1,
title = NULL,
utcDateModified = '${utcNowDateTime}'
WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase);
} }
async function duplicateNote(noteId, parentNoteId) { async function duplicateNote(noteId, parentNoteId) {

View File

@ -18,6 +18,9 @@ async function updateEntity(sync, entity, sourceId) {
else if (entityName === 'note_revisions') { else if (entityName === 'note_revisions') {
await updateNoteRevision(entity, sourceId); await updateNoteRevision(entity, sourceId);
} }
else if (entityName === 'note_revision_contents') {
await updateNoteRevisionContent(entity, sourceId);
}
else if (entityName === 'note_reordering') { else if (entityName === 'note_reordering') {
await updateNoteReordering(sync.entityId, entity, sourceId); await updateNoteReordering(sync.entityId, entity, sourceId);
} }

View File

@ -4,6 +4,11 @@
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">Note revisions</h5> <h5 class="modal-title mr-auto">Note revisions</h5>
<button class="btn btn-xs"
id="note-revisions-erase-all-revisions-button"
title="Erase all revisions of this note"
style="padding: 0 10px 0 10px;" type="button">Erase all revisions</button>
<button class="help-button" type="button" data-help-page="Note-revisions" title="Help on Note revisions">?</button> <button class="help-button" type="button" data-help-page="Note-revisions" title="Help on Note revisions">?</button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;"> <button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">