varaverk: suggestions panel color + parser regex fix
- Change suggestion title color from bright green (#6fcf97) to soft grey-blue (#7a9eb5) - Fix vv_parse_user_script_template() block-detection regex — $ end-anchor failed on lines ending with multibyte U+2500 ─ chars; removed anchor so parser now returns all 22 blocks from user_script_plug-in.sh
This commit is contained in:
@@ -103,6 +103,33 @@
|
||||
.vv-dry-btn:hover { background: #e65100 !important; color: #fff !important;
|
||||
border-color: #ff9800 !important; }
|
||||
|
||||
/* Suggestions panel — accordion */
|
||||
#vv-suggestions { overflow-y: auto; }
|
||||
.vv-sug-block { border-bottom: 1px solid #1e1e1e; }
|
||||
.vv-sug-header { display: flex; align-items: center; gap: 8px; padding: 7px 4px;
|
||||
cursor: pointer; user-select: none; flex-wrap: wrap; }
|
||||
.vv-sug-header:hover { background: rgba(255,255,255,0.03); }
|
||||
.vv-sug-chevron { color: #555; font-size: 11px; flex-shrink: 0; width: 10px; }
|
||||
.vv-sug-title { color: #7a9eb5; font-weight: bold; font-size: 13px; flex: 1; min-width: 120px; }
|
||||
.vv-sug-cron { color: #ddd; background: #111; border: 1px solid #333; padding: 1px 6px;
|
||||
border-radius: 3px; font-size: 11px; font-family: monospace; white-space: nowrap; flex-shrink: 0; }
|
||||
.vv-sug-label { color: #666; font-size: 12px; flex: 1; min-width: 0; white-space: nowrap;
|
||||
overflow: hidden; text-overflow: ellipsis; }
|
||||
.vv-sug-status { font-size: 11px; flex-shrink: 0; margin-left: auto; }
|
||||
.vv-sug-on { color: #4caf50; }
|
||||
.vv-sug-off { color: #777; }
|
||||
.vv-sug-none { color: #444; }
|
||||
.vv-sug-body { padding: 0 14px 10px; }
|
||||
.vv-sug-desc { font-size: 12px; color: #888; white-space: pre-wrap; word-break: break-word;
|
||||
background: none; border: none; margin: 4px 0 8px; padding: 0;
|
||||
font-family: inherit; line-height: 1.6; }
|
||||
.vv-sug-scripts { display: flex; flex-direction: column; gap: 4px; }
|
||||
.vv-sug-script-row { display: flex; align-items: center; gap: 8px; font-size: 12px; }
|
||||
.vv-sug-inline-cron { color: #aaa; background: #111; padding: 1px 5px; border-radius: 3px;
|
||||
font-size: 11px; white-space: nowrap; }
|
||||
.vv-sug-path { color: #888; font-family: monospace; }
|
||||
.vv-sug-configured { color: #4caf50; font-size: 11px; }
|
||||
|
||||
/* Log panel */
|
||||
.vv-log-panel { margin-top: 10px; border-top: 1px solid #333; padding-top: 8px; }
|
||||
.vv-log-toolbar { display: flex; justify-content: space-between; align-items: center;
|
||||
|
||||
@@ -66,6 +66,78 @@ function vv_cron_rebuild(array $schedule): bool {
|
||||
return file_put_contents(CRON_FILE, implode("\n", $lines)) !== false;
|
||||
}
|
||||
|
||||
// Extract the suggested cron and label from a bash script header.
|
||||
// Looks for: # Schedule: */7 * * * * (every 7 minutes via User Scripts plugin)
|
||||
function vv_script_suggested_cron(string $path): array {
|
||||
if (!file_exists($path)) return ['cron' => '', 'label' => ''];
|
||||
$lines = array_slice(file($path) ?: [], 0, 30);
|
||||
foreach ($lines as $raw) {
|
||||
$raw = rtrim($raw);
|
||||
if (!preg_match('/^#\s*Schedule:\s*(.+)$/i', $raw, $m)) continue;
|
||||
$tail = trim($m[1]);
|
||||
$parts = preg_split('/\s+/', $tail, 6);
|
||||
$cron = implode(' ', array_slice($parts, 0, 5));
|
||||
$label = isset($parts[5]) ? trim($parts[5], '() ') : '';
|
||||
return ['cron' => $cron, 'label' => $label];
|
||||
}
|
||||
return ['cron' => '', 'label' => ''];
|
||||
}
|
||||
|
||||
// Parse user_script_plug-in.sh into an array of script blocks.
|
||||
// Each block: title, schedule, desc (array of lines), scripts (array of {rel, cron})
|
||||
function vv_parse_user_script_template(): array {
|
||||
$file = SCRIPTS_DIR . '/user_script_plug-in.sh';
|
||||
if (!file_exists($file)) return [];
|
||||
$lines = file($file, FILE_IGNORE_NEW_LINES);
|
||||
$prefix = rtrim(SCRIPTS_DIR, '/') . '/';
|
||||
$blocks = [];
|
||||
$cur = null;
|
||||
|
||||
foreach ($lines as $line) {
|
||||
// Block header: # ── TITLE ──...
|
||||
if (preg_match('/^# ── (.+?) ─/', $line, $m)) {
|
||||
if ($cur) $blocks[] = $cur;
|
||||
$cur = ['title' => trim($m[1]), 'schedule' => '', 'desc' => [], 'scripts' => []];
|
||||
continue;
|
||||
}
|
||||
if (!$cur) continue;
|
||||
|
||||
// Schedule / Background — captured but not added to desc
|
||||
if (preg_match('/^# (Schedule|Background):\s+(.+)$/i', $line, $m)) {
|
||||
if (strtolower($m[1]) === 'schedule') $cur['schedule'] = trim($m[2]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sunday block inline cron: # 0 6 * * 0 bash /path/script.sh [args]
|
||||
if (preg_match('/^#\s+(\S+ +\S+ +\S+ +\S+ +\S+)\s+bash\s+(\S+\.sh)/', $line, $m)) {
|
||||
$rel = str_replace($prefix, '', trim($m[2]));
|
||||
$cur['scripts'][] = ['rel' => $rel, 'cron' => preg_replace('/\s+/', ' ', trim($m[1]))];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Standard bash line: # bash /prefix/path/script.sh [args]
|
||||
if (preg_match('/^# bash\s+(\S+\.sh)/', $line, $m)) {
|
||||
$rel = str_replace($prefix, '', $m[1]);
|
||||
// Only add primary command (dedupe by rel)
|
||||
$rels = array_column($cur['scripts'], 'rel');
|
||||
if (!in_array($rel, $rels)) {
|
||||
$cur['scripts'][] = ['rel' => $rel, 'cron' => ''];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Description line
|
||||
if (preg_match('/^# ?(.*)$/', $line, $m)) {
|
||||
$inner = $m[1];
|
||||
if (!preg_match('/^[─━=\-]{3,}\s*$/', $inner) && !preg_match('/^█/', $inner)) {
|
||||
$cur['desc'][] = $inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($cur) $blocks[] = $cur;
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
// Extract a one-line description from a bash script header.
|
||||
// Supports two patterns:
|
||||
// 1. # PURPOSE (or # DESCRIPTION) block — returns first non-separator line after it
|
||||
@@ -109,15 +181,18 @@ function vv_job_tree(): array {
|
||||
foreach (glob($orchPattern) ?: [] as $path) {
|
||||
$id = 'Orchestrators/' . basename($path);
|
||||
$entry = $schedule[$id] ?? ['enabled' => false, 'cron' => ''];
|
||||
$suggested = vv_script_suggested_cron($path);
|
||||
$orchs[] = [
|
||||
'id' => $id,
|
||||
'label' => basename($path, '.sh'),
|
||||
'desc' => vv_script_description($path),
|
||||
'type' => 'orchestrator',
|
||||
'enabled' => (bool)($entry['enabled'] ?? false),
|
||||
'cron' => $entry['cron'] ?? '',
|
||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||
'children' => vv_script_children($path, $schedule),
|
||||
'id' => $id,
|
||||
'label' => basename($path, '.sh'),
|
||||
'desc' => vv_script_description($path),
|
||||
'type' => 'orchestrator',
|
||||
'enabled' => (bool)($entry['enabled'] ?? false),
|
||||
'cron' => $entry['cron'] ?? '',
|
||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||
'suggested_cron' => $suggested['cron'],
|
||||
'suggested_label' => $suggested['label'],
|
||||
'children' => vv_script_children($path, $schedule),
|
||||
];
|
||||
}
|
||||
return $orchs;
|
||||
|
||||
Reference in New Issue
Block a user