/* exported workspacesPage -- appeles depuis les attributs HTML des templates */ // A20 phase 3 : registre Alpine.data (le build CSP ne résout pas les // globales window — probe « Undefined variable: workspacesPage »). if (window.Alpine) { Alpine.data('workspacesPage', workspacesPage); fdRefreshXData('workspacesPage'); } else document.addEventListener('alpine:init', function () { Alpine.data('workspacesPage', workspacesPage); }); function workspacesPage() { return { workspaces: [], activeId: null, showCreate: false, showRename: false, closeCreateRename() { this.showCreate = false; this.showRename = false; }, wsName: '', renameTarget: null, // Gitea giteaStatus: 'loading', // loading|ok|not_linked|error giteaGroups: [], giteaTotal: 0, activeOrg: 'all', giteaSearch: '', get filteredGroups() { var self = this; var q = (this.giteaSearch || '').toLowerCase(); var groups = this.activeOrg === 'all' ? this.giteaGroups : this.giteaGroups.filter(function(g) { return g.org === self.activeOrg; }); if (!q) return groups; return groups.map(function(g) { return {org: g.org, avatar: g.avatar, projects: g.projects.filter(function(p) { return p.name.toLowerCase().includes(q) || (p.description||'').toLowerCase().includes(q); })}; }).filter(function(g) { return g.projects.length > 0; }); }, async init() { await this.load(); await this.loadGitea(); }, async load() { const r = await fetch('/api/workspaces'); const d = await r.json(); this.workspaces = d.workspaces || []; this.activeId = d.active_id; }, async selectLocal(ws) { await fetch(`/api/workspaces/${ws.id}/select`, {headers: {'X-CSRF-Token': getCsrf()}, method:'POST'}); window.location = '/local-workspace'; }, async doCreate() { if (!this.wsName.trim()) return; await fetch('/api/workspaces', { method:'POST', headers:{'X-CSRF-Token': getCsrf(), 'Content-Type':'application/json'}, body:JSON.stringify({name:this.wsName.trim()}) }); this.wsName = ''; this.showCreate = false; await this.load(); }, renameWs(ws) { this.renameTarget = ws; this.wsName = ws.name; this.showRename = true; }, async doRename() { if (!this.wsName.trim()||!this.renameTarget) return; await fetch(`/api/workspaces/${this.renameTarget.id}`, { method:'PUT', headers:{'X-CSRF-Token': getCsrf(), 'Content-Type':'application/json'}, body:JSON.stringify({name:this.wsName.trim()}) }); this.wsName = ''; this.showRename = false; this.renameTarget = null; await this.load(); }, async deleteWs(ws) { if (!confirm(`Delete workspace "${ws.name}" and all its pages?`)) return; await fetch(`/api/workspaces/${ws.id}`, {headers: {'X-CSRF-Token': getCsrf()}, method:'DELETE'}); await this.load(); }, // ── Gitea ── async loadGitea() { this.giteaStatus = 'loading'; try { // Get orgs const orgsRes = await fetch('/api/gitea/orgs'); if (orgsRes.status === 401) { this.giteaStatus = 'not_linked'; return; } if (!orgsRes.ok) { this.giteaStatus = 'error'; return; } const orgsData = await orgsRes.json(); const orgs = orgsData.orgs || []; // Fetch repos: user repos + org repos const groups = []; // Get username for the "personal" tab let myLogin = 'Me'; try { const meRes = await fetch('/auth/user'); if (meRes.ok) { const meData = await meRes.json(); myLogin = meData.user?.login || 'Me'; if (myLogin.includes('_')) myLogin = myLogin.split('_').pop(); // strip gitea_ prefix if present } } catch { /* volontaire */ } // User repos (no org filter) try { const userRes = await fetch('/api/gitea/projects'); if (userRes.ok) { const d = await userRes.json(); const repos = d.projects || []; if (repos.length) { groups.push({org: myLogin, avatar: '', projects: repos.map(r => ({...r, owner: r.owner || {login: myLogin}}))}); } } } catch { /* volontaire */ } // Org repos for (const org of orgs) { try { const res = await fetch('/api/gitea/projects?org=' + encodeURIComponent(org.username || org.login || org.name)); if (res.ok) { const d = await res.json(); if (d.projects && d.projects.length) { groups.push({org: org.username || org.login || org.name, avatar: org.avatar_url || '', projects: d.projects}); } } } catch { /* volontaire */ } } this.giteaGroups = groups; this.giteaTotal = groups.reduce((sum, g) => sum + g.projects.length, 0); this.giteaStatus = 'ok'; } catch { this.giteaStatus = 'error'; } }, openGitea(proj) { const owner = proj.owner?.login || proj.owner?.username || proj.full_name?.split('/')[0] || ''; const repo = proj.name; if (owner && repo) { // Set workspace cookie so sidebar shows tree document.cookie = 'flowdeck_workspace=gitea:' + owner + ':' + repo + ';path=/;SameSite=Lax'; window.location = `/gitea-workspace?owner=${encodeURIComponent(owner)}&repo=${encodeURIComponent(repo)}`; } } }; }