Skip to content

Commit 7a7f413

Browse files
committed
[#87692] protoplaster: api, webui: Allow to open artifacts
Signed-off-by: Andrii Chmutov <[email protected]>
1 parent c6b430a commit 7a7f413

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

protoplaster/api/v1/test_runs.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,8 @@ def fetch_artifact(identifier: str, artifact_name: str):
392392
if not os.path.isfile(artifact_path):
393393
return jsonify({"error": "Artifact file not found"}), 404
394394

395+
as_attachment = request.args.get("preview") != "true"
395396
return send_from_directory(os.path.abspath(
396397
os.path.join(artifacts_dir, identifier)),
397398
artifact_name,
398-
as_attachment=True)
399+
as_attachment=as_attachment)

protoplaster/webui/templates/runs.html

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,12 @@ <h6>Artifacts</h6>
203203
const modal = document.getElementById('triggerTestRunModal');
204204
modal.addEventListener('show.bs.modal', updateConfigList);
205205

206+
function canArtifactOpen(contentType) {
207+
return contentType === "application/json"
208+
|| contentType === "application/pdf"
209+
|| ["text", "image", "audio", "video"].includes(contentType.split("/")[0]);
210+
}
211+
206212
// Trigger run form
207213
document.getElementById('triggerRunForm').addEventListener('submit', async (e) => {
208214
e.preventDefault();
@@ -246,15 +252,33 @@ <h6>Artifacts</h6>
246252
const artifactList = document.getElementById('artifact-list');
247253
artifactList.innerHTML = '';
248254
if (data_art && data_art.length > 0) {
249-
data_art.forEach(artifact => {
255+
const contentTypes = await Promise.all(data_art.map(async (artifact) => {
256+
const url = `/api/v1/test-runs/${id}/artifacts/${encodeURIComponent(artifact.name)}`;
257+
return [url, await fetch(url, { method: 'HEAD' })
258+
.then(r => r.ok && r.headers.get('Content-Type'))
259+
.catch(console.error)]
260+
}));
261+
data_art.forEach((artifact, i) => {
262+
const [url, contentType] = contentTypes[i];
250263
const li = document.createElement('li');
251264
li.className = 'list-group-item d-flex justify-content-between align-items-center';
252265
li.textContent = artifact.name;
253-
const a = document.createElement('a');
254-
a.href = `/api/v1/test-runs/${id}/artifacts/${encodeURIComponent(artifact.name)}`;
255-
a.className = 'btn btn-sm btn-outline-primary';
256-
a.textContent = 'Download';
257-
li.appendChild(a);
266+
const buttons = document.createElement('div');
267+
const buttonClasses = 'btn btn-sm btn-outline-primary';
268+
if (contentType && canArtifactOpen(contentType)) {
269+
const openButton = document.createElement('a');
270+
openButton.href = `${url}?preview=true`;
271+
openButton.className = buttonClasses;
272+
openButton.textContent = 'Open';
273+
openButton.style["margin-right"] = '1em';
274+
buttons.appendChild(openButton);
275+
}
276+
const downloadButton = document.createElement('a');
277+
downloadButton.href = url;
278+
downloadButton.className = buttonClasses;
279+
downloadButton.textContent = 'Download';
280+
buttons.appendChild(downloadButton);
281+
li.appendChild(buttons)
258282
artifactList.appendChild(li);
259283
});
260284
} else {

0 commit comments

Comments
 (0)