- Modèles Organization + OrgMember, migration Alembic (SQLite compatible) - organization_id nullable sur Document, Decision, Mandate, VotingProtocol - Service, schéma, router /organizations + dependency get_active_org_id - Seed : Duniter G1 + Axiom Team ; tout le contenu seed attaché à Duniter G1 - Backend : list/create filtrés par header X-Organization - Frontend : store organizations, WorkspaceSelector réel, useApi injecte l'org - Fix critique : rate_limiter exclut les requêtes OPTIONS (CORS preflight) → résout le bug "Failed to fetch /auth/me" au reload (429 sur preflight) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
export interface Organization {
|
|
id: string
|
|
name: string
|
|
slug: string
|
|
org_type: string
|
|
is_transparent: boolean
|
|
color: string | null
|
|
icon: string | null
|
|
description: string | null
|
|
created_at: string
|
|
}
|
|
|
|
interface OrgState {
|
|
organizations: Organization[]
|
|
activeSlug: string | null
|
|
loading: boolean
|
|
error: string | null
|
|
}
|
|
|
|
export const useOrganizationsStore = defineStore('organizations', {
|
|
state: (): OrgState => ({
|
|
organizations: [],
|
|
activeSlug: null,
|
|
loading: false,
|
|
error: null,
|
|
}),
|
|
|
|
getters: {
|
|
active: (state): Organization | null =>
|
|
state.organizations.find(o => o.slug === state.activeSlug) ?? state.organizations[0] ?? null,
|
|
|
|
hasOrganizations: (state): boolean => state.organizations.length > 0,
|
|
},
|
|
|
|
actions: {
|
|
async fetchOrganizations() {
|
|
this.loading = true
|
|
this.error = null
|
|
try {
|
|
const { $api } = useApi()
|
|
const orgs = await $api<Organization[]>('/organizations/')
|
|
// Duniter G1 first, then alphabetical
|
|
this.organizations = orgs.sort((a, b) => {
|
|
if (a.slug === 'duniter-g1') return -1
|
|
if (b.slug === 'duniter-g1') return 1
|
|
return a.name.localeCompare(b.name)
|
|
})
|
|
// Restore persisted active slug, or default to first org
|
|
const stored = import.meta.client ? localStorage.getItem('libredecision_org') : null
|
|
if (stored && this.organizations.some(o => o.slug === stored)) {
|
|
this.activeSlug = stored
|
|
} else if (this.organizations.length > 0) {
|
|
this.activeSlug = this.organizations[0].slug
|
|
}
|
|
} catch (err: any) {
|
|
this.error = err?.message || 'Erreur lors du chargement des organisations'
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
setActive(slug: string) {
|
|
if (this.organizations.some(o => o.slug === slug)) {
|
|
this.activeSlug = slug
|
|
if (import.meta.client) {
|
|
localStorage.setItem('libredecision_org', slug)
|
|
}
|
|
}
|
|
},
|
|
},
|
|
})
|