fix: A27 lint terminé — eslint 0/0 (285 warnings nettoyés) (v7.25.0)
FlowDeck CI / test (push) Failing after 3h9m51s
FlowDeck CI / lint (push) Successful in 1m54s
FlowDeck CI / docker (push) Skipped

3 familles, 13 fichiers (+153/−167) :

1. no-empty ×70 = TOUS des `catch (x) {}` vides → `catch { /* volontaire */ }`
   (binding optionnel ES2019 + commentaire : passe no-empty ET
   no-unused-vars, zéro changement de comportement).

2. no-unused-vars ×171 :
   - bindings de catch inutilisés retirés (e/err/ex/e2/e3)
   - 24 lignes mortes déterministes, chaque suppression validée par assert
     sur le texte exact (`var self = this` ×8, `var lang`, `var acc`,
     `var today`, `var path/restored/files/resolved/items/clickEl`,
     `uid()`/`propName()` sans un seul appel, `.then` + `resolved++`
     compteurs jamais lus)
   - `/* exported */` sur les 10 fonctions appelées depuis les attributs
     HTML des templates (vérifiées par grep : 1 template chacune) :
     setActiveTab/kanbanBoard/filterSystem/sortSystem/newIssueForm/
     showNewIssue, importWizard, libraryPage, workspacesPage, settingsInit

3. no-undef ×44 = vrais globaux déclarés dans eslint.config.mjs
   (getSvgIcon = script inline de base.html, TextDecoder = API navigateur,
   Prism = CDN) + 2 vrais correctifs :
   - settings.js : `typeof toast === 'function'` = guard TOUJOURS faux
     (pas de toast global) → les toasts timezone/SAML ne s'affichaient
     jamais → `window.showToast` (2 sites)
   - local_workspace.js : `_wsInitData = window._wsInitData`
     (auto-affectation sans effet, global implicite) supprimé

eslint static/js : **0 erreur / 0 warning** (285 → 0) · node --check vert
sur tous les fichiers · suite **1089/1089** · ruff OK · docs à jour
This commit is contained in:
2026-10-01 21:30:37 -04:00
parent 103bc57418
commit 8d0d69e7b8
19 changed files with 189 additions and 173 deletions
+58 -58
View File
@@ -1,4 +1,5 @@
const ST=(()=>{try{const el=document.getElementById('st-config');return el?JSON.parse(el.textContent):{}}catch(e){return {}}})();
/* exported settingsInit -- appeles depuis les attributs HTML des templates */
const ST=(()=>{try{const el=document.getElementById('st-config');return el?JSON.parse(el.textContent):{}}catch{return {}}})();
function settingsInit() {
return {
@@ -107,13 +108,13 @@ function settingsInit() {
var r = await fetch('/api/notifications/prefs', {credentials:'same-origin'});
var d = await r.json();
this.notifPrefs = Object.assign({comments:true, mentions:true, reminders:true, assignments:true}, d.prefs || {});
} catch(e) {}
} catch { /* volontaire */ }
try {
var tz = await fetch('/api/notifications/timezone', {credentials:'same-origin'});
var td = await tz.json();
this.userTimezone = td.timezone || '';
this.userZones = td.zones || [];
} catch(e) {}
} catch { /* volontaire */ }
},
async saveNotifPrefs() {
try {
@@ -121,7 +122,7 @@ function settingsInit() {
method: 'POST', headers: {'Content-Type':'application/json','X-CSRF-Token': this.getCsrfToken()},
body: JSON.stringify(this.notifPrefs)
});
} catch(e) {}
} catch { /* volontaire */ }
},
async saveTimezone() {
try {
@@ -129,8 +130,8 @@ function settingsInit() {
method: 'POST', headers: {'Content-Type':'application/json','X-CSRF-Token': this.getCsrfToken()},
body: JSON.stringify({timezone: this.userTimezone})
});
if (r.ok && typeof toast === 'function') toast('Timezone saved');
} catch(e) {}
if (r.ok && typeof window.showToast === 'function') window.showToast('Timezone saved');
} catch { /* volontaire */ }
},
async loadTags() {
@@ -138,7 +139,7 @@ function settingsInit() {
var r = await fetch('/api/settings/tags/all');
var d = await r.json();
this.allTags = d.tags || [];
} catch(e) { this.allTags = []; }
} catch { this.allTags = []; }
},
async createTag() {
@@ -169,7 +170,6 @@ function settingsInit() {
this.renamingTag = tag;
this.renameValue = tag.name;
// Focus the input after Alpine renders the modal
var self = this;
this.$nextTick(function() {
var input = document.querySelector('.modal-box input[type=text]');
if (input) { input.focus(); input.select(); }
@@ -213,7 +213,7 @@ function settingsInit() {
var r = await this.adminFetch('/api/admin/users');
var d = await r.json();
this.adminUsers = d.users || [];
} catch(e) { this.adminUsers = []; }
} catch { this.adminUsers = []; }
await this.loadAdminStats();
},
@@ -221,7 +221,7 @@ function settingsInit() {
try {
var r = await this.adminFetch('/api/admin/stats');
this.adminStats = await r.json();
} catch(e) { this.adminStats = {}; }
} catch { this.adminStats = {}; }
},
async loadAdminAudit() {
@@ -249,7 +249,7 @@ function settingsInit() {
const logs = d.logs || [];
this.auditLogs = (reset !== false) ? logs : this.auditLogs.concat(logs);
this.auditHasMore = logs.length >= this.auditPageSize;
} catch(e) {
} catch {
if (reset !== false) this.auditLogs = [];
this.auditHasMore = false;
}
@@ -278,7 +278,7 @@ function settingsInit() {
var d = await r.json();
window.showToast(d.error || 'Failed to create user', 'error');
}
} catch(e) { window.showToast('Network error', 'error'); }
} catch { window.showToast('Network error', 'error'); }
},
async adminUpdateUser() {
@@ -295,7 +295,7 @@ function settingsInit() {
this.editingUser = null;
await this.loadAdminUsers();
}
} catch(e) {}
} catch { /* volontaire */ }
},
async adminDeleteUser(id) {
@@ -303,7 +303,7 @@ function settingsInit() {
try {
await this.adminFetch('/api/admin/users/' + id, { method: 'DELETE' });
await this.loadAdminUsers();
} catch(e) {}
} catch { /* volontaire */ }
},
// ── LLM / Agent ──
@@ -447,7 +447,7 @@ function settingsInit() {
}
if (this.selectedProviderId) this.keyForm(this.selectedProviderId);
this.syncLlmStatus();
} catch(e) {}
} catch { /* volontaire */ }
},
async loadProviderModels(id) {
var f = this.keyForm(id);
@@ -474,7 +474,7 @@ function settingsInit() {
} else {
f.msg = 'Erreur: ' + (d.error || 'échec de connexion');
}
} catch(e) { f.msg = 'Erreur réseau'; }
} catch { f.msg = 'Erreur réseau'; }
finally { f.modelLoading = false; }
},
async saveUserKey(id) {
@@ -505,7 +505,7 @@ function settingsInit() {
} else {
f.msg = d.detail || 'Erreur lors de l\'enregistrement';
}
} catch(e) { f.msg = 'Erreur réseau'; }
} catch { f.msg = 'Erreur réseau'; }
finally { f.saving = false; }
},
globalNeedsKeyFor(id) {
@@ -534,7 +534,7 @@ function settingsInit() {
this._setProviderState(id, false, d.error || 'échec de connexion');
f.msg = '✗ Test échoué : ' + (d.error || 'échec de connexion');
}
} catch(e) {
} catch {
this._setProviderState(id, false, 'Erreur réseau');
f.msg = 'Erreur réseau';
}
@@ -559,7 +559,7 @@ function settingsInit() {
} else {
f.msg = d.detail || 'Erreur lors de la suppression';
}
} catch(e) { f.msg = 'Erreur réseau'; }
} catch { f.msg = 'Erreur réseau'; }
finally { f.deleting = false; }
},
async loadLlmConfig() {
@@ -576,7 +576,7 @@ function settingsInit() {
api_base: d.api_base || (defp && defp.base_url) || ''};
this.applyLlmModels();
this.syncLlmStatus();
} catch(e) {}
} catch { /* volontaire */ }
},
applyLlmModels() {
var p = this.providerById(this.llmForm.provider);
@@ -619,7 +619,7 @@ function settingsInit() {
} else {
this.llmMsg = d.detail || 'Erreur lors de l\'enregistrement';
}
} catch(e) { this.llmMsg = 'Erreur réseau'; }
} catch { this.llmMsg = 'Erreur réseau'; }
finally { this.llmSaving = false; }
},
async resetGlobalLlm() {
@@ -644,7 +644,7 @@ function settingsInit() {
} else {
this.llmMsg = d.detail || 'Erreur lors de la réinitialisation';
}
} catch(e) { this.llmMsg = 'Erreur réseau'; }
} catch { this.llmMsg = 'Erreur réseau'; }
finally { this.llmSaving = false; }
},
async testLlm() {
@@ -669,7 +669,7 @@ function settingsInit() {
this._setProviderState(this.llmForm.provider, d.ok, d.error || '');
if (d.ok) cur.verified_model = d.model || '';
}
} catch(e) { this.llmTestOk = false; this.llmTestMsg = 'Erreur réseau'; }
} catch { this.llmTestOk = false; this.llmTestMsg = 'Erreur réseau'; }
finally { this.llmTesting = false; }
},
getCompletedLlmTest() { return this.llmTestMsg; },
@@ -698,7 +698,7 @@ function settingsInit() {
} else {
this.accountMsg = '✗ ' + (d.error || 'Error');
}
} catch(e) { this.accountMsg = '✗ Network error'; }
} catch { this.accountMsg = '✗ Network error'; }
this.accountSaving = false;
},
@@ -737,7 +737,7 @@ function settingsInit() {
var r = await fetch('/api/gitea/status');
var d = await r.json();
this.giteaLinked = d.linked || false;
} catch(e) { this.giteaLinked = false; }
} catch { this.giteaLinked = false; }
},
async disconnectGitea() {
@@ -745,41 +745,41 @@ function settingsInit() {
try {
var r = await fetch('/api/gitea/disconnect', { method: 'DELETE', headers: {'X-CSRF-Token': this.getCsrfToken()} });
if (r.ok) { this.giteaLinked = false; }
} catch(e) {}
} catch { /* volontaire */ }
},
async loadGithubStatus() {
try {
var r = await fetch('/api/github/status');
var d = await r.json();
this.githubLinked = d.linked || false;
} catch(e) { this.githubLinked = false; }
} catch { this.githubLinked = false; }
},
async disconnectGithub() {
if (!confirm('Disconnect GitHub? You can reconnect anytime.')) return;
try {
var r = await fetch('/api/github/disconnect', { method: 'DELETE', headers: {'X-CSRF-Token': this.getCsrfToken()} });
if (r.ok) { this.githubLinked = false; }
} catch(e) {}
} catch { /* volontaire */ }
},
async loadAutomations() {
try { await this.loadCollectionsForForm(); } catch(e) {}
try { await this.loadCollectionsForForm(); } catch { /* volontaire */ }
try {
var r = await fetch('/workspace/automations', {credentials:'same-origin'});
var d = await r.json();
this.automations = d.automations || [];
} catch(e) { this.automations = []; }
} catch { this.automations = []; }
},
async loadCollectionsForForm() {
try {
var r = await fetch('/db/api', {credentials:'same-origin'});
var d = await r.json();
this.globalCollections = d.collections || [];
} catch(e) { this.globalCollections = []; }
} catch { this.globalCollections = []; }
},
async saveAutomation() {
if (!this.af.name.trim()) { window.showToast && window.showToast('Nom requis', 'error'); return; }
try { JSON.parse(this.af.condition_json || '[]'); } catch(e) { window.showToast && window.showToast('Conditions JSON invalide', 'error'); return; }
try { JSON.parse(this.af.actions_json || '[]'); } catch(e) { window.showToast && window.showToast('Actions JSON invalide', 'error'); return; }
try { JSON.parse(this.af.condition_json || '[]'); } catch { window.showToast && window.showToast('Conditions JSON invalide', 'error'); return; }
try { JSON.parse(this.af.actions_json || '[]'); } catch { window.showToast && window.showToast('Actions JSON invalide', 'error'); return; }
var payload = {
name: this.af.name,
trigger_type: this.af.trigger_type,
@@ -801,7 +801,7 @@ function settingsInit() {
window.showToast && window.showToast(this.editAutomationId ? 'Automation mise à jour' : 'Automation créée');
this.cancelEditAutomation();
await this.loadAutomations();
} catch(e) { window.showToast && window.showToast('Erreur réseau', 'error'); }
} catch { window.showToast && window.showToast('Erreur réseau', 'error'); }
},
editAutomation(a) {
this.editAutomationId = a.id;
@@ -837,7 +837,7 @@ function settingsInit() {
headers: {'Content-Type':'application/json','X-CSRF-Token': this.getCsrfToken()},
body: JSON.stringify(payload) });
if (r.ok) await this.loadAutomations();
} catch(e) {}
} catch { /* volontaire */ }
},
async runAutomation(id) {
try {
@@ -850,7 +850,7 @@ function settingsInit() {
this.autoRuns.push({ created_at: new Date().toLocaleString(), trigger_source: 'manual', status: d.status || 'fired', detail: d.detail || '' });
window.showToast && window.showToast('Résultat : ' + (d.status || '') + ' — ' + (d.detail || ''));
await this.loadAutomations();
} catch(e) {}
} catch { /* volontaire */ }
},
async deleteAutomation(id) {
if (!confirm('Supprimer cette automation ?')) return;
@@ -858,7 +858,7 @@ function settingsInit() {
var r = await fetch('/workspace/automations/' + id, { method:'DELETE', credentials:'same-origin',
headers: {'X-CSRF-Token': this.getCsrfToken()} });
if (r.ok) await this.loadAutomations();
} catch(e) {}
} catch { /* volontaire */ }
},
// ── v5.2.0 API tokens ──
async loadApiTokens() {
@@ -866,7 +866,7 @@ function settingsInit() {
var r = await fetch('/api/settings/tokens', {headers: {'X-CSRF-Token': (document.cookie.match(/csrf_token=([^;]+)/)||[])[1]||''}, credentials:'same-origin'});
var d = await r.json();
this.apiTokens = d.tokens || [];
} catch(e) { this.apiTokens = []; }
} catch { this.apiTokens = []; }
},
async createApiToken() {
var name = this.tokenName.trim();
@@ -879,12 +879,12 @@ function settingsInit() {
this.newToken = d;
this.tokenName = '';
await this.loadApiTokens();
} catch(e) { window.showToast && window.showToast('Erreur réseau', 'error'); }
} catch { window.showToast && window.showToast('Erreur réseau', 'error'); }
},
async copyNewToken() {
if (!this.newToken) return;
try { await navigator.clipboard.writeText(this.newToken.token); window.showToast && window.showToast('Token copié'); }
catch(e) { window.showToast && window.showToast(this.newToken.token, 'error'); }
catch { window.showToast && window.showToast(this.newToken.token, 'error'); }
},
async revokeApiToken(t) {
if (!confirm('Révoquer le token « ' + t.name + ' » ? Il ne fonctionnera plus immédiatement.')) return;
@@ -892,7 +892,7 @@ function settingsInit() {
var r = await fetch('/api/settings/tokens/' + t.id, {method:'DELETE', credentials:'same-origin',
headers: {'X-CSRF-Token': this.getCsrfToken()} });
if (r.ok) await this.loadApiTokens();
} catch(e) {}
} catch { /* volontaire */ }
},
// ── v5.2.0 Sessions ──
async loadSessions() {
@@ -900,7 +900,7 @@ function settingsInit() {
var r = await fetch('/api/settings/sessions', {credentials:'same-origin'});
var d = await r.json();
this.sessions = d.sessions || [];
} catch(e) { this.sessions = []; }
} catch { this.sessions = []; }
},
async revokeSession(s) {
var msg = s.is_current ? 'Déconnecter cet appareil ?' : 'Révoquer cette session ?';
@@ -912,7 +912,7 @@ function settingsInit() {
if (s.is_current) window.location = '/auth/login?provider=local';
await this.loadSessions();
}
} catch(e) {}
} catch { /* volontaire */ }
},
// ── v6.2.0 Web Clipper ──
async loadClipperDevices() {
@@ -920,14 +920,14 @@ function settingsInit() {
var r = await fetch('/api/v2/web-clipper/devices', {credentials:'same-origin'});
var d = await r.json();
this.clipperDevices = d.devices || [];
} catch(e) { this.clipperDevices = []; }
} catch { this.clipperDevices = []; }
},
async revokeClipperDevice(d) {
if (!confirm('Révoquer l\'extension « ' + (d.device_name || d.device_id) + ' » ?')) return;
try {
var r = await fetch('/api/v2/web-clipper/devices/' + d.id, {method:'DELETE', credentials:'same-origin', headers: {'X-CSRF-Token': this.getCsrfToken()}});
if (r.ok) await this.loadClipperDevices();
} catch(e) {}
} catch { /* volontaire */ }
},
async testClip() {
this.clipTesting = true; this.clipTestMsg = ''; this.clipTestOk = false;
@@ -940,7 +940,7 @@ function settingsInit() {
var d = await r.json();
if (r.ok) { this.clipTestOk = true; this.clipTestMsg = '✓ Page créée : #' + d.page_id + ' — ' + d.title; await this.loadClipperDevices(); }
else this.clipTestMsg = d.detail || 'Erreur';
} catch(e) { this.clipTestMsg = 'Erreur réseau'; }
} catch { this.clipTestMsg = 'Erreur réseau'; }
finally { this.clipTesting = false; }
},
// ── v6.7.0 SSO / Enterprise (admin) ──
@@ -957,8 +957,8 @@ function settingsInit() {
async copySsoMetadata() {
try {
await navigator.clipboard.writeText(this.ssoMetadataUrl());
if (typeof toast === 'function') toast('SP metadata URL copiée');
} catch(e) {}
if (typeof window.showToast === 'function') window.showToast('SP metadata URL copiée');
} catch { /* volontaire */ }
},
async loadSsoConfig() {
this.ssoMsg = '';
@@ -994,7 +994,7 @@ function settingsInit() {
this.ssoGroups = (d.groups_mapping || []).map(function(g){ return {sso_group: g.sso_group || '', workspace_role: g.workspace_role || 'editor', workspace_id: g.workspace_id || ''}; });
}
}
} catch(e) {}
} catch { /* volontaire */ }
try {
var w = await fetch('/api/v2/sso/workspaces', {credentials:'same-origin'});
if (w.ok) {
@@ -1002,13 +1002,13 @@ function settingsInit() {
this.ssoWorkspaces = wd.workspaces || [];
this.ssoProvisioned = wd.provisioned_users || this.ssoProvisioned;
}
} catch(e) {}
} catch { /* volontaire */ }
},
async saveSsoConfig() {
this.ssoMsg = '';
var amap = {};
try { amap = JSON.parse(this.ssoAttrJson || '{}'); }
catch(e) { this.ssoMsg = 'Attribute mapping : JSON invalide'; this.ssoOk = false; return; }
catch { this.ssoMsg = 'Attribute mapping : JSON invalide'; this.ssoOk = false; return; }
if (amap === null || typeof amap !== 'object' || Array.isArray(amap)) {
this.ssoMsg = 'Attribute mapping : doit être un objet JSON'; this.ssoOk = false; return;
}
@@ -1024,10 +1024,10 @@ function settingsInit() {
delete payload.id;
try {
var r = await this.adminFetch('/api/v2/sso/config', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload)});
var d = null; try { d = await r.json(); } catch(e) {}
var d = null; try { d = await r.json(); } catch { /* volontaire */ }
if (!r.ok) { this.ssoMsg = (d && (d.detail || d.error)) || ('Erreur ' + r.status); this.ssoOk = false; }
else { this.ssoMsg = 'Configuration enregistrée'; this.ssoOk = true; await this.loadSsoConfig(); }
} catch(e) { this.ssoMsg = 'Erreur réseau'; this.ssoOk = false; }
} catch { this.ssoMsg = 'Erreur réseau'; this.ssoOk = false; }
finally { this.ssoSaving = false; }
},
async disableSso() {
@@ -1037,16 +1037,16 @@ function settingsInit() {
var r = await this.adminFetch('/api/v2/sso/config', {method:'DELETE'});
if (r.ok) { this.ssoMsg = 'SSO désactivé'; this.ssoOk = true; await this.loadSsoConfig(); }
else { this.ssoMsg = 'Erreur ' + r.status; this.ssoOk = false; }
} catch(e) { this.ssoMsg = 'Erreur réseau'; this.ssoOk = false; }
} catch { this.ssoMsg = 'Erreur réseau'; this.ssoOk = false; }
},
async syncSsoGroups() {
this.ssoMsg = '';
try {
var r = await this.adminFetch('/api/v2/sso/sync', {method:'POST', headers:{'Content-Type':'application/json'}, body:'{}'});
var d = null; try { d = await r.json(); } catch(e) {}
var d = null; try { d = await r.json(); } catch { /* volontaire */ }
if (r.ok) { this.ssoMsg = 'Groupes re-synchronisés — ' + (d && d.updated || 0) + '/' + (d && d.users || 0) + ' utilisateur(s)'; this.ssoOk = true; await this.loadSsoConfig(); }
else { this.ssoMsg = (d && d.detail) || ('Erreur ' + r.status); this.ssoOk = false; }
} catch(e) { this.ssoMsg = 'Erreur réseau'; this.ssoOk = false; }
} catch { this.ssoMsg = 'Erreur réseau'; this.ssoOk = false; }
},
addSsoGroup() { this.ssoGroups.push({sso_group:'', workspace_role:'editor', workspace_id: this.ssoCfg.default_workspace_id || ''}); },
removeSsoGroup(i) { this.ssoGroups.splice(i, 1); },
@@ -1056,7 +1056,7 @@ function settingsInit() {
var r = await this.adminFetch('/api/settings/backups');
var d = await r.json();
this.backups = d.backups || [];
} catch(e) { this.backups = []; }
} catch { this.backups = []; }
},
async runBackup() {
this.backupRunning = true; this.backupMsg = ''; this.backupOk = false;
@@ -1065,7 +1065,7 @@ function settingsInit() {
var d = await r.json();
if (r.ok) { this.backupOk = true; this.backupMsg = '✓ Sauvegarde créée : ' + d.filename; await this.loadBackups(); }
else { this.backupMsg = d.detail || 'Erreur'; }
} catch(e) { this.backupMsg = 'Erreur réseau'; }
} catch { this.backupMsg = 'Erreur réseau'; }
finally { this.backupRunning = false; }
},
closeSettings() {