@webinex/chatify 2.0.0-alpha10 → 2.0.0-alpha12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/{Chatify-DGRV4QKP.js → Chatify-CwAfN1wu.js} +310 -117
  2. package/dist/Chatify-CwAfN1wu.js.map +1 -0
  3. package/dist/Chatify.css +54 -7
  4. package/dist/audit.js +2 -2
  5. package/dist/audit.js.map +1 -1
  6. package/dist/index.js +82 -75
  7. package/dist/types/audit/auditApi.d.ts +5 -1
  8. package/dist/types/core/client.d.ts +4 -1
  9. package/dist/types/ui/ChatGroup/AutoReply/AutoReplyButton.d.ts +1 -0
  10. package/dist/types/ui/ChatGroup/AutoReply/AutoReplyForm.d.ts +12 -0
  11. package/dist/types/ui/ChatGroup/AutoReply/AutoReplyPanel.d.ts +1 -0
  12. package/dist/types/ui/ChatGroup/AutoReply/AutoReplyPeriodInput.d.ts +4 -0
  13. package/dist/types/ui/ChatGroup/AutoReply/AutoReplyTextInput.d.ts +4 -0
  14. package/dist/types/ui/ChatGroup/AutoReply/index.d.ts +17 -0
  15. package/dist/types/ui/ChatGroup/ChatGroupContext.d.ts +2 -1
  16. package/dist/types/ui/ChatGroup/ChatGroupPanel.d.ts +2 -1
  17. package/dist/types/ui/ChatGroup/Layout/ChatGroupActions.d.ts +1 -0
  18. package/dist/types/ui/ChatGroup/Layout/index.d.ts +3 -0
  19. package/dist/types/ui/ChatGroup/index.d.ts +1 -0
  20. package/dist/types/ui/common/Icon.d.ts +1 -0
  21. package/dist/types/ui/localizer.d.ts +15 -0
  22. package/package.json +1 -1
  23. package/src/audit/AuditSearch.tsx +1 -1
  24. package/src/core/api/api.ts +16 -2
  25. package/src/core/client.ts +13 -2
  26. package/src/styles/index.scss +65 -6
  27. package/src/ui/Chat/Members/ChatMembersPanel.tsx +2 -2
  28. package/src/ui/ChatGroup/AutoReply/AutoReplyButton.tsx +21 -0
  29. package/src/ui/ChatGroup/AutoReply/AutoReplyForm.tsx +50 -0
  30. package/src/ui/ChatGroup/AutoReply/AutoReplyPanel.tsx +94 -0
  31. package/src/ui/ChatGroup/AutoReply/AutoReplyPeriodInput.tsx +22 -0
  32. package/src/ui/ChatGroup/AutoReply/AutoReplyTextInput.tsx +22 -0
  33. package/src/ui/ChatGroup/AutoReply/index.ts +19 -0
  34. package/src/ui/ChatGroup/ChatGroupContext.tsx +12 -1
  35. package/src/ui/ChatGroup/ChatGroupPanel.tsx +2 -0
  36. package/src/ui/ChatGroup/Create/CreateChatMemberInput.tsx +1 -1
  37. package/src/ui/ChatGroup/Layout/ChatGroupActions.tsx +15 -0
  38. package/src/ui/ChatGroup/Layout/ChatGroupAside.tsx +2 -2
  39. package/src/ui/ChatGroup/Layout/ChatGroupMain.tsx +2 -0
  40. package/src/ui/ChatGroup/Layout/index.ts +3 -0
  41. package/src/ui/ChatGroup/index.ts +1 -0
  42. package/src/ui/common/Icon.tsx +2 -0
  43. package/src/ui/localizer.tsx +29 -0
  44. package/dist/Chatify-DGRV4QKP.js.map +0 -1
  45. package/dist/types/core/api/api.d.ts +0 -17295
@@ -32,7 +32,7 @@ function useRemove(chatId: string, accountId: string, deleteHistory: boolean) {
32
32
  const ChatMemberListItem = customize('ChatMemberListItem', (props: ChatMemberListItemProps) => {
33
33
  const { chatId } = props;
34
34
  const { data: chat } = chatifyApi.useGetChatQuery({ id: chatId });
35
- const { data: accounts } = chatifyApi.useGetAccountListQuery();
35
+ const { data: accounts } = chatifyApi.useGetAccountListQuery({});
36
36
  const account = accounts!.find((x) => x.id === props.id)!;
37
37
  const isMember = chat!.members.some((x) => x.id === account.id);
38
38
  const [onAddWithoutHistory] = useAdd(chatId, account.id, false);
@@ -82,7 +82,7 @@ const ChatMemberListItem = customize('ChatMemberListItem', (props: ChatMemberLis
82
82
  export const ChatMembersPanel = customize('ChatMembersPanel', () => {
83
83
  const { id } = useChatContext();
84
84
  const { data: chat } = chatifyApi.useGetChatQuery({ id });
85
- const { data: accounts } = chatifyApi.useGetAccountListQuery();
85
+ const { data: accounts } = chatifyApi.useGetAccountListQuery({});
86
86
  const ordered = useMemo(
87
87
  () =>
88
88
  accounts
@@ -0,0 +1,21 @@
1
+ import { Button } from 'antd';
2
+ import { customize } from '../../customize';
3
+ import { useChatGroupContext } from '../ChatGroupContext';
4
+ import { useLocalizer } from '../../localizer';
5
+ import { Icon } from '../../common/Icon';
6
+
7
+ export const AutoReplyButton = customize('AutoReplyButton', () => {
8
+ const { toggleAutoReply } = useChatGroupContext();
9
+ const localizer = useLocalizer();
10
+ const titleText = localizer.autoReply.buttonTitle();
11
+
12
+ return (
13
+ <Button
14
+ className="wxchtf-add-btn-settings"
15
+ onClick={toggleAutoReply}
16
+ icon={<Icon type="settings" />}
17
+ title={titleText}
18
+ aria-label={titleText}
19
+ />
20
+ );
21
+ });
@@ -0,0 +1,50 @@
1
+ import { Button, Form } from 'antd';
2
+ import { Dayjs } from 'dayjs';
3
+ import { customize } from '../../customize';
4
+ import { useLocalizer } from '../../localizer';
5
+ import { AutoReplyPeriodInput } from './AutoReplyPeriodInput';
6
+ import { AutoReplyTextInput } from './AutoReplyTextInput';
7
+ import { useEffect } from 'react';
8
+
9
+ export interface AutoReplyFormValue {
10
+ period: [Dayjs, Dayjs];
11
+ text: string;
12
+ }
13
+
14
+ export interface AutoReplyFormProps {
15
+ value: AutoReplyFormValue;
16
+ onSubmit: (value: AutoReplyFormValue) => void;
17
+ busy?: boolean;
18
+ }
19
+
20
+ export const AUTO_REPLY_FORM_INITIAL_VALUE: AutoReplyFormValue = {
21
+ period: [] as unknown as [Dayjs, Dayjs],
22
+ text: '',
23
+ };
24
+
25
+ export const AutoReplyForm = customize('AutoReplyForm', (props: AutoReplyFormProps) => {
26
+ const { value, busy = false, onSubmit } = props;
27
+ const localizer = useLocalizer();
28
+
29
+ const [form] = Form.useForm<AutoReplyFormValue>();
30
+
31
+ useEffect(() => {
32
+ form.setFieldsValue(value);
33
+ }, [value, form]);
34
+
35
+ return (
36
+ <Form<AutoReplyFormValue>
37
+ form={form}
38
+ layout="vertical"
39
+ onFinish={onSubmit}
40
+ disabled={busy}
41
+ initialValues={value}
42
+ >
43
+ <AutoReplyPeriodInput name="period" />
44
+ <AutoReplyTextInput name="text" />
45
+ <Button loading={busy} type="primary" block htmlType="submit">
46
+ {localizer.autoReply.submitBtn()}
47
+ </Button>
48
+ </Form>
49
+ );
50
+ });
@@ -0,0 +1,94 @@
1
+ import dayjs from 'dayjs';
2
+ import { useCallback, useMemo } from 'react';
3
+ import { Button } from 'antd';
4
+ import { customize } from '../../customize';
5
+ import { useLocalizer } from '../../localizer';
6
+ import { useChatGroupContext } from '../ChatGroupContext';
7
+ import { Icon } from '../../common/Icon';
8
+ import { AutoReply } from '../../../core';
9
+ import { chatifyApi } from '../../../core';
10
+ import { AUTO_REPLY_FORM_INITIAL_VALUE, AutoReplyForm, AutoReplyFormValue } from './AutoReplyForm';
11
+
12
+ function mapToFormValue(autoReply?: AutoReply | null): AutoReplyFormValue {
13
+ if (!autoReply) {
14
+ return AUTO_REPLY_FORM_INITIAL_VALUE;
15
+ }
16
+
17
+ return {
18
+ period: [dayjs(autoReply.period.start), dayjs(autoReply.period.end)],
19
+ text: autoReply.text,
20
+ };
21
+ }
22
+
23
+ function useValue() {
24
+ const { data: me } = chatifyApi.useGeCurrentUserAccountQuery();
25
+
26
+ const value = useMemo<AutoReplyFormValue>(() => {
27
+ return mapToFormValue(me?.autoReply);
28
+ }, [me]);
29
+
30
+ return value;
31
+ }
32
+
33
+ function useAutoReplyActions() {
34
+ const meId = chatifyApi.settings.me();
35
+ const [updateAccount, { isLoading }] = chatifyApi.useUpdateAccountMutation();
36
+
37
+ const onSubmit = useCallback(
38
+ (value: AutoReplyFormValue) =>
39
+ updateAccount({
40
+ id: meId,
41
+ autoReply: {
42
+ hasValue: true,
43
+ value: {
44
+ text: value.text,
45
+ period: {
46
+ start: value.period[0].toISOString(),
47
+ end: value.period[1].toISOString(),
48
+ },
49
+ },
50
+ },
51
+ }).unwrap(),
52
+ [updateAccount, meId],
53
+ );
54
+
55
+ const onClear = useCallback(
56
+ () =>
57
+ updateAccount({
58
+ id: meId,
59
+ autoReply: {
60
+ hasValue: true,
61
+ value: null,
62
+ },
63
+ }).unwrap(),
64
+ [updateAccount, meId],
65
+ );
66
+
67
+ return [onSubmit, isLoading, onClear] as const;
68
+ }
69
+
70
+ export const AutoReplyPanel = customize('AutoReplyPanel', () => {
71
+ const localizer = useLocalizer();
72
+ const { toggleAutoReply } = useChatGroupContext();
73
+ const value = useValue();
74
+ const [onSubmit, submitting, onClear] = useAutoReplyActions();
75
+
76
+ return (
77
+ <div className="wxchtf-auto-reply-panel">
78
+ <Button
79
+ onClick={toggleAutoReply}
80
+ className="wxchtf-auto-reply-panel-close"
81
+ type="link"
82
+ icon={<Icon type="close" />}
83
+ />
84
+ <div className="wxchtf-auto-reply-panel-header">
85
+ <h3>{localizer.autoReply.title()}</h3>
86
+ <Button type="link" onClick={onClear} disabled={submitting} className="wxchtf-auto-reply-panel-clear">
87
+ {localizer.autoReply.clearBtn()}
88
+ </Button>
89
+ </div>
90
+
91
+ <AutoReplyForm value={value} busy={submitting ?? false} onSubmit={onSubmit} />
92
+ </div>
93
+ );
94
+ });
@@ -0,0 +1,22 @@
1
+ import { DatePicker, Form } from 'antd';
2
+ import { customize } from '../../customize';
3
+ import { useLocalizer } from '../../localizer';
4
+
5
+ export interface AutoReplyPeriodInputProps {
6
+ name: string;
7
+ }
8
+
9
+ export const AutoReplyPeriodInput = customize('AutoReplyPeriodInput', (props: AutoReplyPeriodInputProps) => {
10
+ const { name } = props;
11
+ const localizer = useLocalizer();
12
+
13
+ return (
14
+ <Form.Item
15
+ label={localizer.autoReply.period.label()}
16
+ name={name}
17
+ rules={[{ required: true, message: localizer.autoReply.period.required() }]}
18
+ >
19
+ <DatePicker.RangePicker format={localizer.autoReply.period.format()} />
20
+ </Form.Item>
21
+ );
22
+ });
@@ -0,0 +1,22 @@
1
+ import { Form, Input } from 'antd';
2
+ import { customize } from '../../customize';
3
+ import { useLocalizer } from '../../localizer';
4
+
5
+ export interface AutoReplyTextInputProps {
6
+ name: string;
7
+ }
8
+
9
+ export const AutoReplyTextInput = customize('AutoReplyTextInput', (props: AutoReplyTextInputProps) => {
10
+ const { name } = props;
11
+ const localizer = useLocalizer();
12
+
13
+ return (
14
+ <Form.Item
15
+ label={localizer.autoReply.text.label()}
16
+ name={name}
17
+ rules={[{ required: true, message: localizer.autoReply.text.required() }]}
18
+ >
19
+ <Input.TextArea rows={4} />
20
+ </Form.Item>
21
+ );
22
+ });
@@ -0,0 +1,19 @@
1
+ import { AutoReplyButton } from './AutoReplyButton';
2
+ import { AutoReplyForm } from './AutoReplyForm';
3
+ import { AutoReplyPanel } from './AutoReplyPanel';
4
+ import { AutoReplyPeriodInput } from './AutoReplyPeriodInput';
5
+ import { AutoReplyTextInput } from './AutoReplyTextInput';
6
+
7
+ export * from './AutoReplyButton';
8
+ export * from './AutoReplyForm';
9
+ export * from './AutoReplyPanel';
10
+ export * from './AutoReplyPeriodInput';
11
+ export * from './AutoReplyTextInput';
12
+
13
+ export interface AutoReplyCustomizeValue {
14
+ AutoReplyButton?: typeof AutoReplyButton.Component | null;
15
+ AutoReplyForm?: typeof AutoReplyForm.Component | null;
16
+ AutoReplyPanel?: typeof AutoReplyPanel.Component | null;
17
+ AutoReplyPeriodInput?: typeof AutoReplyPeriodInput.Component | null;
18
+ AutoReplyTextInput?: typeof AutoReplyTextInput.Component | null;
19
+ }
@@ -1,7 +1,7 @@
1
1
  import React, { PropsWithChildren, useContext, useMemo, useState } from 'react';
2
2
 
3
3
  export interface ChatGroupContext {
4
- view: 'chat' | 'new-chat' | null;
4
+ view: 'chat' | 'new-chat' | 'auto-reply' | null;
5
5
  chatId: string | null;
6
6
  showMembers: boolean;
7
7
 
@@ -9,6 +9,7 @@ export interface ChatGroupContext {
9
9
  openChat(chatId: string): void;
10
10
  toggleNewChat(): void;
11
11
  toggleMembers(): void;
12
+ toggleAutoReply(): void;
12
13
  }
13
14
 
14
15
  const ChatGroupReactContext = React.createContext<ChatGroupContext>(null!);
@@ -42,6 +43,16 @@ export function ChatGroupContext(props: PropsWithChildren<{}>) {
42
43
  return { ...prev, view: 'new-chat' };
43
44
  }
44
45
  }),
46
+ toggleAutoReply: () =>
47
+ setState((prev) => {
48
+ if (prev.view === 'auto-reply' && prev.chatId) {
49
+ return { ...prev, view: 'chat' };
50
+ } else if (prev.view === 'auto-reply' && !prev.chatId) {
51
+ return { ...prev, view: null };
52
+ } else {
53
+ return { ...prev, view: 'auto-reply' };
54
+ }
55
+ }),
45
56
  }),
46
57
  [state],
47
58
  );
@@ -7,9 +7,11 @@ import { ChatGroupContext, useChatGroupContext } from './ChatGroupContext';
7
7
  import { chatifyApi } from '../../core';
8
8
  import { CustomizeContext } from '../customize';
9
9
  import { ChatViewCustomizeValue } from '../Chat';
10
+ import { AutoReplyCustomizeValue } from './AutoReply';
10
11
 
11
12
  export interface ChatGroupCustomizeValue
12
13
  extends ChatViewCustomizeValue,
14
+ AutoReplyCustomizeValue,
13
15
  CreateChatPanelCustomizeValue,
14
16
  ChatListPanelCustomizeValue,
15
17
  ChatGroupLayoutCustomizeValue {}
@@ -16,7 +16,7 @@ interface CheckboxListProps {
16
16
 
17
17
  function CheckboxList(props: CheckboxListProps) {
18
18
  const { value, onChange } = props;
19
- const { data: accounts, isFetching } = chatifyApi.useGetAccountListQuery();
19
+ const { data: accounts, isFetching } = chatifyApi.useGetAccountListQuery({});
20
20
  const me = chatifyApi.settings.me();
21
21
  const dataSource = useMemo(() => accounts?.filter((x) => x.id !== me) ?? [], [accounts, me]);
22
22
 
@@ -0,0 +1,15 @@
1
+ import { Space } from 'antd';
2
+ import { CreateChatButton } from '../Create';
3
+ import { AutoReplyButton } from '../AutoReply/AutoReplyButton';
4
+ import { customize } from '../../customize';
5
+
6
+ export const ChatGroupActions = customize('ChatGroupActions', () => {
7
+ return (
8
+ <span className="wxchtf-add-btn-wrapper">
9
+ <Space.Compact className="wxchtf-add-btn-group">
10
+ <CreateChatButton />
11
+ <AutoReplyButton />
12
+ </Space.Compact>
13
+ </span>
14
+ );
15
+ });
@@ -1,11 +1,11 @@
1
1
  import { customize } from '../../customize';
2
2
  import { ChatListPanel } from '../List';
3
- import { CreateChatButton } from '../Create/CreateChatButton';
3
+ import { ChatGroupActions } from './ChatGroupActions';
4
4
 
5
5
  export const ChatGroupAside = customize('ChatGroupAside', () => {
6
6
  return (
7
7
  <div className="wxchtf-aside">
8
- <CreateChatButton />
8
+ <ChatGroupActions />
9
9
  <ChatListPanel />
10
10
  </div>
11
11
  );
@@ -3,6 +3,7 @@ import { CreateChatPanel } from '../Create';
3
3
  import { ChatView } from '../../Chat';
4
4
  import { useChatGroupContext } from '../ChatGroupContext';
5
5
  import { chatifyApi } from '../../../core';
6
+ import { AutoReplyPanel } from '../AutoReply';
6
7
 
7
8
  export const ChatGroupMain = customize('ChatGroupMain', () => {
8
9
  const { chatId, view } = useChatGroupContext();
@@ -12,6 +13,7 @@ export const ChatGroupMain = customize('ChatGroupMain', () => {
12
13
  <div className="wxchtf-main">
13
14
  {view === 'chat' && chat && <ChatView value={chat} key={chatId} />}
14
15
  {view === 'new-chat' && <CreateChatPanel />}
16
+ {view === 'auto-reply' && <AutoReplyPanel />}
15
17
  </div>
16
18
  );
17
19
  });
@@ -1,9 +1,11 @@
1
+ import { ChatGroupActions } from './ChatGroupActions';
1
2
  import { ChatGroupAside } from './ChatGroupAside';
2
3
  import { ChatGroupHeader } from './ChatGroupHeader';
3
4
  import { ChatGroupFooter } from './ChatGroupFooter';
4
5
  import { ChatGroupMain } from './ChatGroupMain';
5
6
  import { ChatGroupBody } from './ChatGroupBody';
6
7
 
8
+ export * from './ChatGroupActions';
7
9
  export * from './ChatGroupAside';
8
10
  export * from './ChatGroupHeader';
9
11
  export * from './ChatGroupFooter';
@@ -11,6 +13,7 @@ export * from './ChatGroupMain';
11
13
  export * from './ChatGroupBody';
12
14
 
13
15
  export interface ChatGroupLayoutCustomizeValue {
16
+ ChatGroupActions?: typeof ChatGroupActions.Component | null;
14
17
  ChatGroupAside?: typeof ChatGroupAside.Component | null;
15
18
  ChatGroupHeader?: typeof ChatGroupHeader.Component | null;
16
19
  ChatGroupFooter?: typeof ChatGroupFooter.Component | null;
@@ -1,3 +1,4 @@
1
+ export * from './AutoReply';
1
2
  export * from './Create';
2
3
  export * from './Layout';
3
4
  export * from './List';
@@ -14,6 +14,7 @@ import {
14
14
  EyeOutlined,
15
15
  DeleteOutlined,
16
16
  DownloadOutlined,
17
+ SettingOutlined,
17
18
  } from '@ant-design/icons';
18
19
 
19
20
  export type IconType = keyof typeof ICONS;
@@ -37,6 +38,7 @@ export const ICONS = {
37
38
  unwatch: EyeInvisibleOutlined,
38
39
  'delete-file': DeleteOutlined,
39
40
  'open-file': DownloadOutlined,
41
+ settings: SettingOutlined,
40
42
  };
41
43
 
42
44
  export const Icon = customize<FC<IconProps>>('Icon', (props) => {
@@ -43,6 +43,22 @@ export interface LocalizerBase {
43
43
  chatList: {
44
44
  topShown: (count: number) => string;
45
45
  };
46
+
47
+ autoReply: {
48
+ buttonTitle: () => string;
49
+ title: () => React.ReactNode;
50
+ period: {
51
+ label: () => React.ReactNode;
52
+ required: () => string;
53
+ format: () => string;
54
+ };
55
+ text: {
56
+ label: () => React.ReactNode;
57
+ required: () => string;
58
+ };
59
+ submitBtn: () => React.ReactNode;
60
+ clearBtn: () => React.ReactNode;
61
+ };
46
62
  }
47
63
 
48
64
  export interface Localizer extends LocalizerBase {}
@@ -103,6 +119,19 @@ const base: LocalizerBase = {
103
119
  chatList: {
104
120
  topShown: (count: number) => `Latest active ${count} chat${count !== 1 ? 's' : ''} shown`,
105
121
  },
122
+
123
+ autoReply: {
124
+ buttonTitle: () => 'Auto-reply',
125
+ title: () => 'Auto-reply',
126
+ period: {
127
+ label: () => 'Period',
128
+ required: () => 'Please select start and end date',
129
+ format: () => 'DD/MM/YYYY',
130
+ },
131
+ text: { label: () => 'Message', required: () => 'Please enter message' },
132
+ submitBtn: () => 'Submit',
133
+ clearBtn: () => 'Clear',
134
+ },
106
135
  };
107
136
 
108
137
  export const defaultLocalizer: Localizer = base as unknown as Localizer;