feat: gestion groupes sans serveur via IPC + lecture YAML directe

- Ajout du package yaml dans electron pour parser config.yaml
- Handlers IPC groups:list/create/update/delete lisent/écrivent config.yaml
  directement depuis le Main Process (sans serveur requis)
- fetchGroups() utilise toujours IPC (plus d'appel REST pour la lecture)
- editGroup/deleteGroup/addGroup : REST API si serveur actif, IPC sinon
- loadViewData : onglet Groupes chargé même si serveur arrêté
- Note affichée quand le serveur est arrêté : modifications appliquées
  au prochain démarrage
This commit is contained in:
2026-07-01 13:36:12 +02:00
parent b3fbe31a2d
commit 51245db256
4 changed files with 139 additions and 30 deletions
+70
View File
@@ -10,8 +10,24 @@ const { spawn } = require('child_process');
const http = require('http');
const https = require('https');
const QRCode = require('qrcode');
const yaml = require('yaml');
const setupHelper = require('./setup-helper');
const CONFIG_PATH = path.join(__dirname, '..', 'server', 'config', 'config.yaml');
function readConfig() {
return yaml.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
}
function writeConfig(config) {
fs.writeFileSync(CONFIG_PATH, yaml.stringify(config), 'utf8');
}
function slugify(text) {
return text.toString().normalize('NFD').replace(/[̀-ͯ]/g, '')
.toLowerCase().trim().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-');
}
// État de l'application
let mainWindow = null;
let tray = null;
@@ -366,6 +382,60 @@ app.whenReady().then(async () => {
return setupHelper.getNetworkIP();
});
// ========== Groupes (lecture/écriture YAML directe, sans serveur) ==========
ipcMain.handle('groups:list', () => {
try {
const config = readConfig();
return { groups: config.groups || [] };
} catch (error) {
return { groups: [], error: error.message };
}
});
ipcMain.handle('groups:create', (event, { name, audioBitrate }) => {
try {
const config = readConfig();
const id = slugify(name);
if ((config.groups || []).find(g => slugify(g.name) === id)) {
return { success: false, error: `Un groupe "${name}" existe déjà` };
}
const group = { name, ...(audioBitrate ? { audioBitrate } : {}) };
config.groups = [...(config.groups || []), group];
writeConfig(config);
return { success: true, group };
} catch (error) {
return { success: false, error: error.message };
}
});
ipcMain.handle('groups:update', (event, { id, name, audioBitrate }) => {
try {
const config = readConfig();
const idx = (config.groups || []).findIndex(g => slugify(g.name) === id);
if (idx === -1) return { success: false, error: `Groupe ${id} introuvable` };
if (name !== undefined) config.groups[idx].name = name;
if (audioBitrate !== undefined) config.groups[idx].audioBitrate = audioBitrate;
writeConfig(config);
return { success: true, group: config.groups[idx] };
} catch (error) {
return { success: false, error: error.message };
}
});
ipcMain.handle('groups:delete', (event, { id }) => {
try {
const config = readConfig();
const idx = (config.groups || []).findIndex(g => slugify(g.name) === id);
if (idx === -1) return { success: false, error: `Groupe ${id} introuvable` };
config.groups.splice(idx, 1);
writeConfig(config);
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
});
ipcMain.handle('config:export', async () => {
const configPath = path.join(__dirname, '..', 'server', 'config', 'config.yaml');