mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-05-23 04:17:34 +00:00
Add user-configurable timezone and 12/24-hour preferences, then wire them through settings, runtime snapshots, scheduler payloads, wait handling, notifications, backups, memory, plugin metadata, and frontend formatters. Keep UTC as the boundary for absolute instants while serializing user-facing dates in the configured or browser-resolved timezone. Preserve scheduler wall-clock inputs in the selected timezone, propagate TZ into desktop/runtime process environments, and restart active desktop sessions when the runtime timezone changes. Cover the risky paths with timezone regression tests for settings normalization, auto and fixed timezone resolution, scheduler round-trips, memory timestamp conversion, and desktop timezone sync.
173 lines
6.4 KiB
HTML
173 lines
6.4 KiB
HTML
<html>
|
|
<head>
|
|
<title>Plugin Execute</title>
|
|
<script type="module">
|
|
import { store } from "/components/plugins/list/plugin-execute-store.js";
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div x-data>
|
|
<template x-if="$store.pluginExecuteStore">
|
|
<div x-destroy="$store.pluginExecuteStore.cleanup()"
|
|
x-create="$el.closest('.modal')?.querySelector('.modal-title') && ($el.closest('.modal').querySelector('.modal-title').textContent = 'Execute: ' + $store.pluginExecuteStore.pluginDisplayName)"
|
|
class="plugin-execute-root">
|
|
|
|
<div class="plugin-execute-idle"
|
|
x-show="!$store.pluginExecuteStore.running && $store.pluginExecuteStore.exitCode === null && !$store.pluginExecuteStore.output">
|
|
<span class="material-symbols-outlined idle-icon">terminal</span>
|
|
<div class="idle-text">
|
|
<span class="idle-headline">Press <strong>Run</strong> to execute <strong x-text="$store.pluginExecuteStore.pluginDisplayName"></strong></span>
|
|
<span class="idle-sub">This will run the plugin's <code>execute.py</code> script.</span>
|
|
<template x-if="$store.pluginExecuteStore.lastExecution">
|
|
<span class="last-exec-info">
|
|
Last run:
|
|
<span x-text="$store.pluginExecuteStore.formatTimestamp($store.pluginExecuteStore.lastExecution.executed_at)"></span>
|
|
—
|
|
<span :class="$store.pluginExecuteStore.lastExecution.exit_code === 0 ? 'exit-ok' : 'exit-err'"
|
|
x-text="$store.pluginExecuteStore.lastExecution.exit_code === 0 ? 'succeeded' : 'failed (exit ' + $store.pluginExecuteStore.lastExecution.exit_code + ')'">
|
|
</span>
|
|
</span>
|
|
</template>
|
|
<template x-if="!$store.pluginExecuteStore.lastExecution">
|
|
<span class="last-exec-info never-run">Never executed</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="plugin-execute-status" x-show="$store.pluginExecuteStore.running">
|
|
<span class="material-symbols-outlined spin">progress_activity</span>
|
|
<span>Running execute.py...</span>
|
|
</div>
|
|
|
|
<div class="plugin-execute-exit" x-show="!$store.pluginExecuteStore.running && $store.pluginExecuteStore.exitCode !== null">
|
|
<span class="material-symbols-outlined"
|
|
:class="$store.pluginExecuteStore.exitCode === 0 ? 'exit-ok' : 'exit-err'"
|
|
x-text="$store.pluginExecuteStore.exitCode === 0 ? 'check_circle' : 'error'">
|
|
</span>
|
|
<span x-text="$store.pluginExecuteStore.exitCode === 0 ? 'Completed successfully (exit 0)' : 'Exited with code ' + $store.pluginExecuteStore.exitCode"></span>
|
|
</div>
|
|
|
|
<pre class="plugin-execute-output"
|
|
x-show="$store.pluginExecuteStore.output || $store.pluginExecuteStore.running"
|
|
x-text="$store.pluginExecuteStore.output || ''"></pre>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<div class="modal-footer" data-modal-footer>
|
|
<button class="btn btn-action footer-btn"
|
|
x-data
|
|
:disabled="$store.pluginExecuteStore?.running"
|
|
@click="$store.pluginExecuteStore?.run()">
|
|
<span class="icon material-symbols-outlined">play_arrow</span>
|
|
<span x-text="$store.pluginExecuteStore?.exitCode !== null || $store.pluginExecuteStore?.output ? 'Rerun' : 'Run'">Run</span>
|
|
</button>
|
|
<button class="btn btn-cancel footer-btn" @click="window.closeModal?.()">Close</button>
|
|
</div>
|
|
|
|
<style>
|
|
.plugin-execute-root {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 100%;
|
|
}
|
|
|
|
.plugin-execute-idle {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 1rem;
|
|
padding: 2rem 1.5rem;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.idle-icon {
|
|
font-size: 2.75rem;
|
|
opacity: 0.35;
|
|
flex-shrink: 0;
|
|
margin-top: 0.15rem;
|
|
}
|
|
|
|
.idle-text {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.4rem;
|
|
}
|
|
|
|
.idle-headline {
|
|
font-size: 1rem;
|
|
color: var(--color-text);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.idle-sub {
|
|
font-size: 0.82rem;
|
|
opacity: 0.65;
|
|
}
|
|
|
|
.last-exec-info {
|
|
font-size: 0.8rem;
|
|
opacity: 0.7;
|
|
margin-top: 0.25rem;
|
|
}
|
|
|
|
.never-run {
|
|
font-style: italic;
|
|
}
|
|
|
|
.plugin-execute-status {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.75rem 1.5rem;
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--font-size-small);
|
|
}
|
|
|
|
.plugin-execute-exit {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1.5rem;
|
|
font-size: var(--font-size-small);
|
|
}
|
|
|
|
.exit-ok {
|
|
color: var(--color-success, #27ae60);
|
|
}
|
|
|
|
.exit-err {
|
|
color: var(--color-error, #e74c3c);
|
|
}
|
|
|
|
.plugin-execute-output {
|
|
font-family: "Courier New", Courier, monospace;
|
|
font-size: 0.82rem;
|
|
background: var(--color-bg-secondary, #1e1e1e);
|
|
color: var(--color-text-primary);
|
|
padding: 1rem 1.5rem;
|
|
margin: 0;
|
|
overflow-y: auto;
|
|
max-height: 60vh;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
@keyframes spin {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
.spin {
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
|
|
.footer-btn {
|
|
padding: 0.5rem 1.5rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
border-radius: 0.25rem;
|
|
}
|
|
</style>
|
|
</body>
|
|
</html>
|