codacus commited on
Commit
f8987be
·
unverified ·
2 Parent(s): 1cb836a 30605ea

Merge pull request #412 from wonderwhy-er/Cleanup-extract-import-button

Browse files
app/components/chat/BaseChat.tsx CHANGED
@@ -14,20 +14,13 @@ import { Messages } from './Messages.client';
14
  import { SendButton } from './SendButton.client';
15
  import { APIKeyManager } from './APIKeyManager';
16
  import Cookies from 'js-cookie';
17
- import { toast } from 'react-toastify';
18
  import * as Tooltip from '@radix-ui/react-tooltip';
19
 
20
  import styles from './BaseChat.module.scss';
21
  import type { ProviderInfo } from '~/utils/types';
22
- import { ExportChatButton } from '~/components/chat/ExportChatButton';
23
-
24
- const EXAMPLE_PROMPTS = [
25
- { text: 'Build a todo app in React using Tailwind' },
26
- { text: 'Build a simple blog using Astro' },
27
- { text: 'Create a cookie consent form using Material UI' },
28
- { text: 'Make a space invaders game' },
29
- { text: 'How do I center a div?' },
30
- ];
31
 
32
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
33
  const providerList = PROVIDER_LIST;
@@ -168,67 +161,6 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
168
  }
169
  };
170
 
171
- const chatImportButton = !chatStarted && (
172
- <div className="flex flex-col items-center justify-center flex-1 p-4">
173
- <input
174
- type="file"
175
- id="chat-import"
176
- className="hidden"
177
- accept=".json"
178
- onChange={async (e) => {
179
- const file = e.target.files?.[0];
180
-
181
- if (file && importChat) {
182
- try {
183
- const reader = new FileReader();
184
-
185
- reader.onload = async (e) => {
186
- try {
187
- const content = e.target?.result as string;
188
- const data = JSON.parse(content);
189
-
190
- if (!Array.isArray(data.messages)) {
191
- toast.error('Invalid chat file format');
192
- }
193
-
194
- await importChat(data.description, data.messages);
195
- toast.success('Chat imported successfully');
196
- } catch (error: unknown) {
197
- if (error instanceof Error) {
198
- toast.error('Failed to parse chat file: ' + error.message);
199
- } else {
200
- toast.error('Failed to parse chat file');
201
- }
202
- }
203
- };
204
- reader.onerror = () => toast.error('Failed to read chat file');
205
- reader.readAsText(file);
206
- } catch (error) {
207
- toast.error(error instanceof Error ? error.message : 'Failed to import chat');
208
- }
209
- e.target.value = ''; // Reset file input
210
- } else {
211
- toast.error('Something went wrong');
212
- }
213
- }}
214
- />
215
- <div className="flex flex-col items-center gap-4 max-w-2xl text-center">
216
- <div className="flex gap-2">
217
- <button
218
- onClick={() => {
219
- const input = document.getElementById('chat-import');
220
- input?.click();
221
- }}
222
- className="px-4 py-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary hover:bg-bolt-elements-background-depth-3 transition-all flex items-center gap-2"
223
- >
224
- <div className="i-ph:upload-simple" />
225
- Import Chat
226
- </button>
227
- </div>
228
- </div>
229
- </div>
230
- );
231
-
232
  const baseChat = (
233
  <div
234
  ref={ref}
@@ -378,27 +310,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
378
  </div>
379
  </div>
380
  </div>
381
- {chatImportButton}
382
- {!chatStarted && (
383
- <div id="examples" className="relative w-full max-w-xl mx-auto mt-8 flex justify-center">
384
- <div className="flex flex-col space-y-2 [mask-image:linear-gradient(to_bottom,black_0%,transparent_180%)] hover:[mask-image:none]">
385
- {EXAMPLE_PROMPTS.map((examplePrompt, index) => {
386
- return (
387
- <button
388
- key={index}
389
- onClick={(event) => {
390
- sendMessage?.(event, examplePrompt.text);
391
- }}
392
- className="group flex items-center w-full gap-2 justify-center bg-transparent text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary transition-theme"
393
- >
394
- {examplePrompt.text}
395
- <div className="i-ph:arrow-bend-down-left" />
396
- </button>
397
- );
398
- })}
399
- </div>
400
- </div>
401
- )}
402
  </div>
403
  <ClientOnly>{() => <Workbench chatStarted={chatStarted} isStreaming={isStreaming} />}</ClientOnly>
404
  </div>
 
14
  import { SendButton } from './SendButton.client';
15
  import { APIKeyManager } from './APIKeyManager';
16
  import Cookies from 'js-cookie';
 
17
  import * as Tooltip from '@radix-ui/react-tooltip';
18
 
19
  import styles from './BaseChat.module.scss';
20
  import type { ProviderInfo } from '~/utils/types';
21
+ import { ExportChatButton } from '~/components/chat/chatExportAndImport/ExportChatButton';
22
+ import { ImportButton } from '~/components/chat/chatExportAndImport/ImportButton';
23
+ import { ExamplePrompts } from '~/components/chat/ExamplePrompts';
 
 
 
 
 
 
24
 
25
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
  const providerList = PROVIDER_LIST;
 
161
  }
162
  };
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  const baseChat = (
165
  <div
166
  ref={ref}
 
310
  </div>
311
  </div>
312
  </div>
313
+ {!chatStarted && ImportButton(importChat)}
314
+ {!chatStarted && ExamplePrompts(sendMessage)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  </div>
316
  <ClientOnly>{() => <Workbench chatStarted={chatStarted} isStreaming={isStreaming} />}</ClientOnly>
317
  </div>
app/components/chat/ExamplePrompts.tsx ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+
3
+ const EXAMPLE_PROMPTS = [
4
+ { text: 'Build a todo app in React using Tailwind' },
5
+ { text: 'Build a simple blog using Astro' },
6
+ { text: 'Create a cookie consent form using Material UI' },
7
+ { text: 'Make a space invaders game' },
8
+ { text: 'How do I center a div?' },
9
+ ];
10
+
11
+ export function ExamplePrompts(sendMessage?: { (event: React.UIEvent, messageInput?: string): void | undefined }) {
12
+ return (
13
+ <div id="examples" className="relative w-full max-w-xl mx-auto mt-8 flex justify-center">
14
+ <div className="flex flex-col space-y-2 [mask-image:linear-gradient(to_bottom,black_0%,transparent_180%)] hover:[mask-image:none]">
15
+ {EXAMPLE_PROMPTS.map((examplePrompt, index: number) => {
16
+ return (
17
+ <button
18
+ key={index}
19
+ onClick={(event) => {
20
+ sendMessage?.(event, examplePrompt.text);
21
+ }}
22
+ className="group flex items-center w-full gap-2 justify-center bg-transparent text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary transition-theme"
23
+ >
24
+ {examplePrompt.text}
25
+ <div className="i-ph:arrow-bend-down-left" />
26
+ </button>
27
+ );
28
+ })}
29
+ </div>
30
+ </div>
31
+ );
32
+ }
app/components/chat/{ExportChatButton.tsx → chatExportAndImport/ExportChatButton.tsx} RENAMED
File without changes
app/components/chat/chatExportAndImport/ImportButton.tsx ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Message } from 'ai';
2
+ import { toast } from 'react-toastify';
3
+ import React from 'react';
4
+
5
+ export function ImportButton(importChat: ((description: string, messages: Message[]) => Promise<void>) | undefined) {
6
+ return (
7
+ <div className="flex flex-col items-center justify-center flex-1 p-4">
8
+ <input
9
+ type="file"
10
+ id="chat-import"
11
+ className="hidden"
12
+ accept=".json"
13
+ onChange={async (e) => {
14
+ const file = e.target.files?.[0];
15
+
16
+ if (file && importChat) {
17
+ try {
18
+ const reader = new FileReader();
19
+
20
+ reader.onload = async (e) => {
21
+ try {
22
+ const content = e.target?.result as string;
23
+ const data = JSON.parse(content);
24
+
25
+ if (!Array.isArray(data.messages)) {
26
+ toast.error('Invalid chat file format');
27
+ }
28
+
29
+ await importChat(data.description, data.messages);
30
+ toast.success('Chat imported successfully');
31
+ } catch (error: unknown) {
32
+ if (error instanceof Error) {
33
+ toast.error('Failed to parse chat file: ' + error.message);
34
+ } else {
35
+ toast.error('Failed to parse chat file');
36
+ }
37
+ }
38
+ };
39
+ reader.onerror = () => toast.error('Failed to read chat file');
40
+ reader.readAsText(file);
41
+ } catch (error) {
42
+ toast.error(error instanceof Error ? error.message : 'Failed to import chat');
43
+ }
44
+ e.target.value = ''; // Reset file input
45
+ } else {
46
+ toast.error('Something went wrong');
47
+ }
48
+ }}
49
+ />
50
+ <div className="flex flex-col items-center gap-4 max-w-2xl text-center">
51
+ <div className="flex gap-2">
52
+ <button
53
+ onClick={() => {
54
+ const input = document.getElementById('chat-import');
55
+ input?.click();
56
+ }}
57
+ className="px-4 py-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary hover:bg-bolt-elements-background-depth-3 transition-all flex items-center gap-2"
58
+ >
59
+ <div className="i-ph:upload-simple" />
60
+ Import Chat
61
+ </button>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ );
66
+ }