From 98c89797a58033ff4cf0c66e36d5e6ca3f1e9182 Mon Sep 17 00:00:00 2001 From: Avinash Lingaloo Date: Thu, 14 Jan 2021 23:41:53 +0400 Subject: [PATCH] MM_30476 [v2] Section 'Post' of the server schema (#5077) * MM_30476 : Added all isolated tables from the server schema * MM_30476 : Updated 'test' script in package.json * MM_30476 : ADDED team section of the server schema * MM_30476 : ADDED section for Group from the server schema * MM_30476 : One PR for one section only * MM_30476 : One PR for one section only * MM_30476 : Rename table schemas to avoid name collision * MM_30476 : ADDED section 'Post' of the server schema * MM_30476 : Updated Post section of the server schema * MM_30476 : Apply suggestions from code review Co-authored-by: Miguel Alatzar * MM_30476 : Corrected draft wrt to suggestions * MM_30476 : Apply suggestions from code review Co-authored-by: Elias Nahum * MM_30476 : ADDED lazy queries to group_membership model * MM_30476 : Update model to match definition - GroupsInChannel * MM_30476 : Removed groups_in_team definition from Post section of this PR * MM_30476 : Updated all comments to match their variable/field name * MM_30476 : Updated test * MM_30476 : Updated imports and groups_in_team definition * MM_30476 : Updated FileInfo * MM_30476 : Updated Posts and PostMetadata ts types Co-authored-by: Miguel Alatzar Co-authored-by: Elias Nahum --- app/database/server/models/draft.ts | 39 +++++++ app/database/server/models/file.ts | 56 +++++++++ app/database/server/models/index.ts | 5 + app/database/server/models/post.ts | 110 ++++++++++++++++++ app/database/server/models/post_metadata.ts | 38 ++++++ app/database/server/models/posts_in_thread.ts | 39 +++++++ app/database/server/schema/index.ts | 11 +- .../server/schema/table_schemas/draft.ts | 18 +++ .../server/schema/table_schemas/file.ts | 23 ++++ .../server/schema/table_schemas/index.ts | 5 + .../server/schema/table_schemas/post.ts | 27 +++++ .../schema/table_schemas/post_metadata.ts | 17 +++ .../schema/table_schemas/posts_in_thread.ts | 17 +++ app/database/server/schema/test.ts | 105 ++++++++++++++++- types/database/draft.d.ts | 27 +++++ types/database/file.d.ts | 48 ++++++++ types/database/index.d.ts | 80 ++++++++++++- types/database/post.d.ts | 76 +++++++++++- types/database/post_metadata.d.ts | 30 +++++ types/database/posts_in_channel.d.ts | 21 +++- types/database/posts_in_thread.d.ts | 31 +++++ 21 files changed, 816 insertions(+), 7 deletions(-) create mode 100644 app/database/server/models/draft.ts create mode 100644 app/database/server/models/file.ts create mode 100644 app/database/server/models/post.ts create mode 100644 app/database/server/models/post_metadata.ts create mode 100644 app/database/server/models/posts_in_thread.ts create mode 100644 app/database/server/schema/table_schemas/draft.ts create mode 100644 app/database/server/schema/table_schemas/file.ts create mode 100644 app/database/server/schema/table_schemas/post.ts create mode 100644 app/database/server/schema/table_schemas/post_metadata.ts create mode 100644 app/database/server/schema/table_schemas/posts_in_thread.ts create mode 100644 types/database/draft.d.ts create mode 100644 types/database/file.d.ts create mode 100644 types/database/post_metadata.d.ts create mode 100644 types/database/posts_in_thread.d.ts diff --git a/app/database/server/models/draft.ts b/app/database/server/models/draft.ts new file mode 100644 index 000000000..ad2f246e9 --- /dev/null +++ b/app/database/server/models/draft.ts @@ -0,0 +1,39 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import Model, {Associations} from '@nozbe/watermelondb/Model'; +import {field, json} from '@nozbe/watermelondb/decorators'; + +import {MM_TABLES} from '@constants/database'; + +const {CHANNEL, DRAFT, POST} = MM_TABLES.SERVER; + +/** + * The Draft model represents the draft state of messages in Direct/Group messages and in channels + */ +export default class Draft extends Model { + /** table (entity name) : Draft */ + static table = DRAFT; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations = { + + /** A DRAFT can belong to only one CHANNEL */ + [CHANNEL]: {type: 'belongs_to', key: 'channel_id'}, + + /** A DRAFT is associated to only one POST */ + [POST]: {type: 'belongs_to', key: 'root_id'}, + }; + + /** channel_id : The foreign key pointing to the channel in which the draft was made */ + @field('channel_id') channelId!: string; + + /** message : The draft message */ + @field('message') message!: string; + + /** root_id : The root_id will be empty most of the time unless the draft relates to a draft reply of a thread */ + @field('root_id') rootId!: string; + + /** files : The files field will hold an array of file objects that have not yet been uploaded and persisted within the FILE entity */ + @json('files', (rawJson) => rawJson) files!: FileInfo[]; +} diff --git a/app/database/server/models/file.ts b/app/database/server/models/file.ts new file mode 100644 index 000000000..767a3df65 --- /dev/null +++ b/app/database/server/models/file.ts @@ -0,0 +1,56 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; +import {field, immutableRelation} from '@nozbe/watermelondb/decorators'; + +import {MM_TABLES} from '@constants/database'; +import Post from '@typings/database/post'; + +const {FILE, POST} = MM_TABLES.SERVER; + +/** + * The File model works in pair with the Post model. It hosts information about the files shared in a Post + */ +export default class File extends Model { + /** table (entity name) : File */ + static table = FILE; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations = { + + /** A POST has a 1:N relationship with FILE. */ + [POST]: {type: 'belongs_to', key: 'post_id'}, + }; + + /** extension : The file's extension */ + @field('extension') extension!: string; + + /** height : The height for the image */ + @field('height') height!: number; + + /** image_thumbnail : A base64 representation of an image */ + @field('image_thumbnail') imageThumbnail!: string; + + /** local_path : Local path of the file that has been uploaded to server */ + @field('local_path') localPath!: string; + + /** mime_type : The media type */ + @field('mime_type') mimeType!: string; + + /** name : The name for the file object */ + @field('name') name!: string; + + /** post_id : The foreign key of the related Post model */ + @field('post_id') postId!: string; + + /** size : The numeric value of the size for the file */ + @field('size') size!: number; + + /** width : The width of the file object/image */ + @field('width') width!: number; + + /** post : The related Post record for this file */ + @immutableRelation(POST, 'post_id') post!: Relation; +} diff --git a/app/database/server/models/index.ts b/app/database/server/models/index.ts index 1e6267b70..649fff8f2 100644 --- a/app/database/server/models/index.ts +++ b/app/database/server/models/index.ts @@ -3,11 +3,16 @@ export {default as ChannelMembership} from './channel_membership'; export {default as CustomEmoji} from './custom_emoji'; +export {default as Draft} from './draft'; +export {default as File} from './file'; export {default as GroupMembership} from './group_membership'; export {default as GroupsInChannel} from './groups_in_channel'; export {default as GroupsInTeam} from './groups_in_team'; export {default as Group} from './group'; export {default as MyTeam} from './my_team'; +export {default as PostMetadata} from './post_metadata'; +export {default as PostsInThread} from './posts_in_thread'; +export {default as Post} from './post'; export {default as Preference} from './preference'; export {default as Reaction} from './reaction'; export {default as Role} from './role'; diff --git a/app/database/server/models/post.ts b/app/database/server/models/post.ts new file mode 100644 index 000000000..76f7188e9 --- /dev/null +++ b/app/database/server/models/post.ts @@ -0,0 +1,110 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Q, Query, Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; +import {children, field, immutableRelation, json, lazy} from '@nozbe/watermelondb/decorators'; + +import {MM_TABLES} from '@constants/database'; +import Channel from '@typings/database/channel'; +import Draft from '@typings/database/draft'; +import File from '@typings/database/file'; +import PostInThread from '@typings/database/posts_in_thread'; +import PostMetadata from '@typings/database/post_metadata'; +import Reaction from '@typings/database/reaction'; +import User from '@typings/database/user'; + +const {CHANNEL, DRAFT, FILE, POST, POSTS_IN_THREAD, POST_METADATA, REACTION, USER} = MM_TABLES.SERVER; + +/** + * The Post model is the building block of communication in the Mattermost app. + */ +export default class Post extends Model { + /** table (entity name) : Post */ + static table = POST; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations = { + + /** A CHANNEL can have multiple POST. (relationship is 1:N) */ + [CHANNEL]: {type: 'belongs_to', key: 'channel_id'}, + + /** A POST can have multiple DRAFT. (relationship is 1:N) */ + [DRAFT]: {type: 'has_many', foreignKey: 'root_id'}, + + /** A POST can have multiple FILE. (relationship is 1:N)*/ + [FILE]: {type: 'has_many', foreignKey: 'post_id'}, + + /** A POST can have multiple POSTS_IN_THREAD. (relationship is 1:N)*/ + [POSTS_IN_THREAD]: {type: 'has_many', foreignKey: 'post_id'}, + + /** A POST can have multiple POST_METADATA. (relationship is 1:N)*/ + [POST_METADATA]: {type: 'has_many', foreignKey: 'post_id'}, + + /** A POST can have multiple REACTION. (relationship is 1:N)*/ + [REACTION]: {type: 'has_many', foreignKey: 'post_id'}, + + /** A USER can have multiple POST. A user can author several posts. (relationship is 1:N)*/ + [USER]: {type: 'belongs_to', key: 'user_id'}, + }; + + /** channel_id : The foreign key for the Channel to which this post belongs to. */ + @field('channel_id') channelId!: string; + + /** create_at : The timestamp to when this post was first created */ + @field('create_at') createAt!: number; + + /** delete_at : The timestamp to when this post was last archived/deleted */ + @field('delete_at') deleteAt!: number; + + /** edit_at : The timestamp to when this post was last edited */ + @field('edit_at') editAt!: number; + + /** is_pinned : A Boolean flag indicating if this Post is pinned */ + @field('is_pinned') isPinned!: boolean; + + /** message : Message in the post */ + @field('message') message!: string; + + /** original_id : Any post will have this value empty unless it is updated */ + @field('original_id') originalId!: string; + + /** pending_post_id : The id given to a post before it is published on the server */ + @field('pending_post_id') pendingPostId!: string; + + /** previous_post_id : Id of the previous post. If this value is empty, this implies that it is not in the db and we will request it from server */ + @field('previous_post_id') previousPostId!: string; + + /** root_id : Used in threads. All posts under a thread will have this id in common */ + @field('root_id') rootId!: string; + + /** type : Type of props (e.g. system message) */ + @field('type') type!: string; + + /** user_id : The foreign key of the User who authored this post. */ + @field('user_id') userId!: string; + + /** props : Additional attributes for this props */ + @json('props', (rawJson) => rawJson) props!: string; + + // A draft can be associated with this post for as long as this post is a parent post + @lazy draft = this.collections.get(DRAFT).query(Q.on(POST, 'id', this.id)) as Query + + /** postsInThread: The thread to which this post is associated */ + @lazy postsInThread = this.collections.get(POSTS_IN_THREAD).query(Q.on(POST, 'id', this.id)) as Query + + /** files: All the files associated with this Post */ + @children(FILE) files!: File[]; + + /** metadata: All the extra data associated with this Post */ + @children(POST_METADATA) metadata!: PostMetadata[]; + + /** reactions: All the reactions associated with this Post */ + @children(REACTION) reactions!: Reaction[]; + + /** author: The author of this Post */ + @immutableRelation(USER, 'user_id') author!: Relation; + + /** channel: The channel which is presenting this Post */ + @immutableRelation(CHANNEL, 'channel_id') channel!: Relation; +} diff --git a/app/database/server/models/post_metadata.ts b/app/database/server/models/post_metadata.ts new file mode 100644 index 000000000..8d3030be9 --- /dev/null +++ b/app/database/server/models/post_metadata.ts @@ -0,0 +1,38 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; +import {field, immutableRelation, json} from '@nozbe/watermelondb/decorators'; + +import {MM_TABLES} from '@constants/database'; +import Post from '@typings/database/post'; + +const {POST, POST_METADATA} = MM_TABLES.SERVER; + +/** + * PostMetadata provides additional information on a POST + */ +export default class PostMetadata extends Model { + /** table (entity name) : PostMetadata */ + static table = POST_METADATA; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations = { + + /** A POST can have multiple POST_METADATA.(relationship is 1:N)*/ + [POST]: {type: 'belongs_to', key: 'post_id'}, + }; + + /** post_id : The foreign key of the parent POST model */ + @field('post_id') postId!: string; + + /** type : The type will work in tandem with the value present in the field 'data'. One 'type' for each kind of 'data' */ + @field('type') type!: PostType; + + /** data : Different types of data ranging from arrays, emojis, files to images and reactions. */ + @json('data', (rawJson) => rawJson) data!: PostMetadataTypes; + + /** post: The record representing the POST parent. */ + @immutableRelation(POST, 'post_id') post!: Relation; +} diff --git a/app/database/server/models/posts_in_thread.ts b/app/database/server/models/posts_in_thread.ts new file mode 100644 index 000000000..0f6a9e158 --- /dev/null +++ b/app/database/server/models/posts_in_thread.ts @@ -0,0 +1,39 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; +import {field, immutableRelation} from '@nozbe/watermelondb/decorators'; + +import {MM_TABLES} from '@constants/database'; +import Post from '@typings/database/post'; + +const {POST, POSTS_IN_THREAD} = MM_TABLES.SERVER; + +/** + * PostsInThread model helps us to combine adjacent threads together without leaving + * gaps in between for an efficient user reading experience for threads. + */ +export default class PostsInThread extends Model { + /** table (entity name) : PostsInThread */ + static table = POSTS_IN_THREAD; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations = { + + /** A POST can have multiple POSTS_IN_THREAD.(relationship is 1:N)*/ + [POST]: {type: 'belongs_to', key: 'post_id'}, + }; + + /** earliest : Lower bound of a timestamp range */ + @field('earliest') earliest!: number; + + /** latest : Upper bound of a timestamp range */ + @field('latest') latest!: number; + + /** post_id : The foreign key of the related Post model */ + @field('post_id') postId!: string; + + /** post : The related record to the parent Post model */ + @immutableRelation(POST, 'post_id') post!: Relation; +} diff --git a/app/database/server/schema/index.ts b/app/database/server/schema/index.ts index 9abf36bf1..bbb98b61e 100644 --- a/app/database/server/schema/index.ts +++ b/app/database/server/schema/index.ts @@ -2,15 +2,19 @@ // See LICENSE.txt for license information. import {AppSchema, appSchema} from '@nozbe/watermelondb'; - import { ChannelMembershipSchema, CustomEmojiSchema, + DraftSchema, + FileSchema, GroupMembershipSchema, GroupSchema, GroupsInChannelSchema, GroupsInTeamSchema, MyTeamSchema, + PostInThreadSchema, + PostMetadataSchema, + PostSchema, PreferenceSchema, ReactionSchema, RoleSchema, @@ -29,11 +33,16 @@ export const serverSchema: AppSchema = appSchema({ tables: [ ChannelMembershipSchema, CustomEmojiSchema, + DraftSchema, + FileSchema, GroupMembershipSchema, GroupSchema, GroupsInChannelSchema, GroupsInTeamSchema, MyTeamSchema, + PostInThreadSchema, + PostMetadataSchema, + PostSchema, PreferenceSchema, ReactionSchema, RoleSchema, diff --git a/app/database/server/schema/table_schemas/draft.ts b/app/database/server/schema/table_schemas/draft.ts new file mode 100644 index 000000000..eeeb438c7 --- /dev/null +++ b/app/database/server/schema/table_schemas/draft.ts @@ -0,0 +1,18 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {tableSchema} from '@nozbe/watermelondb'; + +import {MM_TABLES} from '@constants/database'; + +const {DRAFT} = MM_TABLES.SERVER; + +export default tableSchema({ + name: DRAFT, + columns: [ + {name: 'channel_id', type: 'string', isIndexed: true}, + {name: 'files', type: 'string'}, + {name: 'message', type: 'string'}, + {name: 'root_id', type: 'string', isIndexed: true}, + ], +}); diff --git a/app/database/server/schema/table_schemas/file.ts b/app/database/server/schema/table_schemas/file.ts new file mode 100644 index 000000000..f4cf14b48 --- /dev/null +++ b/app/database/server/schema/table_schemas/file.ts @@ -0,0 +1,23 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {tableSchema} from '@nozbe/watermelondb'; + +import {MM_TABLES} from '@constants/database'; + +const {FILE} = MM_TABLES.SERVER; + +export default tableSchema({ + name: FILE, + columns: [ + {name: 'extension', type: 'string'}, + {name: 'height', type: 'number'}, + {name: 'image_thumbnail', type: 'string'}, + {name: 'local_path', type: 'string'}, + {name: 'mime_type', type: 'string'}, + {name: 'name', type: 'string'}, + {name: 'post_id', type: 'string', isIndexed: true}, + {name: 'size', type: 'number'}, + {name: 'width', type: 'number'}, + ], +}); diff --git a/app/database/server/schema/table_schemas/index.ts b/app/database/server/schema/table_schemas/index.ts index 3d5a61404..43ea81d82 100644 --- a/app/database/server/schema/table_schemas/index.ts +++ b/app/database/server/schema/table_schemas/index.ts @@ -3,11 +3,16 @@ export {default as ChannelMembershipSchema} from './channel_membership'; export {default as CustomEmojiSchema} from './custom_emoji'; +export {default as DraftSchema} from './draft'; +export {default as FileSchema} from './file'; export {default as GroupMembershipSchema} from './group_membership'; export {default as GroupSchema} from './group'; export {default as GroupsInChannelSchema} from './groups_in_channel'; export {default as GroupsInTeamSchema} from './groups_in_team'; export {default as MyTeamSchema} from './my_team'; +export {default as PostInThreadSchema} from './posts_in_thread'; +export {default as PostMetadataSchema} from './post_metadata'; +export {default as PostSchema} from './post'; export {default as PreferenceSchema} from './preference'; export {default as ReactionSchema} from './reaction'; export {default as RoleSchema} from './role'; diff --git a/app/database/server/schema/table_schemas/post.ts b/app/database/server/schema/table_schemas/post.ts new file mode 100644 index 000000000..ac969b5f9 --- /dev/null +++ b/app/database/server/schema/table_schemas/post.ts @@ -0,0 +1,27 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {tableSchema} from '@nozbe/watermelondb'; + +import {MM_TABLES} from '@constants/database'; + +const {POST} = MM_TABLES.SERVER; + +export default tableSchema({ + name: POST, + columns: [ + {name: 'channel_id', type: 'string', isIndexed: true}, + {name: 'create_at', type: 'number'}, + {name: 'delete_at', type: 'number'}, + {name: 'edit_at', type: 'number'}, + {name: 'is_pinned', type: 'boolean'}, + {name: 'message', type: 'string'}, + {name: 'original_id', type: 'string'}, + {name: 'pending_post_id', type: 'string'}, + {name: 'previous_post_id', type: 'string'}, + {name: 'props', type: 'string'}, + {name: 'root_id', type: 'string'}, + {name: 'type', type: 'string'}, + {name: 'user_id', type: 'string', isIndexed: true}, + ], +}); diff --git a/app/database/server/schema/table_schemas/post_metadata.ts b/app/database/server/schema/table_schemas/post_metadata.ts new file mode 100644 index 000000000..d316be9a5 --- /dev/null +++ b/app/database/server/schema/table_schemas/post_metadata.ts @@ -0,0 +1,17 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {tableSchema} from '@nozbe/watermelondb'; + +import {MM_TABLES} from '@constants/database'; + +const {POST_METADATA} = MM_TABLES.SERVER; + +export default tableSchema({ + name: POST_METADATA, + columns: [ + {name: 'data', type: 'string'}, + {name: 'post_id', type: 'string', isIndexed: true}, + {name: 'type', type: 'string'}, + ], +}); diff --git a/app/database/server/schema/table_schemas/posts_in_thread.ts b/app/database/server/schema/table_schemas/posts_in_thread.ts new file mode 100644 index 000000000..4168856d9 --- /dev/null +++ b/app/database/server/schema/table_schemas/posts_in_thread.ts @@ -0,0 +1,17 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {tableSchema} from '@nozbe/watermelondb'; + +import {MM_TABLES} from '@constants/database'; + +const {POSTS_IN_THREAD} = MM_TABLES.SERVER; + +export default tableSchema({ + name: POSTS_IN_THREAD, + columns: [ + {name: 'earliest', type: 'number'}, + {name: 'latest', type: 'number'}, + {name: 'post_id', type: 'string', isIndexed: true}, + ], +}); diff --git a/app/database/server/schema/test.ts b/app/database/server/schema/test.ts index 746bd8635..d05cbe323 100644 --- a/app/database/server/schema/test.ts +++ b/app/database/server/schema/test.ts @@ -2,17 +2,21 @@ // See LICENSE.txt for license information. import {MM_TABLES} from '@constants/database'; - import {serverSchema} from './index'; const { CHANNEL_MEMBERSHIP, CUSTOM_EMOJI, + DRAFT, + FILE, GROUP, GROUPS_IN_CHANNEL, GROUPS_IN_TEAM, GROUP_MEMBERSHIP, MY_TEAM, + POST, + POSTS_IN_THREAD, + POST_METADATA, PREFERENCE, REACTION, ROLE, @@ -51,6 +55,105 @@ describe('*** Test schema for SERVER database ***', () => { {name: 'name', type: 'string'}, ], }, + [DRAFT]: { + name: DRAFT, + columns: { + channel_id: {name: 'channel_id', type: 'string', isIndexed: true}, + files: {name: 'files', type: 'string'}, + message: {name: 'message', type: 'string'}, + root_id: {name: 'root_id', type: 'string', isIndexed: true}, + }, + columnArray: [ + {name: 'channel_id', type: 'string', isIndexed: true}, + {name: 'files', type: 'string'}, + {name: 'message', type: 'string'}, + {name: 'root_id', type: 'string', isIndexed: true}, + ], + }, + [FILE]: { + name: FILE, + columns: { + extension: {name: 'extension', type: 'string'}, + height: {name: 'height', type: 'number'}, + image_thumbnail: {name: 'image_thumbnail', type: 'string'}, + local_path: {name: 'local_path', type: 'string'}, + mime_type: {name: 'mime_type', type: 'string'}, + name: {name: 'name', type: 'string'}, + post_id: {name: 'post_id', type: 'string', isIndexed: true}, + size: {name: 'size', type: 'number'}, + width: {name: 'width', type: 'number'}, + }, + columnArray: [ + {name: 'extension', type: 'string'}, + {name: 'height', type: 'number'}, + {name: 'image_thumbnail', type: 'string'}, + {name: 'local_path', type: 'string'}, + {name: 'mime_type', type: 'string'}, + {name: 'name', type: 'string'}, + {name: 'post_id', type: 'string', isIndexed: true}, + {name: 'size', type: 'number'}, + {name: 'width', type: 'number'}, + ], + }, + [POSTS_IN_THREAD]: { + name: POSTS_IN_THREAD, + columns: { + earliest: {name: 'earliest', type: 'number'}, + latest: {name: 'latest', type: 'number'}, + post_id: {name: 'post_id', type: 'string', isIndexed: true}, + }, + columnArray: [ + {name: 'earliest', type: 'number'}, + {name: 'latest', type: 'number'}, + {name: 'post_id', type: 'string', isIndexed: true}, + ], + }, + [POST_METADATA]: { + name: POST_METADATA, + columns: { + data: {name: 'data', type: 'string'}, + post_id: {name: 'post_id', type: 'string', isIndexed: true}, + type: {name: 'type', type: 'string'}, + }, + columnArray: [ + {name: 'data', type: 'string'}, + {name: 'post_id', type: 'string', isIndexed: true}, + {name: 'type', type: 'string'}, + ], + }, + [POST]: { + name: POST, + columns: { + channel_id: {name: 'channel_id', type: 'string', isIndexed: true}, + create_at: {name: 'create_at', type: 'number'}, + delete_at: {name: 'delete_at', type: 'number'}, + edit_at: {name: 'edit_at', type: 'number'}, + is_pinned: {name: 'is_pinned', type: 'boolean'}, + message: {name: 'message', type: 'string'}, + original_id: {name: 'original_id', type: 'string'}, + pending_post_id: {name: 'pending_post_id', type: 'string'}, + previous_post_id: {name: 'previous_post_id', type: 'string'}, + props: {name: 'props', type: 'string'}, + root_id: {name: 'root_id', type: 'string'}, + type: {name: 'type', type: 'string'}, + user_id: {name: 'user_id', type: 'string', isIndexed: true}, + }, + columnArray: [ + {name: 'channel_id', type: 'string', isIndexed: true}, + {name: 'create_at', type: 'number'}, + {name: 'delete_at', type: 'number'}, + {name: 'edit_at', type: 'number'}, + {name: 'is_pinned', type: 'boolean'}, + {name: 'message', type: 'string'}, + {name: 'original_id', type: 'string'}, + {name: 'pending_post_id', type: 'string'}, + {name: 'previous_post_id', type: 'string'}, + {name: 'props', type: 'string'}, + {name: 'root_id', type: 'string'}, + {name: 'type', type: 'string'}, + {name: 'user_id', type: 'string', isIndexed: true}, + ], + }, [GROUP]: { name: GROUP, columns: { diff --git a/types/database/draft.d.ts b/types/database/draft.d.ts new file mode 100644 index 000000000..dd81320fb --- /dev/null +++ b/types/database/draft.d.ts @@ -0,0 +1,27 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import Model, {Associations} from '@nozbe/watermelondb/Model'; + +/** + * The Draft model represents the draft state of messages in Direct/Group messages and in channels + */ +export default class Draft extends Model { + /** table (entity name) : Draft */ + static table: string; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations; + + /** channel_id : The foreign key pointing to the channel in which the draft was made */ + channelId: string; + + /** message : The draft message */ + message: string; + + /** root_id : The root_id will be empty most of the time unless the draft relates to a draft reply of a thread */ + rootId: string; + + /** files : The files field will hold an array of files object that have not yet been uploaded and persisted within the FILE entity */ + files: FileInfo[]; +} diff --git a/types/database/file.d.ts b/types/database/file.d.ts new file mode 100644 index 000000000..1df3391a1 --- /dev/null +++ b/types/database/file.d.ts @@ -0,0 +1,48 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; + +import Post from '@typings/database/post'; + +/** + * The File model works in pair with the Post model. It hosts information about the files shared in a Post + */ +export default class File extends Model { + /** table (entity name) : File */ + static table: string; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations; + + /** extension : The file's extension */ + extension: string; + + /** height : The height for the image */ + height: number; + + /** image_thumbnail : A base64 representation of an image */ + imageThumbnail: string; + + /** local_path : Local path of the file that has been uploaded to server */ + localPath: string; + + /** mime_type : The media type */ + mimeType: string; + + /** name : The name for the file object */ + name: string; + + /** post_id : The foreign key of the related Post model */ + postId: string; + + /** size : The numeric value of the size for the file */ + size: number; + + /** width : The width of the file object/image */ + width: number; + + /** post : The related Post record for this file */ + post: Relation; +} diff --git a/types/database/index.d.ts b/types/database/index.d.ts index f78184dc8..7cefdb19c 100644 --- a/types/database/index.d.ts +++ b/types/database/index.d.ts @@ -11,13 +11,87 @@ interface NotifyProps { push: string; } - interface UserProps { - [userPropsName : string] : any +interface UserProps { + [userPropsName: string]: any } - interface Timezone { +interface Timezone { automaticTimezone: string manualTimezone: string, useAutomaticTimezone: true, } +interface PostEmbed { + type: PostEmbedType; + url: string; + data: Record; +} + +interface CustomEmoji { + id: string; + create_at: number; + update_at: number; + delete_at: number; + creator_id: string; + name: string; + category: 'custom'; +} + +interface FileInfo { + id: string; + user_id: string; + post_id: string; + create_at: number; + update_at: number; + delete_at: number; + name: string; + extension: string; + size: number; + mime_type: string; + width: number; + height: number; + has_preview_image: boolean; + clientId: string; + localPath?: string; + uri?: string; + loading?: boolean; +} + +type PostEmbedType = 'image' | 'message_attachment' | 'opengraph'; + +interface PostImage { + height: number; + width: number; + format?: string; + frame_count?: number; +} + +interface Reaction { + user_id: string; + post_id: string; + emoji_name: string; + create_at: number; +} + +interface PostMetadataTypes { + embeds: Array; + emojis: Array; + files: Array; + images: Dictionary; + reactions: Array; +} + +type PostType = 'system_add_remove' | + 'system_add_to_channel' | + 'system_add_to_team' | + 'system_channel_deleted' | + 'system_channel_restored' | + 'system_displayname_change' | + 'system_convert_channel' | + 'system_ephemeral' | + 'system_header_change' | + 'system_join_channel' | + 'system_join_leave' | + 'system_leave_channel' | + 'system_purpose_change' | + 'system_remove_from_channel'; diff --git a/types/database/post.d.ts b/types/database/post.d.ts index 1c487b5ad..466d67e10 100644 --- a/types/database/post.d.ts +++ b/types/database/post.d.ts @@ -1,10 +1,84 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import Model from '@nozbe/watermelondb/Model'; +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; + +import Channel from '@typings/database/channel'; +import Draft from '@typings/database/draft'; +import File from '@typings/database/file'; +import PostInThread from '@typings/database/posts_in_thread'; +import PostMetadata from '@typings/database/post_metadata'; +import Reaction from '@typings/database/reaction'; +import User from '@typings/database/user'; /** * The Post model is the building block of communication in the Mattermost app. */ export default class Post extends Model { + /** table (entity name) : Post */ + static table: string; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations; + + /** channel_id : The foreign key for the Channel to which this post belongs to. */ + channelId: string; + + /** create_at : The timestamp to when this post was first created */ + createAt: number; + + /** delete_at : The timestamp to when this post was last archived/deleted */ + deleteAt: number; + + /** edit_at : The timestamp to when this post was last edited */ + editAt: number; + + /** is_pinned : A Boolean flag indicating if this Post is pinned */ + isPinned: boolean; + + /** message : Message in the post */ + message: string; + + /** original_id : Any post will have this value empty unless it is updated */ + originalId: string; + + /** pending_post_id : The id given to a post before it is published on the server */ + pendingPostId: string; + + /** previous_post_id : Id of the previous post. If this value is empty, this implies that it is not in the db and we will request it from server */ + previousPostId: string; + + /** root_id : Used in threads. All posts under a thread will have this id in common */ + rootId: string; + + /** type : Type of props (e.g. system message) */ + type: string; + + /** user_id : The foreign key of the User who authored this post. */ + userId: string; + + /** props : Additional attributes for this props */ + props: string; + + /** drafts : Every drafts associated with this Post */ + drafts: Draft; + + /** files: All the files associated with this Post */ + files: File[]; + + /** postsInThread: Every posts associated to a thread */ + postsInThread: PostInThread[]; + + /** metadata: All the extra data associated with this Post */ + metadata: PostMetadata[]; + + /** reactions: All the reactions associated with this Post */ + reactions: Reaction[]; + + /** author: The author of this Post */ + author: Relation; + + /** channel: The channel which is presenting this Post */ + channel: Relation; } diff --git a/types/database/post_metadata.d.ts b/types/database/post_metadata.d.ts new file mode 100644 index 000000000..f69dd2fc2 --- /dev/null +++ b/types/database/post_metadata.d.ts @@ -0,0 +1,30 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; + +import Post from '@typings/database/post'; + +/** + * PostMetadata provides additional information on a POST + */ +export default class PostMetadata extends Model { + /** table (entity name) : PostMetadata */ + static table: string; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations; + + /** post_id : The foreign key of the parent POST model */ + postId: string; + + /** type : The type will work in tandem with the value present in the field 'data'. One 'type' for each kind of 'data' */ + type: string; + + /** data : Different types of data ranging from arrays, emojis, files to images and reactions. */ + data: string; + + /** post: The record representing the POST parent. */ + post: Relation; +} diff --git a/types/database/posts_in_channel.d.ts b/types/database/posts_in_channel.d.ts index 121cc16a4..9e2de5a17 100644 --- a/types/database/posts_in_channel.d.ts +++ b/types/database/posts_in_channel.d.ts @@ -1,12 +1,31 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import Model from '@nozbe/watermelondb/Model'; +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; + +import Channel from '@typings/database/channel'; /** * PostsInChannel model helps us to combine adjacent posts together without leaving * gaps in between for an efficient user reading experience of posts. */ export default class PostsInChannel extends Model { + /** table (entity name) : PostsInChannel */ + static table: string; + /** associations : Describes every relationship to this entity. */ + static associations: Associations; + + /** channel_id : The foreign key of the related parent channel */ + channelId: string; + + /** earliest : The earliest timestamp of the post in that channel */ + earliest: number; + + /** latest : The latest timestamp of the post in that channel */ + latest: number; + + /** channel : The parent record of the channel for those posts */ + channel: Relation; } diff --git a/types/database/posts_in_thread.d.ts b/types/database/posts_in_thread.d.ts new file mode 100644 index 000000000..982a09b6f --- /dev/null +++ b/types/database/posts_in_thread.d.ts @@ -0,0 +1,31 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Relation} from '@nozbe/watermelondb'; +import Model, {Associations} from '@nozbe/watermelondb/Model'; + +import Post from '@typings/database/post'; + +/** + * PostsInThread model helps us to combine adjacent threads together without leaving + * gaps in between for an efficient user reading experience for threads. + */ +export default class PostsInThread extends Model { + /** table (entity name) : PostsInThread */ + static table: string; + + /** associations : Describes every relationship to this entity. */ + static associations: Associations; + + /** earliest : Lower bound of a timestamp range */ + earliest: number; + + /** latest : Upper bound of a timestamp range */ + latest: number; + + /** post_id : The foreign key of the related Post model */ + postId: string; + + /** post : The related record to the parent Post model */ + post: Relation; +}