Akoda35 commited on
Commit
39472e1
·
verified ·
1 Parent(s): c2f5047

Upload 2 files

Browse files
templates/cpanel/runs/detail.html ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Run {{ run.pk|truncatechars:8 }} - PyRunner{% endblock %}
4
+
5
+ {% block extra_head %}
6
+ {% if run.status == 'pending' or run.status == 'running' %}
7
+ <meta http-equiv="refresh" content="5">
8
+ {% endif %}
9
+ {% endblock %}
10
+
11
+ {% block content %}
12
+ <div class="flex">
13
+ {% include "cpanel/_sidebar.html" %}
14
+
15
+ <div class="flex-1 p-8">
16
+ <!-- Header -->
17
+ <div class="mb-8">
18
+ <nav class="flex items-center space-x-2 text-sm text-code-muted mb-4">
19
+ <a href="{% url 'cpanel:run_list' %}" class="hover:text-code-accent">Runs</a>
20
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
21
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
22
+ </svg>
23
+ <span class="text-code-text">Run Details</span>
24
+ </nav>
25
+
26
+ <div class="flex items-start justify-between">
27
+ <div>
28
+ <h1 class="text-2xl font-bold text-code-text flex items-center">
29
+ {{ run.script.name }}
30
+ {% if run.status == 'success' %}
31
+ <span class="ml-3 px-2 py-1 text-xs rounded bg-code-green/20 text-code-green">Success</span>
32
+ {% elif run.status == 'failed' %}
33
+ <span class="ml-3 px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Failed</span>
34
+ {% elif run.status == 'timeout' %}
35
+ <span class="ml-3 px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Timeout</span>
36
+ {% elif run.status == 'running' %}
37
+ <span class="ml-3 px-2 py-1 text-xs rounded bg-code-yellow/20 text-code-yellow">Running</span>
38
+ {% elif run.status == 'pending' %}
39
+ <span class="ml-3 px-2 py-1 text-xs rounded bg-code-muted/20 text-code-muted">Pending</span>
40
+ {% elif run.status == 'cancelled' %}
41
+ <span class="ml-3 px-2 py-1 text-xs rounded bg-code-muted/20 text-code-muted">Cancelled</span>
42
+ {% endif %}
43
+ </h1>
44
+ <p class="text-code-muted mt-1">
45
+ Run ID: <span class="font-mono text-sm">{{ run.pk }}</span>
46
+ </p>
47
+ </div>
48
+
49
+ <a href="{% url 'cpanel:script_detail' pk=run.script.pk %}"
50
+ class="px-4 py-2 bg-code-surface border border-code-border hover:border-code-accent text-code-text rounded-lg transition-colors">
51
+ View Script
52
+ </a>
53
+ </div>
54
+ </div>
55
+
56
+ {% if run.status == 'pending' or run.status == 'running' %}
57
+ <div class="mb-6 p-4 bg-code-accent/10 border border-code-accent/30 rounded-lg flex items-center justify-between">
58
+ <div class="flex items-center space-x-3">
59
+ <svg class="w-5 h-5 text-code-accent animate-spin" fill="none" viewBox="0 0 24 24">
60
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
61
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
62
+ </svg>
63
+ <span class="text-code-accent">
64
+ {% if run.status == 'pending' %}Queued and waiting for a worker...{% else %}Running...{% endif %}
65
+ </span>
66
+ </div>
67
+ <button onclick="location.reload();" class="px-3 py-1 text-sm bg-code-accent/20 hover:bg-code-accent/30 text-code-accent rounded transition-colors">
68
+ Refresh
69
+ </button>
70
+ </div>
71
+ {% endif %}
72
+
73
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
74
+ <!-- Left Column: Output -->
75
+ <div class="lg:col-span-2 space-y-6">
76
+ <!-- Standard Output -->
77
+ <div class="bg-code-surface border border-code-border rounded-xl overflow-hidden">
78
+ <div class="px-4 py-3 border-b border-code-border bg-code-bg flex items-center justify-between">
79
+ <span class="text-sm font-medium text-code-text flex items-center">
80
+ <svg class="w-4 h-4 mr-2 text-code-green" fill="none" stroke="currentColor" viewBox="0 0 24 24">
81
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
82
+ </svg>
83
+ Standard Output (stdout)
84
+ </span>
85
+ {% if run.stdout %}
86
+ <span class="text-xs text-code-muted">{{ run.stdout|length }} chars</span>
87
+ {% endif %}
88
+ </div>
89
+ <div class="p-4 overflow-x-auto max-h-96 overflow-y-auto">
90
+ {% if run.stdout %}
91
+ <pre class="text-code-text font-mono text-sm whitespace-pre-wrap">{{ run.stdout }}</pre>
92
+ {% else %}
93
+ <p class="text-code-muted text-sm italic">No output</p>
94
+ {% endif %}
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Standard Error -->
99
+ {% if run.stderr %}
100
+ <div class="bg-code-surface border border-code-red/30 rounded-xl overflow-hidden">
101
+ <div class="px-4 py-3 border-b border-code-red/30 bg-code-red/10 flex items-center justify-between">
102
+ <span class="text-sm font-medium text-code-red flex items-center">
103
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
104
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
105
+ </svg>
106
+ Standard Error (stderr)
107
+ </span>
108
+ <span class="text-xs text-code-red/70">{{ run.stderr|length }} chars</span>
109
+ </div>
110
+ <div class="p-4 overflow-x-auto max-h-96 overflow-y-auto">
111
+ <pre class="text-code-red font-mono text-sm whitespace-pre-wrap">{{ run.stderr }}</pre>
112
+ </div>
113
+ </div>
114
+ {% endif %}
115
+
116
+ <!-- Code Snapshot (Collapsible) -->
117
+ {% if run.code_snapshot %}
118
+ <details class="bg-code-surface border border-code-border rounded-xl overflow-hidden">
119
+ <summary class="px-4 py-3 border-b border-code-border bg-code-bg cursor-pointer hover:bg-code-bg/80 transition-colors">
120
+ <span class="text-sm font-medium text-code-text">Code Snapshot (at time of execution)</span>
121
+ </summary>
122
+ <div class="p-4 overflow-x-auto max-h-96 overflow-y-auto">
123
+ <pre class="text-code-text font-mono text-sm whitespace-pre-wrap">{{ run.code_snapshot }}</pre>
124
+ </div>
125
+ </details>
126
+ {% endif %}
127
+ </div>
128
+
129
+ <!-- Right Column: Metadata -->
130
+ <div class="space-y-6">
131
+ <!-- Run Info -->
132
+ <div class="bg-code-surface border border-code-border rounded-xl p-6">
133
+ <h3 class="text-sm font-semibold text-code-text mb-4">Run Info</h3>
134
+ <dl class="space-y-4">
135
+ <div>
136
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Script</dt>
137
+ <dd class="text-code-text mt-1">
138
+ <a href="{% url 'cpanel:script_detail' pk=run.script.pk %}" class="text-code-accent hover:underline">
139
+ {{ run.script.name }}
140
+ </a>
141
+ </dd>
142
+ </div>
143
+ <div>
144
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Status</dt>
145
+ <dd class="mt-1">
146
+ {% if run.status == 'success' %}
147
+ <span class="px-2 py-1 text-xs rounded bg-code-green/20 text-code-green">Success</span>
148
+ {% elif run.status == 'failed' %}
149
+ <span class="px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Failed</span>
150
+ {% elif run.status == 'timeout' %}
151
+ <span class="px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Timeout</span>
152
+ {% elif run.status == 'running' %}
153
+ <span class="px-2 py-1 text-xs rounded bg-code-yellow/20 text-code-yellow">Running</span>
154
+ {% elif run.status == 'pending' %}
155
+ <span class="px-2 py-1 text-xs rounded bg-code-muted/20 text-code-muted">Pending</span>
156
+ {% elif run.status == 'cancelled' %}
157
+ <span class="px-2 py-1 text-xs rounded bg-code-muted/20 text-code-muted">Cancelled</span>
158
+ {% endif %}
159
+ </dd>
160
+ </div>
161
+ {% if run.exit_code is not None %}
162
+ <div>
163
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Exit Code</dt>
164
+ <dd class="text-code-text mt-1 font-mono">{{ run.exit_code }}</dd>
165
+ </div>
166
+ {% endif %}
167
+ <div>
168
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Duration</dt>
169
+ <dd class="text-code-text mt-1">
170
+ {% if run.duration_display %}{{ run.duration_display }}{% else %}-{% endif %}
171
+ </dd>
172
+ </div>
173
+ <div>
174
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Triggered By</dt>
175
+ <dd class="text-code-text mt-1">
176
+ {% if run.triggered_by %}{{ run.triggered_by.email }}{% else %}System{% endif %}
177
+ </dd>
178
+ </div>
179
+ </dl>
180
+ </div>
181
+
182
+ <!-- Timing -->
183
+ <div class="bg-code-surface border border-code-border rounded-xl p-6">
184
+ <h3 class="text-sm font-semibold text-code-text mb-4">Timing</h3>
185
+ <dl class="space-y-4">
186
+ <div>
187
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Created</dt>
188
+ <dd class="text-code-text mt-1">{{ run.created_at|date:"M d, Y H:i:s" }}</dd>
189
+ </div>
190
+ {% if run.started_at %}
191
+ <div>
192
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Started</dt>
193
+ <dd class="text-code-text mt-1">{{ run.started_at|date:"M d, Y H:i:s" }}</dd>
194
+ </div>
195
+ {% endif %}
196
+ {% if run.ended_at %}
197
+ <div>
198
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Ended</dt>
199
+ <dd class="text-code-text mt-1">{{ run.ended_at|date:"M d, Y H:i:s" }}</dd>
200
+ </div>
201
+ {% endif %}
202
+ </dl>
203
+ </div>
204
+
205
+ <!-- Task Info (if applicable) -->
206
+ {% if run.task_id %}
207
+ <div class="bg-code-surface border border-code-border rounded-xl p-6">
208
+ <h3 class="text-sm font-semibold text-code-text mb-4">Task Info</h3>
209
+ <dl>
210
+ <dt class="text-xs text-code-muted uppercase tracking-wider">Task ID</dt>
211
+ <dd class="text-code-text mt-1 font-mono text-sm break-all">{{ run.task_id }}</dd>
212
+ </dl>
213
+ </div>
214
+ {% endif %}
215
+ </div>
216
+ </div>
217
+ </div>
218
+ </div>
219
+ {% endblock %}
templates/cpanel/runs/list.html ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Runs - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="flex">
7
+ {% include "cpanel/_sidebar.html" %}
8
+
9
+ <div class="flex-1 p-8">
10
+ <!-- Header -->
11
+ <div class="mb-8">
12
+ <h1 class="text-2xl font-bold text-code-text">Runs</h1>
13
+ <p class="text-code-muted">Execution history for all scripts</p>
14
+ </div>
15
+
16
+ <!-- Filters -->
17
+ <div class="mb-6 flex flex-wrap items-center gap-4">
18
+ <div class="flex items-center space-x-2">
19
+ <span class="text-code-muted text-sm">Status:</span>
20
+ <a href="{% url 'cpanel:run_list' %}{% if script_filter %}?script={{ script_filter }}{% endif %}"
21
+ class="px-3 py-1 text-sm rounded-lg transition-colors {% if not status_filter %}bg-code-accent/20 text-code-accent{% else %}text-code-muted hover:text-code-text hover:bg-code-bg{% endif %}">
22
+ All
23
+ </a>
24
+ {% for value, label in status_choices %}
25
+ <a href="{% url 'cpanel:run_list' %}?status={{ value }}{% if script_filter %}&script={{ script_filter }}{% endif %}"
26
+ class="px-3 py-1 text-sm rounded-lg transition-colors {% if status_filter == value %}{% if value == 'success' %}bg-code-green/20 text-code-green{% elif value == 'failed' or value == 'timeout' %}bg-code-red/20 text-code-red{% elif value == 'running' %}bg-code-yellow/20 text-code-yellow{% else %}bg-code-muted/20 text-code-muted{% endif %}{% else %}text-code-muted hover:text-code-text hover:bg-code-bg{% endif %}">
27
+ {{ label }}
28
+ </a>
29
+ {% endfor %}
30
+ </div>
31
+
32
+ {% if scripts %}
33
+ <div class="flex items-center space-x-2">
34
+ <span class="text-code-muted text-sm">Script:</span>
35
+ <select onchange="window.location.href='{% url 'cpanel:run_list' %}{% if status_filter %}?status={{ status_filter }}&{% else %}?{% endif %}script=' + this.value"
36
+ class="px-3 py-1 text-sm bg-code-bg border border-code-border rounded-lg text-code-text focus:outline-none focus:ring-2 focus:ring-code-accent/50">
37
+ <option value="">All Scripts</option>
38
+ {% for script in scripts %}
39
+ <option value="{{ script.pk }}" {% if script_filter == script.pk|stringformat:"s" %}selected{% endif %}>
40
+ {{ script.name }}
41
+ </option>
42
+ {% endfor %}
43
+ </select>
44
+ </div>
45
+ {% endif %}
46
+ </div>
47
+
48
+ <!-- Runs Table -->
49
+ {% if runs %}
50
+ <div class="bg-code-surface border border-code-border rounded-xl overflow-hidden">
51
+ <table class="w-full">
52
+ <thead class="bg-code-bg border-b border-code-border">
53
+ <tr>
54
+ <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Script</th>
55
+ <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Status</th>
56
+ <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Duration</th>
57
+ <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Triggered By</th>
58
+ <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider">Started</th>
59
+ <th class="px-6 py-4 text-left text-xs font-semibold text-code-muted uppercase tracking-wider"></th>
60
+ </tr>
61
+ </thead>
62
+ <tbody class="divide-y divide-code-border">
63
+ {% for run in runs %}
64
+ <tr class="hover:bg-code-bg/50 transition-colors">
65
+ <td class="px-6 py-4">
66
+ <a href="{% url 'cpanel:script_detail' pk=run.script.pk %}" class="text-code-accent hover:underline font-medium">
67
+ {{ run.script.name }}
68
+ </a>
69
+ </td>
70
+ <td class="px-6 py-4">
71
+ {% if run.status == 'success' %}
72
+ <span class="px-2 py-1 text-xs rounded bg-code-green/20 text-code-green">Success</span>
73
+ {% elif run.status == 'failed' %}
74
+ <span class="px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Failed</span>
75
+ {% elif run.status == 'timeout' %}
76
+ <span class="px-2 py-1 text-xs rounded bg-code-red/20 text-code-red">Timeout</span>
77
+ {% elif run.status == 'running' %}
78
+ <span class="px-2 py-1 text-xs rounded bg-code-yellow/20 text-code-yellow">Running</span>
79
+ {% elif run.status == 'pending' %}
80
+ <span class="px-2 py-1 text-xs rounded bg-code-muted/20 text-code-muted">Pending</span>
81
+ {% elif run.status == 'cancelled' %}
82
+ <span class="px-2 py-1 text-xs rounded bg-code-muted/20 text-code-muted">Cancelled</span>
83
+ {% endif %}
84
+ </td>
85
+ <td class="px-6 py-4 text-code-text">
86
+ {% if run.duration_display %}{{ run.duration_display }}{% else %}-{% endif %}
87
+ </td>
88
+ <td class="px-6 py-4 text-code-muted">
89
+ {% if run.triggered_by %}{{ run.triggered_by.email }}{% else %}System{% endif %}
90
+ </td>
91
+ <td class="px-6 py-4 text-code-muted text-sm">
92
+ {% if run.started_at %}{{ run.started_at|date:"M d, H:i" }}{% else %}{{ run.created_at|date:"M d, H:i" }}{% endif %}
93
+ </td>
94
+ <td class="px-6 py-4 text-right">
95
+ <a href="{% url 'cpanel:run_detail' pk=run.pk %}" class="text-code-accent hover:underline text-sm">
96
+ View
97
+ </a>
98
+ </td>
99
+ </tr>
100
+ {% endfor %}
101
+ </tbody>
102
+ </table>
103
+ </div>
104
+ {% else %}
105
+ <div class="bg-code-surface border border-code-border rounded-xl p-12 text-center">
106
+ <div class="w-16 h-16 bg-code-accent/20 rounded-full flex items-center justify-center mx-auto mb-4">
107
+ <svg class="w-8 h-8 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
108
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
109
+ </svg>
110
+ </div>
111
+ <h3 class="text-lg font-semibold text-code-text mb-2">No runs yet</h3>
112
+ <p class="text-code-muted mb-6">Run a script to see execution history here.</p>
113
+ <a href="{% url 'cpanel:script_list' %}"
114
+ class="inline-flex items-center px-4 py-2 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors">
115
+ View Scripts
116
+ </a>
117
+ </div>
118
+ {% endif %}
119
+ </div>
120
+ </div>
121
+ {% endblock %}