quickblox-react-ui-kit 0.1.7 → 0.2.0

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 (48) hide show
  1. package/dist/Presentation/Views/Base/BaseViewModel.d.ts +8 -0
  2. package/dist/Presentation/Views/Dialogs/Dialogs.d.ts +3 -1
  3. package/dist/Presentation/components/UI/Dialogs/DialogInformation/DialogInformation.d.ts +3 -1
  4. package/dist/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/AIWidget.d.ts +8 -0
  5. package/dist/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/ErrorMessageIcon.d.ts +11 -0
  6. package/dist/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/UseDefaultAIAssistAnswerWidgetWithProxy.d.ts +9 -0
  7. package/dist/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/UseDefaultTextInputWidget.d.ts +2 -0
  8. package/dist/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/useDefaultVoiceInputWidget.d.ts +2 -0
  9. package/dist/Presentation/components/UI/Dialogs/MessagesView/ContextMenu.d.ts +10 -0
  10. package/dist/Presentation/components/UI/Dialogs/MessagesView/MessagesView.d.ts +7 -1
  11. package/dist/Presentation/components/UI/svgs/Icons/Media/AIWidget/index.d.ts +4 -0
  12. package/dist/Presentation/components/layouts/Desktop/QuickBloxUIKitDesktopLayout.d.ts +9 -0
  13. package/dist/Presentation/components/layouts/TestStage/CompanyLogo/CompanyLogo.d.ts +3 -0
  14. package/dist/Presentation/components/providers/QuickBloxUIKitProvider/useQbInitializedDataContext.d.ts +3 -0
  15. package/dist/Presentation/components/providers/QuickBloxUIKitProvider/useQbUIKitDataContext.d.ts +3 -0
  16. package/dist/QBconfig.d.ts +12 -0
  17. package/dist/index-ui.d.ts +3 -2
  18. package/dist/index-ui.js +72 -17
  19. package/dist/utils/utils.d.ts +3 -0
  20. package/package.json +1 -1
  21. package/src/App.tsx +21 -19
  22. package/src/Presentation/Views/Base/BaseViewModel.ts +17 -1
  23. package/src/Presentation/Views/Dialogs/Dialogs.tsx +14 -9
  24. package/src/Presentation/Views/Dialogs/useDialogsViewModel.ts +1 -1
  25. package/src/Presentation/components/UI/Dialogs/DialogInformation/DialogInformation.tsx +17 -8
  26. package/src/Presentation/components/UI/Dialogs/DialogInformation/UsersList/useUsersListViewModel.ts +2 -2
  27. package/src/Presentation/components/UI/Dialogs/EditDialog/EditDialog.tsx +2 -2
  28. package/src/Presentation/components/UI/Dialogs/InviteMembers/useInviteMembersViewModel.ts +2 -2
  29. package/src/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/AIWidget.ts +13 -0
  30. package/src/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/ErrorMessageIcon.tsx +98 -0
  31. package/src/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/UseDefaultAIAssistAnswerWidgetWithProxy.tsx +136 -0
  32. package/src/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/UseDefaultTextInputWidget.tsx +60 -0
  33. package/src/Presentation/components/UI/Dialogs/MessagesView/AIWidgets/useDefaultVoiceInputWidget.tsx +86 -0
  34. package/src/Presentation/components/UI/Dialogs/MessagesView/ContextMenu.tsx +96 -0
  35. package/src/Presentation/components/UI/Dialogs/MessagesView/MessagesView.tsx +275 -51
  36. package/src/Presentation/components/UI/Dialogs/MessagesView/useMessagesViewModel.ts +2 -2
  37. package/src/Presentation/components/UI/svgs/Icons/Media/AIWidget/Send.svg +3 -0
  38. package/src/Presentation/components/UI/svgs/Icons/Media/AIWidget/index.tsx +39 -0
  39. package/src/Presentation/components/layouts/Desktop/QuickBloxUIKitDesktopLayout.tsx +83 -8
  40. package/src/Presentation/components/layouts/TestStage/CompanyLogo/CompanyLogo.tsx +27 -0
  41. package/src/Presentation/components/layouts/TestStage/LoginView/Login.tsx +2 -2
  42. package/src/Presentation/components/providers/QuickBloxUIKitProvider/useEventMessagesRepository.ts +2 -2
  43. package/src/Presentation/components/providers/QuickBloxUIKitProvider/{useQbDataContext.ts → useQbInitializedDataContext.ts} +2 -2
  44. package/src/Presentation/components/providers/QuickBloxUIKitProvider/useQbUIKitDataContext.ts +11 -0
  45. package/src/QBconfig.ts +12 -0
  46. package/src/index-ui.ts +4 -2
  47. package/src/utils/utils.ts +39 -0
  48. package/dist/Presentation/components/providers/QuickBloxUIKitProvider/useQbDataContext.d.ts +0 -3
@@ -0,0 +1,3 @@
1
+ export declare const completeSentence: (text?: string) => string;
2
+ export declare const tokenCounter: (text?: string) => number;
3
+ export declare const loopToLimitTokens: <T>(limit: number, data: T[], getValue?: (item: T) => string, tokens?: number) => T[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quickblox-react-ui-kit",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "main": "dist/index-ui.js",
5
5
  "license": "MIT",
6
6
  "dependencies": {
package/src/App.tsx CHANGED
@@ -5,9 +5,7 @@ import { QBConfig } from './QBconfig';
5
5
  import useQBConnection from './Presentation/components/providers/QuickBloxUIKitProvider/useQBConnection';
6
6
  import { LocalDataSource } from './Data/source/local/LocalDataSource';
7
7
  import Login from './Presentation/components/layouts/TestStage/LoginView/Login';
8
- import QuickBloxUIKitProvider, {
9
- qbDataContext,
10
- } from './Presentation/components/providers/QuickBloxUIKitProvider/QuickBloxUIKitProvider';
8
+ import QuickBloxUIKitProvider from './Presentation/components/providers/QuickBloxUIKitProvider/QuickBloxUIKitProvider';
11
9
  import TestStageMarkup from './Presentation/components/layouts/TestStage/TestStageMarkup';
12
10
  import { Stubs } from './Data/Stubs';
13
11
  import {
@@ -16,10 +14,13 @@ import {
16
14
  } from './Data/source/remote/RemoteDataSource';
17
15
  import QuickBloxUIKitDesktopLayout from './Presentation/components/layouts/Desktop/QuickBloxUIKitDesktopLayout';
18
16
  import DefaultTheme from './Presentation/assets/DefaultThemes/DefaultTheme';
17
+ import useQbUIKitDataContext from './Presentation/components/providers/QuickBloxUIKitProvider/useQbUIKitDataContext';
19
18
 
20
19
  function App() {
21
- const currentContext = React.useContext(qbDataContext);
22
- const remoteDataSourceMock: RemoteDataSource =
20
+ // const currentContext = React.useContext(qbDataContext);
21
+ const currentContext = useQbUIKitDataContext();
22
+
23
+ const remoteDataSource: RemoteDataSource =
23
24
  currentContext.storage.REMOTE_DATA_SOURCE;
24
25
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
26
  const localDataSource: LocalDataSource =
@@ -50,7 +51,7 @@ function App() {
50
51
  console.log('call release...');
51
52
  connectionRepository.stopKeepAlive();
52
53
  console.log('call stopKeepAlive...');
53
- await remoteDataSourceMock.disconnectAndLogoutUser();
54
+ await remoteDataSource.disconnectAndLogoutUser();
54
55
  console.log('call disconnectAndLogoutUser...');
55
56
  await currentContext.storage.LOCAL_DATA_SOURCE.clearAll();
56
57
  console.log('call clearAll...');
@@ -61,9 +62,9 @@ function App() {
61
62
  const prepareSDK = async (authData: LoginData): Promise<void> => {
62
63
  console.log('call prepareSDK with data:', authData);
63
64
  // todo: must be real remote datasource
64
- if (remoteDataSourceMock.needInit) {
65
+ if (remoteDataSource.needInit) {
65
66
  console.log('start prepareSDK actions with data:', authData);
66
- await remoteDataSourceMock.initSDKWithUser(
67
+ await remoteDataSource.initSDKWithUser(
67
68
  {
68
69
  appIdOrToken: currentContext.InitParams.accountData.appId,
69
70
  authKeyOrAppId: currentContext.InitParams.accountData.authKey,
@@ -114,10 +115,10 @@ function App() {
114
115
  console.log('call reloginSDK with data:', JSON.stringify(authData));
115
116
  currentContext.storage.SYNC_DIALOGS_USE_CASE.release();
116
117
  connectionRepository.stopKeepAlive();
117
- await remoteDataSourceMock.disconnectAndLogoutUser();
118
+ await remoteDataSource.disconnectAndLogoutUser();
118
119
  await currentContext.storage.LOCAL_DATA_SOURCE.clearAll();
119
120
 
120
- await remoteDataSourceMock.loginWithUser(authData);
121
+ await remoteDataSource.loginWithUser(authData);
121
122
  //
122
123
  // todo: temporary off, must turn on and reorganize code rows
123
124
  await connectionRepository.initializeStates();
@@ -135,20 +136,25 @@ function App() {
135
136
  const prepareContent = async (): Promise<void> => {
136
137
  console.log('PREPARE CONTENT');
137
138
  // todo: must delete it and ADD Preload data (read first page everywhere)
139
+ // или во все юзкейсы 2) Get/Sync execute(completed/callback):Promise<Entity[]>
140
+ // await prepareMockData();
138
141
  console.log('ADD REAL DATA TO DIALOG MOCK DATA ');
142
+ // await remoteDataSource.getDialogsFirstPage();
143
+ // await remoteDataSource.setUpMockStorage();
144
+ //
139
145
  //
140
146
  };
141
147
 
142
148
  const loginHandler = async (data: LoginData): Promise<void> => {
143
149
  setCurrentUser(data);
144
150
  console.log(`call login actions: ${JSON.stringify(data)}`);
145
- if (remoteDataSourceMock.authInformation) {
151
+ if (remoteDataSource.authInformation) {
146
152
  console.log(
147
153
  `authInformation: ${JSON.stringify(
148
- remoteDataSourceMock?.authInformation.userName,
154
+ remoteDataSource?.authInformation.userName,
149
155
  )}`,
150
156
  );
151
- if (data.login !== remoteDataSourceMock.authInformation.userName) {
157
+ if (data.login !== remoteDataSource.authInformation.userName) {
152
158
  await reloginSDK(data).catch((e) => {
153
159
  console.log(
154
160
  `exception in reloginSDK ${(e as unknown as Error).message}`,
@@ -161,9 +167,9 @@ function App() {
161
167
  }
162
168
  } else {
163
169
  console.log('need prepare SDK with data:', data);
164
- if (remoteDataSourceMock.needInit) {
170
+ if (remoteDataSource.needInit) {
165
171
  console.log('start prepareSDK actions with data:', data);
166
- await remoteDataSourceMock.initSDKWithUser(
172
+ await remoteDataSource.initSDKWithUser(
167
173
  {
168
174
  appIdOrToken: currentContext.InitParams.accountData.appId,
169
175
  authKeyOrAppId: currentContext.InitParams.accountData.authKey,
@@ -215,10 +221,6 @@ function App() {
215
221
  <Route
216
222
  path="/desktop-test-mock"
217
223
  element={
218
- // <QuickBloxUIKitDesktopLayout theme={new CustomTheme()} InputWidgetLeftPlaceHolder={CustomWidgetVoiceToText('','')} />
219
-
220
- // <QuickBloxUIKitDesktopLayout theme={new CustomTheme()} />
221
-
222
224
  <QuickBloxUIKitDesktopLayout theme={new DefaultTheme()} />
223
225
  }
224
226
  />
@@ -49,7 +49,10 @@ export type EditDialogParams = {
49
49
  dialogTitle: string;
50
50
  dialogAvatar: File | string | null;
51
51
  };
52
-
52
+ export interface IChatMessage {
53
+ role: string;
54
+ content: string;
55
+ }
53
56
  export type FunctionTypeFileToToVoid = (file: File) => void;
54
57
  export type FunctionTypePaginationToVoid = (pagination: Pagination) => void;
55
58
  export type FunctionTypeVoidToVoid = () => void;
@@ -65,3 +68,16 @@ export type FunctionTypeDialogEntityToBoolean = (
65
68
  entity: GroupDialogEntity,
66
69
  ) => Promise<boolean>;
67
70
  export type FunctionTypeFileToFileEntity = (file: File) => Promise<FileEntity>;
71
+ export type FunctionTypeJSXElement = () => JSX.Element;
72
+ // export type FunctionTypeChatMessagesToVoid = (
73
+ // lastMessage: string,
74
+ // messages: IChatMessage,
75
+ // ) => void;
76
+ export type FunctionTypeFileWithContextToToVoid = (
77
+ file: File,
78
+ context: IChatMessage[],
79
+ ) => void;
80
+ export type FunctionTypeStringWithContextToVoid = (
81
+ value: string,
82
+ context: IChatMessage[],
83
+ ) => void;
@@ -27,6 +27,7 @@ type DialogsComponentSettings = {
27
27
  themeName?: ThemeNames;
28
28
  withoutHeader?: boolean;
29
29
  useSubHeader?: boolean;
30
+ useUpHeader?: boolean;
30
31
  themeHeader?: UiKitTheme;
31
32
  themePreview?: UiKitTheme;
32
33
  };
@@ -34,7 +35,8 @@ type DialogsComponentSettings = {
34
35
  type DialogsProps = {
35
36
  header?: React.ReactNode;
36
37
  subHeaderContent?: React.ReactNode;
37
- itemSelectHandler?: FunctionTypeViewModelToVoid<DialogEntity>;
38
+ upHeaderContent?: React.ReactNode;
39
+ onDialogSelectHandler?: FunctionTypeViewModelToVoid<DialogEntity>;
38
40
  dialogsViewModel: DialogsViewModel;
39
41
  additionalSettings?: DialogsComponentSettings;
40
42
  };
@@ -43,7 +45,8 @@ type DialogsProps = {
43
45
  const DialogsComponent: React.FC<DialogsProps> = ({
44
46
  header,
45
47
  subHeaderContent,
46
- itemSelectHandler,
48
+ upHeaderContent,
49
+ onDialogSelectHandler,
47
50
  dialogsViewModel,
48
51
  additionalSettings = undefined,
49
52
  }: DialogsProps) => {
@@ -68,15 +71,15 @@ const DialogsComponent: React.FC<DialogsProps> = ({
68
71
  dialogsViewModel?.dialogs.forEach((entiy, index) => {
69
72
  const pw: PreviewDialogViewModel = new PreviewDialogViewModel(
70
73
  (it) => {
71
- if (itemSelectHandler) {
74
+ if (onDialogSelectHandler) {
72
75
  setSelectedItem({ selectedIndex: index, item: it });
73
- itemSelectHandler(it);
76
+ onDialogSelectHandler(it);
74
77
  }
75
78
  },
76
79
  (it) => {
77
- if (itemSelectHandler) {
80
+ if (onDialogSelectHandler) {
78
81
  setSelectedItem({ selectedIndex: index, item: it });
79
- itemSelectHandler(it);
82
+ onDialogSelectHandler(it);
80
83
  }
81
84
  },
82
85
  // Number(entiy.id),
@@ -149,7 +152,9 @@ const DialogsComponent: React.FC<DialogsProps> = ({
149
152
  const useHeader = !additionalSettings?.withoutHeader || header || false;
150
153
  const useSubContent =
151
154
  additionalSettings?.useSubHeader || subHeaderContent || false;
152
- const usingHeader = header || (
155
+ const useUpContent =
156
+ additionalSettings?.useUpHeader || upHeaderContent || false;
157
+ const HeaderContent = header || (
153
158
  <HeaderDialogs
154
159
  title="Dialogs"
155
160
  clickSearchHandler={() => {
@@ -307,8 +312,8 @@ const DialogsComponent: React.FC<DialogsProps> = ({
307
312
  }}
308
313
  >
309
314
  <ColumnContainer>
310
- {useHeader && usingHeader}
311
- {/* {showSearchDialogs ? renderSearchDialogs() : null} */}
315
+ {useUpContent && upHeaderContent}
316
+ {useHeader && HeaderContent}
312
317
  {useSubContent && subHeaderContent}
313
318
  {dialogsViewModel?.loading && (
314
319
  // <div style={{ maxHeight: '44px', minHeight: '44px', height: '44px' }}>
@@ -44,7 +44,7 @@ export default function useDialogsViewModel(
44
44
  //
45
45
  const currentUserId =
46
46
  currentContext.storage.REMOTE_DATA_SOURCE.authInformation?.userId;
47
- // const currentContext = useQbDataContext();
47
+ // const currentContext = useQbInitializedDataContext();
48
48
  const remoteDataSourceMock: RemoteDataSource =
49
49
  currentContext.storage.REMOTE_DATA_SOURCE;
50
50
 
@@ -35,24 +35,28 @@ import { stringifyError } from '../../../../../utils/parse';
35
35
  import { FileEntity } from '../../../../../Domain/entity/FileEntity';
36
36
  import UserAvatar from '../EditDialog/UserAvatar/UserAvatar';
37
37
  import MainButton, { TypeButton } from '../../Buttons/MainButton/MainButton';
38
- import useQbDataContext from '../../../providers/QuickBloxUIKitProvider/useQbDataContext';
38
+ import useQbInitializedDataContext from '../../../providers/QuickBloxUIKitProvider/useQbInitializedDataContext';
39
39
  import UiKitTheme from '../../../../assets/UiKitTheme';
40
40
 
41
41
  type HeaderDialogsProps = {
42
42
  dialog: DialogEntity;
43
43
  dialogViewModel: DialogsViewModel;
44
- closeInformationHandler: FunctionTypeVoidToVoid;
44
+ onCloseDialogInformationHandler: FunctionTypeVoidToVoid;
45
45
  theme?: UiKitTheme;
46
+ subHeaderContent?: React.ReactNode;
47
+ upHeaderContent?: React.ReactNode;
46
48
  };
47
49
  // eslint-disable-next-line react/function-component-definition
48
50
  const DialogInformation: React.FC<HeaderDialogsProps> = ({
49
51
  dialog,
50
52
  dialogViewModel,
51
- closeInformationHandler,
53
+ onCloseDialogInformationHandler,
52
54
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
53
55
  theme = undefined,
56
+ subHeaderContent = undefined,
57
+ upHeaderContent = undefined,
54
58
  }: HeaderDialogsProps) => {
55
- const currentContext = useQbDataContext();
59
+ const currentContext = useQbInitializedDataContext();
56
60
  const currentUserId =
57
61
  currentContext.storage.REMOTE_DATA_SOURCE.authInformation?.userId.toString();
58
62
  const { handleModal } = React.useContext(ModalContext);
@@ -62,9 +66,9 @@ const DialogInformation: React.FC<HeaderDialogsProps> = ({
62
66
 
63
67
  useEffect(() => {
64
68
  console.log('HAVE NEW DIALOG');
65
- if (dialog === undefined && closeInformationHandler) {
69
+ if (dialog === undefined && onCloseDialogInformationHandler) {
66
70
  console.log('HAVE UNDEFINED NEW DIALOG');
67
- closeInformationHandler();
71
+ onCloseDialogInformationHandler();
68
72
 
69
73
  return;
70
74
  }
@@ -244,6 +248,9 @@ const DialogInformation: React.FC<HeaderDialogsProps> = ({
244
248
  }
245
249
  };
246
250
 
251
+ const useSubContent = subHeaderContent || false;
252
+ const useUpContent = upHeaderContent || false;
253
+
247
254
  return isAllMembersShow ? (
248
255
  <MembersList
249
256
  closeInformationHandler={() => {
@@ -254,6 +261,7 @@ const DialogInformation: React.FC<HeaderDialogsProps> = ({
254
261
  ) : (
255
262
  <div className="dialog-information-container">
256
263
  <ColumnContainer maxWidth="320px">
264
+ {useUpContent && upHeaderContent}
257
265
  <div className="dialog-information-container--dialog-information-wrapper">
258
266
  <div className="dialog-information-container__dialog-information">
259
267
  <div>Dialog information</div>
@@ -262,13 +270,14 @@ const DialogInformation: React.FC<HeaderDialogsProps> = ({
262
270
  <ActiveSvg
263
271
  content={<Close applyZoom color="var(--secondary-elements)" />}
264
272
  clickAction={() => {
265
- if (closeInformationHandler) {
266
- closeInformationHandler();
273
+ if (onCloseDialogInformationHandler) {
274
+ onCloseDialogInformationHandler();
267
275
  }
268
276
  }}
269
277
  />
270
278
  </div>
271
279
  </div>
280
+ {useSubContent && subHeaderContent}
272
281
  <div className="dialog-information-container--icon-dialog-wrapper">
273
282
  <div className="dialog-information-container__icon-dialog">
274
283
  <div className="dialog-information-container__icon-dialog__info">
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { DialogEntity } from '../../../../../../Domain/entity/DialogEntity';
3
- import useQbDataContext from '../../../../providers/QuickBloxUIKitProvider/useQbDataContext';
3
+ import useQbInitializedDataContext from '../../../../providers/QuickBloxUIKitProvider/useQbInitializedDataContext';
4
4
  import { UserEntity } from '../../../../../../Domain/entity/UserEntity';
5
5
  import { UsersListViewModel } from './UsersListViewModel';
6
6
  import { GetUsersByIdsUseCase } from '../../../../../../Domain/use_cases/GetUsersByIdsUseCase';
@@ -18,7 +18,7 @@ export default function useUsersListViewModel(
18
18
  const [users, setUsers] = useState<UserEntity[]>([]);
19
19
  const [dialog, setDialog] = useState<DialogEntity>(dialogEntity);
20
20
 
21
- const currentContext = useQbDataContext();
21
+ const currentContext = useQbInitializedDataContext();
22
22
 
23
23
  async function getUsers() {
24
24
  console.log('call getUsers in useUsersListViewModel');
@@ -13,7 +13,7 @@ import UserAvatar from './UserAvatar/UserAvatar';
13
13
  import { DialogType } from '../../../../../Domain/entity/DialogTypes';
14
14
  import GroupChat from '../../svgs/Icons/Contents/GroupChat';
15
15
  import PublicChannel from '../../svgs/Icons/Contents/PublicChannel';
16
- import useQbDataContext from '../../../providers/QuickBloxUIKitProvider/useQbDataContext';
16
+ import useQbInitializedDataContext from '../../../providers/QuickBloxUIKitProvider/useQbInitializedDataContext';
17
17
 
18
18
  export const TypeOpenDialog = {
19
19
  edit: 'edit',
@@ -40,7 +40,7 @@ const EditDialog: React.FC<EditDialogProps> = ({
40
40
  clickUpdatedHandler,
41
41
  clickCancelHandler,
42
42
  }) => {
43
- const currentContext = useQbDataContext();
43
+ const currentContext = useQbInitializedDataContext();
44
44
  const maxUploadFileSize = currentContext.InitParams.maxFileSize;
45
45
  const minLengthNameDialog = 3;
46
46
  const maxLengthNameDialog = 60;
@@ -7,7 +7,7 @@ import {
7
7
  import { UserEntity } from '../../../../../Domain/entity/UserEntity';
8
8
  import { GetAllUsersUseCase } from '../../../../../Domain/use_cases/GetAllUsersUseCase';
9
9
  import UsersRepository from '../../../../../Data/repository/UsersRepository';
10
- import useQbDataContext from '../../../providers/QuickBloxUIKitProvider/useQbDataContext';
10
+ import useQbInitializedDataContext from '../../../providers/QuickBloxUIKitProvider/useQbInitializedDataContext';
11
11
  import { Stubs } from '../../../../../Data/Stubs';
12
12
  import { stringifyError } from '../../../../../utils/parse';
13
13
  import {
@@ -18,7 +18,7 @@ import {
18
18
  export default function useInviteMembersViewModel(): InviteMembersViewModel {
19
19
  // initPagination?: Pagination,
20
20
  console.log('create useUsersListViewModel');
21
- const currentContext = useQbDataContext();
21
+ const currentContext = useQbInitializedDataContext();
22
22
  const [loading, setLoading] = useState(false);
23
23
  const [error, setError] = useState('error with getting user list');
24
24
 
@@ -0,0 +1,13 @@
1
+ import {
2
+ FunctionTypeFileWithContextToToVoid,
3
+ FunctionTypeJSXElement,
4
+ FunctionTypeStringWithContextToVoid,
5
+ } from '../../../../../Views/Base/BaseViewModel';
6
+
7
+ export interface AIWidget {
8
+ renderWidget: FunctionTypeJSXElement;
9
+ textToWidget: FunctionTypeStringWithContextToVoid;
10
+ fileToWidget: FunctionTypeFileWithContextToToVoid;
11
+ textToContent: string | undefined;
12
+ fileToContent: File | undefined;
13
+ }
@@ -0,0 +1,98 @@
1
+ import React, { useState, CSSProperties } from 'react';
2
+
3
+ type ErrorDescription = {
4
+ title: string;
5
+ action: () => void;
6
+ };
7
+
8
+ type ErrorMessageIconProps = {
9
+ errorMessageText: string;
10
+ errorsDescriptions?: ErrorDescription[];
11
+ };
12
+
13
+ const errorMessageIconStyles: { [key: string]: CSSProperties } = {
14
+ errorIcon: {
15
+ display: 'inline-block',
16
+ position: 'relative',
17
+ width: '21px', // Уменьшен размер круга
18
+ height: '21px', // Уменьшен размер круга
19
+ cursor: 'pointer',
20
+ },
21
+ circle: {
22
+ width: '21px', // Уменьшен размер круга
23
+ height: '21px', // Уменьшен размер круга
24
+ backgroundColor: 'red',
25
+ borderRadius: '50%',
26
+ display: 'flex',
27
+ justifyContent: 'center',
28
+ alignItems: 'center',
29
+ },
30
+ exclamationMark: {
31
+ color: 'white',
32
+ fontSize: '12px', // Уменьшен размер восклицательного знака
33
+ },
34
+ errorMessage: {
35
+ position: 'absolute',
36
+ bottom: '100%', // Изменено выравнивание, чтобы текст был выше
37
+ left: '50%',
38
+ transform: 'translateX(-50%)',
39
+ backgroundColor: 'lightgray',
40
+ border: '1px solid gray',
41
+ padding: '6px',
42
+ borderRadius: '8px',
43
+ whiteSpace: 'nowrap',
44
+ display: 'inline-block',
45
+ zIndex: 1, // Установлен zIndex, чтобы текст был выше других элементов
46
+ },
47
+ };
48
+
49
+ function ErrorMessageIcon({
50
+ errorMessageText,
51
+ errorsDescriptions,
52
+ }: ErrorMessageIconProps) {
53
+ const [isHovered, setIsHovered] = useState(false);
54
+
55
+ const handleMouseEnter = () => {
56
+ setIsHovered(true);
57
+ };
58
+
59
+ const handleMouseLeave = () => {
60
+ setIsHovered(false);
61
+ };
62
+
63
+ return (
64
+ <div
65
+ style={{
66
+ ...errorMessageIconStyles.errorIcon,
67
+ ...(isHovered ? { backgroundColor: 'yellow' } : {}),
68
+ }}
69
+ onMouseEnter={handleMouseEnter}
70
+ onMouseLeave={handleMouseLeave}
71
+ >
72
+ <div style={errorMessageIconStyles.circle}>
73
+ <span style={errorMessageIconStyles.exclamationMark}>!</span>
74
+ </div>
75
+ {isHovered && (
76
+ <div style={errorMessageIconStyles.errorMessage}>
77
+ {errorMessageText}
78
+ {errorsDescriptions?.map((item, index) => (
79
+ <div
80
+ key={index}
81
+ style={{
82
+ padding: '4px',
83
+ cursor: 'pointer',
84
+ }}
85
+ onClick={() => {
86
+ item.action();
87
+ }}
88
+ >
89
+ {item.title}
90
+ </div>
91
+ ))}
92
+ </div>
93
+ )}
94
+ </div>
95
+ );
96
+ }
97
+
98
+ export default ErrorMessageIcon;
@@ -0,0 +1,136 @@
1
+ import { useState } from 'react';
2
+ import { AIWidget } from './AIWidget';
3
+ import AIWidgetIcon from '../../../svgs/Icons/Media/AIWidget';
4
+ import { IChatMessage } from '../../../../../Views/Base/BaseViewModel';
5
+ import { stringifyError } from '../../../../../../utils/parse';
6
+ import ErrorMessageIcon from './ErrorMessageIcon';
7
+
8
+ interface MessageWidgetProps {
9
+ // https://api.openai.com/v1/chat/completions'
10
+ // api: 'v1/chat/completions',
11
+ // servername: 'https://myproxy.com',
12
+ // https://func270519800.azurewebsites.net/api/TranslateTextToEng
13
+ servername: string;
14
+ api: string;
15
+ port: string;
16
+ sessionToken: string;
17
+ }
18
+ export default function UseDefaultAIAssistAnswerWidgetWithProxy({
19
+ servername,
20
+ api,
21
+ port,
22
+ sessionToken,
23
+ }: MessageWidgetProps): AIWidget {
24
+ const [errorMessage, setErrorMessage] = useState<string>('');
25
+
26
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
27
+ const fileToWidget = (file: File, context: IChatMessage[]): void => {};
28
+
29
+ const renderWidget = (): JSX.Element => {
30
+ if (errorMessage && errorMessage.length > 0) {
31
+ const errorsDescriptions:
32
+ | { title: string; action: () => void }[]
33
+ | undefined = [];
34
+
35
+ return (
36
+ <ErrorMessageIcon
37
+ errorMessageText={errorMessage}
38
+ errorsDescriptions={errorsDescriptions}
39
+ />
40
+ );
41
+ }
42
+
43
+ return <AIWidgetIcon applyZoom color="green" />;
44
+ };
45
+
46
+ // async function getData(
47
+ // textToSend: string,
48
+ // dialogMessages: ChatCompletionRequestMessage[],
49
+ // ): Promise<string> {
50
+ // //
51
+ // const apiEndpoint = 'https://api.openai.com/v1/chat/completions';
52
+ // const { apiKey } = QBConfig.configAIApi.AIAnswerAssistWidgetConfig; // Замените на ваш реальный ключ API
53
+ // const model = 'gpt-3.5-turbo';
54
+ // const requestOptions = {
55
+ // method: 'POST',
56
+ // headers: {
57
+ // 'Content-Type': 'application/json',
58
+ // Authorization: `Bearer ${apiKey}`,
59
+ // },
60
+ // body: JSON.stringify({
61
+ // messages: [...dialogMessages, { role: 'user', content: textToSend }],
62
+ // model,
63
+ // temperature: 0.5,
64
+ // }),
65
+ // };
66
+ //
67
+ async function getData(
68
+ textToSend: string,
69
+ dialogMessages: IChatMessage[],
70
+ ): Promise<string> {
71
+ let outputMessage = '';
72
+ const apiEndpoint = `${servername}${port}${api}`;
73
+ const apiKey = sessionToken; // Замените на ваш реальный ключ API
74
+ const model = 'gpt-3.5-turbo';
75
+ const prompt = `Respond as a knowledgeable customer support specialist with access to ChatGPT features, and provide a simple and informative response to the inquiry :"${textToSend}"`;
76
+
77
+ const requestOptions = {
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json',
81
+ Authorization: `Bearer ${apiKey}`,
82
+ },
83
+ body: JSON.stringify({
84
+ messages: [...dialogMessages, { role: 'user', content: prompt }],
85
+ model,
86
+ temperature: 0.5,
87
+ }),
88
+ };
89
+
90
+ //
91
+ try {
92
+ const response = await fetch(apiEndpoint, requestOptions);
93
+ const data = await response.json();
94
+
95
+ outputMessage = data.choices[0].message?.content || '';
96
+ } catch (err) {
97
+ outputMessage = stringifyError(err);
98
+ setErrorMessage(outputMessage);
99
+ }
100
+
101
+ return outputMessage;
102
+ }
103
+
104
+ const [textFromWidgetToContent, setTextFromWidgetToContent] = useState('');
105
+ // const textToWidget = (value: string, context: IChatMessage[]): void => {
106
+ // if (value && value.length > 0) {
107
+ // // eslint-disable-next-line promise/catch-or-return
108
+ // getOpenAIApiData(value, context as ChatCompletionRequestMessage[]).then(
109
+ // // eslint-disable-next-line promise/always-return
110
+ // (data) => {
111
+ // setTextFromWidgetToContent(data);
112
+ // },
113
+ // );
114
+ // }
115
+ // };
116
+
117
+ const textToWidget = (value: string, context: IChatMessage[]): void => {
118
+ if (value && value.length > 0) {
119
+ // eslint-disable-next-line promise/catch-or-return
120
+ getData(value, context).then(
121
+ // eslint-disable-next-line promise/always-return
122
+ (data) => {
123
+ setTextFromWidgetToContent(data);
124
+ },
125
+ );
126
+ }
127
+ };
128
+
129
+ return {
130
+ fileToContent: undefined,
131
+ textToContent: textFromWidgetToContent,
132
+ fileToWidget,
133
+ renderWidget,
134
+ textToWidget,
135
+ };
136
+ }