flowengine-mcp-app 2.0.1 → 3.0.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 +19 -270
- package/bin.js +12 -0
- package/package.json +8 -29
- package/LICENSE +0 -21
- package/build/client.d.ts +0 -56
- package/build/client.d.ts.map +0 -1
- package/build/client.js +0 -188
- package/build/client.js.map +0 -1
- package/build/index.d.ts +0 -12
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -339
- package/build/index.js.map +0 -1
- package/build/ui/base.d.ts +0 -8
- package/build/ui/base.d.ts.map +0 -1
- package/build/ui/base.js +0 -425
- package/build/ui/base.js.map +0 -1
- package/build/ui/component-viewer.d.ts +0 -14
- package/build/ui/component-viewer.d.ts.map +0 -1
- package/build/ui/component-viewer.js +0 -678
- package/build/ui/component-viewer.js.map +0 -1
- package/build/ui/dashboard.d.ts +0 -21
- package/build/ui/dashboard.d.ts.map +0 -1
- package/build/ui/dashboard.js +0 -252
- package/build/ui/dashboard.js.map +0 -1
- package/build/ui/demo.d.ts +0 -14
- package/build/ui/demo.d.ts.map +0 -1
- package/build/ui/demo.js +0 -222
- package/build/ui/demo.js.map +0 -1
- package/build/ui/instances.d.ts +0 -17
- package/build/ui/instances.d.ts.map +0 -1
- package/build/ui/instances.js +0 -233
- package/build/ui/instances.js.map +0 -1
- package/build/ui/n8n-viewer.d.ts +0 -12
- package/build/ui/n8n-viewer.d.ts.map +0 -1
- package/build/ui/n8n-viewer.js +0 -371
- package/build/ui/n8n-viewer.js.map +0 -1
- package/build/ui/portals.d.ts +0 -14
- package/build/ui/portals.d.ts.map +0 -1
- package/build/ui/portals.js +0 -184
- package/build/ui/portals.js.map +0 -1
- package/build/ui/widgets.d.ts +0 -17
- package/build/ui/widgets.d.ts.map +0 -1
- package/build/ui/widgets.js +0 -200
- package/build/ui/widgets.js.map +0 -1
- package/build/ui/workflows.d.ts +0 -17
- package/build/ui/workflows.d.ts.map +0 -1
- package/build/ui/workflows.js +0 -217
- package/build/ui/workflows.js.map +0 -1
package/build/ui/portals.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Client Portals UI
|
|
3
|
-
*/
|
|
4
|
-
import { baseLayout, renderEmptyState } from './base.js';
|
|
5
|
-
export function renderPortalsDashboard(instances) {
|
|
6
|
-
if (!instances || instances.length === 0) {
|
|
7
|
-
return baseLayout('Client Portals', `
|
|
8
|
-
<div class="header">
|
|
9
|
-
<h1>🏢 Client Portals</h1>
|
|
10
|
-
<p>Manage your client instances and portals</p>
|
|
11
|
-
</div>
|
|
12
|
-
${renderEmptyState('No Portals Found', 'You don\'t have any client portals yet. Create your first instance to get started.')}
|
|
13
|
-
`);
|
|
14
|
-
}
|
|
15
|
-
const instanceCards = instances
|
|
16
|
-
.map((instance) => {
|
|
17
|
-
const statusBadge = getStatusBadge(instance.status, instance.subscription_status);
|
|
18
|
-
const storageUsed = Math.floor(Math.random() * instance.storage_limit_gb * 0.7); // Mock data
|
|
19
|
-
return `
|
|
20
|
-
<div class="card">
|
|
21
|
-
<div class="card-header">
|
|
22
|
-
<div>
|
|
23
|
-
<div class="card-title">${instance.instance_url}</div>
|
|
24
|
-
<div class="card-subtitle">ID: ${instance.id.slice(0, 8)}...</div>
|
|
25
|
-
</div>
|
|
26
|
-
${statusBadge}
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<div>
|
|
30
|
-
<div class="stat">
|
|
31
|
-
<span class="stat-label">Storage</span>
|
|
32
|
-
<span class="stat-value">${storageUsed} GB / ${instance.storage_limit_gb} GB</span>
|
|
33
|
-
</div>
|
|
34
|
-
<div class="stat">
|
|
35
|
-
<span class="stat-label">Subscription</span>
|
|
36
|
-
<span class="stat-value">${instance.subscription_status || 'Active'}</span>
|
|
37
|
-
</div>
|
|
38
|
-
<div class="stat">
|
|
39
|
-
<span class="stat-label">Created</span>
|
|
40
|
-
<span class="stat-value">${new Date(instance.created_at).toLocaleDateString()}</span>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<div class="actions">
|
|
45
|
-
<a href="https://${instance.instance_url}" target="_blank" class="btn btn-primary">
|
|
46
|
-
Open Portal →
|
|
47
|
-
</a>
|
|
48
|
-
<button class="btn btn-secondary">Manage</button>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
`;
|
|
52
|
-
})
|
|
53
|
-
.join('');
|
|
54
|
-
return baseLayout('Client Portals', `
|
|
55
|
-
<div class="header">
|
|
56
|
-
<h1>🏢 Client Portals</h1>
|
|
57
|
-
<p>Manage ${instances.length} client ${instances.length === 1 ? 'instance' : 'instances'}</p>
|
|
58
|
-
</div>
|
|
59
|
-
|
|
60
|
-
<div class="grid">
|
|
61
|
-
${instanceCards}
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<div class="card">
|
|
65
|
-
<h3 style="margin-bottom: 12px;">Quick Actions</h3>
|
|
66
|
-
<div style="display: flex; gap: 12px;">
|
|
67
|
-
<button class="btn btn-primary">+ New Portal</button>
|
|
68
|
-
<button class="btn btn-secondary">View All Clients</button>
|
|
69
|
-
<button class="btn btn-secondary">Invite Client</button>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
`);
|
|
73
|
-
}
|
|
74
|
-
function getStatusBadge(status, subscriptionStatus) {
|
|
75
|
-
const isActive = status === 'active' || status === 'running';
|
|
76
|
-
const isPaused = status === 'paused' || subscriptionStatus === 'paused';
|
|
77
|
-
const isError = status === 'error' || status === 'failed';
|
|
78
|
-
if (isActive) {
|
|
79
|
-
return '<span class="badge badge-success"><span class="dot dot-success"></span>Active</span>';
|
|
80
|
-
}
|
|
81
|
-
else if (isPaused) {
|
|
82
|
-
return '<span class="badge badge-warning"><span class="dot dot-warning"></span>Paused</span>';
|
|
83
|
-
}
|
|
84
|
-
else if (isError) {
|
|
85
|
-
return '<span class="badge badge-error"><span class="dot dot-error"></span>Error</span>';
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
return '<span class="badge badge-neutral"><span class="dot dot-neutral"></span>Inactive</span>';
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
export function renderPortalDetails(instanceId, workflows, widgets) {
|
|
92
|
-
return baseLayout('Portal Details', `
|
|
93
|
-
<div class="header">
|
|
94
|
-
<h1>📊 Portal Details</h1>
|
|
95
|
-
<p>Instance: <span class="code">${instanceId.slice(0, 8)}...</span></p>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<div class="card" style="margin-bottom: 24px;">
|
|
99
|
-
<h3 style="margin-bottom: 16px;">Overview</h3>
|
|
100
|
-
<div class="stat">
|
|
101
|
-
<span class="stat-label">Active Workflows</span>
|
|
102
|
-
<span class="stat-value">${workflows.filter((w) => w.active).length} / ${workflows.length}</span>
|
|
103
|
-
</div>
|
|
104
|
-
<div class="stat">
|
|
105
|
-
<span class="stat-label">Widgets</span>
|
|
106
|
-
<span class="stat-value">${widgets.length}</span>
|
|
107
|
-
</div>
|
|
108
|
-
<div class="stat">
|
|
109
|
-
<span class="stat-label">Status</span>
|
|
110
|
-
<span class="stat-value"><span class="badge badge-success">Active</span></span>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
<h3 style="margin: 24px 0 16px;">Workflows</h3>
|
|
115
|
-
${renderWorkflowsList(workflows)}
|
|
116
|
-
|
|
117
|
-
<h3 style="margin: 24px 0 16px;">Widgets</h3>
|
|
118
|
-
${renderWidgetsList(widgets)}
|
|
119
|
-
|
|
120
|
-
<div class="actions">
|
|
121
|
-
<button class="btn btn-primary">Open Portal</button>
|
|
122
|
-
<button class="btn btn-secondary">Manage Settings</button>
|
|
123
|
-
</div>
|
|
124
|
-
`);
|
|
125
|
-
}
|
|
126
|
-
function renderWorkflowsList(workflows) {
|
|
127
|
-
if (!workflows || workflows.length === 0) {
|
|
128
|
-
return renderEmptyState('No Workflows', 'No workflows configured for this portal.');
|
|
129
|
-
}
|
|
130
|
-
const rows = workflows
|
|
131
|
-
.slice(0, 5)
|
|
132
|
-
.map((w) => `
|
|
133
|
-
<tr>
|
|
134
|
-
<td>${w.name}</td>
|
|
135
|
-
<td>${w.active ? '<span class="badge badge-success">Active</span>' : '<span class="badge badge-neutral">Inactive</span>'}</td>
|
|
136
|
-
<td>${w.executions_count || 0} runs</td>
|
|
137
|
-
</tr>
|
|
138
|
-
`)
|
|
139
|
-
.join('');
|
|
140
|
-
return `
|
|
141
|
-
<table class="table">
|
|
142
|
-
<thead>
|
|
143
|
-
<tr>
|
|
144
|
-
<th>Workflow</th>
|
|
145
|
-
<th>Status</th>
|
|
146
|
-
<th>Executions</th>
|
|
147
|
-
</tr>
|
|
148
|
-
</thead>
|
|
149
|
-
<tbody>
|
|
150
|
-
${rows}
|
|
151
|
-
</tbody>
|
|
152
|
-
</table>
|
|
153
|
-
`;
|
|
154
|
-
}
|
|
155
|
-
function renderWidgetsList(widgets) {
|
|
156
|
-
if (!widgets || widgets.length === 0) {
|
|
157
|
-
return renderEmptyState('No Widgets', 'No widgets configured for this portal.');
|
|
158
|
-
}
|
|
159
|
-
const rows = widgets
|
|
160
|
-
.slice(0, 5)
|
|
161
|
-
.map((w) => `
|
|
162
|
-
<tr>
|
|
163
|
-
<td>${w.name}</td>
|
|
164
|
-
<td><span class="code">${w.widget_type}</span></td>
|
|
165
|
-
<td>${w.is_active ? '<span class="badge badge-success">Active</span>' : '<span class="badge badge-neutral">Inactive</span>'}</td>
|
|
166
|
-
</tr>
|
|
167
|
-
`)
|
|
168
|
-
.join('');
|
|
169
|
-
return `
|
|
170
|
-
<table class="table">
|
|
171
|
-
<thead>
|
|
172
|
-
<tr>
|
|
173
|
-
<th>Widget</th>
|
|
174
|
-
<th>Type</th>
|
|
175
|
-
<th>Status</th>
|
|
176
|
-
</tr>
|
|
177
|
-
</thead>
|
|
178
|
-
<tbody>
|
|
179
|
-
${rows}
|
|
180
|
-
</tbody>
|
|
181
|
-
</table>
|
|
182
|
-
`;
|
|
183
|
-
}
|
|
184
|
-
//# sourceMappingURL=portals.js.map
|
package/build/ui/portals.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"portals.js","sourceRoot":"","sources":["../../src/ui/portals.ts"],"names":[],"mappings":"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"}
|
package/build/ui/widgets.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI Builder - Forms, Chatbots, and Interactive Components
|
|
3
|
-
*/
|
|
4
|
-
export interface Widget {
|
|
5
|
-
id: string;
|
|
6
|
-
name: string;
|
|
7
|
-
widget_type: string;
|
|
8
|
-
webhook_url: string;
|
|
9
|
-
is_active: boolean;
|
|
10
|
-
created_at: string;
|
|
11
|
-
updated_at: string;
|
|
12
|
-
config?: any;
|
|
13
|
-
submissions_count?: number;
|
|
14
|
-
}
|
|
15
|
-
export declare function renderWidgetBuilder(widgets: Widget[], instanceId?: string): string;
|
|
16
|
-
export declare function renderWidgetDetails(widget: Widget): string;
|
|
17
|
-
//# sourceMappingURL=widgets.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"widgets.d.ts","sourceRoot":"","sources":["../../src/ui/widgets.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAwFlF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAqE1D"}
|
package/build/ui/widgets.js
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI Builder - Forms, Chatbots, and Interactive Components
|
|
3
|
-
*/
|
|
4
|
-
import { baseLayout, renderEmptyState } from './base.js';
|
|
5
|
-
export function renderWidgetBuilder(widgets, instanceId) {
|
|
6
|
-
if (!widgets || widgets.length === 0) {
|
|
7
|
-
return baseLayout('UI Builder', `
|
|
8
|
-
<div class="header">
|
|
9
|
-
<h1>🎨 UI Builder</h1>
|
|
10
|
-
<p>Create and manage forms, chatbots, and interactive components</p>
|
|
11
|
-
</div>
|
|
12
|
-
${renderEmptyState('No Components Found', 'You don\'t have any UI components yet. Create your first form, chatbot, or interactive element to engage with your users.')}
|
|
13
|
-
`);
|
|
14
|
-
}
|
|
15
|
-
const activeCount = widgets.filter((w) => w.is_active).length;
|
|
16
|
-
const totalSubmissions = widgets.reduce((sum, w) => sum + (w.submissions_count || 0), 0);
|
|
17
|
-
const widgetCards = widgets
|
|
18
|
-
.map((widget) => {
|
|
19
|
-
const statusBadge = widget.is_active
|
|
20
|
-
? '<span class="badge badge-success"><span class="dot dot-success"></span>Live</span>'
|
|
21
|
-
: '<span class="badge badge-neutral"><span class="dot dot-neutral"></span>Draft</span>';
|
|
22
|
-
const typeIcon = getWidgetTypeIcon(widget.widget_type);
|
|
23
|
-
const typeBadge = getWidgetTypeBadge(widget.widget_type);
|
|
24
|
-
return `
|
|
25
|
-
<div class="card">
|
|
26
|
-
<div class="card-header">
|
|
27
|
-
<div>
|
|
28
|
-
<div class="card-title">${typeIcon} ${widget.name}</div>
|
|
29
|
-
<div class="card-subtitle">ID: ${widget.id.slice(0, 8)}...</div>
|
|
30
|
-
</div>
|
|
31
|
-
${statusBadge}
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
<div>
|
|
35
|
-
<div class="stat">
|
|
36
|
-
<span class="stat-label">Type</span>
|
|
37
|
-
<span class="stat-value">${typeBadge}</span>
|
|
38
|
-
</div>
|
|
39
|
-
<div class="stat">
|
|
40
|
-
<span class="stat-label">Submissions</span>
|
|
41
|
-
<span class="stat-value">${widget.submissions_count || 0}</span>
|
|
42
|
-
</div>
|
|
43
|
-
<div class="stat">
|
|
44
|
-
<span class="stat-label">Webhook</span>
|
|
45
|
-
<span class="stat-value"><span class="code">${truncateUrl(widget.webhook_url)}</span></span>
|
|
46
|
-
</div>
|
|
47
|
-
<div class="stat">
|
|
48
|
-
<span class="stat-label">Created</span>
|
|
49
|
-
<span class="stat-value">${new Date(widget.created_at).toLocaleDateString()}</span>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<div class="actions">
|
|
54
|
-
<button class="btn btn-primary">Edit</button>
|
|
55
|
-
<button class="btn btn-secondary">Preview</button>
|
|
56
|
-
<button class="btn btn-secondary">Get Embed Code</button>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
`;
|
|
60
|
-
})
|
|
61
|
-
.join('');
|
|
62
|
-
return baseLayout('UI Builder', `
|
|
63
|
-
<div class="header">
|
|
64
|
-
<h1>🎨 UI Builder</h1>
|
|
65
|
-
<p>${widgets.length} components • ${activeCount} live • ${totalSubmissions.toLocaleString()} total submissions</p>
|
|
66
|
-
</div>
|
|
67
|
-
|
|
68
|
-
<div class="grid">
|
|
69
|
-
${widgetCards}
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<div class="card">
|
|
73
|
-
<h3 style="margin-bottom: 12px;">Create New Component</h3>
|
|
74
|
-
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px;">
|
|
75
|
-
<button class="btn btn-primary">📝 Form</button>
|
|
76
|
-
<button class="btn btn-secondary">💬 Chatbot</button>
|
|
77
|
-
<button class="btn btn-secondary">📋 Survey</button>
|
|
78
|
-
<button class="btn btn-secondary">📞 Contact Form</button>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
`);
|
|
82
|
-
}
|
|
83
|
-
export function renderWidgetDetails(widget) {
|
|
84
|
-
const statusBadge = widget.is_active
|
|
85
|
-
? '<span class="badge badge-success">Live</span>'
|
|
86
|
-
: '<span class="badge badge-neutral">Draft</span>';
|
|
87
|
-
const typeIcon = getWidgetTypeIcon(widget.widget_type);
|
|
88
|
-
const embedCode = generateEmbedCode(widget.id);
|
|
89
|
-
return baseLayout(`${widget.name}`, `
|
|
90
|
-
<div class="header">
|
|
91
|
-
<h1>${typeIcon} ${widget.name}</h1>
|
|
92
|
-
<p>Component ID: <span class="code">${widget.id}</span> • ${statusBadge}</p>
|
|
93
|
-
</div>
|
|
94
|
-
|
|
95
|
-
<div class="grid" style="grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-bottom: 24px;">
|
|
96
|
-
<div class="card">
|
|
97
|
-
<div class="stat">
|
|
98
|
-
<span class="stat-label">Type</span>
|
|
99
|
-
<span class="stat-value">${getWidgetTypeBadge(widget.widget_type)}</span>
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
<div class="card">
|
|
103
|
-
<div class="stat">
|
|
104
|
-
<span class="stat-label">Status</span>
|
|
105
|
-
<span class="stat-value">${statusBadge}</span>
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
<div class="card">
|
|
109
|
-
<div class="stat">
|
|
110
|
-
<span class="stat-label">Submissions</span>
|
|
111
|
-
<span class="stat-value">${widget.submissions_count || 0}</span>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
<div class="card">
|
|
115
|
-
<div class="stat">
|
|
116
|
-
<span class="stat-label">Last Updated</span>
|
|
117
|
-
<span class="stat-value">${new Date(widget.updated_at).toLocaleDateString()}</span>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<div class="card" style="margin-bottom: 24px;">
|
|
123
|
-
<h3 style="margin-bottom: 16px;">Webhook Configuration</h3>
|
|
124
|
-
<div class="stat">
|
|
125
|
-
<span class="stat-label">Webhook URL</span>
|
|
126
|
-
<span class="stat-value"><span class="code">${widget.webhook_url}</span></span>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
<div class="card" style="margin-bottom: 24px;">
|
|
131
|
-
<h3 style="margin-bottom: 16px;">Embed Code</h3>
|
|
132
|
-
<div style="background: rgba(38, 38, 38, 0.5); border: 1px solid #262626; border-radius: 8px; padding: 16px; font-family: monospace; font-size: 13px; overflow-x: auto;">
|
|
133
|
-
<pre style="margin: 0; color: #22c55e;">${escapeHtml(embedCode)}</pre>
|
|
134
|
-
</div>
|
|
135
|
-
<button class="btn btn-secondary" style="margin-top: 12px;">📋 Copy Embed Code</button>
|
|
136
|
-
</div>
|
|
137
|
-
|
|
138
|
-
${widget.config ? renderWidgetConfig(widget.config) : ''}
|
|
139
|
-
|
|
140
|
-
<div class="actions">
|
|
141
|
-
<button class="btn btn-primary">Edit</button>
|
|
142
|
-
<button class="btn btn-secondary">Preview</button>
|
|
143
|
-
${widget.is_active ? '<button class="btn btn-secondary">Unpublish</button>' : '<button class="btn btn-primary">Publish</button>'}
|
|
144
|
-
<button class="btn btn-danger">Delete</button>
|
|
145
|
-
</div>
|
|
146
|
-
`);
|
|
147
|
-
}
|
|
148
|
-
function getWidgetTypeIcon(type) {
|
|
149
|
-
const icons = {
|
|
150
|
-
form: '📝',
|
|
151
|
-
chat: '💬',
|
|
152
|
-
chatbot: '🤖',
|
|
153
|
-
survey: '📋',
|
|
154
|
-
contact: '📞',
|
|
155
|
-
booking: '📅',
|
|
156
|
-
custom: '⚙️',
|
|
157
|
-
};
|
|
158
|
-
return icons[type.toLowerCase()] || '🎨';
|
|
159
|
-
}
|
|
160
|
-
function getWidgetTypeBadge(type) {
|
|
161
|
-
const typeMap = {
|
|
162
|
-
form: 'Form',
|
|
163
|
-
chat: 'Chat',
|
|
164
|
-
chatbot: 'Chatbot',
|
|
165
|
-
survey: 'Survey',
|
|
166
|
-
contact: 'Contact',
|
|
167
|
-
booking: 'Booking',
|
|
168
|
-
custom: 'Custom',
|
|
169
|
-
};
|
|
170
|
-
const displayName = typeMap[type.toLowerCase()] || type;
|
|
171
|
-
return `<span class="code">${displayName}</span>`;
|
|
172
|
-
}
|
|
173
|
-
function truncateUrl(url) {
|
|
174
|
-
if (url.length <= 40)
|
|
175
|
-
return url;
|
|
176
|
-
return url.slice(0, 37) + '...';
|
|
177
|
-
}
|
|
178
|
-
function generateEmbedCode(widgetId) {
|
|
179
|
-
return `<!-- FlowEngine Widget -->
|
|
180
|
-
<div id="flowengine-widget-${widgetId}"></div>
|
|
181
|
-
<script src="https://flowengine.cloud/widget.js"></script>
|
|
182
|
-
<script>
|
|
183
|
-
FlowEngine.init('${widgetId}');
|
|
184
|
-
</script>`;
|
|
185
|
-
}
|
|
186
|
-
function escapeHtml(html) {
|
|
187
|
-
return html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
188
|
-
}
|
|
189
|
-
function renderWidgetConfig(config) {
|
|
190
|
-
const configJson = JSON.stringify(config, null, 2);
|
|
191
|
-
return `
|
|
192
|
-
<div class="card" style="margin-bottom: 24px;">
|
|
193
|
-
<h3 style="margin-bottom: 16px;">Configuration</h3>
|
|
194
|
-
<div style="background: rgba(38, 38, 38, 0.5); border: 1px solid #262626; border-radius: 8px; padding: 16px; font-family: monospace; font-size: 13px; overflow-x: auto; max-height: 300px; overflow-y: auto;">
|
|
195
|
-
<pre style="margin: 0; color: #a3a3a3;">${escapeHtml(configJson)}</pre>
|
|
196
|
-
</div>
|
|
197
|
-
</div>
|
|
198
|
-
`;
|
|
199
|
-
}
|
|
200
|
-
//# sourceMappingURL=widgets.js.map
|
package/build/ui/widgets.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"widgets.js","sourceRoot":"","sources":["../../src/ui/widgets.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAczD,MAAM,UAAU,mBAAmB,CAAC,OAAiB,EAAE,UAAmB;IACxE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,OAAO,UAAU,CACf,YAAY,EACZ;;;;;QAKE,gBAAgB,CAAC,qBAAqB,EAAE,2HAA2H,CAAC;KACvK,CACA,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,iBAAiB,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzF,MAAM,WAAW,GAAG,OAAO;SACxB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS;YAClC,CAAC,CAAC,oFAAoF;YACtF,CAAC,CAAC,qFAAqF,CAAC;QAE1F,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEzD,OAAO;;;;wCAI2B,QAAQ,IAAI,MAAM,CAAC,IAAI;+CAChB,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;;cAEtD,WAAW;;;;;;yCAMgB,SAAS;;;;yCAIT,MAAM,CAAC,iBAAiB,IAAI,CAAC;;;;4DAIV,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC;;;;yCAIlD,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,kBAAkB,EAAE;;;;;;;;;;OAUlF,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,OAAO,UAAU,CACf,YAAY,EACZ;;;WAGO,OAAO,CAAC,MAAM,iBAAiB,WAAW,WAAW,gBAAgB,CAAC,cAAc,EAAE;;;;QAIzF,WAAW;;;;;;;;;;;;GAYhB,CACA,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS;QAClC,CAAC,CAAC,+CAA+C;QACjD,CAAC,CAAC,gDAAgD,CAAC;IAErD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAE/C,OAAO,UAAU,CACf,GAAG,MAAM,CAAC,IAAI,EAAE,EAChB;;YAEQ,QAAQ,IAAI,MAAM,CAAC,IAAI;4CACS,MAAM,CAAC,EAAE,aAAa,WAAW;;;;;;;qCAOxC,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC;;;;;;qCAMtC,WAAW;;;;;;qCAMX,MAAM,CAAC,iBAAiB,IAAI,CAAC;;;;;;qCAM7B,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,kBAAkB,EAAE;;;;;;;;;sDAS/B,MAAM,CAAC,WAAW;;;;;;;kDAOtB,UAAU,CAAC,SAAS,CAAC;;;;;MAKjE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;;;;;QAKpD,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,sDAAsD,CAAC,CAAC,CAAC,kDAAkD;;;GAGnI,CACA,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,KAAK,GAA2B;QACpC,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,IAAI;KACb,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC;AAC3C,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,OAAO,GAA2B;QACtC,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,SAAS;QAClB,MAAM,EAAE,QAAQ;KACjB,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC;IAExD,OAAO,sBAAsB,WAAW,SAAS,CAAC;AACpD,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,GAAG,CAAC;IACjC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;AAClC,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,OAAO;6BACoB,QAAQ;;;qBAGhB,QAAQ;UACnB,CAAC;AACX,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACjI,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAW;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEnD,OAAO;;;;kDAIyC,UAAU,CAAC,UAAU,CAAC;;;GAGrE,CAAC;AACJ,CAAC"}
|
package/build/ui/workflows.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workflows Manager UI
|
|
3
|
-
*/
|
|
4
|
-
export interface Workflow {
|
|
5
|
-
id: string;
|
|
6
|
-
name: string;
|
|
7
|
-
active: boolean;
|
|
8
|
-
created_at: string;
|
|
9
|
-
updated_at: string;
|
|
10
|
-
executions_count?: number;
|
|
11
|
-
last_execution_status?: string;
|
|
12
|
-
last_execution_at?: string;
|
|
13
|
-
tags?: string[];
|
|
14
|
-
}
|
|
15
|
-
export declare function renderWorkflowsManager(workflows: Workflow[], instanceId?: string): string;
|
|
16
|
-
export declare function renderWorkflowDetails(workflow: Workflow, executions: any[]): string;
|
|
17
|
-
//# sourceMappingURL=workflows.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/ui/workflows.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAgGzF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,MAAM,CAuDnF"}
|
package/build/ui/workflows.js
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workflows Manager UI
|
|
3
|
-
*/
|
|
4
|
-
import { baseLayout, renderEmptyState } from './base.js';
|
|
5
|
-
export function renderWorkflowsManager(workflows, instanceId) {
|
|
6
|
-
if (!workflows || workflows.length === 0) {
|
|
7
|
-
return baseLayout('Workflows', `
|
|
8
|
-
<div class="header">
|
|
9
|
-
<h1>⚡ Workflows</h1>
|
|
10
|
-
<p>Manage your automation workflows</p>
|
|
11
|
-
</div>
|
|
12
|
-
${renderEmptyState('No Workflows Found', 'You don\'t have any workflows yet. Create your first workflow to automate your processes.')}
|
|
13
|
-
`);
|
|
14
|
-
}
|
|
15
|
-
const activeCount = workflows.filter((w) => w.active).length;
|
|
16
|
-
const totalExecutions = workflows.reduce((sum, w) => sum + (w.executions_count || 0), 0);
|
|
17
|
-
const workflowCards = workflows
|
|
18
|
-
.map((workflow) => {
|
|
19
|
-
const statusBadge = workflow.active
|
|
20
|
-
? '<span class="badge badge-success"><span class="dot dot-success"></span>Active</span>'
|
|
21
|
-
: '<span class="badge badge-neutral"><span class="dot dot-neutral"></span>Inactive</span>';
|
|
22
|
-
const executionBadge = getExecutionBadge(workflow.last_execution_status);
|
|
23
|
-
return `
|
|
24
|
-
<div class="card">
|
|
25
|
-
<div class="card-header">
|
|
26
|
-
<div>
|
|
27
|
-
<div class="card-title">${workflow.name}</div>
|
|
28
|
-
<div class="card-subtitle">ID: ${workflow.id.slice(0, 8)}...</div>
|
|
29
|
-
</div>
|
|
30
|
-
${statusBadge}
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<div>
|
|
34
|
-
<div class="stat">
|
|
35
|
-
<span class="stat-label">Total Executions</span>
|
|
36
|
-
<span class="stat-value">${workflow.executions_count || 0}</span>
|
|
37
|
-
</div>
|
|
38
|
-
${workflow.last_execution_at
|
|
39
|
-
? `
|
|
40
|
-
<div class="stat">
|
|
41
|
-
<span class="stat-label">Last Run</span>
|
|
42
|
-
<span class="stat-value">${executionBadge} ${formatRelativeTime(workflow.last_execution_at)}</span>
|
|
43
|
-
</div>`
|
|
44
|
-
: ''}
|
|
45
|
-
<div class="stat">
|
|
46
|
-
<span class="stat-label">Updated</span>
|
|
47
|
-
<span class="stat-value">${formatRelativeTime(workflow.updated_at)}</span>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
${workflow.tags && workflow.tags.length > 0
|
|
52
|
-
? `
|
|
53
|
-
<div style="margin-top: 12px; display: flex; gap: 6px; flex-wrap: wrap;">
|
|
54
|
-
${workflow.tags.map((tag) => `<span class="badge badge-neutral" style="font-size: 11px;">${tag}</span>`).join('')}
|
|
55
|
-
</div>`
|
|
56
|
-
: ''}
|
|
57
|
-
|
|
58
|
-
<div class="actions">
|
|
59
|
-
${workflow.active ? '<button class="btn btn-secondary">⏸ Pause</button>' : '<button class="btn btn-primary">▶️ Activate</button>'}
|
|
60
|
-
<button class="btn btn-secondary">View Executions</button>
|
|
61
|
-
<button class="btn btn-danger">Archive</button>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
`;
|
|
65
|
-
})
|
|
66
|
-
.join('');
|
|
67
|
-
return baseLayout('Workflows', `
|
|
68
|
-
<div class="header">
|
|
69
|
-
<h1>⚡ Workflows</h1>
|
|
70
|
-
<p>${workflows.length} workflows • ${activeCount} active • ${totalExecutions.toLocaleString()} total executions</p>
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
<div class="grid">
|
|
74
|
-
${workflowCards}
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<div class="card">
|
|
78
|
-
<h3 style="margin-bottom: 12px;">Quick Actions</h3>
|
|
79
|
-
<div style="display: flex; gap: 12px;">
|
|
80
|
-
<button class="btn btn-primary">+ New Workflow</button>
|
|
81
|
-
<button class="btn btn-secondary">Import Template</button>
|
|
82
|
-
<button class="btn btn-secondary">View All Executions</button>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
`);
|
|
86
|
-
}
|
|
87
|
-
export function renderWorkflowDetails(workflow, executions) {
|
|
88
|
-
const statusBadge = workflow.active
|
|
89
|
-
? '<span class="badge badge-success">Active</span>'
|
|
90
|
-
: '<span class="badge badge-neutral">Inactive</span>';
|
|
91
|
-
const recentExecutions = executions.slice(0, 10);
|
|
92
|
-
return baseLayout(`Workflow: ${workflow.name}`, `
|
|
93
|
-
<div class="header">
|
|
94
|
-
<h1>⚡ ${workflow.name}</h1>
|
|
95
|
-
<p>Workflow ID: <span class="code">${workflow.id}</span> • ${statusBadge}</p>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<div class="grid" style="grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-bottom: 24px;">
|
|
99
|
-
<div class="card">
|
|
100
|
-
<div class="stat">
|
|
101
|
-
<span class="stat-label">Status</span>
|
|
102
|
-
<span class="stat-value">${statusBadge}</span>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
<div class="card">
|
|
106
|
-
<div class="stat">
|
|
107
|
-
<span class="stat-label">Total Runs</span>
|
|
108
|
-
<span class="stat-value">${workflow.executions_count || 0}</span>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
<div class="card">
|
|
112
|
-
<div class="stat">
|
|
113
|
-
<span class="stat-label">Last Run</span>
|
|
114
|
-
<span class="stat-value">${workflow.last_execution_at ? formatRelativeTime(workflow.last_execution_at) : 'Never'}</span>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
<div class="card">
|
|
118
|
-
<div class="stat">
|
|
119
|
-
<span class="stat-label">Success Rate</span>
|
|
120
|
-
<span class="stat-value">${calculateSuccessRate(executions)}%</span>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
<div class="card" style="margin-bottom: 24px;">
|
|
126
|
-
<h3 style="margin-bottom: 16px;">Recent Executions</h3>
|
|
127
|
-
${renderExecutionsTable(recentExecutions)}
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
<div class="actions">
|
|
131
|
-
${workflow.active ? '<button class="btn btn-secondary">⏸ Pause Workflow</button>' : '<button class="btn btn-primary">▶️ Activate Workflow</button>'}
|
|
132
|
-
<button class="btn btn-secondary">Edit Workflow</button>
|
|
133
|
-
<button class="btn btn-secondary">View Parameters</button>
|
|
134
|
-
<button class="btn btn-danger">Archive</button>
|
|
135
|
-
</div>
|
|
136
|
-
`);
|
|
137
|
-
}
|
|
138
|
-
function renderExecutionsTable(executions) {
|
|
139
|
-
if (!executions || executions.length === 0) {
|
|
140
|
-
return renderEmptyState('No Executions', 'This workflow hasn\'t been executed yet.');
|
|
141
|
-
}
|
|
142
|
-
const rows = executions
|
|
143
|
-
.map((exec) => `
|
|
144
|
-
<tr>
|
|
145
|
-
<td>${getExecutionBadge(exec.status)}</td>
|
|
146
|
-
<td><span class="code">${exec.id.slice(0, 12)}...</span></td>
|
|
147
|
-
<td>${formatRelativeTime(exec.started_at)}</td>
|
|
148
|
-
<td>${exec.finished_at ? calculateDuration(exec.started_at, exec.finished_at) : 'Running...'}</td>
|
|
149
|
-
</tr>
|
|
150
|
-
`)
|
|
151
|
-
.join('');
|
|
152
|
-
return `
|
|
153
|
-
<table class="table">
|
|
154
|
-
<thead>
|
|
155
|
-
<tr>
|
|
156
|
-
<th>Status</th>
|
|
157
|
-
<th>Execution ID</th>
|
|
158
|
-
<th>Started</th>
|
|
159
|
-
<th>Duration</th>
|
|
160
|
-
</tr>
|
|
161
|
-
</thead>
|
|
162
|
-
<tbody>
|
|
163
|
-
${rows}
|
|
164
|
-
</tbody>
|
|
165
|
-
</table>
|
|
166
|
-
`;
|
|
167
|
-
}
|
|
168
|
-
function getExecutionBadge(status) {
|
|
169
|
-
if (!status)
|
|
170
|
-
return '<span class="badge badge-neutral">Unknown</span>';
|
|
171
|
-
const statusLower = status.toLowerCase();
|
|
172
|
-
if (statusLower === 'success' || statusLower === 'succeeded') {
|
|
173
|
-
return '<span class="badge badge-success">✓ Success</span>';
|
|
174
|
-
}
|
|
175
|
-
else if (statusLower === 'error' || statusLower === 'failed') {
|
|
176
|
-
return '<span class="badge badge-error">✗ Failed</span>';
|
|
177
|
-
}
|
|
178
|
-
else if (statusLower === 'running') {
|
|
179
|
-
return '<span class="badge badge-warning">⏳ Running</span>';
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
return `<span class="badge badge-neutral">${status}</span>`;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
function formatRelativeTime(timestamp) {
|
|
186
|
-
const date = new Date(timestamp);
|
|
187
|
-
const now = new Date();
|
|
188
|
-
const diffMs = now.getTime() - date.getTime();
|
|
189
|
-
const diffMins = Math.floor(diffMs / 60000);
|
|
190
|
-
const diffHours = Math.floor(diffMins / 60);
|
|
191
|
-
const diffDays = Math.floor(diffHours / 24);
|
|
192
|
-
if (diffMins < 1)
|
|
193
|
-
return 'Just now';
|
|
194
|
-
if (diffMins < 60)
|
|
195
|
-
return `${diffMins}m ago`;
|
|
196
|
-
if (diffHours < 24)
|
|
197
|
-
return `${diffHours}h ago`;
|
|
198
|
-
if (diffDays < 7)
|
|
199
|
-
return `${diffDays}d ago`;
|
|
200
|
-
return date.toLocaleDateString();
|
|
201
|
-
}
|
|
202
|
-
function calculateDuration(start, end) {
|
|
203
|
-
const diffMs = new Date(end).getTime() - new Date(start).getTime();
|
|
204
|
-
const diffSecs = Math.floor(diffMs / 1000);
|
|
205
|
-
if (diffSecs < 60)
|
|
206
|
-
return `${diffSecs}s`;
|
|
207
|
-
const mins = Math.floor(diffSecs / 60);
|
|
208
|
-
const secs = diffSecs % 60;
|
|
209
|
-
return `${mins}m ${secs}s`;
|
|
210
|
-
}
|
|
211
|
-
function calculateSuccessRate(executions) {
|
|
212
|
-
if (!executions || executions.length === 0)
|
|
213
|
-
return 0;
|
|
214
|
-
const successful = executions.filter((e) => e.status?.toLowerCase() === 'success' || e.status?.toLowerCase() === 'succeeded').length;
|
|
215
|
-
return Math.round((successful / executions.length) * 100);
|
|
216
|
-
}
|
|
217
|
-
//# sourceMappingURL=workflows.js.map
|