Files
iistwin/migrations/0054_organization_skins.sql
Ильяс Султанов 95279b8fcc feat: skin engine + Twenty CRM theme for iistwin
- Add client/src/themes/ with tokens, built-in skins (iistwin, twenty, omegaprom)
- Add ThemeProvider with data-skin/data-theme and runtime CSS for custom skins
- Add npm run skins:generate script for build-time CSS generation
- Add organization_skins table, migration and CRUD API
- Add activeSkinId to organizations and expose it in /api/auth/me
- Add skin switcher in /profile and admin skin editor in /settings/appearance
- Adapt index.css hardcoded colors to skin tokens
- Update AGENTS.md and Obsidian notes
2026-07-09 20:25:49 +03:00

28 lines
1.1 KiB
SQL

-- Organization skin storage and active skin selector
CREATE TABLE IF NOT EXISTS organization_skins (
id SERIAL PRIMARY KEY,
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
skin_id VARCHAR(50) NOT NULL,
name VARCHAR(100) NOT NULL,
description TEXT,
tokens JSONB NOT NULL,
is_editable BOOLEAN DEFAULT true,
is_active BOOLEAN DEFAULT false,
created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(organization_id, skin_id)
);
CREATE INDEX IF NOT EXISTS organization_skins_org_idx ON organization_skins(organization_id);
ALTER TABLE organizations ADD COLUMN IF NOT EXISTS active_skin_id VARCHAR(50) DEFAULT 'iistwin';
-- Tenant isolation
ALTER TABLE organization_skins ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_iso ON organization_skins;
CREATE POLICY tenant_iso ON organization_skins USING (
current_setting('app.is_superadmin', true) = 'true'
OR organization_id = NULLIF(current_setting('app.current_org_id', true), '')::int
);