File indexing completed on 2026-06-13 08:42:18
0001 {% extends 'base.html' %}
0002
0003 {% block title %}{{ task.name }} - Prod Task - PCS{% endblock %}
0004
0005 {% block content %}
0006 <div class="container-fluid mt-4">
0007 <nav aria-label="breadcrumb">
0008 <ol class="breadcrumb">
0009 <li class="breadcrumb-item"><a href="{% url 'pcs:pcs_hub' %}">PCS</a></li>
0010 <li class="breadcrumb-item"><a href="{% url 'pcs:prod_task_compose' %}?tab=tasks">Prod Tasks</a></li>
0011 <li class="breadcrumb-item active">{{ task.name }}</li>
0012 </ol>
0013 </nav>
0014
0015 <div class="d-flex justify-content-between align-items-start mb-3">
0016 <div>
0017 <h2>{{ task.name }}</h2>
0018 <p class="text-muted">
0019 <span class="badge bg-{% if task.status == 'draft' %}secondary{% elif task.status == 'ready' %}primary{% elif task.status == 'submitted' %}info{% elif task.status == 'completed' %}success{% else %}danger{% endif %}">{{ task.status }}</span>
0020 Created by {{ task.created_by }} on {{ task.created_at|date:"Y-m-d H:i" }}
0021 {% if task.updated_at != task.created_at %} | Updated {{ task.updated_at|date:"Y-m-d H:i" }}{% endif %}
0022 </p>
0023 </div>
0024 <div>
0025 <a href="{% url 'pcs:prod_task_compose' %}?tab=tasks&selected={{ task.name|urlencode }}" class="btn btn-dark-green btn-sm">Edit in Compose</a>
0026 <button class="btn btn-secondary btn-sm" id="btn-regen">Regenerate Commands</button>
0027 </div>
0028 </div>
0029
0030 {% if task.description %}
0031 <p>{{ task.description }}</p>
0032 {% endif %}
0033
0034 <div class="row">
0035 <div class="col-md-6 mb-3">
0036 <div class="card h-100">
0037 <div class="card-body">
0038 <h5 class="card-title">Dataset</h5>
0039 <table class="table table-sm table-bordered mb-0">
0040 <tr><td style="width:40%"><strong>Name</strong></td><td><a href="{% url 'pcs:dataset_detail' pk=task.dataset.pk %}">{{ task.dataset.dataset_name }}</a></td></tr>
0041 <tr><td><strong>DID</strong></td><td><code>{{ task.dataset.did }}</code></td></tr>
0042 <tr><td><strong>Detector Version</strong></td><td>{{ task.dataset.detector_version }}</td></tr>
0043 <tr><td><strong>Detector Config</strong></td><td>{{ task.dataset.detector_config }}</td></tr>
0044 </table>
0045 </div>
0046 </div>
0047 </div>
0048 <div class="col-md-6 mb-3">
0049 <div class="card h-100">
0050 <div class="card-body">
0051 <h5 class="card-title">Production Config</h5>
0052 <table class="table table-sm table-bordered mb-0">
0053 <tr><td style="width:40%"><strong>Name</strong></td><td><a href="{% url 'pcs:prod_config_detail' pk=task.prod_config.pk %}">{{ task.prod_config.name }}</a></td></tr>
0054 <tr><td><strong>JUG_XL Tag</strong></td><td>{{ task.prod_config.jug_xl_tag|default:"-" }}</td></tr>
0055 <tr><td><strong>Container</strong></td><td><code>{{ task.prod_config.container_image|default:"-" }}</code></td></tr>
0056 <tr><td><strong>BG Mixing</strong></td><td>{% if task.prod_config.bg_mixing %}Yes{% else %}No{% endif %}</td></tr>
0057 </table>
0058 </div>
0059 </div>
0060 </div>
0061 </div>
0062
0063 <div class="card mb-3">
0064 <div class="card-body">
0065 <h5 class="card-title">Tags</h5>
0066 <table class="table table-sm table-bordered">
0067 <thead><tr><th>Type</th><th>Tag</th><th>Description</th><th>Key Parameters</th></tr></thead>
0068 <tbody>
0069 <tr>
0070 <td>Physics</td>
0071 <td><a href="{% url 'pcs:tag_compose' tag_type='p' %}?selected={{ task.dataset.physics_tag.tag_label|urlencode }}">{{ task.dataset.physics_tag.tag_label }}</a></td>
0072 <td>{{ task.dataset.physics_tag.description|truncatewords:10 }}</td>
0073 <td>{% for k, v in task.dataset.physics_tag.parameters.items %}<code>{{ k }}</code>={{ v }}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
0074 </tr>
0075 <tr>
0076 <td>EvGen</td>
0077 <td><a href="{% url 'pcs:tag_compose' tag_type='e' %}?selected={{ task.dataset.evgen_tag.tag_label|urlencode }}">{{ task.dataset.evgen_tag.tag_label }}</a></td>
0078 <td>{{ task.dataset.evgen_tag.description|truncatewords:10 }}</td>
0079 <td>{% for k, v in task.dataset.evgen_tag.parameters.items %}<code>{{ k }}</code>={{ v }}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
0080 </tr>
0081 <tr>
0082 <td>Simulation</td>
0083 <td><a href="{% url 'pcs:tag_compose' tag_type='s' %}?selected={{ task.dataset.simu_tag.tag_label|urlencode }}">{{ task.dataset.simu_tag.tag_label }}</a></td>
0084 <td>{{ task.dataset.simu_tag.description|truncatewords:10 }}</td>
0085 <td>{% for k, v in task.dataset.simu_tag.parameters.items %}<code>{{ k }}</code>={{ v }}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
0086 </tr>
0087 <tr>
0088 <td>Reconstruction</td>
0089 <td><a href="{% url 'pcs:tag_compose' tag_type='r' %}?selected={{ task.dataset.reco_tag.tag_label|urlencode }}">{{ task.dataset.reco_tag.tag_label }}</a></td>
0090 <td>{{ task.dataset.reco_tag.description|truncatewords:10 }}</td>
0091 <td>{% for k, v in task.dataset.reco_tag.parameters.items %}<code>{{ k }}</code>={{ v }}{% if not forloop.last %}, {% endif %}{% endfor %}</td>
0092 </tr>
0093 </tbody>
0094 </table>
0095 </div>
0096 </div>
0097
0098 <div class="card mb-3">
0099 <div class="card-body">
0100 <h5 class="card-title">Dataset Roles</h5>
0101 <p class="text-muted mb-2" style="font-size: 0.9em;">
0102 Lists derived from <code>overrides.{input,output,intermediate}_dataset_dids</code>
0103 (JSON, no schema column). Output falls back to the legacy single
0104 <code>dataset</code> FK when no override is set.
0105 </p>
0106 {% if task.output_datasets %}
0107 <h6 class="mt-2">Output</h6>
0108 <table class="table table-sm table-bordered mb-3">
0109 <thead><tr><th style="width:35%">Name</th><th>DID</th><th>Source</th></tr></thead>
0110 <tbody>
0111 {% for ds in task.output_datasets %}
0112 <tr>
0113 <td><a href="{% url 'pcs:dataset_detail' pk=ds.pk %}">{{ ds.dataset_name }}</a></td>
0114 <td><code>{{ ds.did }}</code></td>
0115 <td>{% if ds.source_kind %}<code>{{ ds.source_kind }}</code> {{ ds.source_location }}{% else %}-{% endif %}</td>
0116 </tr>
0117 {% endfor %}
0118 </tbody>
0119 </table>
0120 {% endif %}
0121 {% if task.input_datasets %}
0122 <h6 class="mt-2">Input</h6>
0123 <table class="table table-sm table-bordered mb-3">
0124 <thead><tr><th style="width:35%">Name</th><th>DID</th><th>Source</th></tr></thead>
0125 <tbody>
0126 {% for ds in task.input_datasets %}
0127 <tr>
0128 <td><a href="{% url 'pcs:dataset_detail' pk=ds.pk %}">{{ ds.dataset_name }}</a></td>
0129 <td><code>{{ ds.did }}</code></td>
0130 <td>{% if ds.source_kind %}<code>{{ ds.source_kind }}</code> {{ ds.source_location }}{% else %}-{% endif %}</td>
0131 </tr>
0132 {% endfor %}
0133 </tbody>
0134 </table>
0135 {% endif %}
0136 {% if task.intermediate_datasets %}
0137 <h6 class="mt-2">Intermediate</h6>
0138 <table class="table table-sm table-bordered mb-3">
0139 <thead><tr><th style="width:35%">Name</th><th>DID</th><th>Source</th></tr></thead>
0140 <tbody>
0141 {% for ds in task.intermediate_datasets %}
0142 <tr>
0143 <td><a href="{% url 'pcs:dataset_detail' pk=ds.pk %}">{{ ds.dataset_name }}</a></td>
0144 <td><code>{{ ds.did }}</code></td>
0145 <td>{% if ds.source_kind %}<code>{{ ds.source_kind }}</code> {{ ds.source_location }}{% else %}-{% endif %}</td>
0146 </tr>
0147 {% endfor %}
0148 </tbody>
0149 </table>
0150 {% endif %}
0151 {% if task.input_source_location and not task.input_datasets %}
0152 <h6 class="mt-2">Input Source (legacy)</h6>
0153 <table class="table table-sm table-bordered mb-0">
0154 <tr><td style="width:30%"><strong>Kind</strong></td><td><code>{{ task.input_source_kind }}</code></td></tr>
0155 <tr><td><strong>Location</strong></td><td><code>{{ task.input_source_location }}</code></td></tr>
0156 </table>
0157 {% endif %}
0158 </div>
0159 </div>
0160
0161 {% if task.csv_file %}
0162 <div class="card mb-3">
0163 <div class="card-body">
0164 <h5 class="card-title">Submission (legacy)</h5>
0165 <table class="table table-sm table-bordered">
0166 <tr><td style="width:30%"><strong>CSV File</strong></td><td><code>{{ task.csv_file }}</code></td></tr>
0167 </table>
0168 </div>
0169 </div>
0170 {% endif %}
0171
0172 {% if task.overrides %}
0173 <div class="card mb-3">
0174 <div class="card-body">
0175 <h5 class="card-title">Overrides</h5>
0176 <table class="table table-sm table-bordered mb-0">
0177 {% for key, value in task.overrides.items %}
0178 <tr><td style="width:40%"><strong>{{ key }}</strong></td><td><code>{{ value }}</code></td></tr>
0179 {% endfor %}
0180 </table>
0181 </div>
0182 </div>
0183 {% endif %}
0184
0185 {% if task.condor_command %}
0186 <div class="card mb-3">
0187 <div class="card-body">
0188 <div class="d-flex justify-content-between align-items-center mb-2">
0189 <h5 class="card-title mb-0">Condor Command</h5>
0190 <button class="btn btn-secondary btn-sm btn-copy" data-target="condor-cmd">Copy</button>
0191 </div>
0192 <pre id="condor-cmd" class="bg-dark text-light p-3 mb-0" style="font-size: 0.8em; white-space: pre-wrap; word-break: break-all;">{{ task.condor_command }}</pre>
0193 </div>
0194 </div>
0195 {% endif %}
0196
0197 {% if task.panda_command %}
0198 <div class="card mb-3">
0199 <div class="card-body">
0200 <div class="d-flex justify-content-between align-items-center mb-2">
0201 <h5 class="card-title mb-0">PanDA Command</h5>
0202 <button class="btn btn-secondary btn-sm btn-copy" data-target="panda-cmd">Copy</button>
0203 </div>
0204 <pre id="panda-cmd" class="bg-dark text-light p-3 mb-0" style="font-size: 0.8em; white-space: pre-wrap; word-break: break-all;">{{ task.panda_command }}</pre>
0205 </div>
0206 </div>
0207 {% endif %}
0208
0209 {% if task_params_json %}
0210 <div class="card mb-3">
0211 <div class="card-body">
0212 <div class="d-flex justify-content-between align-items-center mb-2">
0213 <h5 class="card-title mb-0">JEDI taskParamMap</h5>
0214 <button class="btn btn-secondary btn-sm btn-copy" data-target="task-params">Copy</button>
0215 </div>
0216 <div class="text-muted mb-2" style="font-size: 0.85em;">
0217 Computed from current PCS state. Passed to <code>Client.insertTaskParams()</code> for JEDI submission.
0218 </div>
0219 <pre id="task-params" class="bg-dark text-light p-3 mb-0" style="font-size: 0.8em; white-space: pre-wrap;">{{ task_params_json }}</pre>
0220 </div>
0221 </div>
0222 {% elif task_params_error %}
0223 <div class="alert alert-warning mb-3">
0224 <strong>JEDI taskParamMap unavailable:</strong> {{ task_params_error }}
0225 </div>
0226 {% endif %}
0227
0228 {% if task.panda_task_id or task.condor_cluster_id %}
0229 <div class="card mb-3">
0230 <div class="card-body">
0231 <h5 class="card-title">Tracking</h5>
0232 <table class="table table-sm table-bordered">
0233 {% if task.panda_task_id %}<tr><td><strong>PanDA Task ID</strong></td><td>{{ task.panda_task_id }}</td></tr>{% endif %}
0234 {% if task.condor_cluster_id %}<tr><td><strong>Condor Cluster ID</strong></td><td>{{ task.condor_cluster_id }}</td></tr>{% endif %}
0235 </table>
0236 </div>
0237 </div>
0238 {% endif %}
0239 </div>
0240
0241 <script>
0242 document.querySelectorAll('.btn-copy').forEach(btn => {
0243 btn.addEventListener('click', function() {
0244 const pre = document.getElementById(this.dataset.target);
0245 navigator.clipboard.writeText(pre.textContent).then(() => {
0246 this.textContent = 'Copied!';
0247 setTimeout(() => { this.textContent = 'Copy'; }, 1500);
0248 });
0249 });
0250 });
0251 document.getElementById('btn-regen').addEventListener('click', function() {
0252 fetch('{% url "pcs:prod_task_generate_commands" pk=task.pk %}')
0253 .then(r => r.json())
0254 .then(data => { location.reload(); });
0255 });
0256 </script>
0257 {% endblock %}