@realtimex/email-automator 2.2.0 → 2.2.1

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/api/server.ts +0 -6
  2. package/api/src/config/index.ts +3 -0
  3. package/bin/email-automator-setup.js +2 -3
  4. package/bin/email-automator.js +23 -7
  5. package/package.json +1 -2
  6. package/src/App.tsx +0 -622
  7. package/src/components/AccountSettings.tsx +0 -310
  8. package/src/components/AccountSettingsPage.tsx +0 -390
  9. package/src/components/Configuration.tsx +0 -1345
  10. package/src/components/Dashboard.tsx +0 -940
  11. package/src/components/ErrorBoundary.tsx +0 -71
  12. package/src/components/LiveTerminal.tsx +0 -308
  13. package/src/components/LoadingSpinner.tsx +0 -39
  14. package/src/components/Login.tsx +0 -371
  15. package/src/components/Logo.tsx +0 -57
  16. package/src/components/SetupWizard.tsx +0 -388
  17. package/src/components/Toast.tsx +0 -109
  18. package/src/components/migration/MigrationBanner.tsx +0 -97
  19. package/src/components/migration/MigrationModal.tsx +0 -458
  20. package/src/components/migration/MigrationPulseIndicator.tsx +0 -38
  21. package/src/components/mode-toggle.tsx +0 -24
  22. package/src/components/theme-provider.tsx +0 -72
  23. package/src/components/ui/alert.tsx +0 -66
  24. package/src/components/ui/button.tsx +0 -57
  25. package/src/components/ui/card.tsx +0 -75
  26. package/src/components/ui/dialog.tsx +0 -133
  27. package/src/components/ui/input.tsx +0 -22
  28. package/src/components/ui/label.tsx +0 -24
  29. package/src/components/ui/otp-input.tsx +0 -184
  30. package/src/context/AppContext.tsx +0 -422
  31. package/src/context/MigrationContext.tsx +0 -53
  32. package/src/context/TerminalContext.tsx +0 -31
  33. package/src/core/actions.ts +0 -76
  34. package/src/core/auth.ts +0 -108
  35. package/src/core/intelligence.ts +0 -76
  36. package/src/core/processor.ts +0 -112
  37. package/src/hooks/useRealtimeEmails.ts +0 -111
  38. package/src/index.css +0 -140
  39. package/src/lib/api-config.ts +0 -42
  40. package/src/lib/api-old.ts +0 -228
  41. package/src/lib/api.ts +0 -421
  42. package/src/lib/migration-check.ts +0 -264
  43. package/src/lib/sounds.ts +0 -120
  44. package/src/lib/supabase-config.ts +0 -117
  45. package/src/lib/supabase.ts +0 -28
  46. package/src/lib/types.ts +0 -166
  47. package/src/lib/utils.ts +0 -6
  48. package/src/main.tsx +0 -10
@@ -1,310 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { Mail, Cloud, Key, Link as LinkIcon, Loader2, CheckCircle, XCircle } from 'lucide-react';
3
- import { supabase } from '../lib/supabase';
4
-
5
- interface AccountStatus {
6
- gmail: boolean;
7
- m365: boolean;
8
- }
9
-
10
- export function AccountSettings() {
11
- const [status, setStatus] = useState<AccountStatus>({ gmail: false, m365: false });
12
- const [loading, setLoading] = useState(true);
13
- const [showGmailDialog, setShowGmailDialog] = useState(false);
14
- const [showM365Dialog, setShowM365Dialog] = useState(false);
15
-
16
- useEffect(() => {
17
- checkAccountStatus();
18
- }, []);
19
-
20
- async function checkAccountStatus() {
21
- setLoading(true);
22
- const { data } = await supabase
23
- .from('email_accounts')
24
- .select('provider')
25
- .eq('user_id', (await supabase.auth.getUser()).data.user?.id);
26
-
27
- const providers = data?.map(a => a.provider) || [];
28
- setStatus({
29
- gmail: providers.includes('gmail'),
30
- m365: providers.includes('m365')
31
- });
32
- setLoading(false);
33
- }
34
-
35
- return (
36
- <div className="space-y-6">
37
- <h2 className="text-2xl font-bold text-slate-900">Email Accounts</h2>
38
- <p className="text-slate-600">Connect your email providers to start automating</p>
39
-
40
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
41
- {/* Gmail Card */}
42
- <div className="bg-white rounded-2xl border-l-4 border-l-red-500 p-6 shadow-sm">
43
- <div className="flex justify-between items-start mb-4">
44
- <div className="flex items-center gap-3">
45
- <Mail className="w-6 h-6 text-red-500" />
46
- <h3 className="text-lg font-bold">Gmail</h3>
47
- </div>
48
- {status.gmail ? (
49
- <span className="px-3 py-1 bg-emerald-50 text-emerald-700 rounded-full text-xs font-semibold flex items-center gap-1">
50
- <CheckCircle className="w-3 h-3" />
51
- Connected
52
- </span>
53
- ) : (
54
- <span className="px-3 py-1 bg-slate-100 text-slate-600 rounded-full text-xs font-semibold flex items-center gap-1">
55
- <XCircle className="w-3 h-3" />
56
- Disconnected
57
- </span>
58
- )}
59
- </div>
60
-
61
- <button
62
- onClick={() => setShowGmailDialog(true)}
63
- className="w-full bg-red-50 hover:bg-red-100 text-red-600 py-2 rounded-xl font-medium transition-all flex items-center justify-center gap-2"
64
- >
65
- <LinkIcon className="w-4 h-4" />
66
- {status.gmail ? 'Reconnect' : 'Connect Gmail'}
67
- </button>
68
-
69
- <details className="mt-4">
70
- <summary className="cursor-pointer text-sm text-slate-600 hover:text-slate-900 flex items-center gap-2">
71
- <Key className="w-4 h-4" />
72
- Configure Credentials
73
- </summary>
74
- <div className="mt-3 space-y-2">
75
- <p className="text-xs text-slate-500">Paste your Google OAuth credentials JSON:</p>
76
- <textarea
77
- className="w-full p-2 border rounded-lg text-xs font-mono"
78
- rows={4}
79
- placeholder='{"installed": {"client_id": "...", ...}}'
80
- />
81
- <button className="w-full bg-slate-100 hover:bg-slate-200 text-slate-700 py-1 rounded-lg text-sm">
82
- Save Credentials
83
- </button>
84
- </div>
85
- </details>
86
- </div>
87
-
88
- {/* Microsoft 365 Card */}
89
- <div className="bg-white rounded-2xl border-l-4 border-l-blue-500 p-6 shadow-sm">
90
- <div className="flex justify-between items-start mb-4">
91
- <div className="flex items-center gap-3">
92
- <Cloud className="w-6 h-6 text-blue-500" />
93
- <h3 className="text-lg font-bold">Microsoft 365</h3>
94
- </div>
95
- {status.m365 ? (
96
- <span className="px-3 py-1 bg-emerald-50 text-emerald-700 rounded-full text-xs font-semibold flex items-center gap-1">
97
- <CheckCircle className="w-3 h-3" />
98
- Connected
99
- </span>
100
- ) : (
101
- <span className="px-3 py-1 bg-slate-100 text-slate-600 rounded-full text-xs font-semibold flex items-center gap-1">
102
- <XCircle className="w-3 h-3" />
103
- Disconnected
104
- </span>
105
- )}
106
- </div>
107
-
108
- <button
109
- onClick={() => setShowM365Dialog(true)}
110
- className="w-full bg-blue-50 hover:bg-blue-100 text-blue-600 py-2 rounded-xl font-medium transition-all flex items-center justify-center gap-2"
111
- >
112
- <LinkIcon className="w-4 h-4" />
113
- {status.m365 ? 'Reconnect' : 'Connect M365'}
114
- </button>
115
-
116
- <details className="mt-4">
117
- <summary className="cursor-pointer text-sm text-slate-600 hover:text-slate-900 flex items-center gap-2">
118
- <Key className="w-4 h-4" />
119
- Configure Client
120
- </summary>
121
- <div className="mt-3 space-y-2">
122
- <p className="text-xs text-slate-500">Paste your Azure AD app config JSON:</p>
123
- <textarea
124
- className="w-full p-2 border rounded-lg text-xs font-mono"
125
- rows={4}
126
- placeholder='{"client_id": "...", "tenant_id": "..."}'
127
- />
128
- <button className="w-full bg-slate-100 hover:bg-slate-200 text-slate-700 py-1 rounded-lg text-sm">
129
- Save Config
130
- </button>
131
- </div>
132
- </details>
133
- </div>
134
- </div>
135
-
136
- {/* Gmail Auth Dialog */}
137
- {showGmailDialog && (
138
- <GmailAuthDialog onClose={() => {
139
- setShowGmailDialog(false);
140
- checkAccountStatus();
141
- }} />
142
- )}
143
-
144
- {/* M365 Auth Dialog */}
145
- {showM365Dialog && (
146
- <M365AuthDialog onClose={() => {
147
- setShowM365Dialog(false);
148
- checkAccountStatus();
149
- }} />
150
- )}
151
- </div>
152
- );
153
- }
154
-
155
- function GmailAuthDialog({ onClose }: { onClose: () => void }) {
156
- const [authUrl, setAuthUrl] = useState('');
157
- const [code, setCode] = useState('');
158
- const [loading, setLoading] = useState(true);
159
-
160
- useEffect(() => {
161
- fetchAuthUrl();
162
- }, []);
163
-
164
- async function fetchAuthUrl() {
165
- try {
166
- const res = await fetch('http://localhost:3002/api/auth/gmail/url');
167
- const data = await res.json();
168
- setAuthUrl(data.url);
169
- } catch (error) {
170
- console.error(error);
171
- } finally {
172
- setLoading(false);
173
- }
174
- }
175
-
176
- async function handleSubmit() {
177
- try {
178
- await fetch('http://localhost:3002/api/auth/gmail/callback', {
179
- method: 'POST',
180
- headers: { 'Content-Type': 'application/json' },
181
- body: JSON.stringify({ code })
182
- });
183
- onClose();
184
- } catch (error) {
185
- console.error(error);
186
- }
187
- }
188
-
189
- return (
190
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
191
- <div className="bg-white rounded-3xl p-8 max-w-lg w-full mx-4">
192
- <h2 className="text-2xl font-bold mb-4">Connect Gmail</h2>
193
- {loading ? (
194
- <div className="flex items-center justify-center py-8">
195
- <Loader2 className="w-8 h-8 animate-spin text-blue-600" />
196
- </div>
197
- ) : (
198
- <>
199
- <p className="text-slate-600 mb-4">Open this URL to authorize:</p>
200
- <a
201
- href={authUrl}
202
- target="_blank"
203
- rel="noopener noreferrer"
204
- className="block p-3 bg-blue-50 rounded-xl text-blue-600 text-sm break-all hover:bg-blue-100 transition-colors mb-4"
205
- >
206
- {authUrl}
207
- </a>
208
- <input
209
- type="text"
210
- placeholder="Paste authorization code here"
211
- value={code}
212
- onChange={(e) => setCode(e.target.value)}
213
- className="w-full px-4 py-3 border rounded-xl mb-4"
214
- />
215
- <div className="flex gap-3">
216
- <button
217
- onClick={onClose}
218
- className="flex-1 py-2 border rounded-xl hover:bg-slate-50"
219
- >
220
- Cancel
221
- </button>
222
- <button
223
- onClick={handleSubmit}
224
- disabled={!code}
225
- className="flex-1 py-2 bg-blue-600 text-white rounded-xl hover:bg-blue-700 disabled:opacity-50"
226
- >
227
- Submit
228
- </button>
229
- </div>
230
- </>
231
- )}
232
- </div>
233
- </div>
234
- );
235
- }
236
-
237
- function M365AuthDialog({ onClose }: { onClose: () => void }) {
238
- const [deviceCode, setDeviceCode] = useState('');
239
- const [userCode, setUserCode] = useState('');
240
- const [message, setMessage] = useState('');
241
- const [loading, setLoading] = useState(true);
242
-
243
- useEffect(() => {
244
- initiateFlow();
245
- }, []);
246
-
247
- async function initiateFlow() {
248
- try {
249
- const res = await fetch('http://localhost:3002/api/auth/m365/device-flow', {
250
- method: 'POST'
251
- });
252
- const data = await res.json();
253
- setDeviceCode(data.device_code);
254
- setUserCode(data.user_code);
255
- setMessage(data.message);
256
- } catch (error) {
257
- console.error(error);
258
- } finally {
259
- setLoading(false);
260
- }
261
- }
262
-
263
- async function completeFlow() {
264
- try {
265
- await fetch('http://localhost:3002/api/auth/m365/complete', {
266
- method: 'POST',
267
- headers: { 'Content-Type': 'application/json' },
268
- body: JSON.stringify({ device_code: deviceCode })
269
- });
270
- onClose();
271
- } catch (error) {
272
- console.error(error);
273
- }
274
- }
275
-
276
- return (
277
- <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
278
- <div className="bg-white rounded-3xl p-8 max-w-lg w-full mx-4">
279
- <h2 className="text-2xl font-bold mb-4">Connect Microsoft 365</h2>
280
- {loading ? (
281
- <div className="flex items-center justify-center py-8">
282
- <Loader2 className="w-8 h-8 animate-spin text-blue-600" />
283
- </div>
284
- ) : (
285
- <>
286
- <p className="text-slate-600 mb-4">{message}</p>
287
- <div className="bg-blue-50 rounded-xl p-6 text-center mb-6">
288
- <p className="text-sm text-slate-600 mb-2">Enter this code:</p>
289
- <p className="text-4xl font-mono font-bold text-blue-600">{userCode}</p>
290
- </div>
291
- <div className="flex gap-3">
292
- <button
293
- onClick={onClose}
294
- className="flex-1 py-2 border rounded-xl hover:bg-slate-50"
295
- >
296
- Cancel
297
- </button>
298
- <button
299
- onClick={completeFlow}
300
- className="flex-1 py-2 bg-blue-600 text-white rounded-xl hover:bg-blue-700"
301
- >
302
- I've Authenticated
303
- </button>
304
- </div>
305
- </>
306
- )}
307
- </div>
308
- </div>
309
- );
310
- }