@memori.ai/memori-react 7.21.1 → 7.23.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.
- package/CHANGELOG.md +56 -0
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +85 -8
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/dist/components/KnownFacts/KnownFacts.js +1 -1
- package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.css +29 -0
- package/dist/components/StartPanel/StartPanel.js +2 -1
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/Typing/Typing.js +49 -47
- package/dist/components/Typing/Typing.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.d.ts +1 -0
- package/dist/components/UploadButton/UploadButton.js +142 -3
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/icons/Alert.d.ts +5 -0
- package/dist/components/icons/Alert.js +6 -0
- package/dist/components/icons/Alert.js.map +1 -0
- package/dist/components/icons/Info.d.ts +5 -0
- package/dist/components/icons/Info.js +6 -0
- package/dist/components/icons/Info.js.map +1 -0
- package/dist/components/icons/Warning.js +1 -1
- package/dist/components/icons/Warning.js.map +1 -1
- package/dist/components/ui/ConfirmDialog.css +42 -0
- package/dist/components/ui/ConfirmDialog.d.ts +11 -0
- package/dist/components/ui/ConfirmDialog.js +12 -0
- package/dist/components/ui/ConfirmDialog.js.map +1 -0
- package/dist/components/ui/Drawer.css +121 -96
- package/dist/components/ui/Drawer.d.ts +15 -6
- package/dist/components/ui/Drawer.js +44 -13
- package/dist/components/ui/Drawer.js.map +1 -1
- package/dist/locales/de.json +15 -0
- package/dist/locales/en.json +15 -0
- package/dist/locales/es.json +15 -0
- package/dist/locales/fr.json +7 -0
- package/dist/locales/it.json +15 -0
- package/dist/styles.css +6 -4
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +85 -8
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/esm/components/KnownFacts/KnownFacts.js +1 -1
- package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.css +29 -0
- package/esm/components/StartPanel/StartPanel.js +2 -1
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/Typing/Typing.js +49 -47
- package/esm/components/Typing/Typing.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.d.ts +1 -0
- package/esm/components/UploadButton/UploadButton.js +142 -3
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/icons/Alert.d.ts +5 -0
- package/esm/components/icons/Alert.js +4 -0
- package/esm/components/icons/Alert.js.map +1 -0
- package/esm/components/icons/Info.d.ts +5 -0
- package/esm/components/icons/Info.js +4 -0
- package/esm/components/icons/Info.js.map +1 -0
- package/esm/components/icons/Warning.js +1 -1
- package/esm/components/icons/Warning.js.map +1 -1
- package/esm/components/ui/ConfirmDialog.css +42 -0
- package/esm/components/ui/ConfirmDialog.d.ts +11 -0
- package/esm/components/ui/ConfirmDialog.js +9 -0
- package/esm/components/ui/ConfirmDialog.js.map +1 -0
- package/esm/components/ui/Drawer.css +121 -96
- package/esm/components/ui/Drawer.d.ts +15 -6
- package/esm/components/ui/Drawer.js +45 -14
- package/esm/components/ui/Drawer.js.map +1 -1
- package/esm/locales/de.json +15 -0
- package/esm/locales/en.json +15 -0
- package/esm/locales/es.json +15 -0
- package/esm/locales/fr.json +7 -0
- package/esm/locales/it.json +15 -0
- package/esm/styles.css +6 -4
- package/package.json +1 -1
- package/src/components/BlockedMemoriBadge/__snapshots__/BlockedMemoriBadge.test.tsx.snap +10 -0
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.stories.tsx +274 -21
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +117 -21
- package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +39 -21
- package/src/components/KnownFacts/KnownFacts.tsx +1 -1
- package/src/components/StartPanel/StartPanel.css +29 -0
- package/src/components/StartPanel/StartPanel.tsx +47 -0
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +827 -7
- package/src/components/Typing/Typing.tsx +52 -47
- package/src/components/UploadButton/UploadButton.tsx +206 -5
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +1 -1
- package/src/components/icons/Alert.tsx +31 -0
- package/src/components/icons/Info.tsx +31 -0
- package/src/components/icons/Warning.tsx +2 -1
- package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +74 -0
- package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +148 -0
- package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +74 -0
- package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +74 -0
- package/src/components/ui/ConfirmDialog.css +42 -0
- package/src/components/ui/ConfirmDialog.stories.tsx +216 -0
- package/src/components/ui/ConfirmDialog.test.tsx +124 -0
- package/src/components/ui/ConfirmDialog.tsx +58 -0
- package/src/components/ui/Drawer.css +121 -96
- package/src/components/ui/Drawer.stories.tsx +152 -67
- package/src/components/ui/Drawer.test.tsx +6 -2
- package/src/components/ui/Drawer.tsx +195 -89
- package/src/components/ui/__snapshots__/ConfirmDialog.test.tsx.snap +35 -0
- package/src/locales/de.json +15 -0
- package/src/locales/en.json +15 -0
- package/src/locales/es.json +15 -0
- package/src/locales/fr.json +7 -0
- package/src/locales/it.json +15 -0
- package/src/styles.css +6 -4
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useCallback, useMemo, useState } from 'react';
|
|
2
2
|
import { Meta, Story } from '@storybook/react';
|
|
3
3
|
import Drawer, { Props } from './Drawer';
|
|
4
4
|
import Button from './Button';
|
|
5
5
|
|
|
6
6
|
import './Drawer.css';
|
|
7
|
+
import I18nWrapper from '../../I18nWrapper';
|
|
7
8
|
|
|
8
9
|
const meta: Meta = {
|
|
9
10
|
title: 'UI/Drawer',
|
|
@@ -34,12 +35,27 @@ const meta: Meta = {
|
|
|
34
35
|
type: 'text',
|
|
35
36
|
},
|
|
36
37
|
},
|
|
37
|
-
|
|
38
|
+
placement: {
|
|
38
39
|
control: {
|
|
39
40
|
type: 'select',
|
|
40
41
|
options: ['left', 'right'],
|
|
41
42
|
},
|
|
42
43
|
},
|
|
44
|
+
width: {
|
|
45
|
+
control: {
|
|
46
|
+
type: 'text',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
animated: {
|
|
50
|
+
control: {
|
|
51
|
+
type: 'boolean',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
closable: {
|
|
55
|
+
control: {
|
|
56
|
+
type: 'boolean',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
43
59
|
},
|
|
44
60
|
parameters: {
|
|
45
61
|
controls: { expanded: true },
|
|
@@ -61,73 +77,29 @@ const content = (
|
|
|
61
77
|
<p>Nulla at urna diam.</p>
|
|
62
78
|
<h3>Suspendisse a sodales nulla, sed semper nisi.</h3>
|
|
63
79
|
<p>Proin tincidunt enim in felis aliquet, a ultricies purus bibendum.</p>
|
|
64
|
-
<ul>
|
|
65
|
-
<li>Quisque in ultrices lectus.</li>
|
|
66
|
-
<li>Quisque in ultrices lectus.</li>
|
|
67
|
-
<li>Quisque in ultrices lectus.</li>
|
|
68
|
-
</ul>
|
|
69
|
-
<p>Nulla at urna diam.</p>
|
|
70
|
-
<p>Nulla at urna diam.</p>
|
|
71
|
-
<h3>Suspendisse a sodales nulla, sed semper nisi.</h3>
|
|
72
|
-
<p>Proin tincidunt enim in felis aliquet, a ultricies purus bibendum.</p>
|
|
73
|
-
<ul>
|
|
74
|
-
<li>Quisque in ultrices lectus.</li>
|
|
75
|
-
<li>Quisque in ultrices lectus.</li>
|
|
76
|
-
<li>Quisque in ultrices lectus.</li>
|
|
77
|
-
</ul>
|
|
78
|
-
<p>Nulla at urna diam.</p>
|
|
79
80
|
</>
|
|
80
81
|
);
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
</>
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
const Template: Story<Props> = args => {
|
|
90
|
-
const [isOpen, setIsOpen] = React.useState(!!args.open || false);
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<>
|
|
94
|
-
<Button onClick={() => setIsOpen(true)}>Click me</Button>
|
|
95
|
-
<Drawer
|
|
96
|
-
{...args}
|
|
97
|
-
open={isOpen}
|
|
98
|
-
onClose={() => setIsOpen(false)}
|
|
99
|
-
footer={args.footer}
|
|
100
|
-
>
|
|
101
|
-
{content}
|
|
102
|
-
</Drawer>
|
|
103
|
-
</>
|
|
104
|
-
);
|
|
83
|
+
// Create a proper footer object for the Drawer component
|
|
84
|
+
const simpleFooterObject = {
|
|
85
|
+
onSubmit: () => console.log('Submit clicked'),
|
|
86
|
+
loading: false,
|
|
105
87
|
};
|
|
106
88
|
|
|
107
|
-
const
|
|
89
|
+
const Template: Story<Props> = args => {
|
|
108
90
|
const [isOpen, setIsOpen] = React.useState(!!args.open || false);
|
|
109
91
|
|
|
110
92
|
return (
|
|
111
|
-
|
|
112
|
-
<Button onClick={() => setIsOpen(true)}>
|
|
113
|
-
<Drawer
|
|
114
|
-
{...args}
|
|
115
|
-
open={isOpen}
|
|
116
|
-
onClose={() => setIsOpen(false)}
|
|
117
|
-
footer={args.footer}
|
|
118
|
-
>
|
|
119
|
-
{content}
|
|
120
|
-
{content}
|
|
121
|
-
{content}
|
|
122
|
-
{content}
|
|
93
|
+
<I18nWrapper>
|
|
94
|
+
<Button onClick={() => setIsOpen(true)}>Open Drawer</Button>
|
|
95
|
+
<Drawer {...args} open={isOpen} onClose={() => setIsOpen(false)}>
|
|
123
96
|
{content}
|
|
124
97
|
</Drawer>
|
|
125
|
-
|
|
98
|
+
</I18nWrapper>
|
|
126
99
|
);
|
|
127
100
|
};
|
|
128
101
|
|
|
129
|
-
//
|
|
130
|
-
// https://storybook.js.org/docs/react/workflows/unit-testing
|
|
102
|
+
// Basic examples
|
|
131
103
|
export const Default = Template.bind({});
|
|
132
104
|
Default.args = {
|
|
133
105
|
open: false,
|
|
@@ -159,24 +131,137 @@ Loading.args = {
|
|
|
159
131
|
loading: true,
|
|
160
132
|
};
|
|
161
133
|
|
|
162
|
-
export const
|
|
163
|
-
|
|
134
|
+
export const WithSimpleFooter = Template.bind({});
|
|
135
|
+
WithSimpleFooter.args = {
|
|
164
136
|
open: true,
|
|
165
137
|
title: 'Drawer Title',
|
|
166
138
|
description: 'Drawer Description',
|
|
167
|
-
footer
|
|
139
|
+
footer: {
|
|
140
|
+
onSubmit: () => console.log('Submit'),
|
|
141
|
+
loading: false,
|
|
142
|
+
},
|
|
168
143
|
};
|
|
169
144
|
|
|
170
|
-
export const
|
|
171
|
-
|
|
145
|
+
export const PlacementLeft = Template.bind({});
|
|
146
|
+
PlacementLeft.args = {
|
|
172
147
|
open: true,
|
|
173
|
-
|
|
148
|
+
placement: 'left',
|
|
149
|
+
title: 'Left Drawer',
|
|
174
150
|
};
|
|
175
151
|
|
|
176
|
-
export const
|
|
177
|
-
|
|
152
|
+
export const CustomWidth = Template.bind({});
|
|
153
|
+
CustomWidth.args = {
|
|
178
154
|
open: true,
|
|
179
|
-
title: 'Drawer
|
|
180
|
-
|
|
181
|
-
|
|
155
|
+
title: 'Custom Width Drawer',
|
|
156
|
+
width: '50%',
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const NonAnimated = Template.bind({});
|
|
160
|
+
NonAnimated.args = {
|
|
161
|
+
open: true,
|
|
162
|
+
title: 'Non-Animated Drawer',
|
|
163
|
+
animated: false,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const NonClosable = Template.bind({});
|
|
167
|
+
NonClosable.args = {
|
|
168
|
+
open: true,
|
|
169
|
+
title: 'Non-Closable Drawer',
|
|
170
|
+
closable: false,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Template for data detection
|
|
174
|
+
const DataTemplate: Story<Props> = args => {
|
|
175
|
+
const [isOpen, setIsOpen] = React.useState(!!args.open || false);
|
|
176
|
+
// Use static data for the story - don't try to update it which might cause issues
|
|
177
|
+
const staticData = { id: 1, name: 'John Doe' };
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<I18nWrapper>
|
|
181
|
+
<Button onClick={() => setIsOpen(true)}>Open Data Drawer</Button>
|
|
182
|
+
<Drawer
|
|
183
|
+
{...args}
|
|
184
|
+
open={isOpen}
|
|
185
|
+
data={staticData}
|
|
186
|
+
onClose={() => setIsOpen(false)}
|
|
187
|
+
>
|
|
188
|
+
<p>This drawer has data associated with it.</p>
|
|
189
|
+
<p>When you close it, the component will check for unsaved changes.</p>
|
|
190
|
+
<p>(For this demo, no actual changes are tracked)</p>
|
|
191
|
+
</Drawer>
|
|
192
|
+
</I18nWrapper>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const WithDataDetection = DataTemplate.bind({});
|
|
197
|
+
WithDataDetection.args = {
|
|
198
|
+
open: true,
|
|
199
|
+
title: 'Data Change Detection',
|
|
200
|
+
description: 'This drawer demonstrates the data change detection feature',
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Improved ConfirmationDialog template with better state management
|
|
204
|
+
|
|
205
|
+
const ConfirmationDialogTemplate: Story<Props> = ({ open = true }: Props) => {
|
|
206
|
+
const [isOpen, setIsOpen] = useState(open);
|
|
207
|
+
const [data, setData] = useState({ id: 1, name: 'John Doe' });
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<I18nWrapper>
|
|
211
|
+
<Button onClick={() => setIsOpen(true)}>Open Confirmation Dialog</Button>
|
|
212
|
+
<Drawer
|
|
213
|
+
open={isOpen}
|
|
214
|
+
onClose={() => setIsOpen(false)}
|
|
215
|
+
data={data}
|
|
216
|
+
title="Confirmation Example"
|
|
217
|
+
confirmDialogTitle="Confirmation Example"
|
|
218
|
+
confirmDialogMessage="Are you sure you want to close this drawer?"
|
|
219
|
+
footer={{
|
|
220
|
+
onSubmit: () => {
|
|
221
|
+
console.log('Submitted with data:', data);
|
|
222
|
+
setIsOpen(false);
|
|
223
|
+
},
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
226
|
+
<h3>Sample Form Content</h3>
|
|
227
|
+
<p>Current data: {JSON.stringify(data)}</p>
|
|
228
|
+
<Button onClick={() => setData({ id: 1, name: 'Jane Smith' })}>
|
|
229
|
+
Modify Data
|
|
230
|
+
</Button>
|
|
231
|
+
</Drawer>
|
|
232
|
+
</I18nWrapper>
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export const WithConfirmationDialog = ConfirmationDialogTemplate.bind({});
|
|
237
|
+
WithConfirmationDialog.args = {
|
|
238
|
+
open: true,
|
|
239
|
+
title: 'Unsaved Changes Demo',
|
|
240
|
+
description:
|
|
241
|
+
'This drawer shows the confirmation dialog when closing with unsaved changes',
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Fixed Template with lots of content and proper footer
|
|
245
|
+
const LongContentTemplate: Story<Props> = args => {
|
|
246
|
+
const [isOpen, setIsOpen] = React.useState(!!args.open || false);
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<I18nWrapper>
|
|
250
|
+
<Button onClick={() => setIsOpen(true)}>Open Long Content Drawer</Button>
|
|
251
|
+
<Drawer {...args} open={isOpen} onClose={() => setIsOpen(false)}>
|
|
252
|
+
{content}
|
|
253
|
+
{content}
|
|
254
|
+
{content}
|
|
255
|
+
{content}
|
|
256
|
+
</Drawer>
|
|
257
|
+
</I18nWrapper>
|
|
258
|
+
);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
export const WithLongContent = LongContentTemplate.bind({});
|
|
262
|
+
WithLongContent.args = {
|
|
263
|
+
open: true,
|
|
264
|
+
title: 'Long Content Drawer',
|
|
265
|
+
description: 'This drawer has a lot of content',
|
|
266
|
+
footer: simpleFooterObject, // Use the properly structured footer object
|
|
182
267
|
};
|
|
@@ -85,7 +85,11 @@ it('renders Drawer loading unchanged', () => {
|
|
|
85
85
|
|
|
86
86
|
it('renders Drawer with footer unchanged', () => {
|
|
87
87
|
const { container } = render(
|
|
88
|
-
<Drawer open={true} onClose={jest.fn()} footer={
|
|
88
|
+
<Drawer open={true} onClose={jest.fn()} footer={{
|
|
89
|
+
leftAction: <Button>Cancel</Button>,
|
|
90
|
+
onSubmit: jest.fn(),
|
|
91
|
+
loading: false
|
|
92
|
+
}}>
|
|
89
93
|
{content}
|
|
90
94
|
</Drawer>
|
|
91
95
|
);
|
|
@@ -103,7 +107,7 @@ it('renders Drawer non closable unchanged', () => {
|
|
|
103
107
|
|
|
104
108
|
it('renders Drawer side left unchanged', () => {
|
|
105
109
|
const { container } = render(
|
|
106
|
-
<Drawer open={true} onClose={jest.fn()}
|
|
110
|
+
<Drawer open={true} onClose={jest.fn()} placement="left">
|
|
107
111
|
{content}
|
|
108
112
|
</Drawer>
|
|
109
113
|
);
|
|
@@ -1,123 +1,229 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
FC,
|
|
3
|
+
useEffect,
|
|
4
|
+
useState,
|
|
5
|
+
useRef,
|
|
6
|
+
useCallback,
|
|
7
|
+
useMemo,
|
|
8
|
+
} from 'react';
|
|
2
9
|
import { Dialog, Transition } from '@headlessui/react';
|
|
3
10
|
import Spin from './Spin';
|
|
4
11
|
import Button from './Button';
|
|
5
12
|
import Close from '../icons/Close';
|
|
6
13
|
import cx from 'classnames';
|
|
14
|
+
import { useTranslation } from 'react-i18next';
|
|
15
|
+
import ConfirmDialog from './ConfirmDialog';
|
|
7
16
|
|
|
8
17
|
export interface Props {
|
|
18
|
+
title?: string | React.ReactNode;
|
|
9
19
|
open?: boolean;
|
|
10
|
-
|
|
20
|
+
data?: any;
|
|
21
|
+
onClose?: () => void;
|
|
22
|
+
width?: number | string;
|
|
23
|
+
children?: React.ReactNode;
|
|
24
|
+
footer?: {
|
|
25
|
+
leftAction?: React.ReactNode;
|
|
26
|
+
leftActionClassName?: string;
|
|
27
|
+
onSubmit?: () => void;
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
};
|
|
30
|
+
extra?: React.ReactNode;
|
|
11
31
|
className?: string;
|
|
12
|
-
|
|
32
|
+
placement?: 'left' | 'right';
|
|
13
33
|
description?: string | JSX.Element | React.ReactNode;
|
|
14
|
-
children: JSX.Element | React.ReactNode;
|
|
15
|
-
footer?: JSX.Element | React.ReactNode;
|
|
16
34
|
loading?: boolean;
|
|
17
35
|
animated?: boolean;
|
|
18
36
|
closable?: boolean;
|
|
19
|
-
side?: 'left' | 'right';
|
|
20
|
-
width?: string;
|
|
21
37
|
widthMd?: string;
|
|
22
38
|
widthLg?: string;
|
|
39
|
+
confirmDialogTitle?: string;
|
|
40
|
+
confirmDialogMessage?: string;
|
|
23
41
|
}
|
|
24
42
|
|
|
25
43
|
const Drawer: FC<Props> = ({
|
|
26
|
-
open = false,
|
|
27
|
-
onClose,
|
|
28
|
-
className,
|
|
29
44
|
title,
|
|
30
|
-
|
|
45
|
+
open = false,
|
|
46
|
+
data,
|
|
47
|
+
onClose = () => {},
|
|
31
48
|
children,
|
|
49
|
+
width = '80%',
|
|
32
50
|
footer,
|
|
51
|
+
extra,
|
|
52
|
+
className,
|
|
53
|
+
placement = 'right',
|
|
54
|
+
description,
|
|
33
55
|
loading = false,
|
|
34
56
|
animated = true,
|
|
35
|
-
side = 'right',
|
|
36
57
|
closable = true,
|
|
37
|
-
width = '100%',
|
|
38
58
|
widthMd = '80%',
|
|
39
59
|
widthLg = '60%',
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
confirmDialogTitle,
|
|
61
|
+
confirmDialogMessage,
|
|
62
|
+
}: Props) => {
|
|
63
|
+
const [originalData, setOriginalData] = useState<any>(null);
|
|
64
|
+
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
|
65
|
+
const { t } = useTranslation();
|
|
66
|
+
|
|
67
|
+
// Set original data when drawer opens and data is available
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (open && data && !originalData) {
|
|
70
|
+
setOriginalData(data);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Reset original data when drawer closes
|
|
74
|
+
if (!open) {
|
|
75
|
+
setOriginalData(null);
|
|
76
|
+
}
|
|
77
|
+
}, [open, data, originalData]);
|
|
78
|
+
|
|
79
|
+
// Check if data has changed
|
|
80
|
+
const checkChanges = useCallback(() => {
|
|
81
|
+
if (!data || Object.keys(data).length === 0) {
|
|
82
|
+
return onClose();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Compare current data with original data
|
|
86
|
+
if (originalData && JSON.stringify(originalData) !== JSON.stringify(data)) {
|
|
87
|
+
setConfirmDialogOpen(true);
|
|
88
|
+
} else {
|
|
89
|
+
onClose();
|
|
90
|
+
}
|
|
91
|
+
}, [data, originalData, onClose]);
|
|
92
|
+
|
|
93
|
+
// Handle drawer close
|
|
94
|
+
const handleClose = useCallback(() => {
|
|
95
|
+
checkChanges();
|
|
96
|
+
}, [checkChanges]);
|
|
97
|
+
|
|
98
|
+
// Confirm unsaved changes
|
|
99
|
+
const handleConfirmUnsavedChanges = useCallback(() => {
|
|
100
|
+
setConfirmDialogOpen(false);
|
|
101
|
+
onClose();
|
|
102
|
+
}, [onClose]);
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<>
|
|
106
|
+
<ConfirmDialog
|
|
107
|
+
isOpen={confirmDialogOpen}
|
|
108
|
+
onClose={() => setConfirmDialogOpen(false)}
|
|
109
|
+
onConfirm={handleConfirmUnsavedChanges}
|
|
110
|
+
title={confirmDialogTitle || t('confirmDialog.title')}
|
|
111
|
+
message={confirmDialogMessage || t('confirmDialog.message')}
|
|
112
|
+
confirmText={t('confirm') || 'Confirm'}
|
|
113
|
+
cancelText={t('cancel') || 'Cancel'}
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
<Transition appear show={open} as={React.Fragment}>
|
|
117
|
+
<Dialog
|
|
118
|
+
open={open}
|
|
119
|
+
onClose={handleClose}
|
|
120
|
+
className={cx('memori-drawer', className)}
|
|
121
|
+
>
|
|
60
122
|
<Transition.Child
|
|
61
|
-
static
|
|
62
123
|
as={React.Fragment}
|
|
63
124
|
enter="ease-out duration-300"
|
|
64
|
-
enterFrom=
|
|
65
|
-
enterTo="
|
|
125
|
+
enterFrom="opacity-0"
|
|
126
|
+
enterTo="opacity-100"
|
|
66
127
|
leave="ease-in duration-200"
|
|
67
|
-
leaveFrom="
|
|
68
|
-
leaveTo=
|
|
128
|
+
leaveFrom="opacity-100"
|
|
129
|
+
leaveTo="opacity-0"
|
|
69
130
|
>
|
|
70
|
-
<
|
|
71
|
-
className={cx('memori-drawer--panel', {
|
|
72
|
-
'memori-drawer--panel-left': side === 'left',
|
|
73
|
-
'memori-drawer--with-footer': !!footer,
|
|
74
|
-
})}
|
|
75
|
-
>
|
|
76
|
-
<style
|
|
77
|
-
dangerouslySetInnerHTML={{
|
|
78
|
-
__html: `
|
|
79
|
-
.memori-drawer--panel {
|
|
80
|
-
--memori-drawer--width: ${width};
|
|
81
|
-
--memori-drawer--width-lg: ${widthLg};
|
|
82
|
-
--memori-drawer--width-md: ${widthMd};
|
|
83
|
-
}
|
|
84
|
-
`,
|
|
85
|
-
}}
|
|
86
|
-
/>
|
|
87
|
-
{closable && (
|
|
88
|
-
<div className="memori-drawer--close">
|
|
89
|
-
<Button
|
|
90
|
-
shape="circle"
|
|
91
|
-
outlined
|
|
92
|
-
icon={<Close />}
|
|
93
|
-
onClick={() => onClose(false)}
|
|
94
|
-
/>
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
<Spin spinning={loading}>
|
|
98
|
-
{title && (
|
|
99
|
-
<Dialog.Title className="memori-drawer--title">
|
|
100
|
-
{title}
|
|
101
|
-
</Dialog.Title>
|
|
102
|
-
)}
|
|
103
|
-
{description && (
|
|
104
|
-
<Dialog.Description className="memori-drawer--description">
|
|
105
|
-
{description}
|
|
106
|
-
</Dialog.Description>
|
|
107
|
-
)}
|
|
108
|
-
|
|
109
|
-
{children}
|
|
110
|
-
|
|
111
|
-
{footer && (
|
|
112
|
-
<div className="memori-drawer--footer">{footer}</div>
|
|
113
|
-
)}
|
|
114
|
-
</Spin>
|
|
115
|
-
</Dialog.Panel>
|
|
131
|
+
<div className="memori-drawer--backdrop" />
|
|
116
132
|
</Transition.Child>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
133
|
+
<div className="memori-drawer--container">
|
|
134
|
+
<div className="memori-drawer--container-scrollable">
|
|
135
|
+
<Transition.Child
|
|
136
|
+
static
|
|
137
|
+
as={React.Fragment}
|
|
138
|
+
enter="ease-out duration-300"
|
|
139
|
+
enterFrom={animated ? 'max-w-0 opacity-0' : 'opacity-0'}
|
|
140
|
+
enterTo="max-w-80 opacity-100"
|
|
141
|
+
leave="ease-in duration-200"
|
|
142
|
+
leaveFrom="max-w-80 opacity-100"
|
|
143
|
+
leaveTo={animated ? 'max-w-0 opacity-0' : 'opacity-0'}
|
|
144
|
+
>
|
|
145
|
+
<Dialog.Panel
|
|
146
|
+
className={cx('memori-drawer--panel', {
|
|
147
|
+
'memori-drawer--panel-left': placement === 'left',
|
|
148
|
+
'memori-drawer--with-footer': !!footer,
|
|
149
|
+
})}
|
|
150
|
+
style={
|
|
151
|
+
{
|
|
152
|
+
'--memori-drawer--width': width,
|
|
153
|
+
'--memori-drawer--width--lg': widthLg,
|
|
154
|
+
'--memori-drawer--width--md': widthMd,
|
|
155
|
+
} as React.CSSProperties
|
|
156
|
+
}
|
|
157
|
+
>
|
|
158
|
+
{closable && (
|
|
159
|
+
<div className="memori-drawer--close">
|
|
160
|
+
<Button
|
|
161
|
+
shape="circle"
|
|
162
|
+
outlined
|
|
163
|
+
icon={<Close />}
|
|
164
|
+
onClick={handleClose}
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
)}
|
|
168
|
+
<Spin spinning={loading}>
|
|
169
|
+
<div className="memori-drawer--content">
|
|
170
|
+
{title && (
|
|
171
|
+
<Dialog.Title className="memori-drawer--title">
|
|
172
|
+
{title}
|
|
173
|
+
</Dialog.Title>
|
|
174
|
+
)}
|
|
175
|
+
{description && (
|
|
176
|
+
<Dialog.Description className="memori-drawer--description">
|
|
177
|
+
{description}
|
|
178
|
+
</Dialog.Description>
|
|
179
|
+
)}
|
|
180
|
+
<div className="memori-drawer--content--scrollable">
|
|
181
|
+
{children}
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</Spin>
|
|
185
|
+
{footer && (
|
|
186
|
+
<div className="memori-drawer--footer">
|
|
187
|
+
{footer.leftAction && (
|
|
188
|
+
<div
|
|
189
|
+
className={
|
|
190
|
+
'memori-drawer--footer-left-action ' +
|
|
191
|
+
(footer.leftActionClassName || '')
|
|
192
|
+
}
|
|
193
|
+
>
|
|
194
|
+
{footer.leftAction}
|
|
195
|
+
</div>
|
|
196
|
+
)}
|
|
197
|
+
{footer.onSubmit && (
|
|
198
|
+
<div className="memori-drawer--footer-actions">
|
|
199
|
+
<Button outlined onClick={handleClose}>
|
|
200
|
+
{t('cancel')}
|
|
201
|
+
</Button>
|
|
202
|
+
<Button
|
|
203
|
+
htmlType="submit"
|
|
204
|
+
onClick={footer.onSubmit}
|
|
205
|
+
loading={footer.loading}
|
|
206
|
+
className="memori-drawer--footer-confirm"
|
|
207
|
+
>
|
|
208
|
+
{t('confirm')}
|
|
209
|
+
</Button>
|
|
210
|
+
</div>
|
|
211
|
+
)}
|
|
212
|
+
{extra && (
|
|
213
|
+
<div className="memori-drawer--extra">{extra}</div>
|
|
214
|
+
)}
|
|
215
|
+
</div>
|
|
216
|
+
)}
|
|
217
|
+
</Dialog.Panel>
|
|
218
|
+
</Transition.Child>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</Dialog>
|
|
222
|
+
</Transition>
|
|
223
|
+
</>
|
|
224
|
+
);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
Drawer.displayName = 'Drawer';
|
|
122
228
|
|
|
123
229
|
export default Drawer;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renders ConfirmDialog open unchanged 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px; display: none;"
|
|
7
|
+
/>
|
|
8
|
+
</div>
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
exports[`renders ConfirmDialog unchanged 1`] = `<div />`;
|
|
12
|
+
|
|
13
|
+
exports[`renders ConfirmDialog with custom button text unchanged 1`] = `
|
|
14
|
+
<div>
|
|
15
|
+
<div
|
|
16
|
+
style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px; display: none;"
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
exports[`renders ConfirmDialog with custom message unchanged 1`] = `
|
|
22
|
+
<div>
|
|
23
|
+
<div
|
|
24
|
+
style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px; display: none;"
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
exports[`renders ConfirmDialog with custom title unchanged 1`] = `
|
|
30
|
+
<div>
|
|
31
|
+
<div
|
|
32
|
+
style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px; display: none;"
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
`;
|
package/src/locales/de.json
CHANGED
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"nothingFound": "Nichts gefunden",
|
|
39
39
|
"venue": "Veranstaltungsort",
|
|
40
40
|
"searchVenue": "Veranstaltungsort suchen...",
|
|
41
|
+
"privacyPolicy": "Datenschutzbestimmungen",
|
|
41
42
|
"memoriBlockedTitle": "Blockiert",
|
|
42
43
|
"memoriBlockedUntil": "Agent blockiert bis {{date}}",
|
|
43
44
|
"memoriBlockedAnon": "Momentan \"{{name}}„Kann nicht antworten, komm hierher zurück {{date}}",
|
|
@@ -49,6 +50,9 @@
|
|
|
49
50
|
"receiverLabel": "Zugewiesen an",
|
|
50
51
|
"completionsEnabled": "Fortschrittliche KI kann mit automatisch generierten Antworten reagieren, die manchmal falsche Informationen enthalten können",
|
|
51
52
|
"completionProviderDown": "Dieser Zwilling ist mit einer generativen KI von integriert {{provider}}, aber es ist derzeit nicht verfügbar. ",
|
|
53
|
+
"completionProviderMajorOutage": "Dieser Zwilling ist mit einer generativen KI von integriert {{provider}}, aber es ist derzeit nicht verfügbar. Diese Funktion wird nicht verfügbar sein, bis der Service wiederhergestellt ist.",
|
|
54
|
+
"completionProviderPartialOutage": "Dieser Zwilling ist mit einer generativen KI von integriert {{provider}}, aber es ist derzeit nicht verfügbar. Diese Funktion wird nicht verfügbar sein, bis der Service wiederhergestellt ist.",
|
|
55
|
+
"completionProviderDegraded": "Dieser Zwilling ist mit einer generativen KI von integriert {{provider}}, aber es ist derzeit nicht verfügbar. Diese Funktion wird nicht verfügbar sein, bis der Service wiederhergestellt ist.",
|
|
52
56
|
"completionProviderFallbackName": "ein externer Anbieter",
|
|
53
57
|
"completionProviderCheckStatusPage": "Überprüfen Sie die Statusseite",
|
|
54
58
|
"boardOfExperts": "Expertengremium",
|
|
@@ -69,6 +73,10 @@
|
|
|
69
73
|
"deepThoughtPreDisclaimerUnlogged": "Melden Sie sich an, um Deep Thought zu aktivieren.",
|
|
70
74
|
"deepThoughtPreDisclaimerNotAllowed": "Deep Thought ist deaktiviert, da Sie der Nutzung nicht zugestimmt haben. Sie können dies jederzeit in Ihren Kontoeinstellungen ändern.",
|
|
71
75
|
"notEnoughCredits": "Der Autor dieses Zwillings verfügt nicht über genügend Credits, um Ihre Frage zu beantworten.",
|
|
76
|
+
"confirmDialog": {
|
|
77
|
+
"title": "Möchten Sie diese Seite verlassen?",
|
|
78
|
+
"message": "Die Änderungen, die Sie vorgenommen haben, werden verloren."
|
|
79
|
+
},
|
|
72
80
|
"knownFacts": {
|
|
73
81
|
"title": "Bekannte Fakten",
|
|
74
82
|
"description": "Einzelheiten zu den Informationen, die zwischen Ihnen und geteilt werden {{memoriName}}",
|
|
@@ -110,6 +118,13 @@
|
|
|
110
118
|
"micButtonPopoverListening": "Klicken Sie auf die Schaltfläche, um das Sprechen zu stoppen",
|
|
111
119
|
"pageInstructExplanation": "Um mir neue Dinge beizubringen, klicken Sie auf die Schaltfläche „ANLEITEN“, um zu beginnen",
|
|
112
120
|
"pageTryMeExplanation": "Um mit mir zu sprechen, klicken Sie auf die Schaltfläche START, um zu beginnen",
|
|
121
|
+
"pagePrivacyExplanation": "Die Konversationen sind sichtbar von dem Autor des Agenten",
|
|
122
|
+
"pagePrivacyExplanationList": {
|
|
123
|
+
"allConversations": "Alle Konversationen mit diesem Agenten sind sichtbar von dem Autor des Agenten",
|
|
124
|
+
"anonymousUser": "Für anonyme Benutzer: der Autor wird den Inhalt der Konversation und Ihre IP-Adresse sehen",
|
|
125
|
+
"registeredUser": "Für registrierte Benutzer: der Autor wird den Inhalt der Konversation und Ihren Benutzernamen sehen",
|
|
126
|
+
"authorUsesInfo": "Der Autor verwendet diese Informationen, um die Funktionen des Agenten zu verbessern und Ihnen einen besseren Service anzubieten. Wenn Sie die Konversation fortsetzen, stimmen Sie diesen Bedingungen zu."
|
|
127
|
+
},
|
|
113
128
|
"instructButton": "WEISE MICH AN",
|
|
114
129
|
"tryMeButton": "START",
|
|
115
130
|
"chatHistory": "Chatverlauf",
|