From d468b4a688d39ee111128e4272bf8d14930c5e14 Mon Sep 17 00:00:00 2001 From: munkhsaikhan Date: Tue, 10 Sep 2019 18:43:32 +0800 Subject: [PATCH 01/41] erxes/erxes#1200 --- boards.ts | 3 +-- conformities.ts | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ customers.ts | 2 +- 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 conformities.ts diff --git a/boards.ts b/boards.ts index 4925882..35664e1 100644 --- a/boards.ts +++ b/boards.ts @@ -11,6 +11,7 @@ interface ICommonFields { export interface IItemCommonFields { name?: string; + // TODO migrate after remove 2row companyIds?: string[]; customerIds?: string[]; closeDate?: Date; @@ -99,8 +100,6 @@ export const commonItemFieldsSchema = { }), order: field({ type: Number }), name: field({ type: String }), - companyIds: field({ type: [String] }), - customerIds: field({ type: [String] }), closeDate: field({ type: Date }), description: field({ type: String, optional: true }), assignedUserIds: field({ type: [String] }), diff --git a/conformities.ts b/conformities.ts new file mode 100644 index 0000000..4419575 --- /dev/null +++ b/conformities.ts @@ -0,0 +1,58 @@ +import { Document, Schema } from 'mongoose'; +import { field } from './utils'; + +export interface IConformity { + mainType: string; + mainTypeId: string; + relType: string; + relTypeId: string; +} + +export interface IConformityAdd { + mainType: string; + mainTypeId: string; + relType: string; + relTypeId: string; +} + +export interface IConformityEdit { + mainType: string; + mainTypeId: string; + relType: string; + relTypeIds: string[]; +} + +export interface IConformitySaved { + mainType: string; + mainTypeId: string; + relType: string; +} + +export interface IConformityChange { + type: string; + newTypeId: string; + oldTypeIds: string[]; +} + +export interface IConformityFilter { + mainType: string; + mainTypeIds: string[]; + relType: string; +} + +export interface IConformityRemove { + mainType: string; + mainTypeId: string; +} + +export interface IConformityDocument extends IConformity, Document { + _id: string; +} + +export const conformitySchema = new Schema({ + _id: field({ pkey: true }), + mainType: field({ type: String }), + mainTypeId: field({ type: String }), + relType: field({ type: String }), + relTypeId: field({ type: String }), +}); diff --git a/customers.ts b/customers.ts index 1c3d80e..6f397ed 100644 --- a/customers.ts +++ b/customers.ts @@ -66,6 +66,7 @@ export interface ICustomer { isUser?: boolean; integrationId?: string; tagIds?: string[]; + // TODO migrate after remove 1row companyIds?: string[]; mergedIds?: string[]; status?: string; @@ -208,7 +209,6 @@ export const customerSchema = schemaWrapper( integrationId: field({ type: String, optional: true }), tagIds: field({ type: [String], optional: true, index: true }), - companyIds: field({ type: [String], optional: true }), // Merged customer ids mergedIds: field({ type: [String], optional: true }), From 165c436eea7dc6852fea7588695b8a59aa1bb673 Mon Sep 17 00:00:00 2001 From: Narmandakh Enkhtuvshin <37796969+Enkhtuvshin0513@users.noreply.github.com> Date: Wed, 11 Sep 2019 19:06:30 +0800 Subject: [PATCH 02/41] erxes/erxes#1108 --- constants.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/constants.ts b/constants.ts index 62da9c8..20d7f1c 100644 --- a/constants.ts +++ b/constants.ts @@ -54,10 +54,11 @@ export const FORM_SUCCESS_ACTIONS = { export const KIND_CHOICES = { MESSENGER: 'messenger', FORM: 'form', - FACEBOOK: 'facebook', + FACEBOOK_MESSENGER: 'facebook-messenger', + FACEBOOK_POST: 'facebook-post', GMAIL: 'gmail', CALLPRO: 'callpro', - ALL: ['messenger', 'form', 'facebook', 'gmail', 'callpro'], + ALL: ['messenger', 'form', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro'], }; // messenger data availability constants From 64bd094b7b51e47873e59a62e34655b29c784c22 Mon Sep 17 00:00:00 2001 From: Munkhjin Date: Fri, 13 Sep 2019 20:58:41 +0800 Subject: [PATCH 03/41] erxes/erxes#1113 --- boards.ts | 23 +++++--- constants.ts | 53 ++++++++++++++++--- forms.ts | 121 +++++++++++++++++++++++++++---------------- growthHacks.ts | 25 +++++++++ integrations.ts | 85 ++++++++++++++++++++++++++---- pipelineTemplates.ts | 40 ++++++++++++++ 6 files changed, 276 insertions(+), 71 deletions(-) create mode 100644 growthHacks.ts create mode 100644 pipelineTemplates.ts diff --git a/boards.ts b/boards.ts index 35664e1..0006a11 100644 --- a/boards.ts +++ b/boards.ts @@ -1,5 +1,5 @@ import { Document, Schema } from 'mongoose'; -import { BOARD_TYPES, PIPELINE_VISIBLITIES, PROBABILITY } from './constants'; +import { BOARD_TYPES, HACK_SCORING_TYPES, PIPELINE_VISIBLITIES, PROBABILITY } from './constants'; import { field, schemaWrapper } from './utils'; interface ICommonFields { @@ -31,7 +31,6 @@ export interface IItemCommonFields { export interface IBoard extends ICommonFields { name?: string; - isDefault?: boolean; } export interface IBoardDocument extends IBoard, Document { @@ -45,6 +44,8 @@ export interface IPipeline extends ICommonFields { memberIds?: string[]; bgColor?: string; watchedUserIds?: string[]; + hackScoringType?: string; + templateId?: string; } export interface IPipelineDocument extends IPipeline, Document { @@ -54,13 +55,17 @@ export interface IPipelineDocument extends IPipeline, Document { export interface IStage extends ICommonFields { name?: string; probability?: string; - pipelineId?: string; + pipelineId: string; + formId?: string; } export interface IStageDocument extends IStage, Document { _id: string; } +// Not mongoose document, just stage shaped plain object +export type IPipelineStage = IStage & { _id: string }; + export interface IOrderInput { _id: string; order: number; @@ -105,7 +110,7 @@ export const commonItemFieldsSchema = { assignedUserIds: field({ type: [String] }), watchedUserIds: field({ type: [String] }), attachments: field({ type: [attachmentSchema] }), - stageId: field({ type: String, optional: true }), + stageId: field({ type: String }), initialStageId: field({ type: String, optional: true }), modifiedAt: field({ type: Date, @@ -118,10 +123,6 @@ export const boardSchema = schemaWrapper( new Schema({ _id: field({ pkey: true }), name: field({ type: String }), - isDefault: field({ - type: Boolean, - default: false, - }), ...commonFieldsSchema, }), ); @@ -138,6 +139,11 @@ export const pipelineSchema = new Schema({ watchedUserIds: field({ type: [String] }), memberIds: field({ type: [String] }), bgColor: field({ type: String }), + hackScoringType: field({ + type: String, + enum: HACK_SCORING_TYPES.ALL, + }), + templateId: field({ type: String, optional: true }), ...commonFieldsSchema, }); @@ -149,5 +155,6 @@ export const stageSchema = new Schema({ enum: PROBABILITY.ALL, }), // Win probability pipelineId: field({ type: String }), + formId: field({ type: String }), ...commonFieldsSchema, }); diff --git a/constants.ts b/constants.ts index 20d7f1c..9fbeb65 100644 --- a/constants.ts +++ b/constants.ts @@ -34,7 +34,7 @@ export const METHODS = { ALL: ['messenger', 'email'], }; -export const FORM_LOAD_TYPES = { +export const LEAD_LOAD_TYPES = { SHOUTBOX: 'shoutbox', POPUP: 'popup', EMBEDDED: 'embedded', @@ -44,7 +44,7 @@ export const FORM_LOAD_TYPES = { ALL: ['', 'shoutbox', 'popup', 'embedded', 'dropdown', 'slideInLeft', 'slideInRight'], }; -export const FORM_SUCCESS_ACTIONS = { +export const LEAD_SUCCESS_ACTIONS = { EMAIL: 'email', REDIRECT: 'redirect', ONPAGE: 'onPage', @@ -53,12 +53,12 @@ export const FORM_SUCCESS_ACTIONS = { export const KIND_CHOICES = { MESSENGER: 'messenger', - FORM: 'form', + LEAD: 'lead', FACEBOOK_MESSENGER: 'facebook-messenger', FACEBOOK_POST: 'facebook-post', GMAIL: 'gmail', CALLPRO: 'callpro', - ALL: ['messenger', 'form', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro'], + ALL: ['messenger', 'lead', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro'], }; // messenger data availability constants @@ -75,8 +75,9 @@ export const ACTIVITY_CONTENT_TYPES = { DEAL: 'deal', TICKET: 'ticket', TASK: 'task', + GROWTH_HACK: 'growthHack', - ALL: ['customer', 'company', 'user', 'deal', 'ticket', 'task'], + ALL: ['customer', 'company', 'user', 'deal', 'ticket', 'task', 'growthHack'], }; export const PUBLISH_STATUSES = { @@ -96,8 +97,21 @@ export const ACTIVITY_TYPES = { TICKET: 'ticket', TASK: 'task', BRAND: 'brand', + GROWTH_HACK: 'growthHack', - ALL: ['customer', 'company', 'internal_note', 'conversation', 'segment', 'deal', 'email', 'ticket', 'task', 'brand'], + ALL: [ + 'customer', + 'company', + 'internal_note', + 'conversation', + 'segment', + 'deal', + 'email', + 'ticket', + 'task', + 'brand', + 'growthHack', + ], }; export const ACTIVITY_ACTIONS = { @@ -131,6 +145,12 @@ export const PIPELINE_VISIBLITIES = { ALL: ['public', 'private'], }; +export const HACK_SCORING_TYPES = { + RICE: 'rice', + ICE: 'ice', + ALL: ['rice', 'ice'], +}; + export const FIELDS_GROUPS_CONTENT_TYPES = { CUSTOMER: 'customer', COMPANY: 'company', @@ -281,7 +301,8 @@ export const BOARD_TYPES = { DEAL: 'deal', TICKET: 'ticket', TASK: 'task', - ALL: ['deal', 'ticket', 'task'], + GROWTH_HACK: 'growthHack', + ALL: ['deal', 'ticket', 'task', 'growthHack'], }; // module constants @@ -296,6 +317,12 @@ export const NOTIFICATION_TYPES = { DEAL_CHANGE: 'dealChange', DEAL_DUE_DATE: 'dealDueDate', DEAL_DELETE: 'dealDelete', + GROWTH_HACK_ADD: 'growthHackAdd', + GROWTH_HACK_REMOVE_ASSIGN: 'growthHackRemoveAssign', + GROWTH_HACK_EDIT: 'growthHackEdit', + GROWTH_HACK_CHANGE: 'growthHackChange', + GROWTH_HACK_DUE_DATE: 'growthHackDueDate', + GROWTH_HACK_DELETE: 'growthHackDelete', TICKET_ADD: 'ticketAdd', TICKET_REMOVE_ASSIGN: 'ticketRemoveAssign', TICKET_EDIT: 'ticketEdit', @@ -321,6 +348,12 @@ export const NOTIFICATION_TYPES = { 'dealChange', 'dealDueDate', 'dealDelete', + 'growthHackAdd', + 'growthHackRemoveAssign', + 'growthHackEdit', + 'growthHackChange', + 'growthHackDueDate', + 'growthHackDelete', 'ticketAdd', 'ticketRemoveAssign', 'ticketEdit', @@ -338,6 +371,12 @@ export const NOTIFICATION_TYPES = { ], }; +export const FORM_TYPES = { + LEAD: 'lead', + GROWTH_HACK: 'growthHack', + ALL: ['lead', 'growthHack'], +}; + export const NOTIFICATION_CONTENT_TYPES = { TASK: 'task', DEAL: 'deal', diff --git a/forms.ts b/forms.ts index 480e0b7..f290382 100644 --- a/forms.ts +++ b/forms.ts @@ -1,81 +1,110 @@ import { Document, Schema } from 'mongoose'; import { IRule, ruleSchema } from './common'; +import { FORM_TYPES } from './constants'; +import { calloutSchema, ICallout, ISubmission, submissionSchema } from './integrations'; import { field, schemaWrapper } from './utils'; -export interface ICallout extends Document { - title?: string; - body?: string; - buttonText?: string; - featuredImage?: string; - skip?: boolean; -} - -interface ISubmission extends Document { - customerId: string; - submittedAt: Date; -} - export interface IForm { title: string; code?: string; + type: string; description?: string; buttonText?: string; - themeColor?: string; - callout?: ICallout; - rules?: IRule; } export interface IFormDocument extends IForm, Document { _id: string; createdUserId: string; createdDate: Date; - viewCount: number; - contactsGathered: number; - submissions: ISubmission[]; + // TODO: remove + contactsGathered?: number; + // TODO: remove + viewCount?: number; + // TODO: remove + submissions?: ISubmission[]; + // TODO: remove + themeColor?: string; + // TODO: remove + callout?: ICallout; + // TODO: remove + rules?: IRule; } -// schema for form's callout component -const calloutSchema = new Schema( - { - title: field({ type: String, optional: true }), - body: field({ type: String, optional: true }), - buttonText: field({ type: String, optional: true }), - featuredImage: field({ type: String, optional: true }), - skip: field({ type: Boolean, optional: true }), - }, - { _id: false }, -); - -// schema for form submission details -const submissionSchema = new Schema( - { - customerId: field({ type: String }), - submittedAt: field({ type: Date }), - }, - { _id: false }, -); - // schema for form document export const formSchema = schemaWrapper( new Schema({ _id: field({ pkey: true }), title: field({ type: String, optional: true }), + type: field({ type: String, enum: FORM_TYPES.ALL, required: true }), description: field({ type: String, optional: true, }), buttonText: field({ type: String, optional: true }), - themeColor: field({ type: String, optional: true }), code: field({ type: String }), createdUserId: field({ type: String }), createdDate: field({ type: Date, default: Date.now, }), - callout: field({ type: calloutSchema, default: {} }), - viewCount: field({ type: Number }), - contactsGathered: field({ type: Number }), - submissions: field({ type: [submissionSchema] }), - rules: field({ type: [ruleSchema] }), + + // TODO: remove + themeColor: field({ + type: String, + optional: true, + }), + // TODO: remove + callout: field({ + type: calloutSchema, + optional: true, + }), + // TODO: remove + viewCount: field({ + type: Number, + optional: true, + }), + // TODO: remove + contactsGathered: field({ + type: Number, + optional: true, + }), + // TODO: remove + submissions: field({ + type: [submissionSchema], + optional: true, + }), + // TODO: remove + rules: field({ + type: [ruleSchema], + optional: true, + }), + }), +); + +export interface IFormSubmission { + customerId?: string; + contentType?: string; + contentTypeId?: string; + formId?: string; + formFieldId?: string; + value?: JSON; + submittedAt?: Date; +} + +export interface IFormSubmissionDocument extends IFormSubmission, Document { + _id: string; +} + +// schema for form submission document +export const formSubmissionSchema = schemaWrapper( + new Schema({ + _id: field({ pkey: true }), + customerId: field({ type: String, optional: true }), + contentType: field({ type: String, optional: true }), + contentTypeId: field({ type: String, optional: true }), + value: field({ type: Object, optional: true }), + submittedAt: field({ type: Date, default: Date.now }), + formId: field({ type: String, optional: true }), + formFieldId: field({ type: String, optional: true }), }), ); diff --git a/growthHacks.ts b/growthHacks.ts new file mode 100644 index 0000000..8a2283e --- /dev/null +++ b/growthHacks.ts @@ -0,0 +1,25 @@ +import { Document, Schema } from 'mongoose'; +import { commonItemFieldsSchema, IItemCommonFields } from './boards'; +import { field } from './utils'; + +export interface IGrowthHack extends IItemCommonFields { + hackDescription?: string; + goal?: string; +} + +export interface IGrowthHackDocument extends IGrowthHack, Document { + _id: string; +} + +export const growthHackSchema = new Schema({ + ...commonItemFieldsSchema, + + hackDescription: field({ type: String, optional: true }), + goal: field({ type: String, optional: true }), + hackStages: field({ type: [String], optional: true }), + priority: field({ type: String, optional: true }), + reach: field({ type: Number, optional: true }), + impact: field({ type: Number, optional: true }), + confidence: field({ type: Number, optional: true }), + ease: field({ type: Number, optional: true }), +}); diff --git a/integrations.ts b/integrations.ts index eccc276..1fcad46 100644 --- a/integrations.ts +++ b/integrations.ts @@ -1,7 +1,13 @@ import { Document, Schema } from 'mongoose'; -import { FORM_LOAD_TYPES, FORM_SUCCESS_ACTIONS, KIND_CHOICES, MESSENGER_DATA_AVAILABILITY } from './constants'; +import { IRule, ruleSchema } from './common'; +import { KIND_CHOICES, LEAD_LOAD_TYPES, LEAD_SUCCESS_ACTIONS, MESSENGER_DATA_AVAILABILITY } from './constants'; import { field } from './utils'; +export interface ISubmission extends Document { + customerId: string; + submittedAt: Date; +} + export interface ILink { twitter?: string; facebook?: string; @@ -44,7 +50,15 @@ export interface IMessengerData { export interface IMessengerDataDocument extends IMessengerData, Document {} -export interface IFormData { +export interface ICallout extends Document { + title?: string; + body?: string; + buttonText?: string; + featuredImage?: string; + skip?: boolean; +} + +export interface ILeadData { loadType?: string; successAction?: string; fromEmail?: string; @@ -55,9 +69,15 @@ export interface IFormData { adminEmailContent?: string; thankContent?: string; redirectUrl?: string; + themeColor?: string; + callout?: ICallout; + rules?: IRule; } -export interface IFormDataDocument extends IFormData, Document {} +export interface ILeadDataDocument extends ILeadData, Document { + viewCount?: number; + contactsGathered?: number; +} export interface IUiOptions { color?: string; @@ -75,14 +95,15 @@ export interface IIntegration { languageCode?: string; tagIds?: string[]; formId?: string; - formData?: IFormData; + leadData?: ILeadData; messengerData?: IMessengerData; uiOptions?: IUiOptions; } export interface IIntegrationDocument extends IIntegration, Document { _id: string; - formData?: IFormDataDocument; + // TODO: remove + formData?: ILeadData; messengerData?: IMessengerDataDocument; uiOptions?: IUiOptionsDocument; } @@ -128,16 +149,38 @@ const messengerDataSchema = new Schema( { _id: false }, ); -// subdocument schema for FormData -const formDataSchema = new Schema( +// schema for lead's callout component +export const calloutSchema = new Schema( + { + title: field({ type: String, optional: true }), + body: field({ type: String, optional: true }), + buttonText: field({ type: String, optional: true }), + featuredImage: field({ type: String, optional: true }), + skip: field({ type: Boolean, optional: true }), + }, + { _id: false }, +); + +// TODO: remove +// schema for lead submission details +export const submissionSchema = new Schema( + { + customerId: field({ type: String }), + submittedAt: field({ type: Date }), + }, + { _id: false }, +); + +// subdocument schema for LeadData +const leadDataSchema = new Schema( { loadType: field({ type: String, - enum: FORM_LOAD_TYPES.ALL, + enum: LEAD_LOAD_TYPES.ALL, }), successAction: field({ type: String, - enum: FORM_SUCCESS_ACTIONS.ALL, + enum: LEAD_SUCCESS_ACTIONS.ALL, optional: true, }), fromEmail: field({ @@ -172,6 +215,26 @@ const formDataSchema = new Schema( type: String, optional: true, }), + themeColor: field({ + type: String, + optional: true, + }), + callout: field({ + type: calloutSchema, + optional: true, + }), + viewCount: field({ + type: Number, + optional: true, + }), + contactsGathered: field({ + type: Number, + optional: true, + }), + rules: field({ + type: [ruleSchema], + optional: true, + }), }, { _id: false }, ); @@ -204,7 +267,9 @@ export const integrationSchema = new Schema({ }), tagIds: field({ type: [String], optional: true }), formId: field({ type: String }), - formData: field({ type: formDataSchema }), + leadData: field({ type: leadDataSchema }), + // TODO: remove + formData: field({ type: leadDataSchema }), messengerData: field({ type: messengerDataSchema }), uiOptions: field({ type: uiOptionsSchema }), }); diff --git a/pipelineTemplates.ts b/pipelineTemplates.ts new file mode 100644 index 0000000..8893f3d --- /dev/null +++ b/pipelineTemplates.ts @@ -0,0 +1,40 @@ +import { Document, Schema } from 'mongoose'; +import { field } from './utils'; + +export interface IPipelineTemplateStage { + _id: string; + name: string; + formId: string; +} + +export interface IPipelineTemplate { + name: string; + description?: string; + type: string; + isDefinedByErxes: boolean; + stages: IPipelineTemplateStage[]; +} + +export interface IPipelineTemplateDocument extends IPipelineTemplate, Document { + _id: string; +} + +const stageSchema = new Schema( + { + _id: field({ type: String }), + name: field({ type: String }), + formId: field({ type: String, optional: true }), + order: field({ type: Number }), + }, + { _id: false }, +); + +export const pipelineTemplateSchema = new Schema({ + _id: field({ pkey: true }), + + name: field({ type: String }), + type: field({ type: String }), + description: field({ type: String, optional: true }), + stages: field({ type: [stageSchema], default: [] }), + isDefinedByErxes: field({ type: Boolean, default: false }), +}); From 4301a528cb82f6ca62c844f666c07b8670005f91 Mon Sep 17 00:00:00 2001 From: munkhjin Date: Mon, 16 Sep 2019 17:43:12 +0800 Subject: [PATCH 04/41] add createdAt and createdBy field for pipeline template --- pipelineTemplates.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pipelineTemplates.ts b/pipelineTemplates.ts index 8893f3d..0cfea40 100644 --- a/pipelineTemplates.ts +++ b/pipelineTemplates.ts @@ -13,6 +13,8 @@ export interface IPipelineTemplate { type: string; isDefinedByErxes: boolean; stages: IPipelineTemplateStage[]; + createdBy: string; + createdDate: Date; } export interface IPipelineTemplateDocument extends IPipelineTemplate, Document { @@ -37,4 +39,9 @@ export const pipelineTemplateSchema = new Schema({ description: field({ type: String, optional: true }), stages: field({ type: [stageSchema], default: [] }), isDefinedByErxes: field({ type: Boolean, default: false }), + createdBy: field({ type: String }), + createdAt: field({ + type: Date, + default: new Date(), + }), }); From 8fadc57823675496759204c414b36b5e15ef6029 Mon Sep 17 00:00:00 2001 From: munkhjin Date: Wed, 18 Sep 2019 10:51:20 +0800 Subject: [PATCH 05/41] remove goal and hackDescription fields from growth hack --- growthHacks.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/growthHacks.ts b/growthHacks.ts index 8a2283e..bbd1abc 100644 --- a/growthHacks.ts +++ b/growthHacks.ts @@ -3,8 +3,12 @@ import { commonItemFieldsSchema, IItemCommonFields } from './boards'; import { field } from './utils'; export interface IGrowthHack extends IItemCommonFields { - hackDescription?: string; - goal?: string; + hackStages?: string; + priority?: string; + reach?: number; + impact?: number; + confidence?: number; + ease?: number; } export interface IGrowthHackDocument extends IGrowthHack, Document { @@ -14,8 +18,6 @@ export interface IGrowthHackDocument extends IGrowthHack, Document { export const growthHackSchema = new Schema({ ...commonItemFieldsSchema, - hackDescription: field({ type: String, optional: true }), - goal: field({ type: String, optional: true }), hackStages: field({ type: [String], optional: true }), priority: field({ type: String, optional: true }), reach: field({ type: Number, optional: true }), From 1f92c3ef917a62690a4b8c4687efaae03c9493cc Mon Sep 17 00:00:00 2001 From: munkhjin Date: Thu, 19 Sep 2019 10:08:21 +0800 Subject: [PATCH 06/41] add startDate, endDate, metric fields for pipeline --- boards.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boards.ts b/boards.ts index 0006a11..0691989 100644 --- a/boards.ts +++ b/boards.ts @@ -44,6 +44,10 @@ export interface IPipeline extends ICommonFields { memberIds?: string[]; bgColor?: string; watchedUserIds?: string[]; + // growth hack + startDate?: Date; + endDate?: Date; + metric?: string; hackScoringType?: string; templateId?: string; } @@ -139,6 +143,10 @@ export const pipelineSchema = new Schema({ watchedUserIds: field({ type: [String] }), memberIds: field({ type: [String] }), bgColor: field({ type: String }), + // Growth hack + startDate: field({ type: Date, optional: true }), + endDate: field({ type: Date, optional: true }), + metric: field({ type: String, optional: true }), hackScoringType: field({ type: String, enum: HACK_SCORING_TYPES.ALL, From 26a41b56bc91af7f802c73e54c1f5098b9408360 Mon Sep 17 00:00:00 2001 From: Mungunshagai Enkhbat Date: Thu, 19 Sep 2019 16:00:43 +0800 Subject: [PATCH 07/41] erxes/erxes#1210 --- boards.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards.ts b/boards.ts index 0691989..30529a1 100644 --- a/boards.ts +++ b/boards.ts @@ -110,6 +110,8 @@ export const commonItemFieldsSchema = { order: field({ type: Number }), name: field({ type: String }), closeDate: field({ type: Date }), + reminderMinute: field({ type: Number }), + isComplete: field({ type: Boolean, default: false }), description: field({ type: String, optional: true }), assignedUserIds: field({ type: [String] }), watchedUserIds: field({ type: [String] }), From 1fadcfdbe6a6fd9d8bf3fdf96107b3a1251f9af4 Mon Sep 17 00:00:00 2001 From: Narmandakh Enkhtuvshin <37796969+Enkhtuvshin0513@users.noreply.github.com> Date: Mon, 23 Sep 2019 20:28:01 +0800 Subject: [PATCH 08/41] erxes/erxes#1238 --- constants.ts | 6 ++++-- deals.ts | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/constants.ts b/constants.ts index 9fbeb65..77fabf5 100644 --- a/constants.ts +++ b/constants.ts @@ -75,9 +75,10 @@ export const ACTIVITY_CONTENT_TYPES = { DEAL: 'deal', TICKET: 'ticket', TASK: 'task', + PRODUCT: 'product', GROWTH_HACK: 'growthHack', - ALL: ['customer', 'company', 'user', 'deal', 'ticket', 'task', 'growthHack'], + ALL: ['customer', 'company', 'user', 'deal', 'ticket', 'task', 'product', 'growthHack'], }; export const PUBLISH_STATUSES = { @@ -154,7 +155,8 @@ export const HACK_SCORING_TYPES = { export const FIELDS_GROUPS_CONTENT_TYPES = { CUSTOMER: 'customer', COMPANY: 'company', - ALL: ['customer', 'company'], + PRODUCT: 'product', + ALL: ['customer', 'company', 'product'], }; export const CUSTOMER_LEAD_STATUS_TYPES = [ diff --git a/deals.ts b/deals.ts index 8f27ea8..3710ddc 100644 --- a/deals.ts +++ b/deals.ts @@ -5,9 +5,13 @@ import { field } from './utils'; export interface IProduct { name: string; + categoryId?: string; + categoryCode?: string; type?: string; description?: string; sku?: string; + code: string; + customFieldsData?: any; productId?: string; } @@ -16,6 +20,19 @@ export interface IProductDocument extends IProduct, Document { createdAt: Date; } +export interface IProductCategory { + name: string; + code: string; + order: string; + description?: string; + parentId?: string; +} + +export interface IProductCategoryDocument extends IProductCategory, Document { + _id: string; + createdAt: Date; +} + interface IProductData extends Document { productId: string; uom: string; @@ -42,6 +59,8 @@ export interface IDealDocument extends IDeal, Document { export const productSchema = new Schema({ _id: field({ pkey: true }), name: field({ type: String }), + code: field({ type: String, unique: true }), + categoryId: field({ type: String }), type: field({ type: String, enum: PRODUCT_TYPES.ALL, @@ -49,6 +68,22 @@ export const productSchema = new Schema({ }), description: field({ type: String, optional: true }), sku: field({ type: String, optional: true }), // Stock Keeping Unit + customFieldsData: field({ + type: Object, + }), + createdAt: field({ + type: Date, + default: new Date(), + }), +}); + +export const productCategorySchema = new Schema({ + _id: field({ pkey: true }), + name: field({ type: String }), + code: field({ type: String, unique: true }), + order: field({ type: String }), + parentId: field({ type: String, optional: true }), + description: field({ type: String, optional: true }), createdAt: field({ type: Date, default: new Date(), From 192d8128a57f84078f6103aec3e40b0bfe643bdd Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Tue, 24 Sep 2019 15:16:44 +0800 Subject: [PATCH 09/41] use schemaWrapper in product schemas --- deals.ts | 66 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/deals.ts b/deals.ts index 3710ddc..199bfd9 100644 --- a/deals.ts +++ b/deals.ts @@ -1,7 +1,7 @@ import { Document, Schema } from 'mongoose'; import { commonItemFieldsSchema, IItemCommonFields } from './boards'; import { PRODUCT_TYPES } from './constants'; -import { field } from './utils'; +import { field, schemaWrapper } from './utils'; export interface IProduct { name: string; @@ -56,39 +56,43 @@ export interface IDealDocument extends IDeal, Document { // Mongoose schemas ======================= -export const productSchema = new Schema({ - _id: field({ pkey: true }), - name: field({ type: String }), - code: field({ type: String, unique: true }), - categoryId: field({ type: String }), - type: field({ - type: String, - enum: PRODUCT_TYPES.ALL, - default: PRODUCT_TYPES.PRODUCT, +export const productSchema = schemaWrapper( + new Schema({ + _id: field({ pkey: true }), + name: field({ type: String }), + code: field({ type: String, unique: true }), + categoryId: field({ type: String }), + type: field({ + type: String, + enum: PRODUCT_TYPES.ALL, + default: PRODUCT_TYPES.PRODUCT, + }), + description: field({ type: String, optional: true }), + sku: field({ type: String, optional: true }), // Stock Keeping Unit + customFieldsData: field({ + type: Object, + }), + createdAt: field({ + type: Date, + default: new Date(), + }), }), - description: field({ type: String, optional: true }), - sku: field({ type: String, optional: true }), // Stock Keeping Unit - customFieldsData: field({ - type: Object, - }), - createdAt: field({ - type: Date, - default: new Date(), - }), -}); +); -export const productCategorySchema = new Schema({ - _id: field({ pkey: true }), - name: field({ type: String }), - code: field({ type: String, unique: true }), - order: field({ type: String }), - parentId: field({ type: String, optional: true }), - description: field({ type: String, optional: true }), - createdAt: field({ - type: Date, - default: new Date(), +export const productCategorySchema = schemaWrapper( + new Schema({ + _id: field({ pkey: true }), + name: field({ type: String }), + code: field({ type: String, unique: true }), + order: field({ type: String }), + parentId: field({ type: String, optional: true }), + description: field({ type: String, optional: true }), + createdAt: field({ + type: Date, + default: new Date(), + }), }), -}); +); const productDataSchema = new Schema( { From ed88774aca3efa4bd934404280144d24a2ac3ec2 Mon Sep 17 00:00:00 2001 From: Munkh-Orgil Date: Tue, 24 Sep 2019 17:20:41 +0800 Subject: [PATCH 10/41] erxes/erxes#1126 --- constants.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/constants.ts b/constants.ts index 77fabf5..873971c 100644 --- a/constants.ts +++ b/constants.ts @@ -290,7 +290,9 @@ export const PROBABILITY = { NINETY: '90%', WON: 'Won', LOST: 'Lost', - ALL: ['10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', 'Won', 'Lost'], + DONE: 'Done', + RESOLVED: 'Resolved', + ALL: ['10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', 'Won', 'Lost', 'Done', 'Resolved'], }; export const STATUSES = { From c31d6390ee03f36d491609b27069479d14ad1b12 Mon Sep 17 00:00:00 2001 From: munkhsaikhan Date: Tue, 24 Sep 2019 17:21:21 +0800 Subject: [PATCH 11/41] add index on conformities (#561) --- conformities.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conformities.ts b/conformities.ts index 4419575..0b04863 100644 --- a/conformities.ts +++ b/conformities.ts @@ -51,8 +51,8 @@ export interface IConformityDocument extends IConformity, Document { export const conformitySchema = new Schema({ _id: field({ pkey: true }), - mainType: field({ type: String }), + mainType: field({ type: String, index: true }), mainTypeId: field({ type: String }), - relType: field({ type: String }), + relType: field({ type: String, index: true }), relTypeId: field({ type: String }), }); From 8999d9f8e692a1cfbb90ca345812ab079941d406 Mon Sep 17 00:00:00 2001 From: Narmandakh Enkhtuvshin <37796969+Enkhtuvshin0513@users.noreply.github.com> Date: Wed, 25 Sep 2019 14:56:00 +0800 Subject: [PATCH 12/41] add unit price field in product --- deals.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deals.ts b/deals.ts index 199bfd9..547fc7e 100644 --- a/deals.ts +++ b/deals.ts @@ -10,6 +10,7 @@ export interface IProduct { type?: string; description?: string; sku?: string; + unitPrice?: number; code: string; customFieldsData?: any; productId?: string; @@ -69,6 +70,7 @@ export const productSchema = schemaWrapper( }), description: field({ type: String, optional: true }), sku: field({ type: String, optional: true }), // Stock Keeping Unit + unitPrice: field({ type: Number, optional: true }), customFieldsData: field({ type: Object, }), From 2d8885049f4e355778c59c9f1b481780113bc973 Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Fri, 27 Sep 2019 14:53:04 +0800 Subject: [PATCH 13/41] add schemaWrapper in fields schema --- fields.ts | 56 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/fields.ts b/fields.ts index 4f9ae48..7a46c3b 100644 --- a/fields.ts +++ b/fields.ts @@ -1,6 +1,6 @@ import { Document, Schema } from 'mongoose'; import { FIELDS_GROUPS_CONTENT_TYPES } from './constants'; -import { field } from './utils'; +import { field, schemaWrapper } from './utils'; export interface IField { contentType?: string; @@ -37,36 +37,38 @@ export interface IFieldGroupDocument extends IFieldGroup, Document { } // Mongoose schemas ============= -export const fieldSchema = new Schema({ - _id: field({ pkey: true }), +export const fieldSchema = schemaWrapper( + new Schema({ + _id: field({ pkey: true }), - // form, customer, company - contentType: field({ type: String }), + // form, customer, company + contentType: field({ type: String }), - // formId when contentType is form - contentTypeId: field({ type: String }), + // formId when contentType is form + contentTypeId: field({ type: String }), - type: field({ type: String }), - validation: field({ - type: String, - optional: true, - }), - text: field({ type: String }), - description: field({ - type: String, - optional: true, + type: field({ type: String }), + validation: field({ + type: String, + optional: true, + }), + text: field({ type: String }), + description: field({ + type: String, + optional: true, + }), + options: field({ + type: [String], + optional: true, + }), + isRequired: field({ type: Boolean }), + isDefinedByErxes: field({ type: Boolean }), + order: field({ type: Number }), + groupId: field({ type: String }), + isVisible: field({ type: Boolean, default: true }), + lastUpdatedUserId: field({ type: String }), }), - options: field({ - type: [String], - optional: true, - }), - isRequired: field({ type: Boolean }), - isDefinedByErxes: field({ type: Boolean }), - order: field({ type: Number }), - groupId: field({ type: String }), - isVisible: field({ type: Boolean, default: true }), - lastUpdatedUserId: field({ type: String }), -}); +); export const fieldGroupSchema = new Schema({ _id: field({ pkey: true }), From 8f3bd3e4e8e0ce3b436f8715d875a33a5c91472f Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Fri, 27 Sep 2019 15:18:34 +0800 Subject: [PATCH 14/41] add schemaWrapper in fields group schema --- fields.ts | 76 +++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/fields.ts b/fields.ts index 7a46c3b..2421f3a 100644 --- a/fields.ts +++ b/fields.ts @@ -37,50 +37,50 @@ export interface IFieldGroupDocument extends IFieldGroup, Document { } // Mongoose schemas ============= -export const fieldSchema = schemaWrapper( - new Schema({ - _id: field({ pkey: true }), +export const fieldSchema = new Schema({ + _id: field({ pkey: true }), - // form, customer, company - contentType: field({ type: String }), + // form, customer, company + contentType: field({ type: String }), - // formId when contentType is form - contentTypeId: field({ type: String }), + // formId when contentType is form + contentTypeId: field({ type: String }), - type: field({ type: String }), - validation: field({ - type: String, - optional: true, - }), - text: field({ type: String }), - description: field({ - type: String, - optional: true, - }), - options: field({ - type: [String], - optional: true, - }), - isRequired: field({ type: Boolean }), - isDefinedByErxes: field({ type: Boolean }), - order: field({ type: Number }), - groupId: field({ type: String }), - isVisible: field({ type: Boolean, default: true }), - lastUpdatedUserId: field({ type: String }), + type: field({ type: String }), + validation: field({ + type: String, + optional: true, }), -); - -export const fieldGroupSchema = new Schema({ - _id: field({ pkey: true }), - name: field({ type: String }), - // customer, company - contentType: field({ type: String, enum: FIELDS_GROUPS_CONTENT_TYPES.ALL }), - order: field({ type: Number }), - isDefinedByErxes: field({ type: Boolean, default: false }), + text: field({ type: String }), description: field({ type: String, + optional: true, }), - // Id of user who updated the group - lastUpdatedUserId: field({ type: String }), + options: field({ + type: [String], + optional: true, + }), + isRequired: field({ type: Boolean }), + isDefinedByErxes: field({ type: Boolean }), + order: field({ type: Number }), + groupId: field({ type: String }), isVisible: field({ type: Boolean, default: true }), + lastUpdatedUserId: field({ type: String }), }); + +export const fieldGroupSchema = schemaWrapper( + new Schema({ + _id: field({ pkey: true }), + name: field({ type: String }), + // customer, company + contentType: field({ type: String, enum: FIELDS_GROUPS_CONTENT_TYPES.ALL }), + order: field({ type: Number }), + isDefinedByErxes: field({ type: Boolean, default: false }), + description: field({ + type: String, + }), + // Id of user who updated the group + lastUpdatedUserId: field({ type: String }), + isVisible: field({ type: Boolean, default: true }), + }), +); From e14ec45538f4633d2b30eacccbd8251f64efd749 Mon Sep 17 00:00:00 2001 From: Munkhjin Date: Wed, 2 Oct 2019 13:01:52 +0800 Subject: [PATCH 15/41] Growth hack views (#576) Closes #1222 --- constants.ts | 3 ++- growthHacks.ts | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/constants.ts b/constants.ts index 873971c..9670095 100644 --- a/constants.ts +++ b/constants.ts @@ -149,7 +149,8 @@ export const PIPELINE_VISIBLITIES = { export const HACK_SCORING_TYPES = { RICE: 'rice', ICE: 'ice', - ALL: ['rice', 'ice'], + PIE: 'pie', + ALL: ['rice', 'ice', 'pie'], }; export const FIELDS_GROUPS_CONTENT_TYPES = { diff --git a/growthHacks.ts b/growthHacks.ts index bbd1abc..4ee9d15 100644 --- a/growthHacks.ts +++ b/growthHacks.ts @@ -20,8 +20,8 @@ export const growthHackSchema = new Schema({ hackStages: field({ type: [String], optional: true }), priority: field({ type: String, optional: true }), - reach: field({ type: Number, optional: true }), - impact: field({ type: Number, optional: true }), - confidence: field({ type: Number, optional: true }), - ease: field({ type: Number, optional: true }), + reach: field({ type: Number, default: 0, optional: true }), + impact: field({ type: Number, default: 0, optional: true }), + confidence: field({ type: Number, default: 0, optional: true }), + ease: field({ type: Number, default: 0, optional: true }), }); From 1bbb5db99736c17d9b99b6560db972411344c3c5 Mon Sep 17 00:00:00 2001 From: Narmandakh Enkhtuvshin <37796969+Enkhtuvshin0513@users.noreply.github.com> Date: Thu, 3 Oct 2019 16:37:58 +0800 Subject: [PATCH 16/41] Show product custom fields on deal sidebar prodcuts (#579) get customer field data for products resolver of deal --- fields.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fields.ts b/fields.ts index 2421f3a..dd49e89 100644 --- a/fields.ts +++ b/fields.ts @@ -7,7 +7,7 @@ export interface IField { contentTypeId?: string; type?: string; validation?: string; - text?: string; + text: string; description?: string; options?: string[]; isRequired?: boolean; From d22fd4d97bac2025c13ceec18171a3c943ffef86 Mon Sep 17 00:00:00 2001 From: Battulga BatAmar Date: Mon, 7 Oct 2019 21:34:32 -0700 Subject: [PATCH 17/41] change onboarding --- robot.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ users.ts | 2 -- 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 robot.ts diff --git a/robot.ts b/robot.ts new file mode 100644 index 0000000..cb310ce --- /dev/null +++ b/robot.ts @@ -0,0 +1,42 @@ +import { Document, Schema } from 'mongoose'; +import { field } from './utils'; + +// entry ==================== +export interface IRobotEntry { + parentId?: string; + isNotified: boolean; + action: string; + data: object; +} + +export interface IRobotEntryDocument extends IRobotEntry, Document { + _id: string; +} + +export const robotEntrySchema = new Schema({ + _id: field({ pkey: true }), + parentId: field({ type: String, optional: true }), + isNotified: field({ type: Boolean, default: false }), + action: field({ type: String }), + data: field({ type: Object }), +}); + +// onboarding history ==================== +export interface IOnboardingHistory { + userId: string; + totalPoint: number; + isCompleted: boolean; + completedSteps: string[]; +} + +export interface IOnboardingHistoryDocument extends IOnboardingHistory, Document { + _id: string; +} + +export const onboardingHistorySchema = new Schema({ + _id: field({ pkey: true }), + userId: field({ type: String }), + totalPoint: field({ type: Number }), + isCompleted: field({ type: Boolean }), + completedSteps: field({ type: [String] }), +}); diff --git a/users.ts b/users.ts index 78c94a1..0e91d9e 100644 --- a/users.ts +++ b/users.ts @@ -38,7 +38,6 @@ export interface IUser { registrationToken?: string; registrationTokenExpires?: Date; isOwner?: boolean; - hasSeenOnBoard?: boolean; email?: string; getNotificationByEmail?: boolean; emailSignatures?: IEmailSignature[]; @@ -102,7 +101,6 @@ export const userSchema = new Schema({ registrationTokenExpires: field({ type: Date }), resetPasswordExpires: field({ type: Date }), isOwner: field({ type: Boolean }), - hasSeenOnBoard: field({ type: Boolean }), email: field({ type: String, unique: true, From 42fa1455fe339d283b2213e79084b3554bd12bb7 Mon Sep 17 00:00:00 2001 From: Munkhjin Date: Wed, 9 Oct 2019 13:42:18 +0800 Subject: [PATCH 18/41] Growth hack vote (#588) Closes erxes/erxes#1302 --- growthHacks.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/growthHacks.ts b/growthHacks.ts index 4ee9d15..58c5ac6 100644 --- a/growthHacks.ts +++ b/growthHacks.ts @@ -3,6 +3,9 @@ import { commonItemFieldsSchema, IItemCommonFields } from './boards'; import { field } from './utils'; export interface IGrowthHack extends IItemCommonFields { + voteCount?: number; + votedUserIds?: string[]; + hackStages?: string; priority?: string; reach?: number; @@ -18,6 +21,9 @@ export interface IGrowthHackDocument extends IGrowthHack, Document { export const growthHackSchema = new Schema({ ...commonItemFieldsSchema, + voteCount: field({ type: Number, default: 0, optional: true }), + votedUserIds: field({ type: [String], optional: true }), + hackStages: field({ type: [String], optional: true }), priority: field({ type: String, optional: true }), reach: field({ type: Number, default: 0, optional: true }), From fa399d22a4ad3e671dd1b797dd3c011bb8a73ed8 Mon Sep 17 00:00:00 2001 From: munkhjin Date: Wed, 9 Oct 2019 18:56:01 +0800 Subject: [PATCH 19/41] fix growth hack notification types --- constants.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/constants.ts b/constants.ts index 9670095..c26ea33 100644 --- a/constants.ts +++ b/constants.ts @@ -322,12 +322,12 @@ export const NOTIFICATION_TYPES = { DEAL_CHANGE: 'dealChange', DEAL_DUE_DATE: 'dealDueDate', DEAL_DELETE: 'dealDelete', - GROWTH_HACK_ADD: 'growthHackAdd', - GROWTH_HACK_REMOVE_ASSIGN: 'growthHackRemoveAssign', - GROWTH_HACK_EDIT: 'growthHackEdit', - GROWTH_HACK_CHANGE: 'growthHackChange', - GROWTH_HACK_DUE_DATE: 'growthHackDueDate', - GROWTH_HACK_DELETE: 'growthHackDelete', + GROWTHHACK_ADD: 'growthHackAdd', + GROWTHHACK_REMOVE_ASSIGN: 'growthHackRemoveAssign', + GROWTHHACK_EDIT: 'growthHackEdit', + GROWTHHACK_CHANGE: 'growthHackChange', + GROWTHHACK_DUE_DATE: 'growthHackDueDate', + GROWTHHACK_DELETE: 'growthHackDelete', TICKET_ADD: 'ticketAdd', TICKET_REMOVE_ASSIGN: 'ticketRemoveAssign', TICKET_EDIT: 'ticketEdit', From d71e6bb9253599255664ff4605c88b7f091e7fc2 Mon Sep 17 00:00:00 2001 From: Munkh-Orgil Date: Thu, 10 Oct 2019 11:44:30 +0800 Subject: [PATCH 20/41] erxes/erxes-integrations#25 --- constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/constants.ts b/constants.ts index c26ea33..cbdd4c0 100644 --- a/constants.ts +++ b/constants.ts @@ -57,8 +57,9 @@ export const KIND_CHOICES = { FACEBOOK_MESSENGER: 'facebook-messenger', FACEBOOK_POST: 'facebook-post', GMAIL: 'gmail', + NYLAS_GMAIL: 'nylas-gmail', CALLPRO: 'callpro', - ALL: ['messenger', 'lead', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro'], + ALL: ['messenger', 'lead', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro', 'nylas-gmail'], }; // messenger data availability constants From 896cb776dbbaafe5d6a5073402d89171b14e20d5 Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Thu, 10 Oct 2019 01:04:33 -0700 Subject: [PATCH 21/41] change lead steps in onboard --- integrations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integrations.ts b/integrations.ts index 1fcad46..61c0f5c 100644 --- a/integrations.ts +++ b/integrations.ts @@ -102,6 +102,7 @@ export interface IIntegration { export interface IIntegrationDocument extends IIntegration, Document { _id: string; + createdUserId: string; // TODO: remove formData?: ILeadData; messengerData?: IMessengerDataDocument; @@ -252,6 +253,7 @@ const uiOptionsSchema = new Schema( // schema for integration document export const integrationSchema = new Schema({ _id: field({ pkey: true }), + createdUserId: field({ type: String }), kind: field({ type: String, From 308ea717912e227abb54a1efb802975e8f8fbddf Mon Sep 17 00:00:00 2001 From: munkhjin Date: Sat, 12 Oct 2019 18:30:58 +0800 Subject: [PATCH 22/41] update --- constants.ts | 3 ++- deals.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/constants.ts b/constants.ts index cbdd4c0..3caeb91 100644 --- a/constants.ts +++ b/constants.ts @@ -11,7 +11,8 @@ export const TAG_TYPES = { ENGAGE_MESSAGE: 'engageMessage', COMPANY: 'company', INTEGRATION: 'integration', - ALL: ['conversation', 'customer', 'engageMessage', 'company', 'integration'], + PRODUCT: 'product', + ALL: ['conversation', 'customer', 'engageMessage', 'company', 'integration', 'product'], }; export const MESSENGER_KINDS = { diff --git a/deals.ts b/deals.ts index 547fc7e..54f36bc 100644 --- a/deals.ts +++ b/deals.ts @@ -14,6 +14,7 @@ export interface IProduct { code: string; customFieldsData?: any; productId?: string; + tagIds?: string[]; } export interface IProductDocument extends IProduct, Document { @@ -68,6 +69,7 @@ export const productSchema = schemaWrapper( enum: PRODUCT_TYPES.ALL, default: PRODUCT_TYPES.PRODUCT, }), + tagIds: field({ type: [String], optional: true }), description: field({ type: String, optional: true }), sku: field({ type: String, optional: true }), // Stock Keeping Unit unitPrice: field({ type: Number, optional: true }), From a765bab159c4610e7e0f8f9ea5b53fd9e0163d50 Mon Sep 17 00:00:00 2001 From: Buyantogtokh Date: Mon, 14 Oct 2019 14:44:41 +0800 Subject: [PATCH 23/41] add industry type to company const (#595) --- constants.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/constants.ts b/constants.ts index cbdd4c0..3adb7f9 100644 --- a/constants.ts +++ b/constants.ts @@ -252,6 +252,7 @@ export const COMPANY_INDUSTRY_TYPES = [ 'Finance, Insurance & Real Estate', 'Food & Beverage', 'Foundations, Philanthropists & Non-Profits', + 'Government Organization', 'Health', 'Hotels, Motels & Tourism', 'Insurance', From 1bc159b2f9ea11de6211e7a0d97527dcffee1e4b Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Thu, 17 Oct 2019 12:29:11 +0800 Subject: [PATCH 24/41] erxes/erxes#1358 --- constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/constants.ts b/constants.ts index 3adb7f9..b41b42b 100644 --- a/constants.ts +++ b/constants.ts @@ -59,7 +59,8 @@ export const KIND_CHOICES = { GMAIL: 'gmail', NYLAS_GMAIL: 'nylas-gmail', CALLPRO: 'callpro', - ALL: ['messenger', 'lead', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro', 'nylas-gmail'], + CHATFUEL: 'chatfuel', + ALL: ['messenger', 'lead', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro', 'chatfuel', 'nylas-gmail'], }; // messenger data availability constants From 277ee2a23386f578dc4d3d2ad1a6cdb8c89e595b Mon Sep 17 00:00:00 2001 From: Munkh-Orgil Date: Sat, 19 Oct 2019 16:47:42 +0800 Subject: [PATCH 25/41] erxes/erxes#1367 --- constants.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/constants.ts b/constants.ts index 42cf8ac..77b6141 100644 --- a/constants.ts +++ b/constants.ts @@ -59,9 +59,20 @@ export const KIND_CHOICES = { FACEBOOK_POST: 'facebook-post', GMAIL: 'gmail', NYLAS_GMAIL: 'nylas-gmail', + NYLAS_imap: 'nylas-imap', CALLPRO: 'callpro', CHATFUEL: 'chatfuel', - ALL: ['messenger', 'lead', 'facebook-messenger', 'facebook-post', 'gmail', 'callpro', 'chatfuel', 'nylas-gmail'], + ALL: [ + 'messenger', + 'lead', + 'facebook-messenger', + 'facebook-post', + 'gmail', + 'callpro', + 'chatfuel', + 'nylas-gmail', + 'nylas-imap', + ], }; // messenger data availability constants From 824e0b7044c6fcd605413c3e1ae4ae0b466357b0 Mon Sep 17 00:00:00 2001 From: Khangarid Bayarsaikhan <32699094+khangaridb@users.noreply.github.com> Date: Mon, 21 Oct 2019 16:01:37 +0800 Subject: [PATCH 26/41] erxes/erxes#1127 --- constants.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/constants.ts b/constants.ts index 77b6141..87fcda1 100644 --- a/constants.ts +++ b/constants.ts @@ -61,6 +61,7 @@ export const KIND_CHOICES = { NYLAS_GMAIL: 'nylas-gmail', NYLAS_imap: 'nylas-imap', CALLPRO: 'callpro', + TWITTER_DM: 'twitter-dm', CHATFUEL: 'chatfuel', ALL: [ 'messenger', @@ -72,6 +73,7 @@ export const KIND_CHOICES = { 'chatfuel', 'nylas-gmail', 'nylas-imap', + 'twitter-dm', ], }; From 8d8863f11520a0114acf2edb0ca21b15e538a67d Mon Sep 17 00:00:00 2001 From: munkhsaikhan Date: Tue, 22 Oct 2019 12:48:18 +0800 Subject: [PATCH 27/41] fix(deal): fixed search close #1251 --- boards.ts | 2 ++ companies.ts | 2 ++ customers.ts | 2 ++ integrations.ts | 3 ++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/boards.ts b/boards.ts index 30529a1..d8ee2fe 100644 --- a/boards.ts +++ b/boards.ts @@ -27,6 +27,7 @@ export interface IItemCommonFields { userId?: string; createdAt?: Date; order?: number; + searchText?: string; } export interface IBoard extends ICommonFields { @@ -123,6 +124,7 @@ export const commonItemFieldsSchema = { default: new Date(), }), modifiedBy: field({ type: String }), + searchText: field({ type: String, optional: true, index: true }), }; export const boardSchema = schemaWrapper( diff --git a/companies.ts b/companies.ts index 7501c12..2ce6ea5 100644 --- a/companies.ts +++ b/companies.ts @@ -59,6 +59,7 @@ export interface ICompanyDocument extends ICompany, Document { status?: string; createdAt: Date; modifiedAt: Date; + searchText: string; } const linkSchema = new Schema( @@ -183,5 +184,6 @@ export const companySchema = schemaWrapper( customFieldsData: field({ type: Object, }), + searchText: field({ type: String, optional: true, index: true }), }), ); diff --git a/customers.ts b/customers.ts index 6f397ed..1a39984 100644 --- a/customers.ts +++ b/customers.ts @@ -89,6 +89,7 @@ export interface ICustomerDocument extends ICustomer, Document { createdAt: Date; modifiedAt: Date; deviceTokens?: string[]; + searchText?: string; } /* location schema */ @@ -228,5 +229,6 @@ export const customerSchema = schemaWrapper( urlVisits: Object, deviceTokens: field({ type: [String], default: [] }), + searchText: field({ type: String, optional: true, index: true }), }), ); diff --git a/integrations.ts b/integrations.ts index 61c0f5c..480aeb6 100644 --- a/integrations.ts +++ b/integrations.ts @@ -103,8 +103,9 @@ export interface IIntegration { export interface IIntegrationDocument extends IIntegration, Document { _id: string; createdUserId: string; - // TODO: remove + // TODO remove formData?: ILeadData; + leadData?: ILeadDataDocument; messengerData?: IMessengerDataDocument; uiOptions?: IUiOptionsDocument; } From 31e3f8777b5c1cb55956bccc7f2bc6db2413f005 Mon Sep 17 00:00:00 2001 From: Daarii Date: Thu, 24 Oct 2019 15:52:39 +0800 Subject: [PATCH 28/41] Check list (#600) feat(checklist) add checklist Closes erxes/erxes#1066 --- checklists.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ constants.ts | 2 ++ 2 files changed, 52 insertions(+) create mode 100644 checklists.ts diff --git a/checklists.ts b/checklists.ts new file mode 100644 index 0000000..0de2de6 --- /dev/null +++ b/checklists.ts @@ -0,0 +1,50 @@ +import { Document, Schema } from 'mongoose'; +import { ACTIVITY_CONTENT_TYPES } from './constants'; +import { field } from './utils'; + +export interface IChecklist { + contentType: string; + contentTypeId: string; + title: string; +} + +export interface IChecklistDocument extends IChecklist, Document { + _id: string; + createdUserId: string; + createdDate: Date; +} + +export interface IChecklistItem { + checklistId: string; + content: string; + isChecked: boolean; +} + +export interface IChecklistItemDocument extends IChecklistItem, Document { + _id: string; + createdUserId: string; + createdDate: Date; +} + +// Mongoose schemas ======================= + +export const checklistSchema = new Schema({ + _id: field({ pkey: true }), + contentType: field({ + type: String, + enum: ACTIVITY_CONTENT_TYPES.ALL, + }), + contentTypeId: field({ type: String }), + title: field({ type: String }), + createdUserId: field({ type: String }), + createdDate: field({ type: Date }), +}); + +export const checklistItemSchema = new Schema({ + _id: field({ pkey: true }), + checklistId: field({ type: String }), + content: field({ type: String }), + isChecked: field({ type: Boolean }), + createdUserId: field({ type: String }), + createdDate: field({ type: Date }), +}); diff --git a/constants.ts b/constants.ts index 87fcda1..95d264e 100644 --- a/constants.ts +++ b/constants.ts @@ -107,6 +107,7 @@ export const ACTIVITY_TYPES = { CUSTOMER: 'customer', COMPANY: 'company', INTERNAL_NOTE: 'internal_note', + CHECKLIST: 'checklist', CONVERSATION: 'conversation', SEGMENT: 'segment', DEAL: 'deal', @@ -120,6 +121,7 @@ export const ACTIVITY_TYPES = { 'customer', 'company', 'internal_note', + 'checklist', 'conversation', 'segment', 'deal', From aab18e699e4d6385d0f19a51ca1e23ab476bebde Mon Sep 17 00:00:00 2001 From: munkhjin Date: Fri, 25 Oct 2019 19:16:03 +0800 Subject: [PATCH 29/41] feat(deal/task/ticket) add label Close erxes/erxes#1288 --- boards.ts | 2 ++ pipelineLabels.ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 pipelineLabels.ts diff --git a/boards.ts b/boards.ts index d8ee2fe..c5d2133 100644 --- a/boards.ts +++ b/boards.ts @@ -19,6 +19,7 @@ export interface IItemCommonFields { assignedUserIds?: string[]; watchedUserIds?: string[]; notifiedUserIds?: string[]; + labelIds?: string[]; attachments?: any[]; stageId?: string; initialStageId?: string; @@ -116,6 +117,7 @@ export const commonItemFieldsSchema = { description: field({ type: String, optional: true }), assignedUserIds: field({ type: [String] }), watchedUserIds: field({ type: [String] }), + labelIds: field({ type: [String] }), attachments: field({ type: [attachmentSchema] }), stageId: field({ type: String }), initialStageId: field({ type: String, optional: true }), diff --git a/pipelineLabels.ts b/pipelineLabels.ts new file mode 100644 index 0000000..36b6355 --- /dev/null +++ b/pipelineLabels.ts @@ -0,0 +1,33 @@ +import { Document, Schema } from 'mongoose'; +import { BOARD_TYPES } from './constants'; +import { field } from './utils'; + +export interface IPipelineLabel { + name: string; + type: string; + colorCode: string; + pipelineId: string; + createdBy?: string; + createdDate?: Date; +} + +export interface IPipelineLabelDocument extends IPipelineLabel, Document { + _id: string; +} + +export const pipelineLabelSchema = new Schema({ + _id: field({ pkey: true }), + + name: field({ type: String }), + type: field({ + type: String, + enum: BOARD_TYPES.ALL, + }), + colorCode: field({ type: String }), + pipelineId: field({ type: String }), + createdBy: field({ type: String }), + createdAt: field({ + type: Date, + default: new Date(), + }), +}); From 81e4616b1dd285055ee7883df872af8f570cd8ac Mon Sep 17 00:00:00 2001 From: Munkh-Orgil Date: Mon, 28 Oct 2019 15:33:31 +0800 Subject: [PATCH 30/41] erxes/erxes-integrations#41 --- constants.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/constants.ts b/constants.ts index 95d264e..5a495ea 100644 --- a/constants.ts +++ b/constants.ts @@ -59,7 +59,8 @@ export const KIND_CHOICES = { FACEBOOK_POST: 'facebook-post', GMAIL: 'gmail', NYLAS_GMAIL: 'nylas-gmail', - NYLAS_imap: 'nylas-imap', + NYLAS_IMAP: 'nylas-imap', + NYLAS_OFFICE365: 'nylas-office365', CALLPRO: 'callpro', TWITTER_DM: 'twitter-dm', CHATFUEL: 'chatfuel', @@ -73,6 +74,7 @@ export const KIND_CHOICES = { 'chatfuel', 'nylas-gmail', 'nylas-imap', + 'nylas-office365', 'twitter-dm', ], }; From cadcf32e6a9d0a3f89469f6764d1337f81a588a0 Mon Sep 17 00:00:00 2001 From: munkhjin Date: Tue, 29 Oct 2019 18:58:00 +0800 Subject: [PATCH 31/41] remove type field from pipeline label --- pipelineLabels.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pipelineLabels.ts b/pipelineLabels.ts index 36b6355..00c878d 100644 --- a/pipelineLabels.ts +++ b/pipelineLabels.ts @@ -1,10 +1,8 @@ import { Document, Schema } from 'mongoose'; -import { BOARD_TYPES } from './constants'; import { field } from './utils'; export interface IPipelineLabel { name: string; - type: string; colorCode: string; pipelineId: string; createdBy?: string; @@ -19,10 +17,6 @@ export const pipelineLabelSchema = new Schema({ _id: field({ pkey: true }), name: field({ type: String }), - type: field({ - type: String, - enum: BOARD_TYPES.ALL, - }), colorCode: field({ type: String }), pipelineId: field({ type: String }), createdBy: field({ type: String }), From 5f2522d3d21d65587dc06a2fb927397e724bf878 Mon Sep 17 00:00:00 2001 From: Munkh-Orgil Date: Thu, 31 Oct 2019 13:09:19 +0800 Subject: [PATCH 32/41] erxes/erxes-integrations#47 --- constants.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/constants.ts b/constants.ts index 5a495ea..7fb584d 100644 --- a/constants.ts +++ b/constants.ts @@ -61,6 +61,7 @@ export const KIND_CHOICES = { NYLAS_GMAIL: 'nylas-gmail', NYLAS_IMAP: 'nylas-imap', NYLAS_OFFICE365: 'nylas-office365', + NYLAS_OUTLOOK: 'nylas-outlook', CALLPRO: 'callpro', TWITTER_DM: 'twitter-dm', CHATFUEL: 'chatfuel', @@ -75,6 +76,7 @@ export const KIND_CHOICES = { 'nylas-gmail', 'nylas-imap', 'nylas-office365', + 'nylas-outlook', 'twitter-dm', ], }; From 48bfa0feae8eeeae8970a583943a716cc3fe3fa7 Mon Sep 17 00:00:00 2001 From: Munkh-Orgil Date: Thu, 31 Oct 2019 15:10:51 +0800 Subject: [PATCH 33/41] erxes/erxes-integrations#48 --- constants.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/constants.ts b/constants.ts index 7fb584d..9ce00be 100644 --- a/constants.ts +++ b/constants.ts @@ -62,6 +62,7 @@ export const KIND_CHOICES = { NYLAS_IMAP: 'nylas-imap', NYLAS_OFFICE365: 'nylas-office365', NYLAS_OUTLOOK: 'nylas-outlook', + NYLAS_YAHOO: 'nylas-yahoo', CALLPRO: 'callpro', TWITTER_DM: 'twitter-dm', CHATFUEL: 'chatfuel', @@ -77,6 +78,7 @@ export const KIND_CHOICES = { 'nylas-imap', 'nylas-office365', 'nylas-outlook', + 'nylas-yahoo', 'twitter-dm', ], }; From f6f6f1d724711c314aaffaa3f08a2fd26b62677f Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Mon, 11 Nov 2019 19:33:49 +0800 Subject: [PATCH 34/41] use integration name in integrationsGetUsedTypes --- constants.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/constants.ts b/constants.ts index 9ce00be..de7fbb8 100644 --- a/constants.ts +++ b/constants.ts @@ -83,6 +83,22 @@ export const KIND_CHOICES = { ], }; +export const INTEGRATION_NAMES_MAP = { + messenger: 'Web messenger', + lead: 'Lead', + 'facebook-messenger': 'Facebook messenger', + 'facebook-post': 'Facebook post', + gmail: 'Gmail', + callpro: 'Call pro', + chatfuel: 'Chatfuel', + 'nylas-gmail': 'Gmail', + 'nylas-imap': 'Imap', + 'nylas-office365': 'Office 365', + 'nylas-outlook': 'Outook', + 'nylas-yahoo': 'Yahoo', + 'twitter-dm': 'Twitter dm', +}; + // messenger data availability constants export const MESSENGER_DATA_AVAILABILITY = { MANUAL: 'manual', From 30c1c614fbb5058895be2397ff0cee426e730c44 Mon Sep 17 00:00:00 2001 From: munkhjin Date: Thu, 14 Nov 2019 15:06:09 +0800 Subject: [PATCH 35/41] add priority for deal and fix growth hack filter --- boards.ts | 2 ++ growthHacks.ts | 2 -- tasks.ts | 9 +-------- tickets.ts | 2 -- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/boards.ts b/boards.ts index c5d2133..db7d1bf 100644 --- a/boards.ts +++ b/boards.ts @@ -29,6 +29,7 @@ export interface IItemCommonFields { createdAt?: Date; order?: number; searchText?: string; + priority?: string; } export interface IBoard extends ICommonFields { @@ -127,6 +128,7 @@ export const commonItemFieldsSchema = { }), modifiedBy: field({ type: String }), searchText: field({ type: String, optional: true, index: true }), + priority: field({ type: String, optional: true }), }; export const boardSchema = schemaWrapper( diff --git a/growthHacks.ts b/growthHacks.ts index 58c5ac6..1e190af 100644 --- a/growthHacks.ts +++ b/growthHacks.ts @@ -7,7 +7,6 @@ export interface IGrowthHack extends IItemCommonFields { votedUserIds?: string[]; hackStages?: string; - priority?: string; reach?: number; impact?: number; confidence?: number; @@ -25,7 +24,6 @@ export const growthHackSchema = new Schema({ votedUserIds: field({ type: [String], optional: true }), hackStages: field({ type: [String], optional: true }), - priority: field({ type: String, optional: true }), reach: field({ type: Number, default: 0, optional: true }), impact: field({ type: Number, default: 0, optional: true }), confidence: field({ type: Number, default: 0, optional: true }), diff --git a/tasks.ts b/tasks.ts index 1f4d866..081d812 100644 --- a/tasks.ts +++ b/tasks.ts @@ -1,18 +1,11 @@ import { Document, Schema } from 'mongoose'; import { commonItemFieldsSchema, IItemCommonFields } from './boards'; -import { field } from './utils'; -export interface ITask extends IItemCommonFields { - priority?: string; -} - -export interface ITaskDocument extends ITask, Document { +export interface ITaskDocument extends IItemCommonFields, Document { _id: string; } // Mongoose schemas ======================= export const taskSchema = new Schema({ ...commonItemFieldsSchema, - - priority: field({ type: String, optional: true }), }); diff --git a/tickets.ts b/tickets.ts index 1f26d5a..a3f0d8c 100644 --- a/tickets.ts +++ b/tickets.ts @@ -3,7 +3,6 @@ import { commonItemFieldsSchema, IItemCommonFields } from './boards'; import { field } from './utils'; export interface ITicket extends IItemCommonFields { - priority?: string; source?: string; } @@ -15,6 +14,5 @@ export interface ITicketDocument extends ITicket, Document { export const ticketSchema = new Schema({ ...commonItemFieldsSchema, - priority: field({ type: String }), source: field({ type: String }), }); From 149c367e9ad44e76ed306f1840b1be3c945a4746 Mon Sep 17 00:00:00 2001 From: Buyantogtokh Date: Thu, 14 Nov 2019 19:42:16 +0800 Subject: [PATCH 36/41] feat(integration): archive close #624 --- integrations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integrations.ts b/integrations.ts index 480aeb6..7025163 100644 --- a/integrations.ts +++ b/integrations.ts @@ -98,6 +98,7 @@ export interface IIntegration { leadData?: ILeadData; messengerData?: IMessengerData; uiOptions?: IUiOptions; + isArchived?: boolean; } export interface IIntegrationDocument extends IIntegration, Document { @@ -275,4 +276,5 @@ export const integrationSchema = new Schema({ formData: field({ type: leadDataSchema }), messengerData: field({ type: messengerDataSchema }), uiOptions: field({ type: uiOptionsSchema }), + isActive: field({ type: Boolean, optional: true, default: true }), }); From f4e64ad2d30154d12ae0f4ae8a973a9bec46f44f Mon Sep 17 00:00:00 2001 From: munkhsaikhan Date: Fri, 15 Nov 2019 18:37:18 +0800 Subject: [PATCH 37/41] erxes/erxes#1428 --- boards.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boards.ts b/boards.ts index db7d1bf..e207021 100644 --- a/boards.ts +++ b/boards.ts @@ -47,12 +47,14 @@ export interface IPipeline extends ICommonFields { memberIds?: string[]; bgColor?: string; watchedUserIds?: string[]; - // growth hack + startDate?: Date; endDate?: Date; metric?: string; hackScoringType?: string; templateId?: string; + isCheckUser?: boolean; + excludeCheckUserIds?: string[]; } export interface IPipelineDocument extends IPipeline, Document { @@ -160,6 +162,8 @@ export const pipelineSchema = new Schema({ enum: HACK_SCORING_TYPES.ALL, }), templateId: field({ type: String, optional: true }), + isCheckUser: field({ type: Boolean, optional: true }), + excludeCheckUserIds: field({ type: [String], optional: true }), ...commonFieldsSchema, }); From 40e52d80f1e1d556145d82dd0efeed27d47081c1 Mon Sep 17 00:00:00 2001 From: Buyantogtokh Date: Tue, 19 Nov 2019 22:18:32 +0800 Subject: [PATCH 38/41] feat(customers): added code field close #631 --- customers.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/customers.ts b/customers.ts index 1a39984..2aea5c9 100644 --- a/customers.ts +++ b/customers.ts @@ -76,6 +76,7 @@ export interface ICustomer { visitorContactInfo?: IVisitorContact; urlVisits?: any; deviceTokens?: string[]; + code?: string; } export interface ICustomerDocument extends ICustomer, Document { @@ -230,5 +231,6 @@ export const customerSchema = schemaWrapper( deviceTokens: field({ type: [String], default: [] }), searchText: field({ type: String, optional: true, index: true }), + code: field({ type: String, label: 'Code', optional: true }), }), ); From 2dba7ff8a0509c378f6e0c8889a4c28836ec4638 Mon Sep 17 00:00:00 2001 From: Buyantogtokh Date: Tue, 19 Nov 2019 22:19:07 +0800 Subject: [PATCH 39/41] erxes/erxes-api#631 --- src/data/resolvers/mutations/messenger.ts | 6 ++++- src/data/schema.ts | 1 + src/db/factories.ts | 1 + src/db/models/Customers.ts | 32 ++++++++++++++++------- src/db/models/definitions/customers.ts | 2 ++ 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/data/resolvers/mutations/messenger.ts b/src/data/resolvers/mutations/messenger.ts index 743cb6d..eedfb84 100644 --- a/src/data/resolvers/mutations/messenger.ts +++ b/src/data/resolvers/mutations/messenger.ts @@ -16,6 +16,7 @@ export default { brandCode: string; email?: string; phone?: string; + code?: string; isUser?: boolean; companyData?: any; data?: any; @@ -23,7 +24,7 @@ export default { deviceToken?: string; }, ) { - const { brandCode, email, phone, isUser, companyData, data, cachedCustomerId, deviceToken } = args; + const { brandCode, email, phone, code, isUser, companyData, data, cachedCustomerId, deviceToken } = args; const customData = data; @@ -41,6 +42,7 @@ export default { cachedCustomerId, email, phone, + code, }); if (customer) { @@ -50,6 +52,7 @@ export default { doc: { email, phone, + code, isUser, deviceToken, }, @@ -63,6 +66,7 @@ export default { integrationId: integration._id, email, phone, + code, isUser, deviceToken, }, diff --git a/src/data/schema.ts b/src/data/schema.ts index 1a0cbce..a8a6d5c 100755 --- a/src/data/schema.ts +++ b/src/data/schema.ts @@ -242,6 +242,7 @@ export const mutations = ` brandCode: String! email: String phone: String + code: String isUser: Boolean companyData: JSON diff --git a/src/db/factories.ts b/src/db/factories.ts index 7544277..f16fd68 100644 --- a/src/db/factories.ts +++ b/src/db/factories.ts @@ -141,6 +141,7 @@ export function customerFactory(params: ICustomerParams = {}) { }, urlVisits: params.urlVisits, deviceTokens: params.deviceToken || [], + code: faker.random.word(), }); return customer.save(); diff --git a/src/db/models/Customers.ts b/src/db/models/Customers.ts index 4e81e6c..8ff31df 100644 --- a/src/db/models/Customers.ts +++ b/src/db/models/Customers.ts @@ -6,6 +6,7 @@ import Integrations from './Integrations'; interface IGetCustomerParams { email?: string; phone?: string; + code?: string; cachedCustomerId?: string; } @@ -14,6 +15,7 @@ interface ICreateCustomerParams { email?: string; hasValidEmail?: boolean; phone?: string; + code?: string; isUser?: boolean; firstName?: string; lastName?: string; @@ -27,6 +29,7 @@ export interface IUpdateMessengerCustomerParams { doc: { email?: string; phone?: string; + code?: string; isUser?: boolean; deviceToken?: string; }; @@ -131,12 +134,15 @@ export const loadClass = () => { if (!nullValues.includes(customer.primaryEmail || '')) { score += 15; - searchText = searchText.concat(' ', customer.primaryEmail); } if (!nullValues.includes(customer.primaryPhone || '')) { score += 10; - searchText = searchText.concat(' ', customer.primaryPhone); + } + + if (!nullValues.includes(customer.code || '')) { + score += 10; + searchText = searchText.concat(' ', customer.code); } if (customer.visitorContactInfo != null) { @@ -164,26 +170,32 @@ export const loadClass = () => { /* * Get customer */ - public static getCustomer(params: IGetCustomerParams) { - const { email, phone, cachedCustomerId } = params; + public static async getCustomer(params: IGetCustomerParams) { + const { email, phone, code, cachedCustomerId } = params; + + let customer: ICustomerDocument; if (email) { - return Customers.findOne({ + customer = await Customers.findOne({ $or: [{ emails: { $in: [email] } }, { primaryEmail: email }], }); } - if (phone) { - return Customers.findOne({ + if (!customer && phone) { + customer = await Customers.findOne({ $or: [{ phones: { $in: [phone] } }, { primaryPhone: phone }], }); } - if (cachedCustomerId) { - return Customers.findOne({ _id: cachedCustomerId }); + if (!customer && code) { + customer = await Customers.findOne({ code }); + } + + if (!customer && cachedCustomerId) { + customer = await Customers.findOne({ _id: cachedCustomerId }); } - return null; + return customer; } /* diff --git a/src/db/models/definitions/customers.ts b/src/db/models/definitions/customers.ts index 1a39984..e407213 100644 --- a/src/db/models/definitions/customers.ts +++ b/src/db/models/definitions/customers.ts @@ -76,6 +76,7 @@ export interface ICustomer { visitorContactInfo?: IVisitorContact; urlVisits?: any; deviceTokens?: string[]; + code?: string; } export interface ICustomerDocument extends ICustomer, Document { @@ -230,5 +231,6 @@ export const customerSchema = schemaWrapper( deviceTokens: field({ type: [String], default: [] }), searchText: field({ type: String, optional: true, index: true }), + code: field({ type: String, label: 'Code', unique: true }), }), ); From b297f559946d40aad9f265d3450d0dff8be316e6 Mon Sep 17 00:00:00 2001 From: Buyantogtokh Date: Wed, 20 Nov 2019 20:17:34 +0800 Subject: [PATCH 40/41] fix isArchived field in integration type --- integrations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations.ts b/integrations.ts index 7025163..c933b7f 100644 --- a/integrations.ts +++ b/integrations.ts @@ -98,7 +98,7 @@ export interface IIntegration { leadData?: ILeadData; messengerData?: IMessengerData; uiOptions?: IUiOptions; - isArchived?: boolean; + isActive?: boolean; } export interface IIntegrationDocument extends IIntegration, Document { From 467d074117227635ef82158523d75b30ed3527fc Mon Sep 17 00:00:00 2001 From: BatAmar Battulga Date: Fri, 29 Nov 2019 15:42:49 +0800 Subject: [PATCH 41/41] fix conversation content max length --- package.json | 1 + src/data/resolvers/mutations/messenger.ts | 8 ++++++-- yarn.lock | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1c50742..58e82c0 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "nodemailer": "^4.0.1", "q": "^1.5.1", "snyk": "^1.239.5", + "strip": "^3.0.0", "underscore": "^1.8.3", "validator": "^10.9.0" }, diff --git a/src/data/resolvers/mutations/messenger.ts b/src/data/resolvers/mutations/messenger.ts index eedfb84..5b9be6f 100644 --- a/src/data/resolvers/mutations/messenger.ts +++ b/src/data/resolvers/mutations/messenger.ts @@ -1,3 +1,5 @@ +import * as strip from 'strip'; + import { Brands, Companies, Conversations, Customers, Integrations, Messages } from '../../../db/models'; import { IBrowserInfo, IVisitorContactInfoParams } from '../../../db/models/Customers'; @@ -112,12 +114,14 @@ export default { ) { const { integrationId, customerId, conversationId, message, attachments } = args; + const conversationContent = strip(message || '').substring(0, 100); + // get or create conversation const conversation = await Conversations.getOrCreateConversation({ conversationId, integrationId, customerId, - content: message, + content: conversationContent, }); // create message @@ -136,7 +140,7 @@ export default { status: Conversations.getConversationStatuses().OPEN, // setting conversation's content to last message - content: message, + content: conversationContent, // Mark as unread readUserIds: [], diff --git a/yarn.lock b/yarn.lock index 684579a..e24bcd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7878,6 +7878,11 @@ strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip/-/strip-3.0.0.tgz#750fc933152a7d35af0b7420e651789b914cc35e" + integrity sha1-dQ/JMxUqfTWvC3Qg5lF4m5FMw14= + subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2"