flowengine-mcp-app 1.1.2 → 1.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.
- package/README.md +4 -5
- package/build/index.js +56 -54
- package/build/index.js.map +1 -1
- package/build/ui/base.d.ts +1 -0
- package/build/ui/base.d.ts.map +1 -1
- package/build/ui/base.js +201 -77
- package/build/ui/base.js.map +1 -1
- package/build/ui/component-viewer.d.ts +14 -0
- package/build/ui/component-viewer.d.ts.map +1 -0
- package/build/ui/component-viewer.js +678 -0
- package/build/ui/component-viewer.js.map +1 -0
- package/build/ui/dashboard.d.ts +21 -0
- package/build/ui/dashboard.d.ts.map +1 -0
- package/build/ui/dashboard.js +252 -0
- package/build/ui/dashboard.js.map +1 -0
- package/build/ui/instances.js +4 -0
- package/build/ui/instances.js.map +1 -1
- package/build/ui/n8n-viewer.d.ts +12 -0
- package/build/ui/n8n-viewer.d.ts.map +1 -0
- package/build/ui/n8n-viewer.js +371 -0
- package/build/ui/n8n-viewer.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI Component Viewer - Direct component preview via MCP
|
|
3
|
+
* Displays forms, chatbots, widgets, and other UI components
|
|
4
|
+
*/
|
|
5
|
+
export function renderComponentViewer(component) {
|
|
6
|
+
const componentType = component?.type || 'chatbot';
|
|
7
|
+
const componentName = component?.name || 'UI Component';
|
|
8
|
+
// Escape JSON for safe embedding in HTML/JavaScript
|
|
9
|
+
const componentJson = JSON.stringify(component || {});
|
|
10
|
+
const escapedComponentJson = componentJson
|
|
11
|
+
.replace(/\\/g, '\\\\')
|
|
12
|
+
.replace(/`/g, '\\`')
|
|
13
|
+
.replace(/\$/g, '\\$');
|
|
14
|
+
return `<!DOCTYPE html>
|
|
15
|
+
<html lang="en">
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="UTF-8">
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
<title>FlowEngine - ${componentName}</title>
|
|
20
|
+
<style>
|
|
21
|
+
* {
|
|
22
|
+
margin: 0;
|
|
23
|
+
padding: 0;
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
29
|
+
background: #000000;
|
|
30
|
+
color: #ffffff;
|
|
31
|
+
height: 100vh;
|
|
32
|
+
overflow: hidden;
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Header */
|
|
38
|
+
.viewer-header {
|
|
39
|
+
padding: 12px 16px;
|
|
40
|
+
border-bottom: 1px solid rgba(31, 41, 55, 1);
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 12px;
|
|
45
|
+
background: #000000;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.logo {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 8px;
|
|
53
|
+
font-size: 16px;
|
|
54
|
+
font-weight: 700;
|
|
55
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6, #10b981);
|
|
56
|
+
-webkit-background-clip: text;
|
|
57
|
+
-webkit-text-fill-color: transparent;
|
|
58
|
+
background-clip: text;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.component-info {
|
|
62
|
+
flex: 1;
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: 12px;
|
|
66
|
+
padding: 0 16px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.component-title {
|
|
70
|
+
font-size: 14px;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
color: rgba(209, 213, 219, 1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.component-badge {
|
|
76
|
+
padding: 4px 8px;
|
|
77
|
+
background: rgba(16, 185, 129, 0.1);
|
|
78
|
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
79
|
+
border-radius: 4px;
|
|
80
|
+
color: rgba(52, 211, 153, 1);
|
|
81
|
+
font-size: 11px;
|
|
82
|
+
font-weight: 600;
|
|
83
|
+
text-transform: uppercase;
|
|
84
|
+
letter-spacing: 0.05em;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.component-badge.form {
|
|
88
|
+
background: rgba(59, 130, 246, 0.1);
|
|
89
|
+
border-color: rgba(59, 130, 246, 0.3);
|
|
90
|
+
color: rgba(96, 165, 250, 1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.component-badge.chatbot {
|
|
94
|
+
background: rgba(139, 92, 246, 0.1);
|
|
95
|
+
border-color: rgba(139, 92, 246, 0.3);
|
|
96
|
+
color: rgba(196, 181, 253, 1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.header-actions {
|
|
100
|
+
display: flex;
|
|
101
|
+
gap: 8px;
|
|
102
|
+
align-items: center;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.action-btn {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
gap: 6px;
|
|
110
|
+
padding: 6px 12px;
|
|
111
|
+
background: rgba(31, 41, 55, 0.5);
|
|
112
|
+
border: 1px solid rgba(75, 85, 99, 1);
|
|
113
|
+
border-radius: 6px;
|
|
114
|
+
color: rgba(209, 213, 219, 1);
|
|
115
|
+
font-size: 12px;
|
|
116
|
+
font-weight: 500;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
transition: all 0.2s;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.action-btn:hover {
|
|
122
|
+
background: rgba(31, 41, 55, 0.8);
|
|
123
|
+
border-color: rgba(107, 114, 128, 1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.action-btn.primary {
|
|
127
|
+
background: #ffffff;
|
|
128
|
+
color: #000000;
|
|
129
|
+
border-color: #ffffff;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.action-btn.primary:hover {
|
|
133
|
+
background: rgba(229, 231, 235, 1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Component Viewer Container */
|
|
137
|
+
.viewer-container {
|
|
138
|
+
flex: 1;
|
|
139
|
+
overflow: auto;
|
|
140
|
+
background: #000000;
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
justify-content: center;
|
|
144
|
+
padding: 32px;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Preview Frame */
|
|
148
|
+
.preview-frame {
|
|
149
|
+
width: 100%;
|
|
150
|
+
max-width: 480px;
|
|
151
|
+
background: rgba(17, 24, 39, 0.5);
|
|
152
|
+
border: 1px solid rgba(31, 41, 55, 1);
|
|
153
|
+
border-radius: 12px;
|
|
154
|
+
padding: 24px;
|
|
155
|
+
position: relative;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Chatbot Preview Styles */
|
|
159
|
+
.chatbot-preview {
|
|
160
|
+
position: relative;
|
|
161
|
+
width: 100%;
|
|
162
|
+
max-width: 400px;
|
|
163
|
+
height: 500px;
|
|
164
|
+
margin: 0 auto;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.chat-bubble {
|
|
168
|
+
position: absolute;
|
|
169
|
+
bottom: 16px;
|
|
170
|
+
right: 16px;
|
|
171
|
+
width: 60px;
|
|
172
|
+
height: 60px;
|
|
173
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
|
174
|
+
border-radius: 50%;
|
|
175
|
+
display: flex;
|
|
176
|
+
align-items: center;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
transition: transform 0.2s;
|
|
181
|
+
z-index: 2;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.chat-bubble:hover {
|
|
185
|
+
transform: scale(1.05);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.chat-window {
|
|
189
|
+
position: absolute;
|
|
190
|
+
bottom: 96px;
|
|
191
|
+
right: 16px;
|
|
192
|
+
width: 340px;
|
|
193
|
+
height: 380px;
|
|
194
|
+
background: rgba(17, 24, 39, 1);
|
|
195
|
+
border: 1px solid rgba(55, 65, 81, 1);
|
|
196
|
+
border-radius: 12px;
|
|
197
|
+
display: flex;
|
|
198
|
+
flex-direction: column;
|
|
199
|
+
overflow: hidden;
|
|
200
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
|
|
201
|
+
z-index: 1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.chat-header {
|
|
205
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
|
206
|
+
padding: 16px 20px;
|
|
207
|
+
display: flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
gap: 12px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.chat-header-avatar {
|
|
213
|
+
width: 40px;
|
|
214
|
+
height: 40px;
|
|
215
|
+
background: rgba(255, 255, 255, 0.2);
|
|
216
|
+
border-radius: 50%;
|
|
217
|
+
display: flex;
|
|
218
|
+
align-items: center;
|
|
219
|
+
justify-content: center;
|
|
220
|
+
color: #ffffff;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.chat-header-title {
|
|
224
|
+
color: #ffffff;
|
|
225
|
+
font-weight: 600;
|
|
226
|
+
font-size: 16px;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.chat-messages-preview {
|
|
230
|
+
flex: 1;
|
|
231
|
+
padding: 16px;
|
|
232
|
+
background: rgba(17, 24, 39, 1);
|
|
233
|
+
overflow-y: auto;
|
|
234
|
+
display: flex;
|
|
235
|
+
flex-direction: column;
|
|
236
|
+
gap: 12px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.chat-message-bot {
|
|
240
|
+
display: flex;
|
|
241
|
+
gap: 8px;
|
|
242
|
+
align-items: flex-start;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.chat-message-avatar {
|
|
246
|
+
width: 32px;
|
|
247
|
+
height: 32px;
|
|
248
|
+
background: linear-gradient(135deg, #10b981, #06b6d4);
|
|
249
|
+
border-radius: 50%;
|
|
250
|
+
flex-shrink: 0;
|
|
251
|
+
display: flex;
|
|
252
|
+
align-items: center;
|
|
253
|
+
justify-content: center;
|
|
254
|
+
color: #ffffff;
|
|
255
|
+
font-size: 12px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.chat-message-bubble {
|
|
259
|
+
background: rgba(31, 41, 55, 0.8);
|
|
260
|
+
padding: 10px 14px;
|
|
261
|
+
border-radius: 12px;
|
|
262
|
+
color: rgba(209, 213, 219, 1);
|
|
263
|
+
font-size: 14px;
|
|
264
|
+
line-height: 1.5;
|
|
265
|
+
max-width: 80%;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.chat-message-user {
|
|
269
|
+
display: flex;
|
|
270
|
+
justify-content: flex-end;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.chat-message-user .chat-message-bubble {
|
|
274
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
|
275
|
+
color: #ffffff;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.chat-input-preview {
|
|
279
|
+
padding: 12px;
|
|
280
|
+
background: rgba(17, 24, 39, 1);
|
|
281
|
+
border-top: 1px solid rgba(55, 65, 81, 1);
|
|
282
|
+
display: flex;
|
|
283
|
+
gap: 8px;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.chat-input-field {
|
|
287
|
+
flex: 1;
|
|
288
|
+
padding: 10px 14px;
|
|
289
|
+
background: rgba(31, 41, 55, 0.8);
|
|
290
|
+
border: 1px solid rgba(75, 85, 99, 1);
|
|
291
|
+
border-radius: 8px;
|
|
292
|
+
color: rgba(209, 213, 219, 1);
|
|
293
|
+
font-size: 14px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.chat-send-btn {
|
|
297
|
+
width: 40px;
|
|
298
|
+
height: 40px;
|
|
299
|
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
|
300
|
+
border: none;
|
|
301
|
+
border-radius: 8px;
|
|
302
|
+
color: #ffffff;
|
|
303
|
+
display: flex;
|
|
304
|
+
align-items: center;
|
|
305
|
+
justify-content: center;
|
|
306
|
+
cursor: pointer;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Form Preview Styles */
|
|
310
|
+
.form-preview {
|
|
311
|
+
width: 100%;
|
|
312
|
+
max-width: 500px;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.form-field {
|
|
316
|
+
margin-bottom: 16px;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.form-label {
|
|
320
|
+
display: block;
|
|
321
|
+
font-size: 14px;
|
|
322
|
+
font-weight: 500;
|
|
323
|
+
color: #ffffff;
|
|
324
|
+
margin-bottom: 8px;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.form-input {
|
|
328
|
+
width: 100%;
|
|
329
|
+
padding: 12px 16px;
|
|
330
|
+
background: rgba(31, 41, 55, 0.5);
|
|
331
|
+
border: 1px solid rgba(75, 85, 99, 1);
|
|
332
|
+
border-radius: 8px;
|
|
333
|
+
color: #ffffff;
|
|
334
|
+
font-size: 14px;
|
|
335
|
+
transition: all 0.2s;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.form-input:focus {
|
|
339
|
+
outline: none;
|
|
340
|
+
border-color: #3b82f6;
|
|
341
|
+
background: rgba(31, 41, 55, 0.8);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.form-input::placeholder {
|
|
345
|
+
color: rgba(156, 163, 175, 1);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.form-textarea {
|
|
349
|
+
min-height: 100px;
|
|
350
|
+
resize: vertical;
|
|
351
|
+
font-family: inherit;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.form-submit {
|
|
355
|
+
width: 100%;
|
|
356
|
+
padding: 12px 16px;
|
|
357
|
+
background: #ffffff;
|
|
358
|
+
color: #000000;
|
|
359
|
+
border: none;
|
|
360
|
+
border-radius: 8px;
|
|
361
|
+
font-size: 14px;
|
|
362
|
+
font-weight: 500;
|
|
363
|
+
cursor: pointer;
|
|
364
|
+
transition: all 0.2s;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.form-submit:hover {
|
|
368
|
+
background: rgba(229, 231, 235, 1);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* Empty State */
|
|
372
|
+
.empty-state {
|
|
373
|
+
text-align: center;
|
|
374
|
+
padding: 48px 24px;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.empty-state svg {
|
|
378
|
+
margin: 0 auto 16px;
|
|
379
|
+
opacity: 0.3;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.empty-state h3 {
|
|
383
|
+
font-size: 18px;
|
|
384
|
+
font-weight: 600;
|
|
385
|
+
color: #ffffff;
|
|
386
|
+
margin-bottom: 8px;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.empty-state p {
|
|
390
|
+
font-size: 14px;
|
|
391
|
+
color: rgba(156, 163, 175, 1);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Custom Component HTML Container */
|
|
395
|
+
.custom-html-container {
|
|
396
|
+
width: 100%;
|
|
397
|
+
height: 100%;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
::-webkit-scrollbar {
|
|
401
|
+
width: 8px;
|
|
402
|
+
height: 8px;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
::-webkit-scrollbar-track {
|
|
406
|
+
background: transparent;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
::-webkit-scrollbar-thumb {
|
|
410
|
+
background: rgba(75, 85, 99, 0.5);
|
|
411
|
+
border-radius: 4px;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
::-webkit-scrollbar-thumb:hover {
|
|
415
|
+
background: rgba(75, 85, 99, 0.7);
|
|
416
|
+
}
|
|
417
|
+
</style>
|
|
418
|
+
</head>
|
|
419
|
+
<body>
|
|
420
|
+
<!-- Header -->
|
|
421
|
+
<div class="viewer-header">
|
|
422
|
+
<div class="logo">
|
|
423
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
424
|
+
<path d="M12 2L2 7L12 12L22 7L12 2Z" fill="url(#gradient)" stroke="currentColor" stroke-width="2"/>
|
|
425
|
+
<path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2"/>
|
|
426
|
+
<path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2"/>
|
|
427
|
+
<defs>
|
|
428
|
+
<linearGradient id="gradient" x1="2" y1="2" x2="22" y2="22">
|
|
429
|
+
<stop offset="0%" stop-color="#3b82f6"/>
|
|
430
|
+
<stop offset="50%" stop-color="#8b5cf6"/>
|
|
431
|
+
<stop offset="100%" stop-color="#10b981"/>
|
|
432
|
+
</linearGradient>
|
|
433
|
+
</defs>
|
|
434
|
+
</svg>
|
|
435
|
+
FlowEngine
|
|
436
|
+
</div>
|
|
437
|
+
<div class="component-info">
|
|
438
|
+
<div class="component-title" id="componentTitle">${componentName}</div>
|
|
439
|
+
<div class="component-badge ${componentType}" id="componentBadge">${componentType}</div>
|
|
440
|
+
</div>
|
|
441
|
+
<div class="header-actions">
|
|
442
|
+
<button class="action-btn" id="copyCodeBtn" title="Copy HTML code">
|
|
443
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
444
|
+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
|
445
|
+
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
|
446
|
+
</svg>
|
|
447
|
+
<span>Copy Code</span>
|
|
448
|
+
</button>
|
|
449
|
+
<button class="action-btn" id="exportBtn" title="Export component">
|
|
450
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
451
|
+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
452
|
+
<polyline points="7 10 12 15 17 10"></polyline>
|
|
453
|
+
<line x1="12" y1="15" x2="12" y2="3"></line>
|
|
454
|
+
</svg>
|
|
455
|
+
<span>Export</span>
|
|
456
|
+
</button>
|
|
457
|
+
<button class="action-btn primary" id="embedBtn" title="Get embed code">
|
|
458
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
459
|
+
<polyline points="16 18 22 12 16 6"></polyline>
|
|
460
|
+
<polyline points="8 6 2 12 8 18"></polyline>
|
|
461
|
+
</svg>
|
|
462
|
+
<span>Embed</span>
|
|
463
|
+
</button>
|
|
464
|
+
</div>
|
|
465
|
+
</div>
|
|
466
|
+
|
|
467
|
+
<!-- Component Viewer Container -->
|
|
468
|
+
<div class="viewer-container" id="viewerContainer">
|
|
469
|
+
<!-- Component Preview will be rendered here -->
|
|
470
|
+
</div>
|
|
471
|
+
|
|
472
|
+
<script>
|
|
473
|
+
const componentData = JSON.parse(\`${escapedComponentJson}\`);
|
|
474
|
+
const viewerContainer = document.getElementById('viewerContainer');
|
|
475
|
+
const copyCodeBtn = document.getElementById('copyCodeBtn');
|
|
476
|
+
const exportBtn = document.getElementById('exportBtn');
|
|
477
|
+
const embedBtn = document.getElementById('embedBtn');
|
|
478
|
+
|
|
479
|
+
// Render component based on type
|
|
480
|
+
function renderComponent() {
|
|
481
|
+
const type = componentData.type || 'chatbot';
|
|
482
|
+
|
|
483
|
+
if (componentData.html) {
|
|
484
|
+
// Custom HTML component
|
|
485
|
+
viewerContainer.innerHTML = \`
|
|
486
|
+
<div class="custom-html-container">
|
|
487
|
+
\${componentData.html}
|
|
488
|
+
</div>
|
|
489
|
+
\`;
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Default components based on type
|
|
494
|
+
switch (type) {
|
|
495
|
+
case 'chatbot':
|
|
496
|
+
renderChatbot();
|
|
497
|
+
break;
|
|
498
|
+
case 'form':
|
|
499
|
+
case 'contact-form':
|
|
500
|
+
case 'survey':
|
|
501
|
+
renderForm();
|
|
502
|
+
break;
|
|
503
|
+
case 'widget':
|
|
504
|
+
renderWidget();
|
|
505
|
+
break;
|
|
506
|
+
default:
|
|
507
|
+
renderEmptyState();
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function renderChatbot() {
|
|
512
|
+
viewerContainer.innerHTML = \`
|
|
513
|
+
<div class="chatbot-preview">
|
|
514
|
+
<!-- Chat Bubble -->
|
|
515
|
+
<div class="chat-bubble">
|
|
516
|
+
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
517
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" stroke="#ffffff"></path>
|
|
518
|
+
</svg>
|
|
519
|
+
</div>
|
|
520
|
+
|
|
521
|
+
<!-- Chat Window -->
|
|
522
|
+
<div class="chat-window">
|
|
523
|
+
<!-- Header -->
|
|
524
|
+
<div class="chat-header">
|
|
525
|
+
<div class="chat-header-avatar">
|
|
526
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
527
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
528
|
+
</svg>
|
|
529
|
+
</div>
|
|
530
|
+
<div class="chat-header-title">\${componentData.name || 'AI Assistant'}</div>
|
|
531
|
+
</div>
|
|
532
|
+
|
|
533
|
+
<!-- Messages -->
|
|
534
|
+
<div class="chat-messages-preview">
|
|
535
|
+
<!-- Bot Message -->
|
|
536
|
+
<div class="chat-message-bot">
|
|
537
|
+
<div class="chat-message-avatar">🤖</div>
|
|
538
|
+
<div class="chat-message-bubble">
|
|
539
|
+
Hi! I'm your AI assistant. How can I help you today?
|
|
540
|
+
</div>
|
|
541
|
+
</div>
|
|
542
|
+
|
|
543
|
+
<!-- User Message -->
|
|
544
|
+
<div class="chat-message-user">
|
|
545
|
+
<div class="chat-message-bubble">
|
|
546
|
+
Hello! What can you do?
|
|
547
|
+
</div>
|
|
548
|
+
</div>
|
|
549
|
+
|
|
550
|
+
<!-- Bot Message -->
|
|
551
|
+
<div class="chat-message-bot">
|
|
552
|
+
<div class="chat-message-avatar">🤖</div>
|
|
553
|
+
<div class="chat-message-bubble">
|
|
554
|
+
I can help you with various tasks, answer questions, and guide you through processes. Just ask!
|
|
555
|
+
</div>
|
|
556
|
+
</div>
|
|
557
|
+
</div>
|
|
558
|
+
|
|
559
|
+
<!-- Input Area -->
|
|
560
|
+
<div class="chat-input-preview">
|
|
561
|
+
<input type="text" class="chat-input-field" placeholder="Type your message..." disabled>
|
|
562
|
+
<button class="chat-send-btn">
|
|
563
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
|
|
564
|
+
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path>
|
|
565
|
+
</svg>
|
|
566
|
+
</button>
|
|
567
|
+
</div>
|
|
568
|
+
</div>
|
|
569
|
+
</div>
|
|
570
|
+
\`;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function renderForm() {
|
|
574
|
+
viewerContainer.innerHTML = \`
|
|
575
|
+
<div class="form-preview">
|
|
576
|
+
<form id="previewForm">
|
|
577
|
+
<div class="form-field">
|
|
578
|
+
<label class="form-label">Name</label>
|
|
579
|
+
<input type="text" class="form-input" placeholder="Enter your name" disabled>
|
|
580
|
+
</div>
|
|
581
|
+
<div class="form-field">
|
|
582
|
+
<label class="form-label">Email</label>
|
|
583
|
+
<input type="email" class="form-input" placeholder="you@example.com" disabled>
|
|
584
|
+
</div>
|
|
585
|
+
<div class="form-field">
|
|
586
|
+
<label class="form-label">Message</label>
|
|
587
|
+
<textarea class="form-input form-textarea" placeholder="Your message..." disabled></textarea>
|
|
588
|
+
</div>
|
|
589
|
+
<button type="submit" class="form-submit" disabled>Submit</button>
|
|
590
|
+
</form>
|
|
591
|
+
</div>
|
|
592
|
+
\`;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function renderWidget() {
|
|
596
|
+
viewerContainer.innerHTML = \`
|
|
597
|
+
<div class="empty-state">
|
|
598
|
+
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
599
|
+
<rect x="3" y="3" width="7" height="7"></rect>
|
|
600
|
+
<rect x="14" y="3" width="7" height="7"></rect>
|
|
601
|
+
<rect x="14" y="14" width="7" height="7"></rect>
|
|
602
|
+
<rect x="3" y="14" width="7" height="7"></rect>
|
|
603
|
+
</svg>
|
|
604
|
+
<h3>Widget Preview</h3>
|
|
605
|
+
<p>This is a preview of your custom widget component</p>
|
|
606
|
+
</div>
|
|
607
|
+
\`;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function renderEmptyState() {
|
|
611
|
+
viewerContainer.innerHTML = \`
|
|
612
|
+
<div class="empty-state">
|
|
613
|
+
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
614
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
615
|
+
<line x1="9" y1="9" x2="15" y2="9"></line>
|
|
616
|
+
<line x1="9" y1="15" x2="15" y2="15"></line>
|
|
617
|
+
</svg>
|
|
618
|
+
<h3>No Component Loaded</h3>
|
|
619
|
+
<p>No UI component data available to display</p>
|
|
620
|
+
</div>
|
|
621
|
+
\`;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// Initialize
|
|
625
|
+
renderComponent();
|
|
626
|
+
|
|
627
|
+
// Copy Code button
|
|
628
|
+
copyCodeBtn.addEventListener('click', () => {
|
|
629
|
+
const htmlCode = componentData.html || viewerContainer.innerHTML;
|
|
630
|
+
navigator.clipboard.writeText(htmlCode).then(() => {
|
|
631
|
+
const originalText = copyCodeBtn.innerHTML;
|
|
632
|
+
copyCodeBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg><span>Copied!</span>';
|
|
633
|
+
setTimeout(() => {
|
|
634
|
+
copyCodeBtn.innerHTML = originalText;
|
|
635
|
+
}, 2000);
|
|
636
|
+
}).catch(err => {
|
|
637
|
+
console.error('Failed to copy:', err);
|
|
638
|
+
alert('Failed to copy code to clipboard');
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
// Export button
|
|
643
|
+
exportBtn.addEventListener('click', () => {
|
|
644
|
+
const data = JSON.stringify(componentData, null, 2);
|
|
645
|
+
const blob = new Blob([data], { type: 'application/json' });
|
|
646
|
+
const url = URL.createObjectURL(blob);
|
|
647
|
+
const a = document.createElement('a');
|
|
648
|
+
a.href = url;
|
|
649
|
+
a.download = (componentData.name || 'component').replace(/[^a-z0-9]/gi, '-').toLowerCase() + '.json';
|
|
650
|
+
a.click();
|
|
651
|
+
URL.revokeObjectURL(url);
|
|
652
|
+
|
|
653
|
+
const originalText = exportBtn.innerHTML;
|
|
654
|
+
exportBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg><span>Exported!</span>';
|
|
655
|
+
setTimeout(() => {
|
|
656
|
+
exportBtn.innerHTML = originalText;
|
|
657
|
+
}, 2000);
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
// Embed button
|
|
661
|
+
embedBtn.addEventListener('click', () => {
|
|
662
|
+
const embedCode = \`<iframe src="https://flowengine.cloud/embed/\${componentData.id || 'component'}" width="100%" height="600" frameborder="0"></iframe>\`;
|
|
663
|
+
navigator.clipboard.writeText(embedCode).then(() => {
|
|
664
|
+
const originalText = embedBtn.innerHTML;
|
|
665
|
+
embedBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg><span>Copied!</span>';
|
|
666
|
+
setTimeout(() => {
|
|
667
|
+
embedBtn.innerHTML = originalText;
|
|
668
|
+
}, 2000);
|
|
669
|
+
}).catch(err => {
|
|
670
|
+
console.error('Failed to copy:', err);
|
|
671
|
+
alert('Failed to copy embed code to clipboard');
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
</script>
|
|
675
|
+
</body>
|
|
676
|
+
</html>`;
|
|
677
|
+
}
|
|
678
|
+
//# sourceMappingURL=component-viewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-viewer.js","sourceRoot":"","sources":["../../src/ui/component-viewer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,UAAU,qBAAqB,CAAC,SAAyB;IAC7D,MAAM,aAAa,GAAG,SAAS,EAAE,IAAI,IAAI,SAAS,CAAC;IACnD,MAAM,aAAa,GAAG,SAAS,EAAE,IAAI,IAAI,cAAc,CAAC;IAExD,oDAAoD;IACpD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,oBAAoB,GAAG,aAAa;SACvC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAEzB,OAAO;;;;;wBAKe,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDAmaoB,aAAa;oCAClC,aAAa,yBAAyB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yCAkC9C,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2MrD,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Dashboard - Portals & Hosting Management
|
|
3
|
+
* Combines portal and instance management into a single interface
|
|
4
|
+
*/
|
|
5
|
+
export interface UnifiedPortalInstance {
|
|
6
|
+
id: string;
|
|
7
|
+
instance_name: string;
|
|
8
|
+
instance_url: string;
|
|
9
|
+
storage_limit_gb: number;
|
|
10
|
+
storage_used_gb?: number;
|
|
11
|
+
status: string;
|
|
12
|
+
subscription_status?: string;
|
|
13
|
+
type: 'pay-per-instance' | 'dedicated';
|
|
14
|
+
created_at: string;
|
|
15
|
+
updated_at?: string;
|
|
16
|
+
client_email?: string;
|
|
17
|
+
allow_full_access?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function renderUnifiedDashboard(portals: UnifiedPortalInstance[]): string;
|
|
20
|
+
export declare function renderPortalDetails(portal: UnifiedPortalInstance): string;
|
|
21
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/ui/dashboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,IAAI,EAAE,kBAAkB,GAAG,WAAW,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAuI/E;AA0BD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAoGzE"}
|