Update project and dist
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
VITE_SUPABASE_URL="https://dbit.digitalcompass.agency"
|
||||||
|
VITE_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"
|
||||||
|
VITE_REPORT_WEBHOOK_URL="https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-reportar"
|
||||||
|
VITE_CHAT_WEBHOOK_URL="https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-chat"
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
# dist/ se versiona para el despliegue estático en Gitea.
|
||||||
|
dist-ssr
|
||||||
|
.output
|
||||||
|
.vinxi
|
||||||
|
.tanstack/**
|
||||||
|
.nitro
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Wrangler / Cloudflare
|
||||||
|
.wrangler/
|
||||||
|
.dev.vars
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.output
|
||||||
|
.vinxi
|
||||||
|
pnpm-lock.yaml
|
||||||
|
package-lock.json
|
||||||
|
bun.lock
|
||||||
|
routeTree.gen.ts
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Build estático (`dist`)
|
||||||
|
|
||||||
|
Este frontend está configurado como SPA de Vite + TanStack Router.
|
||||||
|
|
||||||
|
## Generar build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
La salida de producción se genera en:
|
||||||
|
|
||||||
|
```text
|
||||||
|
dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
La aplicación conserva la ruta base:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/cotizador-wmc/
|
||||||
|
```
|
||||||
|
|
||||||
|
Para servir rutas internas como `/cotizador-wmc/chat` directamente desde el navegador,
|
||||||
|
el servidor web debe usar fallback SPA hacia `/cotizador-wmc/index.html` cuando el archivo solicitado no exista.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Supabase — Cotizador Walmart Connect
|
||||||
|
|
||||||
|
> **Estado de esta entrega:** el backend de Supabase ya se considera preparado para esta versión del frontend. Los SQL incluidos en la raíz (`SUPABASE-ACCESOS.sql` y `SUPABASE-PERMISO-TARIFARIO.sql`) se conservan únicamente como referencia histórica; **no es necesario volver a ejecutarlos** si ya instalaste el script completo y el patch final del proyecto.
|
||||||
|
|
||||||
|
## Auth / Google OAuth
|
||||||
|
|
||||||
|
La aplicación utiliza Supabase Auth con Google y vuelve a:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://digitalcompass.agency/cotizador-wmc/
|
||||||
|
```
|
||||||
|
|
||||||
|
Callback de Supabase para Google OAuth:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://dbit.digitalcompass.agency/auth/v1/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
## Control de acceso
|
||||||
|
|
||||||
|
La fuente de verdad es:
|
||||||
|
|
||||||
|
```text
|
||||||
|
public.cotizador_wmc_access
|
||||||
|
```
|
||||||
|
|
||||||
|
- `is_active=true`: acceso general a la app.
|
||||||
|
- `can_use_tarifario=true`: habilita el módulo Tarifario.
|
||||||
|
|
||||||
|
El frontend revalida el acceso periódicamente y al recuperar foco/visibilidad.
|
||||||
|
|
||||||
|
## Backend que esta versión espera
|
||||||
|
|
||||||
|
- Tablas `cotizador_wmc_conversations` y `cotizador_wmc_messages`.
|
||||||
|
- Bucket privado `cotizador-wmc-uploads`.
|
||||||
|
- RPC `glm_track_app_event`.
|
||||||
|
- RPC `cotizador_wmc_process_my_agent_action`.
|
||||||
|
- Tabla `cotizador_wmc_tariff_items` con RLS.
|
||||||
|
- Las funciones/tablas de cotizaciones, artefactos y métricas instaladas por el SQL completo/patch final.
|
||||||
|
|
||||||
|
No se utiliza ninguna `service_role` en el navegador.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Corrección de acceso n8n
|
||||||
|
|
||||||
|
La tabla `public.cotizador_wmc_access` sigue siendo la fuente de verdad del acceso.
|
||||||
|
|
||||||
|
El error 403 observado no era causado por el usuario ni por `is_active`: el nodo HTTP Request de n8n puede convertir una respuesta PostgREST con un array de una fila en un item individual. El antiguo nodo `Validar acceso` solo aceptaba arrays y por eso descartaba una fila válida, dejando `accessAllowed=false`.
|
||||||
|
|
||||||
|
Usa `n8n/01_Cotizador_WMC_Agente_Gemini_Supabase_SIN_ENV_ACCESO_CORREGIDO.json`. No requiere nuevas variables de entorno ni service role.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# Cotizador Walmart Connect
|
||||||
|
|
||||||
|
Frontend interno de GomezLee Marketing para cotizaciones Walmart Connect.
|
||||||
|
|
||||||
|
## Estado de esta versión
|
||||||
|
|
||||||
|
Esta versión ya está conectada a la arquitectura de producción definida para el proyecto:
|
||||||
|
|
||||||
|
- Supabase Auth + control de acceso `cotizador_wmc_access`.
|
||||||
|
- n8n `/webhook/cotizador-wmc-chat` para Gemini, tarifario, históricos y generación de artefactos.
|
||||||
|
- n8n `/webhook/cotizador-wmc-reportar` para reportes de usuario.
|
||||||
|
- Persistencia de conversaciones y mensajes en Supabase.
|
||||||
|
- Adjuntos privados en el bucket `cotizador-wmc-uploads`, con URLs firmadas temporales para n8n/Gemini.
|
||||||
|
- Analítica global mediante `glm_track_app_event` para alimentar el dashboard general de aplicaciones GLM.
|
||||||
|
- Módulo Tarifario visible únicamente cuando `can_use_tarifario=true`, con lectura y cambios auditados mediante los RPC seguros de Supabase.
|
||||||
|
- Google Sheets / Slides / imágenes se generan desde los workflows de n8n y el Apps Script ya configurado en backend.
|
||||||
|
|
||||||
|
## Tecnologías
|
||||||
|
|
||||||
|
- React 19 + TypeScript
|
||||||
|
- TanStack Router / Query
|
||||||
|
- Vite (SPA estática)
|
||||||
|
- Tailwind CSS
|
||||||
|
- Supabase JS
|
||||||
|
|
||||||
|
## Ruta de producción
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://digitalcompass.agency/cotizador-wmc/
|
||||||
|
```
|
||||||
|
|
||||||
|
La aplicación se compila con base:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/cotizador-wmc/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuración frontend
|
||||||
|
|
||||||
|
El `.env` incluido contiene las variables públicas necesarias para compilar esta versión:
|
||||||
|
|
||||||
|
```env
|
||||||
|
VITE_SUPABASE_URL="https://dbit.digitalcompass.agency"
|
||||||
|
VITE_SUPABASE_ANON_KEY="..."
|
||||||
|
VITE_REPORT_WEBHOOK_URL="https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-reportar"
|
||||||
|
VITE_CHAT_WEBHOOK_URL="https://agenteit.digitalcompass.agency/webhook/cotizador-wmc-chat"
|
||||||
|
```
|
||||||
|
|
||||||
|
La ANON KEY de Supabase es una clave pública de cliente. No debe agregarse `service_role` al frontend.
|
||||||
|
|
||||||
|
## Desarrollo / build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm ci
|
||||||
|
npm run dev
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
`npm run build` genera una carpeta **`dist/`** lista para el despliegue del frontend estático.
|
||||||
|
La ruta base de producción se mantiene en `/cotizador-wmc/`.
|
||||||
|
|
||||||
|
## Flujo de uso
|
||||||
|
|
||||||
|
1. El usuario inicia sesión con Google mediante Supabase Auth.
|
||||||
|
2. La app verifica dominio GLM + acceso activo en `cotizador_wmc_access`.
|
||||||
|
3. Al entrar se registra actividad para métricas globales de uso.
|
||||||
|
4. Cada chat se conserva en Supabase y además mantiene respaldo local del navegador.
|
||||||
|
5. Los adjuntos se guardan en Storage privado antes de llamar a n8n.
|
||||||
|
6. La app envía a n8n el JWT real de Supabase, usuario, conversación, mensaje, adjuntos y `appSessionId`.
|
||||||
|
7. n8n consulta contexto/tarifario/históricos, llama Gemini y devuelve la respuesta y, cuando aplique, el enlace del Google Sheet, Google Slides o imagen generado.
|
||||||
|
8. La respuesta y sus metadatos quedan guardados en el historial.
|
||||||
|
|
||||||
|
## Tarifario
|
||||||
|
|
||||||
|
El botón **Tarifario** solo aparece para usuarios con `can_use_tarifario=true`.
|
||||||
|
|
||||||
|
Desde el módulo se puede:
|
||||||
|
|
||||||
|
- buscar y filtrar por país;
|
||||||
|
- consultar tarifa vigente;
|
||||||
|
- crear una tarifa;
|
||||||
|
- editar una tarifa;
|
||||||
|
- eliminar/desactivar una tarifa.
|
||||||
|
|
||||||
|
Los cambios no escriben directamente sobre la tabla desde el navegador: utilizan `cotizador_wmc_process_my_agent_action`, que valida de nuevo el permiso y conserva auditoría.
|
||||||
|
|
||||||
|
## Analítica para dashboard GLM
|
||||||
|
|
||||||
|
La app registra eventos autenticados con `glm_track_app_event`, entre ellos:
|
||||||
|
|
||||||
|
- `app_open`;
|
||||||
|
- `message_sent`;
|
||||||
|
- `chat_deleted`;
|
||||||
|
- `tariff_opened`;
|
||||||
|
- `agent_error`;
|
||||||
|
- `logout`.
|
||||||
|
|
||||||
|
Los workflows registran adicionalmente las cotizaciones, propuestas, imágenes, mensualizaciones GLM, ejecuciones del agente y reportes, por lo que las vistas de dashboard de Supabase pueden calcular usuarios únicos, usuarios mensuales, promedio mensual, cotizaciones creadas y demás KPIs definidos.
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- Cotizador Walmart Connect - Control de acceso por usuario
|
||||||
|
-- GomezLee Marketing
|
||||||
|
-- ============================================================
|
||||||
|
-- Script completo para una instalación nueva.
|
||||||
|
-- Si la tabla YA existe, para agregar únicamente el permiso del
|
||||||
|
-- Tarifario usa SUPABASE-PERMISO-TARIFARIO.sql.
|
||||||
|
|
||||||
|
create table if not exists public.cotizador_wmc_access (
|
||||||
|
email text primary key,
|
||||||
|
full_name text not null,
|
||||||
|
is_active boolean not null default true,
|
||||||
|
can_use_tarifario boolean not null default false,
|
||||||
|
created_at timestamptz not null default now(),
|
||||||
|
constraint cotizador_wmc_access_email_normalized_chk
|
||||||
|
check (email = lower(btrim(email))),
|
||||||
|
constraint cotizador_wmc_access_glm_domain_chk
|
||||||
|
check (email like '%@gomezleemarketing.com')
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Si esta tabla fue creada con una versión anterior, agrega la columna nueva.
|
||||||
|
alter table public.cotizador_wmc_access
|
||||||
|
add column if not exists can_use_tarifario boolean not null default false;
|
||||||
|
|
||||||
|
comment on table public.cotizador_wmc_access is
|
||||||
|
'Usuarios autorizados para ingresar al Cotizador Walmart Connect.';
|
||||||
|
comment on column public.cotizador_wmc_access.is_active is
|
||||||
|
'true = acceso general permitido; false = acceso general revocado.';
|
||||||
|
comment on column public.cotizador_wmc_access.can_use_tarifario is
|
||||||
|
'true = puede visualizar/utilizar el módulo Tarifario; false = no tiene acceso al módulo.';
|
||||||
|
|
||||||
|
-- RLS: el navegador solo puede comprobar SU PROPIO acceso y únicamente
|
||||||
|
-- cuando la fila está activa. No puede leer usuarios ajenos ni modificar la tabla.
|
||||||
|
alter table public.cotizador_wmc_access enable row level security;
|
||||||
|
|
||||||
|
revoke all on table public.cotizador_wmc_access from anon;
|
||||||
|
revoke insert, update, delete, truncate, references, trigger
|
||||||
|
on table public.cotizador_wmc_access from authenticated;
|
||||||
|
grant select on table public.cotizador_wmc_access to authenticated;
|
||||||
|
|
||||||
|
drop policy if exists "cotizador_wmc_read_own_active_access"
|
||||||
|
on public.cotizador_wmc_access;
|
||||||
|
|
||||||
|
create policy "cotizador_wmc_read_own_active_access"
|
||||||
|
on public.cotizador_wmc_access
|
||||||
|
for select
|
||||||
|
to authenticated
|
||||||
|
using (
|
||||||
|
is_active = true
|
||||||
|
and email = lower(coalesce((select auth.jwt() ->> 'email'), ''))
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Usuarios autorizados iniciales.
|
||||||
|
-- El permiso de Tarifario queda false por defecto y se administra por separado.
|
||||||
|
insert into public.cotizador_wmc_access (email, full_name, is_active)
|
||||||
|
values
|
||||||
|
('iaracena@gomezleemarketing.com', 'Isaac Aracena', true),
|
||||||
|
('lmatos@gomezleemarketing.com', 'Luis Matos', true),
|
||||||
|
('ethen@gomezleemarketing.com', 'Eidan Then', true),
|
||||||
|
('mgomez@gomezleemarketing.com', 'Máximo Gómez', true),
|
||||||
|
('jgomez@gomezleemarketing.com', 'José Leopoldo Gómez', true),
|
||||||
|
('wlopez@gomezleemarketing.com', 'William Lopez', true)
|
||||||
|
on conflict (email) do update
|
||||||
|
set full_name = excluded.full_name;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- EJEMPLOS DE ADMINISTRACIÓN (NO es necesario ejecutarlos ahora)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- QUITAR ACCESO GENERAL sin borrar el usuario:
|
||||||
|
-- update public.cotizador_wmc_access
|
||||||
|
-- set is_active = false
|
||||||
|
-- where email = 'usuario@gomezleemarketing.com';
|
||||||
|
|
||||||
|
-- VOLVER A DAR ACCESO GENERAL:
|
||||||
|
-- update public.cotizador_wmc_access
|
||||||
|
-- set is_active = true
|
||||||
|
-- where email = 'usuario@gomezleemarketing.com';
|
||||||
|
|
||||||
|
-- DAR ACCESO AL TARIFARIO:
|
||||||
|
-- update public.cotizador_wmc_access
|
||||||
|
-- set can_use_tarifario = true
|
||||||
|
-- where email = 'usuario@gomezleemarketing.com';
|
||||||
|
|
||||||
|
-- QUITAR ACCESO AL TARIFARIO:
|
||||||
|
-- update public.cotizador_wmc_access
|
||||||
|
-- set can_use_tarifario = false
|
||||||
|
-- where email = 'usuario@gomezleemarketing.com';
|
||||||
|
|
||||||
|
-- DAR ACCESO GENERAL A UNA PERSONA NUEVA:
|
||||||
|
-- insert into public.cotizador_wmc_access (email, full_name, is_active)
|
||||||
|
-- values ('usuario@gomezleemarketing.com', 'Nombre Apellido', true)
|
||||||
|
-- on conflict (email) do update
|
||||||
|
-- set full_name = excluded.full_name, is_active = true;
|
||||||
|
|
||||||
|
-- ELIMINAR COMPLETAMENTE UN REGISTRO:
|
||||||
|
-- delete from public.cotizador_wmc_access
|
||||||
|
-- where email = 'usuario@gomezleemarketing.com';
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- Cotizador Walmart Connect - Permiso del módulo Tarifario
|
||||||
|
-- GomezLee Marketing
|
||||||
|
-- ============================================================
|
||||||
|
-- EJECUTAR UNA SOLA VEZ en Supabase > SQL Editor sobre la BD
|
||||||
|
-- que ya tiene public.cotizador_wmc_access.
|
||||||
|
--
|
||||||
|
-- false = el usuario NO ve ni puede utilizar el botón/módulo Tarifario.
|
||||||
|
-- true = el usuario SÍ ve y puede utilizar el botón/módulo Tarifario.
|
||||||
|
|
||||||
|
alter table public.cotizador_wmc_access
|
||||||
|
add column if not exists can_use_tarifario boolean not null default false;
|
||||||
|
|
||||||
|
comment on column public.cotizador_wmc_access.can_use_tarifario is
|
||||||
|
'true = puede visualizar/utilizar el módulo Tarifario; false = no tiene acceso al módulo.';
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- EJEMPLOS DE ADMINISTRACIÓN (NO se ejecutan automáticamente)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- DAR ACCESO AL TARIFARIO:
|
||||||
|
-- update public.cotizador_wmc_access
|
||||||
|
-- set can_use_tarifario = true
|
||||||
|
-- where email = 'iaracena@gomezleemarketing.com';
|
||||||
|
|
||||||
|
-- QUITAR ACCESO AL TARIFARIO:
|
||||||
|
-- update public.cotizador_wmc_access
|
||||||
|
-- set can_use_tarifario = false
|
||||||
|
-- where email = 'iaracena@gomezleemarketing.com';
|
||||||
|
|
||||||
|
-- Fuerza a PostgREST a refrescar el esquema inmediatamente si fuese necesario.
|
||||||
|
notify pgrst, 'reload schema';
|
||||||
@@ -0,0 +1,977 @@
|
|||||||
|
/**
|
||||||
|
* Cotizador Walmart Connect · Google Workspace Worker
|
||||||
|
* GomezLee Marketing · 2026
|
||||||
|
*
|
||||||
|
* Versión corregida para Google Apps Script V8.
|
||||||
|
* - NO usa variables de entorno.
|
||||||
|
* - NO usa Script Properties.
|
||||||
|
* - Gemini NO se llama desde Apps Script.
|
||||||
|
* - Las imágenes llegan desde los nodos nativos de Google Gemini en n8n.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const WMC_CONFIG = {
|
||||||
|
GOOGLE_AUTOMATION_SECRET: 'mwI_n-1r4_-QTLp1-zIt-zQKh_HqaoGoVhyapyLN2T2-r7xf8iP5AC3v9wJt5Av6',
|
||||||
|
OUTPUT_FOLDER_ID: '19EmZsJ7PzWCaFzeij9AZ3-mkPctNyK0G',
|
||||||
|
WALMART_TEMPLATE_ID: '17f1MB1uXQiQk4jn4_MPQixpBRwCpwDMZTsRmWA9UMOA',
|
||||||
|
GLM_MONTHLY_TEMPLATE_ID: '1RL9BckErp1QCLdxlM6riBRh9iO4f14ezf6fUgizBZJw',
|
||||||
|
|
||||||
|
// Confirmado en los ejemplos GLM enviados (Guatemala y Costa Rica).
|
||||||
|
GLM_VENDOR_NUMBER: '1603060802',
|
||||||
|
GLM_IVA_RATE: 0.12
|
||||||
|
};
|
||||||
|
|
||||||
|
const WMC = {
|
||||||
|
NAVY: '#041E42',
|
||||||
|
GREEN: '#6CC24A',
|
||||||
|
BLUE: '#4F758B',
|
||||||
|
TEXT: '#4A4A4A',
|
||||||
|
LIGHT: '#F5F5F5'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health check sencillo: al abrir la URL /exec en el navegador debe devolver JSON.
|
||||||
|
*/
|
||||||
|
function doGet() {
|
||||||
|
return json_({
|
||||||
|
ok: true,
|
||||||
|
service: 'Cotizador WMC · Google Workspace Worker',
|
||||||
|
version: '2026-08-23.3'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function doPost(e) {
|
||||||
|
try {
|
||||||
|
const body = JSON.parse((e && e.postData && e.postData.contents) || '{}');
|
||||||
|
requireSecret_(body.secret);
|
||||||
|
|
||||||
|
const action = String(body.action || '');
|
||||||
|
let result;
|
||||||
|
|
||||||
|
if (action === 'generate_quote') {
|
||||||
|
result = generateWalmartQuote_(body);
|
||||||
|
} else if (action === 'generate_monthly_glm') {
|
||||||
|
result = generateMonthlyGlm_(body);
|
||||||
|
} else if (action === 'generate_proposal') {
|
||||||
|
result = generateProposal_(body);
|
||||||
|
} else if (action === 'generate_image') {
|
||||||
|
result = generateImageArtifact_(body);
|
||||||
|
} else {
|
||||||
|
result = { ok: true, skipped: true, message: 'Acción sin artefacto.' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_(result);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err && err.stack ? err.stack : err);
|
||||||
|
return json_({
|
||||||
|
ok: false,
|
||||||
|
error: String(err && err.message ? err.message : err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function requireSecret_(value) {
|
||||||
|
if (!WMC_CONFIG.GOOGLE_AUTOMATION_SECRET || String(value || '') !== WMC_CONFIG.GOOGLE_AUTOMATION_SECRET) {
|
||||||
|
throw new Error('Solicitud no autorizada.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function json_(obj) {
|
||||||
|
return ContentService
|
||||||
|
.createTextOutput(JSON.stringify(obj))
|
||||||
|
.setMimeType(ContentService.MimeType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeName_(value, fallback) {
|
||||||
|
const s = String(value || fallback || 'WMC')
|
||||||
|
.replace(/[\\/:*?"<>|#%{}\[\]]+/g, ' ')
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
return s.slice(0, 160) || String(fallback || 'WMC');
|
||||||
|
}
|
||||||
|
|
||||||
|
function outputFolder_() {
|
||||||
|
return DriveApp.getFolderById(WMC_CONFIG.OUTPUT_FOLDER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyTemplate_(templateId, name) {
|
||||||
|
const file = DriveApp.getFileById(templateId);
|
||||||
|
return file.makeCopy(safeName_(name, 'WMC'), outputFolder_());
|
||||||
|
}
|
||||||
|
|
||||||
|
function norm_(v) {
|
||||||
|
return String(v || '')
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g, '')
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function findCell_(sheet, variants) {
|
||||||
|
const values = sheet.getDataRange().getDisplayValues();
|
||||||
|
const wanted = variants.map(function(v) { return norm_(v); });
|
||||||
|
|
||||||
|
for (let r = 0; r < values.length; r++) {
|
||||||
|
for (let c = 0; c < values[r].length; c++) {
|
||||||
|
const n = norm_(values[r][c]);
|
||||||
|
for (let i = 0; i < wanted.length; i++) {
|
||||||
|
const w = wanted[i];
|
||||||
|
if (n === w || n.indexOf(w + ':') === 0 || n.indexOf(w) >= 0) {
|
||||||
|
return { row: r + 1, col: c + 1, text: values[r][c] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findRow_(sheet, variants) {
|
||||||
|
const c = findCell_(sheet, variants);
|
||||||
|
return c ? c.row : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRightOfLabel_(sheet, variants, value) {
|
||||||
|
if (value === undefined || value === null || value === '') return false;
|
||||||
|
const cell = findCell_(sheet, variants);
|
||||||
|
if (!cell) return false;
|
||||||
|
sheet.getRange(cell.row, Math.min(cell.col + 1, sheet.getMaxColumns())).setValue(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function visibleFirstSheet_(ss) {
|
||||||
|
const sheets = ss.getSheets();
|
||||||
|
for (let i = 0; i < sheets.length; i++) {
|
||||||
|
if (!sheets[i].isSheetHidden()) return sheets[i];
|
||||||
|
}
|
||||||
|
return sheets[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function findExactTextRowInColumnAfter_(sheet, col, text, afterRow, beforeRow) {
|
||||||
|
const start = Math.max(1, Number(afterRow || 1));
|
||||||
|
const end = Math.min(sheet.getMaxRows(), Number(beforeRow || sheet.getMaxRows()));
|
||||||
|
if (end < start) return null;
|
||||||
|
|
||||||
|
const values = sheet.getRange(start, col, end - start + 1, 1).getDisplayValues();
|
||||||
|
const wanted = norm_(text);
|
||||||
|
|
||||||
|
for (let i = 0; i < values.length; i++) {
|
||||||
|
if (norm_(values[i][0]) === wanted) return start + i;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function firstNumber_() {
|
||||||
|
for (let i = 0; i < arguments.length; i++) {
|
||||||
|
const v = arguments[i];
|
||||||
|
if (v === '' || v === null || v === undefined) continue;
|
||||||
|
const n = Number(v);
|
||||||
|
if (Number.isFinite(n)) return n;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function numOrBlank_(v) {
|
||||||
|
if (v === '' || v === null || v === undefined) return '';
|
||||||
|
const n = Number(v);
|
||||||
|
return Number.isFinite(n) ? n : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function countryCurrencyCode_(code) {
|
||||||
|
const map = { GT: 'GTQ', CR: 'CRC', SV: 'USD', HN: 'HNL', NI: 'NIO' };
|
||||||
|
return map[String(code || '').toUpperCase()] || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function countryCurrencySymbol_(code) {
|
||||||
|
const map = { GT: 'Q', CR: '₡', SV: '$', HN: 'L', NI: 'C$' };
|
||||||
|
return map[String(code || '').toUpperCase()] || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// NORMALIZACIÓN FINANCIERA DEFENSIVA
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function money_(value) {
|
||||||
|
const n = Number(value);
|
||||||
|
if (!Number.isFinite(n)) return 0;
|
||||||
|
return Math.round((n + Number.EPSILON) * 100) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFeeSection_(section) {
|
||||||
|
return norm_(section).indexOf('fee') >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeWalmartQuoteFinancials_(input) {
|
||||||
|
const q = JSON.parse(JSON.stringify(input || {}));
|
||||||
|
const rateRaw = Number(q.exchangeRate !== undefined ? q.exchangeRate : q.exchange_rate);
|
||||||
|
const rate = Number.isFinite(rateRaw) && rateRaw > 0 ? rateRaw : 1;
|
||||||
|
const items = Array.isArray(q.items) ? q.items : [];
|
||||||
|
|
||||||
|
let subtotalUsd = 0;
|
||||||
|
let explicitFeeUsd = 0;
|
||||||
|
|
||||||
|
q.items = items.map(function(raw) {
|
||||||
|
const it = raw && typeof raw === 'object' ? raw : {};
|
||||||
|
const units = firstNumber_(it.units, it.quantity, 0);
|
||||||
|
const days = (it.days === '' || it.days === null || it.days === undefined)
|
||||||
|
? 1
|
||||||
|
: firstNumber_(it.days, 1);
|
||||||
|
const unitUsd = firstNumber_(it.unitCostUsd, it.unit_cost_usd, 0);
|
||||||
|
const suppliedTotal = firstNumber_(it.totalUsd, it.total_usd, 0);
|
||||||
|
const computedTotal = money_(Number(units || 0) * Number(days || 0) * Number(unitUsd || 0));
|
||||||
|
const totalUsd = Number(unitUsd || 0) > 0 && Number(units || 0) > 0
|
||||||
|
? computedTotal
|
||||||
|
: money_(suppliedTotal || 0);
|
||||||
|
|
||||||
|
const normalized = Object.assign({}, it, {
|
||||||
|
units: Number(units || 0),
|
||||||
|
days: Number(days || 0),
|
||||||
|
unitCostUsd: money_(unitUsd || 0),
|
||||||
|
totalUsd: totalUsd,
|
||||||
|
unitCostLocal: money_(Number(unitUsd || 0) * rate),
|
||||||
|
totalLocal: money_(totalUsd * rate)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isFeeSection_(it.section)) explicitFeeUsd += totalUsd;
|
||||||
|
else subtotalUsd += totalUsd;
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
});
|
||||||
|
|
||||||
|
subtotalUsd = money_(subtotalUsd);
|
||||||
|
let feeRate = firstNumber_(q.agencyFeeRate, q.feeRate);
|
||||||
|
if (feeRate === null && explicitFeeUsd > 0 && subtotalUsd > 0) feeRate = explicitFeeUsd / subtotalUsd;
|
||||||
|
if (feeRate === null || !Number.isFinite(feeRate) || feeRate < 0) feeRate = 0.06;
|
||||||
|
if (feeRate > 1) feeRate = feeRate / 100;
|
||||||
|
|
||||||
|
const feeUsd = money_(subtotalUsd * feeRate);
|
||||||
|
q.exchangeRate = rate;
|
||||||
|
q.agencyFeeRate = feeRate;
|
||||||
|
q.subtotalUsd = subtotalUsd;
|
||||||
|
q.subtotalLocal = money_(subtotalUsd * rate);
|
||||||
|
q.agencyFeeUsd = feeUsd;
|
||||||
|
q.agencyFeeLocal = money_(feeUsd * rate);
|
||||||
|
q.totalUsd = money_(subtotalUsd + feeUsd);
|
||||||
|
q.totalLocal = money_(q.totalUsd * rate);
|
||||||
|
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readWalmartGrandTotals_(sheet, q) {
|
||||||
|
const totalCell = findCell_(sheet, ['Total con todos los rubros', 'Total general']);
|
||||||
|
if (!totalCell) {
|
||||||
|
return {
|
||||||
|
totalUsd: money_(q.totalUsd || 0),
|
||||||
|
totalLocal: money_(q.totalLocal || 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const row = totalCell.row;
|
||||||
|
const usd = Number(sheet.getRange(row, 5).getValue());
|
||||||
|
const local = Number(sheet.getRange(row, 7).getValue());
|
||||||
|
return {
|
||||||
|
totalUsd: Number.isFinite(usd) ? money_(usd) : money_(q.totalUsd || 0),
|
||||||
|
totalLocal: Number.isFinite(local) ? money_(local) : money_(q.totalLocal || 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 1) COTIZACIÓN OFICIAL WALMART CONNECT
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function generateWalmartQuote_(body) {
|
||||||
|
const q = normalizeWalmartQuoteFinancials_(body.quote || {});
|
||||||
|
if (!q.countryCode || !Array.isArray(q.items) || !q.items.length) {
|
||||||
|
throw new Error('La cotización no contiene país/items suficientes.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const stamp = Utilities.formatDate(
|
||||||
|
new Date(),
|
||||||
|
Session.getScriptTimeZone() || 'America/Guatemala',
|
||||||
|
'yyyyMMdd-HHmm'
|
||||||
|
);
|
||||||
|
|
||||||
|
const name = safeName_(
|
||||||
|
'WMC_' + (q.project || q.advertiser || 'Cotizacion') + '_' + q.countryCode + '_' + stamp,
|
||||||
|
'WMC_Cotizacion'
|
||||||
|
);
|
||||||
|
|
||||||
|
const file = copyTemplate_(WMC_CONFIG.WALMART_TEMPLATE_ID, name);
|
||||||
|
const ss = SpreadsheetApp.openById(file.getId());
|
||||||
|
const sheet = ss.getSheetByName('Solicitud Cotizaciones') || visibleFirstSheet_(ss);
|
||||||
|
|
||||||
|
setRightOfLabel_(sheet, ['Brand Solution'], q.brandSolution || 'WMC');
|
||||||
|
setRightOfLabel_(sheet, ['País', 'Pais'], q.country || q.countryCode);
|
||||||
|
setRightOfLabel_(sheet, ['Agencia'], 'GomezLee Marketing S.A.');
|
||||||
|
setRightOfLabel_(sheet, ['Proyecto'], q.project || '');
|
||||||
|
setRightOfLabel_(sheet, ['Anunciante'], q.advertiser || '');
|
||||||
|
setRightOfLabel_(sheet, ['Formato'], q.format || '');
|
||||||
|
setRightOfLabel_(sheet, ['Tipo de cambio'], Number(q.exchangeRate || 1));
|
||||||
|
|
||||||
|
const sectionDefs = [
|
||||||
|
{ key: 'Personal', aliases: ['Personal'] },
|
||||||
|
{ key: 'Mobiliario - Equipo', aliases: ['Mobiliario - Equipo', 'Mobiliario y Equipo', 'Mobiliario'] },
|
||||||
|
{ key: 'Insumos de degustación y/o preparación', aliases: ['Insumos de degustación y/o preparación', 'Insumos de degustación', 'Insumos'] },
|
||||||
|
{ key: 'Logística e Instalación', aliases: ['Logística e Instalación', 'Logistica e Instalación', 'Logistica e Instalacion', 'Logística', 'Logistica'] }
|
||||||
|
];
|
||||||
|
|
||||||
|
const grouped = {};
|
||||||
|
for (let i = 0; i < q.items.length; i++) {
|
||||||
|
const it = q.items[i] || {};
|
||||||
|
const section = String(it.section || 'Otros');
|
||||||
|
if (!grouped[section]) grouped[section] = [];
|
||||||
|
grouped[section].push(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// De abajo hacia arriba para que las inserciones no desplacen secciones todavía no procesadas.
|
||||||
|
const results = [];
|
||||||
|
for (let i = sectionDefs.length - 1; i >= 0; i--) {
|
||||||
|
const def = sectionDefs[i];
|
||||||
|
const items = getItemsForSection_(q.items, def.aliases);
|
||||||
|
results.push(fillWalmartSection_(sheet, def.aliases, items));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reordenamos para cálculos posteriores.
|
||||||
|
const sectionTotals = [];
|
||||||
|
for (let i = 0; i < sectionDefs.length; i++) {
|
||||||
|
const headerRow = findRow_(sheet, sectionDefs[i].aliases);
|
||||||
|
if (!headerRow) continue;
|
||||||
|
const totalRow = findExactTextRowInColumnAfter_(sheet, 1, 'Total', headerRow + 1);
|
||||||
|
if (totalRow) sectionTotals.push(totalRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
configureWalmartFee_(sheet, q, sectionTotals);
|
||||||
|
configureWalmartGrandTotal_(sheet, sectionTotals);
|
||||||
|
|
||||||
|
setRightOfLabel_(sheet, ['Vigencia de la cotización', 'Vigencia'], q.validity || '30 días');
|
||||||
|
setRightOfLabel_(
|
||||||
|
sheet,
|
||||||
|
['Observaciones o exclusiones', 'Observaciones'],
|
||||||
|
Array.isArray(q.observations) ? q.observations.join('\n') : (q.observations || '')
|
||||||
|
);
|
||||||
|
|
||||||
|
insertVisualReferences_(sheet, q.visualReferences || []);
|
||||||
|
|
||||||
|
// Forzamos el recálculo del machote y guardamos en la trazabilidad los mismos
|
||||||
|
// totales finales que ve el usuario en la hoja (incluyendo Fee de agencia).
|
||||||
|
SpreadsheetApp.flush();
|
||||||
|
const finalTotals = readWalmartGrandTotals_(sheet, q);
|
||||||
|
q.totalUsd = finalTotals.totalUsd;
|
||||||
|
q.totalLocal = finalTotals.totalLocal;
|
||||||
|
|
||||||
|
let data = ss.getSheetByName('_WMC_DATA');
|
||||||
|
if (!data) data = ss.insertSheet('_WMC_DATA');
|
||||||
|
data.clear();
|
||||||
|
data.getRange('A1:B8').setValues([
|
||||||
|
['generatedAt', new Date()],
|
||||||
|
['countryCode', q.countryCode],
|
||||||
|
['currencyCode', q.currencyCode || countryCurrencyCode_(q.countryCode)],
|
||||||
|
['exchangeRate', Number(q.exchangeRate || 1)],
|
||||||
|
['totalUsd', Number(q.totalUsd || 0)],
|
||||||
|
['totalLocal', Number(q.totalLocal || 0)],
|
||||||
|
['conversationId', body.conversationId || ''],
|
||||||
|
['quoteJson', JSON.stringify(q)]
|
||||||
|
]);
|
||||||
|
data.hideSheet();
|
||||||
|
|
||||||
|
try {
|
||||||
|
sheet.setName(safeName_('Cotización ' + (q.format || '') + ' ' + q.countryCode, 'Cotización').slice(0, 99));
|
||||||
|
} catch (ignore) {}
|
||||||
|
|
||||||
|
SpreadsheetApp.flush();
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
artifactType: 'quote',
|
||||||
|
artifactId: file.getId(),
|
||||||
|
artifactUrl: ss.getUrl(),
|
||||||
|
title: name,
|
||||||
|
provider: 'Google Sheets'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getItemsForSection_(items, aliases) {
|
||||||
|
const wanted = aliases.map(function(v) { return norm_(v); });
|
||||||
|
const out = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const it = items[i] || {};
|
||||||
|
const section = norm_(it.section || '');
|
||||||
|
let match = false;
|
||||||
|
|
||||||
|
for (let j = 0; j < wanted.length; j++) {
|
||||||
|
if (section === wanted[j] || section.indexOf(wanted[j]) >= 0 || wanted[j].indexOf(section) >= 0) {
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) out.push(it);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillWalmartSection_(sheet, aliases, items) {
|
||||||
|
const headerRow = findRow_(sheet, aliases);
|
||||||
|
if (!headerRow) return { headerRow: null, totalRow: null };
|
||||||
|
|
||||||
|
let totalRow = findExactTextRowInColumnAfter_(sheet, 1, 'Total', headerRow + 1);
|
||||||
|
if (!totalRow) throw new Error('No se encontró la fila Total para la sección ' + aliases[0] + '.');
|
||||||
|
|
||||||
|
const start = headerRow + 1;
|
||||||
|
let slots = totalRow - start;
|
||||||
|
const needed = Math.max(1, items.length);
|
||||||
|
|
||||||
|
if (needed > slots) {
|
||||||
|
const extra = needed - slots;
|
||||||
|
sheet.insertRowsBefore(totalRow, extra);
|
||||||
|
|
||||||
|
if (slots > 0) {
|
||||||
|
sheet.getRange(start, 1, 1, 7).copyTo(
|
||||||
|
sheet.getRange(totalRow, 1, extra, 7),
|
||||||
|
SpreadsheetApp.CopyPasteType.PASTE_FORMAT,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalRow += extra;
|
||||||
|
slots += extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limpia únicamente las filas de detalle; nunca toca la fila Total.
|
||||||
|
if (slots > 0) sheet.getRange(start, 1, slots, 7).clearContent();
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const row = start + i;
|
||||||
|
const it = items[i] || {};
|
||||||
|
|
||||||
|
sheet.getRange(row, 1, 1, 4).setValues([[
|
||||||
|
it.description || 'Item',
|
||||||
|
numOrBlank_(it.units),
|
||||||
|
numOrBlank_(it.days),
|
||||||
|
numOrBlank_(it.unitCostUsd)
|
||||||
|
]]);
|
||||||
|
|
||||||
|
sheet.getRange(row, 5).setFormula('=B' + row + '*C' + row + '*D' + row);
|
||||||
|
sheet.getRange(row, 6).setFormula('=D' + row + '*$B$11');
|
||||||
|
sheet.getRange(row, 7).setFormula('=E' + row + '*$B$11');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mantiene fórmulas neutras en espacios libres para que el subtotal siga siendo confiable.
|
||||||
|
for (let r = start + items.length; r < totalRow; r++) {
|
||||||
|
sheet.getRange(r, 5).setFormula('=B' + r + '*C' + r + '*D' + r);
|
||||||
|
sheet.getRange(r, 6).setFormula('=D' + r + '*$B$11');
|
||||||
|
sheet.getRange(r, 7).setFormula('=E' + r + '*$B$11');
|
||||||
|
}
|
||||||
|
|
||||||
|
const end = totalRow - 1;
|
||||||
|
sheet.getRange(totalRow, 4).setFormula('=SUM(D' + start + ':D' + end + ')');
|
||||||
|
sheet.getRange(totalRow, 5).setFormula('=SUM(E' + start + ':E' + end + ')');
|
||||||
|
sheet.getRange(totalRow, 6).setFormula('=SUM(F' + start + ':F' + end + ')');
|
||||||
|
sheet.getRange(totalRow, 7).setFormula('=SUM(G' + start + ':G' + end + ')');
|
||||||
|
|
||||||
|
sheet.getRange(start, 4, Math.max(1, slots), 2).setNumberFormat('$#,##0.00;[Red]-$#,##0.00');
|
||||||
|
sheet.getRange(start, 6, Math.max(1, slots), 2).setNumberFormat('#,##0.00;[Red]-#,##0.00');
|
||||||
|
|
||||||
|
return { headerRow: headerRow, totalRow: totalRow };
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureWalmartFee_(sheet, q, sectionTotalRows) {
|
||||||
|
const feeHeader = findRow_(sheet, ['Fee de agencia', 'Fee Agencia', 'Fee']);
|
||||||
|
if (!feeHeader) return;
|
||||||
|
|
||||||
|
const feeCalcRow = feeHeader + 1;
|
||||||
|
let feeRate = firstNumber_(q.agencyFeeRate, q.feeRate);
|
||||||
|
|
||||||
|
const feeItems = getItemsForSection_(q.items || [], ['Fee de agencia', 'Fee Agencia', 'Fee']);
|
||||||
|
if (feeRate === null && feeItems.length) {
|
||||||
|
const baseUsd = sumItemTotals_(q.items || [], false);
|
||||||
|
const feeUsd = sumItemTotals_(feeItems, true);
|
||||||
|
if (baseUsd > 0 && feeUsd >= 0) feeRate = feeUsd / baseUsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si Gemini no suministra un fee explícito, conserva el 6% del machote oficial.
|
||||||
|
if (feeRate === null || !Number.isFinite(feeRate) || feeRate < 0) {
|
||||||
|
const current = Number(sheet.getRange(feeHeader, 4).getValue());
|
||||||
|
feeRate = Number.isFinite(current) && current >= 0 ? current : 0.06;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feeRate > 1) feeRate = feeRate / 100;
|
||||||
|
|
||||||
|
sheet.getRange(feeHeader, 4).setValue(feeRate).setNumberFormat('0.00%');
|
||||||
|
sheet.getRange(feeHeader, 6).setValue(feeRate).setNumberFormat('0.00%');
|
||||||
|
|
||||||
|
const dRefs = sectionTotalRows.map(function(r) { return 'D' + r; });
|
||||||
|
const eRefs = sectionTotalRows.map(function(r) { return 'E' + r; });
|
||||||
|
const fRefs = sectionTotalRows.map(function(r) { return 'F' + r; });
|
||||||
|
const gRefs = sectionTotalRows.map(function(r) { return 'G' + r; });
|
||||||
|
|
||||||
|
sheet.getRange(feeCalcRow, 4).setFormula('=(' + dRefs.join('+') + ')*D' + feeHeader);
|
||||||
|
sheet.getRange(feeCalcRow, 5).setFormula('=(' + eRefs.join('+') + ')*D' + feeHeader);
|
||||||
|
sheet.getRange(feeCalcRow, 6).setFormula('=(' + fRefs.join('+') + ')*F' + feeHeader);
|
||||||
|
sheet.getRange(feeCalcRow, 7).setFormula('=(' + gRefs.join('+') + ')*F' + feeHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureWalmartGrandTotal_(sheet, sectionTotalRows) {
|
||||||
|
const totalCell = findCell_(sheet, ['Total con todos los rubros', 'Total general']);
|
||||||
|
if (!totalCell) return;
|
||||||
|
|
||||||
|
const grandRow = totalCell.row;
|
||||||
|
const feeHeader = findRow_(sheet, ['Fee de agencia', 'Fee Agencia', 'Fee']);
|
||||||
|
const feeCalcRow = feeHeader ? feeHeader + 1 : null;
|
||||||
|
|
||||||
|
const cols = [4, 5, 6, 7];
|
||||||
|
for (let i = 0; i < cols.length; i++) {
|
||||||
|
const col = cols[i];
|
||||||
|
const letter = columnLetter_(col);
|
||||||
|
const refs = sectionTotalRows.map(function(r) { return letter + r; });
|
||||||
|
if (feeCalcRow) refs.push(letter + feeCalcRow);
|
||||||
|
sheet.getRange(grandRow, col).setFormula('=' + refs.join('+'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sumItemTotals_(items, includeAll) {
|
||||||
|
let total = 0;
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const it = items[i] || {};
|
||||||
|
if (!includeAll && norm_(it.section || '').indexOf('fee') >= 0) continue;
|
||||||
|
const n = firstNumber_(it.totalUsd, it.total_usd);
|
||||||
|
if (n !== null) total += n;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
function columnLetter_(col) {
|
||||||
|
let n = Number(col);
|
||||||
|
let s = '';
|
||||||
|
while (n > 0) {
|
||||||
|
const rem = (n - 1) % 26;
|
||||||
|
s = String.fromCharCode(65 + rem) + s;
|
||||||
|
n = Math.floor((n - 1) / 26);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 2) REFERENCIAS VISUALES
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function insertVisualReferences_(sheet, refs) {
|
||||||
|
if (!Array.isArray(refs) || !refs.length) return;
|
||||||
|
|
||||||
|
const row = findRow_(sheet, ['Referencias visuales', 'Referencia visual']);
|
||||||
|
if (!row) return;
|
||||||
|
|
||||||
|
let col = 1;
|
||||||
|
refs.slice(0, 6).forEach(function(ref) {
|
||||||
|
try {
|
||||||
|
const blob = visualBlob_(ref);
|
||||||
|
if (!blob) return;
|
||||||
|
|
||||||
|
const img = sheet.insertImage(blob, col, row + 1);
|
||||||
|
const maxW = 360;
|
||||||
|
const maxH = 260;
|
||||||
|
const scale = Math.min(1, maxW / img.getWidth(), maxH / img.getHeight());
|
||||||
|
|
||||||
|
img.setWidth(Math.round(img.getWidth() * scale));
|
||||||
|
img.setHeight(Math.round(img.getHeight() * scale));
|
||||||
|
col = Math.min(col + 4, Math.max(1, sheet.getMaxColumns() - 1));
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('No se pudo insertar referencia visual: ' + err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function driveIdFromUrl_(url) {
|
||||||
|
const text = String(url || '');
|
||||||
|
let m = text.match(/\/d\/([a-zA-Z0-9_-]{15,})/);
|
||||||
|
if (m) return m[1];
|
||||||
|
m = text.match(/[?&]id=([a-zA-Z0-9_-]{15,})/);
|
||||||
|
return m ? m[1] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function visualBlob_(ref) {
|
||||||
|
const obj = ref && typeof ref === 'object' ? ref : {};
|
||||||
|
const directId = String(obj.imageDriveId || obj.driveId || obj.fileId || '').trim();
|
||||||
|
if (directId) return DriveApp.getFileById(directId).getBlob();
|
||||||
|
|
||||||
|
const url = typeof ref === 'string' ? ref : String(obj.url || obj.imageUrl || '').trim();
|
||||||
|
if (!url) return null;
|
||||||
|
|
||||||
|
const driveId = driveIdFromUrl_(url);
|
||||||
|
if (driveId) return DriveApp.getFileById(driveId).getBlob();
|
||||||
|
|
||||||
|
const response = UrlFetchApp.fetch(url, {
|
||||||
|
muteHttpExceptions: true,
|
||||||
|
followRedirects: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.getResponseCode() < 200 || response.getResponseCode() >= 300) {
|
||||||
|
throw new Error('No se pudo descargar la referencia visual. HTTP ' + response.getResponseCode());
|
||||||
|
}
|
||||||
|
return response.getBlob();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 3) MENSUALIZACIÓN INTERNA GLM
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function generateMonthlyGlm_(body) {
|
||||||
|
const q = body.quote || {};
|
||||||
|
const a = body.artifact || {};
|
||||||
|
const metadata = a.metadata && typeof a.metadata === 'object' ? a.metadata : {};
|
||||||
|
|
||||||
|
const stamp = Utilities.formatDate(
|
||||||
|
new Date(),
|
||||||
|
Session.getScriptTimeZone() || 'America/Guatemala',
|
||||||
|
'yyyyMMdd-HHmm'
|
||||||
|
);
|
||||||
|
|
||||||
|
const name = safeName_(
|
||||||
|
'GLM-' + (q.project || a.title || 'WMC') + '_' + (q.countryCode || '') + '_' + stamp,
|
||||||
|
'GLM-WMC'
|
||||||
|
);
|
||||||
|
|
||||||
|
const file = copyTemplate_(WMC_CONFIG.GLM_MONTHLY_TEMPLATE_ID, name);
|
||||||
|
const ss = SpreadsheetApp.openById(file.getId());
|
||||||
|
const sheet = ss.getSheetByName('Cotización') || visibleFirstSheet_(ss);
|
||||||
|
|
||||||
|
const country = q.country || q.countryName || q.countryCode || '';
|
||||||
|
const countryCode = String(q.countryCode || '').toUpperCase();
|
||||||
|
const advertiser = q.advertiser || a.client || '';
|
||||||
|
const project = q.project || a.project || q.format || 'Cotización Walmart Connect';
|
||||||
|
const contact = a.attention || metadata.attention || q.contactName || q.contact_name || '';
|
||||||
|
const email = a.email || metadata.email || q.contactEmail || q.contact_email || (body.user ? body.user.email : '') || '';
|
||||||
|
const currencySymbol = a.currencySymbol || metadata.currencySymbol || q.currencySymbol || countryCurrencySymbol_(countryCode);
|
||||||
|
const vendor = a.vendorNumber || metadata.vendorNumber || WMC_CONFIG.GLM_VENDOR_NUMBER;
|
||||||
|
const quoteCode = a.quoteCode || metadata.quoteCode || q.quoteCode || q.quote_code || '';
|
||||||
|
|
||||||
|
// El formato GLM real guarda estos valores dentro de la misma celda A6:A12.
|
||||||
|
sheet.getRange('A6').setValue('País: ' + country);
|
||||||
|
sheet.getRange('E6').setValue(quoteCode);
|
||||||
|
sheet.getRange('A7').setValue('Empresa: Walmart Connect');
|
||||||
|
sheet.getRange('A8').setValue('Asunto: ' + project);
|
||||||
|
sheet.getRange('A9').setValue('Atención:' + contact);
|
||||||
|
sheet.getRange('A10').setValue('Correo:' + email);
|
||||||
|
sheet.getRange('A11').setValue('Moneda: ' + currencySymbol);
|
||||||
|
sheet.getRange('A12').setValue('Vendor #: ' + vendor);
|
||||||
|
|
||||||
|
const summaryTitle = a.summaryTitle || metadata.summaryTitle || ('Walmart Connect-' + (advertiser || project));
|
||||||
|
sheet.getRange('A14').setValue(summaryTitle);
|
||||||
|
|
||||||
|
const monthlyDate = parseDateOrNow_(a.monthlyDate || metadata.monthlyDate || a.date || metadata.date);
|
||||||
|
sheet.getRange('A15').setValue(monthlyDate).setNumberFormat('mmmm yyyy');
|
||||||
|
sheet.getRange('B17').setValue(country);
|
||||||
|
|
||||||
|
const lines = Array.isArray(a.monthlyLines) && a.monthlyLines.length
|
||||||
|
? a.monthlyLines
|
||||||
|
: (Array.isArray(q.items) ? q.items : []);
|
||||||
|
|
||||||
|
const activity = fillGlmActivityLines_(sheet, lines, q, a, metadata);
|
||||||
|
refreshGlmBudgetSummary_(sheet, activity);
|
||||||
|
|
||||||
|
let data = ss.getSheetByName('_WMC_MONTHLY_DATA');
|
||||||
|
if (!data) data = ss.insertSheet('_WMC_MONTHLY_DATA');
|
||||||
|
data.clear();
|
||||||
|
data.getRange('A1:B7').setValues([
|
||||||
|
['generatedAt', new Date()],
|
||||||
|
['countryCode', countryCode],
|
||||||
|
['currency', currencySymbol],
|
||||||
|
['sourceQuoteId', a.sourceQuoteId || ''],
|
||||||
|
['conversationId', body.conversationId || ''],
|
||||||
|
['quoteJson', JSON.stringify(q)],
|
||||||
|
['artifactJson', JSON.stringify(a)]
|
||||||
|
]);
|
||||||
|
data.hideSheet();
|
||||||
|
|
||||||
|
SpreadsheetApp.flush();
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
artifactType: 'monthly_glm',
|
||||||
|
artifactId: file.getId(),
|
||||||
|
artifactUrl: ss.getUrl(),
|
||||||
|
title: name,
|
||||||
|
provider: 'Google Sheets'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillGlmActivityLines_(sheet, lines, quote, artifact, metadata) {
|
||||||
|
const header = findCell_(sheet, ['DESCRIPCIÓN', 'Descripcion', 'Descripción']);
|
||||||
|
if (!header) throw new Error('No se encontró el encabezado DESCRIPCIÓN en la plantilla GLM.');
|
||||||
|
|
||||||
|
const start = header.row + 1;
|
||||||
|
let totalRow = findExactTextRowInColumnAfter_(sheet, 4, 'Total', start);
|
||||||
|
if (!totalRow) throw new Error('No se encontró la primera fila Total del bloque de actividades GLM.');
|
||||||
|
|
||||||
|
let slots = totalRow - start;
|
||||||
|
const needed = Math.max(1, lines.length);
|
||||||
|
|
||||||
|
if (needed > slots) {
|
||||||
|
const extra = needed - slots;
|
||||||
|
sheet.insertRowsBefore(totalRow, extra);
|
||||||
|
|
||||||
|
if (slots > 0) {
|
||||||
|
sheet.getRange(start, 1, 1, 5).copyTo(
|
||||||
|
sheet.getRange(totalRow, 1, extra, 5),
|
||||||
|
SpreadsheetApp.CopyPasteType.PASTE_FORMAT,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalRow += extra;
|
||||||
|
slots += extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slots > 0) sheet.getRange(start, 1, slots, 5).clearContent();
|
||||||
|
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const row = start + i;
|
||||||
|
const it = lines[i] || {};
|
||||||
|
const qty = firstNumber_(it.units, it.quantity, 1);
|
||||||
|
const days = firstNumber_(it.days, 1);
|
||||||
|
const localUnit = firstNumber_(
|
||||||
|
it.unitCostLocal,
|
||||||
|
it.unit_cost_local,
|
||||||
|
firstNumber_(it.unitCostUsd, it.unit_cost_usd, 0) * firstNumber_(quote.exchangeRate, quote.exchange_rate, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
sheet.getRange(row, 1, 1, 4).setValues([[
|
||||||
|
it.description || it.concept || it.item_name || 'Item',
|
||||||
|
qty,
|
||||||
|
days,
|
||||||
|
localUnit
|
||||||
|
]]);
|
||||||
|
sheet.getRange(row, 5).setFormula('=D' + row + '*B' + row + '*C' + row);
|
||||||
|
}
|
||||||
|
|
||||||
|
const end = totalRow - 1;
|
||||||
|
sheet.getRange(totalRow, 4).setValue('Total ');
|
||||||
|
sheet.getRange(totalRow, 5).setFormula('=SUM(E' + start + ':E' + end + ')');
|
||||||
|
|
||||||
|
const taxRow = totalRow + 1;
|
||||||
|
const grandRow = totalRow + 2;
|
||||||
|
let taxRate = firstNumber_(artifact.taxRate, metadata.taxRate, WMC_CONFIG.GLM_IVA_RATE);
|
||||||
|
if (taxRate > 1) taxRate = taxRate / 100;
|
||||||
|
|
||||||
|
sheet.getRange(taxRow, 4).setValue('IVA ');
|
||||||
|
sheet.getRange(taxRow, 5).setFormula('=E' + totalRow + '*' + taxRate);
|
||||||
|
sheet.getRange(grandRow, 4).setValue('Total ');
|
||||||
|
sheet.getRange(grandRow, 5).setFormula('=E' + totalRow + '+E' + taxRow);
|
||||||
|
|
||||||
|
sheet.getRange(start, 4, Math.max(1, slots), 2).setNumberFormat('#,##0.00;[Red]-#,##0.00');
|
||||||
|
sheet.getRange(totalRow, 5, 3, 1).setNumberFormat('#,##0.00;[Red]-#,##0.00');
|
||||||
|
|
||||||
|
return {
|
||||||
|
startRow: start,
|
||||||
|
endRow: end,
|
||||||
|
totalRow: totalRow,
|
||||||
|
taxRow: taxRow,
|
||||||
|
grandRow: grandRow
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshGlmBudgetSummary_(sheet, activity) {
|
||||||
|
const pmCell = findCell_(sheet, ['Project Management']);
|
||||||
|
let pmTotalRow = null;
|
||||||
|
|
||||||
|
if (pmCell) {
|
||||||
|
// En el machote GLM real, el total de Project Management es el último Total antes de Presupuesto.
|
||||||
|
const presupuestoCell = findCell_(sheet, ['Presupuesto']);
|
||||||
|
const before = presupuestoCell ? presupuestoCell.row - 1 : sheet.getMaxRows();
|
||||||
|
|
||||||
|
for (let r = before; r > pmCell.row; r--) {
|
||||||
|
const d = norm_(sheet.getRange(r, 4).getDisplayValue());
|
||||||
|
if (d === 'total') {
|
||||||
|
pmTotalRow = r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sinFee = findCell_(sheet, ['Sub-Total-1 Presupuesto actividades SIN FEE']);
|
||||||
|
const conFee = findCell_(sheet, ['Sub-Total-1 Presupuesto actividades CON FEE']);
|
||||||
|
const totalActividad = findCell_(sheet, ['Total De Actividad', 'Total de Actividad']);
|
||||||
|
|
||||||
|
if (sinFee) {
|
||||||
|
if (pmTotalRow) sheet.getRange(sinFee.row, 2).setFormula('=E' + pmTotalRow);
|
||||||
|
else sheet.getRange(sinFee.row, 2).setValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conFee) sheet.getRange(conFee.row, 2).setFormula('=E' + activity.grandRow);
|
||||||
|
|
||||||
|
if (totalActividad) {
|
||||||
|
const refs = [];
|
||||||
|
if (sinFee) refs.push('B' + sinFee.row);
|
||||||
|
if (conFee) refs.push('B' + conFee.row);
|
||||||
|
if (refs.length) sheet.getRange(totalActividad.row, 2).setFormula('=' + refs.join('+'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDateOrNow_(value) {
|
||||||
|
if (value instanceof Date && !isNaN(value.getTime())) return value;
|
||||||
|
if (value) {
|
||||||
|
const d = new Date(value);
|
||||||
|
if (!isNaN(d.getTime())) return d;
|
||||||
|
}
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 4) GOOGLE SLIDES
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function generateProposal_(body) {
|
||||||
|
const a = body.artifact || {};
|
||||||
|
const q = body.quote || {};
|
||||||
|
const title = safeName_(a.title || q.project || 'Propuesta Walmart Connect', 'Propuesta Walmart Connect');
|
||||||
|
|
||||||
|
const pres = SlidesApp.create(title);
|
||||||
|
const file = DriveApp.getFileById(pres.getId());
|
||||||
|
file.moveTo(outputFolder_());
|
||||||
|
|
||||||
|
const slides = Array.isArray(a.slides) && a.slides.length
|
||||||
|
? a.slides
|
||||||
|
: [
|
||||||
|
{ type: 'cover', title: title, subtitle: 'Walmart Connect' },
|
||||||
|
{ type: 'thankyou', title: 'Thank you!' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Primero agrega las nuevas diapositivas y al final elimina la inicial automática.
|
||||||
|
const initialSlide = pres.getSlides().length ? pres.getSlides()[0] : null;
|
||||||
|
for (let i = 0; i < slides.length; i++) {
|
||||||
|
addProposalSlide_(pres, slides[i], body, i);
|
||||||
|
}
|
||||||
|
if (initialSlide && pres.getSlides().length > 1) initialSlide.remove();
|
||||||
|
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
artifactType: 'proposal',
|
||||||
|
artifactId: pres.getId(),
|
||||||
|
artifactUrl: pres.getUrl(),
|
||||||
|
title: title,
|
||||||
|
provider: 'Google Slides'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function addProposalSlide_(pres, spec, body, index) {
|
||||||
|
const type = String(spec.type || 'content');
|
||||||
|
const slide = pres.appendSlide(SlidesApp.PredefinedLayout.BLANK);
|
||||||
|
const pageW = pres.getPageWidth();
|
||||||
|
const pageH = pres.getPageHeight();
|
||||||
|
const dark = type === 'cover' || type === 'section' || type === 'thankyou';
|
||||||
|
|
||||||
|
slide.getBackground().setSolidFill(dark ? WMC.NAVY : '#FFFFFF');
|
||||||
|
|
||||||
|
const titleText = String(spec.title || (index === 0 ? (body.title || 'Walmart Connect') : ''));
|
||||||
|
const titleBox = slide.insertTextBox(
|
||||||
|
titleText,
|
||||||
|
dark ? 48 : 44,
|
||||||
|
dark ? pageH * 0.38 : 28,
|
||||||
|
pageW - 96,
|
||||||
|
dark ? 90 : 48
|
||||||
|
);
|
||||||
|
|
||||||
|
titleBox.getText().getTextStyle()
|
||||||
|
.setFontFamily('Arial')
|
||||||
|
.setFontSize(dark ? 28 : 22)
|
||||||
|
.setBold(true)
|
||||||
|
.setForegroundColor(dark ? '#FFFFFF' : WMC.NAVY);
|
||||||
|
|
||||||
|
titleBox.getText().getParagraphStyle().setParagraphAlignment(
|
||||||
|
dark ? SlidesApp.ParagraphAlignment.CENTER : SlidesApp.ParagraphAlignment.START
|
||||||
|
);
|
||||||
|
|
||||||
|
const sub = String(spec.subtitle || spec.body || '');
|
||||||
|
if (sub) {
|
||||||
|
const subBox = slide.insertTextBox(
|
||||||
|
sub,
|
||||||
|
52,
|
||||||
|
dark ? pageH * 0.57 : 82,
|
||||||
|
pageW - 104,
|
||||||
|
70
|
||||||
|
);
|
||||||
|
|
||||||
|
subBox.getText().getTextStyle()
|
||||||
|
.setFontFamily('Arial')
|
||||||
|
.setFontSize(13)
|
||||||
|
.setForegroundColor(dark ? '#FFFFFF' : WMC.TEXT);
|
||||||
|
|
||||||
|
if (dark) {
|
||||||
|
subBox.getText().getParagraphStyle().setParagraphAlignment(SlidesApp.ParagraphAlignment.CENTER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dark) {
|
||||||
|
try {
|
||||||
|
const blob = visualBlob_({
|
||||||
|
imageDriveId: spec.imageDriveId || '',
|
||||||
|
imageUrl: spec.imageUrl || '',
|
||||||
|
url: spec.imageUrl || ''
|
||||||
|
});
|
||||||
|
|
||||||
|
if (blob) {
|
||||||
|
const img = slide.insertImage(blob);
|
||||||
|
const maxW = pageW - 96;
|
||||||
|
const maxH = pageH - 185;
|
||||||
|
const scale = Math.min(maxW / img.getWidth(), maxH / img.getHeight());
|
||||||
|
const finalW = img.getWidth() * scale;
|
||||||
|
const finalH = img.getHeight() * scale;
|
||||||
|
|
||||||
|
img.setWidth(finalW)
|
||||||
|
.setHeight(finalH)
|
||||||
|
.setLeft((pageW - finalW) / 2)
|
||||||
|
.setTop(150);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('No se pudo insertar imagen en Slides: ' + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const footer = slide.insertTextBox(
|
||||||
|
'PROPRIETARY & CONFIDENTIAL · Walmart Connect / GomezLee Marketing',
|
||||||
|
30,
|
||||||
|
pageH - 26,
|
||||||
|
pageW - 60,
|
||||||
|
14
|
||||||
|
);
|
||||||
|
|
||||||
|
footer.getText().getTextStyle()
|
||||||
|
.setFontFamily('Arial')
|
||||||
|
.setFontSize(7)
|
||||||
|
.setForegroundColor(dark ? '#D9E2F3' : '#777777');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 5) IMAGEN YA GENERADA POR GEMINI EN N8N
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function generateImageArtifact_(body) {
|
||||||
|
const a = body.artifact || {};
|
||||||
|
const driveId = String(a.imageDriveId || a.driveId || a.fileId || '').trim();
|
||||||
|
|
||||||
|
if (driveId) {
|
||||||
|
const file = DriveApp.getFileById(driveId);
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
artifactType: 'image',
|
||||||
|
artifactId: file.getId(),
|
||||||
|
artifactUrl: file.getUrl(),
|
||||||
|
title: a.title || file.getName() || 'Visual WMC',
|
||||||
|
provider: 'Google Gemini (n8n) + Google Drive'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = String(a.imageUrl || a.url || '').trim();
|
||||||
|
if (url) {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
artifactType: 'image',
|
||||||
|
artifactId: null,
|
||||||
|
artifactUrl: url,
|
||||||
|
title: a.title || 'Visual WMC',
|
||||||
|
provider: 'Google Gemini (n8n)'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Las imágenes se generan en n8n con el nodo nativo Google Gemini; no se recibió imageDriveId/imageUrl.');
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"css": "src/styles.css",
|
||||||
|
"baseColor": "slate",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"rtl": false,
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"registries": {}
|
||||||
|
}
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-5HE753X5-Bw-yg4kO.js";import{n as t}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as n}from"./src-BY_WSiz7.js";import"./chunk-I66GZJ75-DyIufBk3.js";import"./chunk-3NCLNEKW-CxJ1byyi.js";import{n as r,r as i,t as a}from"./chunk-6Q2QTUOP-UdMAlPWh.js";import{t as o}from"./chunk-JWPE2WC7-DVXcaiue.js";import{t as s}from"./mermaid-parser.core-3r-A_QO0.js";var c=e().RailroadAbnf.parser.LangiumParser,l=t(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=t(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=t(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=t(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=t(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=t(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=t(e=>{o(e,a),e.title&&a.setTitle(e.title),e.rules.map(e=>a.addRule(m(e)))},`populateDb`),g={parser:{parse:t(e=>{a.clear(),n.debug(`[ABNF Parser] Starting Langium parse`);let t=c.parse(e);if(t.lexerErrors.length>0||t.parserErrors.length>0)throw new s(t);let r=t.value;n.debug(`[ABNF Parser] Parsed rules:`,r.rules.length),h(r),n.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:a}},db:a,renderer:i,styles:r};export{g as diagram};
|
||||||
+11
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-BDCdLWk4.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import"./chunk-KEIR6QF5-BICK3FdT.js";import{n as e}from"./chunk-MOZMSUNE-XVucA-n6.js";export{e as createArchitectureServices};
|
||||||
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
Array.prototype.slice;function e(e){return typeof e==`object`&&`length`in e?e:Array.from(e)}export{e as t};
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
var e=[Object.freeze(JSON.parse(`{"displayName":"Berry","name":"berry","patterns":[{"include":"#controls"},{"include":"#strings"},{"include":"#comment-block"},{"include":"#comments"},{"include":"#keywords"},{"include":"#function"},{"include":"#member"},{"include":"#identifier"},{"include":"#number"},{"include":"#operator"}],"repository":{"comment-block":{"begin":"#-","end":"-#","name":"comment.berry","patterns":[{}]},"comments":{"begin":"#","end":"\\\\n","name":"comment.line.berry","patterns":[{}]},"controls":{"patterns":[{"match":"\\\\b(if|elif|else|for|while|do|end|break|continue|return|try|except|raise)\\\\b","name":"keyword.control.berry"}]},"function":{"patterns":[{"match":"\\\\b([A-Z_a-z][0-9A-Z_a-z]*(?=\\\\s*\\\\())","name":"entity.name.function.berry"}]},"identifier":{"patterns":[{"match":"\\\\b[A-Z_a-z]\\\\w+\\\\b","name":"identifier.berry"}]},"keywords":{"patterns":[{"match":"\\\\b(var|static|def|class|true|false|nil|self|super|import|as|_class)\\\\b","name":"keyword.berry"}]},"member":{"patterns":[{"captures":{"0":{"name":"entity.other.attribute-name.berry"}},"match":"\\\\.([A-Z_a-z][0-9A-Z_a-z]*)"}]},"number":{"patterns":[{"match":"0x\\\\h+|\\\\d+|(\\\\d+\\\\.?|\\\\.\\\\d)\\\\d*([Ee][-+]?\\\\d+)?","name":"constant.numeric.berry"}]},"operator":{"patterns":[{"match":"[-\\\\]!%\\\\&(-+./:<=>\\\\[^|~]","name":"keyword.operator.berry"}]},"strings":{"patterns":[{"begin":"f(?=[\\"'])","patterns":[{"begin":"\\"","end":"\\"","name":"string.quoted.other.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"},{"match":"\\\\{\\\\{[^}]*}}","name":"string.quoted.other.berry"},{"begin":"\\\\{","end":"}","name":"keyword.other.unit.berry","patterns":[{"include":"#keywords"},{"include":"#numbers"},{"include":"#identifier"},{"include":"#operator"},{"include":"#member"},{"include":"#function"}]}]},{"begin":"'","end":"'","name":"string.quoted.other.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"},{"match":"\\\\{\\\\{[^}]*}}","name":"string.quoted.other.berry"},{"begin":"\\\\{","end":"}","name":"keyword.other.unit.berry","patterns":[{"include":"#keywords"},{"include":"#numbers"},{"include":"#identifier"},{"include":"#operator"},{"include":"#member"},{"include":"#function"}]}]}],"while":"\\\\G|^[\\\\t ]*(?=[\\"'])"},{"begin":"([\\"'])","end":"\\\\1","name":"string.quoted.double.berry","patterns":[{"match":"(\\\\\\\\x\\\\h{2})|(\\\\\\\\[0-7]{3})|(\\\\\\\\\\\\\\\\)|(\\\\\\\\\\")|(\\\\\\\\')|(\\\\\\\\a)|(\\\\\\\\b)|(\\\\\\\\f)|(\\\\\\\\n)|(\\\\\\\\r)|(\\\\\\\\t)|(\\\\\\\\v)","name":"constant.character.escape.berry"}]}]}},"scopeName":"source.berry","aliases":["be"]}`))];export{e as default};
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
var e=[Object.freeze(JSON.parse(`{"displayName":"BibTeX","name":"bibtex","patterns":[{"captures":{"0":{"name":"punctuation.definition.comment.bibtex"}},"match":"@(?i:comment)(?=[({\\\\s])","name":"comment.block.at-sign.bibtex"},{"include":"#preamble"},{"include":"#string"},{"include":"#entry"},{"begin":"[^\\\\n@]","end":"(?=@)","name":"comment.block.bibtex"}],"repository":{"entry":{"patterns":[{"begin":"((@)[-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*)\\\\s*(\\\\{)\\\\s*([^,}\\\\s]*)","beginCaptures":{"1":{"name":"keyword.other.entry-type.bibtex"},"2":{"name":"punctuation.definition.keyword.bibtex"},"3":{"name":"punctuation.section.entry.begin.bibtex"},"4":{"name":"entity.name.type.entry-key.bibtex"}},"end":"}","endCaptures":{"0":{"name":"punctuation.section.entry.end.bibtex"}},"name":"meta.entry.braces.bibtex","patterns":[{"begin":"([-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*)\\\\s*(=)","beginCaptures":{"1":{"name":"support.function.key.bibtex"},"2":{"name":"punctuation.separator.key-value.bibtex"}},"end":"(?=[,}])","name":"meta.key-assignment.bibtex","patterns":[{"include":"#field_value"}]}]},{"begin":"((@)[-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*)\\\\s*(\\\\()\\\\s*([^,\\\\s]*)","beginCaptures":{"1":{"name":"keyword.other.entry-type.bibtex"},"2":{"name":"punctuation.definition.keyword.bibtex"},"3":{"name":"punctuation.section.entry.begin.bibtex"},"4":{"name":"entity.name.type.entry-key.bibtex"}},"end":"\\\\)","endCaptures":{"0":{"name":"punctuation.section.entry.end.bibtex"}},"name":"meta.entry.parenthesis.bibtex","patterns":[{"begin":"([-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*)\\\\s*(=)","beginCaptures":{"1":{"name":"support.function.key.bibtex"},"2":{"name":"punctuation.separator.key-value.bibtex"}},"end":"(?=[),])","name":"meta.key-assignment.bibtex","patterns":[{"include":"#field_value"}]}]}]},"field_value":{"patterns":[{"include":"#string_content"},{"include":"#integer"},{"include":"#string_var"},{"match":"#","name":"keyword.operator.bibtex"}]},"integer":{"captures":{"1":{"name":"constant.numeric.bibtex"}},"match":"\\\\s*(\\\\d+)\\\\s*"},"nested_braces":{"begin":"\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.group.begin.bibtex"}},"end":"}","endCaptures":{"0":{"name":"punctuation.definition.group.end.bibtex"}},"patterns":[{"include":"#nested_braces"}]},"preamble":{"patterns":[{"begin":"((@)(?i:preamble))\\\\s*(\\\\{)\\\\s*","beginCaptures":{"1":{"name":"keyword.other.preamble.bibtex"},"2":{"name":"punctuation.definition.keyword.bibtex"},"3":{"name":"punctuation.section.preamble.begin.bibtex"}},"end":"}","endCaptures":{"0":{"name":"punctuation.section.preamble.end.bibtex"}},"name":"meta.preamble.braces.bibtex","patterns":[{"include":"#field_value"}]},{"begin":"((@)(?i:preamble))\\\\s*(\\\\()\\\\s*","beginCaptures":{"1":{"name":"keyword.other.preamble.bibtex"},"2":{"name":"punctuation.definition.keyword.bibtex"},"3":{"name":"punctuation.section.preamble.begin.bibtex"}},"end":"\\\\)","endCaptures":{"0":{"name":"punctuation.section.preamble.end.bibtex"}},"name":"meta.preamble.parenthesis.bibtex","patterns":[{"include":"#field_value"}]}]},"string":{"patterns":[{"begin":"((@)(?i:string))\\\\s*(\\\\{)\\\\s*([-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*)","beginCaptures":{"1":{"name":"keyword.other.string-constant.bibtex"},"2":{"name":"punctuation.definition.keyword.bibtex"},"3":{"name":"punctuation.section.string-constant.begin.bibtex"},"4":{"name":"variable.other.bibtex"}},"end":"}","endCaptures":{"0":{"name":"punctuation.section.string-constant.end.bibtex"}},"name":"meta.string-constant.braces.bibtex","patterns":[{"include":"#field_value"}]},{"begin":"((@)(?i:string))\\\\s*(\\\\()\\\\s*([-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*)","beginCaptures":{"1":{"name":"keyword.other.string-constant.bibtex"},"2":{"name":"punctuation.definition.keyword.bibtex"},"3":{"name":"punctuation.section.string-constant.begin.bibtex"},"4":{"name":"variable.other.bibtex"}},"end":"\\\\)","endCaptures":{"0":{"name":"punctuation.section.string-constant.end.bibtex"}},"name":"meta.string-constant.parenthesis.bibtex","patterns":[{"include":"#field_value"}]}]},"string_content":{"patterns":[{"begin":"\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.bibtex"}},"end":"}","endCaptures":{"0":{"name":"punctuation.definition.string.end.bibtex"}},"patterns":[{"include":"#nested_braces"}]},{"begin":"\\"","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.bibtex"}},"end":"\\"","endCaptures":{"0":{"name":"punctuation.definition.string.end.bibtex"}},"patterns":[{"include":"#nested_braces"}]}]},"string_var":{"captures":{"0":{"name":"support.variable.bibtex"}},"match":"[-!$\\\\&*+./:;<>-z|~][!$\\\\&*+\\\\--<>-z|~]*"}},"scopeName":"text.bibtex"}`))];export{e as default};
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+132
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+10
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
import e from"./python-gzcpVVnB.js";var t=Object.freeze(JSON.parse(`{"displayName":"Cairo","name":"cairo","patterns":[{"begin":"\\\\b(if).*\\\\(","beginCaptures":{"1":{"name":"keyword.control.if"},"2":{"name":"entity.name.condition"}},"contentName":"source.cairo0","end":"}","endCaptures":{"0":{"name":"keyword.control.end"}},"name":"meta.control.if","patterns":[{"include":"source.cairo0"}]},{"begin":"\\\\b(with)\\\\s+(.+)\\\\s*\\\\{","beginCaptures":{"1":{"name":"keyword.control.with"},"2":{"name":"entity.name.identifiers"}},"contentName":"source.cairo0","end":"}","endCaptures":{"0":{"name":"keyword.control.end"}},"name":"meta.control.with","patterns":[{"include":"source.cairo0"}]},{"begin":"\\\\b(with_attr)\\\\s+([A-Z_a-z][0-9A-Z_a-z]*)\\\\s*[({]","beginCaptures":{"1":{"name":"keyword.control.with_attr"},"2":{"name":"entity.name.function"}},"contentName":"source.cairo0","end":"}","endCaptures":{"0":{"name":"keyword.control.end"}},"name":"meta.control.with_attr","patterns":[{"include":"source.cairo0"}]},{"match":"\\\\belse\\\\b","name":"keyword.control.else"},{"match":"\\\\b(call|jmp|ret|abs|rel|if)\\\\b","name":"keyword.other.opcode"},{"match":"\\\\b([af]p)\\\\b","name":"keyword.other.register"},{"match":"\\\\b(const|let|local|tempvar|felt|as|from|import|static_assert|return|assert|cast|alloc_locals|with|with_attr|nondet|dw|codeoffset|new|using|and)\\\\b","name":"keyword.other.meta"},{"match":"\\\\b(SIZE(?:OF_LOCALS|))\\\\b","name":"markup.italic"},{"match":"//[^\\\\n]*\\\\n","name":"comment.line.sharp"},{"match":"\\\\b[A-Z_a-z][0-9A-Z_a-z]*:\\\\s*$","name":"entity.name.function"},{"begin":"\\\\b(func)\\\\s+([A-Z_a-z][0-9A-Z_a-z]*)\\\\s*[({]","beginCaptures":{"1":{"name":"storage.type.function.cairo"},"2":{"name":"entity.name.function"}},"contentName":"source.cairo0","end":"}","endCaptures":{"0":{"name":"storage.type.function.cairo"}},"name":"meta.function.cairo","patterns":[{"include":"source.cairo0"}]},{"begin":"\\\\b(struct|namespace)\\\\s+([A-Z_a-z][0-9A-Z_a-z]*)\\\\s*\\\\{","beginCaptures":{"1":{"name":"storage.type.function.cairo"},"2":{"name":"entity.name.function"}},"contentName":"source.cairo0","end":"}","endCaptures":{"0":{"name":"storage.type.function.cairo"}},"name":"meta.function.cairo","patterns":[{"include":"source.cairo0"}]},{"match":"\\\\b[-+]?[0-9]+\\\\b","name":"constant.numeric.decimal"},{"match":"\\\\b[-+]?0x\\\\h+\\\\b","name":"constant.numeric.hexadecimal"},{"match":"'[^']*'","name":"string.quoted.single"},{"match":"\\"[^\\"]*\\"","name":"string.quoted.double"},{"begin":"%\\\\{","beginCaptures":{"0":{"name":"punctuation.section.embedded.begin.python"}},"contentName":"source.python","end":"%}","endCaptures":{"0":{"name":"punctuation.section.embedded.end.python"},"1":{"name":"source.python"}},"name":"meta.embedded.block.python","patterns":[{"include":"source.python"}]}],"scopeName":"source.cairo0","embeddedLangs":["python"]}`)),n=[...e,t];export{n as default};
|
||||||
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
import{at as e,ot as t}from"./chunk-I66GZJ75-DyIufBk3.js";var n=(n,r)=>t.lang.round(e.parse(n)[r]);export{n as t};
|
||||||
Vendored
+208
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{p as t}from"./src-BY_WSiz7.js";import{j as n}from"./chunk-I66GZJ75-DyIufBk3.js";import{t as r}from"./dist-BDCdLWk4.js";var i=r(),a=e((e,t)=>{let n=e.append(`rect`);if(n.attr(`x`,t.x),n.attr(`y`,t.y),n.attr(`fill`,t.fill),n.attr(`stroke`,t.stroke),n.attr(`width`,t.width),n.attr(`height`,t.height),t.name&&n.attr(`name`,t.name),t.rx&&n.attr(`rx`,t.rx),t.ry&&n.attr(`ry`,t.ry),t.attrs!==void 0)for(let e in t.attrs)n.attr(e,t.attrs[e]);return t.class&&n.attr(`class`,t.class),n},`drawRect`),o=e((e,t)=>{a(e,{x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:`rect`}).lower()},`drawBackgroundRect`),s=e((e,t)=>{let r=t.text.replace(n,` `),i=e.append(`text`);i.attr(`x`,t.x),i.attr(`y`,t.y),i.attr(`class`,`legend`),i.style(`text-anchor`,t.anchor),t.class&&i.attr(`class`,t.class);let a=i.append(`tspan`);return a.attr(`x`,t.x+t.textMargin*2),a.text(r),i},`drawText`),c=e((e,t,n,r)=>{let a=e.append(`image`);a.attr(`x`,t),a.attr(`y`,n);let o=(0,i.sanitizeUrl)(r);a.attr(`xlink:href`,o)},`drawImage`),l=e((e,t,n,r)=>{let a=e.append(`use`);a.attr(`x`,t),a.attr(`y`,n);let o=(0,i.sanitizeUrl)(r);a.attr(`xlink:href`,`#${o}`)},`drawEmbeddedImage`),u=e(()=>({x:0,y:0,width:100,height:100,fill:`#EDF2AE`,stroke:`#666`,anchor:`start`,rx:0,ry:0}),`getNoteRect`),d=e(()=>({x:0,y:0,width:100,height:100,"text-anchor":`start`,style:`#666`,textMargin:0,rx:0,ry:0,tspan:!0}),`getTextObj`),f=e(()=>{let e=t(`.mermaidTooltip`);return e.empty()&&(e=t(`body`).append(`div`).attr(`class`,`mermaidTooltip`).style(`opacity`,0).style(`position`,`absolute`).style(`text-align`,`center`).style(`max-width`,`200px`).style(`padding`,`2px`).style(`font-size`,`12px`).style(`background`,`#ffffde`).style(`border`,`1px solid #333`).style(`border-radius`,`2px`).style(`pointer-events`,`none`).style(`z-index`,`100`)),e},`createTooltip`);export{a,d as c,c as i,o as n,s as o,l as r,u as s,f as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";var t=class{constructor(e){this.init=e,this.records=this.init()}static{e(this,`ImperativeState`)}reset(){this.records=this.init()}};export{t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{p as t}from"./src-BY_WSiz7.js";import{x as n}from"./chunk-I66GZJ75-DyIufBk3.js";var r=e(e=>{let{securityLevel:r}=n(),i=t(`body`);if(r===`sandbox`){let n=t(`#i${e}`).node()?.contentDocument??document;i=t(n.body)}return i.select(`#${e}`)},`selectSvgElement`);export{r as t};
|
||||||
+1
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,b as n,n as r,o as i,u as a,w as o,x as s}from"./chunk-KEIR6QF5-BICK3FdT.js";var c=class extends r{static{s(this,`WardleyValueConverter`)}runCustomConverter(e,t,n){switch(e.name.toUpperCase()){case`LINK_LABEL`:return t.substring(1).trim();default:return}}},l={parser:{ValueConverter:s(()=>new c,`ValueConverter`)}};function u(r=i){let s=o(e(r),a),c=o(t({shared:s}),n,l);return s.ServiceRegistry.register(c),{shared:s,Wardley:c}}s(u,`createWardleyServices`);export{u as n,l as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,m as n,n as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`RailroadAbnfTokenBuilder`)}constructor(){super([`railroad-abnf-beta`])}},u=class extends r{static{c(this,`RailroadAbnfValueConverter`)}runConverter(e,t,n){let r=super.runConverter(e,t,n);if(e.name===`TITLE`&&typeof r==`string`){let e=r.trim();if(e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`))return e.slice(1,-1)}return r}runCustomConverter(e,t,n){if(e.name===`ABNF_STRING`)return t.slice(1,-1)}},d={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new u,`ValueConverter`)}};function f(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,d);return a.ServiceRegistry.register(c),{shared:a,RailroadAbnf:c}}c(f,`createRailroadAbnfServices`);export{f as n,d as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,i as n,o as r,s as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`EventModelingTokenBuilder`)}constructor(){super([`eventmodeling`])}},u=new Set([`cmd`,`command`]),d=new Set([`evt`,`event`]),f=new Set([`rmo`,`readmodel`]),p=new Set([`pcr`,`processor`]),m=new Set([`ui`]);function h(e){let t=e.validation.EventModelingValidator,n=e.validation.ValidationRegistry;if(n){let e={EmTimeFrame:t.checkSourceFrameTypes.bind(t),EmResetFrame:t.checkSourceFrameTypes.bind(t)};n.register(e,t)}}c(h,`registerValidationChecks`);var g=class{static{c(this,`EventModelingValidator`)}checkSourceFrameTypes(e,t){e.sourceFrames.length!==0&&(u.has(e.modelEntityType)?this.validateSources(e,new Set([...m,...p]),`command`,`ui or processor`,t):d.has(e.modelEntityType)?this.validateSources(e,u,`event`,`command`,t):f.has(e.modelEntityType)?this.validateSources(e,d,`read model`,`event`,t):p.has(e.modelEntityType)?this.validateSources(e,f,`processor`,`read model`,t):m.has(e.modelEntityType)&&this.validateSources(e,f,`ui`,`read model`,t))}validateSources(e,t,n,r,i){for(let a of e.sourceFrames){let o=a.ref;o!==void 0&&!t.has(o.modelEntityType)&&i(`error`,`A ${n} can only receive input from a ${r}, not from '${o.modelEntityType}'.`,{node:e,property:`sourceFrames`})}}},_={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new n,`ValueConverter`)},validation:{EventModelingValidator:c(()=>new g,`EventModelingValidator`)}};function v(n=r){let a=s(e(n),o),c=s(t({shared:a}),i,_);return a.ServiceRegistry.register(c),h(c),{shared:a,EventModel:c}}c(v,`createEventModelingServices`);export{v as n,_ as t};
|
||||||
+231
File diff suppressed because one or more lines are too long
+2
@@ -0,0 +1,2 @@
|
|||||||
|
import{C as e,S as t,g as n,n as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`RailroadTokenBuilder`)}constructor(){super([`railroad-beta`])}},u=c(e=>{let t=e.slice(1,-1),n=``;for(let e=0;e<t.length;e++){let r=t[e];if(r===`\\`&&e+1<t.length){e++;let r=t[e];switch(r){case`n`:n+=`
|
||||||
|
`;break;case`r`:n+=`\r`;break;case`t`:n+=` `;break;default:n+=r}continue}n+=r}return n},`decodeEscapedString`),d=class extends r{static{c(this,`RailroadValueConverter`)}runConverter(e,t,n){let r=super.runConverter(e,t,n);if(e.name===`TITLE`&&typeof r==`string`){let e=r.trim();if(e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`))return u(e)}return r}runCustomConverter(e,t,n){if(e.name===`RR_STRING`)return u(t)}},f={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new d,`ValueConverter`)}};function p(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,f);return a.ServiceRegistry.register(c),{shared:a,Railroad:c}}c(p,`createRailroadServices`);export{p as n,f as t};
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";var t=e(()=>`
|
||||||
|
/* Font Awesome icon styling - consolidated */
|
||||||
|
.label-icon {
|
||||||
|
display: inline-block;
|
||||||
|
height: 1em;
|
||||||
|
overflow: visible;
|
||||||
|
vertical-align: -0.125em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node .label-icon path {
|
||||||
|
fill: currentColor;
|
||||||
|
stroke: revert;
|
||||||
|
stroke-width: revert;
|
||||||
|
}
|
||||||
|
`,`getIconStyles`);export{t};
|
||||||
+88
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";var t=e((e,t)=>{if(t)return`translate(`+-e.width/2+`, `+-e.height/2+`)`;let n=e.x??0,r=e.y??0;return`translate(`+-(n+e.width/2)+`, `+-(r+e.height/2)+`)`},`computeLabelTransform`),n={aggregation:17.25,extension:17.25,composition:17.25,dependency:6,lollipop:13.5,arrow_point:4,arrow_barb:0,arrow_barb_neo:5.5},r={arrow_point:4,arrow_cross:12.5,arrow_circle:12.5};function i(e,t){if(e===void 0||t===void 0)return{angle:0,deltaX:0,deltaY:0};e=a(e),t=a(t);let[n,r]=[e.x,e.y],[i,o]=[t.x,t.y],s=i-n,c=o-r;return{angle:Math.atan(c/s),deltaX:s,deltaY:c}}e(i,`calculateDeltaAndAngle`);var a=e(e=>Array.isArray(e)?{x:e[0],y:e[1]}:e,`pointTransformer`),o=e(t=>({x:e(function(e,r,o){let s=0,c=a(o[0]).x<a(o[o.length-1]).x?`left`:`right`;if(r===0&&Object.hasOwn(n,t.arrowTypeStart)){let{angle:e,deltaX:r}=i(o[0],o[1]);s=n[t.arrowTypeStart]*Math.cos(e)*(r>=0?1:-1)}else if(r===o.length-1&&Object.hasOwn(n,t.arrowTypeEnd)){let{angle:e,deltaX:r}=i(o[o.length-1],o[o.length-2]);s=n[t.arrowTypeEnd]*Math.cos(e)*(r>=0?1:-1)}let l=Math.abs(a(e).x-a(o[o.length-1]).x),u=Math.abs(a(e).y-a(o[o.length-1]).y),d=Math.abs(a(e).x-a(o[0]).x),f=Math.abs(a(e).y-a(o[0]).y),p=n[t.arrowTypeStart],m=n[t.arrowTypeEnd];if(l<m&&l>0&&u<m){let e=m+1-l;e*=c===`right`?-1:1,s-=e}if(d<p&&d>0&&f<p){let e=p+1-d;e*=c===`right`?-1:1,s+=e}return a(e).x+s},`x`),y:e(function(e,r,o){let s=0,c=a(o[0]).y<a(o[o.length-1]).y?`down`:`up`;if(r===0&&Object.hasOwn(n,t.arrowTypeStart)){let{angle:e,deltaY:r}=i(o[0],o[1]);s=n[t.arrowTypeStart]*Math.abs(Math.sin(e))*(r>=0?1:-1)}else if(r===o.length-1&&Object.hasOwn(n,t.arrowTypeEnd)){let{angle:e,deltaY:r}=i(o[o.length-1],o[o.length-2]);s=n[t.arrowTypeEnd]*Math.abs(Math.sin(e))*(r>=0?1:-1)}let l=Math.abs(a(e).y-a(o[o.length-1]).y),u=Math.abs(a(e).x-a(o[o.length-1]).x),d=Math.abs(a(e).y-a(o[0]).y),f=Math.abs(a(e).x-a(o[0]).x),p=n[t.arrowTypeStart],m=n[t.arrowTypeEnd];if(l<m&&l>0&&u<m){let e=m+1-l;e*=c===`up`?-1:1,s-=e}if(d<p&&d>0&&f<p){let e=p+1-d;e*=c===`up`?-1:1,s+=e}return a(e).y+s},`y`)}),`getLineFunctionsWithOffset`);export{r as i,o as n,n as r,t};
|
||||||
+10
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,i as n,l as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`InfoTokenBuilder`)}constructor(){super([`info`,`showInfo`])}},u={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new n,`ValueConverter`)}};function d(n=i){let a=s(e(n),o),c=s(t({shared:a}),r,u);return a.ServiceRegistry.register(c),{shared:a,Info:c}}c(d,`createInfoServices`);export{d as n,u as t};
|
||||||
+131
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,n,o as r,t as i,u as a,v as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends n{static{c(this,`TreeViewValueConverter`)}runCustomConverter(e,t,n){if(e.name===`INDENTATION`)return t?.length||0;if(e.name===`QUOTED_NAME`)return t.substring(1,t.length-1);if(e.name===`BARE_NAME`)return t.replace(/[\t ]+$/,``);if(e.name===`CLASS_ANNOTATION`)return t.trim().substring(3).trim();if(e.name===`ICON_ANNOTATION`){let e=t.trim();return e.substring(5,e.length-1)}if(e.name===`DESC_ANNOTATION`)return t.trim().substring(2).trim()}},u=class extends i{static{c(this,`TreeViewTokenBuilder`)}constructor(){super([`treeView-beta`])}},d={parser:{TokenBuilder:c(()=>new u,`TokenBuilder`),ValueConverter:c(()=>new l,`ValueConverter`)}};function f(n=r){let i=s(e(n),a),c=s(t({shared:i}),o,d);return i.ServiceRegistry.register(c),{shared:i,TreeView:c}}c(f,`createTreeViewServices`);export{f as n,d as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,c as n,i as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`GitGraphTokenBuilder`)}constructor(){super([`gitGraph`])}},u={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new r,`ValueConverter`)}};function d(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,u);return a.ServiceRegistry.register(c),{shared:a,GitGraph:c}}c(d,`createGitGraphServices`);export{d as n,u as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,d as n,i as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`PacketTokenBuilder`)}constructor(){super([`packet`])}},u={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new r,`ValueConverter`)}};function d(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,u);return a.ServiceRegistry.register(c),{shared:a,Packet:c}}c(d,`createPacketServices`);export{d as n,u as t};
|
||||||
+206
File diff suppressed because one or more lines are too long
+128
File diff suppressed because one or more lines are too long
+2
@@ -0,0 +1,2 @@
|
|||||||
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/dagre-VZM6K2ZE-5CAQBCM3.js","assets/chunk-Y2CYZVJY-DsF7k-Jl.js","assets/src-BY_WSiz7.js","assets/rolldown-runtime-B0Z9INg1.js","assets/chunk-I66GZJ75-DyIufBk3.js","assets/preload-helper-BGRGm2aY.js","assets/chunk-NSK5VX7P-C5rgTOqf.js","assets/dist-BDCdLWk4.js","assets/chunk-4I5QYGJK-CqcwRbfk.js","assets/chunk-WRU74C26-BTfK14t9.js","assets/chunk-7BUUIJ7U-Bb538aSH.js","assets/chunk-UBXNYLIW-D4IRhP65.js","assets/graphlib-DS17s2tU.js","assets/dagre-Buvkdvvj.js","assets/map-BaFkSB1l.js","assets/chunk-RYQCIY6F-DCAUdfJM.js","assets/chunk-W5SLKNZC-Bwa0Erac.js","assets/chunk-QR6OTTB3-Gf6zEt7G.js","assets/rough.esm-Dy-Kn_BL.js","assets/chunk-7Z6QIM7H-C8-Xmgc1.js","assets/line-C3peQHkb.js","assets/path-fybaL0A-.js","assets/array-BifhSqXX.js","assets/swimlanes-SLNWSIFB-BlynRk4a.js","assets/cose-bilkent-JH36ORCC-C2z-I-lM.js","assets/cytoscape.esm-B-NFISlW.js"])))=>i.map(i=>d[i]);
|
||||||
|
import{t as e}from"./preload-helper-BGRGm2aY.js";import{n as t}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as n}from"./src-BY_WSiz7.js";import{b as r,s as i}from"./chunk-I66GZJ75-DyIufBk3.js";import{d as a}from"./chunk-NSK5VX7P-C5rgTOqf.js";import{a as o,i as s,s as c}from"./chunk-QR6OTTB3-Gf6zEt7G.js";import{a as l,i as u,o as d,r as f}from"./chunk-7Z6QIM7H-C8-Xmgc1.js";var p={common:i,getConfig:r,insertCluster:s,insertEdge:f,insertEdgeLabel:u,insertMarkers:l,insertNode:o,interpolateToCurve:a,labelHelper:c,log:n,positionEdgeLabel:d},m={},h=t(e=>{for(let t of e)m[t.name]=t},`registerLayoutLoaders`);t(()=>{h([{name:`dagre`,loader:t(async()=>await e(()=>import(`./dagre-VZM6K2ZE-5CAQBCM3.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22])),`loader`)},{name:`swimlane`,loader:t(async()=>await e(()=>import(`./swimlanes-SLNWSIFB-BlynRk4a.js`),__vite__mapDeps([23,5,1,2,3,4,6,7,8,9,10,11,12,15,14,16,17,18,19,20,21,22])),`loader`)},{name:`cose-bilkent`,loader:t(async()=>await e(()=>import(`./cose-bilkent-JH36ORCC-C2z-I-lM.js`),__vite__mapDeps([24,3,1,2,25])),`loader`)}])},`registerDefaultLayoutLoaders`)();var g=t(async(e,t,n)=>{if(!(e.layoutAlgorithm in m))throw Error(`Unknown layout algorithm: ${e.layoutAlgorithm}`);if(e.diagramId)for(let t of e.nodes){let n=t.domId||t.id;t.domId=`${e.diagramId}-${n}`}let r=m[e.layoutAlgorithm],i=await r.loader(),{theme:a,themeVariables:o}=e.config,{useGradient:s,gradientStart:c,gradientStop:l}=o,u=t.attr(`id`);if(t.append(`defs`).append(`filter`).attr(`id`,`${u}-drop-shadow`).attr(`height`,`130%`).attr(`width`,`130%`).append(`feDropShadow`).attr(`dx`,`4`).attr(`dy`,`4`).attr(`stdDeviation`,0).attr(`flood-opacity`,`0.06`).attr(`flood-color`,`${a?.includes(`dark`)?`#FFFFFF`:`#000000`}`),t.append(`defs`).append(`filter`).attr(`id`,`${u}-drop-shadow-small`).attr(`height`,`150%`).attr(`width`,`150%`).append(`feDropShadow`).attr(`dx`,`2`).attr(`dy`,`2`).attr(`stdDeviation`,0).attr(`flood-opacity`,`0.06`).attr(`flood-color`,`${a?.includes(`dark`)?`#FFFFFF`:`#000000`}`),s){let e=t.append(`linearGradient`).attr(`id`,t.attr(`id`)+`-gradient`).attr(`gradientUnits`,`objectBoundingBox`).attr(`x1`,`0%`).attr(`y1`,`0%`).attr(`x2`,`100%`).attr(`y2`,`0%`);e.append(`svg:stop`).attr(`offset`,`0%`).attr(`stop-color`,c).attr(`stop-opacity`,1),e.append(`svg:stop`).attr(`offset`,`100%`).attr(`stop-color`,l).attr(`stop-opacity`,1)}return i.render(e,t,p,{algorithm:r.algorithm},n)},`render`),_=t((e=``,{fallback:t=`dagre`}={})=>{if(e in m)return e;if(t in m)return n.warn(`Layout algorithm ${e} is not registered. Using ${t} as fallback.`),t;throw Error(`Both layout algorithms ${e} and ${t} are not registered.`)},`getRegisteredLayoutAlgorithm`);export{h as n,g as r,_ as t};
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
import{C as e,S as t,_ as n,n as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`RailroadPegTokenBuilder`)}constructor(){super([`railroad-peg-beta`])}},u=c(e=>{let t=e.slice(1,-1),n=``;for(let e=0;e<t.length;e++){let r=t[e];if(r===`\\`&&e+1<t.length){e++;let r=t[e];switch(r){case`n`:n+=`
|
||||||
|
`;break;case`r`:n+=`\r`;break;case`t`:n+=` `;break;default:n+=r}continue}n+=r}return n},`decodeEscapedString`),d=class extends r{static{c(this,`RailroadPegValueConverter`)}runConverter(e,t,n){let r=super.runConverter(e,t,n);if(e.name===`TITLE`&&typeof r==`string`){let e=r.trim();if(e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`))return u(e)}return r}runCustomConverter(e,t,n){if(e.name===`PEG_STRING`)return u(t)}},f={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new d,`ValueConverter`)}};function p(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,f);return a.ServiceRegistry.register(c),{shared:a,RailroadPeg:c}}c(p,`createRailroadPegServices`);export{p as n,f as t};
|
||||||
+156
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";function t(e,t){e.accDescr&&t.setAccDescription?.(e.accDescr),e.accTitle&&t.setAccTitle?.(e.accTitle),e.title&&t.setDiagramTitle?.(e.title)}e(t,`populateCommonDb`);export{t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as t}from"./src-BY_WSiz7.js";import{c as n}from"./chunk-I66GZJ75-DyIufBk3.js";var r=e((e,r,o,s)=>{e.attr(`class`,o);let{width:c,height:l,x:u,y:d}=i(e,r);n(e,l,c,s);let f=a(u,d,c,l,r);e.attr(`viewBox`,f),t.debug(`viewBox configured: ${f} with padding: ${r}`)},`setupViewPortForSVG`),i=e((e,t)=>{let n=e.node()?.getBBox()||{width:0,height:0,x:0,y:0};return{width:n.width+t*2,height:n.height+t*2,x:n.x,y:n.y}},`calculateDimensionsWithPadding`),a=e((e,t,n,r,i)=>`${e-i} ${t-i} ${n} ${r}`,`createViewBox`);export{r as t};
|
||||||
+161
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,n,o as r,r as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`ArchitectureTokenBuilder`)}constructor(){super([`architecture`])}},u=class extends n{static{c(this,`ArchitectureValueConverter`)}runCustomConverter(e,t,n){if(e.name===`ARCH_ICON`)return t.replace(/[()]/g,``).trim();if(e.name===`ARCH_TEXT_ICON`)return t.replace(/["()]/g,``);if(e.name===`ARCH_TITLE`){let e=t.replace(/^\[|]$/g,``).trim();return(e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`))&&(e=e.slice(1,-1),e=e.replace(/\\"/g,`"`).replace(/\\'/g,`'`)),e.trim()}}},d={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new u,`ValueConverter`)}};function f(n=r){let a=s(e(n),o),c=s(t({shared:a}),i,d);return a.ServiceRegistry.register(c),{shared:a,Architecture:c}}c(f,`createArchitectureServices`);export{f as n,d as t};
|
||||||
+2
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,a as n,i as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`CynefinTokenBuilder`)}constructor(){super([`cynefin-beta`])}},u={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new r,`ValueConverter`)}};function d(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,u);return a.ServiceRegistry.register(c),{shared:a,Cynefin:c}}c(d,`createCynefinServices`);export{d as n,u as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,i as n,o as r,p as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`RadarTokenBuilder`)}constructor(){super([`radar-beta`])}},u={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new n,`ValueConverter`)}};function d(n=r){let a=s(e(n),o),c=s(t({shared:a}),i,u);return a.ServiceRegistry.register(c),{shared:a,Radar:c}}c(d,`createRadarServices`);export{d as n,u as t};
|
||||||
+62
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,n,o as r,t as i,u as a,w as o,x as s,y as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends i{static{s(this,`TreemapTokenBuilder`)}constructor(){super([`treemap`])}},u=/classDef\s+([A-Z_a-z]\w+)(?:\s+([^\n\r;]*))?;?/,d=class extends n{static{s(this,`TreemapValueConverter`)}runCustomConverter(e,t,n){if(e.name===`NUMBER2`)return parseFloat(t.replace(/,/g,``));if(e.name===`SEPARATOR`||e.name===`STRING2`)return t.substring(1,t.length-1);if(e.name===`INDENTATION`)return t.length;if(e.name===`ClassDef`){if(typeof t!=`string`)return t;let e=u.exec(t);if(e)return{$type:`ClassDefStatement`,className:e[1],styleText:e[2]||void 0}}}};function f(e){let t=e.validation.TreemapValidator,n=e.validation.ValidationRegistry;if(n){let e={Treemap:t.checkSingleRoot.bind(t)};n.register(e,t)}}s(f,`registerValidationChecks`);var p=class{static{s(this,`TreemapValidator`)}checkSingleRoot(e,t){let n;for(let r of e.TreemapRows)r.item&&(n===void 0&&r.indent===void 0?n=0:(r.indent===void 0||n!==void 0&&n>=parseInt(r.indent,10))&&t(`error`,`Multiple root nodes are not allowed in a treemap.`,{node:r,property:`item`}))}},m={parser:{TokenBuilder:s(()=>new l,`TokenBuilder`),ValueConverter:s(()=>new d,`ValueConverter`)},validation:{TreemapValidator:s(()=>new p,`TreemapValidator`)}};function h(n=r){let i=o(e(n),a),s=o(t({shared:i}),c,m);return i.ServiceRegistry.register(s),f(s),{shared:i,Treemap:s}}s(h,`createTreemapServices`);export{h as n,m as t};
|
||||||
+1
File diff suppressed because one or more lines are too long
+2
@@ -0,0 +1,2 @@
|
|||||||
|
import{C as e,S as t,h as n,n as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`RailroadEbnfTokenBuilder`)}constructor(){super([`railroad-ebnf-beta`])}},u=c(e=>{let t=e.slice(1,-1),n=``;for(let e=0;e<t.length;e++){let r=t[e];if(r===`\\`&&e+1<t.length){e++;let r=t[e];switch(r){case`n`:n+=`
|
||||||
|
`;break;case`r`:n+=`\r`;break;case`t`:n+=` `;break;default:n+=r}continue}n+=r}return n},`decodeEscapedString`),d=class extends r{static{c(this,`RailroadEbnfValueConverter`)}runConverter(e,t,n){let r=super.runConverter(e,t,n);if(e.name===`TITLE`&&typeof r==`string`){let e=r.trim();if(e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`))return u(e)}return r}runCustomConverter(e,t,n){if(e.name===`EBNF_STRING`)return u(t);if(e.name===`EBNF_SPECIAL_SEQUENCE`)return t.slice(1,-1).trim()}},f={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new d,`ValueConverter`)}};function p(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,f);return a.ServiceRegistry.register(c),{shared:a,RailroadEbnf:c}}c(p,`createRailroadEbnfServices`);export{p as n,f as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{f as t,x as n}from"./chunk-I66GZJ75-DyIufBk3.js";import{p as r}from"./chunk-NSK5VX7P-C5rgTOqf.js";var i=e(({flowchart:e})=>{let t=e?.subGraphTitleMargin?.top??0,n=e?.subGraphTitleMargin?.bottom??0;return{subGraphTitleTopMargin:t,subGraphTitleBottomMargin:n,subGraphTitleTotalMargin:t+n}},`getSubGraphTitleMargins`);async function a(i,a){let o=i.getElementsByTagName(`img`);if(!o||o.length===0)return;let s=a.replace(/<img[^>]*>/g,``).trim()===``;await Promise.all([...o].map(i=>new Promise(a=>{function o(){if(i.style.display=`flex`,i.style.flexDirection=`column`,s){let e=n().fontSize?n().fontSize:window.getComputedStyle(document.body).fontSize,[a=t.fontSize]=r(e),o=a*5+`px`;i.style.minWidth=o,i.style.maxWidth=o}else i.style.width=`100%`;a(i)}e(o,`setupImage`),setTimeout(()=>{i.complete&&o()}),i.addEventListener(`error`,o),i.addEventListener(`load`,o)})))}e(a,`configureLabelImages`);export{i as n,a as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{x as t}from"./chunk-I66GZJ75-DyIufBk3.js";var n=e(e=>{let{handDrawnSeed:n}=t();return{fill:e,hachureAngle:120,hachureGap:4,fillWeight:2,roughness:.7,stroke:e,seed:n}},`solidStateFill`),r=e(e=>{let t=i([...e.cssCompiledStyles||[],...e.cssStyles||[],...e.labelStyle||[]]);return{stylesMap:t,stylesArray:[...t]}},`compileStyles`),i=e(e=>{let t=new Map;return e.forEach(e=>{let[n,r]=e.split(`:`);t.set(n.trim(),r?.trim())}),t},`styles2Map`),a=e(e=>e===`color`||e===`font-size`||e===`font-family`||e===`font-weight`||e===`font-style`||e===`text-decoration`||e===`text-align`||e===`text-transform`||e===`line-height`||e===`letter-spacing`||e===`word-spacing`||e===`text-shadow`||e===`text-overflow`||e===`white-space`||e===`word-wrap`||e===`word-break`||e===`overflow-wrap`||e===`hyphens`,`isLabelStyle`),o=e(e=>{let{stylesArray:t}=r(e),n=[],i=[],o=[],s=[];return t.forEach(e=>{let t=e[0];a(t)?n.push(e.join(`:`)+` !important`):(i.push(e.join(`:`)+` !important`),t.includes(`stroke`)&&o.push(e.join(`:`)+` !important`),t===`fill`&&s.push(e.join(`:`)+` !important`))}),{labelStyles:n.join(`;`),nodeStyles:i.join(`;`),stylesArray:t,borderStyles:o,backgroundStyles:s}},`styles2String`),s=e((e,n)=>{let{themeVariables:i,handDrawnSeed:a}=t(),{nodeBorder:o,mainBkg:s}=i,{stylesMap:l}=r(e);return Object.assign({roughness:.7,fill:l.get(`fill`)||s,fillStyle:`hachure`,fillWeight:4,hachureGap:5.2,stroke:l.get(`stroke`)||o,seed:a,strokeWidth:l.get(`stroke-width`)?.replace(`px`,``)||1.3,fillLineDash:[0,0],strokeLineDash:c(l.get(`stroke-dasharray`))},n)},`userNodeOverrides`),c=e(e=>{if(!e)return[0,0];let t=e.trim().split(/\s+/).map(Number);if(t.length===1){let e=isNaN(t[0])?0:t[0];return[e,e]}return[isNaN(t[0])?0:t[0],isNaN(t[1])?0:t[1]]},`getStrokeDashArray`);export{s as a,o as i,a as n,n as r,r as t};
|
||||||
+70
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
|||||||
|
import{n as e}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{p as t}from"./src-BY_WSiz7.js";var n=e((e,n)=>{let r;return n===`sandbox`&&(r=t(`#i`+e)),t(n===`sandbox`?r.nodes()[0].contentDocument.body:`body`).select(`[id="${e}"]`)},`getDiagramElement`);export{n as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
var e=Object.defineProperty,t=(t,n)=>e(t,`name`,{value:n,configurable:!0}),n=(t,n)=>{for(var r in n)e(t,r,{get:n[r],enumerable:!0})};export{t as n,n as t};
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
import{C as e,S as t,f as n,n as r,o as i,t as a,u as o,w as s,x as c}from"./chunk-KEIR6QF5-BICK3FdT.js";var l=class extends a{static{c(this,`PieTokenBuilder`)}constructor(){super([`pie`,`showData`])}},u=class extends r{static{c(this,`PieValueConverter`)}runCustomConverter(e,t,n){if(e.name===`PIE_SECTION_LABEL`)return t.replace(/"/g,``).trim()}},d={parser:{TokenBuilder:c(()=>new l,`TokenBuilder`),ValueConverter:c(()=>new u,`ValueConverter`)}};function f(r=i){let a=s(e(r),o),c=s(t({shared:a}),n,d);return a.ServiceRegistry.register(c),{shared:a,Pie:c}}c(f,`createPieServices`);export{f as n,d as t};
|
||||||
+32
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user