refactor: simplification structure des groupes

Simplification majeure de la configuration des groupes :
- Suppression des champs redondants 'id' et 'description'
- Le nom du groupe sert maintenant d'identifiant (converti en slug automatiquement)
- Génération automatique des IDs pour groupes et canaux via fonction slugify()

Backend (server/) :
- Ajout fonction slugify() pour génération d'IDs à partir des noms
- Génération automatique des IDs au chargement de la config (index.js)
- API admin adaptée : POST/PUT /admin/groups génèrent les IDs automatiquement
- Pas besoin de fournir l'ID lors de la création/modification

Frontend (client/src/Admin.jsx + Admin.css) :
- Suppression champs ID et description du formulaire
- Simplification interface : nom + bitrate + canaux
- Mise à jour layout CSS canal (4 colonnes au lieu de 5)
- Cartes de groupe épurées (plus d'affichage d'ID)

Configuration (config.yaml) :
- Format simplifié : groupes avec 'name', 'channels' et 'audioBitrate' optionnel
- Exemple : "Production" au lieu de id/name/description séparés
- Plus lisible et maintenable

Les IDs sont générés dynamiquement :
- Groupe "Production" → id: "production"
- Canal "Principal" → id: "production-principal"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-05-24 20:32:24 +02:00
parent 637cc3e3a7
commit a0839ed563
5 changed files with 93 additions and 91 deletions
+1 -1
View File
@@ -293,7 +293,7 @@
.channel-item {
display: grid;
grid-template-columns: 1fr 1fr 80px 80px 50px;
grid-template-columns: 2fr 80px 80px 50px;
gap: 0.5rem;
margin-bottom: 0.5rem;
align-items: center;
+8 -48
View File
@@ -16,9 +16,7 @@ function Admin() {
const [showGroupForm, setShowGroupForm] = useState(false);
const [editingGroup, setEditingGroup] = useState(null);
const [groupForm, setGroupForm] = useState({
id: '',
name: '',
description: '',
audioBitrate: 96,
channels: []
});
@@ -152,9 +150,7 @@ function Admin() {
const startEditGroup = (group) => {
setEditingGroup(group.id);
setGroupForm({
id: group.id,
name: group.name,
description: group.description || '',
audioBitrate: group.audioBitrate || 96,
channels: group.channels || []
});
@@ -163,9 +159,7 @@ function Admin() {
const resetGroupForm = () => {
setGroupForm({
id: '',
name: '',
description: '',
audioBitrate: 96,
channels: []
});
@@ -178,7 +172,7 @@ function Admin() {
...groupForm,
channels: [
...groupForm.channels,
{ id: '', name: '', audioInput: 0, audioOutput: 0 }
{ name: '', audioInput: 0, audioOutput: 0 }
]
});
};
@@ -295,38 +289,18 @@ function Admin() {
<div className="form-row">
<label>
ID groupe
Nom du groupe
<input
type="text"
value={groupForm.id}
onChange={(e) => setGroupForm({ ...groupForm, id: e.target.value })}
disabled={!!editingGroup}
value={groupForm.name}
onChange={(e) => setGroupForm({ ...groupForm, name: e.target.value })}
placeholder="ex: Production, Technique..."
required
/>
</label>
<label>
Nom
<input
type="text"
value={groupForm.name}
onChange={(e) => setGroupForm({ ...groupForm, name: e.target.value })}
required
/>
</label>
</div>
<label>
Description
<input
type="text"
value={groupForm.description}
onChange={(e) => setGroupForm({ ...groupForm, description: e.target.value })}
/>
</label>
<label>
Bitrate audio (kbps)
Bitrate audio (kbps)
<input
type="number"
value={groupForm.audioBitrate}
@@ -348,14 +322,7 @@ function Admin() {
<div key={index} className="channel-item">
<input
type="text"
placeholder="ID canal"
value={channel.id}
onChange={(e) => updateChannel(index, 'id', e.target.value)}
required
/>
<input
type="text"
placeholder="Nom"
placeholder="Nom canal (ex: Principal, Backup...)"
value={channel.name}
onChange={(e) => updateChannel(index, 'name', e.target.value)}
required
@@ -397,10 +364,7 @@ function Admin() {
{groups.map(group => (
<div key={group.id} className="group-card">
<div className="group-header">
<div>
<h3>{group.name}</h3>
<span className="group-id">#{group.id}</span>
</div>
<h3>{group.name}</h3>
<div className="group-actions">
<button onClick={() => startEditGroup(group)} className="btn-edit">
@@ -411,10 +375,6 @@ function Admin() {
</div>
</div>
{group.description && (
<p className="group-description">{group.description}</p>
)}
<div className="group-info">
<span>Bitrate: {group.audioBitrate || 96} kbps</span>
<span>Canaux: {group.channels?.length || 0}</span>