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
This commit is contained in:
27
migrations/0054_organization_skins.sql
Normal file
27
migrations/0054_organization_skins.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
-- 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
|
||||
);
|
||||
Reference in New Issue
Block a user