hydra/src/root/jobset.tt
Pierre Bourdon 65618fd590 web: replace 'errormsg' with 'errormsg IS NULL' in most cases
This is implement in an extremely hacky way due to poor DBIx feature
support. Ideally, what we'd need is a way to tell DBIx to ignore the
errormsg column unless explicitly requested, and to automatically add a
computed 'errormsg IS NULL' column in others. Since it does not support
that, this commit instead hacks some support via method overrides while
taking care to not break anything obvious.
2025-04-09 11:31:47 -04:00

229 lines
7.7 KiB
Plaintext

[% WRAPPER layout.tt
titleHTML=makeNameLinksForJobset(jobset)
title=makeNameTextForJobset(jobset) %]
[% PROCESS common.tt %]
[% USE format %]
[% BLOCK renderJobsetInput %]
<tr class="input [% extraClass %]" [% IF id %]id="[% id %]"[% END %]>
<td>
<tt>[% HTML.escape(input.name) %]</tt>
</td>
<td>
[% INCLUDE renderSelection curValue=input.type param="$baseName-type" options=inputTypes %]
</td>
<td class="inputalts" id="[% baseName %]">
[% FOREACH alt IN input.search_related('jobsetinputalts', {}, { order_by => 'altnr' }) %]
<tt class="inputalt">
[% IF input.type == "string" %]
"<span class="keep-whitespace">[% HTML.escape(alt.value) %]</span>"
[% ELSE %]
[% HTML.escape(alt.value) %]
[% END %]
</tt>
[% END %]
</td>
</tr>
[% END %]
[% BLOCK renderJobsetInputs %]
<h3>Inputs</h3>
<table class="table table-striped table-condensed">
<thead>
<tr><th>Input name</th><th>Type</th><th>Values</th></tr>
</thead>
<tbody class="inputs">
[% FOREACH input IN jobset.jobsetinputs %]
[% INCLUDE renderJobsetInput input=input baseName="input-$input.name" %]
[% END %]
</tbody>
</table>
[% END %]
<ul class="nav nav-tabs">
[% IF c.user_exists %]
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">Actions</a>
<div class="dropdown-menu">
[% UNLESS project.declfile %]
[% INCLUDE menuItem title="Edit configuration" icon="icon-edit" uri=c.uri_for(c.controller('Jobset').action_for('edit'), c.req.captures) %]
<!--
[% INCLUDE menuItem title="Delete this jobset" icon="icon-trash" uri="javascript:deleteJobset()" %]
-->
[% INCLUDE menuItem title="Clone this jobset" uri=c.uri_for(c.controller('Jobset').action_for('edit'), c.req.captures, { cloneJobset => 1 }) %]
[% END %]
[% INCLUDE menuItem title="Evaluate this jobset" uri="javascript:confirmEvaluateJobset()" %]
</div>
</li>
[% END %]
<li class="nav-item"><a class="nav-link active" href="#tabs-evaluations" data-toggle="tab">Evaluations</a></li>
[% IF jobset.has_error || jobset.fetcherrormsg %]
<li class="nav-item"><a class="nav-link" href="#tabs-errors" data-toggle="tab"><span class="text-warning">Evaluation Errors</span></a></li>
[% END %]
<li class="nav-item"><a class="nav-link" href="#tabs-jobs" data-toggle="tab">Jobs</a></li>
<li class="nav-item"><a class="nav-link" href="#tabs-configuration" data-toggle="tab">Configuration</a></li>
<li class="nav-item"><a class="nav-link" href="#tabs-links" data-toggle="tab">Links</a></li>
<li class="nav-item"><a class="nav-link" href="#tabs-channels" data-toggle="tab">Channels</a></li>
</ul>
<div id="generic-tabs" class="tab-content">
<div id="tabs-evaluations" class="tab-pane active">
<table class="info-table">
<tr>
<th>Last checked:</th>
<td>
[% IF jobset.lastcheckedtime %]
[% INCLUDE renderDateTime timestamp = jobset.lastcheckedtime %], [% IF jobset.has_error || jobset.fetcherrormsg %]<em class="text-warning">with errors!</em>[% ELSE %]<em>no errors</em>[% END %]
[% ELSE %]
<em>never</em>
[% END %]
</td>
</tr>
<tr>
<th>Last evaluation:</th>
<td>
[% IF latestEval %]
[% INCLUDE renderDateTime timestamp = latestEval.timestamp %]
(took [% relativeDuration (latestEval.checkouttime + latestEval.evaltime) %])
[% ELSE %]
<em>never</em>
[% END %]
</td>
</tr>
[% IF jobset.starttime %]
<tr>
<th>Evaluation running since:</th>
<td>[% INCLUDE renderRelativeDate timestamp = jobset.starttime %]</td>
</tr>
[% ELSIF jobset.triggertime %]
<tr>
<th>Evaluation pending since:</th>
<td>[% INCLUDE renderRelativeDate timestamp = jobset.triggertime %]</td>
</tr>
[% END %]
</table>
<br/>
[% IF evals.size() > 0 %]
[% INCLUDE renderEvals linkToAll=c.uri_for(c.controller('Jobset').action_for('evals'), [project.name, jobset.name]) %]
[% END %]
</div>
[% IF jobset.has_error || jobset.fetcherrormsg %]
<div id="tabs-errors" class="tab-pane">
<iframe src="[% c.uri_for('/jobset' project.name jobset.name "errors") %]" loading="lazy" frameBorder="0" width="100%"></iframe>
</div>
[% END %]
<div id="tabs-configuration" class="tab-pane">
<table class="info-table">
<tr>
<th>State:</th>
<td>[% IF jobset.enabled == 0; "Disabled"; ELSIF jobset.enabled == 1; "Enabled"; ELSIF jobset.enabled == 2; "One-shot"; ELSIF jobset.enabled == 3; "One-at-a-time"; END %]</td>
</tr>
<tr>
<th>Description:</th>
<td>[% HTML.escape(jobset.description) %]</td>
</tr>
[% IF jobset.type == 1 %]
<tr>
<th>Flake URI:</th>
<td>
<tt>[% HTML.escape(jobset.flake) %]</tt>
</td>
</tr>
[% END %]
[% IF jobset.type == 0 %]
<tr>
<th>Nix expression:</th>
<td>
<tt>[% HTML.escape(jobset.nixexprpath) %]</tt> in input
<tt>[% HTML.escape(jobset.nixexprinput) %]</tt>
</td>
</tr>
[% END %]
<tr>
<th>Check interval:</th>
<td>[% jobset.checkinterval || "<em>disabled</em>" %]</td>
</tr>
<tr>
<th>Scheduling shares:</th>
<td>[% jobset.schedulingshares %] [% IF totalShares %] ([% f = format("%.2f"); f(jobset.schedulingshares / totalShares * 100) %]% out of [% totalShares %] shares)[% END %]</td>
</tr>
<tr>
<th>Enable Dynamic RunCommand Hooks:</th>
<td>[% c.config.dynamicruncommand.enable ? project.enable_dynamic_run_command ? jobset.enable_dynamic_run_command ? "Yes" : "No (not enabled by jobset)" : "No (not enabled by project)" : "No (not enabled by server)" %]</td>
</tr>
[% IF emailNotification %]
<tr>
<th>Enable email notification:</th>
<td>[% jobset.enableemail ? "Yes" : "No" %]</td>
</tr>
<tr>
<th>Email override:</th>
<td>[% HTML.escape(jobset.emailoverride) %]</td>
</tr>
[% END %]
<tr>
<th>Number of evaluations to keep:</th>
<td>[% jobset.keepnr %]</td>
</tr>
</table>
[% IF jobset.type == 0 %]
[% INCLUDE renderJobsetInputs %]
[% END %]
</div>
[% INCLUDE makeLazyTab tabName="tabs-jobs" uri=c.uri_for('/jobset' project.name jobset.name "jobs-tab") %]
<div id="tabs-links" class="tab-pane">
<ul>
<li><a href="[% c.uri_for(c.controller('Jobset').action_for('latest_eval'), c.req.captures) %]">Latest finished evaluation</a></li>
</ul>
</div>
[% INCLUDE makeLazyTab tabName="tabs-channels" uri=c.uri_for('/jobset' project.name jobset.name "channels-tab") %]
</div>
<script>
function confirmEvaluateJobset() {
bootbox.confirm(
'Are you sure you want to force evaluation of this jobset?',
function(c) {
if (!c) return;
requestJSON({
url: "[% HTML.escape(c.uri_for('/api/push', { jobsets = project.name _ ':' _ jobset.name, force = "1" })) %]",
type: 'POST',
success: function(data) {
bootbox.alert("The jobset has been scheduled for evaluation.");
}
});
});
};
function deleteJobset() {
bootbox.confirm(
'Are you sure you want to delete this jobset?',
function(c) {
if (!c) return;
redirectJSON({
url: "[% c.uri_for(c.controller('Jobset').action_for('jobset'), c.req.captures) %]",
type: 'DELETE'
});
});
};
</script>
[% END %]