beercan 0.3.8 → 0.4.0
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/package.json +1 -1
- package/src/dashboard/index.html +41 -1
package/package.json
CHANGED
package/src/dashboard/index.html
CHANGED
|
@@ -762,6 +762,19 @@
|
|
|
762
762
|
</div>
|
|
763
763
|
</section>
|
|
764
764
|
|
|
765
|
+
<!-- ── Schedules ──────────────────────────────────────── -->
|
|
766
|
+
<section class="schedules-section">
|
|
767
|
+
<div class="container">
|
|
768
|
+
<div class="section-label">Schedules</div>
|
|
769
|
+
<h2 class="section-title">Recurring tasks</h2>
|
|
770
|
+
<p class="section-desc">Cron-based bloops that run automatically.</p>
|
|
771
|
+
|
|
772
|
+
<div id="schedules-container">
|
|
773
|
+
<div class="empty-state">No schedules. Add one with Skippy: "schedule daily at 9am: fetch news"</div>
|
|
774
|
+
</div>
|
|
775
|
+
</div>
|
|
776
|
+
</section>
|
|
777
|
+
|
|
765
778
|
<!-- ── Active Bloops ───────────────────────────────────── -->
|
|
766
779
|
<section class="active-bloops-section hidden" id="active-bloops-section">
|
|
767
780
|
<div class="container">
|
|
@@ -914,17 +927,19 @@
|
|
|
914
927
|
const apiUrl = getApiUrl();
|
|
915
928
|
|
|
916
929
|
try {
|
|
917
|
-
const [statusRes, projectsRes, jobsRes, recentRes] = await Promise.all([
|
|
930
|
+
const [statusRes, projectsRes, jobsRes, recentRes, schedulesRes] = await Promise.all([
|
|
918
931
|
fetch(apiUrl + '/api/status').then(r => r.json()),
|
|
919
932
|
fetch(apiUrl + '/api/projects').then(r => r.json()),
|
|
920
933
|
fetch(apiUrl + '/api/jobs').then(r => r.json()),
|
|
921
934
|
fetch(apiUrl + '/api/bloops/recent').then(r => r.json()),
|
|
935
|
+
fetch(apiUrl + '/api/schedules').then(r => r.json()),
|
|
922
936
|
]);
|
|
923
937
|
|
|
924
938
|
setConnected(true);
|
|
925
939
|
renderOverview(statusRes, jobsRes);
|
|
926
940
|
renderProjects(projectsRes);
|
|
927
941
|
renderJobs(jobsRes);
|
|
942
|
+
renderSchedules(schedulesRes);
|
|
928
943
|
renderActiveBloops(recentRes);
|
|
929
944
|
renderHistory(recentRes);
|
|
930
945
|
} catch (err) {
|
|
@@ -1029,6 +1044,31 @@
|
|
|
1029
1044
|
}
|
|
1030
1045
|
|
|
1031
1046
|
// ── Render: Active Bloops ─────────────────────────
|
|
1047
|
+
// ── Render: Schedules ─────────────────────────────
|
|
1048
|
+
function renderSchedules(data) {
|
|
1049
|
+
const container = document.getElementById('schedules-container');
|
|
1050
|
+
const schedules = data.schedules || [];
|
|
1051
|
+
|
|
1052
|
+
if (schedules.length === 0) {
|
|
1053
|
+
container.innerHTML = '<div class="empty-state">No schedules. Add one with Skippy: "schedule daily at 9am: fetch news"</div>';
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
let html = '<div class="history-list">';
|
|
1058
|
+
for (const s of schedules) {
|
|
1059
|
+
const statusDot = s.enabled ? '<span class="dot green"></span>' : '<span class="dot red"></span>';
|
|
1060
|
+
const lastRun = s.lastRunAt ? formatTimestamp(s.lastRunAt) : 'never';
|
|
1061
|
+
html += '<div class="history-item">';
|
|
1062
|
+
html += statusDot;
|
|
1063
|
+
html += '<span class="history-goal"><code>' + escapeHtml(s.cronExpression) + '</code> — ' + escapeHtml(s.goal) + '</span>';
|
|
1064
|
+
html += '<span class="history-project">' + escapeHtml(s.projectSlug) + '</span>';
|
|
1065
|
+
html += '<span class="history-duration">Last: ' + lastRun + '</span>';
|
|
1066
|
+
html += '</div>';
|
|
1067
|
+
}
|
|
1068
|
+
html += '</div>';
|
|
1069
|
+
container.innerHTML = html;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1032
1072
|
function renderActiveBloops(data) {
|
|
1033
1073
|
const bloops = (data.bloops || []).filter(b => b.status === 'running');
|
|
1034
1074
|
const section = document.getElementById('active-bloops-section');
|