Comme c’est bientôt Noël, je vous propose un tutoriel pour apprendre à utiliser le Custom Widget Builder en buvant un petit chocolat chaud ! Si vous suivez toutes ces étapes vous pourrez créer le dashboard du Père Noël.
Si vous préférez voir directement le résultat (et que vous avez accès aux templates de la DINUM) c’est par là ![]()

Et puisque tout ce qui compte à Noël ce sont les
je vous partage le guide pour modifier le contenu et l’apparence de la fiche commande en bas de ce post.
Création de la table
- Créez un nouveau document Grist
- Renommez la table en « Commandes_Noel »
- Créez les champs suivants :
id_commande
nom_enfant
type_commande (type Choix unique)
statut_commande (type Choix unique)
date_reception (type Date)
date_maj (type Date)
zone_livraison (type Choix unique)
delai_livraison
moyen_transport (type Choice)
equipe_lutins
lutin_responsable
lutin_assistant
renne_assigne (type Choix unique)
budget_matieres (type Numérique)
budget_lutins (type Numérique)
budget_total (type formule : budget_matieres +budget_lutins)
notes_budget
alerte_budget
niveau_sagesse (type Choix unique)
points_bonus (type Numérique)
priorite_livraison (type Choix unique)
- Pour chaque champ Choix unique copiez les options suivantes :
type_commande :
Cadeau simple
Jouet électronique
Livre/Culture
Peluche/Doudou
Jeu d’extérieur
Activité créative
statut_commande :
Lettre reçue
En cours d’étude
En fabrication
En test qualité
Prêt pour emballage
Prêt pour livraison
Livré
niveau_sagesse :
Très sage
Sage
Quelques bêtises
À surveiller
zone_livraison :
Pôle Nord
Europe
Amériques
Asie-Pacifique
moyen_transport :
Traîneau standard
Traîneau supersonique
Mini-traîneau héliporté
Renne solo
renne_assigne :
Oui
Non
priorite_livraison :
Ultra prioritaire
Très prioritaire
Priorité normale
Non urgent
Configuration du Widget
- Cliquez sur « Nouveau »
- Ajoutez une vue à la page : Personnalisée
- Liez le widget à la table « Commandes_Noel »
- Sélectionnez le custom widget builder
- Cliquez sur « Ouvrir la configuration »
- Dans l’onglet HTML, supprimez le code présent et collez celui-ci :
`
<!-- Ligne 2 : Référence + Type + État -->
<div class="flex items-center gap-4 text-left mb-3">
<div>
<span class="text-yellow-200">🎅</span>
<span id="id_commande" class="text-yellow-200 font-bold"></span>
</div>
<div>
<span class="text-yellow-200"></span>
<span id="type_commande" class="px-3 py-1 rounded-md text-sm font-medium"></span>
</div>
<div>
<span class="text-yellow-200"></span>
<span id="statut_commande" class="px-3 py-1 rounded-md text-sm font-medium"></span>
</div>
</div>
<!-- Ligne 3 : Atelier + Zone + Délai -->
<div class="mt-2 pt-2 border-t border-yellow-300">
<div class="grid grid-cols-3 gap-4 mb-3">
<div>
<span class="text-yellow-200">🏭 Atelier</span>
<div id="equipe_lutins" class="font-medium"></div>
</div>
<div>
<span class="text-yellow-200">🌍 Zone de livraison</span>
<div id="zone_livraison" class="font-medium"></div>
</div>
<div class="text-right">
<span class="text-yellow-200">📅 Délai</span>
<div id="delai_livraison" class="font-medium"></div>
</div>
</div>
<!-- Dates en bas à droite -->
<div class="flex justify-end text-xs text-yellow-200/80">
<div class="text-right">
<div>Lettre reçue le <span id="date_reception"></span></div>
<div>Dernière mise à jour <span id="date_maj"></span></div>
</div>
</div>
</div>
</div>
<!-- Section Budget -->
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
<h2 class="text-lg font-semibold mb-4">✨ Budget Fabrication</h2>
<div class="grid grid-cols-2 gap-6">
<!-- Première colonne -->
<div class="space-y-2">
<div class="flex justify-between p-2 bg-green-50 rounded">
<span>Matières premières</span>
<span id="budget_matieres" class="font-extralight"></span>
</div>
<div class="flex justify-between p-2 bg-green-50 rounded">
<span>Main d'œuvre lutins</span>
<span id="budget_lutins" class="font-extralight"></span>
</div>
</div>
<!-- Deuxième colonne -->
<div class="space-y-3">
<div class="p-2 bg-green-50 rounded">
<div class="text-gray-600 mb-1">Notes spéciales :</div>
<div id="notes_budget" class="font-medium"></div>
</div>
</div>
</div>
<!-- Total fabrication -->
<div class="mt-2 pt-2 border-t border-[#1B4D3E]">
<div class="grid grid-cols-12 gap-4 items-center px-2">
<div class="col-span-3">
<span class="text-xl font-semibold">Budget total fabrication</span>
</div>
<div class="col-span-3 text-left">
<span id="budget_total" class="text-xl font-bold"></span>
</div>
<div class="col-span-6">
<span id="alerte_budget" class="text-sm text-red-500"></span>
</div>
</div>
</div>
</div>
<!-- Section Priorités -->
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
🎄 Priorités de livraison
</h2>
<div class="space-y-2">
<div class="p-2 bg-green-50 rounded">
<div class="text-sm text-gray-600 mb-1">Niveau priorité</div>
<div id="priorite_livraison" class="font-medium"></div>
</div>
<div class="p-2 bg-green-50 rounded">
<div class="text-sm text-gray-600 mb-1">Transport prévu</div>
<div id="moyen_transport" class="font-medium"></div>
</div>
</div>
</div>
<!-- Section Évaluation -->
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
😇 Évaluation Sagesse
</h2>
<div class="grid grid-cols-2 gap-6">
<div>
<div class="flex justify-between p-2 bg-green-50 rounded">
<span>Niveau de sagesse</span>
<span id="niveau_sagesse" class="font-medium"></span>
</div>
</div>
<div>
<div class="flex justify-between p-2 bg-green-50 rounded">
<span>Points bonus</span>
<span id="points_bonus" class="font-medium"></span>
</div>
</div>
</div>
</div>
<!-- Section Équipe Lutins -->
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
🧝♂️ Équipe Assignée
</h2>
<div class="grid grid-cols-2 gap-6">
<!-- Colonne Contacts -->
<div class="space-y-3">
<div class="p-3 bg-green-50 rounded-lg">
<div class="flex items-center gap-2">
🎅 <span class="text-gray-600">Lutin responsable :</span>
<span id="lutin_responsable" class="font-medium"></span>
</div>
</div>
<div class="p-3 bg-green-50 rounded-lg">
<div class="flex items-center gap-2">
🧝♀️ <span class="text-gray-600">Lutin assistant :</span>
<span id="lutin_assistant" class="font-medium"></span>
</div>
</div>
</div>
<!-- Colonne Renne -->
<div>
<div class="p-4 bg-red-50 rounded-lg">
<div class="flex items-center justify-between">
<span class="font-medium">Renne assigné</span>
<span id="renne_assigne" class="font-medium"></span>
</div>
</div>
</div>
</div>
</div>
<!-- Section Documents -->
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
📜 Documents
</h2>
<div class="grid grid-cols-2 gap-6">
<!-- Colonne 1 -->
<div class="space-y-3">
<div class="flex items-center gap-2 p-3 bg-green-50 rounded">
<span class="text-[#8B0000]">✉️</span>
<span>Lettre au Père Noël</span>
<span id="lettre_enfant" class="ml-2 px-2 py-1 text-xs rounded-full"></span>
</div>
<div class="flex items-center gap-2 p-3 bg-green-50 rounded">
<span class="text-[#8B0000]">🎨</span>
<span>Dessin</span>
<span id="dessin_enfant" class="ml-2 px-2 py-1 text-xs rounded-full"></span>
</div>
<div class="flex items-center gap-2 p-3 bg-green-50 rounded">
<span class="text-[#8B0000]">📋</span>
<span>Liste détaillée</span>
<span id="liste_cadeaux" class="ml-2 px-2 py-1 text-xs rounded-full"></span>
</div>
</div>
<!-- Colonne 2 -->
<div class="space-y-3">
<div class="flex items-center gap-2 p-3 bg-green-50 rounded">
<span class="text-[#8B0000]">📝</span>
<span>Notes des lutins</span>
<span id="notes_lutins" class="ml-2 px-2 py-1 text-xs rounded-full"></span>
</div>
<div class="flex items-center gap-2 p-3 bg-green-50 rounded">
<span class="text-[#8B0000]">⭐</span>
<span>Certificat de sagesse</span>
<span id="certificat_sagesse" class="ml-2 px-2 py-1 text-xs rounded-full"></span>
</div>
<div class="mt-6">
<a id="lien_dossier" href="#" target="_blank"
class="inline-flex items-center gap-2 px-4 py-2 bg-red-50 hover:bg-red-100 rounded transition-colors text-[#8B0000]">
🎄 <span class="underline">Voir dossier complet</span>
</a>
</div>
</div>
</div>
</div>
- Dans l’onglet JavaScript, supprimez le code existant et collez celui-ci :
function formatDate(date) {
if (!date) return '';
return new Date(date).toLocaleDateString('fr-FR', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
function formatMoney(amount) {
if (!amount) return '0 🎄';
return new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 0
}).format(amount).replace('€', '🎄');
}
function getStateColor(state) {
const stateColors = {
'Lettre reçue': 'bg-[#FFD700]',
'En cours d\'étude': 'bg-[#1B4D3E]',
'En fabrication': 'bg-[#8B0000]',
'En test qualité': 'bg-[#B8860B]',
'Prêt pour emballage': 'bg-[#228B22]',
'Prêt pour livraison': 'bg-[#4169E1]',
'Livré': 'bg-[#9B0000]'
};
return stateColors[state] || 'bg-[#FFD700]';
}
function getTypeColor(type) {
const typeColors = {
'Cadeau simple': 'bg-[#228B22]',
'Jouet électronique': 'bg-[#4169E1]',
'Livre/Culture': 'bg-[#8B4513]',
'Peluche/Doudou': 'bg-[#FF69B4]',
'Jeu d\'extérieur': 'bg-[#32CD32]',
'Activité créative': 'bg-[#FF8C00]'
};
return typeColors[type] || 'bg-[#FFD700]';
}
grist.ready({
requiredTables: ['Commandes_Noel']
});
grist.onRecord(function(record) {
if (!record) return;
// État de la commande
const etatElement = document.getElementById('statut_commande');
etatElement.textContent = record.statut_commande || '';
etatElement.className = 'px-3 py-1 rounded-full text-sm font-medium text-white ' + getStateColor(record.statut_commande);
// Type de commande
const typeElement = document.getElementById('type_commande');
typeElement.textContent = record.type_commande || '';
typeElement.className = 'px-3 py-1 rounded-full text-sm font-medium text-white ' + getTypeColor(record.type_commande);
// Bandeau
document.getElementById('id_commande').textContent = record.id_commande || '';
document.getElementById('nom_enfant').textContent = record.nom_enfant || '';
document.getElementById('equipe_lutins').textContent = record.equipe_lutins || '';
document.getElementById('zone_livraison').textContent = record.zone_livraison || '';
document.getElementById('delai_livraison').textContent = record.delai_livraison || '';
document.getElementById('date_reception').textContent = formatDate(record.date_reception);
document.getElementById('date_maj').textContent = formatDate(record.date_maj);
// Priorités
document.getElementById('priorite_livraison').textContent = record.priorite_livraison || '';
document.getElementById('moyen_transport').textContent = record.moyen_transport || '';
// Budget
document.getElementById('budget_matieres').textContent = formatMoney(record.budget_matieres);
document.getElementById('budget_lutins').textContent = formatMoney(record.budget_lutins);
document.getElementById('notes_budget').textContent = record.notes_budget || 'Aucune note';
document.getElementById('budget_total').textContent = formatMoney(record.budget_total);
document.getElementById('alerte_budget').textContent = record.alerte_budget || '';
// Évaluation sagesse
document.getElementById('niveau_sagesse').textContent = record.niveau_sagesse || '';
document.getElementById('points_bonus').textContent = record.points_bonus || '';
// Équipe
const renneElement = document.getElementById('renne_assigne');
const renneValue = record.renne_assigne;
if (renneValue === 'Oui') {
renneElement.textContent = '✅ Assigné';
renneElement.className = 'font-medium text-green-600';
} else {
renneElement.textContent = '❌ Non assigné';
renneElement.className = 'font-medium text-red-600';
}
document.getElementById('lutin_responsable').textContent = record.lutin_responsable || '';
document.getElementById('lutin_assistant').textContent = record.lutin_assistant || '';
// Documents
['lettre_enfant', 'dessin_enfant', 'liste_cadeaux', 'notes_lutins', 'certificat_sagesse'].forEach(id => {
const element = document.getElementById(id);
if (element) {
if (record[id]) {
element.textContent = 'Document présent';
element.className = 'ml-2 px-2 py-1 text-xs rounded-full bg-green-100 text-green-800';
} else {
element.textContent = 'Manquant';
element.className = 'ml-2 px-2 py-1 text-xs rounded-full bg-red-100 text-red-800';
}
}
});
// Lien dossier
const lienElement = document.getElementById('lien_dossier');
if (record.lien_dossier) {
lienElement.href = record.lien_dossier || '#';
lienElement.target = '_blank';
}
});
- Cliquez sur « Preview » et enregistrez
Test avec données d’exemple
Copiez ces 10 lignes dans votre table (disponible dans les commentaires ci-dessous).
1 Emma Dubois 🎮 Jouet électronique 📝 Lettre reçue 2023-12-01 2023-12-02 🌍 Europe Urgent 🛷 Traîneau standard Atelier high-tech Pixel Micro Oui 250 150 400 Budget standard Aucune 😇 Très sage 5 ⭐ Ultra prioritaire
2 Lucas Martin 📚 Livre/Culture 🏭 En fabrication 2023-12-02 2023-12-03 🌎 Amériques Normal ✈️ Traîneau supersonique Atelier culture Story Read Non 120 80 200 Budget réduit Aucune 😊 Sage 3 💫 Non urgent
3 Sofia Patel 🚲 Jeu d'extérieur ✨ En test qualité 2023-12-01 2023-12-04 🌏 Asie-Pacifique Urgent 🚁 Mini-traîneau héliporté Atelier jouets bois Sport Active Non 290 160 450 Matériaux spéciaux Attention au délai 😐 Quelques bêtises 2 ✨ Priorité normale
4 Amir Hassan 🎨 Activité créative 🛷 Prêt pour livraison 2023-12-02 2023-12-05 🌍 Europe Normal 🦌 Renne solo Atelier créatif Create Make Oui 180 120 300 RAS Aucune 😇 Très sage 4 🌟 Très prioritaire
5 Léa Chen 🎮 Jouet électronique 👀 En cours d'étude 2023-12-03 2023-12-04 🌏 Asie-Pacifique Urgent ✈️ Traîneau supersonique Atelier high-tech Tech Code Non 200 150 350 Budget majoré Aucune 😊 Sage 3 ⭐ Ultra prioritaire
6 Mohamed Dubois 🧸 Peluche/Doudou 🏭 En fabrication 2023-12-01 2023-12-05 🌍 Europe Normal 🛷 Traîneau standard Atelier peluches Soft Cuddle Oui 300 200 500 Matériaux rares Attention budget 😐 Quelques bêtises 2 ✨ Priorité normale
7 Julie N'Guyen 📚 Livre/Culture 📝 Lettre reçue 2023-12-02 2023-12-03 🌍 Afrique Urgent 🚁 Mini-traîneau héliporté Atelier culture Book Write Non 280 180 460 RAS Aucune 😇 Très sage 5 🌟 Très prioritaire
8 Thomas Lee 🚲 Jeu d'extérieur ✨ En test qualité 2023-12-03 2023-12-05 🌏 Asie-Pacifique Normal 🦌 Renne solo Atelier jouets bois Build Craft Oui 150 100 250 Budget standard Aucune 😊 Sage 3 💫 Non urgent
9 Maria Garcia 🎨 Activité créative 🛷 Prêt pour livraison 2023-12-01 2023-12-04 🌎 Amériques Urgent ✈️ Traîneau supersonique Atelier créatif Art Paint Non 110 70 180 RAS Aucune 😇 Très sage 4 ⭐ Ultra prioritaire
10 Yuki Tanaka 🎮 Jouet électronique 👀 En cours d'étude 2023-12-02 2023-12-03 🌏 Asie-Pacifique Normal 🛷 Traîneau standard Atelier high-tech Robot Circuit Oui 160 110 270 Budget réduit Aucune 😐 Quelques bêtises 2 ✨ Priorité normale
Si tout est bien configuré, vous devriez voir apparaître le dashboard de Noël ! Mais, bien sûr cet exemple n’est qu’un pretexte, vous pouvez adapter ce format d’affichage à vos besoins.
Personnalisation
Modifier les couleurs
Fond principal
<body class="bg-[#C41E3A] min-h-screen">
Changez #C41E3A pour une autre couleur
Bandeau supérieur
<div class="bg-gradient-to-r from-[#7BBF6A] to-[#016936] rounded-lg">
Modifiez #7BBF6A et #016936 pour changer le dégradé
Sections
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
#F9F9F9: fond des sections#1B4D3E: couleur du texte#B8860B: couleur des bordures
Ajouter une section
- Copiez ce template :
<div class="bg-[#F9F9F9] rounded-lg shadow p-4 mt-4 text-[#1B4D3E] border-2 border-[#B8860B]">
<h2 class="text-lg font-semibold mb-4 flex items-center gap-2">
🎄 Titre Section
</h2>
<div class="grid grid-cols-2 gap-6">
<div class="p-2 bg-green-50 rounded">
<span>Label</span>
<span id="nom_champ" class="font-medium"></span>
</div>
</div>
</div>
- Ajoutez dans le JavaScript :
document.getElementById('nom_champ').textContent = record.nom_champ || '';
Supprimer une section
- Identifiez la section dans le HTML (entre
<div class="bg-[#F9F9F9]...">et son</div>correspondant) - Supprimez tout le bloc
- Supprimez les références correspondantes dans le JavaScript
Modifier les icônes
Cherchez les emojis (
,
, etc.) et remplacez-les par d’autres
Format des données
Les dates utilisent :
formatDate(record.date)
Les montants utilisent :
formatMoney(record.montant)
Statuts et couleurs
Modifiez les couleurs des statuts dans le JavaScript :
function getStateColor(state) {
const stateColors = {
'Statut 1': 'bg-[#COULEUR]',
// etc.
};
}
Personnalisations avancées
Modification des tableaux de données
<div class="grid grid-cols-2 gap-6">
grid-cols-2: nombre de colonnes (1-12)gap-6: espacement entre éléments (1-12)
Styles de cartes
<div class="p-4 bg-green-50 rounded-lg">
p-4: padding (1-12)rounded-lg: arrondis (sm, md, lg, full)bg-green-50: intensité couleur (50-900)
Typographie
<span class="text-lg font-semibold text-gray-600">
text-lg: taille (sm, base, lg, xl, 2xl…)font-semibold: graisse (light, normal, medium, bold…)text-gray-600: couleur texte
Effets visuels
<div class="shadow hover:shadow-lg transition-all">
shadow: ombre (sm, md, lg, xl)hover:: effet au survoltransition-all: animation
Styles d’alertes
<div class="bg-red-100 text-red-800 p-2 rounded">
- Rouge : erreur
- Jaune : alerte
- Vert : succès
- Bleu : info
Badges et états
<span class="px-2 py-1 text-xs rounded-full">
Modifiez :
- Couleurs :
bg-[#COULEUR] - Taille :
text-xs,text-sm - Padding :
px-2,py-1
Espacements dynamiques
<div class="space-y-3">
space-y-3: vertical (1-12)space-x-3: horizontal (1-12)
Breakpoints responsifs
Préfixes :
sm:: >640pxmd:: >768pxlg:: >1024pxxl:: >1280px
Exemple :
<div class="md:grid-cols-2 lg:grid-cols-3">
Ajouter des animations
<div class="transition-all duration-300 hover:scale-105">
duration-300: vitesse (100-1000)scale-105: zoom (95-125)rotate-3: rotationtranslate-y-1: déplacement
Amusez-vous bien ![]()