feat: conectar Tablero CDC a Supabase empresarial
This commit is contained in:
+2
-2
@@ -1,3 +1,3 @@
|
||||
VITE_SUPABASE_URL="https://ecngyelpabyqbdxhftdy.supabase.co"
|
||||
VITE_SUPABASE_URL="https://dbit.digitalcompass.agency"
|
||||
VITE_SUPABASE_ANON_KEY="TU_ANON_PUBLIC_KEY"
|
||||
VITE_WEBHOOK_URL=""
|
||||
VITE_WEBHOOK_URL="https://agenteit.digitalcompass.agency/webhook/tablero-cdc-sync-proyecto"
|
||||
|
||||
@@ -24,7 +24,7 @@ Esta versión incluye:
|
||||
- Paginación local en las vistas de Todos, Activos y Cerrados con 12 proyectos por página.
|
||||
- Persistencia de proyectos en Supabase.
|
||||
- Sincronización multiusuario con Supabase Realtime.
|
||||
- Desplegables dinámicos desde Supabase `app_lists`, con fallback local mientras se termina la sincronización del Sheet.
|
||||
- Desplegables dinámicos desde Supabase `tablero_cdc_app_lists`, con fallback local mientras se termina la sincronización del Sheet.
|
||||
|
||||
---
|
||||
|
||||
@@ -50,7 +50,7 @@ Esta versión incluye:
|
||||
|
||||
Las siguientes funcionalidades se implementarán en próximas fases:
|
||||
|
||||
1. Sincronización automática de la hoja `listas` del Google Sheet original hacia Supabase `app_lists`.
|
||||
1. Sincronización automática de la hoja `listas` del Google Sheet original hacia Supabase `tablero_cdc_app_lists`.
|
||||
2. Escritura automática de datos en el Sheet original mediante n8n u otra integración definida.
|
||||
3. Agregar una nueva columna final para enlace de brief en el Sheet original.
|
||||
4. Reglas de seguridad definitivas con Supabase RLS.
|
||||
@@ -173,22 +173,22 @@ Desarrollo y soporte técnico: **Isaac Aracena**.
|
||||
|
||||
Esta versión ya no depende de `localStorage` para los proyectos. El tablero lee y guarda la información en Supabase usando las tablas:
|
||||
|
||||
- `projects`
|
||||
- `project_links`
|
||||
- `profiles`
|
||||
- `app_lists`
|
||||
- `tablero_cdc_projects`
|
||||
- `tablero_cdc_project_links`
|
||||
- `tablero_cdc_profiles`
|
||||
- `tablero_cdc_app_lists`
|
||||
|
||||
Notas importantes:
|
||||
|
||||
- Los proyectos abiertos se guardan en base de datos con `status = 'Activo'`, pero en la interfaz se muestran como proyectos sin estatus para mantener el comportamiento visual original.
|
||||
- Los usuarios normales no ven ni actualizan el monto interno desde la app.
|
||||
- Solo Gerardo Marrero puede modificar estatus, monto interno y eliminar proyectos desde la interfaz.
|
||||
- Los links de propuestas y artes finales se guardan en `project_links`.
|
||||
- Los desplegables se leen desde `app_lists`. Si una categoría todavía no existe en Supabase, la app usa una lista local de respaldo para no bloquear el formulario.
|
||||
- Los links de propuestas y artes finales se guardan en `tablero_cdc_project_links`.
|
||||
- Los desplegables se leen desde `tablero_cdc_app_lists`. Si una categoría todavía no existe en Supabase, la app usa una lista local de respaldo para no bloquear el formulario.
|
||||
|
||||
## Supabase Realtime
|
||||
|
||||
Para que la sincronización multiusuario funcione, habilita Realtime para las tablas `projects`, `project_links` y `app_lists` ejecutando en Supabase SQL Editor el archivo:
|
||||
Para que la sincronización multiusuario funcione, habilita Realtime para las tablas `tablero_cdc_projects`, `tablero_cdc_project_links` y `tablero_cdc_app_lists` ejecutando en Supabase SQL Editor el archivo:
|
||||
|
||||
```text
|
||||
supabase_realtime_projects.sql
|
||||
@@ -199,7 +199,7 @@ Luego abre la app en dos pestañas o dos navegadores: al crear, editar o elimina
|
||||
|
||||
## Desplegables dinámicos
|
||||
|
||||
La app intenta cargar estos desplegables desde `public.app_lists`:
|
||||
La app intenta cargar estos desplegables desde `public.tablero_cdc_app_lists`:
|
||||
|
||||
- `client` / `cliente` / `clientes`
|
||||
- `brand` / `marca` / `marcas`
|
||||
@@ -207,4 +207,4 @@ La app intenta cargar estos desplegables desde `public.app_lists`:
|
||||
- `status` / `estatus`
|
||||
- `country_manager` / `cm` / `bu_cm` para mapear BU → Country Manager
|
||||
|
||||
Si una categoría aún no existe en Supabase, se usa el respaldo local del frontend. Más adelante n8n sincronizará la hoja `listas` del Sheet original hacia `app_lists`.
|
||||
Si una categoría aún no existe en Supabase, se usa el respaldo local del frontend. Más adelante n8n sincronizará la hoja `listas` del Sheet original hacia `tablero_cdc_app_lists`.
|
||||
|
||||
+37
-37
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
||||
<meta name="description" content="Herramienta interna del Departamento de Diseño Creativo." />
|
||||
<meta name="author" content="CDC" />
|
||||
<link rel="icon" type="image/svg+xml" href="/tablero-cdc/favicon.svg" />
|
||||
<script type="module" crossorigin src="/tablero-cdc/assets/index-BYKs5Exj.js"></script>
|
||||
<script type="module" crossorigin src="/tablero-cdc/assets/index-BEinrcZb.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/tablero-cdc/assets/index-DjXLQf1G.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -108,7 +108,7 @@ export function ProjectDialog({ open, onOpenChange, project }: Props) {
|
||||
return match?.[1] ?? "";
|
||||
};
|
||||
|
||||
// BU → Country Manager automático desde Supabase app_lists, con fallback local.
|
||||
// BU → Country Manager automático desde Supabase tablero_cdc_app_lists, con fallback local.
|
||||
const onBU = (bu: string) => {
|
||||
const cleanBu = canonicalOptionLabel(bu);
|
||||
setForm((f) => ({ ...f, bu: cleanBu, cm: getCountryManager(cleanBu) }));
|
||||
|
||||
+3
-3
@@ -137,7 +137,7 @@ export async function loadAppLists() {
|
||||
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from("app_lists")
|
||||
.from("tablero_cdc_app_lists")
|
||||
.select("category, value, label, sort_order, is_active")
|
||||
.eq("is_active", true)
|
||||
.order("category", { ascending: true })
|
||||
@@ -180,12 +180,12 @@ function startAppListsRealtime() {
|
||||
|
||||
appListsRealtimeChannel = supabase
|
||||
.channel("tablero-cdc-app-lists")
|
||||
.on("postgres_changes", { event: "*", schema: "public", table: "app_lists" }, () =>
|
||||
.on("postgres_changes", { event: "*", schema: "public", table: "tablero_cdc_app_lists" }, () =>
|
||||
scheduleRealtimeRefresh(),
|
||||
)
|
||||
.subscribe((status) => {
|
||||
if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
|
||||
console.warn("Supabase Realtime no pudo suscribirse a app_lists:", status);
|
||||
console.warn("Supabase Realtime no pudo suscribirse a tablero_cdc_app_lists:", status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+8
-8
@@ -294,12 +294,12 @@ function startProjectsRealtime() {
|
||||
.channel("tablero-cdc-projects")
|
||||
.on(
|
||||
"postgres_changes",
|
||||
{ event: "*", schema: "public", table: "projects" },
|
||||
{ event: "*", schema: "public", table: "tablero_cdc_projects" },
|
||||
() => scheduleRealtimeRefresh(),
|
||||
)
|
||||
.on(
|
||||
"postgres_changes",
|
||||
{ event: "*", schema: "public", table: "project_links" },
|
||||
{ event: "*", schema: "public", table: "tablero_cdc_project_links" },
|
||||
() => scheduleRealtimeRefresh(),
|
||||
)
|
||||
.subscribe((status) => {
|
||||
@@ -323,7 +323,7 @@ function stopProjectsRealtime() {
|
||||
|
||||
async function replaceProjectLinks(projectId: string, project: Pick<Project, "propuestaLinks" | "afLinks">) {
|
||||
const { error: deleteError } = await supabase
|
||||
.from("project_links")
|
||||
.from("tablero_cdc_project_links")
|
||||
.delete()
|
||||
.eq("project_id", projectId);
|
||||
|
||||
@@ -333,7 +333,7 @@ async function replaceProjectLinks(projectId: string, project: Pick<Project, "pr
|
||||
|
||||
if (linkRows.length === 0) return;
|
||||
|
||||
const { error: insertError } = await supabase.from("project_links").insert(linkRows);
|
||||
const { error: insertError } = await supabase.from("tablero_cdc_project_links").insert(linkRows);
|
||||
|
||||
if (insertError) throw insertError;
|
||||
}
|
||||
@@ -359,7 +359,7 @@ async function loadProjects() {
|
||||
brief_link,
|
||||
created_at,
|
||||
extra_data,
|
||||
project_links (
|
||||
project_links:tablero_cdc_project_links (
|
||||
id,
|
||||
link_type,
|
||||
url,
|
||||
@@ -368,7 +368,7 @@ async function loadProjects() {
|
||||
`;
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from("projects")
|
||||
.from("tablero_cdc_projects")
|
||||
.select(selectColumns)
|
||||
.order("created_at", { ascending: false });
|
||||
|
||||
@@ -399,7 +399,7 @@ async function addProject(project: Project) {
|
||||
};
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from("projects")
|
||||
.from("tablero_cdc_projects")
|
||||
.insert(insertPayload)
|
||||
.select("id")
|
||||
.single();
|
||||
@@ -447,7 +447,7 @@ async function updateProject(id: string, patch: Partial<Project>) {
|
||||
updated_by: userId,
|
||||
};
|
||||
|
||||
const { error } = await supabase.from("projects").update(updatePayload).eq("id", id);
|
||||
const { error } = await supabase.from("tablero_cdc_projects").update(updatePayload).eq("id", id);
|
||||
|
||||
if (error) {
|
||||
setError(error.message);
|
||||
|
||||
@@ -11,9 +11,9 @@ begin
|
||||
from pg_publication_tables
|
||||
where pubname = 'supabase_realtime'
|
||||
and schemaname = 'public'
|
||||
and tablename = 'projects'
|
||||
and tablename = 'tablero_cdc_projects'
|
||||
) then
|
||||
alter publication supabase_realtime add table public.projects;
|
||||
alter publication supabase_realtime add table public.tablero_cdc_projects;
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
@@ -21,9 +21,9 @@ begin
|
||||
from pg_publication_tables
|
||||
where pubname = 'supabase_realtime'
|
||||
and schemaname = 'public'
|
||||
and tablename = 'project_links'
|
||||
and tablename = 'tablero_cdc_project_links'
|
||||
) then
|
||||
alter publication supabase_realtime add table public.project_links;
|
||||
alter publication supabase_realtime add table public.tablero_cdc_project_links;
|
||||
end if;
|
||||
|
||||
if not exists (
|
||||
@@ -31,8 +31,8 @@ begin
|
||||
from pg_publication_tables
|
||||
where pubname = 'supabase_realtime'
|
||||
and schemaname = 'public'
|
||||
and tablename = 'app_lists'
|
||||
and tablename = 'tablero_cdc_app_lists'
|
||||
) then
|
||||
alter publication supabase_realtime add table public.app_lists;
|
||||
alter publication supabase_realtime add table public.tablero_cdc_app_lists;
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
Reference in New Issue
Block a user