mirror of https://github.com/laurent22/joplin.git
fix
parent
9047605637
commit
a43d4593c5
|
@ -351,7 +351,7 @@ export default class JoplinDatabase extends Database {
|
|||
// must be set in the synchronizer too.
|
||||
|
||||
// Note: v16 and v17 don't do anything. They were used to debug an issue.
|
||||
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41];
|
||||
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42];
|
||||
|
||||
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
|
||||
|
||||
|
@ -910,6 +910,10 @@ export default class JoplinDatabase extends Database {
|
|||
queries.push('ALTER TABLE `folders` ADD COLUMN icon TEXT NOT NULL DEFAULT ""');
|
||||
}
|
||||
|
||||
if (targetVersion == 42) {
|
||||
queries.push('ALTER TABLE `notes` ADD COLUMN is_shared_recursive INT NOT NULL DEFAULT 0');
|
||||
}
|
||||
|
||||
const updateVersionQuery = { sql: 'UPDATE version SET version = ?', params: [targetVersion] };
|
||||
|
||||
queries.push(updateVersionQuery);
|
||||
|
|
|
@ -348,24 +348,55 @@ export default class Folder extends BaseItem {
|
|||
}
|
||||
|
||||
public static async updateNoteShareIds() {
|
||||
// Find all the notes where the share_id is not the same as the
|
||||
// parent share_id because we only need to update those.
|
||||
const rows = await this.db().selectAll(`
|
||||
SELECT notes.id, folders.share_id, notes.parent_id
|
||||
FROM notes
|
||||
LEFT JOIN folders ON notes.parent_id = folders.id
|
||||
WHERE notes.share_id != folders.share_id
|
||||
`);
|
||||
{
|
||||
// Find all the notes where the share_id is not the same as the
|
||||
// parent share_id because we only need to update those.
|
||||
const rows = await this.db().selectAll(`
|
||||
SELECT notes.id, folders.share_id, notes.parent_id
|
||||
FROM notes
|
||||
LEFT JOIN folders ON notes.parent_id = folders.id
|
||||
WHERE notes.share_id != folders.share_id
|
||||
`);
|
||||
|
||||
logger.debug('updateNoteShareIds: notes to update:', rows.length);
|
||||
logger.debug('updateNoteShareIds: notes to update:', rows.length);
|
||||
|
||||
for (const row of rows) {
|
||||
await Note.save({
|
||||
id: row.id,
|
||||
share_id: row.share_id || '',
|
||||
parent_id: row.parent_id,
|
||||
updated_time: Date.now(),
|
||||
}, { autoTimestamp: false });
|
||||
for (const row of rows) {
|
||||
await Note.save({
|
||||
id: row.id,
|
||||
share_id: row.share_id || '',
|
||||
parent_id: row.parent_id,
|
||||
updated_time: Date.now(),
|
||||
}, { autoTimestamp: false });
|
||||
}
|
||||
}
|
||||
|
||||
// Also applies recursively published notes
|
||||
{
|
||||
// Find all the notes where the share_id is not the same as the
|
||||
// parent share_id because we only need to update those.
|
||||
const rows = await this.db().selectAll(`
|
||||
SELECT notes.id, folders.share_id, notes.parent_id, notes.body
|
||||
FROM notes
|
||||
WHERE notes.is_shared = 1 AND notes.is_shared_recursive = 1
|
||||
`);
|
||||
|
||||
logger.debug('updateNoteShareIds: notes recursively published:', rows.length);
|
||||
|
||||
// for (const row of rows) {
|
||||
|
||||
// // await Note.save({
|
||||
// // id: row.id,
|
||||
// // share_id: row.share_id || '',
|
||||
// // parent_id: row.parent_id,
|
||||
// // updated_time: Date.now(),
|
||||
// // }, { autoTimestamp: false });
|
||||
// }
|
||||
|
||||
// TODO: should start from root notes - don't set is_recursive on children?
|
||||
// TODO: when a child note is moved out of parent, how to know that is_shared should be cleared? - need share_root prop?
|
||||
// or based on Share API objects? (passed to this function?)
|
||||
// TODO: also unshare notes that have been unlinked (is_shared != parent.is_shared)
|
||||
// TODO: avoid infinite loops
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,7 +656,7 @@ export default class Folder extends BaseItem {
|
|||
rootFolders.push(folder);
|
||||
} else {
|
||||
if (!idToFolders[folder.parent_id]) {
|
||||
// It means the notebook is refering a folder that doesn't exist. In theory it shouldn't happen
|
||||
// It means the notebook is referring a folder that doesn't exist. In theory it shouldn't happen
|
||||
// but sometimes does - https://github.com/laurent22/joplin/issues/1068#issuecomment-450594708
|
||||
rootFolders.push(folder);
|
||||
} else {
|
||||
|
|
|
@ -52,6 +52,10 @@ export const defaultFolderIcon = () => {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// AUTO-GENERATED BY packages/tools/generate-database-types.js
|
||||
|
||||
/*
|
||||
|
@ -59,225 +63,226 @@ export const defaultFolderIcon = () => {
|
|||
* Rerun sql-ts to regenerate this file.
|
||||
*/
|
||||
export interface AlarmEntity {
|
||||
"id"?: number | null
|
||||
"note_id"?: string
|
||||
"trigger_time"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'note_id'?: string;
|
||||
'trigger_time'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface DeletedItemEntity {
|
||||
"id"?: number | null
|
||||
"item_type"?: number
|
||||
"item_id"?: string
|
||||
"deleted_time"?: number
|
||||
"sync_target"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'item_type'?: number;
|
||||
'item_id'?: string;
|
||||
'deleted_time'?: number;
|
||||
'sync_target'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface FolderEntity {
|
||||
"id"?: string | null
|
||||
"title"?: string
|
||||
"created_time"?: number
|
||||
"updated_time"?: number
|
||||
"user_created_time"?: number
|
||||
"user_updated_time"?: number
|
||||
"encryption_cipher_text"?: string
|
||||
"encryption_applied"?: number
|
||||
"parent_id"?: string
|
||||
"is_shared"?: number
|
||||
"share_id"?: string
|
||||
"master_key_id"?: string
|
||||
"icon"?: string
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'title'?: string;
|
||||
'created_time'?: number;
|
||||
'updated_time'?: number;
|
||||
'user_created_time'?: number;
|
||||
'user_updated_time'?: number;
|
||||
'encryption_cipher_text'?: string;
|
||||
'encryption_applied'?: number;
|
||||
'parent_id'?: string;
|
||||
'is_shared'?: number;
|
||||
'share_id'?: string;
|
||||
'master_key_id'?: string;
|
||||
'icon'?: string;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface ItemChangeEntity {
|
||||
"id"?: number | null
|
||||
"item_type"?: number
|
||||
"item_id"?: string
|
||||
"type"?: number
|
||||
"created_time"?: number
|
||||
"source"?: number
|
||||
"before_change_item"?: string
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'item_type'?: number;
|
||||
'item_id'?: string;
|
||||
'type'?: number;
|
||||
'created_time'?: number;
|
||||
'source'?: number;
|
||||
'before_change_item'?: string;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface KeyValueEntity {
|
||||
"id"?: number | null
|
||||
"key"?: string
|
||||
"value"?: string
|
||||
"type"?: number
|
||||
"updated_time"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'key'?: string;
|
||||
'value'?: string;
|
||||
'type'?: number;
|
||||
'updated_time'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface MigrationEntity {
|
||||
"id"?: number | null
|
||||
"number"?: number
|
||||
"updated_time"?: number
|
||||
"created_time"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'number'?: number;
|
||||
'updated_time'?: number;
|
||||
'created_time'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface NoteResourceEntity {
|
||||
"id"?: number | null
|
||||
"note_id"?: string
|
||||
"resource_id"?: string
|
||||
"is_associated"?: number
|
||||
"last_seen_time"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'note_id'?: string;
|
||||
'resource_id'?: string;
|
||||
'is_associated'?: number;
|
||||
'last_seen_time'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface NoteTagEntity {
|
||||
"id"?: string | null
|
||||
"note_id"?: string
|
||||
"tag_id"?: string
|
||||
"created_time"?: number
|
||||
"updated_time"?: number
|
||||
"user_created_time"?: number
|
||||
"user_updated_time"?: number
|
||||
"encryption_cipher_text"?: string
|
||||
"encryption_applied"?: number
|
||||
"is_shared"?: number
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'note_id'?: string;
|
||||
'tag_id'?: string;
|
||||
'created_time'?: number;
|
||||
'updated_time'?: number;
|
||||
'user_created_time'?: number;
|
||||
'user_updated_time'?: number;
|
||||
'encryption_cipher_text'?: string;
|
||||
'encryption_applied'?: number;
|
||||
'is_shared'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface NoteEntity {
|
||||
"id"?: string | null
|
||||
"parent_id"?: string
|
||||
"title"?: string
|
||||
"body"?: string
|
||||
"created_time"?: number
|
||||
"updated_time"?: number
|
||||
"is_conflict"?: number
|
||||
"latitude"?: number
|
||||
"longitude"?: number
|
||||
"altitude"?: number
|
||||
"author"?: string
|
||||
"source_url"?: string
|
||||
"is_todo"?: number
|
||||
"todo_due"?: number
|
||||
"todo_completed"?: number
|
||||
"source"?: string
|
||||
"source_application"?: string
|
||||
"application_data"?: string
|
||||
"order"?: number
|
||||
"user_created_time"?: number
|
||||
"user_updated_time"?: number
|
||||
"encryption_cipher_text"?: string
|
||||
"encryption_applied"?: number
|
||||
"markup_language"?: number
|
||||
"is_shared"?: number
|
||||
"share_id"?: string
|
||||
"conflict_original_id"?: string
|
||||
"master_key_id"?: string
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'parent_id'?: string;
|
||||
'title'?: string;
|
||||
'body'?: string;
|
||||
'created_time'?: number;
|
||||
'updated_time'?: number;
|
||||
'is_conflict'?: number;
|
||||
'latitude'?: number;
|
||||
'longitude'?: number;
|
||||
'altitude'?: number;
|
||||
'author'?: string;
|
||||
'source_url'?: string;
|
||||
'is_todo'?: number;
|
||||
'todo_due'?: number;
|
||||
'todo_completed'?: number;
|
||||
'source'?: string;
|
||||
'source_application'?: string;
|
||||
'application_data'?: string;
|
||||
'order'?: number;
|
||||
'user_created_time'?: number;
|
||||
'user_updated_time'?: number;
|
||||
'encryption_cipher_text'?: string;
|
||||
'encryption_applied'?: number;
|
||||
'markup_language'?: number;
|
||||
'is_shared'?: number;
|
||||
'share_id'?: string;
|
||||
'conflict_original_id'?: string;
|
||||
'master_key_id'?: string;
|
||||
'is_shared_recursive'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface NotesNormalizedEntity {
|
||||
"id"?: string
|
||||
"title"?: string
|
||||
"body"?: string
|
||||
"user_created_time"?: number
|
||||
"user_updated_time"?: number
|
||||
"is_todo"?: number
|
||||
"todo_completed"?: number
|
||||
"parent_id"?: string
|
||||
"latitude"?: number
|
||||
"longitude"?: number
|
||||
"altitude"?: number
|
||||
"source_url"?: string
|
||||
"todo_due"?: number
|
||||
"type_"?: number
|
||||
'id'?: string;
|
||||
'title'?: string;
|
||||
'body'?: string;
|
||||
'user_created_time'?: number;
|
||||
'user_updated_time'?: number;
|
||||
'is_todo'?: number;
|
||||
'todo_completed'?: number;
|
||||
'parent_id'?: string;
|
||||
'latitude'?: number;
|
||||
'longitude'?: number;
|
||||
'altitude'?: number;
|
||||
'source_url'?: string;
|
||||
'todo_due'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface ResourceLocalStateEntity {
|
||||
"id"?: number | null
|
||||
"resource_id"?: string
|
||||
"fetch_status"?: number
|
||||
"fetch_error"?: string
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'resource_id'?: string;
|
||||
'fetch_status'?: number;
|
||||
'fetch_error'?: string;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface ResourceEntity {
|
||||
"id"?: string | null
|
||||
"title"?: string
|
||||
"mime"?: string
|
||||
"filename"?: string
|
||||
"created_time"?: number
|
||||
"updated_time"?: number
|
||||
"user_created_time"?: number
|
||||
"user_updated_time"?: number
|
||||
"file_extension"?: string
|
||||
"encryption_cipher_text"?: string
|
||||
"encryption_applied"?: number
|
||||
"encryption_blob_encrypted"?: number
|
||||
"size"?: number
|
||||
"is_shared"?: number
|
||||
"share_id"?: string
|
||||
"master_key_id"?: string
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'title'?: string;
|
||||
'mime'?: string;
|
||||
'filename'?: string;
|
||||
'created_time'?: number;
|
||||
'updated_time'?: number;
|
||||
'user_created_time'?: number;
|
||||
'user_updated_time'?: number;
|
||||
'file_extension'?: string;
|
||||
'encryption_cipher_text'?: string;
|
||||
'encryption_applied'?: number;
|
||||
'encryption_blob_encrypted'?: number;
|
||||
'size'?: number;
|
||||
'is_shared'?: number;
|
||||
'share_id'?: string;
|
||||
'master_key_id'?: string;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface ResourcesToDownloadEntity {
|
||||
"id"?: number | null
|
||||
"resource_id"?: string
|
||||
"updated_time"?: number
|
||||
"created_time"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'resource_id'?: string;
|
||||
'updated_time'?: number;
|
||||
'created_time'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface RevisionEntity {
|
||||
"id"?: string | null
|
||||
"parent_id"?: string
|
||||
"item_type"?: number
|
||||
"item_id"?: string
|
||||
"item_updated_time"?: number
|
||||
"title_diff"?: string
|
||||
"body_diff"?: string
|
||||
"metadata_diff"?: string
|
||||
"encryption_cipher_text"?: string
|
||||
"encryption_applied"?: number
|
||||
"updated_time"?: number
|
||||
"created_time"?: number
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'parent_id'?: string;
|
||||
'item_type'?: number;
|
||||
'item_id'?: string;
|
||||
'item_updated_time'?: number;
|
||||
'title_diff'?: string;
|
||||
'body_diff'?: string;
|
||||
'metadata_diff'?: string;
|
||||
'encryption_cipher_text'?: string;
|
||||
'encryption_applied'?: number;
|
||||
'updated_time'?: number;
|
||||
'created_time'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface SettingEntity {
|
||||
"key"?: string | null
|
||||
"value"?: string | null
|
||||
"type_"?: number
|
||||
'key'?: string | null;
|
||||
'value'?: string | null;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface SyncItemEntity {
|
||||
"id"?: number | null
|
||||
"sync_target"?: number
|
||||
"sync_time"?: number
|
||||
"item_type"?: number
|
||||
"item_id"?: string
|
||||
"sync_disabled"?: number
|
||||
"sync_disabled_reason"?: string
|
||||
"force_sync"?: number
|
||||
"item_location"?: number
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'sync_target'?: number;
|
||||
'sync_time'?: number;
|
||||
'item_type'?: number;
|
||||
'item_id'?: string;
|
||||
'sync_disabled'?: number;
|
||||
'sync_disabled_reason'?: string;
|
||||
'force_sync'?: number;
|
||||
'item_location'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface TableFieldEntity {
|
||||
"id"?: number | null
|
||||
"table_name"?: string
|
||||
"field_name"?: string
|
||||
"field_type"?: number
|
||||
"field_default"?: string | null
|
||||
"type_"?: number
|
||||
'id'?: number | null;
|
||||
'table_name'?: string;
|
||||
'field_name'?: string;
|
||||
'field_type'?: number;
|
||||
'field_default'?: string | null;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface TagEntity {
|
||||
"id"?: string | null
|
||||
"title"?: string
|
||||
"created_time"?: number
|
||||
"updated_time"?: number
|
||||
"user_created_time"?: number
|
||||
"user_updated_time"?: number
|
||||
"encryption_cipher_text"?: string
|
||||
"encryption_applied"?: number
|
||||
"is_shared"?: number
|
||||
"parent_id"?: string
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'title'?: string;
|
||||
'created_time'?: number;
|
||||
'updated_time'?: number;
|
||||
'user_created_time'?: number;
|
||||
'user_updated_time'?: number;
|
||||
'encryption_cipher_text'?: string;
|
||||
'encryption_applied'?: number;
|
||||
'is_shared'?: number;
|
||||
'parent_id'?: string;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface TagsWithNoteCountEntity {
|
||||
"id"?: string | null
|
||||
"title"?: string | null
|
||||
"created_time"?: number | null
|
||||
"updated_time"?: number | null
|
||||
"note_count"?: any | null
|
||||
"todo_completed_count"?: any | null
|
||||
"type_"?: number
|
||||
'id'?: string | null;
|
||||
'title'?: string | null;
|
||||
'created_time'?: number | null;
|
||||
'updated_time'?: number | null;
|
||||
'note_count'?: any | null;
|
||||
'todo_completed_count'?: any | null;
|
||||
'type_'?: number;
|
||||
}
|
||||
export interface VersionEntity {
|
||||
"version"?: number
|
||||
"table_fields_version"?: number
|
||||
"type_"?: number
|
||||
'version'?: number;
|
||||
'table_fields_version'?: number;
|
||||
'type_'?: number;
|
||||
}
|
||||
|
|
|
@ -241,6 +241,7 @@ export default class ShareService {
|
|||
id: note.id,
|
||||
parent_id: note.parent_id,
|
||||
is_shared: 1,
|
||||
is_shared_recursive: recursive ? 1 : 0,
|
||||
updated_time: Date.now(),
|
||||
}, {
|
||||
autoTimestamp: false,
|
||||
|
|
|
@ -27,6 +27,7 @@ export interface StateShare {
|
|||
folder_id: string;
|
||||
note_id: string;
|
||||
master_key_id: string;
|
||||
recursive: number;
|
||||
user?: StateShareUserUser;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ export default class ShareModel extends BaseModel<Share> {
|
|||
if (object.owner_id) output.owner_id = object.owner_id;
|
||||
if (object.note_id) output.note_id = object.note_id;
|
||||
if (object.master_key_id) output.master_key_id = object.master_key_id;
|
||||
if ('recursive' in object) output.recursive = object.recursive;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue