clay-server 2.27.0-beta.8 → 2.27.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/README.md +10 -0
- package/lib/daemon-projects.js +164 -0
- package/lib/daemon.js +13 -126
- package/lib/mates-identity.js +132 -0
- package/lib/mates-knowledge.js +113 -0
- package/lib/mates-prompts.js +398 -0
- package/lib/mates.js +40 -599
- package/lib/project-connection.js +2 -0
- package/lib/project-debate.js +19 -12
- package/lib/project-http.js +4 -2
- package/lib/project-loop.js +110 -48
- package/lib/project-mate-interaction.js +4 -0
- package/lib/project-notifications.js +210 -0
- package/lib/project-sessions.js +5 -2
- package/lib/project-user-message.js +2 -1
- package/lib/project.js +26 -2
- package/lib/public/app.js +1193 -8521
- package/lib/public/css/command-palette.css +14 -0
- package/lib/public/css/loop.css +301 -0
- package/lib/public/css/notifications-center.css +190 -0
- package/lib/public/css/rewind.css +6 -0
- package/lib/public/index.html +89 -35
- package/lib/public/modules/app-connection.js +160 -0
- package/lib/public/modules/app-cursors.js +473 -0
- package/lib/public/modules/app-debate-ui.js +389 -0
- package/lib/public/modules/app-dm.js +627 -0
- package/lib/public/modules/app-favicon.js +212 -0
- package/lib/public/modules/app-header.js +229 -0
- package/lib/public/modules/app-home-hub.js +600 -0
- package/lib/public/modules/app-loop-ui.js +589 -0
- package/lib/public/modules/app-loop-wizard.js +439 -0
- package/lib/public/modules/app-messages.js +1560 -0
- package/lib/public/modules/app-misc.js +299 -0
- package/lib/public/modules/app-notifications.js +372 -0
- package/lib/public/modules/app-panels.js +888 -0
- package/lib/public/modules/app-projects.js +798 -0
- package/lib/public/modules/app-rate-limit.js +451 -0
- package/lib/public/modules/app-rendering.js +597 -0
- package/lib/public/modules/app-skills-install.js +234 -0
- package/lib/public/modules/command-palette.js +27 -4
- package/lib/public/modules/input.js +31 -20
- package/lib/public/modules/scheduler-config.js +1532 -0
- package/lib/public/modules/scheduler-history.js +79 -0
- package/lib/public/modules/scheduler.js +33 -1554
- package/lib/public/modules/session-search.js +13 -1
- package/lib/public/modules/sidebar-mates.js +812 -0
- package/lib/public/modules/sidebar-mobile.js +1269 -0
- package/lib/public/modules/sidebar-projects.js +1449 -0
- package/lib/public/modules/sidebar-sessions.js +986 -0
- package/lib/public/modules/sidebar.js +232 -4591
- package/lib/public/modules/store.js +27 -0
- package/lib/public/modules/ws-ref.js +7 -0
- package/lib/public/style.css +1 -0
- package/lib/sdk-bridge.js +96 -717
- package/lib/sdk-message-processor.js +587 -0
- package/lib/sdk-message-queue.js +42 -0
- package/lib/sdk-skill-discovery.js +131 -0
- package/lib/server-admin.js +712 -0
- package/lib/server-auth.js +737 -0
- package/lib/server-dm.js +221 -0
- package/lib/server-mates.js +281 -0
- package/lib/server-palette.js +110 -0
- package/lib/server-settings.js +479 -0
- package/lib/server-skills.js +280 -0
- package/lib/server.js +246 -2755
- package/lib/sessions.js +11 -4
- package/lib/users-auth.js +146 -0
- package/lib/users-permissions.js +118 -0
- package/lib/users-preferences.js +210 -0
- package/lib/users.js +48 -398
- package/lib/ws-schema.js +498 -0
- package/package.json +1 -1
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
// app-loop-wizard.js - Ralph Loop wizard: step navigation, data collection, repeat picker
|
|
2
|
+
// Extracted from app-loop-ui.js
|
|
3
|
+
|
|
4
|
+
import { refreshIcons } from './icons.js';
|
|
5
|
+
import { store } from './store.js';
|
|
6
|
+
import { getWs } from './ws-ref.js';
|
|
7
|
+
import { requireSkills } from './app-skills-install.js';
|
|
8
|
+
|
|
9
|
+
// --- Module-owned state (not in store) ---
|
|
10
|
+
var wizardStep = 1;
|
|
11
|
+
var wizardSource = "ralph"; // "ralph" or "task"
|
|
12
|
+
var wizardMode = "draft"; // "draft" or "own"
|
|
13
|
+
var loopModeChoice = "judge"; // "simple" | "judge"
|
|
14
|
+
var promptAuthor = "clay"; // "clay" | "me"
|
|
15
|
+
var judgeAuthor = "clay"; // "clay" | "me"
|
|
16
|
+
|
|
17
|
+
// --- Module-local state accessors ---
|
|
18
|
+
export function getWizardSource() { return wizardSource; }
|
|
19
|
+
|
|
20
|
+
// --- DOM refs for repeat picker (captured in init) ---
|
|
21
|
+
var repeatSelect = null;
|
|
22
|
+
var repeatTimeRow = null;
|
|
23
|
+
var repeatCustom = null;
|
|
24
|
+
var repeatUnitSelect = null;
|
|
25
|
+
var repeatDowRow = null;
|
|
26
|
+
var cronPreview = null;
|
|
27
|
+
|
|
28
|
+
// ========================================================
|
|
29
|
+
// Init
|
|
30
|
+
// ========================================================
|
|
31
|
+
export function initLoopWizard() {
|
|
32
|
+
// Repeat picker DOM refs
|
|
33
|
+
repeatSelect = document.getElementById("ralph-repeat");
|
|
34
|
+
repeatTimeRow = document.getElementById("ralph-time-row");
|
|
35
|
+
repeatCustom = document.getElementById("ralph-custom-repeat");
|
|
36
|
+
repeatUnitSelect = document.getElementById("ralph-repeat-unit");
|
|
37
|
+
repeatDowRow = document.getElementById("ralph-custom-dow-row");
|
|
38
|
+
cronPreview = document.getElementById("ralph-cron-preview");
|
|
39
|
+
|
|
40
|
+
// --- Wizard button listeners ---
|
|
41
|
+
var wizardCloseBtn = document.getElementById("ralph-wizard-close");
|
|
42
|
+
var wizardBackdrop = document.querySelector(".ralph-wizard-backdrop");
|
|
43
|
+
var wizardBackBtn = document.getElementById("ralph-wizard-back");
|
|
44
|
+
var wizardSkipBtn = document.getElementById("ralph-wizard-skip");
|
|
45
|
+
var wizardNextBtn = document.getElementById("ralph-wizard-next");
|
|
46
|
+
|
|
47
|
+
if (wizardCloseBtn) wizardCloseBtn.addEventListener("click", closeRalphWizard);
|
|
48
|
+
if (wizardBackdrop) wizardBackdrop.addEventListener("click", closeRalphWizard);
|
|
49
|
+
if (wizardBackBtn) wizardBackBtn.addEventListener("click", wizardBack);
|
|
50
|
+
if (wizardSkipBtn) wizardSkipBtn.addEventListener("click", wizardSkip);
|
|
51
|
+
if (wizardNextBtn) wizardNextBtn.addEventListener("click", wizardNext);
|
|
52
|
+
|
|
53
|
+
// --- Mode cards (step 1: loop mode) ---
|
|
54
|
+
var modeCards = document.querySelectorAll(".ralph-mode-card");
|
|
55
|
+
for (var mc = 0; mc < modeCards.length; mc++) {
|
|
56
|
+
modeCards[mc].addEventListener("click", function () {
|
|
57
|
+
loopModeChoice = this.getAttribute("data-loop-mode");
|
|
58
|
+
var all = document.querySelectorAll(".ralph-mode-card");
|
|
59
|
+
for (var i = 0; i < all.length; i++) all[i].classList.remove("active");
|
|
60
|
+
this.classList.add("active");
|
|
61
|
+
updateModePreview();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// --- Authorship toggles (step 3) ---
|
|
66
|
+
var authorBtns = document.querySelectorAll(".ralph-authorship-toggle .config-segment-btn");
|
|
67
|
+
for (var ab = 0; ab < authorBtns.length; ab++) {
|
|
68
|
+
authorBtns[ab].addEventListener("click", function () {
|
|
69
|
+
var toggle = this.parentElement;
|
|
70
|
+
var file = toggle.getAttribute("data-file");
|
|
71
|
+
var author = this.getAttribute("data-author");
|
|
72
|
+
var siblings = toggle.querySelectorAll(".config-segment-btn");
|
|
73
|
+
for (var s = 0; s < siblings.length; s++) siblings[s].classList.remove("active");
|
|
74
|
+
this.classList.add("active");
|
|
75
|
+
if (file === "prompt") promptAuthor = author;
|
|
76
|
+
if (file === "judge") judgeAuthor = author;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// --- Repeat picker handlers ---
|
|
81
|
+
if (repeatSelect) {
|
|
82
|
+
repeatSelect.addEventListener("change", updateRepeatUI);
|
|
83
|
+
}
|
|
84
|
+
if (repeatUnitSelect) {
|
|
85
|
+
repeatUnitSelect.addEventListener("change", function () {
|
|
86
|
+
if (repeatDowRow) repeatDowRow.style.display = this.value === "week" ? "" : "none";
|
|
87
|
+
updateRepeatUI();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var timeInput = document.getElementById("ralph-time");
|
|
92
|
+
if (timeInput) timeInput.addEventListener("change", updateRepeatUI);
|
|
93
|
+
|
|
94
|
+
// DOW buttons in custom repeat
|
|
95
|
+
var customDowBtns = document.querySelectorAll("#ralph-custom-repeat .sched-dow-btn");
|
|
96
|
+
for (var di = 0; di < customDowBtns.length; di++) {
|
|
97
|
+
customDowBtns[di].addEventListener("click", function () {
|
|
98
|
+
this.classList.toggle("active");
|
|
99
|
+
updateRepeatUI();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ========================================================
|
|
105
|
+
// Mode preview toggle
|
|
106
|
+
// ========================================================
|
|
107
|
+
|
|
108
|
+
function updateModePreview() {
|
|
109
|
+
var judgePreview = document.querySelector(".ralph-mode-preview-judge");
|
|
110
|
+
var simplePreview = document.querySelector(".ralph-mode-preview-simple");
|
|
111
|
+
if (judgePreview) judgePreview.style.display = loopModeChoice === "judge" ? "" : "none";
|
|
112
|
+
if (simplePreview) simplePreview.style.display = loopModeChoice === "simple" ? "" : "none";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ========================================================
|
|
116
|
+
// requireClayRalph
|
|
117
|
+
// ========================================================
|
|
118
|
+
|
|
119
|
+
function requireClayRalph(cb) {
|
|
120
|
+
requireSkills({
|
|
121
|
+
title: "Skill Installation Required",
|
|
122
|
+
reason: "This feature requires the following skill to be installed.",
|
|
123
|
+
skills: [{ name: "clay-ralph", url: "https://github.com/chadbyte/clay-ralph", scope: "global" }]
|
|
124
|
+
}, cb);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ========================================================
|
|
128
|
+
// Ralph Wizard (exported: openRalphWizard, closeRalphWizard)
|
|
129
|
+
// ========================================================
|
|
130
|
+
|
|
131
|
+
export function openRalphWizard(source) {
|
|
132
|
+
requireClayRalph(function () {
|
|
133
|
+
wizardSource = source || "ralph";
|
|
134
|
+
store.setState({ wizardData: { name: "", task: "", maxIterations: null } });
|
|
135
|
+
loopModeChoice = "judge";
|
|
136
|
+
promptAuthor = "clay";
|
|
137
|
+
judgeAuthor = "clay";
|
|
138
|
+
|
|
139
|
+
var el = document.getElementById("ralph-wizard");
|
|
140
|
+
if (!el) return;
|
|
141
|
+
|
|
142
|
+
// Reset inputs
|
|
143
|
+
var taskEl = document.getElementById("ralph-task");
|
|
144
|
+
if (taskEl) taskEl.value = "";
|
|
145
|
+
var promptInput = document.getElementById("ralph-prompt-input");
|
|
146
|
+
if (promptInput) promptInput.value = "";
|
|
147
|
+
var judgeInput = document.getElementById("ralph-judge-input");
|
|
148
|
+
if (judgeInput) judgeInput.value = "";
|
|
149
|
+
|
|
150
|
+
// Reset mode cards
|
|
151
|
+
var modeCards = document.querySelectorAll(".ralph-mode-card");
|
|
152
|
+
for (var mc = 0; mc < modeCards.length; mc++) {
|
|
153
|
+
if (modeCards[mc].getAttribute("data-loop-mode") === "judge") {
|
|
154
|
+
modeCards[mc].classList.add("active");
|
|
155
|
+
} else {
|
|
156
|
+
modeCards[mc].classList.remove("active");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Reset authorship toggles
|
|
161
|
+
var authorToggles = document.querySelectorAll(".ralph-authorship-toggle");
|
|
162
|
+
for (var at = 0; at < authorToggles.length; at++) {
|
|
163
|
+
var btns = authorToggles[at].querySelectorAll(".config-segment-btn");
|
|
164
|
+
for (var b = 0; b < btns.length; b++) {
|
|
165
|
+
if (btns[b].getAttribute("data-author") === "clay") {
|
|
166
|
+
btns[b].classList.add("active");
|
|
167
|
+
} else {
|
|
168
|
+
btns[b].classList.remove("active");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Update text based on source
|
|
174
|
+
var isTask = wizardSource === "task";
|
|
175
|
+
var headerSpan = el.querySelector(".ralph-wizard-header > span");
|
|
176
|
+
if (headerSpan) headerSpan.textContent = isTask ? "New Task" : "New Loop";
|
|
177
|
+
|
|
178
|
+
if (wizardSource === "task") {
|
|
179
|
+
// Tasks skip step 1 (loop mode), go to step 2
|
|
180
|
+
wizardStep = 2;
|
|
181
|
+
} else {
|
|
182
|
+
wizardStep = 1;
|
|
183
|
+
}
|
|
184
|
+
el.classList.remove("hidden");
|
|
185
|
+
var statusEl = document.getElementById("ralph-install-status");
|
|
186
|
+
if (statusEl) { statusEl.classList.add("hidden"); statusEl.innerHTML = ""; }
|
|
187
|
+
|
|
188
|
+
// Reset exec modal flag
|
|
189
|
+
store.setState({ execModalShown: false });
|
|
190
|
+
|
|
191
|
+
updateModePreview();
|
|
192
|
+
updateWizardStep();
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function closeRalphWizard() {
|
|
197
|
+
var el = document.getElementById("ralph-wizard");
|
|
198
|
+
if (el) el.classList.add("hidden");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// --- Internal wizard helpers ---
|
|
202
|
+
|
|
203
|
+
function updateWizardStep() {
|
|
204
|
+
var steps = document.querySelectorAll(".ralph-step");
|
|
205
|
+
for (var i = 0; i < steps.length; i++) {
|
|
206
|
+
var stepNum = parseInt(steps[i].getAttribute("data-step"), 10);
|
|
207
|
+
if (stepNum === wizardStep) {
|
|
208
|
+
steps[i].classList.add("active");
|
|
209
|
+
} else {
|
|
210
|
+
steps[i].classList.remove("active");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
var dots = document.querySelectorAll(".ralph-dot");
|
|
214
|
+
for (var j = 0; j < dots.length; j++) {
|
|
215
|
+
var dotStep = parseInt(dots[j].getAttribute("data-step"), 10);
|
|
216
|
+
dots[j].classList.remove("active", "done");
|
|
217
|
+
if (dotStep === wizardStep) dots[j].classList.add("active");
|
|
218
|
+
else if (dotStep < wizardStep) dots[j].classList.add("done");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Show/hide JUDGE authorship row based on loop mode
|
|
222
|
+
var judgeRow = document.getElementById("ralph-judge-authorship-row");
|
|
223
|
+
if (judgeRow) judgeRow.style.display = loopModeChoice === "simple" ? "none" : "";
|
|
224
|
+
|
|
225
|
+
// Update step 3 input visibility
|
|
226
|
+
if (wizardStep === 3) updateInputVisibility();
|
|
227
|
+
|
|
228
|
+
var backBtn = document.getElementById("ralph-wizard-back");
|
|
229
|
+
var skipBtn = document.getElementById("ralph-wizard-skip");
|
|
230
|
+
var nextBtn = document.getElementById("ralph-wizard-next");
|
|
231
|
+
if (backBtn) {
|
|
232
|
+
var firstStep = (wizardSource === "task") ? 2 : 1;
|
|
233
|
+
backBtn.style.visibility = (wizardStep === firstStep) ? "hidden" : "visible";
|
|
234
|
+
backBtn.textContent = (wizardSource === "task" && wizardStep <= 2) ? "Cancel" : "Back";
|
|
235
|
+
}
|
|
236
|
+
if (skipBtn) skipBtn.style.display = "none";
|
|
237
|
+
if (nextBtn) {
|
|
238
|
+
if (wizardStep === 3) nextBtn.textContent = "Launch";
|
|
239
|
+
else nextBtn.textContent = "Next";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function updateInputVisibility() {
|
|
244
|
+
var taskSection = document.getElementById("ralph-input-task-section");
|
|
245
|
+
var promptSection = document.getElementById("ralph-input-prompt-section");
|
|
246
|
+
var judgeSection = document.getElementById("ralph-input-judge-section");
|
|
247
|
+
|
|
248
|
+
var needsTask = (promptAuthor === "clay");
|
|
249
|
+
var needsPrompt = (promptAuthor === "me");
|
|
250
|
+
var needsJudge = (loopModeChoice === "judge" && judgeAuthor === "me");
|
|
251
|
+
|
|
252
|
+
if (taskSection) {
|
|
253
|
+
if (needsTask) taskSection.classList.remove("hidden");
|
|
254
|
+
else taskSection.classList.add("hidden");
|
|
255
|
+
}
|
|
256
|
+
if (promptSection) {
|
|
257
|
+
if (needsPrompt) promptSection.classList.remove("hidden");
|
|
258
|
+
else promptSection.classList.add("hidden");
|
|
259
|
+
}
|
|
260
|
+
if (judgeSection) {
|
|
261
|
+
if (needsJudge) judgeSection.classList.remove("hidden");
|
|
262
|
+
else judgeSection.classList.add("hidden");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
var heading = document.querySelector('.ralph-step[data-step="3"] h3');
|
|
266
|
+
if (heading) {
|
|
267
|
+
if (needsTask && !needsJudge) heading.textContent = "Describe your task";
|
|
268
|
+
else if (needsPrompt && !needsJudge) heading.textContent = "Provide your prompt";
|
|
269
|
+
else if (needsPrompt && needsJudge) heading.textContent = "Provide your files";
|
|
270
|
+
else if (needsTask && needsJudge) heading.textContent = "Provide details";
|
|
271
|
+
else heading.textContent = "Provide details";
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function collectWizardData() {
|
|
276
|
+
var wd = {
|
|
277
|
+
name: "",
|
|
278
|
+
maxIterations: null,
|
|
279
|
+
cron: buildWizardCron(),
|
|
280
|
+
loopMode: loopModeChoice,
|
|
281
|
+
promptAuthor: promptAuthor,
|
|
282
|
+
judgeAuthor: (loopModeChoice === "judge") ? judgeAuthor : null,
|
|
283
|
+
mode: (promptAuthor === "me") ? "own" : "draft"
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
if (promptAuthor === "clay") {
|
|
287
|
+
var taskEl = document.getElementById("ralph-task");
|
|
288
|
+
wd.task = taskEl ? taskEl.value.trim() : "";
|
|
289
|
+
wd.promptText = null;
|
|
290
|
+
} else {
|
|
291
|
+
var promptInput = document.getElementById("ralph-prompt-input");
|
|
292
|
+
wd.task = "";
|
|
293
|
+
wd.promptText = promptInput ? promptInput.value.trim() : "";
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (loopModeChoice === "judge" && judgeAuthor === "me") {
|
|
297
|
+
var judgeInput = document.getElementById("ralph-judge-input");
|
|
298
|
+
wd.judgeText = judgeInput ? judgeInput.value.trim() : "";
|
|
299
|
+
} else {
|
|
300
|
+
wd.judgeText = null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
store.setState({ wizardData: wd });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function buildWizardCron() {
|
|
307
|
+
if (!repeatSelect) return null;
|
|
308
|
+
var preset = repeatSelect.value;
|
|
309
|
+
if (preset === "none") return null;
|
|
310
|
+
|
|
311
|
+
var timeEl = document.getElementById("ralph-time");
|
|
312
|
+
var timeVal = timeEl ? timeEl.value : "09:00";
|
|
313
|
+
var timeParts = timeVal.split(":");
|
|
314
|
+
var hour = parseInt(timeParts[0], 10) || 9;
|
|
315
|
+
var minute = parseInt(timeParts[1], 10) || 0;
|
|
316
|
+
|
|
317
|
+
if (preset === "daily") return minute + " " + hour + " * * *";
|
|
318
|
+
if (preset === "weekdays") return minute + " " + hour + " * * 1-5";
|
|
319
|
+
if (preset === "weekly") return minute + " " + hour + " * * " + new Date().getDay();
|
|
320
|
+
if (preset === "monthly") return minute + " " + hour + " " + new Date().getDate() + " * *";
|
|
321
|
+
|
|
322
|
+
if (preset === "custom") {
|
|
323
|
+
var unitEl = document.getElementById("ralph-repeat-unit");
|
|
324
|
+
var unit = unitEl ? unitEl.value : "day";
|
|
325
|
+
if (unit === "day") return minute + " " + hour + " * * *";
|
|
326
|
+
if (unit === "month") return minute + " " + hour + " " + new Date().getDate() + " * *";
|
|
327
|
+
// week: collect selected days
|
|
328
|
+
var dowBtns = document.querySelectorAll("#ralph-custom-repeat .sched-dow-btn.active");
|
|
329
|
+
var days = [];
|
|
330
|
+
for (var i = 0; i < dowBtns.length; i++) {
|
|
331
|
+
days.push(dowBtns[i].dataset.dow);
|
|
332
|
+
}
|
|
333
|
+
if (days.length === 0) days.push(String(new Date().getDay()));
|
|
334
|
+
return minute + " " + hour + " * * " + days.join(",");
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function cronToHumanText(cron) {
|
|
340
|
+
if (!cron) return "";
|
|
341
|
+
var parts = cron.trim().split(/\s+/);
|
|
342
|
+
if (parts.length !== 5) return cron;
|
|
343
|
+
var m = parts[0], h = parts[1], dom = parts[2], dow = parts[4];
|
|
344
|
+
var pad = function(n) { return (parseInt(n,10) < 10 ? "0" : "") + parseInt(n,10); };
|
|
345
|
+
var t = pad(h) + ":" + pad(m);
|
|
346
|
+
var dayNames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
|
|
347
|
+
if (dow === "*" && dom === "*") return "Every day at " + t;
|
|
348
|
+
if (dow === "1-5" && dom === "*") return "Weekdays at " + t;
|
|
349
|
+
if (dom !== "*" && dow === "*") return "Monthly on day " + dom + " at " + t;
|
|
350
|
+
if (dow !== "*" && dom === "*") {
|
|
351
|
+
var ds = dow.split(",").map(function(d) { return dayNames[parseInt(d,10)] || d; });
|
|
352
|
+
return "Every " + ds.join(", ") + " at " + t;
|
|
353
|
+
}
|
|
354
|
+
return cron;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
var LAST_STEP = 3;
|
|
358
|
+
|
|
359
|
+
function validateLastStep() {
|
|
360
|
+
var wd = store.getState().wizardData;
|
|
361
|
+
if (promptAuthor === "clay") {
|
|
362
|
+
var taskEl = document.getElementById("ralph-task");
|
|
363
|
+
if (!wd.task) {
|
|
364
|
+
if (taskEl) { taskEl.focus(); taskEl.style.borderColor = "#e74c3c"; setTimeout(function() { taskEl.style.borderColor = ""; }, 2000); }
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
var promptInput = document.getElementById("ralph-prompt-input");
|
|
369
|
+
if (!wd.promptText) {
|
|
370
|
+
if (promptInput) { promptInput.focus(); promptInput.style.borderColor = "#e74c3c"; setTimeout(function() { promptInput.style.borderColor = ""; }, 2000); }
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (loopModeChoice === "judge" && judgeAuthor === "me") {
|
|
375
|
+
var judgeInput = document.getElementById("ralph-judge-input");
|
|
376
|
+
if (!wd.judgeText) {
|
|
377
|
+
if (judgeInput) { judgeInput.focus(); judgeInput.style.borderColor = "#e74c3c"; setTimeout(function() { judgeInput.style.borderColor = ""; }, 2000); }
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function wizardNext() {
|
|
385
|
+
collectWizardData();
|
|
386
|
+
if (wizardStep < LAST_STEP) {
|
|
387
|
+
wizardStep++;
|
|
388
|
+
updateWizardStep();
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (validateLastStep()) wizardSubmit();
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function wizardBack() {
|
|
395
|
+
if (wizardSource === "task" && wizardStep <= 2) {
|
|
396
|
+
closeRalphWizard();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (wizardStep > 1) {
|
|
400
|
+
collectWizardData();
|
|
401
|
+
wizardStep--;
|
|
402
|
+
updateWizardStep();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function wizardSkip() {
|
|
407
|
+
if (wizardStep < 3) {
|
|
408
|
+
wizardStep++;
|
|
409
|
+
updateWizardStep();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function wizardSubmit() {
|
|
414
|
+
collectWizardData();
|
|
415
|
+
var wd = Object.assign({}, store.getState().wizardData);
|
|
416
|
+
wd.source = wizardSource === "task" ? "task" : undefined;
|
|
417
|
+
store.setState({ wizardData: wd });
|
|
418
|
+
closeRalphWizard();
|
|
419
|
+
var ws = getWs();
|
|
420
|
+
if (ws && ws.readyState === 1) {
|
|
421
|
+
ws.send(JSON.stringify({ type: "ralph_wizard_complete", data: wd }));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function updateRepeatUI() {
|
|
426
|
+
if (!repeatSelect) return;
|
|
427
|
+
var val = repeatSelect.value;
|
|
428
|
+
var isScheduled = val !== "none";
|
|
429
|
+
if (repeatTimeRow) repeatTimeRow.style.display = isScheduled ? "" : "none";
|
|
430
|
+
if (repeatCustom) repeatCustom.style.display = val === "custom" ? "" : "none";
|
|
431
|
+
if (cronPreview) cronPreview.style.display = isScheduled ? "" : "none";
|
|
432
|
+
if (isScheduled) {
|
|
433
|
+
var cron = buildWizardCron();
|
|
434
|
+
var humanEl = document.getElementById("ralph-cron-human");
|
|
435
|
+
var cronEl = document.getElementById("ralph-cron-expr");
|
|
436
|
+
if (humanEl) humanEl.textContent = cronToHumanText(cron);
|
|
437
|
+
if (cronEl) cronEl.textContent = cron || "";
|
|
438
|
+
}
|
|
439
|
+
}
|