Compare commits

...

15 Commits

Author SHA1 Message Date
azivner
c8b9c7d936 release 0.12.0 2018-04-14 08:28:50 -04:00
azivner
d57057ba28 fix note ordering sync 2018-04-14 08:23:06 -04:00
azivner
66cee8daa4 restructuring CSS grid/flex which fixes jumpy scrolling in tree 2018-04-13 19:58:33 -04:00
azivner
afd7df0942 fix collapse tree button 2018-04-13 19:22:12 -04:00
azivner
bd6ae33d32 fancytree upgrade to 2.28.1 2018-04-12 20:42:12 -04:00
azivner
70660a0d68 Merge branch 'stable' 2018-04-12 20:04:01 -04:00
azivner
cdad18551a upgrade CKEditor to 1.0 beta.2, fixes #93 2018-04-12 20:03:23 -04:00
azivner
592c51d1a5 fix note reordering sync again 2018-04-12 18:31:29 -04:00
azivner
6a57b8a7e7 fix ordering sync 2018-04-12 18:13:48 -04:00
azivner
7a94e21c54 tabindex 2 for text and code editor so that tabbing from title leads to editor focus 2018-04-11 22:44:33 -04:00
azivner
5b43f321e2 release 0.11.1 2018-04-11 00:10:33 -04:00
azivner
a4eafb934f non null note title and content in the DB schema, allow saving non-valid JSON notes, children overview style changes 2018-04-11 00:10:11 -04:00
azivner
7b59a665dd hideChildrenOverview label which can disable children overview for specific notes 2018-04-10 23:15:41 -04:00
azivner
3d15450ffc children overview styling 2018-04-10 21:08:00 -04:00
azivner
b0c6d52461 can't rollback transaction multiple times 2018-04-10 20:28:02 -04:00
29 changed files with 360 additions and 255 deletions

View File

@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<dataSource name="document.db">
<database-model serializer="dbm" rdbms="SQLITE" format-version="4.7">
<root id="1"/>
<database-model serializer="dbm" rdbms="SQLITE" format-version="4.8">
<root id="1">
<ServerVersion>3.16.1</ServerVersion>
</root>
<schema id="2" parent="1" name="main">
<Current>1</Current>
<Visible>1</Visible>
@@ -107,8 +109,7 @@
<index id="35" parent="7" name="IDX_branches_noteId_parentNoteId">
<ColNames>noteId
parentNoteId</ColNames>
<ColumnCollations>
</ColumnCollations>
<ColumnCollations></ColumnCollations>
</index>
<index id="36" parent="7" name="IDX_branches_noteId">
<ColNames>noteId</ColNames>
@@ -142,445 +143,449 @@ parentNoteId</ColNames>
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<foreign-key id="43" parent="8">
<ColNames>noteId</ColNames>
<RefTableName>notes</RefTableName>
<RefColNames>noteId</RefColNames>
</foreign-key>
<column id="44" parent="9" name="imageId">
<column id="43" parent="9" name="imageId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="45" parent="9" name="format">
<column id="44" parent="9" name="format">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="46" parent="9" name="checksum">
<column id="45" parent="9" name="checksum">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="47" parent="9" name="name">
<column id="46" parent="9" name="name">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="48" parent="9" name="data">
<column id="47" parent="9" name="data">
<Position>5</Position>
<DataType>BLOB|0s</DataType>
</column>
<column id="49" parent="9" name="isDeleted">
<column id="48" parent="9" name="isDeleted">
<Position>6</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="50" parent="9" name="dateModified">
<column id="49" parent="9" name="dateModified">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="51" parent="9" name="dateCreated">
<column id="50" parent="9" name="dateCreated">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="52" parent="9" name="sqlite_autoindex_images_1">
<index id="51" parent="9" name="sqlite_autoindex_images_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>imageId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="53" parent="9">
<key id="52" parent="9">
<ColNames>imageId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_images_1</UnderlyingIndexName>
</key>
<column id="54" parent="10" name="labelId">
<column id="53" parent="10" name="labelId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="55" parent="10" name="noteId">
<column id="54" parent="10" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="56" parent="10" name="name">
<column id="55" parent="10" name="name">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="57" parent="10" name="value">
<column id="56" parent="10" name="value">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="58" parent="10" name="position">
<column id="57" parent="10" name="position">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="59" parent="10" name="dateCreated">
<column id="58" parent="10" name="dateCreated">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="60" parent="10" name="dateModified">
<column id="59" parent="10" name="dateModified">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="61" parent="10" name="isDeleted">
<column id="60" parent="10" name="isDeleted">
<Position>8</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="62" parent="10" name="sqlite_autoindex_labels_1">
<index id="61" parent="10" name="sqlite_autoindex_labels_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>labelId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="63" parent="10" name="IDX_labels_noteId">
<index id="62" parent="10" name="IDX_labels_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="64" parent="10" name="IDX_labels_name_value">
<index id="63" parent="10" name="IDX_labels_name_value">
<ColNames>name
value</ColNames>
<ColumnCollations>
</ColumnCollations>
<ColumnCollations></ColumnCollations>
</index>
<key id="65" parent="10">
<key id="64" parent="10">
<ColNames>labelId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_labels_1</UnderlyingIndexName>
</key>
<column id="66" parent="11" name="noteImageId">
<column id="65" parent="11" name="noteImageId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="67" parent="11" name="noteId">
<column id="66" parent="11" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="68" parent="11" name="imageId">
<column id="67" parent="11" name="imageId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="69" parent="11" name="isDeleted">
<column id="68" parent="11" name="isDeleted">
<Position>4</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="70" parent="11" name="dateModified">
<column id="69" parent="11" name="dateModified">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="71" parent="11" name="dateCreated">
<column id="70" parent="11" name="dateCreated">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="72" parent="11" name="sqlite_autoindex_note_images_1">
<index id="71" parent="11" name="sqlite_autoindex_note_images_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteImageId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="73" parent="11" name="IDX_note_images_noteId_imageId">
<index id="72" parent="11" name="IDX_note_images_noteId_imageId">
<ColNames>noteId
imageId</ColNames>
<ColumnCollations>
</ColumnCollations>
<ColumnCollations></ColumnCollations>
</index>
<index id="74" parent="11" name="IDX_note_images_noteId">
<index id="73" parent="11" name="IDX_note_images_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="75" parent="11" name="IDX_note_images_imageId">
<index id="74" parent="11" name="IDX_note_images_imageId">
<ColNames>imageId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="76" parent="11">
<key id="75" parent="11">
<ColNames>noteImageId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_images_1</UnderlyingIndexName>
</key>
<column id="77" parent="12" name="noteRevisionId">
<column id="76" parent="12" name="noteRevisionId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="78" parent="12" name="noteId">
<column id="77" parent="12" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="79" parent="12" name="title">
<column id="78" parent="12" name="title">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="80" parent="12" name="content">
<column id="79" parent="12" name="content">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="81" parent="12" name="isProtected">
<column id="80" parent="12" name="isProtected">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="82" parent="12" name="dateModifiedFrom">
<column id="81" parent="12" name="dateModifiedFrom">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="83" parent="12" name="dateModifiedTo">
<column id="82" parent="12" name="dateModifiedTo">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="84" parent="12" name="sqlite_autoindex_note_revisions_1">
<column id="83" parent="12" name="type">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="84" parent="12" name="mime">
<Position>9</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<index id="85" parent="12" name="sqlite_autoindex_note_revisions_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="85" parent="12" name="IDX_note_revisions_noteId">
<index id="86" parent="12" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="86" parent="12" name="IDX_note_revisions_dateModifiedFrom">
<index id="87" parent="12" name="IDX_note_revisions_dateModifiedFrom">
<ColNames>dateModifiedFrom</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="87" parent="12" name="IDX_note_revisions_dateModifiedTo">
<index id="88" parent="12" name="IDX_note_revisions_dateModifiedTo">
<ColNames>dateModifiedTo</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="88" parent="12">
<key id="89" parent="12">
<ColNames>noteRevisionId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
</key>
<column id="89" parent="13" name="noteId">
<column id="90" parent="13" name="noteId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="90" parent="13" name="title">
<column id="91" parent="13" name="title">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="91" parent="13" name="content">
<column id="92" parent="13" name="content">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="92" parent="13" name="isProtected">
<column id="93" parent="13" name="isProtected">
<Position>4</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="93" parent="13" name="isDeleted">
<column id="94" parent="13" name="isDeleted">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="94" parent="13" name="dateCreated">
<column id="95" parent="13" name="dateCreated">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="95" parent="13" name="dateModified">
<column id="96" parent="13" name="dateModified">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="96" parent="13" name="type">
<column id="97" parent="13" name="type">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;text&apos;</DefaultExpression>
</column>
<column id="97" parent="13" name="mime">
<column id="98" parent="13" name="mime">
<Position>9</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;text/html&apos;</DefaultExpression>
</column>
<index id="98" parent="13" name="sqlite_autoindex_notes_1">
<index id="99" parent="13" name="sqlite_autoindex_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="99" parent="13" name="IDX_notes_isDeleted">
<index id="100" parent="13" name="IDX_notes_isDeleted">
<ColNames>isDeleted</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="100" parent="13">
<key id="101" parent="13">
<ColNames>noteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
</key>
<column id="101" parent="14" name="name">
<column id="102" parent="14" name="name">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="102" parent="14" name="value">
<column id="103" parent="14" name="value">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="103" parent="14" name="dateModified">
<column id="104" parent="14" name="dateModified">
<Position>3</Position>
<DataType>INT|0s</DataType>
</column>
<column id="104" parent="14" name="isSynced">
<column id="105" parent="14" name="isSynced">
<Position>4</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<index id="105" parent="14" name="sqlite_autoindex_options_1">
<index id="106" parent="14" name="sqlite_autoindex_options_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>name</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="106" parent="14">
<key id="107" parent="14">
<ColNames>name</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
</key>
<column id="107" parent="15" name="branchId">
<column id="108" parent="15" name="branchId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="108" parent="15" name="notePath">
<column id="109" parent="15" name="notePath">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="109" parent="15" name="dateAccessed">
<column id="110" parent="15" name="dateAccessed">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="110" parent="15" name="isDeleted">
<column id="111" parent="15" name="isDeleted">
<Position>4</Position>
<DataType>INT|0s</DataType>
</column>
<index id="111" parent="15" name="sqlite_autoindex_recent_notes_1">
<index id="112" parent="15" name="sqlite_autoindex_recent_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>branchId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="112" parent="15">
<key id="113" parent="15">
<ColNames>branchId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
</key>
<column id="113" parent="16" name="sourceId">
<column id="114" parent="16" name="sourceId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="114" parent="16" name="dateCreated">
<column id="115" parent="16" name="dateCreated">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="115" parent="16" name="sqlite_autoindex_source_ids_1">
<index id="116" parent="16" name="sqlite_autoindex_source_ids_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>sourceId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="116" parent="16">
<key id="117" parent="16">
<ColNames>sourceId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
</key>
<column id="117" parent="17" name="type">
<column id="118" parent="17" name="type">
<Position>1</Position>
<DataType>text|0s</DataType>
</column>
<column id="118" parent="17" name="name">
<column id="119" parent="17" name="name">
<Position>2</Position>
<DataType>text|0s</DataType>
</column>
<column id="119" parent="17" name="tbl_name">
<column id="120" parent="17" name="tbl_name">
<Position>3</Position>
<DataType>text|0s</DataType>
</column>
<column id="120" parent="17" name="rootpage">
<column id="121" parent="17" name="rootpage">
<Position>4</Position>
<DataType>integer|0s</DataType>
</column>
<column id="121" parent="17" name="sql">
<column id="122" parent="17" name="sql">
<Position>5</Position>
<DataType>text|0s</DataType>
</column>
<column id="122" parent="18" name="name">
<column id="123" parent="18" name="name">
<Position>1</Position>
</column>
<column id="123" parent="18" name="seq">
<column id="124" parent="18" name="seq">
<Position>2</Position>
</column>
<column id="124" parent="19" name="id">
<column id="125" parent="19" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<SequenceIdentity>1</SequenceIdentity>
</column>
<column id="125" parent="19" name="entityName">
<column id="126" parent="19" name="entityName">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="126" parent="19" name="entityId">
<column id="127" parent="19" name="entityId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="127" parent="19" name="sourceId">
<column id="128" parent="19" name="sourceId">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="128" parent="19" name="syncDate">
<column id="129" parent="19" name="syncDate">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="129" parent="19" name="IDX_sync_entityName_entityId">
<index id="130" parent="19" name="IDX_sync_entityName_entityId">
<ColNames>entityName
entityId</ColNames>
<ColumnCollations>
</ColumnCollations>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="130" parent="19" name="IDX_sync_syncDate">
<index id="131" parent="19" name="IDX_sync_syncDate">
<ColNames>syncDate</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="131" parent="19">
<key id="132" parent="19">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>

View File

@@ -0,0 +1,34 @@
CREATE TABLE event_logc027
(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
noteId TEXT,
comment TEXT,
dateAdded TEXT NOT NULL
);
INSERT INTO event_logc027(id, noteId, comment, dateAdded) SELECT id, noteId, comment, dateAdded FROM event_log;
DROP TABLE event_log;
ALTER TABLE event_logc027 RENAME TO event_log;
CREATE TABLE IF NOT EXISTS "notes_mig" (
`noteId` TEXT NOT NULL,
`title` TEXT NOT NULL DEFAULT "unnamed",
`content` TEXT NOT NULL DEFAULT "",
`isProtected` INT NOT NULL DEFAULT 0,
`isDeleted` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
type TEXT NOT NULL DEFAULT 'text',
mime TEXT NOT NULL DEFAULT 'text/html',
PRIMARY KEY(`noteId`)
);
INSERT INTO notes_mig (noteId, title, content, isProtected, isDeleted, dateCreated, dateModified, type, mime)
SELECT noteId, title, content, isProtected, isDeleted, dateCreated, dateModified, type, mime FROM notes;
DROP TABLE notes;
ALTER TABLE notes_mig RENAME TO notes;
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (
`isDeleted`
);

View File

@@ -21,28 +21,6 @@ CREATE TABLE IF NOT EXISTS "source_ids" (
`dateCreated` TEXT NOT NULL,
PRIMARY KEY(`sourceId`)
);
CREATE TABLE IF NOT EXISTS "notes" (
`noteId` TEXT NOT NULL,
`title` TEXT,
`content` TEXT,
`isProtected` INT NOT NULL DEFAULT 0,
`isDeleted` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
type TEXT NOT NULL DEFAULT 'text',
mime TEXT NOT NULL DEFAULT 'text/html',
PRIMARY KEY(`noteId`)
);
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (
`isDeleted`
);
CREATE TABLE IF NOT EXISTS "event_log" (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`noteId` TEXT,
`comment` TEXT,
`dateAdded` TEXT NOT NULL,
FOREIGN KEY(noteId) REFERENCES notes(noteId)
);
CREATE TABLE IF NOT EXISTS "note_revisions" (
`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
`noteId` TEXT NOT NULL,
@@ -51,7 +29,7 @@ CREATE TABLE IF NOT EXISTS "note_revisions" (
`isProtected` INT NOT NULL DEFAULT 0,
`dateModifiedFrom` TEXT NOT NULL,
`dateModifiedTo` TEXT NOT NULL
);
, type TEXT DEFAULT '' NOT NULL, mime TEXT DEFAULT '' NOT NULL);
CREATE INDEX `IDX_note_revisions_noteId` ON `note_revisions` (
`noteId`
);
@@ -130,3 +108,25 @@ CREATE INDEX IDX_labels_name_value
on labels (name, value);
CREATE INDEX IDX_labels_noteId
on labels (noteId);
CREATE TABLE IF NOT EXISTS "event_log"
(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
noteId TEXT,
comment TEXT,
dateAdded TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS "notes" (
`noteId` TEXT NOT NULL,
`title` TEXT NOT NULL DEFAULT "unnamed",
`content` TEXT NOT NULL DEFAULT "",
`isProtected` INT NOT NULL DEFAULT 0,
`isDeleted` INT NOT NULL DEFAULT 0,
`dateCreated` TEXT NOT NULL,
`dateModified` TEXT NOT NULL,
type TEXT NOT NULL DEFAULT 'text',
mime TEXT NOT NULL DEFAULT 'text/html',
PRIMARY KEY(`noteId`)
);
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (
`isDeleted`
);

View File

@@ -1,7 +1,7 @@
{
"name": "trilium",
"description": "Trilium Notes",
"version": "0.11.0-beta",
"version": "0.12.0",
"license": "AGPL-3.0-only",
"main": "electron.js",
"repository": {

View File

@@ -17,17 +17,16 @@ class Note extends Entity {
protected_session.decryptNote(this);
}
if (this.isJson()) {
this.jsonContent = JSON.parse(this.content);
}
this.setContent(this.content);
}
setContent(content) {
this.content = content;
if (this.isJson()) {
try {
this.jsonContent = JSON.parse(this.content);
}
catch(e) {}
}
isJson() {
@@ -142,7 +141,7 @@ class Note extends Entity {
beforeSaving() {
super.beforeSaving();
if (this.isJson()) {
if (this.isJson() && this.jsonContent) {
this.content = JSON.stringify(this.jsonContent, null, '\t');
}

View File

@@ -45,8 +45,8 @@ async function showDialog() {
$clonePrefix.val('');
$linkTitle.val('');
function setDefaultLinkTitle(noteId) {
const noteTitle = treeUtils.getNoteTitle(noteId);
async function setDefaultLinkTitle(noteId) {
const noteTitle = await treeUtils.getNoteTitle(noteId);
$linkTitle.val(noteTitle);
}
@@ -54,7 +54,7 @@ async function showDialog() {
$autoComplete.autocomplete({
source: await autocompleteService.getAutocompleteItems(),
minLength: 0,
change: () => {
change: async () => {
const val = $autoComplete.val();
const notePath = linkService.getNodePathFromLabel(val);
if (!notePath) {
@@ -64,16 +64,16 @@ async function showDialog() {
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
if (noteId) {
setDefaultLinkTitle(noteId);
await setDefaultLinkTitle(noteId);
}
},
// this is called when user goes through autocomplete list with keyboard
// at this point the item isn't selected yet so we use supplied ui.item to see WHERE the cursor is
focus: (event, ui) => {
focus: async (event, ui) => {
const notePath = linkService.getNodePathFromLabel(ui.item.value);
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
setDefaultLinkTitle(noteId);
await setDefaultLinkTitle(noteId);
}
});
}

View File

@@ -6,8 +6,11 @@ class NoteFull extends NoteShort {
this.content = row.content;
if (this.isJson()) {
this.jsonContent = JSON.parse(this.content);
if (this.content !== "" && this.isJson()) {
try {
this.jsonContent = JSON.parse(this.content);
}
catch(e) {}
}
}
}

View File

@@ -24,6 +24,10 @@ class NoteShort {
}
async getChildBranches() {
if (!this.treeCache.children[this.noteId]) {
return [];
}
const branches = [];
for (const child of this.treeCache.children[this.noteId]) {

View File

@@ -76,9 +76,11 @@ function goToLink(e) {
function addLinkToEditor(linkTitle, linkHref) {
const editor = noteDetailText.getEditor();
const doc = editor.document;
doc.enqueueChanges(() => editor.data.insertLink(linkTitle, linkHref), doc.selection);
editor.model.change( writer => {
const insertPosition = editor.model.document.selection.getFirstPosition();
writer.insertText(linkTitle, { linkHref: linkHref }, insertPosition);
});
}
function addTextToEditor(text) {

View File

@@ -176,12 +176,18 @@ async function loadNoteDetail(noteId) {
// after loading new note make sure editor is scrolled to the top
$noteDetailWrapper.scrollTop(0);
await loadLabelList();
const labels = await loadLabelList();
await showChildrenOverview();
const hideChildrenOverview = labels.some(label => label.name === 'hideChildrenOverview');
await showChildrenOverview(hideChildrenOverview);
}
async function showChildrenOverview() {
async function showChildrenOverview(hideChildrenOverview) {
if (hideChildrenOverview) {
$childrenOverview.hide();
return;
}
const note = getCurrentNote();
$childrenOverview.empty();
@@ -197,6 +203,8 @@ async function showChildrenOverview() {
const childEl = $('<div class="child-overview">').html(link);
$childrenOverview.append(childEl);
}
$childrenOverview.show();
}
async function loadLabelList() {
@@ -216,6 +224,8 @@ async function loadLabelList() {
else {
$labelList.hide();
}
return labels;
}
async function loadNote(noteId) {

View File

@@ -31,7 +31,8 @@ async function show() {
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false},
lint: true,
gutters: ["CodeMirror-lint-markers"],
lineNumbers: true
lineNumbers: true,
tabindex: 2 // so that tab from title will lead to code editor focus
});
codeEditor.on('change', noteDetailService.noteChanged);

View File

@@ -11,11 +11,10 @@ async function show() {
textEditor = await BalloonEditor.create($noteDetailText[0], {});
textEditor.document.on('change', noteDetailService.noteChanged);
textEditor.model.document.on('change', noteDetailService.noteChanged);
}
// temporary workaround for https://github.com/ckeditor/ckeditor5-enter/issues/49
textEditor.setData(noteDetailService.getCurrentNote().content || "<p></p>");
textEditor.setData(noteDetailService.getCurrentNote().content);
$noteDetailText.show();
}

View File

@@ -541,9 +541,9 @@ $(window).bind('hashchange', function() {
});
utils.bindShortcut('alt+c', () => collapseTree()); // don't use shortened form since collapseTree() accepts argument
$collapseTreeButton.click(() => collapseTree());
$createTopLevelNoteButton.click(createNewTopLevelNote);
$collapseTreeButton.click(collapseTree);
$scrollToCurrentNoteButton.click(scrollToCurrentNote);
export default {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -12,9 +12,40 @@
/*------------------------------------------------------------------------------
* Helpers
*----------------------------------------------------------------------------*/
.ui-helper-hidden {
.fancytree-helper-hidden {
display: none;
}
.fancytree-helper-indeterminate-cb {
color: #777;
}
.fancytree-helper-disabled {
color: #c0c0c0;
}
/* Helper to allow spinning loader icon with glyph-, ligature-, and SVG-icons. */
.fancytree-helper-spin {
-webkit-animation: spin 1000ms infinite linear;
animation: spin 1000ms infinite linear;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
/*------------------------------------------------------------------------------
* Container and UL / LI
*----------------------------------------------------------------------------*/
@@ -338,6 +369,16 @@ span.fancytree-node.fancytree-error span.fancytree-title {
/*------------------------------------------------------------------------------
* Drag'n'drop support
*----------------------------------------------------------------------------*/
/* ext-dnd5: */
span.fancytree-childcounter {
color: #fff;
background: #337ab7;
border: 1px solid gray;
border-radius: 10px;
padding: 2px;
text-align: center;
}
/* ext-dnd: */
div.fancytree-drag-helper span.fancytree-childcounter,
div.fancytree-drag-helper span.fancytree-dnd-modifier {
display: inline-block;
@@ -402,8 +443,7 @@ span.fancytree-drag-source.fancytree-drag-remove {
.fancytree-container.fancytree-rtl span.fancytree-connector,
.fancytree-container.fancytree-rtl span.fancytree-expander,
.fancytree-container.fancytree-rtl span.fancytree-icon,
.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,
.fancytree-container.fancytree-rtl #fancytree-drop-marker {
.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img {
background-image: url("../skin-win8/icons-rtl.gif");
}
.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,
@@ -425,6 +465,9 @@ ul.fancytree-container.fancytree-rtl li.fancytree-lastsib,
ul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {
background-image: none;
}
#fancytree-drop-marker.fancytree-rtl {
background-image: url("../skin-win8/icons-rtl.gif");
}
/*------------------------------------------------------------------------------
* 'table' extension
*----------------------------------------------------------------------------*/
@@ -482,7 +525,7 @@ table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:h
* 'filter' extension
*----------------------------------------------------------------------------*/
.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {
color: silver;
color: #c0c0c0;
font-weight: lighter;
}
.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,
@@ -501,7 +544,7 @@ table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:h
}
.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,
.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {
color: silver;
color: #c0c0c0;
font-weight: lighter;
}
.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,

File diff suppressed because one or more lines are too long

View File

@@ -4,18 +4,12 @@
display: grid;
grid-template-areas: "header header"
"tree-actions title"
"search note-detail"
"tree note-detail"
"parent-list note-detail"
"parent-list label-list";
"left-pane title"
"left-pane note-detail";
grid-template-columns: 2fr 5fr;
grid-template-rows: auto
auto
auto
1fr
auto
auto;
1fr;
justify-content: center;
grid-gap: 10px;
@@ -28,6 +22,23 @@
align-items: center;
}
#note-detail-wrapper {
position: relative;
overflow: hidden;
grid-area: note-detail;
padding-left: 10px;
padding-top: 10px;
display: flex;
flex-direction: column;
}
#note-detail-component-wrapper {
flex-grow: 1;
position: relative;
overflow: auto;
flex-basis: content;
}
.note-detail-component {
display: none;
}
@@ -36,7 +47,7 @@
border: 0 !important;
box-shadow: none !important;
/* This is because with empty content height of editor is 0 and it's impossible to click into it */
min-height: 400px;
min-height: 200px;
overflow: auto;
}
@@ -249,7 +260,7 @@ div.ui-tooltip {
}
#note-detail-code {
height: 100%;
min-height: 200px;
}
.CodeMirror {
@@ -274,7 +285,6 @@ div.ui-tooltip {
.cm-matchhighlight {background-color: #eeeeee}
#label-list {
grid-area: label-list;
color: #777777;
border-top: 1px solid #eee;
padding: 5px; display: none;
@@ -291,18 +301,33 @@ div.ui-tooltip {
}
#children-overview {
padding-top: 20px;
flex-grow: 1000;
flex-shrink: 1000;
flex-basis: 0px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
height: 100px;
overflow: auto;
}
.child-overview {
font-weight: bold;
font-size: large;
padding: 10px;
border: 1px solid black;
background: #f4f4f4;
width: 150px;
height: 95px;
height: 90px;
line-height: 2em;
margin-right: 20px;
margin-bottom: 20px;
border-radius: 15px;
overflow: hidden;
text-align: center;
margin-top: 15px;
text-overflow: ellipsis;
word-wrap: break-word;
}
.child-overview a {
color: #444;
}

View File

@@ -68,7 +68,7 @@ async function update(req) {
const entities = req.body.entities;
for (const {sync, entity} of entities) {
await syncUpdateService.updateEntity(sync.entityName, entity, sourceId);
await syncUpdateService.updateEntity(sync, entity, sourceId);
}
}

View File

@@ -3,7 +3,7 @@
const build = require('./build');
const packageJson = require('../../package');
const APP_DB_VERSION = 87;
const APP_DB_VERSION = 88;
module.exports = {
appVersion: packageJson.version,

View File

@@ -1 +1 @@
module.exports = { buildDate:"2018-04-09T22:38:37-04:00", buildRevision: "d8924c536b70415a9e35299f62bcf978320d8fee" };
module.exports = { buildDate:"2018-04-14T08:28:50-04:00", buildRevision: "d57057ba28d2d93ffaeed15900116836fc791968" };

View File

@@ -197,16 +197,6 @@ async function runAllChecks() {
AND images.isDeleted = 1`,
"Note image is not deleted while image is deleted for noteImageId", errorList);
await runCheck(`
SELECT
noteId
FROM
notes
WHERE
isDeleted = 0
AND (title IS NULL OR content IS NULL)`,
"Note has null title or text", errorList);
await runCheck(`
SELECT
noteId

View File

@@ -11,7 +11,8 @@ const BUILTIN_LABELS = [
'run',
'manualTransactionHandling',
'disableInclusion',
'appCss'
'appCss',
'hideChildrenOverview'
];
async function getNotesWithLabel(name, value) {

View File

@@ -149,11 +149,13 @@ async function transactional(func) {
resolve();
}
catch (e) {
log.error("Error executing transaction, executing rollback. Inner exception: " + e.stack + error.stack);
if (transactionActive) {
log.error("Error executing transaction, executing rollback. Inner exception: " + e.stack + error.stack);
await rollback();
await rollback();
transactionActive = false;
transactionActive = false;
}
reject(e);
}

View File

@@ -101,7 +101,7 @@ async function pullSync(syncContext) {
log.info(`Skipping pull #${sync.id} ${sync.entityName} ${sync.entityId} because ${sync.sourceId} is a local source id.`);
}
else {
await syncUpdateService.updateEntity(sync.entityName, entity, syncContext.sourceId);
await syncUpdateService.updateEntity(sync, entity, syncContext.sourceId);
}
await setLastSyncedPull(sync.id);

View File

@@ -3,7 +3,9 @@ const log = require('./log');
const eventLogService = require('./event_log');
const syncTableService = require('./sync_table');
async function updateEntity(entityName, entity, sourceId) {
async function updateEntity(sync, entity, sourceId) {
const {entityName} = sync;
if (entityName === 'notes') {
await updateNote(entity, sourceId);
}
@@ -14,7 +16,7 @@ async function updateEntity(entityName, entity, sourceId) {
await updateNoteRevision(entity, sourceId);
}
else if (entityName === 'note_reordering') {
await updateNoteReordering(entity, sourceId);
await updateNoteReordering(sync.entityId, entity, sourceId);
}
else if (entityName === 'options') {
await updateOptions(entity, sourceId);
@@ -35,7 +37,7 @@ async function updateEntity(entityName, entity, sourceId) {
await updateApiToken(entity, sourceId);
}
else {
throw new Error(`Unrecognized entity type ${entityName}`);
throw new Error(`Unrecognized entity type ${sync}`);
}
}
@@ -94,13 +96,13 @@ async function updateNoteRevision(entity, sourceId) {
});
}
async function updateNoteReordering(entity, sourceId) {
async function updateNoteReordering(entityId, entity, sourceId) {
await sql.transactional(async () => {
Object.keys(entity.ordering).forEach(async key => {
await sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [entity.ordering[key], key]);
Object.keys(entity).forEach(async key => {
await sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [entity[key], key]);
});
await syncTableService.addNoteReorderingSync(entity.parentNoteId, sourceId);
await syncTableService.addNoteReorderingSync(entityId, sourceId);
});
}

View File

@@ -38,7 +38,7 @@
</div>
</div>
<div class="hide-toggle" style="grid-area: tree-actions;">
<div style="grid-area: left-pane; display: flex; flex-direction: column;" class="hide-toggle">
<div style="display: flex; justify-content: space-around; padding: 10px 0 10px 0; margin: 0 20px 0 20px; border: 1px solid #ccc;">
<a id="create-top-level-note-button" title="Create new top level note" class="icon-action"
style="background: url('/images/icons/file-plus.png')"></a>
@@ -54,28 +54,28 @@
</div>
<input type="file" id="import-upload" style="display: none" />
</div>
<div id="search-box" class="hide-toggle" style="grid-area: search; display: none; padding: 10px; margin-top: 10px;">
<div style="display: flex; align-items: center;">
<input name="search-text" placeholder="Search text, labels" style="flex-grow: 100; margin-left: 5px; margin-right: 5px;" autocomplete="off">
<button id="do-search-button" class="btn btn-primary btn-sm" title="Search">Search</button>
<div id="search-box" style="display: none; padding: 10px; margin-top: 10px;">
<div style="display: flex; align-items: center;">
<input name="search-text" placeholder="Search text, labels" style="flex-grow: 100; margin-left: 5px; margin-right: 5px;" autocomplete="off">
<button id="do-search-button" class="btn btn-primary btn-sm" title="Search">Search</button>
</div>
<div style="display: flex; align-items: center; justify-content: space-evenly; margin-top: 10px;">
<button id="reset-search-button" class="btn btn-sm" title="Reset search">Reset search</button>
<button id="save-search-button" class="btn btn-sm" title="Save search">Save search</button>
</div>
</div>
<div style="display: flex; align-items: center; justify-content: space-evenly; margin-top: 10px;">
<button id="reset-search-button" class="btn btn-sm" title="Reset search">Reset search</button>
<button id="save-search-button" class="btn btn-sm" title="Save search">Save search</button>
<div id="tree" class="hide-toggle" style="overflow: auto; flex-grow: 100; flex-shrink: 100; margin-top: 10px;">
</div>
</div>
<div id="tree" class="hide-toggle" style="grid-area: tree; overflow: auto;">
</div>
<div id="parent-list">
<p><strong>Note locations:</strong></p>
<div id="parent-list" class="hide-toggle">
<p><strong>Note locations:</strong></p>
<ul id="parent-list-inner"></ul>
<ul id="parent-list-inner"></ul>
</div>
</div>
<div class="hide-toggle" style="grid-area: title;">
@@ -132,9 +132,9 @@
</div>
</div>
<div style="position: relative; overflow: hidden; grid-area: note-detail; padding-left: 10px; padding-top: 10px; display: flex; flex-direction: column;" id="note-detail-wrapper">
<div style="flex-grow: 1; position: relative; overflow: auto; flex-basis: content;">
<div id="note-detail-text" style="height: 100%;" class="note-detail-component"></div>
<div id="note-detail-wrapper">
<div id="note-detail-component-wrapper">
<div id="note-detail-text" class="note-detail-component" tabindex="2"></div>
<div id="note-detail-search" class="note-detail-component">
<div style="display: flex; align-items: center;">
@@ -205,15 +205,14 @@
<input type="file" id="file-upload" style="display: none" />
</div>
<div id="children-overview" style="flex-grow: 1000; flex-shrink: 1000; flex-basis: 1px; height: 100px; overflow: hidden; display: flex; flex-wrap: wrap">
<div id="children-overview"></div>
<div id="label-list">
<button class="btn btn-sm show-labels-button">Labels:</button>
<span id="label-list-inner"></span>
</div>
</div>
<div id="label-list">
<button class="btn btn-sm show-labels-button">Labels:</button>
<span id="label-list-inner"></span>
</div>
</div>
<div id="recent-notes-dialog" title="Recent notes" style="display: none;">