From 7f727a398109c1a9b542bc76b680a654675241d0 Mon Sep 17 00:00:00 2001
From: Tuguldur Ch
Date: Mon, 2 Oct 2023 14:16:02 +0800
Subject: [PATCH 01/64] update(exm):add ability segmentation
---
.../plugin-exmfeed-api/src/automations.ts | 22 +++++++
packages/plugin-exmfeed-api/src/configs.ts | 6 +-
packages/plugin-exmfeed-api/src/essyncer.js | 12 ++++
packages/plugin-exmfeed-api/src/forms.ts | 59 +++++++++++++++++
packages/plugin-exmfeed-api/src/segments.ts | 64 +++++++++++++++++++
packages/plugin-imap-ui/src/configs.js | 54 ++++++++--------
packages/plugin-reactions-api/src/configs.ts | 4 +-
packages/plugin-reactions-api/src/essyncer.js | 12 ++++
packages/plugin-reactions-api/src/forms.ts | 59 +++++++++++++++++
packages/plugin-reactions-api/src/segments.ts | 18 ++++++
10 files changed, 281 insertions(+), 29 deletions(-)
create mode 100644 packages/plugin-exmfeed-api/src/automations.ts
create mode 100644 packages/plugin-exmfeed-api/src/essyncer.js
create mode 100644 packages/plugin-exmfeed-api/src/forms.ts
create mode 100644 packages/plugin-exmfeed-api/src/segments.ts
create mode 100644 packages/plugin-reactions-api/src/essyncer.js
create mode 100644 packages/plugin-reactions-api/src/forms.ts
create mode 100644 packages/plugin-reactions-api/src/segments.ts
diff --git a/packages/plugin-exmfeed-api/src/automations.ts b/packages/plugin-exmfeed-api/src/automations.ts
new file mode 100644
index 0000000000..f3725629a0
--- /dev/null
+++ b/packages/plugin-exmfeed-api/src/automations.ts
@@ -0,0 +1,22 @@
+export default {
+ constants: {
+ triggers: [
+ {
+ type: 'exmfeed:feeds',
+ img: 'automation3.svg',
+ icon: 'file-plus-alt',
+ label: 'Exm Feed',
+ description:
+ 'Start with a blank workflow that enralls and is triggered off exm feed'
+ },
+ {
+ type: 'exmfeed:thanks',
+ img: 'automation3.svg',
+ icon: 'file-plus-alt',
+ label: 'Exm Thanks',
+ description:
+ 'Start with a blank workflow that enralls and is triggered off exm thanks'
+ }
+ ]
+ }
+};
diff --git a/packages/plugin-exmfeed-api/src/configs.ts b/packages/plugin-exmfeed-api/src/configs.ts
index f87d794599..4d58aa059f 100644
--- a/packages/plugin-exmfeed-api/src/configs.ts
+++ b/packages/plugin-exmfeed-api/src/configs.ts
@@ -9,6 +9,10 @@ import cronjobs, {
sendCeremonyNotification
} from './cronjobs';
+import automations from './automations';
+import segments from './segments';
+import forms from './forms';
+
export let debug;
export let graphqlPubsub;
export let mainDb;
@@ -55,5 +59,5 @@ export default {
graphqlPubsub = options.pubsubClient;
},
- meta: { cronjobs }
+ meta: { cronjobs, automations, segments, forms }
};
diff --git a/packages/plugin-exmfeed-api/src/essyncer.js b/packages/plugin-exmfeed-api/src/essyncer.js
new file mode 100644
index 0000000000..b796a20239
--- /dev/null
+++ b/packages/plugin-exmfeed-api/src/essyncer.js
@@ -0,0 +1,12 @@
+module.exports = [
+ {
+ name: 'exm_feeds',
+ schema: '{}',
+ script: ''
+ },
+ {
+ name: 'exm_thanks',
+ schema: '{}',
+ script: ''
+ }
+];
diff --git a/packages/plugin-exmfeed-api/src/forms.ts b/packages/plugin-exmfeed-api/src/forms.ts
new file mode 100644
index 0000000000..76164f5700
--- /dev/null
+++ b/packages/plugin-exmfeed-api/src/forms.ts
@@ -0,0 +1,59 @@
+import { generateFieldsFromSchema } from '@erxes/api-utils/src';
+import { generateModels } from './connectionResolver';
+
+const generateFields = async ({ subdomain, data }) => {
+ const { type, usageType } = data;
+
+ const models = await generateModels(subdomain);
+
+ const { ExmFeed, ExmThanks } = models;
+
+ let schema: any;
+ let fields: Array<{
+ _id: number;
+ name: string;
+ group?: string;
+ label?: string;
+ type?: string;
+ validation?: string;
+ options?: string[];
+ selectOptions?: Array<{ label: string; value: string }>;
+ }> = [];
+
+ switch (type) {
+ case 'feeds':
+ schema = ExmFeed.schema;
+ break;
+
+ case 'thanks':
+ schema = ExmThanks.schema;
+ break;
+ }
+
+ fields = [];
+
+ if (schema) {
+ fields = [...fields, ...(await generateFieldsFromSchema(schema, ''))];
+
+ for (const name of Object.keys(schema.paths)) {
+ const path = schema.paths[name];
+
+ if (path.schema) {
+ fields = [
+ ...fields,
+ ...(await generateFieldsFromSchema(path.schema, `${name}.`))
+ ];
+ }
+ }
+ }
+
+ return fields;
+};
+
+export default {
+ types: [
+ { description: 'Exm feed', type: 'feed' },
+ { description: 'Exm thanks', type: 'thanks' }
+ ],
+ fields: generateFields
+};
diff --git a/packages/plugin-exmfeed-api/src/segments.ts b/packages/plugin-exmfeed-api/src/segments.ts
new file mode 100644
index 0000000000..8d5b4c79c3
--- /dev/null
+++ b/packages/plugin-exmfeed-api/src/segments.ts
@@ -0,0 +1,64 @@
+import * as _ from 'underscore';
+import { fetchByQuery } from '@erxes/api-utils/src/elasticsearch';
+import { getEsIndexByContentType } from '@erxes/api-utils/src/segments';
+
+export default {
+ dependentServices: [
+ { name: 'contacts', twoWay: true },
+ { name: 'core', twoWay: true }
+ ],
+
+ contentTypes: [
+ { type: 'feeds', description: 'Exm Feed', esIndex: 'exm_feeds' },
+ { type: 'thanks', description: 'Exm Thanks', esIndex: 'exm_thanks' }
+ ],
+
+ esTypesMap: async () => {
+ return { data: { typesMap: {} }, status: 'success' };
+ },
+
+ associationFilter: async ({
+ subdomain,
+ data: { mainType, propertyType, positiveQuery, negativeQuery }
+ }) => {
+ let ids: string[] = [];
+
+ if (mainType.includes('core')) {
+ ids = await fetchByQuery({
+ subdomain,
+ index: 'exm_feeds',
+ _source: 'createdBy',
+ positiveQuery,
+ negativeQuery
+ });
+ }
+
+ if (propertyType.includes('core')) {
+ const teamMemberIds = await fetchByQuery({
+ subdomain,
+ index: await getEsIndexByContentType(propertyType),
+ positiveQuery,
+ negativeQuery
+ });
+
+ console.log({ teamMemberIds });
+
+ ids = await fetchByQuery({
+ subdomain,
+ index: 'exm_feeds',
+ _source: '_id',
+ positiveQuery: {
+ terms: {
+ createdBy: teamMemberIds
+ }
+ },
+ negativeQuery: undefined
+ });
+ console.log({ ids });
+ }
+
+ ids = _.uniq(ids);
+
+ return { data: ids, status: 'success' };
+ }
+};
diff --git a/packages/plugin-imap-ui/src/configs.js b/packages/plugin-imap-ui/src/configs.js
index 54b2265371..46f91cc386 100644
--- a/packages/plugin-imap-ui/src/configs.js
+++ b/packages/plugin-imap-ui/src/configs.js
@@ -1,36 +1,36 @@
module.exports = {
- name: "imap",
+ name: 'imap',
scope: 'imap',
port: 3014,
exposes: {
- './routes': './src/routes.tsx',
- "./inboxIntegrationSettings": "./src/components/IntegrationSettings.tsx",
- "./inboxIntegrationForm": "./src/components/IntegrationForm.tsx",
- "./inboxConversationDetail": "./src/components/ConversationDetail.tsx",
- './activityLog': './src/components/ActivityLog.tsx',
- "./integrationDetailsForm": "./src/components/IntegrationEditForm.tsx",
+ './routes': './src/routes.tsx'
+ // './inboxIntegrationSettings': './src/components/IntegrationSettings.tsx',
+ // './inboxIntegrationForm': './src/components/IntegrationForm.tsx',
+ // './inboxConversationDetail': './src/components/ConversationDetail.tsx',
+ // './activityLog': './src/components/ActivityLog.tsx',
+ // './integrationDetailsForm': './src/components/IntegrationEditForm.tsx'
},
routes: {
url: 'http://localhost:3014/remoteEntry.js',
scope: 'imap',
module: './routes'
- },
- inboxIntegrationSettings: './inboxIntegrationSettings',
- inboxIntegrationForm: './inboxIntegrationForm',
- inboxConversationDetail: './inboxConversationDetail',
- inboxIntegrations: [{
- name: 'IMAP',
- description:
- 'Connect a company email address such as sales@mycompany.com or info@mycompany.com',
- inMessenger: false,
- isAvailable: true,
- kind: 'imap',
- logo: '/images/integrations/email.png',
- createModal: 'imap',
- category:
- 'All integrations, For support teams, Marketing automation, Email marketing',
- components: ['inboxConversationDetail'],
- }],
- integrationDetailsForm: './integrationDetailsForm',
- activityLog: './activityLog',
-};
\ No newline at end of file
+ }
+ // inboxIntegrationSettings: './inboxIntegrationSettings',
+ // inboxIntegrationForm: './inboxIntegrationForm',
+ // inboxConversationDetail: './inboxConversationDetail',
+ // inboxIntegrations: [{
+ // name: 'IMAP',
+ // description:
+ // 'Connect a company email address such as sales@mycompany.com or info@mycompany.com',
+ // inMessenger: false,
+ // isAvailable: true,
+ // kind: 'imap',
+ // logo: '/images/integrations/email.png',
+ // createModal: 'imap',
+ // category:
+ // 'All integrations, For support teams, Marketing automation, Email marketing',
+ // components: ['inboxConversationDetail'],
+ // }],
+ // integrationDetailsForm: './integrationDetailsForm',
+ // activityLog: './activityLog'
+};
diff --git a/packages/plugin-reactions-api/src/configs.ts b/packages/plugin-reactions-api/src/configs.ts
index 0ed32f51fa..7ef3944b01 100644
--- a/packages/plugin-reactions-api/src/configs.ts
+++ b/packages/plugin-reactions-api/src/configs.ts
@@ -3,6 +3,8 @@ import resolvers from './graphql/resolvers';
import { generateModels } from './connectionResolver';
import { initBroker } from './messageBroker';
import { getSubdomain } from '@erxes/api-utils/src/core';
+import segments from './segments';
+import forms from './forms';
export let debug;
export let graphqlPubsub;
@@ -36,5 +38,5 @@ export default {
debug = options.debug;
graphqlPubsub = options.pubsubClient;
},
- meta: {}
+ meta: { segments, forms }
};
diff --git a/packages/plugin-reactions-api/src/essyncer.js b/packages/plugin-reactions-api/src/essyncer.js
new file mode 100644
index 0000000000..0a71bcf441
--- /dev/null
+++ b/packages/plugin-reactions-api/src/essyncer.js
@@ -0,0 +1,12 @@
+module.exports = [
+ {
+ name: 'emojis',
+ schema: '{}',
+ script: ''
+ },
+ {
+ name: 'comments',
+ schema: '{}',
+ script: ''
+ }
+];
diff --git a/packages/plugin-reactions-api/src/forms.ts b/packages/plugin-reactions-api/src/forms.ts
new file mode 100644
index 0000000000..c1499705ab
--- /dev/null
+++ b/packages/plugin-reactions-api/src/forms.ts
@@ -0,0 +1,59 @@
+import { generateFieldsFromSchema } from '@erxes/api-utils/src';
+import { generateModels } from './connectionResolver';
+
+const generateFields = async ({ subdomain, data }) => {
+ const { type, usageType } = data;
+
+ const models = await generateModels(subdomain);
+
+ const { Comments, Emojis } = models;
+
+ let schema: any;
+ let fields: Array<{
+ _id: number;
+ name: string;
+ group?: string;
+ label?: string;
+ type?: string;
+ validation?: string;
+ options?: string[];
+ selectOptions?: Array<{ label: string; value: string }>;
+ }> = [];
+
+ switch (type) {
+ case 'comments':
+ schema = Comments.schema;
+ break;
+
+ case 'emojis':
+ schema = Emojis.schema;
+ break;
+ }
+
+ fields = [];
+
+ if (schema) {
+ fields = [...fields, ...(await generateFieldsFromSchema(schema, ''))];
+
+ for (const name of Object.keys(schema.paths)) {
+ const path = schema.paths[name];
+
+ if (path.schema) {
+ fields = [
+ ...fields,
+ ...(await generateFieldsFromSchema(path.schema, `${name}.`))
+ ];
+ }
+ }
+ }
+
+ return fields;
+};
+
+export default {
+ types: [
+ { description: 'Exm Comments', type: 'comments' },
+ { description: 'Exm Emojis', type: 'emojis' }
+ ],
+ fields: generateFields
+};
diff --git a/packages/plugin-reactions-api/src/segments.ts b/packages/plugin-reactions-api/src/segments.ts
new file mode 100644
index 0000000000..61f60e7f55
--- /dev/null
+++ b/packages/plugin-reactions-api/src/segments.ts
@@ -0,0 +1,18 @@
+export default {
+ dependentServices: [{ name: 'exmfeed', twoWay: true }],
+
+ contentTypes: [
+ {
+ type: 'emojis',
+ description: 'Emojis',
+ sIndex: 'emojis',
+ hideInSidebar: true
+ },
+ {
+ type: 'comments',
+ description: 'Commnents',
+ sIndex: 'comments',
+ hideInSidebar: true
+ }
+ ]
+};
From c297d2a2206ff3084079afda269b584406bfe96e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Mon, 16 Oct 2023 15:46:46 +0800
Subject: [PATCH 02/64] updating
---
.../responseTemplates/components/List.tsx | 61 ++++++++++++++-----
1 file changed, 47 insertions(+), 14 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index bbeeeebb8e..9495e53200 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -22,6 +22,14 @@ import SelectBrands from '@erxes/ui/src/brands/containers/SelectBrands';
import Table from '@erxes/ui/src/components/table';
import Tip from '@erxes/ui/src/components/Tip';
import { withRouter } from 'react-router-dom';
+import {
+ Actions,
+ IframePreview,
+ Template,
+ TemplateBox,
+ Templates,
+ TemplateInfo
+} from '@erxes/ui-emailtemplates/src/styles';
type Props = {
renderButton: (props: IButtonMutateProps) => JSX.Element;
@@ -159,19 +167,44 @@ class ResponseTemplateList extends React.Component {
);
};
- renderContent = props => {
- return (
-
-
-
- {__('Brand')} |
- {__('Name')} |
- {__('Actions')} |
-
-
- {this.renderRows(props)}
-
- );
+ // renderContent = (props) => {
+ // return (
+ //
+ //
+ //
+ // {__("Brand")} |
+ // {__("Name")} |
+ // {__("Actions")} |
+ //
+ //
+ // {this.renderRows(props)}
+ //
+ // );
+ // };
+
+ renderRow = ({ objects }) => {
+ return objects.map((object, index) => {
+ return (
+ 46}>
+ {object.brand.name}
+ {object.name}
+
+
+
+
+
+
+
+ CreatedAt
+ 16 Oct 2023
+
+
+ Created by
+ erxes Inc
+
+
+ );
+ });
};
render() {
@@ -196,7 +229,7 @@ class ResponseTemplateList extends React.Component {
}
renderFilter={this.renderFilter}
renderForm={this.renderForm}
- renderContent={this.renderContent}
+ renderContent={this.renderRow}
size="lg"
{...this.props}
center={true}
From 5f0866c8a8df452af5836b4c9da78d2251c800ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Mon, 16 Oct 2023 16:43:37 +0800
Subject: [PATCH 03/64] templates updating
---
.../responseTemplates/components/List.tsx | 59 ++++++++++++++-----
1 file changed, 44 insertions(+), 15 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index 9495e53200..6d315c1978 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -30,6 +30,7 @@ import {
Templates,
TemplateInfo
} from '@erxes/ui-emailtemplates/src/styles';
+import ModalTrigger from '@erxes/ui/src/components/ModalTrigger';
type Props = {
renderButton: (props: IButtonMutateProps) => JSX.Element;
@@ -68,6 +69,28 @@ class ResponseTemplateList extends React.Component {
return ;
};
+ renderEditAction = object => {
+ const { save } = this.props;
+
+ const content = props => {
+ return this.renderForm({ ...props, object, save });
+ };
+
+ return (
+
+ Edit
+
+ }
+ content={content}
+ />
+ );
+ };
+
renderDisableAction = object => {
const { changeStatus } = this.props;
const _id = object._id;
@@ -92,9 +115,7 @@ class ResponseTemplateList extends React.Component {
return (
);
};
@@ -182,32 +203,40 @@ class ResponseTemplateList extends React.Component {
// );
// };
- renderRow = ({ objects }) => {
+ removeTemplate = object => {
+ this.props.remove(object._id);
+ };
+
+ renderBlock = ({ objects }) => {
return objects.map((object, index) => {
return (
46}>
{object.brand.name}
{object.name}
-
+
+ {this.renderEditAction(object)}
+
+ Delete
+
+ {this.renderDisableAction(object)}
+
-
+
-
- CreatedAt
- 16 Oct 2023
-
-
- Created by
- erxes Inc
-
);
});
};
+ // renderContent = () => {
+ // return {this.renderBlock(objects:objects)};
+ // };
+
render() {
+ console.log(this.props.renderButton);
+
return (
{
}
renderFilter={this.renderFilter}
renderForm={this.renderForm}
- renderContent={this.renderRow}
+ renderContent={this.renderBlock}
size="lg"
{...this.props}
center={true}
From 7a5fec9d1b0651b4d676558aadb97b22187abaaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Mon, 16 Oct 2023 17:06:38 +0800
Subject: [PATCH 04/64] add style
---
.../responseTemplates/components/List.tsx | 25 ++++++++++---------
packages/ui-emailtemplates/src/styles.ts | 9 ++++++-
2 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index 6d315c1978..764b4dff88 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -28,7 +28,8 @@ import {
Template,
TemplateBox,
Templates,
- TemplateInfo
+ TemplateInfo,
+ RowTitle
} from '@erxes/ui-emailtemplates/src/styles';
import ModalTrigger from '@erxes/ui/src/components/ModalTrigger';
@@ -207,12 +208,14 @@ class ResponseTemplateList extends React.Component {
this.props.remove(object._id);
};
- renderBlock = ({ objects }) => {
- return objects.map((object, index) => {
+ renderBlock = () => {
+ return this.props.objects.map((object, index) => {
return (
- 46}>
- {object.brand.name}
- {object.name}
+ 5}>
+
+ {object.brand.name}
+ {object.name}
+
{this.renderEditAction(object)}
@@ -230,9 +233,9 @@ class ResponseTemplateList extends React.Component {
});
};
- // renderContent = () => {
- // return {this.renderBlock(objects:objects)};
- // };
+ renderContent = () => {
+ return {this.renderBlock()};
+ };
render() {
console.log(this.props.renderButton);
@@ -258,11 +261,9 @@ class ResponseTemplateList extends React.Component {
}
renderFilter={this.renderFilter}
renderForm={this.renderForm}
- renderContent={this.renderBlock}
+ renderContent={this.renderContent}
size="lg"
{...this.props}
- center={true}
- hasBorder={false}
/>
);
}
diff --git a/packages/ui-emailtemplates/src/styles.ts b/packages/ui-emailtemplates/src/styles.ts
index 95bdca0da2..df6c40a19e 100644
--- a/packages/ui-emailtemplates/src/styles.ts
+++ b/packages/ui-emailtemplates/src/styles.ts
@@ -147,6 +147,12 @@ const Template = styledTS<{ isLongName?: boolean }>(styled.div)`
}
`;
+const RowTitle = styled.h5`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+`;
+
const TemplateInfo = styled.div`
display: flex;
justify-content: space-between;
@@ -171,5 +177,6 @@ export {
IframePreview,
IframeFullScreen,
TemplateInfo,
- TemplateWrapper
+ TemplateWrapper,
+ RowTitle
};
From d0bd22c2f5db78593126217965eb971ccfc8a898 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:12:45 +0800
Subject: [PATCH 05/64] perf(inbox): response templates ui update
---
.../responseTemplates/components/List.tsx | 48 ++-----------------
.../src/common/components/List.tsx | 19 ++++++--
2 files changed, 18 insertions(+), 49 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index 764b4dff88..fbbff1f680 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -17,10 +17,7 @@ import HeaderDescription from '@erxes/ui/src/components/HeaderDescription';
import { ICommonListProps } from '@erxes/ui-settings/src/common/types';
import Icon from '@erxes/ui/src/components/Icon';
import List from '@erxes/ui-settings/src/common/components/List';
-import RowActions from '@erxes/ui-settings/src/common/components/RowActions';
import SelectBrands from '@erxes/ui/src/brands/containers/SelectBrands';
-import Table from '@erxes/ui/src/components/table';
-import Tip from '@erxes/ui/src/components/Tip';
import { withRouter } from 'react-router-dom';
import {
Actions,
@@ -28,7 +25,6 @@ import {
Template,
TemplateBox,
Templates,
- TemplateInfo,
RowTitle
} from '@erxes/ui-emailtemplates/src/styles';
import ModalTrigger from '@erxes/ui/src/components/ModalTrigger';
@@ -121,26 +117,6 @@ class ResponseTemplateList extends React.Component {
);
};
- renderRows = ({ objects }) => {
- return objects.map((object, index) => {
- const brand = object.brand || {};
-
- return (
-
- {brand.name} |
- {object.name} |
-
-
- );
- });
- };
-
handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
const { value, name } = e.currentTarget as HTMLInputElement;
@@ -163,7 +139,6 @@ class ResponseTemplateList extends React.Component {
- Search
{
- Brand
{
);
};
- // renderContent = (props) => {
- // return (
- //
- //
- //
- // {__("Brand")} |
- // {__("Name")} |
- // {__("Actions")} |
- //
- //
- // {this.renderRows(props)}
- //
- // );
- // };
-
removeTemplate = object => {
this.props.remove(object._id);
};
@@ -222,7 +181,7 @@ class ResponseTemplateList extends React.Component {
Delete
- {this.renderDisableAction(object)}
+ {/* {this.renderDisableAction(object)} */}
@@ -238,8 +197,6 @@ class ResponseTemplateList extends React.Component {
};
render() {
- console.log(this.props.renderButton);
-
return (
{
)}`}
/>
}
- renderFilter={this.renderFilter}
+ flexFilter={this.renderFilter}
renderForm={this.renderForm}
renderContent={this.renderContent}
size="lg"
{...this.props}
+ rightActionBar="true"
/>
);
}
diff --git a/packages/ui-settings/src/common/components/List.tsx b/packages/ui-settings/src/common/components/List.tsx
index 5bf5854399..a09d8a6ebb 100644
--- a/packages/ui-settings/src/common/components/List.tsx
+++ b/packages/ui-settings/src/common/components/List.tsx
@@ -31,6 +31,7 @@ type Props = {
rightActionBar?: any;
transparent?: boolean;
hasBorder?: boolean;
+ flexFilter?: () => any;
};
class List extends React.Component {
@@ -59,7 +60,8 @@ class List extends React.Component {
queryParams,
transparent,
history,
- hasBorder
+ hasBorder,
+ flexFilter
} = this.props;
const trigger = (
@@ -73,10 +75,19 @@ class List extends React.Component {
};
const actionBarRight = rightActionBar ? (
-
- {additionalButton}
+
+ {flexFilter && flexFilter()}
{/* */}
-
+
+
) : (
{additionalButton}
From bacd774327f29bb15b83510aa487fad4c7d14d92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:34:29 +0800
Subject: [PATCH 06/64] perf(inbox): response templates ui update
---
.../responseTemplates/components/List.tsx | 38 +++++++++++--------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index fbbff1f680..670cd59804 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -117,12 +117,19 @@ class ResponseTemplateList extends React.Component {
);
};
- handleKeyDown = (e: React.KeyboardEvent) => {
- if (e.key === 'Enter') {
- const { value, name } = e.currentTarget as HTMLInputElement;
-
- router.setParams(this.props.history, { [name]: value });
+ handleKeyDown = (
+ e: React.KeyboardEvent | React.MouseEvent
+ ) => {
+ if (
+ e instanceof KeyboardEvent &&
+ e.key !== 'Enter' &&
+ e.key !== 'Backspace'
+ ) {
+ return;
}
+
+ const { value, name } = (e.currentTarget as any) as HTMLInputElement;
+ router.setParams(this.props.history, { [name]: value });
};
onSelect = (values: string[] | string, name: string) => {
@@ -138,6 +145,16 @@ class ResponseTemplateList extends React.Component {
return (
+
+
+
+
{
onChange={this.onChange}
value={this.state.searchValue}
onKeyPress={this.handleKeyDown}
+ onKeyDown={this.handleKeyDown}
autoFocus={true}
/>
-
-
-
-
);
From 93c4571d58a5c6a571bd5c8d0b084cc46b3f8402 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Tue, 17 Oct 2023 11:02:54 +0800
Subject: [PATCH 07/64] perf(inbox): response templates ui update
---
.../src/settings/responseTemplates/components/List.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index 670cd59804..a7046d471a 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -180,8 +180,12 @@ class ResponseTemplateList extends React.Component {
return (
5}>
- {object.brand.name}
- {object.name}
+
+
{object.brand.name}
+
+
+
{object.name}
+
From 0c971e2d73a3549fe90e90598c1834239775acea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Tue, 17 Oct 2023 16:28:02 +0800
Subject: [PATCH 08/64] perf(inbox): response templates ui update
---
.../responseTemplates/components/List.tsx | 36 +++++++------------
1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
index a7046d471a..bef14bc091 100755
--- a/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/settings/responseTemplates/components/List.tsx
@@ -7,9 +7,7 @@ import {
RESPONSE_TEMPLATE_TIPTEXT
} from '../constants';
import { __, router } from 'coreui/utils';
-
import Button from '@erxes/ui/src/components/Button';
-import ControlLabel from '@erxes/ui/src/components/form/Label';
import { FilterContainer } from '@erxes/ui-settings/src/styles';
import Form from '@erxes/ui-inbox/src/settings/responseTemplates/components/Form';
import { FormControl } from '@erxes/ui/src/components/form';
@@ -25,7 +23,7 @@ import {
Template,
TemplateBox,
Templates,
- RowTitle
+ TemplateInfo
} from '@erxes/ui-emailtemplates/src/styles';
import ModalTrigger from '@erxes/ui/src/components/ModalTrigger';
@@ -117,19 +115,12 @@ class ResponseTemplateList extends React.Component {
);
};
- handleKeyDown = (
- e: React.KeyboardEvent | React.MouseEvent
- ) => {
- if (
- e instanceof KeyboardEvent &&
- e.key !== 'Enter' &&
- e.key !== 'Backspace'
- ) {
- return;
- }
+ handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === 'Enter') {
+ const { value, name } = e.currentTarget as HTMLInputElement;
- const { value, name } = (e.currentTarget as any) as HTMLInputElement;
- router.setParams(this.props.history, { [name]: value });
+ router.setParams(this.props.history, { [name]: value });
+ }
};
onSelect = (values: string[] | string, name: string) => {
@@ -178,15 +169,8 @@ class ResponseTemplateList extends React.Component {
renderBlock = () => {
return this.props.objects.map((object, index) => {
return (
- 5}>
-
-
-
{object.brand.name}
-
-
-
{object.name}
-
-
+ 45}>
+ {object.name}
{this.renderEditAction(object)}
@@ -199,6 +183,10 @@ class ResponseTemplateList extends React.Component {
+
+ Brand
+ {object.brand.name}
+
);
});
From ff20dbb55464df2455e9ea3106a17490a4f3380b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Tue, 17 Oct 2023 16:53:29 +0800
Subject: [PATCH 09/64] perf(inbox): update response & script ui
---
.../src/scripts/components/InstallCode.tsx | 4 +-
.../src/scripts/components/List.tsx | 272 +++++++++++++-----
2 files changed, 203 insertions(+), 73 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/scripts/components/InstallCode.tsx b/packages/plugin-inbox-ui/src/scripts/components/InstallCode.tsx
index 2f8e24b7e8..3f8d0d3133 100644
--- a/packages/plugin-inbox-ui/src/scripts/components/InstallCode.tsx
+++ b/packages/plugin-inbox-ui/src/scripts/components/InstallCode.tsx
@@ -10,7 +10,7 @@ import { IScript } from '../types';
type Props = {
script: IScript;
- closeModal: () => void;
+ closeModal?: () => void;
};
type State = {
@@ -61,7 +61,7 @@ class InstallCode extends React.Component {
return (
-
+
{this.state.code ? (
+
+ Install code
+
}
content={content}
/>
);
};
- renderRows = ({ objects }) => {
- return objects.map((object, index) => {
+ handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === 'Enter') {
+ const { value, name } = e.currentTarget as HTMLInputElement;
+
+ router.setParams(this.props.history, { [name]: value });
+ }
+ };
+
+ onSelect = (values: string[] | string, name: string) => {
+ router.setParams(this.props.history, { [name]: values });
+ };
+
+ renderFilter = () => {
+ const scriptId =
+ this.props.queryParams && this.props.queryParams.scriptId
+ ? this.props.queryParams
+ : '';
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ };
+
+ removeTemplate = object => {
+ this.props.remove(object._id);
+ };
+
+ renderBlock = () => {
+ return this.props.objects.map((object, index) => {
+ const contentHtml = renderToString();
+
return (
-
- {object.name} |
-
- {object.messenger && (
-
-
-
- {' '}
- {object.messenger.name}
-
- )}
- {object.kbTopic && (
-
-
-
- {' '}
- {object.kbTopic.title}
+
+ {object.name}
+
+
+ {this.renderEditAction(object)}
+
+ Delete
- )}
- {object.leads.length > 0 && (
-
-
-
-
- {object.leads.map(lead => ` ${lead.name},`)}
-
- )}
- |
-
-
+ {this.installCodeAction(object)}
+
+
+
+
+
+
+
+ {object.messenger && (
+
+
+
+ {' '}
+ {object.messenger.name}
+
+ )}
+ {object.kbTopic && (
+
+
+
+
+ {object.kbTopic.title}
+
+ )}
+ {object.leads.length > 0 && (
+
+
+
+
+ {object.leads.map(lead => ` ${lead.name},`)}
+
+ )}
+
+
+
);
});
};
- renderContent = props => {
- return (
-
-
-
- {__('Name')} |
- {__('Integrations')} |
- {__('Actions')} |
-
-
- {this.renderRows(props)}
-
- );
+ searchHandler = event => {
+ const { history } = this.props;
+
+ router.setParams(history, { page: 1, searchValue: event.target.value });
+ };
+
+ renderContent = () => {
+ return {this.renderBlock()};
};
render() {
return (
{
)}`}
/>
}
+ // flexFilter={this.renderFilter}
+ // rightActionBar="true"
+ emptyContent={}
renderForm={this.renderForm}
renderContent={this.renderContent}
- center={true}
- emptyContent={}
{...this.props}
+ queryParams={this.props.queryParams}
+ history={this.props.history}
+ additionalButton={
+
+ }
/>
);
}
}
-export default ScriptList;
+export default withRouter(ScriptList);
From 851c8118961e88eae10469e80547c795aa986870 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=91=D0=B0=D1=8F=D0=BB=D0=B0=D0=B3?=
<40917206+Baylag321@users.noreply.github.com>
Date: Thu, 19 Oct 2023 21:14:23 +0800
Subject: [PATCH 10/64] perf(inbox): update response & script ui
---
.../src/scripts/components/List.tsx | 59 ++++++++-----------
1 file changed, 24 insertions(+), 35 deletions(-)
diff --git a/packages/plugin-inbox-ui/src/scripts/components/List.tsx b/packages/plugin-inbox-ui/src/scripts/components/List.tsx
index f0b9d96bf0..e5c5088197 100755
--- a/packages/plugin-inbox-ui/src/scripts/components/List.tsx
+++ b/packages/plugin-inbox-ui/src/scripts/components/List.tsx
@@ -175,32 +175,32 @@ class ScriptList extends React.Component {
-
- {object.messenger && (
-
-
-
- {' '}
- {object.messenger.name}
-
- )}
- {object.kbTopic && (
-
-
-
-
+ {object.messenger && (
+ <>
+
Messenger
+
+ {object.messenger.name}
+
+ >
+ )}
+ {object.kbTopic && (
+ <>
+
Knowledge Base"
+
+
{object.kbTopic.title}
-
- )}
- {object.leads.length > 0 && (
-
-
-
-
+
+ >
+ )}
+ {object.leads.length > 0 && (
+ <>
+
Forms
+
+
{object.leads.map(lead => ` ${lead.name},`)}
-
- )}
-
+
+ >
+ )}
);
@@ -237,23 +237,12 @@ class ScriptList extends React.Component {
)}`}
/>
}
- // flexFilter={this.renderFilter}
- // rightActionBar="true"
emptyContent={}
renderForm={this.renderForm}
renderContent={this.renderContent}
{...this.props}
queryParams={this.props.queryParams}
history={this.props.history}
- additionalButton={
-
- }
/>
);
}
From 375b65027adb71306730961c8bb444f583315d87 Mon Sep 17 00:00:00 2001
From: soyombo <40427263+soyombo-baterdene@users.noreply.github.com>
Date: Tue, 24 Oct 2023 17:19:39 +0800
Subject: [PATCH 11/64] update(clientportal): add vendorportal
---
packages/core-ui/public/locales/en.json | 15 ++
packages/erxes-ui/src/utils/menus.ts | 2 +-
.../plugin-cards-api/src/messageBroker.ts | 2 +-
.../components/BoardItemCreatedLog.tsx | 37 +++--
.../src/afterMutations/cards.ts | 2 +-
.../src/commands/migrateUserCards.mjs | 55 +++++++
.../src/connectionResolver.ts | 11 ++
packages/plugin-clientportal-api/src/forms.ts | 2 +-
.../resolvers/mutations/clientPortal.ts | 22 +--
.../resolvers/mutations/clientPortalUser.ts | 15 +-
.../graphql/resolvers/mutations/comment.ts | 13 +-
.../graphql/resolvers/queries/clientPortal.ts | 51 ++++++-
.../src/graphql/schema/clientPortal.ts | 134 +++++++++++-------
.../src/graphql/typeDefs.ts | 8 +-
.../plugin-clientportal-api/src/logUtils.ts | 127 +++++++++++++++++
.../src/models/ClientPortal.ts | 4 +-
.../src/models/ClientPortalCompany.ts | 74 ++++++++++
.../src/models/ClientPortalUser.ts | 2 +-
.../src/models/ClientPortalUserCard.ts | 97 +++++--------
.../src/models/definitions/clientPortal.ts | 13 ++
.../models/definitions/clientPortalCompany.ts | 21 +++
.../models/definitions/clientPortalUser.ts | 1 -
.../definitions/clientPortalUserCards.ts | 48 ++++++-
.../src/permissions.js | 2 +-
packages/plugin-clientportal-api/src/utils.ts | 17 +++
.../src/components/ClientPortal.tsx | 17 ++-
.../src/components/ClientPortalDetail.tsx | 1 +
.../src/components/FieldConfigForm.tsx | 4 +-
.../src/components/List.tsx | 15 +-
.../src/components/Menu.tsx | 105 ++++++++++++++
.../cardRightSidebarSection/Detail.tsx | 40 ++++++
.../cardRightSidebarSection/VendorSection.tsx | 81 +++++++++++
.../src/components/detail/DetailInfo.tsx | 2 +-
.../src/components/detail/RightSidebar.tsx | 18 ++-
.../src/components/forms/Appearance.tsx | 2 +-
.../components/forms/ClientPortalUserForm.tsx | 2 +-
.../src/components/forms/General.tsx | 64 ++++++++-
.../components/list/ClientPortalIdFilter.tsx | 2 +-
.../plugin-clientportal-ui/src/configs.js | 47 +++++-
.../src/containers/ClientPortalDetail.tsx | 21 +--
.../src/containers/General.tsx | 1 +
.../src/containers/List.tsx | 36 +++--
.../ClientSection.tsx | 32 +++++
.../VendorSection.tsx | 32 +++++
.../src/graphql/mutations.ts | 108 +-------------
.../src/graphql/queries.ts | 37 ++++-
.../plugin-clientportal-ui/src/routes.tsx | 40 +++++-
.../plugin-clientportal-ui/src/styles.tsx | 8 ++
packages/plugin-clientportal-ui/src/types.ts | 2 +
.../src/graphql/resolvers/activityLog.ts | 23 +++
packages/ui-log/src/activityLogs/utils.ts | 16 +++
.../items/create/BoardItemCreate.tsx | 5 +
52 files changed, 1216 insertions(+), 320 deletions(-)
create mode 100644 packages/plugin-clientportal-api/src/commands/migrateUserCards.mjs
create mode 100644 packages/plugin-clientportal-api/src/logUtils.ts
create mode 100644 packages/plugin-clientportal-api/src/models/ClientPortalCompany.ts
create mode 100644 packages/plugin-clientportal-api/src/models/definitions/clientPortalCompany.ts
create mode 100644 packages/plugin-clientportal-ui/src/components/Menu.tsx
create mode 100644 packages/plugin-clientportal-ui/src/components/cardRightSidebarSection/Detail.tsx
create mode 100644 packages/plugin-clientportal-ui/src/components/cardRightSidebarSection/VendorSection.tsx
create mode 100644 packages/plugin-clientportal-ui/src/containers/cardsRightSidebarSection/ClientSection.tsx
create mode 100644 packages/plugin-clientportal-ui/src/containers/cardsRightSidebarSection/VendorSection.tsx
diff --git a/packages/core-ui/public/locales/en.json b/packages/core-ui/public/locales/en.json
index eaa97cac0c..6ac02bfcae 100644
--- a/packages/core-ui/public/locales/en.json
+++ b/packages/core-ui/public/locales/en.json
@@ -2107,15 +2107,26 @@
"Client Portal": "Client Portal",
"Add New Client Portal": "Add New Client Portal",
"New Client Portal": "New Client Portal",
+ "Business portal": "Business portal",
+ "Business Portal": "Business Portal",
+ "Vendor Portal": "Vendor Portal",
+ "Add New Vendor Portal": "Add New Vendor Portal",
+ "Add New Business Portal": "Add New Business Portal",
+ "New Business Portal": "New Business Portal",
"There is no client portal": "There is no client portal",
"Getting Started with Client Portal": "Getting Started with Client Portal",
"Client Portal Name": "Client Portal Name",
+ "Getting Started with Business Portal": "Getting Started with Business Portal",
+ "Business Portal Name": "Business Portal Name",
+ "Vendor Portal Name": "Vendor Portal Name",
"Displayed in the header area": "Displayed in the header area",
"Redirect URL to the main website": "Redirect URL to the main website",
"Features": "Features",
"Knowledge Base Name": "Knowledge Base Name",
"Shown name on menu": "Shown name on menu",
"Knowledge base topic in Client Portal": "Knowledge base topic in Client Portal",
+ "Knowledge base topic in Business Portal": "Knowledge base topic in Business Portal",
+ "Knowledge base topic in Vendor Portal": "Knowledge base topic in Vendor Portal",
"Please enter a label for Ticket": "Please enter a label for Ticket",
"Please enter a label for Task": "Please enter a label for Task",
"Select a knowledge base topic": "Select a knowledge base topic",
@@ -2124,10 +2135,14 @@
"Public task pipeline": "Public task pipeline",
"Public task board": "Public task board",
"Show in Client Portal": "Show in Client Portal",
+ "Show in Vendor Portal": "Show in Vendor Portal",
+ "Show in Business Portal": "Show in Business Portal",
"Logo and favicon": "Logo and favicon",
"Main Logo": "Main Logo",
"Favicon": "Favicon",
"Client portal main logo PNG": "Client portal main logo PNG",
+ "Business portal main logo PNG": "Business portal main logo PNG",
+ "Vendpr portal main logo PNG": "Vendor portal main logo PNG",
"16x16px transparent PNG": "16x16px transparent PNG",
"Main colors": "Main colors",
"Background color": "Background color",
diff --git a/packages/erxes-ui/src/utils/menus.ts b/packages/erxes-ui/src/utils/menus.ts
index e6dd66bd38..ea16c97efc 100644
--- a/packages/erxes-ui/src/utils/menus.ts
+++ b/packages/erxes-ui/src/utils/menus.ts
@@ -10,7 +10,7 @@ const menuContacts = [
{ title: 'Companies', link: '/companies' },
isEnabled('clientportal')
? {
- title: 'Client Portal Users',
+ title: 'Business Portal Users',
link: '/settings/client-portal/user'
}
: { title: '', link: '' }
diff --git a/packages/plugin-cards-api/src/messageBroker.ts b/packages/plugin-cards-api/src/messageBroker.ts
index c038a3f63a..437d428472 100644
--- a/packages/plugin-cards-api/src/messageBroker.ts
+++ b/packages/plugin-cards-api/src/messageBroker.ts
@@ -46,7 +46,7 @@ export const initBroker = async cl => {
consumeRPCQueue('cards:tasks.create', async ({ subdomain, data }) => {
const models = await generateModels(subdomain);
- const task = await models.Tasks.create(data);
+ const task = await models.Tasks.createTask(data);
const { customerId = '' } = data;
diff --git a/packages/plugin-cards-ui/src/activityLogs/components/BoardItemCreatedLog.tsx b/packages/plugin-cards-ui/src/activityLogs/components/BoardItemCreatedLog.tsx
index 38e6926ec4..57c1eabb98 100644
--- a/packages/plugin-cards-ui/src/activityLogs/components/BoardItemCreatedLog.tsx
+++ b/packages/plugin-cards-ui/src/activityLogs/components/BoardItemCreatedLog.tsx
@@ -4,13 +4,13 @@ import {
FlexCenterContent
} from '@erxes/ui-log/src/activityLogs/styles';
-import { IActivityLogItemProps } from '@erxes/ui-log/src/activityLogs/types';
+import { getCPUserName } from '@erxes/ui-log/src/activityLogs/utils';
import Icon from '@erxes/ui/src/components/Icon';
-import { Link } from 'react-router-dom';
-import React from 'react';
import Tip from '@erxes/ui/src/components/Tip';
-import dayjs from 'dayjs';
import { renderUserFullName } from '@erxes/ui/src/utils';
+import dayjs from 'dayjs';
+import React from 'react';
+import { Link } from 'react-router-dom';
type Props = {
activity: any;
@@ -24,14 +24,6 @@ class BoardItemCreatedLog extends React.Component {
let userName = 'Unknown';
- if (createdByDetail && createdByDetail.type === 'user') {
- const { content } = createdByDetail;
-
- if (content && content.details) {
- userName = renderUserFullName(createdByDetail.content);
- }
- }
-
const body = (
{
);
+ if (createdByDetail && createdByDetail.type === 'user') {
+ const { content } = createdByDetail;
+
+ if (content && content.details) {
+ userName = renderUserFullName(createdByDetail.content);
+ }
+ }
+
+ if (createdByDetail && createdByDetail.type === 'clientPortalUser') {
+ userName = getCPUserName(createdByDetail.content);
+ const cpUrl = createdByDetail.content.clientPortal.url || '';
+ return (
+
+ {userName} created {body} {contentType} from{' '}
+
+ {createdByDetail.content.clientPortal.name || 'client portal'}
+
+
+ );
+ }
+
return (
{userName} created {body} {contentType}
diff --git a/packages/plugin-clientportal-api/src/afterMutations/cards.ts b/packages/plugin-clientportal-api/src/afterMutations/cards.ts
index 856e913831..7f9557f4a7 100644
--- a/packages/plugin-clientportal-api/src/afterMutations/cards.ts
+++ b/packages/plugin-clientportal-api/src/afterMutations/cards.ts
@@ -98,7 +98,7 @@ export const cardDeleteHandler = async (models: IModels, subdomain, params) => {
card._id
);
- await models.ClientPortalUserCards.remove({ cardId: card._id });
+ await models.ClientPortalUserCards.deleteMany({ cardId: card._id });
if (userIds.length === 0) {
return;
diff --git a/packages/plugin-clientportal-api/src/commands/migrateUserCards.mjs b/packages/plugin-clientportal-api/src/commands/migrateUserCards.mjs
new file mode 100644
index 0000000000..f63061d451
--- /dev/null
+++ b/packages/plugin-clientportal-api/src/commands/migrateUserCards.mjs
@@ -0,0 +1,55 @@
+import mongoDb from 'mongodb';
+import { nanoid } from 'nanoid';
+
+const MongoClient = mongoDb.MongoClient;
+
+const MONGO_URL = process.argv[2] || 'mongodb://localhost:27017/erxes';
+
+console.log('MONGO_URL', MONGO_URL);
+
+if (!MONGO_URL) {
+ throw new Error(`Environment variable MONGO_URL not set.`);
+}
+
+const client = new MongoClient(MONGO_URL, { useUnifiedTopology: true });
+
+let db;
+
+let Cards;
+
+const command = async () => {
+ try {
+ await client.connect();
+ console.log('Connected to ', MONGO_URL);
+ db = client.db();
+
+ Cards = db.collection('client_portal_user_cards');
+
+ const cards = await Cards.find({}).toArray();
+
+ for (const card of cards) {
+ for (const userId of card.userIds) {
+ const doc = {
+ _id: nanoid(),
+ contentType: card.type,
+ contentTypeId: card.cardId,
+ createdAt: card.createdAt,
+ cpUserId: userId,
+ };
+ await Cards.insertOne(doc);
+ }
+
+ await Cards.deleteOne({ _id: card._id });
+ }
+ }
+ catch (e) {
+ console.error("eeeeeeee ",e);
+ }
+
+
+ console.log(`Process finished at: ${new Date()}`);
+
+ process.exit();
+};
+
+command();
diff --git a/packages/plugin-clientportal-api/src/connectionResolver.ts b/packages/plugin-clientportal-api/src/connectionResolver.ts
index c137537931..a679175fc9 100644
--- a/packages/plugin-clientportal-api/src/connectionResolver.ts
+++ b/packages/plugin-clientportal-api/src/connectionResolver.ts
@@ -26,6 +26,11 @@ import { ICommentModel, loadCommentClass } from './models/Comment';
import { ICommentDocument } from './models/definitions/comment';
import { IFieldConfigModel, loadFieldConfigClass } from './models/FieldConfigs';
import { IFieldConfigDocument } from './models/definitions/fieldConfigs';
+import {
+ IClientCompanyModel,
+ loadCompanyClass
+} from './models/ClientPortalCompany';
+import { IClientCompanyDocument } from './models/definitions/clientPortalCompany';
export interface IModels {
ClientPortals: IClientPortalModel;
@@ -34,6 +39,7 @@ export interface IModels {
ClientPortalUserCards: ICPUserCardModel;
Comments: ICommentModel;
FieldConfigs: IFieldConfigModel;
+ Companies: IClientCompanyModel;
}
export interface IContext extends IMainContext {
@@ -77,6 +83,11 @@ export const loadClasses = (db: mongoose.Connection): IModels => {
loadFieldConfigClass(models)
);
+ models.Companies = db.model(
+ 'client_portal_companies',
+ loadCompanyClass(models)
+ );
+
return models;
};
diff --git a/packages/plugin-clientportal-api/src/forms.ts b/packages/plugin-clientportal-api/src/forms.ts
index cff9d04331..9c43e87f41 100644
--- a/packages/plugin-clientportal-api/src/forms.ts
+++ b/packages/plugin-clientportal-api/src/forms.ts
@@ -4,7 +4,7 @@ import { generateFields } from './utils';
export default {
types: [
{
- description: 'Client Portal User',
+ description: 'Business Portal User',
type: 'user'
}
],
diff --git a/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortal.ts b/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortal.ts
index 6a7ce9ed86..554a46a966 100644
--- a/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortal.ts
+++ b/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortal.ts
@@ -3,6 +3,8 @@ import { sendCardsMessage, sendContactsMessage } from '../../../messageBroker';
import { IClientPortal } from '../../../models/definitions/clientPortal';
import { IContext } from '../../../connectionResolver';
import { checkPermission } from '@erxes/api-utils/src';
+import { putActivityLog } from '../../../logUtils';
+import { getUserName } from '../../../utils';
export interface IVerificationParams {
userId: string;
@@ -11,8 +13,12 @@ export interface IVerificationParams {
}
const clientPortalMutations = {
- clientPortalConfigUpdate(_root, args: IClientPortal, { models }: IContext) {
- return models.ClientPortals.createOrUpdateConfig(args);
+ clientPortalConfigUpdate(
+ _root,
+ { config }: { config: IClientPortal },
+ { models }: IContext
+ ) {
+ return models.ClientPortals.createOrUpdateConfig(config);
},
clientPortalRemove(_root, { _id }: { _id: string }, { models }: IContext) {
@@ -82,13 +88,11 @@ const clientPortalMutations = {
isRPC: true
});
- await models.ClientPortalUserCards.createOrUpdateCard(
- {
- type,
- cardId: card._id
- },
- cpUser._id
- );
+ await models.ClientPortalUserCards.createOrUpdateCard({
+ contentType: type,
+ contentTypeId: card._id,
+ cpUserId: cpUser._id
+ });
return card;
}
diff --git a/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortalUser.ts b/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortalUser.ts
index 9957241f5d..3f0cb4877a 100644
--- a/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortalUser.ts
+++ b/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/clientPortalUser.ts
@@ -861,8 +861,12 @@ const clientPortalUserMutations = {
clientPortalUserAssignCompany: async (
_root,
args: { userId: string; erxesCompanyId: string; erxesCustomerId: string },
- { models, subdomain }: IContext
+ { models, subdomain, cpUser }: IContext
) => {
+ if (!cpUser) {
+ throw new Error('login required');
+ }
+
const { userId, erxesCompanyId, erxesCustomerId } = args;
const getCompany = await sendContactsMessage({
@@ -894,6 +898,15 @@ const clientPortalUserMutations = {
throw new Error(error);
}
+ const cp = await models.ClientPortals.findOne(cpUser.clientPortalId).lean();
+
+ if (cp || cp.kind === 'vendor') {
+ await models.Companies.createOrUpdateCompany({
+ erxesCompanyId,
+ clientPortalId: cp._id
+ });
+ }
+
return models.ClientPortalUsers.updateOne(
{ _id: userId },
{ $set: setOps }
diff --git a/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/comment.ts b/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/comment.ts
index 0003ccf623..24c7bfc2da 100644
--- a/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/comment.ts
+++ b/packages/plugin-clientportal-api/src/graphql/resolvers/mutations/comment.ts
@@ -30,17 +30,16 @@ const clientPortalCommentMutations = {
userId: userId || user._id
});
- const relatedCard = await models.ClientPortalUserCards.findOne({
- cardId: typeId
- });
+ const relatedCards = await models.ClientPortalUserCards.getUserIds(
+ type,
+ typeId
+ );
- if (!relatedCard || userType === 'client') {
+ if (!relatedCards || relatedCards.length === 0 || userType === 'client') {
return comment;
}
- const { userIds } = relatedCard;
-
- for (const cardUserId of userIds) {
+ for (const cardUserId of relatedCards) {
await sendNotification(models, subdomain, {
receivers: [cardUserId],
title: `${user.details?.fullName} has commented on your ${type}.`,
diff --git a/packages/plugin-clientportal-api/src/graphql/resolvers/queries/clientPortal.ts b/packages/plugin-clientportal-api/src/graphql/resolvers/queries/clientPortal.ts
index fdff42dbf8..396c5d4289 100644
--- a/packages/plugin-clientportal-api/src/graphql/resolvers/queries/clientPortal.ts
+++ b/packages/plugin-clientportal-api/src/graphql/resolvers/queries/clientPortal.ts
@@ -29,10 +29,12 @@ const getByHost = async (models, requestInfo) => {
const configClientPortalQueries = {
async clientPortalGetConfigs(
_root,
- args: { page?: number; perPage?: number },
+ args: { kind?: string; page?: number; perPage?: number },
{ models }: IContext
) {
- return paginate(models.ClientPortals.find({}), args);
+ const { kind = 'client' } = args;
+
+ return paginate(models.ClientPortals.find({ kind }), args);
},
async clientPortalConfigsTotalCount(_root, _args, { models }: IContext) {
@@ -42,8 +44,8 @@ const configClientPortalQueries = {
/**
* Get last config
*/
- clientPortalGetLast(_root, _args, { models }: IContext) {
- return models.ClientPortals.findOne({}).sort({
+ clientPortalGetLast(_root, { kind }, { models }: IContext) {
+ return models.ClientPortals.findOne({ kind }).sort({
createdAt: -1
});
},
@@ -253,6 +255,47 @@ const configClientPortalQueries = {
isRequired: true
};
});
+ },
+
+ async clientPortalCardUsers(
+ _root,
+ { contentType, contentTypeId, userKind },
+ { models }: IContext
+ ) {
+ const userIds = await models.ClientPortalUserCards.getUserIds(
+ contentType,
+ contentTypeId
+ );
+
+ if (!userIds || userIds.length === 0) {
+ return [];
+ }
+
+ const users = await models.ClientPortalUsers.aggregate([
+ {
+ $match: {
+ _id: { $in: userIds }
+ }
+ },
+ {
+ $lookup: {
+ from: 'client_portals',
+ localField: 'clientPortalId',
+ foreignField: '_id',
+ as: 'clientPortal'
+ }
+ },
+ {
+ $unwind: '$clientPortal'
+ },
+ {
+ $match: {
+ 'clientPortal.kind': userKind
+ }
+ }
+ ]);
+
+ return users;
}
};
diff --git a/packages/plugin-clientportal-api/src/graphql/schema/clientPortal.ts b/packages/plugin-clientportal-api/src/graphql/schema/clientPortal.ts
index e5ac73e51b..6fa5ee3f32 100644
--- a/packages/plugin-clientportal-api/src/graphql/schema/clientPortal.ts
+++ b/packages/plugin-clientportal-api/src/graphql/schema/clientPortal.ts
@@ -1,4 +1,9 @@
-export const types = (cardAvailable, kbAvailable, formsAvailable) => `
+export const types = (
+ cardAvailable,
+ kbAvailable,
+ formsAvailable,
+ productsAvailable
+) => `
${
cardAvailable
? `
@@ -35,6 +40,16 @@ ${
: ''
}
+${
+ productsAvailable
+ ? `
+ extend type ProductCategory @key(fields: "_id") {
+ _id: String! @external
+ }
+ `
+ : ''
+}
+
${
formsAvailable
? `
@@ -92,9 +107,15 @@ ${
header
}
+ enum BusinessPortalKind {
+ client
+ vendor
+ }
+
type ClientPortal {
_id: String!
name: String!
+ kind: BusinessPortalKind!
description: String
url: String
logo: String
@@ -150,6 +171,7 @@ ${
tokenExpiration: Int
refreshTokenExpiration: Int
tokenPassMethod: TokenPassMethod
+ vendorParentProductCategoryId: String
}
type Styles {
@@ -192,76 +214,46 @@ ${
month: Int
year: Int
}
-`;
-export const queries = (cardAvailable, kbAvailable, formsAvailable) => `
- clientPortalGetConfigs(page: Int, perPage: Int): [ClientPortal]
- clientPortalGetConfig(_id: String!): ClientPortal
- clientPortalGetConfigByDomain: ClientPortal
- clientPortalGetLast: ClientPortal
- clientPortalConfigsTotalCount: Int
- ${
- formsAvailable
- ? `
- clientPortalGetAllowedFields(_id: String!): [Field]
- `
- : ''
- }
- ${
- cardAvailable
- ? `
- clientPortalGetTaskStages: [Stage]
- clientPortalGetTasks(stageId: String!): [Task]
- clientPortalTickets(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Ticket]
- clientPortalDeals(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Deal]
- clientPortalPurchases(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Purchase]
- clientPortalTasks(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Task]
- clientPortalTicket(_id: String!): Ticket
- `
- : ''
- }
-
- ${
- kbAvailable
- ? `
- clientPortalKnowledgeBaseTopicDetail(_id: String!): KnowledgeBaseTopic
- clientPortalKnowledgeBaseArticles(searchValue: String, categoryIds: [String], topicId: String):
-[KnowledgeBaseArticle]
- `
- : ''
- }
-`;
-
-export const mutations = cardAvailable => `
- clientPortalConfigUpdate (
+ input ClientPortalConfigInput {
_id: String
- name: String
+ name: String!
+ kind: BusinessPortalKind!
description: String
+ url: String
logo: String
icon: String
headerHtml: String
footerHtml: String
- url: String
+
domain: String
+ dnsStatus: String
messengerBrandCode: String
+ kbToggle: Boolean,
knowledgeBaseLabel: String
knowledgeBaseTopicId: String
ticketLabel: String
- taskLabel: String
dealLabel: String
purchaseLabel: String
+
+ taskToggle: Boolean,
+ publicTaskToggle: Boolean,
taskPublicBoardId: String
taskPublicPipelineId: String
taskPublicLabel: String
+ taskLabel: String
taskStageId: String
taskPipelineId: String
taskBoardId: String
+ ticketToggle: Boolean,
ticketStageId: String
ticketPipelineId: String
ticketBoardId: String
+ dealToggle: Boolean,
dealStageId: String
dealPipelineId: String
dealBoardId: String
+ purchaseToggle: Boolean,
purchaseStageId: String
purchasePipelineId: String
purchaseBoardId: String
@@ -273,12 +265,6 @@ export const mutations = cardAvailable => `
erxesAppToken: String
styles: StylesParams
mobileResponsive: Boolean
- kbToggle: Boolean,
- publicTaskToggle: Boolean,
- ticketToggle: Boolean,
- dealToggle: Boolean,
- purchaseToggle: Boolean,
- taskToggle: Boolean,
otpConfig: OTPConfigInput
mailConfig: MailConfigInput
@@ -287,6 +273,52 @@ export const mutations = cardAvailable => `
tokenPassMethod: TokenPassMethod
tokenExpiration: Int
refreshTokenExpiration: Int
+ vendorParentProductCategoryId: String
+ }
+`;
+
+export const queries = (cardAvailable, kbAvailable, formsAvailable) => `
+ clientPortalGetConfigs(kind:BusinessPortalKind, page: Int, perPage: Int): [ClientPortal]
+ clientPortalGetConfig(_id: String!): ClientPortal
+ clientPortalGetConfigByDomain: ClientPortal
+ clientPortalGetLast(kind: BusinessPortalKind): ClientPortal
+ clientPortalConfigsTotalCount: Int
+ ${
+ formsAvailable
+ ? `
+ clientPortalGetAllowedFields(_id: String!): [Field]
+ `
+ : ''
+ }
+ ${
+ cardAvailable
+ ? `
+ clientPortalGetTaskStages: [Stage]
+ clientPortalGetTasks(stageId: String!): [Task]
+ clientPortalTickets(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Ticket]
+ clientPortalDeals(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Deal]
+ clientPortalPurchases(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Purchase]
+ clientPortalTasks(priority: [String], labelIds:[String], stageId: String, userIds: [String], closeDateType: String, date: ItemDate): [Task]
+ clientPortalTicket(_id: String!): Ticket
+ clientPortalCardUsers(contentType: String!, contentTypeId: String!, userKind: BusinessPortalKind): [ClientPortalUser]
+ `
+ : ''
+ }
+
+ ${
+ kbAvailable
+ ? `
+ clientPortalKnowledgeBaseTopicDetail(_id: String!): KnowledgeBaseTopic
+ clientPortalKnowledgeBaseArticles(searchValue: String, categoryIds: [String], topicId: String):
+[KnowledgeBaseArticle]
+ `
+ : ''
+ }
+`;
+
+export const mutations = cardAvailable => `
+ clientPortalConfigUpdate (
+ config: ClientPortalConfigInput!
): ClientPortal
clientPortalRemove (_id: String!): JSON
diff --git a/packages/plugin-clientportal-api/src/graphql/typeDefs.ts b/packages/plugin-clientportal-api/src/graphql/typeDefs.ts
index 6ca246effa..e000a1e7ad 100644
--- a/packages/plugin-clientportal-api/src/graphql/typeDefs.ts
+++ b/packages/plugin-clientportal-api/src/graphql/typeDefs.ts
@@ -32,12 +32,18 @@ const typeDefs = async serviceDiscovery => {
const cardAvailable = await serviceDiscovery.isEnabled('cards');
const isContactsEnabled = await serviceDiscovery.isEnabled('contacts');
const formsAvailable = await serviceDiscovery.isEnabled('forms');
+ const productsAvailable = await serviceDiscovery.isEnabled('products');
return gql`
scalar JSON
scalar Date
- ${clientPortalTypes(cardAvailable, kbAvailable, formsAvailable)}
+ ${clientPortalTypes(
+ cardAvailable,
+ kbAvailable,
+ formsAvailable,
+ productsAvailable
+ )}
${clientPortalUserTypes(isContactsEnabled)}
${notificationTypes}
${commentTypes}
diff --git a/packages/plugin-clientportal-api/src/logUtils.ts b/packages/plugin-clientportal-api/src/logUtils.ts
new file mode 100644
index 0000000000..7a1a94624e
--- /dev/null
+++ b/packages/plugin-clientportal-api/src/logUtils.ts
@@ -0,0 +1,127 @@
+import {
+ putCreateLog as commonPutCreateLog,
+ putUpdateLog as commonPutUpdateLog,
+ putDeleteLog as commonPutDeleteLog,
+ putActivityLog as commonPutActivityLog,
+ LogDesc,
+ IDescriptions,
+ getSchemaLabels
+} from '@erxes/api-utils/src/logUtils';
+
+import { IModels } from './connectionResolver';
+import messageBroker from './messageBroker';
+import { clientPortalUserSchema } from './models/definitions/clientPortalUser';
+
+export const LOG_ACTIONS = {
+ CREATE: 'create',
+ UPDATE: 'update',
+ DELETE: 'delete'
+};
+
+const gatherDescriptions = async (
+ _args,
+ _args1,
+ params: any
+): Promise => {
+ const { action, object } = params;
+
+ const extraDesc: LogDesc[] = [];
+ const description = `"${object.name}" has been ${action}d`;
+
+ return { extraDesc, description };
+};
+
+export const putDeleteLog = async (
+ models: IModels,
+ subdomain: string,
+ logDoc,
+ user
+) => {
+ const { description, extraDesc } = await gatherDescriptions(
+ models,
+ subdomain,
+ {
+ ...logDoc,
+ action: LOG_ACTIONS.DELETE
+ }
+ );
+
+ await commonPutDeleteLog(
+ subdomain,
+ messageBroker(),
+ { ...logDoc, description, extraDesc, type: `processes:${logDoc.type}` },
+ user
+ );
+};
+
+export const putUpdateLog = async (
+ models: IModels,
+ subdomain: string,
+ logDoc,
+ user
+) => {
+ const { description, extraDesc } = await gatherDescriptions(
+ models,
+ subdomain,
+ {
+ ...logDoc,
+ action: LOG_ACTIONS.UPDATE
+ }
+ );
+
+ await commonPutUpdateLog(
+ subdomain,
+ messageBroker(),
+ { ...logDoc, description, extraDesc, type: `processes:${logDoc.type}` },
+ user
+ );
+};
+
+export const putCreateLog = async (
+ models: IModels,
+ subdomain: string,
+ logDoc,
+ user
+) => {
+ const { description, extraDesc } = await gatherDescriptions(
+ models,
+ subdomain,
+ {
+ ...logDoc,
+ action: LOG_ACTIONS.CREATE
+ }
+ );
+
+ await commonPutCreateLog(
+ subdomain,
+ messageBroker(),
+ { ...logDoc, description, extraDesc, type: `processes:${logDoc.type}` },
+ user
+ );
+};
+
+export const putActivityLog = async (
+ subdomain,
+ params: { action: string; data: any }
+) => {
+ const { data, action } = params;
+
+ const updatedParams = {
+ ...params,
+ data
+ };
+
+ return commonPutActivityLog(subdomain, {
+ messageBroker: messageBroker(),
+ ...updatedParams
+ });
+};
+
+export default {
+ getSchemaLabels: ({ data: { type } }) => ({
+ status: 'success',
+ data: getSchemaLabels(type, [
+ { name: 'clientPortalUser', schemas: [clientPortalUserSchema] }
+ ])
+ })
+};
diff --git a/packages/plugin-clientportal-api/src/models/ClientPortal.ts b/packages/plugin-clientportal-api/src/models/ClientPortal.ts
index ef90109129..49d8106731 100644
--- a/packages/plugin-clientportal-api/src/models/ClientPortal.ts
+++ b/packages/plugin-clientportal-api/src/models/ClientPortal.ts
@@ -42,11 +42,13 @@ export const loadClientPortalClass = (models: IModels) => {
return config.toJSON();
}
- return models.ClientPortals.findOneAndUpdate(
+ await models.ClientPortals.findOneAndUpdate(
{ _id: config._id },
{ $set: doc },
{ new: true }
);
+
+ return models.ClientPortals.findOne({ _id: config._id });
}
}
diff --git a/packages/plugin-clientportal-api/src/models/ClientPortalCompany.ts b/packages/plugin-clientportal-api/src/models/ClientPortalCompany.ts
new file mode 100644
index 0000000000..259f097b9e
--- /dev/null
+++ b/packages/plugin-clientportal-api/src/models/ClientPortalCompany.ts
@@ -0,0 +1,74 @@
+import { Model } from 'mongoose';
+import { IModels } from '../connectionResolver';
+import {
+ companySchema,
+ IClientCompany,
+ IClientCompanyDocument
+} from './definitions/clientPortalCompany';
+
+export interface IClientCompanyModel extends Model {
+ getCompany(_id: string): Promise;
+ createOrUpdateCompany(doc: IClientCompany): Promise;
+ createCompany(doc: IClientCompany): Promise;
+ updateCompany(
+ _id: string,
+ doc: IClientCompany
+ ): Promise;
+ deleteCompany(_id: string): void;
+}
+
+export const loadCompanyClass = (models: IModels) => {
+ class Company {
+ /**
+ * Retreives clientPortalCompany
+ */
+ public static async getCompany(_id: string) {
+ const clientPortalCompany = await models.Companies.findOne({ _id });
+
+ if (!clientPortalCompany) {
+ throw new Error('Company not found');
+ }
+
+ return clientPortalCompany;
+ }
+
+ public static async createCompany(doc: IClientCompanyDocument) {
+ return models.Companies.create({
+ ...doc,
+ createdAt: new Date()
+ });
+ }
+
+ public static async updateCompany(
+ _id: string,
+ doc: IClientCompanyDocument
+ ) {
+ await models.Companies.updateOne({ _id }, { $set: doc });
+
+ return this.getCompany(_id);
+ }
+
+ public static async deleteCompany(_id: string) {
+ return models.Companies.deleteOne({ _id });
+ }
+
+ public static async createOrUpdateCompany(doc: IClientCompanyDocument) {
+ const { erxesCompanyId, clientPortalId } = doc;
+
+ const company = await models.Companies.findOne({
+ erxesCompanyId,
+ clientPortalId
+ });
+
+ if (company) {
+ return this.updateCompany(company._id, doc);
+ }
+
+ return this.createCompany(doc);
+ }
+ }
+
+ companySchema.loadClass(Company);
+
+ return companySchema;
+};
diff --git a/packages/plugin-clientportal-api/src/models/ClientPortalUser.ts b/packages/plugin-clientportal-api/src/models/ClientPortalUser.ts
index 4fe9231019..46ea60f728 100644
--- a/packages/plugin-clientportal-api/src/models/ClientPortalUser.ts
+++ b/packages/plugin-clientportal-api/src/models/ClientPortalUser.ts
@@ -341,7 +341,7 @@ export const loadClientPortalUserClass = (models: IModels) => {
}
/**
- * Remove remove Client Portal Users
+ * Remove remove Business Portal Users
*/
public static async removeUser(
subdomain: string,
diff --git a/packages/plugin-clientportal-api/src/models/ClientPortalUserCard.ts b/packages/plugin-clientportal-api/src/models/ClientPortalUserCard.ts
index ce84440208..a3282043ec 100644
--- a/packages/plugin-clientportal-api/src/models/ClientPortalUserCard.ts
+++ b/packages/plugin-clientportal-api/src/models/ClientPortalUserCard.ts
@@ -9,15 +9,8 @@ import {
} from './definitions/clientPortalUserCards';
export interface ICPUserCardModel extends Model {
- createOrUpdateCard(
- doc: ICPUserCard,
- userId: string
- ): Promise;
- removeUserFromCard(
- cardId: string,
- userId: string
- ): Promise;
- getUserIds(type: string, cardId: string): Promise;
+ createOrUpdateCard(doc: ICPUserCard): Promise;
+ getUserIds(contentType: string, contentTypeId: string): Promise;
}
export const loadUserCardClass = (models: IModels) => {
@@ -30,58 +23,30 @@ export const loadUserCardClass = (models: IModels) => {
*/
public static async createOrUpdateCard(doc: ICPUserCard, userId: string) {
const card = await models.ClientPortalUserCards.findOne({
- type: doc.type,
- cardId: doc.cardId
+ contentType: doc.contentType,
+ contentTypeId: doc.contentTypeId
});
if (!card) {
return models.ClientPortalUserCards.create({
...doc,
- userIds: [userId]
+ userId
});
}
- if (card.userIds.indexOf(userId) === -1) {
- card.userIds.push(userId);
-
- await card.save();
-
- return card;
- } else {
- return card;
- }
- }
-
- /**
- * Remove user from card
- * @param cardId
- * @param userId
- * @return {Promise}
- * @memberof CleintPortalUserCard
- */
-
- public static async removeUserFromCard(cardId: string, userId: string) {
- const card = await models.ClientPortalUserCards.findOne({
- cardId
+ await models.ClientPortalUserCards.updateOne(
+ { _id: card._id },
+ {
+ $set: {
+ ...doc,
+ modifiedAt: new Date()
+ }
+ }
+ );
+
+ return models.ClientPortalUserCards.findOne({
+ _id: card._id
});
-
- if (!card) {
- throw new Error('Card not found');
- }
-
- const index = card.userIds.indexOf(userId);
-
- if (index > -1) {
- card.userIds.splice(index, 1);
- }
-
- await card.save();
-
- if (card.userIds.length === 0) {
- await card.remove();
- }
-
- return card;
}
/**
@@ -91,17 +56,23 @@ export const loadUserCardClass = (models: IModels) => {
* @memberof CleintPortalUserCard
*/
- public static async getUserIds(type: string, cardId: string) {
- const card = await models.ClientPortalUserCards.findOne({
- cardId,
- type
- });
-
- if (!card) {
- throw new Error('Card not found');
- }
-
- return card.userIds;
+ public static async getUserIds(contentType: string, contentTypeId: string) {
+ // aggregate and return array of cpUserId field of ClientPortalUserCards
+ const userIds = await models.ClientPortalUserCards.aggregate([
+ {
+ $match: {
+ contentType,
+ contentTypeId
+ }
+ },
+ {
+ $project: {
+ cpUserId: 1
+ }
+ }
+ ]);
+
+ return userIds.map((user: any) => user.cpUserId);
}
}
diff --git a/packages/plugin-clientportal-api/src/models/definitions/clientPortal.ts b/packages/plugin-clientportal-api/src/models/definitions/clientPortal.ts
index 90dfd46ab9..aafcc3c9f0 100644
--- a/packages/plugin-clientportal-api/src/models/definitions/clientPortal.ts
+++ b/packages/plugin-clientportal-api/src/models/definitions/clientPortal.ts
@@ -36,6 +36,7 @@ export interface IPasswordVerificationConfig {
export interface IClientPortal {
_id?: string;
name?: string;
+ kind: 'client' | 'vendor';
description?: string;
logo?: string;
icon?: string;
@@ -89,6 +90,8 @@ export interface IClientPortal {
dealToggle?: boolean;
purchaseToggle?: boolean;
taskToggle?: boolean;
+
+ vendorParentProductCategoryId?: string;
}
interface IStyles {
@@ -164,6 +167,11 @@ export const clientPortalSchema = new Schema({
_id: field({ pkey: true }),
name: field({ type: String }),
description: field({ type: String, optional: true }),
+ kind: field({
+ type: String,
+ enum: ['client', 'vendor'],
+ default: 'client'
+ }),
url: field({ type: String }),
logo: field({ type: String, optional: true }),
icon: field({ type: String, optional: true }),
@@ -261,5 +269,10 @@ export const clientPortalSchema = new Schema({
default: 'cookie',
label: 'Token pass method',
enum: ['cookie', 'header']
+ }),
+
+ vendorParentProductCategoryId: field({
+ type: String,
+ optional: true
})
});
diff --git a/packages/plugin-clientportal-api/src/models/definitions/clientPortalCompany.ts b/packages/plugin-clientportal-api/src/models/definitions/clientPortalCompany.ts
new file mode 100644
index 0000000000..7b0f12838a
--- /dev/null
+++ b/packages/plugin-clientportal-api/src/models/definitions/clientPortalCompany.ts
@@ -0,0 +1,21 @@
+import { field } from '@erxes/api-utils/src';
+import { Document, Schema } from 'mongoose';
+
+export interface IClientCompany {
+ erxesCompanyId: string;
+ productCategoryIds?: string[];
+ clientPortalId: string;
+}
+
+export interface IClientCompanyDocument extends IClientCompany, Document {
+ _id: string;
+ createdAt?: Date;
+}
+
+export const companySchema = new Schema({
+ _id: field({ pkey: true }),
+ erxesCompanyId: field({ type: String }),
+ productCategoryIds: field({ type: [String] }),
+ clientPortalId: field({ type: String }),
+ createdAt: field({ type: Date, default: Date.now })
+});
diff --git a/packages/plugin-clientportal-api/src/models/definitions/clientPortalUser.ts b/packages/plugin-clientportal-api/src/models/definitions/clientPortalUser.ts
index 7d97be6c1c..d1dcd01b2e 100644
--- a/packages/plugin-clientportal-api/src/models/definitions/clientPortalUser.ts
+++ b/packages/plugin-clientportal-api/src/models/definitions/clientPortalUser.ts
@@ -168,7 +168,6 @@ export const clientPortalUserSchema = new Schema({
label: 'Company registration number'
}),
clientPortalId: field({ type: String, required: true }),
-
erxesCompanyId: field({ type: String, optional: true }),
erxesCustomerId: field({ type: String, optional: true }),
phoneVerificationCode: field({ type: String, optional: true }),
diff --git a/packages/plugin-clientportal-api/src/models/definitions/clientPortalUserCards.ts b/packages/plugin-clientportal-api/src/models/definitions/clientPortalUserCards.ts
index 3d88e9f9ee..15a7e22d49 100644
--- a/packages/plugin-clientportal-api/src/models/definitions/clientPortalUserCards.ts
+++ b/packages/plugin-clientportal-api/src/models/definitions/clientPortalUserCards.ts
@@ -2,20 +2,54 @@ import { Document, Schema } from 'mongoose';
import { field } from './utils';
export interface ICPUserCard {
- type: 'deal' | 'task' | 'ticket' | 'purchase';
- cardId: string;
+ contentType: 'deal' | 'task' | 'ticket' | 'purchase';
+ contentTypeId: string;
+ cpUserId: string;
+ status?:
+ | 'participating'
+ | 'invited'
+ | 'left'
+ | 'rejected'
+ | 'won'
+ | 'lost'
+ | 'completed';
+ paymentStatus?: 'paid' | 'unpaid';
+ paymentAmount?: number;
+ offeredAmount?: number;
+ hasVat?: boolean;
}
export interface ICPUserCardDocument extends ICPUserCard, Document {
_id: string;
- userIds: string[];
createdAt: Date;
+ modifiedAt: Date;
}
export const cpUserCardSchema = new Schema({
_id: field({ pkey: true }),
- type: field({ type: String }),
- cardId: field({ type: String }),
- userIds: field({ type: [String] }),
- createdAt: field({ type: Date, default: Date.now })
+ contentType: field({
+ type: String,
+ enum: ['deal', 'task', 'ticket', 'purchase']
+ }),
+ contentTypeId: field({ type: String }),
+ cpUserId: field({ type: String }),
+ status: field({
+ type: String,
+ default: 'participating',
+ enum: [
+ 'participating',
+ 'invited',
+ 'left',
+ 'rejected',
+ 'won',
+ 'lost',
+ 'completed'
+ ]
+ }),
+ paymentStatus: field({ type: String, enum: ['paid', 'unpaid'] }),
+ paymentAmount: field({ type: Number }),
+ offeredAmount: field({ type: Number }),
+ hasVat: field({ type: Boolean }),
+ createdAt: field({ type: Date, default: Date.now }),
+ modifiedAt: field({ type: Date, default: Date.now })
});
diff --git a/packages/plugin-clientportal-api/src/permissions.js b/packages/plugin-clientportal-api/src/permissions.js
index 3da3209e7b..957ca2e7c2 100644
--- a/packages/plugin-clientportal-api/src/permissions.js
+++ b/packages/plugin-clientportal-api/src/permissions.js
@@ -1,7 +1,7 @@
module.exports = {
clientPortal: {
name: 'clientPortal',
- description: 'Client portal',
+ description: 'Business portal',
actions: [
{
name: 'clientPortalAll',
diff --git a/packages/plugin-clientportal-api/src/utils.ts b/packages/plugin-clientportal-api/src/utils.ts
index 6e37a93395..ff39bb63b6 100644
--- a/packages/plugin-clientportal-api/src/utils.ts
+++ b/packages/plugin-clientportal-api/src/utils.ts
@@ -16,6 +16,7 @@ import {
import * as admin from 'firebase-admin';
import { CLOSE_DATE_TYPES } from './constants';
+import { IUser } from './models/definitions/clientPortalUser';
export const getConfig = async (
code: string,
@@ -585,3 +586,19 @@ export const getCloseDateByType = (closeDateType: string) => {
return { $lt: today };
}
};
+
+export const getUserName = (data: IUser) => {
+ if (!data) {
+ return null;
+ }
+
+ if (data.firstName || data.lastName) {
+ return data.firstName + ' ' + data.lastName;
+ }
+
+ if (data.email || data.username || data.phone) {
+ return data.email || data.username || data.phone;
+ }
+
+ return 'Unknown';
+};
diff --git a/packages/plugin-clientportal-ui/src/components/ClientPortal.tsx b/packages/plugin-clientportal-ui/src/components/ClientPortal.tsx
index 60f7bf3e77..b112984e5b 100644
--- a/packages/plugin-clientportal-ui/src/components/ClientPortal.tsx
+++ b/packages/plugin-clientportal-ui/src/components/ClientPortal.tsx
@@ -10,15 +10,21 @@ import { __ } from '@erxes/ui/src/utils/core';
type Props = {
queryParams: any;
loading?: boolean;
+ kind: 'client' | 'vendor';
} & IRouterProps;
class ClientPortal extends React.Component {
render() {
const { loading = false, queryParams, history } = this.props;
+ const text = this.props.kind === 'client' ? 'Client' : 'Vendor';
const breadcrumb = [
{ title: __('Settings'), link: '/settings' },
- { title: __('Client Portal'), link: '/settings/client-portal' }
+ { title: __('Business Portal'), link: '/settings/business-portal' },
+ {
+ title: __(`${text} Portal`),
+ link: `/settings/business-portal/${this.props.kind}`
+ }
];
const count = queryParams._id ? 1 : 0;
@@ -26,14 +32,14 @@ class ClientPortal extends React.Component {
return (
+
}
mainHead={
}
@@ -44,11 +50,12 @@ class ClientPortal extends React.Component {
}
count={count}
loading={loading}
- emptyText="Getting Started with Client Portal"
+ emptyText="Getting Started with Business Portal"
emptyImage="/images/actions/13.svg"
/>
}
diff --git a/packages/plugin-clientportal-ui/src/components/ClientPortalDetail.tsx b/packages/plugin-clientportal-ui/src/components/ClientPortalDetail.tsx
index 85b177051a..bf01fd1d52 100644
--- a/packages/plugin-clientportal-ui/src/components/ClientPortalDetail.tsx
+++ b/packages/plugin-clientportal-ui/src/components/ClientPortalDetail.tsx
@@ -8,6 +8,7 @@ import Form from './Form';
type Props = {
config: ClientPortalConfig;
+ kind: 'client' | 'vendor';
handleUpdate: (doc: ClientPortalConfig) => void;
};
diff --git a/packages/plugin-clientportal-ui/src/components/FieldConfigForm.tsx b/packages/plugin-clientportal-ui/src/components/FieldConfigForm.tsx
index ecb4cafaea..50d83ac56b 100644
--- a/packages/plugin-clientportal-ui/src/components/FieldConfigForm.tsx
+++ b/packages/plugin-clientportal-ui/src/components/FieldConfigForm.tsx
@@ -65,9 +65,9 @@ function FieldConfigForm(props: Props) {
return (
<>
-
+
- {__('Allowed Client Portals')}
+ {__('Allowed Business Portals')}
{__('Please select client portals that can use this field.')}
From a9eabae904c74d871f045c0dafb10f841b34aebe Mon Sep 17 00:00:00 2001
From: orgilshdeee
Date: Wed, 25 Oct 2023 16:52:41 +0800
Subject: [PATCH 20/64] added ebarimtConfig fixes
---
.../src/components/GeneralSettings.tsx | 11 +++++++---
.../src/components/PerSettings.tsx | 9 +++++---
.../src/components/ReturnPerSettings.tsx | 9 +++++---
.../src/components/ReturnStageSettings.tsx | 21 +++++++++----------
.../src/components/Sidebar.tsx | 2 +-
.../src/components/StageSettings.tsx | 18 +++++++++-------
.../src/containers/Settings.tsx | 5 +----
packages/plugin-ebarimt-ui/src/styles.ts | 1 -
8 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/packages/plugin-ebarimt-ui/src/components/GeneralSettings.tsx b/packages/plugin-ebarimt-ui/src/components/GeneralSettings.tsx
index 0dff74b934..f79424cbdb 100644
--- a/packages/plugin-ebarimt-ui/src/components/GeneralSettings.tsx
+++ b/packages/plugin-ebarimt-ui/src/components/GeneralSettings.tsx
@@ -3,7 +3,8 @@ import {
CollapseContent,
ControlLabel,
FormControl,
- FormGroup
+ FormGroup,
+ Icon
} from '@erxes/ui/src/components';
import { __ } from '@erxes/ui/src/utils';
import { Wrapper } from '@erxes/ui/src/layout';
@@ -77,7 +78,7 @@ class GeneralSettings extends React.Component {
const actionButtons = (