forked from retoor/devplacepy
Code Farm: per-plot auto-replant pause and crop-lock check; community sync and node work
Continuous Delivery could never be turned off once a crop was planted. Add a one-shot per-plot "stop after harvest" flag (POST /game/plot/stop, Devii tool game_plot_stop, game_plots.stop_after_harvest), cleared by the next plant, autoreplant claim or Refactor. Autoreplant now also respects crop locks through the shared _crop_lock predicate. Plan and measurements in happyplanting.md. Also includes the pending community sync, node network and related work in the tree; the full suite passed (4999) with all of it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -108,7 +108,8 @@ p {
|
||||
}
|
||||
|
||||
.dot.connecting,
|
||||
.dot.backoff {
|
||||
.dot.backoff,
|
||||
.dot.suspended {
|
||||
background: var(--warn);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ const STATE_LABELS = {
|
||||
online: "Online",
|
||||
backoff: "Reconnecting",
|
||||
halted: "Stopped",
|
||||
suspended: "Suspended",
|
||||
};
|
||||
|
||||
function formatBytes(value) {
|
||||
@@ -18,6 +19,30 @@ function formatBytes(value) {
|
||||
return `${unit === 0 ? size : size.toFixed(1)} ${UNITS[unit]}`;
|
||||
}
|
||||
|
||||
function pad(value) {
|
||||
return String(value).padStart(2, "0");
|
||||
}
|
||||
|
||||
function formatInstant(iso) {
|
||||
const moment = new Date(iso);
|
||||
if (Number.isNaN(moment.getTime())) {
|
||||
return "";
|
||||
}
|
||||
return `${pad(moment.getDate())}/${pad(moment.getMonth() + 1)}/${moment.getFullYear()} ${pad(moment.getHours())}:${pad(moment.getMinutes())}`;
|
||||
}
|
||||
|
||||
export function describeState(state) {
|
||||
if (state.state === "suspended") {
|
||||
const ends = formatInstant(state.suspendedUntil);
|
||||
return ends ? `Suspended until ${ends}, retrying automatically` : "Suspended, retrying automatically";
|
||||
}
|
||||
return state.detail || state.lastError || "";
|
||||
}
|
||||
|
||||
export function displayLabel(state, config) {
|
||||
return state.deviceLabel || config.label;
|
||||
}
|
||||
|
||||
class Popup {
|
||||
constructor(root) {
|
||||
this.root = root;
|
||||
@@ -55,8 +80,8 @@ class Popup {
|
||||
const { config, state, usage } = view;
|
||||
this.$("dot").className = `dot ${state.state}`;
|
||||
this.$("state").textContent = STATE_LABELS[state.state] || state.state;
|
||||
this.$("detail").textContent = state.detail || state.lastError || "";
|
||||
this.$("label").textContent = config.label;
|
||||
this.$("detail").textContent = describeState(state);
|
||||
this.$("label").textContent = displayLabel(state, config);
|
||||
this.$("disclosure-card").hidden = config.disclosed;
|
||||
const toggle = this.$("toggle");
|
||||
toggle.checked = config.enabled;
|
||||
@@ -152,4 +177,6 @@ class Popup {
|
||||
}
|
||||
}
|
||||
|
||||
new Popup(document).start();
|
||||
if (typeof document !== "undefined") {
|
||||
new Popup(document).start();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user