@lchase/kiln 0.10.0 → 0.12.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/assets/serve.js CHANGED
@@ -911,6 +911,54 @@
911
911
  .catch(function () { showSettingsError("Could not load settings."); });
912
912
  }
913
913
 
914
+ function toggleTrigger(button) {
915
+ var id = button.getAttribute("data-trigger-toggle");
916
+ var enabled = button.getAttribute("data-enabled") !== "true";
917
+ var error = document.getElementById("trigger-error");
918
+ if (error) error.hidden = true;
919
+ button.disabled = true;
920
+ fetch("/api/settings", { cache: "no-store", headers: { Accept: "application/json" } })
921
+ .then(function (response) { return response.json().then(function (data) { return { ok: response.ok, data: data }; }); })
922
+ .then(function (result) {
923
+ if (!result.ok) throw new Error((result.data && result.data.error) || "Could not load settings.");
924
+ var data = result.data;
925
+ var toggles = [];
926
+ var buttons = document.querySelectorAll("[data-trigger-toggle]");
927
+ for (var i = 0; i < buttons.length; i++) {
928
+ var buttonId = buttons[i].getAttribute("data-trigger-toggle");
929
+ var on = buttons[i].getAttribute("data-enabled") === "true";
930
+ if (buttonId === id) on = enabled;
931
+ toggles.push({ id: buttonId, enabled: on });
932
+ }
933
+ var body = { revision: data.revision, repos: data.repos || {}, triggers: toggles };
934
+ ["stallTimeoutMs", "maxAttempts", "maxFixRounds", "maxSameFingerprint", "dailyDollarCap"].forEach(function (key) {
935
+ if (data[key] !== undefined && data[key] !== null) body[key] = data[key];
936
+ });
937
+ if (data.sandbox) body.sandbox = data.sandbox;
938
+ return fetch("/api/settings", {
939
+ method: "PUT",
940
+ headers: {
941
+ Accept: "application/json",
942
+ "Content-Type": "application/json",
943
+ "X-Kiln-CSRF": document.body.getAttribute("data-csrf") || "",
944
+ },
945
+ body: JSON.stringify(body),
946
+ });
947
+ })
948
+ .then(function (response) { return response.json().then(function (data) { return { ok: response.ok, data: data }; }); })
949
+ .then(function (result) {
950
+ if (!result.ok) throw new Error((result.data && result.data.error) || "Could not save settings.");
951
+ location.reload();
952
+ })
953
+ .catch(function (err) {
954
+ button.disabled = false;
955
+ if (error) {
956
+ error.hidden = false;
957
+ error.textContent = err && err.message ? err.message : "Could not update the trigger.";
958
+ }
959
+ });
960
+ }
961
+
914
962
  function saveSettings() {
915
963
  if (settingsSaving) return;
916
964
  if (!flushEditor()) return;
@@ -1011,8 +1059,14 @@
1011
1059
  document.addEventListener("click", function (event) {
1012
1060
  var target = event.target;
1013
1061
  if (!target || !target.closest) return;
1014
- if (target.closest("#open-settings")) {
1015
- openSettings();
1062
+ var triggerToggle = target.closest("[data-trigger-toggle]");
1063
+ if (triggerToggle) {
1064
+ toggleTrigger(triggerToggle);
1065
+ return;
1066
+ }
1067
+ var settingsControl = target.closest("#open-settings");
1068
+ if (settingsControl) {
1069
+ if (settingsControl.tagName !== "A") openSettings();
1016
1070
  return;
1017
1071
  }
1018
1072
  if (target.closest("#add-job")) {
@@ -1169,7 +1223,7 @@
1169
1223
  return;
1170
1224
  }
1171
1225
  el.className = "status";
1172
- var jobs = document.querySelectorAll(".board .card").length;
1226
+ var jobs = document.querySelectorAll(".job").length;
1173
1227
  el.textContent = jobs + (jobs === 1 ? " job · " : " jobs · ") + new Date().toLocaleTimeString();
1174
1228
  localizeTimes(document);
1175
1229
  }
@@ -1194,11 +1248,20 @@
1194
1248
  toggle.textContent = data.paused ? "Resume" : "Pause";
1195
1249
  toggle.setAttribute("aria-pressed", data.paused ? "true" : "false");
1196
1250
  form.setAttribute("action", data.paused ? "/api/resume" : "/api/pause");
1251
+ var label = document.getElementById("run-label");
1252
+ var dot = document.getElementById("run-dot");
1253
+ if (label) label.textContent = data.paused ? "Paused" : "Running";
1254
+ if (dot) dot.classList.toggle("paused", data.paused);
1197
1255
  }
1198
1256
  var spend = document.getElementById("spend");
1199
1257
  if (spend && data && data.spend) {
1200
1258
  var capText = data.spend.cap == null ? "no cap" : "$" + Number(data.spend.cap).toFixed(2);
1201
1259
  spend.textContent = "today " + data.spend.day + " $" + Number(data.spend.usd).toFixed(2) + " / " + capText;
1260
+ var capNote = document.getElementById("cap-note");
1261
+ if (capNote) {
1262
+ var blocked = data.spend.blocked === true || (data.spend.cap != null && Number(data.spend.usd) >= Number(data.spend.cap));
1263
+ capNote.hidden = !blocked;
1264
+ }
1202
1265
  }
1203
1266
  stamp(true);
1204
1267
  })
@@ -1237,11 +1300,70 @@
1237
1300
  }
1238
1301
  var previewBtn = document.getElementById("preview-job");
1239
1302
  if (previewBtn) previewBtn.addEventListener("click", function () { submitIntake(true); });
1303
+ function readSeen() {
1304
+ try {
1305
+ var raw = localStorage.getItem("kiln-seen");
1306
+ var parsed = raw ? JSON.parse(raw) : {};
1307
+ return parsed && typeof parsed === "object" ? parsed : {};
1308
+ } catch (err) {
1309
+ return {};
1310
+ }
1311
+ }
1312
+
1313
+ function writeSeen(map) {
1314
+ try { localStorage.setItem("kiln-seen", JSON.stringify(map)); } catch (err) { /* private mode */ }
1315
+ }
1316
+
1317
+ function paintCount(node, count) {
1318
+ if (!node) return;
1319
+ if (!count) {
1320
+ node.hidden = true;
1321
+ node.textContent = "";
1322
+ return;
1323
+ }
1324
+ node.hidden = false;
1325
+ node.textContent = count === 1 ? "1 change since you last looked" : count + " changes since you last looked";
1326
+ }
1327
+
1328
+ function paintUnseen() {
1329
+ var seen = readSeen();
1330
+ var params = [];
1331
+ for (var id in seen) {
1332
+ if (!Object.prototype.hasOwnProperty.call(seen, id)) continue;
1333
+ if (typeof seen[id] !== "string" || !seen[id]) continue;
1334
+ params.push("seen=" + encodeURIComponent(id + "|" + seen[id]));
1335
+ }
1336
+ fetch("/api/unseen" + (params.length ? "?" + params.join("&") : ""), { cache: "no-store", headers: { Accept: "application/json" } })
1337
+ .then(function (response) { return response.ok ? response.json() : null; })
1338
+ .then(function (data) {
1339
+ if (!data) return;
1340
+ var counts = {};
1341
+ var jobs = data.jobs || [];
1342
+ for (var i = 0; i < jobs.length; i++) counts[jobs[i].jobId] = jobs[i].count;
1343
+ var nodes = document.querySelectorAll("[data-unseen-for]");
1344
+ for (var n = 0; n < nodes.length; n++) paintCount(nodes[n], counts[nodes[n].getAttribute("data-unseen-for")] || 0);
1345
+ paintCount(document.getElementById("inbox-unseen"), data.inbox || 0);
1346
+ })
1347
+ .catch(function () { /* the list still works without the badge */ });
1348
+ }
1349
+
1350
+ function markLooking() {
1351
+ var id = body.getAttribute("data-job");
1352
+ var latest = body.getAttribute("data-latest");
1353
+ if (!id || !latest) return;
1354
+ var seen = readSeen();
1355
+ seen[id] = latest;
1356
+ writeSeen(seen);
1357
+ }
1358
+
1240
1359
  showFresh();
1241
1360
  renderCompact();
1242
1361
  notifyLabel();
1243
1362
  applyRepo();
1244
1363
  stamp(true);
1364
+ paintUnseen();
1365
+ markLooking();
1366
+ if (document.getElementById("settings-form")) loadSettings();
1245
1367
  try {
1246
1368
  var open = localStorage.getItem("kiln-drawer");
1247
1369
  if (open) openJob(open);