...
This commit is contained in:
@@ -12,6 +12,12 @@
|
||||
Process Manager
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/jobs">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-briefcase"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path></svg>
|
||||
Job Manager
|
||||
</a>
|
||||
</li>
|
||||
<!-- Add more menu items here as needed -->
|
||||
</ul>
|
||||
{{ end }}
|
@@ -8,6 +8,8 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="/static/css/custom.css">
|
||||
<link rel="stylesheet" href="/static/css/jobs.css">
|
||||
{{ block css() }}{{ end }}
|
||||
</head>
|
||||
<body>
|
||||
{{ include "../components/navbar" }}
|
||||
|
33
pkg/servers/ui/views/pages/debug.jet
Normal file
33
pkg/servers/ui/views/pages/debug.jet
Normal file
@@ -0,0 +1,33 @@
|
||||
{{ extends "../layouts/base" }}
|
||||
|
||||
{{ block title() }}Debug Template Variables{{ end }}
|
||||
|
||||
{{ block body() }}
|
||||
<div class="container mt-4">
|
||||
<h1>Template Variables Debug</h1>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Available Variables</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre id="debug-output">{{ dump(.) }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ block scripts() }}
|
||||
<script>
|
||||
// Format the JSON for better readability
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
try {
|
||||
const debugOutput = document.getElementById('debug-output');
|
||||
const content = debugOutput.textContent;
|
||||
const obj = JSON.parse(content);
|
||||
debugOutput.textContent = JSON.stringify(obj, null, 2);
|
||||
} catch (e) {
|
||||
console.error('Failed to parse JSON:', e);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{ end }}
|
172
pkg/servers/ui/views/pages/job_details.jet
Normal file
172
pkg/servers/ui/views/pages/job_details.jet
Normal file
@@ -0,0 +1,172 @@
|
||||
{{ extends "../layouts/base" }}
|
||||
|
||||
{{ block title() }}Job Details - HeroApp UI{{ end }}
|
||||
|
||||
{{ block body() }}
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Job Details</h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<div class="btn-group me-2">
|
||||
<a href="/jobs" class="btn btn-sm btn-outline-secondary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>
|
||||
Back to Jobs
|
||||
</a>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="refreshJobDetails()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-refresh-cw"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5>Job #{{ .Job.JobID }}</h5>
|
||||
<span class="badge {{ if .Job.Status == "error" }}bg-danger{{ else if .Job.Status == "done" }}bg-success{{ else if .Job.Status == "active" }}bg-warning text-dark{{ else }}bg-primary{{ end }}">
|
||||
{{ .Job.Status }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Job ID</th>
|
||||
<td>{{ .Job.JobID }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Circle ID</th>
|
||||
<td>{{ .Job.CircleID }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Topic</th>
|
||||
<td>{{ .Job.Topic }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td>
|
||||
<span class="badge {{ if .Job.Status == "error" }}bg-danger{{ else if .Job.Status == "done" }}bg-success{{ else if .Job.Status == "active" }}bg-warning text-dark{{ else }}bg-primary{{ end }}">
|
||||
{{ .Job.Status }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Parameters Type</th>
|
||||
<td>{{ .Job.ParamsType }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Scheduled Time</th>
|
||||
<td>{{ .Job.TimeScheduled.Format("2006-01-02 15:04:05") }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Start Time</th>
|
||||
<td>
|
||||
{{ if not .Job.TimeStart.IsZero }}
|
||||
{{ .Job.TimeStart.Format("2006-01-02 15:04:05") }}
|
||||
{{ else }}
|
||||
Not started
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>End Time</th>
|
||||
<td>
|
||||
{{ if not .Job.TimeEnd.IsZero }}
|
||||
{{ .Job.TimeEnd.Format("2006-01-02 15:04:05") }}
|
||||
{{ else }}
|
||||
Not completed
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Duration</th>
|
||||
<td>{{ .Job.Duration }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Session Key</th>
|
||||
<td>{{ .Job.SessionKey }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error Section (if applicable) -->
|
||||
{{ if .Job.HasError }}
|
||||
<div class="card mb-4 border-danger">
|
||||
<div class="card-header bg-danger text-white">
|
||||
<h5>Error</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre class="error-message">{{ .Job.Error }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<!-- Result Section (if completed) -->
|
||||
{{ if .Job.Status == "done" }}
|
||||
<div class="card mb-4 border-success">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h5>Result</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre class="result-content">{{ .Job.Result }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<!-- Parameters Section -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5>Parameters</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre class="params-content">{{ .Job.Params }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ block scripts() }}
|
||||
<script>
|
||||
function refreshJobDetails() {
|
||||
window.location.reload();
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
pre.error-message {
|
||||
background-color: #f8d7da;
|
||||
color: #842029;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre.result-content {
|
||||
background-color: #d1e7dd;
|
||||
color: #0f5132;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre.params-content {
|
||||
background-color: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
{{ end }}
|
224
pkg/servers/ui/views/pages/jobs.jet
Normal file
224
pkg/servers/ui/views/pages/jobs.jet
Normal file
@@ -0,0 +1,224 @@
|
||||
{{ extends "../layouts/base" }}
|
||||
|
||||
{{ block title() }}Job Management - HeroApp UI{{ end }}
|
||||
|
||||
{{ block body() }}
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Job Management</h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<div class="btn-group me-2">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="refreshJobs()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-refresh-cw"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Job Stats Cards -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-primary">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Total Jobs</h5>
|
||||
<p class="card-text display-6">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-success">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Completed Jobs</h5>
|
||||
<p class="card-text display-6">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-warning">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Active Jobs</h5>
|
||||
<p class="card-text display-6">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white bg-danger">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Error Jobs</h5>
|
||||
<p class="card-text display-6">0</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filters -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Filters</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="filterForm" action="/jobs" method="get" class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label for="circle" class="form-label">Circle</label>
|
||||
<select class="form-select" id="circle" name="circle" onchange="this.form.submit()">
|
||||
<option value="">All Circles</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="topic" class="form-label">Topic</label>
|
||||
<select class="form-select" id="topic" name="topic" onchange="this.form.submit()">
|
||||
<option value="">All Topics</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="status" class="form-label">Status</label>
|
||||
<select class="form-select" id="status" name="status" onchange="this.form.submit()">
|
||||
<option value="">All Statuses</option>
|
||||
<option value="new">New</option>
|
||||
<option value="active">Active</option>
|
||||
<option value="done">Done</option>
|
||||
<option value="error">Error</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary">Apply Filters</button>
|
||||
<a href="/jobs" class="btn btn-secondary ms-2">Clear Filters</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Tree View -->
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Job Tree</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="jobTree" class="job-tree">
|
||||
<p>No job tree data available</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Job List -->
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Job List</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Circle</th>
|
||||
<th>Topic</th>
|
||||
<th>Status</th>
|
||||
<th>Scheduled</th>
|
||||
<th>Duration</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">No jobs available</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ block scripts() }}
|
||||
<script>
|
||||
function toggleCircle(element) {
|
||||
const topicsContainer = element.nextElementSibling;
|
||||
const chevron = element.querySelector('svg');
|
||||
|
||||
if (topicsContainer.style.display === 'none') {
|
||||
topicsContainer.style.display = 'block';
|
||||
chevron.classList.add('rotate-90');
|
||||
} else {
|
||||
topicsContainer.style.display = 'none';
|
||||
chevron.classList.remove('rotate-90');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTopic(element) {
|
||||
const jobsContainer = element.nextElementSibling;
|
||||
const chevron = element.querySelector('svg');
|
||||
|
||||
if (jobsContainer.style.display === 'none') {
|
||||
jobsContainer.style.display = 'block';
|
||||
chevron.classList.add('rotate-90');
|
||||
} else {
|
||||
jobsContainer.style.display = 'none';
|
||||
chevron.classList.remove('rotate-90');
|
||||
}
|
||||
}
|
||||
|
||||
function refreshJobs() {
|
||||
window.location.reload();
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.job-tree {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.circle-header, .topic-header {
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.circle-header:hover, .topic-header:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.circle-name, .topic-name {
|
||||
margin-left: 5px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.job-node {
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.job-link {
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.rotate-90 {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.circle-node, .topic-node {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.topics-container, .jobs-container {
|
||||
padding-top: 5px;
|
||||
}
|
||||
</style>
|
||||
{{ end }}
|
Reference in New Issue
Block a user