synapse-sdk 1.0.0a98__py3-none-any.whl → 1.0.0b1__py3-none-any.whl
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.
Potentially problematic release.
This version of synapse-sdk might be problematic. Click here for more details.
- synapse_sdk/cli/__init__.py +139 -84
- synapse_sdk/cli/code_server.py +169 -0
- synapse_sdk/cli/config.py +105 -4
- synapse_sdk/cli/devtools.py +54 -34
- synapse_sdk/clients/base.py +3 -4
- synapse_sdk/devtools/server.py +24 -791
- synapse_sdk/devtools/streamlit_app/__init__.py +5 -0
- synapse_sdk/devtools/streamlit_app/app.py +128 -0
- synapse_sdk/devtools/streamlit_app/services/__init__.py +11 -0
- synapse_sdk/devtools/streamlit_app/services/job_service.py +233 -0
- synapse_sdk/devtools/streamlit_app/services/plugin_service.py +236 -0
- synapse_sdk/devtools/streamlit_app/services/serve_service.py +95 -0
- synapse_sdk/devtools/streamlit_app/ui/__init__.py +15 -0
- synapse_sdk/devtools/streamlit_app/ui/config_tab.py +76 -0
- synapse_sdk/devtools/streamlit_app/ui/deployment_tab.py +66 -0
- synapse_sdk/devtools/streamlit_app/ui/http_tab.py +125 -0
- synapse_sdk/devtools/streamlit_app/ui/jobs_tab.py +573 -0
- synapse_sdk/devtools/streamlit_app/ui/serve_tab.py +346 -0
- synapse_sdk/devtools/streamlit_app/ui/status_bar.py +118 -0
- synapse_sdk/devtools/streamlit_app/utils/__init__.py +40 -0
- synapse_sdk/devtools/streamlit_app/utils/json_viewer.py +197 -0
- synapse_sdk/devtools/streamlit_app/utils/log_formatter.py +38 -0
- synapse_sdk/devtools/streamlit_app/utils/styles.py +241 -0
- synapse_sdk/devtools/streamlit_app/utils/ui_components.py +289 -0
- synapse_sdk/devtools/streamlit_app.py +10 -0
- synapse_sdk/plugins/categories/upload/actions/upload.py +2 -1
- synapse_sdk/utils/converters/dm/__init__.py +0 -1
- {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/METADATA +4 -6
- {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/RECORD +33 -44
- synapse_sdk/devtools/models.py +0 -55
- synapse_sdk/devtools/utils.py +0 -52
- synapse_sdk/devtools/web/.gitignore +0 -2
- synapse_sdk/devtools/web/README.md +0 -34
- synapse_sdk/devtools/web/dist/index.html +0 -17
- synapse_sdk/devtools/web/index.html +0 -16
- synapse_sdk/devtools/web/jsconfig.json +0 -15
- synapse_sdk/devtools/web/package-lock.json +0 -2609
- synapse_sdk/devtools/web/package.json +0 -27
- synapse_sdk/devtools/web/pnpm-lock.yaml +0 -1055
- synapse_sdk/devtools/web/src/App.jsx +0 -14
- synapse_sdk/devtools/web/src/App.module.css +0 -33
- synapse_sdk/devtools/web/src/assets/favicon.ico +0 -0
- synapse_sdk/devtools/web/src/components/Breadcrumbs.jsx +0 -42
- synapse_sdk/devtools/web/src/components/Layout.jsx +0 -12
- synapse_sdk/devtools/web/src/components/LogViewer.jsx +0 -280
- synapse_sdk/devtools/web/src/components/MessageViewer.jsx +0 -150
- synapse_sdk/devtools/web/src/components/NavigationSidebar.jsx +0 -128
- synapse_sdk/devtools/web/src/components/ServerStatusBar.jsx +0 -245
- synapse_sdk/devtools/web/src/components/icons.jsx +0 -325
- synapse_sdk/devtools/web/src/index.css +0 -470
- synapse_sdk/devtools/web/src/index.jsx +0 -15
- synapse_sdk/devtools/web/src/logo.svg +0 -1
- synapse_sdk/devtools/web/src/router.jsx +0 -34
- synapse_sdk/devtools/web/src/utils/api.js +0 -442
- synapse_sdk/devtools/web/src/views/ApplicationDetailView.jsx +0 -241
- synapse_sdk/devtools/web/src/views/ApplicationsView.jsx +0 -224
- synapse_sdk/devtools/web/src/views/HomeView.jsx +0 -197
- synapse_sdk/devtools/web/src/views/JobDetailView.jsx +0 -310
- synapse_sdk/devtools/web/src/views/PluginView.jsx +0 -914
- synapse_sdk/devtools/web/vite.config.js +0 -13
- {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/WHEEL +0 -0
- {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/licenses/LICENSE +0 -0
- {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/top_level.txt +0 -0
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import { Show, For } from "solid-js";
|
|
2
|
-
import { useNavigate } from "@solidjs/router";
|
|
3
|
-
import { createApplicationsResource } from "../utils/api";
|
|
4
|
-
import { RefreshIcon, TrashIcon, CubeIcon } from "../components/icons";
|
|
5
|
-
|
|
6
|
-
export default function ApplicationsView() {
|
|
7
|
-
const navigate = useNavigate();
|
|
8
|
-
const { data: applications, loading, error, refresh } = createApplicationsResource();
|
|
9
|
-
|
|
10
|
-
const getStatusClass = (status) => {
|
|
11
|
-
switch (status?.toUpperCase()) {
|
|
12
|
-
case "RUNNING":
|
|
13
|
-
return "badge-outline badge-success";
|
|
14
|
-
case "DEPLOYING":
|
|
15
|
-
return "badge-outline badge-info";
|
|
16
|
-
case "DEPLOY_FAILED":
|
|
17
|
-
return "badge-outline badge-error";
|
|
18
|
-
case "DELETING":
|
|
19
|
-
return "badge-outline badge-warning";
|
|
20
|
-
default:
|
|
21
|
-
return "badge-outline badge-neutral";
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const navigateToDetail = (appId) => {
|
|
26
|
-
navigate(`/serve_application/${appId}`);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const deleteApplication = async (appId, appName) => {
|
|
30
|
-
if (!confirm(`Are you sure you want to delete application "${appName}"?`)) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch(`/api/serve_applications/${appId}`, {
|
|
36
|
-
method: 'DELETE'
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (response.ok) {
|
|
40
|
-
refresh(); // Refresh the list
|
|
41
|
-
} else {
|
|
42
|
-
alert('Failed to delete application');
|
|
43
|
-
}
|
|
44
|
-
} catch (error) {
|
|
45
|
-
alert('Failed to delete application: ' + error.message);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<div class="p-6">
|
|
51
|
-
{/* Header */}
|
|
52
|
-
<div class="mb-6">
|
|
53
|
-
<div class="flex justify-between items-center">
|
|
54
|
-
<div>
|
|
55
|
-
<h1 class="text-2xl font-semibold text-slate-900 mb-1">Serve Applications</h1>
|
|
56
|
-
<p class="text-sm text-slate-600">
|
|
57
|
-
Monitor and manage Ray Serve applications
|
|
58
|
-
</p>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<div class="flex items-center gap-3">
|
|
62
|
-
<div class="flex items-center gap-2 text-sm text-slate-500">
|
|
63
|
-
<RefreshIcon class="w-4 h-4 animate-spin" />
|
|
64
|
-
<span>Auto (3s)</span>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
{/* Main Card */}
|
|
71
|
-
<div class="card bg-white shadow-professional">
|
|
72
|
-
<div class="card-body p-6">
|
|
73
|
-
{/* Card Header */}
|
|
74
|
-
<div class="flex justify-between items-center mb-6">
|
|
75
|
-
<h2 class="text-lg font-semibold text-slate-900">
|
|
76
|
-
Applications ({applications()?.length || 0})
|
|
77
|
-
</h2>
|
|
78
|
-
<button
|
|
79
|
-
class="btn btn-sm btn-ghost"
|
|
80
|
-
onClick={refresh}
|
|
81
|
-
disabled={loading()}
|
|
82
|
-
>
|
|
83
|
-
<RefreshIcon class="w-4 h-4" />
|
|
84
|
-
Refresh
|
|
85
|
-
</button>
|
|
86
|
-
</div>
|
|
87
|
-
|
|
88
|
-
{/* Error Alert */}
|
|
89
|
-
<Show when={error()}>
|
|
90
|
-
<div class="alert alert-error mb-4">
|
|
91
|
-
<div>
|
|
92
|
-
<h3 class="font-medium">Error loading applications</h3>
|
|
93
|
-
<div class="text-sm">{error()}</div>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
</Show>
|
|
97
|
-
|
|
98
|
-
{/* Loading State */}
|
|
99
|
-
<Show when={loading() && (!applications() || applications().length === 0)}>
|
|
100
|
-
<div class="flex flex-col items-center justify-center py-12">
|
|
101
|
-
<div class="loading loading-spinner loading-md mb-4"></div>
|
|
102
|
-
<p class="text-slate-500">Loading applications...</p>
|
|
103
|
-
</div>
|
|
104
|
-
</Show>
|
|
105
|
-
|
|
106
|
-
{/* Empty State */}
|
|
107
|
-
<Show when={!loading() && (!applications() || applications().length === 0) && !error()}>
|
|
108
|
-
<div class="flex flex-col items-center justify-center py-12">
|
|
109
|
-
<div class="text-slate-400 mb-4">
|
|
110
|
-
<CubeIcon class="w-16 h-16" />
|
|
111
|
-
</div>
|
|
112
|
-
<h3 class="text-lg font-medium text-slate-900 mb-2">No applications found</h3>
|
|
113
|
-
<p class="text-slate-500">Serve applications will appear here once deployed</p>
|
|
114
|
-
</div>
|
|
115
|
-
</Show>
|
|
116
|
-
|
|
117
|
-
{/* Applications Table */}
|
|
118
|
-
<Show when={applications() && applications().length > 0}>
|
|
119
|
-
<div class="overflow-x-auto">
|
|
120
|
-
<table class="table table-sm w-full">
|
|
121
|
-
<thead>
|
|
122
|
-
<tr class="border-slate-200">
|
|
123
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Application</th>
|
|
124
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Status</th>
|
|
125
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Route Prefix</th>
|
|
126
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Deployments</th>
|
|
127
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Last Updated</th>
|
|
128
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Actions</th>
|
|
129
|
-
</tr>
|
|
130
|
-
</thead>
|
|
131
|
-
<tbody>
|
|
132
|
-
<For each={applications()}>
|
|
133
|
-
{(app) => (
|
|
134
|
-
<tr
|
|
135
|
-
class="hover:bg-slate-50 cursor-pointer border-slate-100"
|
|
136
|
-
onClick={() => navigateToDetail(app.name)}
|
|
137
|
-
>
|
|
138
|
-
<td class="py-3">
|
|
139
|
-
<div class="flex flex-col">
|
|
140
|
-
<span class="font-medium text-slate-900">{app.name}</span>
|
|
141
|
-
<span class="text-sm text-slate-500">
|
|
142
|
-
{app.docs_path ? `Docs: ${app.docs_path}` : 'No docs path'}
|
|
143
|
-
</span>
|
|
144
|
-
</div>
|
|
145
|
-
</td>
|
|
146
|
-
<td>
|
|
147
|
-
<span class={`badge badge-sm ${getStatusClass(app.status)}`}>
|
|
148
|
-
{app.status}
|
|
149
|
-
</span>
|
|
150
|
-
</td>
|
|
151
|
-
<td>
|
|
152
|
-
<code class="text-sm bg-slate-100 px-2 py-1 rounded">
|
|
153
|
-
{app.route_prefix || '/'}
|
|
154
|
-
</code>
|
|
155
|
-
</td>
|
|
156
|
-
<td>
|
|
157
|
-
<span class="text-sm text-slate-700">
|
|
158
|
-
{app.deployments?.length || 0} deployment{(app.deployments?.length || 0) !== 1 ? 's' : ''}
|
|
159
|
-
</span>
|
|
160
|
-
</td>
|
|
161
|
-
<td class="text-sm text-slate-600">
|
|
162
|
-
{app.last_deployed_time_s
|
|
163
|
-
? new Date(app.last_deployed_time_s * 1000).toLocaleString()
|
|
164
|
-
: 'N/A'
|
|
165
|
-
}
|
|
166
|
-
</td>
|
|
167
|
-
<td>
|
|
168
|
-
<div class="flex gap-2" onClick={(e) => e.stopPropagation()}>
|
|
169
|
-
<button
|
|
170
|
-
class="btn btn-sm btn-ghost"
|
|
171
|
-
onClick={() => navigateToDetail(app.name)}
|
|
172
|
-
title="View details"
|
|
173
|
-
>
|
|
174
|
-
View
|
|
175
|
-
</button>
|
|
176
|
-
<button
|
|
177
|
-
class="btn btn-sm btn-ghost text-red-600 hover:bg-red-50"
|
|
178
|
-
onClick={() => deleteApplication(app.name, app.name)}
|
|
179
|
-
title="Delete application"
|
|
180
|
-
>
|
|
181
|
-
<TrashIcon class="w-3 h-3" />
|
|
182
|
-
</button>
|
|
183
|
-
</div>
|
|
184
|
-
</td>
|
|
185
|
-
</tr>
|
|
186
|
-
)}
|
|
187
|
-
</For>
|
|
188
|
-
</tbody>
|
|
189
|
-
</table>
|
|
190
|
-
</div>
|
|
191
|
-
</Show>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
|
|
195
|
-
{/* Summary Stats */}
|
|
196
|
-
<Show when={applications() && applications().length > 0}>
|
|
197
|
-
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
|
|
198
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
199
|
-
<div class="stat-title text-sm text-slate-600">Total Applications</div>
|
|
200
|
-
<div class="stat-value text-lg text-slate-900">{applications().length}</div>
|
|
201
|
-
</div>
|
|
202
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
203
|
-
<div class="stat-title text-sm text-slate-600">Running</div>
|
|
204
|
-
<div class="stat-value text-lg text-emerald-600">
|
|
205
|
-
{applications().filter(app => app.status === "RUNNING").length}
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
209
|
-
<div class="stat-title text-sm text-slate-600">Deploying</div>
|
|
210
|
-
<div class="stat-value text-lg text-blue-600">
|
|
211
|
-
{applications().filter(app => app.status === "DEPLOYING").length}
|
|
212
|
-
</div>
|
|
213
|
-
</div>
|
|
214
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
215
|
-
<div class="stat-title text-sm text-slate-600">Failed</div>
|
|
216
|
-
<div class="stat-value text-lg text-red-600">
|
|
217
|
-
{applications().filter(app => app.status === "DEPLOY_FAILED").length}
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|
|
221
|
-
</Show>
|
|
222
|
-
</div>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { Show, For } from "solid-js";
|
|
2
|
-
import { useNavigate } from "@solidjs/router";
|
|
3
|
-
import { createJobsResource, getJobStatusVariant, formatTimestamp } from "../utils/api";
|
|
4
|
-
import { RefreshIcon } from "../components/icons";
|
|
5
|
-
|
|
6
|
-
export default function HomeView() {
|
|
7
|
-
const navigate = useNavigate();
|
|
8
|
-
const { data: jobs, loading, error, refresh } = createJobsResource();
|
|
9
|
-
|
|
10
|
-
const getStatusClass = (status) => {
|
|
11
|
-
switch (status?.toUpperCase()) {
|
|
12
|
-
case "SUCCEEDED":
|
|
13
|
-
return "badge-outline badge-success";
|
|
14
|
-
case "FAILED":
|
|
15
|
-
return "badge-outline badge-error";
|
|
16
|
-
case "RUNNING":
|
|
17
|
-
return "badge-outline badge-info";
|
|
18
|
-
case "PENDING":
|
|
19
|
-
case "SUBMITTED":
|
|
20
|
-
return "badge-outline badge-warning";
|
|
21
|
-
case "STOPPED":
|
|
22
|
-
case "CANCELLED":
|
|
23
|
-
return "badge-outline badge-neutral";
|
|
24
|
-
default:
|
|
25
|
-
return "badge-outline badge-neutral";
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const navigateToJobDetail = (submissionId) => {
|
|
30
|
-
navigate(`/job/${submissionId}`);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<div class="p-6">
|
|
35
|
-
{/* Header */}
|
|
36
|
-
<div class="mb-6">
|
|
37
|
-
<div class="flex justify-between items-center">
|
|
38
|
-
<div>
|
|
39
|
-
<h1 class="text-2xl font-semibold text-slate-900 mb-1">Jobs</h1>
|
|
40
|
-
<p class="text-sm text-slate-600">
|
|
41
|
-
Monitor and manage Ray job executions
|
|
42
|
-
</p>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div class="flex items-center gap-3">
|
|
46
|
-
<div class="flex items-center gap-2 text-sm text-slate-500">
|
|
47
|
-
<RefreshIcon class="w-4 h-4 animate-spin" />
|
|
48
|
-
<span>Auto (3s)</span>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
{/* Main Card */}
|
|
55
|
-
<div class="card bg-white shadow-professional">
|
|
56
|
-
<div class="card-body p-6">
|
|
57
|
-
{/* Card Header */}
|
|
58
|
-
<div class="flex justify-between items-center mb-6">
|
|
59
|
-
<h2 class="text-lg font-semibold text-slate-900">
|
|
60
|
-
All Jobs ({jobs()?.length || 0})
|
|
61
|
-
</h2>
|
|
62
|
-
<button
|
|
63
|
-
class="btn btn-sm btn-ghost"
|
|
64
|
-
onClick={refresh}
|
|
65
|
-
disabled={loading()}
|
|
66
|
-
>
|
|
67
|
-
<RefreshIcon class="w-4 h-4" />
|
|
68
|
-
Refresh
|
|
69
|
-
</button>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
{/* Error Alert */}
|
|
73
|
-
<Show when={error()}>
|
|
74
|
-
<div class="alert alert-error mb-4">
|
|
75
|
-
<div>
|
|
76
|
-
<h3 class="font-medium">Error loading jobs</h3>
|
|
77
|
-
<div class="text-sm">{error()}</div>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
</Show>
|
|
81
|
-
|
|
82
|
-
{/* Loading State */}
|
|
83
|
-
<Show when={loading() && (!jobs() || jobs().length === 0)}>
|
|
84
|
-
<div class="flex flex-col items-center justify-center py-12">
|
|
85
|
-
<div class="loading loading-spinner loading-md mb-4"></div>
|
|
86
|
-
<p class="text-slate-500">Loading jobs...</p>
|
|
87
|
-
</div>
|
|
88
|
-
</Show>
|
|
89
|
-
|
|
90
|
-
{/* Empty State */}
|
|
91
|
-
<Show when={!loading() && (!jobs() || jobs().length === 0) && !error()}>
|
|
92
|
-
<div class="flex flex-col items-center justify-center py-12">
|
|
93
|
-
<div class="text-slate-400 mb-4">
|
|
94
|
-
<svg class="w-16 h-16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
95
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
96
|
-
d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
|
97
|
-
</svg>
|
|
98
|
-
</div>
|
|
99
|
-
<h3 class="text-lg font-medium text-slate-900 mb-2">No jobs found</h3>
|
|
100
|
-
<p class="text-slate-500">Jobs will appear here once they are submitted</p>
|
|
101
|
-
</div>
|
|
102
|
-
</Show>
|
|
103
|
-
|
|
104
|
-
{/* Jobs Table */}
|
|
105
|
-
<Show when={jobs() && jobs().length > 0}>
|
|
106
|
-
<div class="overflow-x-auto">
|
|
107
|
-
<table class="table table-sm w-full">
|
|
108
|
-
<thead>
|
|
109
|
-
<tr class="border-slate-200">
|
|
110
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Job ID</th>
|
|
111
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Type</th>
|
|
112
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Status</th>
|
|
113
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Message</th>
|
|
114
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">Start Time</th>
|
|
115
|
-
<th class="bg-slate-50 text-slate-600 font-medium text-sm">End Time</th>
|
|
116
|
-
</tr>
|
|
117
|
-
</thead>
|
|
118
|
-
<tbody>
|
|
119
|
-
<For each={jobs()}>
|
|
120
|
-
{(job) => (
|
|
121
|
-
<tr
|
|
122
|
-
class="hover:bg-slate-50 cursor-pointer border-slate-100"
|
|
123
|
-
onClick={() => navigateToJobDetail(job.submission_id)}
|
|
124
|
-
>
|
|
125
|
-
<td class="py-3">
|
|
126
|
-
<div class="flex flex-col gap-1">
|
|
127
|
-
<span class="font-mono text-sm font-medium text-blue-600">
|
|
128
|
-
{job.submission_id}
|
|
129
|
-
</span>
|
|
130
|
-
<Show when={job.job_id}>
|
|
131
|
-
<span class="font-mono text-sm text-slate-500">
|
|
132
|
-
{job.job_id}
|
|
133
|
-
</span>
|
|
134
|
-
</Show>
|
|
135
|
-
</div>
|
|
136
|
-
</td>
|
|
137
|
-
<td>
|
|
138
|
-
<span class="badge badge-outline badge-neutral badge-sm font-mono">
|
|
139
|
-
{job.type}
|
|
140
|
-
</span>
|
|
141
|
-
</td>
|
|
142
|
-
<td>
|
|
143
|
-
<span class={`badge badge-sm ${getStatusClass(job.status)}`}>
|
|
144
|
-
{job.status}
|
|
145
|
-
</span>
|
|
146
|
-
</td>
|
|
147
|
-
<td class="max-w-sm">
|
|
148
|
-
<div class="truncate text-sm">
|
|
149
|
-
{job.status === "SUCCEEDED" ? "" : job.message || ""}
|
|
150
|
-
</div>
|
|
151
|
-
</td>
|
|
152
|
-
<td class="text-sm text-slate-600">
|
|
153
|
-
{formatTimestamp(job.start_time)}
|
|
154
|
-
</td>
|
|
155
|
-
<td class="text-sm text-slate-600">
|
|
156
|
-
{formatTimestamp(job.end_time)}
|
|
157
|
-
</td>
|
|
158
|
-
</tr>
|
|
159
|
-
)}
|
|
160
|
-
</For>
|
|
161
|
-
</tbody>
|
|
162
|
-
</table>
|
|
163
|
-
</div>
|
|
164
|
-
</Show>
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
|
|
168
|
-
{/* Summary Stats */}
|
|
169
|
-
<Show when={jobs() && jobs().length > 0}>
|
|
170
|
-
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
|
|
171
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
172
|
-
<div class="stat-title text-sm text-slate-600">Total Jobs</div>
|
|
173
|
-
<div class="stat-value text-lg text-slate-900">{jobs().length}</div>
|
|
174
|
-
</div>
|
|
175
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
176
|
-
<div class="stat-title text-sm text-slate-600">Succeeded</div>
|
|
177
|
-
<div class="stat-value text-lg text-emerald-600">
|
|
178
|
-
{jobs().filter(job => job.status === "SUCCEEDED").length}
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
182
|
-
<div class="stat-title text-sm text-slate-600">Failed</div>
|
|
183
|
-
<div class="stat-value text-lg text-red-600">
|
|
184
|
-
{jobs().filter(job => job.status === "FAILED").length}
|
|
185
|
-
</div>
|
|
186
|
-
</div>
|
|
187
|
-
<div class="stat bg-white border border-slate-200 rounded-lg">
|
|
188
|
-
<div class="stat-title text-sm text-slate-600">Running</div>
|
|
189
|
-
<div class="stat-value text-lg text-blue-600">
|
|
190
|
-
{jobs().filter(job => ["RUNNING", "PENDING"].includes(job.status)).length}
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
</Show>
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|