Un custom widget minimal pour afficher une pièce jointe de type image dans une vue personnalisée.
Le code :
js :
document.addEventListener("DOMContentLoaded", function () {
const contentEl = document.getElementById("content");
const properUrlEl = document.getElementById("properUrl");
const shortUrlEl = document.getElementById("shortUrl");
let properUrl = "";
let attachmentName = "";
let id = 0;
let token = "";
let baseUrl = "";
grist.ready({ requiredAccess: "full" });
grist.onRecord((record) => {
attachmentName = record.Nom_PJ || "piece_jointe";
id = record.PJ?.[0] || 0;
contentEl.textContent = attachmentName;
updateUrls();
});
grist.docApi.getAccessToken({ readOnly: true }).then((response) => {
token = response.token;
baseUrl = response.baseUrl;
updateUrls();
});
function updateUrls() {
if (!baseUrl || !id) return;
// Lien principal : avec nom du fichier dans l’URL
properUrl = `${baseUrl}/attachments/${id}/${encodeURIComponent(attachmentName)}?auth=${token}`
.replace("0.0.0.0", "localhost");
// Afficher le lien complet
properUrlEl.textContent = properUrl;
properUrlEl.href = "#";
// Afficher le lien court sous forme du nom du fichier cliquable
shortUrlEl.textContent = attachmentName;
shortUrlEl.href = "#";
shortUrlEl.style.color = "#2d68f0";
shortUrlEl.style.textDecoration = "underline";
shortUrlEl.style.cursor = "pointer";
}
// Téléchargement manuel (sinon bloqués car iframe sandboxée)
function triggerDownload(url, filename) {
fetch(url)
.then((res) => res.blob())
.then((blob) => {
const blobUrl = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = blobUrl;
a.download = filename || "piece_jointe";
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(blobUrl);
})
.catch((err) => console.error("Erreur de téléchargement :", err));
}
// Clic sur le lien complet
properUrlEl.addEventListener("click", (e) => {
e.preventDefault();
if (properUrl) triggerDownload(properUrl, attachmentName);
});
// Clic sur le lien court (nom du fichier)
shortUrlEl.addEventListener("click", (e) => {
e.preventDefault();
if (properUrl) triggerDownload(properUrl, attachmentName);
});
});
html :
<!DOCTYPE html>
<html lang="">
<head>
<script src="https://docs.getgrist.com/grist-plugin-api.js"></script>
<style>
/* Reset and base styles */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.5;
color: #24292f;
background-color: #ffffff;
padding: 16px;
}
div {
margin: 30px;
}
</style>
<title></title>
</head>
<body>
<div class="group">
<div>
<strong>Nom de la PJ</strong> :
<p id="content"></p>
</div>
<div>
<strong>Lien complet</strong> :
<a id="properUrl"></a>
</div>
<div>
<strong>Lien court (nom de la PJ)</strong> :
<a id="shortUrl"></a>
</div>
</div>
</body>
</html>
Lien du document : Ex - afficher PJ / charger PJ / télécharger PJ - Grist
