sass-cms-template-common 0.0.23 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.js +27 -27
- package/dist/index.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/{services-CBf1oWSA.js → services-xDvlUc4t.js} +16 -4
- package/dist/services-xDvlUc4t.js.map +1 -0
- package/package.json +1 -1
- package/dist/services-CBf1oWSA.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services-xDvlUc4t.js","names":[],"sources":["../src/lib/theme/variables.ts","../src/lib/errors/commonErrors.en.ts","../src/lib/errors/commonErrors.es.ts","../src/lib/errors/commonErrors.pt.ts","../src/lib/errors/index.ts","../src/lib/network/classifyNetworkError.ts","../src/lib/network/networkBridge.ts","../src/lib/utils/toTestId.ts","../src/lib/utils/site-selector.ts","../src/lib/utils/site-time.ts","../src/lib/utils/permissions.ts","../src/lib/services/auth.ts","../src/lib/services/dashboard.ts","../src/lib/services/profile.ts","../src/lib/services/publication.ts","../src/lib/services/site.ts","../src/lib/services/authLogin.ts","../src/lib/services/upload.ts","../src/lib/services/preview.ts","../src/lib/services/audios.ts","../src/lib/services/categories.ts","../src/lib/services/ckeditor.ts","../src/lib/services/copilot.ts","../src/lib/services/comments.ts","../src/lib/services/contributions.ts","../src/lib/services/sections.ts","../src/lib/services/productivityPlan.ts","../src/lib/services/events.ts","../src/lib/services/fileExplorer.ts","../src/lib/services/general.ts","../src/lib/services/images.ts","../src/lib/services/news.ts","../src/lib/services/notification.ts","../src/lib/services/people.ts","../src/lib/services/planning.ts","../src/lib/services/polls.ts","../src/lib/services/recipes.ts","../src/lib/services/users.ts","../src/lib/services/zones.ts","../src/lib/services/workpaper.ts","../src/lib/services/vods.ts","../src/lib/services/videos.ts","../src/lib/services/trivias.ts","../src/lib/services/transcribe.ts","../src/lib/services/tags.ts","../src/lib/services/index.ts"],"sourcesContent":["/**\n * Variables de estilo compartidas de la librería.\n *\n * Centralizan los valores que se repetían hardcodeados en los distintos\n * `*.styles.ts` (colores, radios, sombras, alturas de botón). La idea es que\n * TODO componente de la lib consuma estas variables en lugar de literales\n * sueltos, para mantener botones y colores unificados.\n *\n * ── Modo claro / oscuro ──────────────────────────────────────────────────\n * Los colores semánticos son *mode-aware*: cada uno se expone como una CSS\n * custom property `var(--cms-…, <valor claro>)`. El valor claro va de fallback\n * (idéntico al histórico, sin regresión) y el `CmsColorSchemeVars` inyecta los\n * valores claro/oscuro según el atributo `data-mui-color-scheme` que togglea\n * MUI. Así, al cambiar el modo, TODOS los componentes que consumen estas\n * variables se oscurecen sin tocar cada `*.styles.ts`.\n *\n * Nota: varios de estos colores son ajustes de diseño que NO coinciden 1:1 con\n * el esquema Material 3 de `material-theme.json`. Por eso viven acá como\n * variables propias en vez de derivarse del theme MUI. Para superficies/estados\n * que sí mapean a valores del tema (`m3.*`, `action.*`) se sigue usando el\n * theme directamente en el `sx`.\n */\n\n/** Par de valores de un color: claro y oscuro. */\ntype ColorPair = { light: string; dark: string };\n\n/** kebab-case para el nombre de la CSS var (`primaryHover` → `primary-hover`). */\nfunction kebab(name: string): string {\n return name.replace(/([A-Z])/g, '-$1').toLowerCase();\n}\n\n/**\n * A partir de una tabla `{ clave: {light, dark} }` devuelve:\n * - `values`: `{ clave: 'var(--cms-<prefijo>-<clave>, <claro>)' }` (lo que se consume).\n * - `light` / `dark`: mapas `{ '--cms-…': hex }` para inyectar por esquema.\n */\nfunction buildTokens<T extends Record<string, ColorPair>>(\n prefix: string,\n table: T,\n) {\n const values = {} as Record<keyof T, string>;\n const light: Record<string, string> = {};\n const dark: Record<string, string> = {};\n (Object.keys(table) as (keyof T)[]).forEach((key) => {\n const varName = `--cms-${prefix ? `${prefix}-` : ''}${kebab(String(key))}`;\n const pair = table[key];\n values[key] = `var(${varName}, ${pair.light})`;\n light[varName] = pair.light;\n dark[varName] = pair.dark;\n });\n return { values, light, dark };\n}\n\n/** Igual que `buildTokens` pero para familias de chips `{ nombre: {bg, on} }`. */\nfunction buildPairTokens<T extends Record<string, { bg: ColorPair; on: ColorPair }>>(\n prefix: string,\n table: T,\n) {\n const values = {} as Record<keyof T, { bg: string; on: string }>;\n const light: Record<string, string> = {};\n const dark: Record<string, string> = {};\n (Object.keys(table) as (keyof T)[]).forEach((key) => {\n const base = `--cms-${prefix}-${kebab(String(key))}`;\n const { bg, on } = table[key];\n values[key] = {\n bg: `var(${base}-bg, ${bg.light})`,\n on: `var(${base}-on, ${on.light})`,\n };\n light[`${base}-bg`] = bg.light;\n light[`${base}-on`] = on.light;\n dark[`${base}-bg`] = bg.dark;\n dark[`${base}-on`] = on.dark;\n });\n return { values, light, dark };\n}\n\n/**\n * Tabla de colores semánticos de la paleta (claro histórico + oscuro nuevo).\n * El azul primario (CTA) se mantiene igual en ambos modos porque es color de\n * marca; el resto de superficies/textos/bordes se oscurecen.\n */\nconst CMS_COLOR_TABLE = {\n /** Color de acción primaria (CTA \"Publicar/Guardar\", botones, foco activo). */\n primary: { light: '#0067C4', dark: '#0067C4' },\n /** Hover del primario. */\n primaryHover: { light: '#005CAF', dark: '#2F7BD1' },\n /** Fondo de control primario deshabilitado (negro 10% / blanco 10%). */\n primaryDisabled: { light: '#1D1B201A', dark: '#FFFFFF1A' },\n\n /**\n * Acento del motor de IA \"Kundera\" (CTA \"Generar con Kundera\"). Es color de\n * marca: se mantiene igual en ambos modos (como `primary`).\n */\n kundera: { light: '#2962FF', dark: '#2962FF' },\n /** Hover del acento Kundera. */\n kunderaHover: { light: '#2254DE', dark: '#2254DE' },\n\n /** Color secundario / contenedor (estado activo o seleccionado). */\n secondary: { light: '#D8E2FF', dark: '#2C4678' },\n /** Hover sobre superficies secundarias (opciones de desplegable). */\n secondaryHover: { light: '#E1E2EA', dark: '#2E3140' },\n /** Texto / íconos sobre el contenedor `secondary` (`onSecondaryContainer` M3). */\n onSecondaryContainer: { light: '#2C4678', dark: '#D8E2FF' },\n /** Secundario sólido (borde del avatar al hover de fila). */\n secondaryStrong: { light: '#455E91', dark: '#8FA8D8' },\n\n /** Borde por defecto de controles tipo select. */\n controlBorder: { light: '#727784', dark: '#8E9199' },\n /** Texto por defecto de controles tipo select. */\n controlText: { light: '#000000', dark: '#E1E2E9' },\n /** Fondo de hover de un control tipo select (sin valor activo). */\n controlHoverBg: { light: '#F9F9FF', dark: '#1D2024' },\n\n /** Fondo del buscador (`CmsSearchField`) en hover: gris algo más oscuro que el reposo. */\n searchHoverBg: { light: '#DBDCE2', dark: '#34363B' },\n /** Fondo del buscador (`CmsSearchField`) en foco: gris lavanda claro. */\n searchFocusBg: { light: '#E7E8EE', dark: '#33363C' },\n /** Hover del botón limpiar (X) del buscador: state layer neutro al 10%. */\n searchClearHoverBg: {\n light: 'rgba(25, 28, 32, 0.10)',\n dark: 'rgba(255, 255, 255, 0.10)',\n },\n /** Hover de la \"x\" de un chip del buscador: `onSecondaryContainer` al ~16%. */\n chipDeleteHoverBg: {\n light: 'rgba(44, 70, 120, 0.16)',\n dark: 'rgba(216, 226, 255, 0.16)',\n },\n\n /** Borde del botón en variante blanca (BtnDropdown). */\n whiteBtnBorder: { light: '#DDDDDD', dark: '#43474E' },\n /** Texto del botón en variante blanca (BtnDropdown). */\n whiteBtnText: { light: '#515253', dark: '#C4C6CF' },\n\n /** Fondo de hover/activo del botón de ícono (disparador del SimpleDropdown). */\n iconButtonHoverBg: { light: '#E6E6E6', dark: '#2A2D33' },\n /** Color del ícono del disparador en reposo. */\n iconButtonIcon: { light: '#929193', dark: '#A9AEB8' },\n\n /** Fondo de menús flotantes (perfil, selector de sitios). */\n menuSurface: { light: '#ECEDF6', dark: '#2A2C31' },\n /** Fondo de la opción activa/hover dentro de un menú desplegable simple. */\n menuItemActive: { light: '#E1E2EB', dark: '#34363B' },\n /** Hover neutro sobre superficies claras (sidebar, top bar). */\n surfaceHover: { light: '#E3E2E6', dark: '#34363B' },\n\n /** Texto tenue del índice alfabético (letras inactivas A–Z del listado). */\n alphabetIdle: { light: '#B4BEDA', dark: '#5A6478' },\n /** Fondo translúcido del índice alfabético inactivo (evita `alpha()` sobre var). */\n alphabetIdleSoft: {\n light: 'rgba(180, 190, 218, 0.12)',\n dark: 'rgba(140, 150, 180, 0.14)',\n },\n /** Letra del índice alfabético CON resultados (clickeable). */\n alphabetLetter: { light: '#191C20', dark: '#E1E2E9' },\n /** Letra del índice alfabético SIN resultados (deshabilitada, sin click). */\n alphabetLetterDisabled: { light: '#C4C6CF', dark: '#43474E' },\n\n /**\n * State layer neutro para el hover de filas de tabla (M3 onSurface al 6%).\n * Gris muy tenue sobre superficie clara; en oscuro, blanco tenue.\n */\n rowHover: {\n light: 'rgba(25, 28, 32, 0.06)',\n dark: 'rgba(255, 255, 255, 0.06)',\n },\n /**\n * State layer neutro para el hover de chips/botones NO seleccionados\n * (índice alfabético en reposo). M3 onSurface al 8%.\n */\n neutralHover: {\n light: 'rgba(25, 28, 32, 0.08)',\n dark: 'rgba(255, 255, 255, 0.10)',\n },\n /**\n * State layer on-primary (blanco al 8%) que se suma sobre un relleno primario\n * al hacer hover en un chip/botón YA seleccionado: nunca revierte a gris.\n */\n onPrimaryStateLayer: {\n light: 'rgba(255, 255, 255, 0.08)',\n dark: 'rgba(255, 255, 255, 0.08)',\n },\n\n /** Ícono de acción en reposo (p. ej. el `more_vert` de fila): gris medio. */\n actionIcon: { light: '#43474E', dark: '#C4C6CF' },\n /** Ícono de acción en hover: onSurface (se oscurece en claro, se aclara en oscuro). */\n actionIconHover: { light: '#191C20', dark: '#E1E2E9' },\n\n /** Texto fuerte (títulos de ítems, nombre de perfil). */\n textStrong: { light: '#191C22', dark: '#E4E2E6' },\n /** Texto de navegación / secundario. */\n textNav: { light: '#414752', dark: '#C4C6CF' },\n /** Texto atenuado: títulos de sección, encabezados de columna. */\n textMuted: { light: '#94A2AA', dark: '#8A929C' },\n\n /** Azul para enlaces de texto y botones tipo texto. */\n link: { light: '#004F99', dark: '#9ECAFF' },\n\n /** Acento de acción destructiva (CTA \"Desactivar/Resetear\", badge de riesgo). */\n danger: { light: '#BA1A1A', dark: '#DE3730' },\n /** Hover del acento destructivo. */\n dangerHover: { light: '#93000A', dark: '#FF6B5E' },\n /** Acento de acción positiva (badge de \"Activar\"). */\n success: { light: '#1E8E3E', dark: '#4CD97B' },\n\n /** Bordes y divisores sutiles. */\n border: { light: '#C1C6D4', dark: '#3A3E46' },\n\n /** Fondo del avatar de perfil. */\n avatarBg: { light: '#F2F6FC', dark: '#282A2F' },\n /** Borde del avatar de perfil. */\n avatarBorder: { light: '#DEE2E6', dark: '#43474E' },\n\n /** Fondo del avatar de un usuario inactivo (look apagado, gris lavanda). */\n avatarInactiveBg: { light: '#E1E5F2', dark: '#282A2F' },\n /** Ícono (persona) del avatar de un usuario inactivo. */\n avatarInactiveIcon: { light: '#6C7396', dark: '#8A929C' },\n\n /**\n * Fondo de los tooltips (superficie oscura). Es color de superficie oscura por\n * diseño, fijo en ambos modos (mismo criterio que el toast). Texto: `white`.\n */\n tooltipSurface: { light: '#2E3035', dark: '#2E3035' },\n\n /**\n * Superficie elevada (menús, sidebar, buscador en hover). En claro es blanco;\n * en oscuro pasa a una superficie oscura. Sustituye a `white` en los usos que\n * son \"fondo elevado\" (no confundir con el blanco de contraste, ver `white`).\n */\n surface: { light: '#FFFFFF', dark: '#282A2F' },\n} as const;\n\nconst cmsTokens = buildTokens('', CMS_COLOR_TABLE);\n\n/**\n * Paleta de la librería. Valores semánticos, no por componente.\n *\n * Casi todos son *mode-aware* (`var(--cms-…)`). La única excepción es `white`,\n * que es blanco de contraste (texto sobre botón de color) y se mantiene blanco\n * en ambos modos.\n */\nexport const cmsColors = {\n ...cmsTokens.values,\n /** Blanco de contraste (texto/íconos sobre botones de color). Fijo en ambos modos. */\n white: '#FFFFFF',\n} as const;\n\n/** Radios de borde. */\nexport const radii = {\n /** Inputs / triggers compactos. */\n sm: '8px',\n /** Ítems de menú. */\n md: '10px',\n /** Flyout desplegable del menú lateral (submenús del Sidebar). */\n flyout: '12px',\n /** Papers de menú (dropdowns). */\n lg: '14px',\n /** Menús flotantes de cuenta (perfil): esquinas 16px. */\n accountMenu: '16px',\n /** Píldoras grandes / menús redondeados (M3). */\n xl: '28px',\n /** Diálogos / modales de confirmación. */\n dialog: '24px',\n /** Píldora completa. */\n pill: '999px',\n} as const;\n\n/** Sombras (elevaciones) reutilizables. */\nexport const shadows = {\n /** Botones (CTA y blancos). */\n button: '0 1px 2px rgba(0, 0, 0, 0.10)',\n /** Menús con elevación M3 nivel 2 (perfil, selector de sitios). */\n menu: '0px 1px 3px 0px rgba(0, 0, 0, 0.30), 0px 4px 8px 3px rgba(0, 0, 0, 0.15)',\n /** Paper suave y difuso (dropdowns genéricos). */\n menuSoft: '0 10px 30px rgba(0, 0, 0, 0.18)',\n /** Menú flotante de cuenta (perfil): sombra difusa con tinte neutro (#191C20 al 18%). */\n accountMenu: '0 10px 30px rgba(25, 28, 32, 0.18)',\n /** Desplegable de opciones (M3 Elevation Light/5): dos capas suaves. */\n menuDropdown:\n '0px 4px 4px 0px rgba(0, 0, 0, 0.30), 0px 8px 12px 6px rgba(0, 0, 0, 0.15)',\n /** Submenús flotantes del sidebar (flyout del menú lateral). */\n flyout: '0 6px 12px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.10)',\n} as const;\n\n/** Tamaños recurrentes de controles. */\nexport const sizes = {\n /** Alto estándar de botón pill (CTA / dropdowns). */\n buttonHeight: 40,\n /** Alto de botones/triggers compactos (selector de sitios). */\n buttonHeightSm: 34,\n /** Alto del campo buscador (`CmsSearchField`): igual al del filtro (`buttonHeight`). */\n searchHeight: 40,\n} as const;\n\n/**\n * Colores de feedback de operaciones (toasts/notificaciones).\n *\n * El toast usa una superficie oscura (estilo de diseño del CMS) con texto\n * claro y un ícono de acento por severidad. Como ya es un componente oscuro por\n * diseño, NO cambia entre modos (se mantiene igual en claro y oscuro).\n */\nexport const feedbackColors = {\n /** Fondo oscuro del toast (común a todas las severidades). */\n surface: '#2E2E2E',\n /** Texto/íconos sobre la superficie oscura. */\n onSurface: '#FFFFFF',\n /** Texto secundario (detalle, url, versión) sobre la superficie oscura. */\n onSurfaceMuted: '#C7C7C7',\n\n /** Acento de éxito (verde). */\n success: '#00C853',\n /** Acento de advertencia (ámbar). */\n warning: '#FFAB00',\n /** Acento de error (rojo). */\n error: '#FF1744',\n /** Acento informativo (azul). */\n info: '#2196F3',\n\n /** Enlace (url del recurso) sobre la superficie oscura del toast. */\n link: '#9ECAFF',\n /** Fondo sutil del detalle crudo del servidor del toast de error. */\n overlay: '#3B3B3B',\n /** Texto atenuado del toast de error (descripción, chip de versión, fecha). */\n onSurfaceSoft: '#F0F0F7',\n /** Fondo del chip de versión (blanco translúcido sobre la superficie oscura). */\n versionChipBg: '#F0F0F71A',\n /** Punto separador entre versión y fecha (blanco translúcido). */\n separator: '#F0F0F7B3',\n} as const;\n\n/**\n * Colores del círculo de ícono del toast por severidad. `bg` = fondo del\n * círculo; `on` = color del ícono. Como el toast es oscuro en ambos modos,\n * estos tampoco cambian.\n */\nexport const feedbackBadgeColors = {\n /** Éxito: círculo verde menta con check verde oscuro. */\n success: { bg: '#92F7B7', on: '#002112' },\n /** Advertencia: círculo ámbar con ícono marrón. */\n warning: { bg: '#FFDDB0', on: '#5F4200' },\n /** Error: círculo rosado con ícono rojo oscuro. */\n error: { bg: '#FFDAD6', on: '#93000A' },\n /** Info: círculo azul tonal con ícono azul oscuro. */\n info: { bg: '#D8E2FF', on: '#001551' },\n} as const;\n\n/**\n * Colores de estado editorial para los chips de estado en listados de\n * contenido (sugerencias de CoPilot, noticias, etc.). Mode-aware: en oscuro se\n * usan contenedores oscuros con texto claro (patrón M3 dark).\n */\nconst STATE_COLOR_TABLE = {\n /** Activo / publicado (verde). Light: verde más saturado del mock Material (NAA-4656). */\n active: { bg: { light: '#92F7B7', dark: '#0F3D22' }, on: { light: '#002112', dark: '#7FE0A0' } },\n /** Generando con IA (azul Bluestack tonal). */\n generating: { bg: { light: '#DCE3FF', dark: '#1E2A52' }, on: { light: '#001551', dark: '#B7C9FF' } },\n /** Asignado / en redacción (púrpura). */\n assigned: { bg: { light: '#EADDFF', dark: '#2C2249' }, on: { light: '#21005D', dark: '#D9C6FF' } },\n /** Descartado / archivado (neutral). Light: gris de los badges con dislike del mock (NAA-4656). */\n discarded: { bg: { light: '#E7E8EE', dark: '#2A2C31' }, on: { light: '#43474E', dark: '#C4C6CF' } },\n} as const;\n\nexport const stateColors = buildPairTokens('state', STATE_COLOR_TABLE).values;\n\n/**\n * Colores del chip de estado de cuenta de usuario (activo / inactivo).\n * Mode-aware.\n */\nconst USER_STATUS_COLOR_TABLE = {\n /** Activo: contenedor verde menta. */\n active: { bg: { light: '#92F7B7', dark: '#0F3D22' }, on: { light: '#002112', dark: '#92F7B7' } },\n /** Inactivo: contenedor neutro. */\n inactive: { bg: { light: '#E1E2E9', dark: '#2E3035' }, on: { light: '#002112', dark: '#C4C6CF' } },\n} as const;\n\nexport const userStatusColors = buildPairTokens('user-status', USER_STATUS_COLOR_TABLE).values;\n\n/**\n * Colores del avatar de ícono de cada tarjeta del centro de notificaciones\n * (campanita del TopBar). Mode-aware; \"assigned\" reutiliza el secundario de la\n * paleta (que ya es mode-aware).\n */\nconst NOTIFICATION_COLOR_TABLE = {\n /** Actividades por vencer (naranja). El `on` se reutiliza para la fecha de vencimiento. */\n pending: { bg: { light: '#FFE2D5', dark: '#3A1D12' }, on: { light: '#B3300A', dark: '#FFB59B' } },\n /** Notificaciones del sistema / videos (verde). */\n system: { bg: { light: '#DCEFE0', dark: '#123021' }, on: { light: '#11663B', dark: '#8FD9A8' } },\n /** Oportunidades editoriales copilot (azul copilot pleno, ícono blanco). */\n editorialOpportunity: {\n bg: { light: '#3162E0', dark: '#3B6FF0' },\n on: { light: '#FFFFFF', dark: '#FFFFFF' },\n },\n} as const;\n\nconst notificationTokens = buildPairTokens('notification', NOTIFICATION_COLOR_TABLE);\n\nexport const notificationColors = {\n /** Temas asignados (azul): mismo contenedor secundario que los chips activos. */\n assigned: { bg: cmsColors.secondary, on: cmsColors.onSecondaryContainer },\n /** Desasignación de tarea (person_remove): mismo fondo/ícono que asignados. */\n unassigned: { bg: cmsColors.secondary, on: cmsColors.onSecondaryContainer },\n ...notificationTokens.values,\n} as const;\n\n/**\n * Colores de la card de oportunidades editoriales copilot (campanita, NAA-4837).\n * Tomados del diseño del CMS Angular (commit NAA-4645). Producción es solo light;\n * los valores oscuros son best-effort para no romper el modo oscuro de desarrollo.\n */\nconst EDITORIAL_OPPORTUNITY_COLOR_TABLE = {\n /** Acento azul copilot: barra de la oportunidad destacada. */\n accent: { light: '#3162E0', dark: '#3B6FF0' },\n /** Texto de acento: label, % de coincidencia y \"Ver más\". */\n text: { light: '#2B65BE', dark: '#A9C4FF' },\n /** Fondo de cada oportunidad dentro de la card. */\n topicBg: { light: '#ECEDF6', dark: '#262A33' },\n /** Fondo de cada oportunidad en hover (gris azulado más marcado). */\n topicHoverBg: { light: '#D4D5DE', dark: '#313640' },\n /** Barra de acento de las oportunidades secundarias (gris). */\n topicBorder: { light: '#C4C6CE', dark: '#43474E' },\n /** Etiqueta \"Trending\" (dorado). */\n trending: { light: '#8B4F00', dark: '#E5B87A' },\n /** Hover de una fila de la tabla de oportunidades (gris neutro claro, NAA-4656). */\n listRowHover: { light: '#EFF0F0', dark: '#2A2C31' },\n /** Hover del botón \"Asignar\" (tonal) de la tabla de oportunidades (NAA-4656). */\n assignBtnHover: { light: '#C2CCE6', dark: '#35507F' },\n} as const;\n\nconst editorialOpportunityTokens = buildTokens(\n 'editorial-opportunity',\n EDITORIAL_OPPORTUNITY_COLOR_TABLE,\n);\n\nexport const editorialOpportunityColors = editorialOpportunityTokens.values;\n\n/**\n * Colores de un badge de confianza/score por nivel. Mode-aware.\n */\nconst CONFIDENCE_COLOR_TABLE = {\n /** Alto, ≥85% (verde). */\n high: { bg: { light: '#D7F5DD', dark: '#0F3D22' }, on: { light: '#0D5B2B', dark: '#7FE0A0' } },\n /** Medio, 70–84% (ámbar). */\n medium: { bg: { light: '#FFF0C8', dark: '#3A2E05' }, on: { light: '#6B4D00', dark: '#FFD98A' } },\n /** Bajo, <70% (gris). */\n low: { bg: { light: '#E7E8EE', dark: '#2A2C31' }, on: { light: '#43474E', dark: '#C4C6CF' } },\n} as const;\n\nexport const confidenceColors = buildPairTokens('confidence', CONFIDENCE_COLOR_TABLE).values;\n\n/**\n * Feedback de interés del usuario sobre un ítem (me gusta / no me gusta).\n * Se mantienen literales (se usan con `alpha()` para los hovers).\n */\nexport const interestColors = {\n /** Me gusta (verde). */\n like: '#1E8E3E',\n /** No me gusta (rojo). */\n dislike: '#D93025',\n} as const;\n\n/**\n * Colores de marca por fuente de origen (puntos/indicadores de fuente en\n * filtros y chips). **Valores placeholder**. Mode-aware: en oscuro los tonos\n * muy oscuros (X) se aclaran para seguir siendo visibles.\n */\nconst SOURCE_COLOR_TABLE = {\n /** RSS (naranja). */\n rss: { light: '#FB923C', dark: '#FB923C' },\n /** Google Trends (azul). */\n gtrends: { light: '#4285F4', dark: '#6BA0F8' },\n /** Search Console (verde). */\n sconsole: { light: '#0F9D58', dark: '#34C77B' },\n /** X / Twitter (negro → claro en oscuro). */\n x: { light: '#111111', dark: '#E1E2E9' },\n} as const;\n\nconst sourceTokens = buildTokens('source', SOURCE_COLOR_TABLE);\n\nexport const sourceColors = sourceTokens.values;\n\n/**\n * Mapas de CSS variables por esquema para inyectar globalmente.\n * `CmsColorSchemeVars` los coloca en `:root` (claro) y\n * `:root[data-mui-color-scheme=\"dark\"]` (oscuro).\n */\nexport function buildCmsColorSchemeVars(): {\n light: Record<string, string>;\n dark: Record<string, string>;\n} {\n return {\n light: {\n ...cmsTokens.light,\n ...buildPairTokens('state', STATE_COLOR_TABLE).light,\n ...buildPairTokens('user-status', USER_STATUS_COLOR_TABLE).light,\n ...notificationTokens.light,\n ...editorialOpportunityTokens.light,\n ...buildPairTokens('confidence', CONFIDENCE_COLOR_TABLE).light,\n ...sourceTokens.light,\n },\n dark: {\n ...cmsTokens.dark,\n ...buildPairTokens('state', STATE_COLOR_TABLE).dark,\n ...buildPairTokens('user-status', USER_STATUS_COLOR_TABLE).dark,\n ...notificationTokens.dark,\n ...editorialOpportunityTokens.dark,\n ...buildPairTokens('confidence', CONFIDENCE_COLOR_TABLE).dark,\n ...sourceTokens.dark,\n },\n };\n}\n\n/**\n * Familias tipográficas del CMS. `googleSans` = fuente única de todo el CMS\n * (texto, marca y títulos); reemplaza a Roboto y Product Sans. La `@font-face`\n * que la carga vive en `theme/fonts.ts` y se inyecta vía el provider MUI.\n */\nexport const fontFamilies = {\n googleSans: '\"Google Sans\",\"Helvetica\",\"Arial\",sans-serif',\n /** Monoespaciada (url del toast de error, fragmentos de código). No es de marca. */\n mono: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',\n} as const;\n\nexport type CmsColors = typeof cmsColors;\nexport type CmsRadii = typeof radii;\nexport type CmsShadows = typeof shadows;\nexport type CmsSizes = typeof sizes;\nexport type FeedbackColors = typeof feedbackColors;\nexport type FeedbackBadgeColors = typeof feedbackBadgeColors;\nexport type StateColors = typeof stateColors;\nexport type NotificationColors = typeof notificationColors;\nexport type EditorialOpportunityColors = typeof editorialOpportunityColors;\nexport type UserStatusColors = typeof userStatusColors;\nexport type ConfidenceColors = typeof confidenceColors;\nexport type InterestColors = typeof interestColors;\nexport type SourceColors = typeof sourceColors;\n","/**\n * CMS error code → readable message map (English).\n *\n * English counterpart of {@link commonErrorsEs}. See that file for the key\n * convention and the `código → código+'a'` fallback handled by\n * `getCommonError`.\n */\nexport const commonErrorsEn: Record<string, string> = {\n '000.000': 'The user is already logged in',\n '000.001': 'The user does not exist',\n '000.002': 'The user will be disabled after 3 invalid login attempts.',\n '000.003': 'The user is disabled',\n '000.004': 'General error',\n '000.005': 'Insufficient permissions',\n '000.006': 'Your session has expired (failed to identify the intended token)',\n '000.007': 'The password should not contain personal information',\n '000.008': 'The password is longer than allowed',\n '000.009': 'The password must be at least %%min characters',\n '000.010': 'The password must contain at least one numeric character',\n '000.011': 'The password must contain at least one special character',\n '000.012': 'Password must contain at least one lowercase letter',\n '000.013': 'Password must contain at least one uppercase letter',\n '000.014': 'Generic error check the error variable',\n '000.015': 'The email does not correspond to a registered user',\n '000.016': 'The time to change your password has expired. Try again',\n '000.017': 'Did not start with the password recovery process',\n '000.018': 'Email format error',\n '000.019':\n 'The user has been disabled due to 3 invalid login attempts. The user will be available in %%1 minutes.',\n '000.020': 'This method is not configured on the server.',\n '000.021': 'The user has not created the temporary code, to advance.',\n '000.023': 'The code is invalid',\n '000.024': 'Error when sending the sms.',\n '000.025': 'Error when sending the email.',\n '000.027': 'This email has already been registered.',\n '001.001': 'The operation could not be performed',\n '002.001': 'User has no selected pins',\n '002.002': 'Could not update pins',\n '002.003': 'User already has that pin',\n '002.004': 'User does not have that pin',\n '003.001': 'The tag status could not be changed',\n '003.002': 'The tag name is required',\n '003.003': 'Select a value for the tag type',\n '003.004': 'A tag with the same name already exists',\n '003.005': 'Tag data could not be validated',\n '003.006': 'The tag could not be deleted',\n '003.007': 'The tag could not be updated',\n '003.008': 'There is no tag for id and type',\n '004.001': 'Could not change the status of the person',\n '004.002': 'The name of the person is required',\n '004.003': 'A person with the same name already exists',\n '004.004': 'Data validation error',\n '004.005': 'Could not delete person',\n '005.001': 'The username is required',\n '005.002': 'Another error in profile',\n '005.003': 'Account could not be linked',\n '005.004':\n 'You do not have a G-SUITE account linked to the system. Contact your administrator',\n '006.001': 'Failed to create a zone, duplicate zone',\n '006.002': 'Duplicate zone',\n '006.003': 'Description is required',\n '006.004': 'Color is mandatory',\n '006.005': 'Failed to delete a zone',\n '007.001': 'There is no survey',\n '007.002': 'Can not save survey',\n '007.003': 'Poll blocked by someone else',\n '008.000': 'Could not post a note',\n '008.001': 'No post was sent to publish',\n '008.002': 'This note is already pinned',\n '008.003': 'This note cannot be removed',\n '008.004': 'The note does not exist',\n '008.005': 'The scheduled publication date must be in the future',\n '008.006': 'Unidentified error, check the variable \"error\"',\n '008.012': 'Error getting XSD definition',\n '008.013': 'Failed to unlock note on exit',\n '008.014': 'Note locked by someone else',\n '008.015': 'This post has a draft',\n '008.016': 'The availability date is not valid',\n '008.017':\n 'The note could not be updated, with the desired last modification date',\n '008.018': 'There are fields with invalid content',\n '009.002': 'It is not a number',\n '010.001': 'The change could not be saved due to invalid fields',\n '010.011': 'Internal error while fetching the information',\n '010.012': 'The resource is locked by another user',\n '015.001': 'The video already exists',\n '015.011': 'An error occurred in the service',\n // 030.x series — Copilot/Kundera gateway (webservices copilot module)\n '030.000': 'The Copilot service is not configured',\n '030.001': 'The Copilot service returned an error',\n '030.002': 'No response from the Copilot service',\n '030.003': 'Action not supported by Copilot',\n '030.004': 'The opportunity identifier is missing',\n '030.005': 'The writer to assign is missing',\n '030.006': 'The Copilot service does not exist at the configured address',\n '030.007': 'The Copilot site of the publication is not valid',\n '999.000': 'The request does not have the expected format',\n '999.001a':\n 'The request has an error that was not captured. Contact your Administrator and detail the steps you followed',\n '999.002a': 'An error occurred in the service',\n '999.003a': 'CMS internal error. Please contact your Administrator',\n '999.006a': 'Login failed',\n '999.009a': 'Maximum number of pins exceeded',\n // Internal network/server codes (not from the CMS): see `classifyNetworkError`.\n 'net.offline':\n 'No connection. Check your network or Wi-Fi status. We will retry when the connection is restored.',\n 'net.timeout': 'The request took too long. Retrying…',\n 'net.unavailable': 'Server unavailable.',\n 'net.server': 'Internal server error.',\n};\n","/**\n * Mapa de códigos de error del CMS → mensaje legible (español).\n *\n * Equivalente al `CommonErrorsEs` del Angular legacy (`cmsmedios-ux`). Es la\n * base compartida por todos los gestores; **se va ampliando** con cada código\n * nuevo que se aprenda durante el desarrollo (ver CLAUDE.md raíz).\n *\n * Convención de claves: el código tal cual lo devuelve el webservice\n * (`000.005`, `999.000`, …). Algunos mensajes genéricos usan el sufijo `a`\n * (`999.002a`) por compatibilidad con el legacy; `getCommonError` resuelve el\n * fallback `código → código+'a'` automáticamente.\n */\nexport const commonErrorsEs: Record<string, string> = {\n '000.000': 'El usuario ya se encuentra logueado',\n '000.001': 'El usuario no existe',\n '000.002':\n 'El usuario será deshabilitado luego de 3 intentos de inicio de sesión no válidos.',\n '000.003': 'El usuario está deshabilitado',\n '000.004': 'Error general',\n '000.005': 'Permisos insuficientes',\n '000.006': 'Su sesión ha expirado (falló identificando el token previsto)',\n '000.007': 'La contraseña no debe contener información personal',\n '000.008': 'La contraseña tiene una longitud mayor a la permitida',\n '000.009': 'La contraseña debe tener como mínimo %%min caracteres',\n '000.010': 'La contraseña debe contener al menos un caracter numérico',\n '000.011': 'La contraseña debe contener al menos un caracter especial',\n '000.012': 'La contraseña debe contener al menos una letra en minúscula',\n '000.013': 'La contraseña debe contener al menos una letra en mayúscula',\n '000.014': 'Error genérico revisar la variable error',\n '000.015': 'El email no corresponde a un usuario registrado',\n '000.016': 'Expiró el tiempo para cambiar su contraseña. Vuelva a intentarlo',\n '000.017': 'No inició con el proceso de recuperar contraseña',\n '000.018': 'Error con el formato del email',\n '000.019':\n 'El usuario ha sido deshabilitado debido a 3 intentos de inicio de sesión no válidos. El usuario estará disponible en %%1 minutos.',\n '000.020': 'No esta configurado ese método en el servidor.',\n '000.021': 'El usuario no tiene creado el código temporal, para avanzar.',\n '000.023': 'El código es inválido',\n '000.024': 'Error al enviar el sms.',\n '000.025': 'Error al enviar el email.',\n '000.027': 'Este email ya se encuentra registrado.',\n '001.001': 'No se pudo realizar la operación',\n '002.001': 'El usuario no tiene pines seleccionados',\n '002.002': 'No se pudo actualizar los pines',\n '002.003': 'El usuario ya tiene ese pin',\n '002.004': 'El usuario no tiene ese pin',\n '003.001': 'No se pudo cambiar el status del tag',\n '003.002': 'El nombre del tag es obligatorio',\n '003.003': 'Seleccione un valor para el tipo de tag',\n '003.004': 'Ya existe un tag con el mismo nombre',\n '003.005': 'No se pudo validar los datos del tag',\n '003.006': 'No se pudo borrar el tag',\n '003.007': 'No se pudo actualizar el tag',\n '003.008': 'No existe el tag para el id y el type',\n '004.001': 'No se pudo cambiar el status de la persona',\n '004.002': 'El nombre de la persona es obligatorio',\n '004.003': 'Ya existe una persona con el mismo nombre',\n '004.004': 'Error en validación de datos',\n '004.005': 'No se pudo borrar la persona',\n '005.001': 'El username es obligatorio',\n '005.002': 'Otro error en perfil',\n '005.003': 'No se pudo vincular la cuenta',\n '005.004':\n 'No tiene vinculada una cuenta G-SUITE con el sistema. Contacte con su administrador',\n '006.001': 'Error al crear una zona, zona duplicada',\n '006.002': 'Zona duplicada',\n '006.003': 'La descripción es obligatoria',\n '006.004': 'El color es obligatorio',\n '006.005': 'Error al borrar una zona',\n '007.001': 'No existe la encuesta',\n '007.002': 'No se puede guardar la encuesta',\n '007.003': 'Encuesta bloqueada por otra persona',\n '008.000': 'No se pudo publicar una nota',\n '008.001': 'No se enviaron noticias a publicar',\n '008.002': 'Esta nota ya esta pineada',\n '008.003': 'No se puede despinear esta nota',\n '008.004': 'La nota no existe',\n '008.005': 'La fecha de publicación programada debe ser en el futuro',\n '008.006': 'Error no identificado, revisar la variable \"error\"',\n '008.012': 'Error al obtener definición del XSD',\n '008.013': 'Error al desbloquear la nota en el exit',\n '008.014': 'Nota bloqueada por otra persona',\n '008.015': 'Esta noticia tiene un borrador',\n '008.016': 'La fecha de disponibilidad no es válida',\n '008.017':\n 'No se pudo actualizar la nota, con la fecha de ultima modificacion deseada',\n '008.018': 'Algunos campos no cumplen con el formato valido',\n '009.002': 'No es un número ',\n '010.001': 'No se pudo guardar el cambio por errores en los campos.',\n '010.011': 'Error interno al consultar la información',\n '010.012': 'El recurso está bloqueado por otro usuario',\n '015.001': 'El vídeo ya existe',\n '015.011': 'Se produjo un error en el servicio',\n // Serie 030.x — gateway Copilot/Kundera (módulo copilot de webservices)\n '030.000': 'El servicio Copilot no está configurado',\n '030.001': 'El servicio Copilot devolvió un error',\n '030.002': 'No hay respuesta del servicio Copilot',\n '030.003': 'Acción no soportada por Copilot',\n '030.004': 'Falta el identificador de la oportunidad',\n '030.005': 'Falta el redactor a asignar',\n '030.006': 'El servicio Copilot no existe en la dirección configurada',\n '030.007': 'El sitio Copilot de la publicación no es válido',\n '999.000': 'El requerimiento no cuenta con el formato esperado',\n '999.001a':\n 'El requerimiento tiene un error que no se capturó. Comuniquese con su Administrador y detalle los pasos que siguió',\n '999.002a': 'Se produjo un error en el servicio',\n '999.003a': 'Error interno de CMS. Comuniquese con su administrador',\n '999.006a': 'Falló el login',\n '999.009a': 'Supero el máximo de pines',\n // Códigos internos de red/servidor (no del CMS): ver `classifyNetworkError`.\n 'net.offline':\n 'Sin conexión. Revisa tu red o el estado del Wi-Fi. Reintentaremos cuando se restablezca.',\n 'net.timeout': 'La solicitud tardó demasiado. Reintentando…',\n 'net.unavailable': 'Servidor no disponible.',\n 'net.server': 'Error interno del servidor.',\n};\n","/**\n * Mapa de código de erro do CMS → mensagem legível (português).\n *\n * Equivalente em português de {@link commonErrorsEs}.\n */\nexport const commonErrorsPt: Record<string, string> = {\n '000.000': 'O usuário já está logado',\n '000.001': 'O usuário não existe',\n '000.002': 'O usuário será desabilitado após 3 tentativas de login inválidas.',\n '000.003': 'O usuário está desabilitado',\n '000.004': 'Erro geral',\n '000.005': 'Permissões insuficientes',\n '000.006': 'Sua sessão expirou (falha ao identificar o token pretendido)',\n '000.007': 'A senha não deve conter informações pessoais',\n '000.008': 'A senha é maior que o permitido',\n '000.009': 'A senha deve ter pelo menos %%min caracteres',\n '000.010': 'A senha deve conter pelo menos um caractere numérico',\n '000.011': 'A senha deve conter pelo menos um caractere especial',\n '000.012': 'A senha deve conter pelo menos uma letra minúscula',\n '000.013': 'A senha deve conter pelo menos uma letra maiúscula',\n '000.014': 'Erro genérico verifique a variável de erro',\n '000.015': 'O email não corresponde a um usuário registrado',\n '000.016': 'O tempo para alterar sua senha expirou. tente novamente',\n '000.017': 'Não iniciou o processo de recuperação de senha',\n '000.018': 'Erro no formato do e-mail',\n '000.019':\n 'O usuário foi desativado devido a 3 tentativas de login inválidas. O usuário estará disponível em %%1 minutos.',\n '000.020': 'Este método não está configurado no servidor.',\n '000.021': 'O usuário não criou o código temporal para avançar.',\n '000.023': 'O código é inválido',\n '000.024': 'Erro ao enviar a mensagem.',\n '000.025': 'Erro ao enviar o email.',\n '000.027': 'Este e-mail já está registado.',\n '001.001': 'A operação não pôde ser executada',\n '002.001': 'Usuário não selecionou pinos',\n '002.002': 'Não foi possível atualizar os pinos',\n '002.003': 'O usuário já possui esse pin',\n '002.004': 'Usuário não possui esse pin',\n '003.001': 'Não foi possível alterar o status da tag',\n '003.002': 'O nome da tag é obrigatório',\n '003.003': 'Selecione um valor para o tipo de tag',\n '003.004': 'Já existe uma tag com o mesmo nome',\n '003.005': 'Os dados da tag não puderam ser validados',\n '003.006': 'A tag não pôde ser excluída',\n '003.007': 'A tag não pôde ser atualizada',\n '003.008': 'Não há tag para id e tipo',\n '004.001': 'Não foi possível alterar o status da pessoa',\n '004.002': 'O nome da pessoa é obrigatório',\n '004.003': 'Já existe uma pessoa com o mesmo nome',\n '004.004': 'Falha na validação de dados',\n '004.005': 'Não foi possível excluir a pessoa',\n '005.001': 'O nome de usuário é obrigatório',\n '005.002': 'Outro erro no perfil',\n '005.003': 'A conta não pôde ser vinculada',\n '005.004':\n 'Você não tem uma conta G-SUITE vinculada ao sistema. Entre em contato com seu administrador',\n '006.001': 'Falha ao criar uma zona, zona duplicada',\n '006.002': 'Zona duplicada',\n '006.003': 'A descrição é obrigatória',\n '006.004': 'A cor é obrigatória',\n '006.005': 'Falha ao excluir uma zona',\n '007.001': 'Não há pesquisa',\n '007.002': 'Não é possível salvar pesquisa',\n '007.003': 'Enquete bloqueada por outra pessoa',\n '008.000': 'Não foi possível postar uma nota',\n '008.001': 'Nenhuma notícia foi enviada para publicação',\n '008.002': 'Esta nota já está fixada',\n '008.003': 'Esta nota não pode ser removida',\n '008.004': 'A nota não existe',\n '008.005': 'A data de publicação programada deve ser futura',\n '008.006': 'Erro não identificado, verifique a variável \"erro\"',\n '008.012': 'Erro ao obter definição XSD',\n '008.013': 'Falha ao desbloquear nota ao sair',\n '008.014': 'Nota bloqueada por outra pessoa',\n '008.015': 'Esta notícia tem um rascunho',\n '008.016': 'A data de disponibilidade não é válida',\n '008.017':\n 'Não foi possível atualizar a nota, com a data da última modificação desejada',\n '008.018': 'Existem campos com conteúdo inválido',\n '009.002': 'Não é um número',\n '010.001': 'A alteração não pôde ser salva devido a campos inválidos',\n '010.011': 'Erro interno ao consultar a informação',\n '010.012': 'O recurso está bloqueado por outro usuário',\n '015.001': 'O vídeo já existe',\n '015.011': 'Ocorreu um erro no serviço',\n // Série 030.x — gateway Copilot/Kundera (módulo copilot de webservices)\n '030.000': 'O serviço Copilot não está configurado',\n '030.001': 'O serviço Copilot retornou um erro',\n '030.002': 'Sem resposta do serviço Copilot',\n '030.003': 'Ação não suportada pelo Copilot',\n '030.004': 'Falta o identificador da oportunidade',\n '030.005': 'Falta o redator a atribuir',\n '030.006': 'O serviço Copilot não existe no endereço configurado',\n '030.007': 'O site Copilot da publicação não é válido',\n '999.000': 'A solicitação não tem o formato esperado',\n '999.001a':\n 'O pedido tem um erro que não foi capturado. Entre em contato com seu administrador e detalhe as etapas que você seguiu',\n '999.002a': 'Ocorreu um erro no serviço',\n '999.003a': 'Erro interno do CMS. Entre em contato com seu administrador',\n '999.006a': 'Falha no login',\n '999.009a': 'Número máximo de pinos excedido',\n // Códigos internos de rede/servidor (não do CMS): ver `classifyNetworkError`.\n 'net.offline':\n 'Sem conexão. Verifique sua rede ou o status do Wi-Fi. Tentaremos novamente quando a conexão for restabelecida.',\n 'net.timeout': 'A solicitação demorou demais. Tentando novamente…',\n 'net.unavailable': 'Servidor não disponível.',\n 'net.server': 'Erro interno do servidor.',\n};\n","/**\n * Mapeo de códigos de error del CMS a mensajes legibles y a severidad de toast.\n *\n * Módulo **server-safe** (sin React): se puede usar tanto en server actions del\n * gestor como en el cliente. El sistema de toasts de la lib lo consume para\n * resolver el texto y el color del feedback.\n */\nimport type { Locale } from '../i18n/types';\nimport { commonErrorsEn } from './commonErrors.en';\nimport { commonErrorsEs } from './commonErrors.es';\nimport { commonErrorsPt } from './commonErrors.pt';\n\nexport { commonErrorsEn } from './commonErrors.en';\nexport { commonErrorsEs } from './commonErrors.es';\nexport { commonErrorsPt } from './commonErrors.pt';\n\nconst DICTS: Record<Locale, Record<string, string>> = {\n es: commonErrorsEs,\n en: commonErrorsEn,\n pt: commonErrorsPt,\n};\n\n/** Severidad de feedback derivada de un código de error. */\nexport type CmsErrorSeverity = 'warning' | 'error';\n\n/**\n * Códigos que representan condiciones **esperadas y accionables** por el\n * usuario (sin permiso, no encontrado, validación/formato, duplicado). Se\n * muestran como `warning`. Todo lo demás (fallos de servicio/servidor, token\n * expirado, errores internos) se muestra como `error`.\n *\n * Se amplía junto con `commonErrors.*` a medida que se aprenden más códigos.\n */\nconst WARNING_CODES = new Set<string>([\n // Permisos\n '000.005',\n // No encontrado\n '000.001',\n '000.015',\n '003.008',\n '008.004',\n // Validación / formato\n '000.018',\n '999.000',\n '009.002',\n '004.004',\n '008.018',\n '030.003',\n '030.004',\n '030.005',\n // Reglas de contraseña (el usuario las puede corregir)\n '000.007',\n '000.008',\n '000.009',\n '000.010',\n '000.011',\n '000.012',\n '000.013',\n // Duplicado / estado previo\n '000.027',\n '002.001',\n '002.003',\n '002.004',\n '003.004',\n '004.003',\n '006.002',\n '999.009a',\n]);\n\n/**\n * Normaliza un `errorCode` que puede venir como string, número o array (el CMS\n * devuelve un array de códigos cuando hay varias violaciones de contraseña).\n * Devuelve el primer código no vacío.\n */\nexport function normalizeErrorCode(\n errorCode: string | number | Array<string | number> | null | undefined,\n): string | undefined {\n if (errorCode === null || errorCode === undefined) return undefined;\n if (Array.isArray(errorCode)) {\n const first = errorCode.find((c) => c !== null && c !== undefined && c !== '');\n return first === undefined ? undefined : String(first);\n }\n const value = String(errorCode);\n return value === '' ? undefined : value;\n}\n\n/**\n * Resuelve el mensaje legible de un código de error en el idioma indicado.\n * Aplica el fallback legacy `código → código+'a'` (p. ej. `999.002` → `999.002a`)\n * y, si el idioma no tiene el código, cae a inglés. Devuelve `undefined` si el\n * código es desconocido (el caller debe usar entonces el `error` crudo o un\n * mensaje genérico).\n */\nexport function getCommonError(\n errorCode: string | number | Array<string | number> | null | undefined,\n locale: Locale = 'es',\n): string | undefined {\n const code = normalizeErrorCode(errorCode);\n if (!code) return undefined;\n const dict = DICTS[locale] ?? commonErrorsEn;\n return (\n dict[code] ??\n dict[`${code}a`] ??\n commonErrorsEn[code] ??\n commonErrorsEn[`${code}a`]\n );\n}\n\n/** Devuelve la severidad de toast para un código de error (`warning`/`error`). */\nexport function resolveErrorSeverity(\n errorCode: string | number | Array<string | number> | null | undefined,\n): CmsErrorSeverity {\n const code = normalizeErrorCode(errorCode);\n if (!code) return 'error';\n return WARNING_CODES.has(code) ? 'warning' : 'error';\n}\n","/**\n * Clasificación de errores de red / servidor.\n *\n * Módulo **server-safe** (sin React): lo usan tanto los server actions del\n * gestor (para convertir una excepción de axios en un `CmsResponse` con código\n * de red) como el hook de reintento del cliente (`useResilientAction`) y el\n * clasificador de resultados ya devueltos.\n *\n * Los códigos `net.*` NO provienen del CMS: son internos de la lib para\n * distinguir \"sin conexión\" / \"timeout\" / \"backend caído\" del resto de fallos.\n * Sus textos legibles viven en `commonErrors.{es,en,pt}.ts` y se muestran vía\n * `notifyCmsResponse` (severidad `error`, igual que el toast rojo del Angular).\n */\n\n/** Códigos internos de error de red/servidor (no son del CMS). */\nexport const NETWORK_ERROR_CODES = {\n /** Sin conexión a internet (no se pudo alcanzar el servidor). */\n offline: 'net.offline',\n /** La petición excedió el timeout. */\n timeout: 'net.timeout',\n /** El backend no responde (502/503/504). */\n unavailable: 'net.unavailable',\n /** Error interno del servidor (5xx genérico). */\n server: 'net.server',\n} as const;\n\nexport type NetworkErrorCode =\n (typeof NETWORK_ERROR_CODES)[keyof typeof NETWORK_ERROR_CODES];\n\nconst NETWORK_CODE_SET = new Set<string>(Object.values(NETWORK_ERROR_CODES));\n\n/**\n * Códigos de red que conviene **reintentar** (todos, por ahora: son fallos\n * transitorios de conectividad/servidor). Se separa por si en el futuro algún\n * código de red no debiera reintentarse.\n */\nconst RETRYABLE_NETWORK_CODES = new Set<string>([\n NETWORK_ERROR_CODES.offline,\n NETWORK_ERROR_CODES.timeout,\n NETWORK_ERROR_CODES.unavailable,\n NETWORK_ERROR_CODES.server,\n]);\n\nexport interface ClassifiedNetworkError {\n errorCode: NetworkErrorCode;\n /** Si conviene reintentar la petición. */\n retryable: boolean;\n /** Mensaje crudo del error original (para el detalle copiable del toast). */\n error: string;\n}\n\n/** `true` si el código dado es uno de los códigos internos de red. */\nexport function isNetworkErrorCode(code: string | null | undefined): boolean {\n return code !== null && code !== undefined && NETWORK_CODE_SET.has(code);\n}\n\n/** `true` si un código de red debe reintentarse. */\nexport function isRetryableNetworkCode(code: string | null | undefined): boolean {\n return code !== null && code !== undefined && RETRYABLE_NETWORK_CODES.has(code);\n}\n\n/**\n * Clasifica una excepción (error de axios en el servidor, o `TypeError:\n * Failed to fetch` del navegador al invocar un server action) como error de\n * red/servidor. Devuelve `null` si NO es un error de red (p. ej. un 4xx o una\n * excepción de lógica): el caller lo trata entonces como error de negocio.\n */\nexport function classifyNetworkError(\n error: unknown,\n): ClassifiedNetworkError | null {\n const err = error as {\n code?: string;\n message?: string;\n response?: { status?: number };\n request?: unknown;\n status?: number;\n } | null;\n const message = error instanceof Error ? error.message : String(error);\n const status = err?.response?.status ?? err?.status;\n const code = err?.code;\n\n // Timeout de axios (o mensaje explícito de timeout).\n if (code === 'ECONNABORTED' || code === 'ETIMEDOUT' || /timeout/i.test(message)) {\n return { errorCode: NETWORK_ERROR_CODES.timeout, retryable: true, error: message };\n }\n\n // Respuesta HTTP de servidor caído.\n if (status === 502 || status === 503 || status === 504) {\n return { errorCode: NETWORK_ERROR_CODES.unavailable, retryable: true, error: message };\n }\n if (typeof status === 'number' && status >= 500) {\n return { errorCode: NETWORK_ERROR_CODES.server, retryable: true, error: message };\n }\n\n // Error de red sin respuesta: axios ERR_NETWORK, fetch \"Failed to fetch\" /\n // \"Network Error\", o una excepción sin `response` (no llegó nada del server).\n const looksLikeNetwork =\n code === 'ERR_NETWORK' ||\n /network\\s?error|failed to fetch|load failed|networkerror|fetch failed/i.test(\n message,\n ) ||\n (status === undefined && err?.response === undefined && err?.request !== undefined);\n if (looksLikeNetwork) {\n return { errorCode: NETWORK_ERROR_CODES.offline, retryable: true, error: message };\n }\n\n // Hay un status < 500 (4xx) o es una excepción de negocio: no es red.\n return null;\n}\n\n/**\n * Si un resultado ya devuelto por un server action es un envelope de error con\n * un código de red (`{ status: 'error', errorCode: 'net.*' }`), devuelve ese\n * código; si no, `null`. Permite reintentar cuando el fallo de red se detectó\n * en el servidor (Next→OpenCms) y viajó como `CmsResponse`.\n */\nexport function getNetworkErrorCodeFromResult(\n result: unknown,\n): NetworkErrorCode | null {\n if (typeof result !== 'object' || result === null) return null;\n const r = result as { status?: unknown; errorCode?: unknown };\n if (r.status !== 'error' && r.status !== 'fail') return null;\n const code = typeof r.errorCode === 'string' ? r.errorCode : undefined;\n return code && NETWORK_CODE_SET.has(code) ? (code as NetworkErrorCode) : null;\n}\n","/**\n * Puente entre el interceptor de axios (un módulo, sin React) y el\n * `CmsNetworkProvider` (React). Replica el rol del `NetworkService` que se\n * inyecta en el `NetworkInterceptor` del Angular legacy: el interceptor no\n * puede usar hooks, así que el provider registra aquí sus funciones y el\n * interceptor las consume.\n *\n * Módulo **server-safe** (sin React, sin `'use client'`): así lo puede importar\n * el `lib/http/axios.ts` del gestor —que corre tanto en cliente como en\n * servidor— sin arrastrar componentes cliente. En el servidor el bridge queda\n * sin registrar (no hay provider) y `resumeAxiosOnNetworkError` re-lanza el\n * error para que lo maneje el server action (`toCmsError`).\n */\n\nimport { classifyNetworkError } from './classifyNetworkError';\n\n/** Funciones que el `CmsNetworkProvider` registra para el interceptor. */\nexport interface CmsNetworkBridgeHandlers {\n /** Marca la conexión como offline de inmediato (dispara el toast). */\n reportOffline: () => void;\n /** Resuelve cuando la conexión vuelve (confirmada por el ping/eventos). */\n waitForOnline: () => Promise<void>;\n /** Confirma por ping si hay internet real. `true` = online. */\n verifyConnectivity: () => Promise<boolean>;\n}\n\n// El estado vive en `globalThis`, no en una variable de módulo: Vite empaqueta\n// la lib en dos entries (cliente `index` y `server`) y el bridge podría quedar\n// duplicado (el provider lo importa del cliente; el interceptor de axios, de\n// `/server`). Con una variable de módulo serían dos singletons y el registro no\n// se vería. En el navegador `globalThis` es único, así que ambas copias\n// comparten el mismo estado.\nconst BRIDGE_KEY = '__cmsNetworkBridgeHandlers__';\n\ntype GlobalWithBridge = typeof globalThis & {\n [BRIDGE_KEY]?: CmsNetworkBridgeHandlers | null;\n};\n\nfunction getHandlers(): CmsNetworkBridgeHandlers | null {\n return (globalThis as GlobalWithBridge)[BRIDGE_KEY] ?? null;\n}\n\nfunction setHandlers(next: CmsNetworkBridgeHandlers | null): void {\n (globalThis as GlobalWithBridge)[BRIDGE_KEY] = next;\n}\n\n/**\n * Singleton que conecta el interceptor de axios con el provider de red. El\n * provider llama `register` al montar y `unregister` al desmontar; el\n * interceptor usa los métodos (con fallback seguro si no hay provider).\n */\nexport const cmsNetworkBridge = {\n register(next: CmsNetworkBridgeHandlers): void {\n setHandlers(next);\n },\n unregister(): void {\n setHandlers(null);\n },\n /** `true` si hay un `CmsNetworkProvider` montado escuchando. */\n get isRegistered(): boolean {\n return getHandlers() !== null;\n },\n reportOffline(): void {\n getHandlers()?.reportOffline();\n },\n waitForOnline(): Promise<void> {\n return getHandlers()?.waitForOnline() ?? Promise.resolve();\n },\n verifyConnectivity(): Promise<boolean> {\n return (\n getHandlers()?.verifyConnectivity() ??\n Promise.resolve(typeof navigator === 'undefined' || navigator.onLine)\n );\n },\n};\n\n/**\n * Da resiliencia de red a una petición de axios, replicando el\n * `NetworkInterceptor` del Angular legacy. Pensado para el `onRejected` del\n * interceptor de respuesta de axios del gestor:\n *\n * ```ts\n * api.interceptors.response.use(\n * (r) => r,\n * (error) => resumeAxiosOnNetworkError(error, (config) => api.request(config)),\n * );\n * ```\n *\n * - **En el servidor, o no es error de red, o no hay provider montado** →\n * re-lanza el error (lo maneja el caller / `toCmsError`).\n * - **Sin internet** (el navegador reporta offline, o el ping confirma que no\n * hay salida real, p. ej. `ERR_NAME_NOT_RESOLVED`): muestra \"sin conexión\"\n * (vía el provider), arranca el ping y, al volver la conexión, **reintenta**\n * la petición (retoma el servicio).\n * - **Con internet** (el caído era el backend: 5xx/timeout): re-lanza sin\n * reintentar, para no repetir a ciegas un POST. Ese caso lo cubre\n * `useResilientAction`/`toCmsError` en las mutaciones envueltas.\n */\nexport async function resumeAxiosOnNetworkError<T = unknown>(\n error: unknown,\n reAttempt: (config: unknown) => Promise<T>,\n): Promise<T> {\n // Solo en el navegador: en el servidor lo maneja el server action.\n if (typeof window === 'undefined') throw error;\n\n // Solo errores de red/servidor; un 4xx o error de negocio se re-lanza.\n const classified = classifyNetworkError(error);\n if (!classified) throw error;\n\n const config = (error as { config?: unknown } | null)?.config;\n // Sin config no se puede reintentar; sin provider no hay toast/ping/espera.\n if (config == null || !cmsNetworkBridge.isRegistered) throw error;\n\n // ¿Realmente no hay internet? El ping evita un falso \"sin conexión\" cuando el\n // que está caído es el backend (y sí hay salida a internet).\n let offline: boolean;\n if (typeof navigator !== 'undefined' && !navigator.onLine) {\n cmsNetworkBridge.reportOffline();\n offline = true;\n } else {\n offline = !(await cmsNetworkBridge.verifyConnectivity());\n }\n\n // Había internet → era el backend, no una pérdida de red: que lo maneje el\n // caller (toast de error / reintento de la mutación envuelta).\n if (!offline) throw error;\n\n // Sin internet: espera la reconexión (ping polling) y reintenta la petición.\n // No lleva contador: si al reintentar sigue caído, vuelve a esperar; el ciclo\n // lo gobierna la conexión real, igual que el interceptor del Angular.\n await cmsNetworkBridge.waitForOnline();\n return reAttempt(config);\n}\n","/**\n * Normaliza un valor a un `data-testid` estable en kebab-case ASCII.\n *\n * Equivalente React del pipe `toTestId` del CMS Angular (`cmsmedios-ux`):\n * pasa a minúsculas, quita tildes/acentos y convierte cualquier separador\n * (espacios, puntos, guiones bajos, barras) en un único guion.\n *\n * IMPORTANTE: el valor que se le pasa debe ser **independiente del idioma**\n * (una clave i18n, un `id`/`value`/`slug`, un código o enum interno), nunca el\n * texto traducido: si no, el `data-testid` cambiaría según el idioma del usuario\n * y las pruebas no podrían apuntarlo de forma estable.\n *\n * @param value Valor de origen (clave i18n, id, código o índice).\n * @returns El `data-testid` normalizado, o `''` si el valor es vacío/nulo.\n *\n * @example\n * toTestId('modal.deactivate.title') // 'modal-deactivate-title'\n * toTestId('Próximo evento') // 'proximo-evento'\n * toTestId(3) // '3'\n */\nexport function toTestId(value: string | number | null | undefined): string {\n if (value === null || value === undefined || value === '') return '';\n return String(value)\n .trim()\n .toLowerCase()\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '') // quita tildes y acentos\n .replace(/[\\s._/\\\\]+/g, '-') // espacios, puntos, guiones bajos y barras → guion\n .replace(/[^a-z0-9-]/g, '') // descarta cualquier otro carácter\n .replace(/-+/g, '-') // colapsa guiones repetidos\n .replace(/^-+|-+$/g, ''); // recorta guiones al inicio y al final\n}\n","import { cmsColors } from '../theme/variables';\nimport type { Publication } from '../types/publication';\nimport type { SiteSection } from '../types/site';\n\nexport const MENU_BG = cmsColors.menuSurface;\nexport const ITEM_HOVER_BG = cmsColors.secondary;\nexport const ITEM_DEFAULT_BG = cmsColors.surface;\n\nexport const DEFAULT_SITE_ID = 'bluestack-es';\n\nexport function getAllPublications(sites: SiteSection[]): Publication[] {\n return sites.flatMap((section) => section.publications);\n}\n\nexport function findPublicationBySlug(\n sites: SiteSection[],\n slug: string,\n): Publication | undefined {\n return getAllPublications(sites).find((p) => String(p.id) === slug);\n}\n\nexport function findPublicationLabel(\n sites: SiteSection[],\n publicationId: string,\n): string {\n const publication = getAllPublications(sites).find(\n (p) => String(p.id) === publicationId,\n );\n return publication?.description ?? 'Seleccionar publicación';\n}\n\nexport function getDefaultPublicationSlug(sites: SiteSection[]): string {\n const first = getAllPublications(sites)[0];\n return first ? String(first.id) : '1';\n}\n\nexport function parsePublicationSlug(slug: string): number {\n const id = Number(slug);\n return Number.isFinite(id) && id > 0 ? id : 1;\n}\n","/**\n * Utilidades de hora del sitio (zona de redacción de la publicación).\n *\n * El backend entrega en cada `Publication` un offset GMT fijo\n * (`gmtRedaction`, p. ej. `\"-3\"` / `\"+0\"`) — NO una zona IANA. Por eso la\n * conversión se hace con un offset fijo y no contempla horario de verano\n * (DST). Es el equivalente, en React, de lo que en el CMS Angular hacía\n * `settings.service` (`getFormattedRedactionTimeStamp` /\n * `getFormattedRedactionTimeUTC`).\n *\n * El criterio: un timestamp del CMS es un instante en UTC (epoch ms). Para\n * mostrarlo \"como lo ve la redacción\" se desplaza el instante por el offset y\n * se formatea en `timeZone: 'UTC'`, de modo que el resultado es estable e\n * independiente de la zona horaria del navegador.\n */\n\n/**\n * Convierte el offset GMT de una publicación a minutos.\n * Acepta `\"-3\"`, `\"+3\"`, `\"3\"`, `\"+5:30\"`, tolera prefijos `GMT`/`UTC` y\n * espacios. Si el valor no es interpretable, devuelve `0` (UTC).\n *\n * @param gmt Offset tal como llega en `Publication.gmtRedaction`.\n * @returns Offset en minutos respecto de UTC (negativo al oeste de Greenwich).\n */\nexport function parseGmtOffsetMinutes(gmt: string | null | undefined): number {\n if (!gmt) return 0;\n const cleaned = String(gmt).trim().replace(/^(GMT|UTC)/i, '').trim();\n const match = cleaned.match(/^([+-]?)(\\d{1,2})(?::(\\d{2}))?$/);\n if (!match) return 0;\n const sign = match[1] === '-' ? -1 : 1;\n const hours = Number(match[2]);\n const minutes = match[3] ? Number(match[3]) : 0;\n return sign * (hours * 60 + minutes);\n}\n\n/**\n * Desplaza un instante (epoch ms en UTC) al \"reloj de pared\" de la zona de\n * redacción del sitio. El número resultante, formateado con `timeZone: 'UTC'`,\n * muestra la hora local del sitio sin importar la zona del navegador.\n *\n * @param epochMs Instante en milisegundos (UTC).\n * @param gmtRedaction Offset GMT de la publicación.\n * @returns Epoch ms desplazado por el offset del sitio.\n */\nexport function toSiteWallClock(\n epochMs: number,\n gmtRedaction: string | null | undefined,\n): number {\n return epochMs + parseGmtOffsetMinutes(gmtRedaction) * 60_000;\n}\n\n/** Opciones de formato por defecto: `DD/MM/AAAA HH:MM` en 24h. */\nconst DEFAULT_DATE_TIME_OPTIONS: Intl.DateTimeFormatOptions = {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n};\n\n/**\n * Formatea un instante (epoch ms) en la zona horaria del sitio, de forma\n * estable entre navegadores.\n *\n * @param epochMs Instante en milisegundos (UTC).\n * @param gmtRedaction Offset GMT de la publicación.\n * @param localeTag Tag BCP 47 (p. ej. `\"es-AR\"`); usar `getIntlLocaleTag(locale)`.\n * @param options Opciones de `Intl.DateTimeFormat` (se fuerza `timeZone: 'UTC'`).\n */\nexport function formatSiteDateTime(\n epochMs: number,\n gmtRedaction: string | null | undefined,\n localeTag: string,\n options: Intl.DateTimeFormatOptions = DEFAULT_DATE_TIME_OPTIONS,\n): string {\n const shifted = toSiteWallClock(epochMs, gmtRedaction);\n return new Intl.DateTimeFormat(localeTag, {\n ...options,\n timeZone: 'UTC',\n }).format(shifted);\n}\n\n/**\n * Hora actual del sitio (equivalente al `getFormattedRedactionTimeUTC` del CMS\n * Angular): \"ahora\" formateado en la zona de redacción de la publicación.\n *\n * @param gmtRedaction Offset GMT de la publicación.\n * @param localeTag Tag BCP 47 (p. ej. `\"es-AR\"`).\n * @param options Opciones de `Intl.DateTimeFormat`.\n */\nexport function getSiteNow(\n gmtRedaction: string | null | undefined,\n localeTag: string,\n options: Intl.DateTimeFormatOptions = DEFAULT_DATE_TIME_OPTIONS,\n): string {\n return formatSiteDateTime(Date.now(), gmtRedaction, localeTag, options);\n}\n\n/** Estilo del texto relativo (`Intl.RelativeTimeFormat`). */\nexport type RelativeTimeStyle = 'long' | 'short' | 'narrow';\n\n/**\n * Escala de unidades para elegir la más significativa. Cada `amount` es cuántas\n * de esa unidad entran en la siguiente (60 s = 1 min, 60 min = 1 h, …). La\n * última (`year`) es tope, por eso `Infinity`.\n */\nconst RELATIVE_DIVISIONS: {\n amount: number;\n unit: Intl.RelativeTimeFormatUnit;\n}[] = [\n { amount: 60, unit: 'second' },\n { amount: 60, unit: 'minute' },\n { amount: 24, unit: 'hour' },\n { amount: 7, unit: 'day' },\n { amount: 4.34524, unit: 'week' }, // semanas por mes (365.25 / 12 / 7)\n { amount: 12, unit: 'month' },\n { amount: Number.POSITIVE_INFINITY, unit: 'year' },\n];\n\n/**\n * Formatea un instante como tiempo transcurrido hasta \"ahora\": \"hace 18 minutos\",\n * \"hace 3 días\", \"hace 3 meses\". Elige sola la unidad más significativa y se\n * traduce al idioma del `localeTag` vía `Intl.RelativeTimeFormat` (no requiere\n * claves i18n propias).\n *\n * La cuenta es una resta de instantes UTC, así que NO depende del GMT del sitio\n * ni de la zona del navegador (a diferencia de `formatSiteDateTime`).\n *\n * @param epochMs Instante en milisegundos (UTC).\n * @param localeTag Tag BCP 47 (p. ej. `\"es-AR\"`); usar `getIntlLocaleTag(locale)`.\n * @param options `nowMs` (referencia de \"ahora\", por defecto `Date.now()`) y\n * `style` (por defecto `\"long\"`).\n */\nexport function formatRelativeTime(\n epochMs: number,\n localeTag: string,\n options: { nowMs?: number; style?: RelativeTimeStyle } = {},\n): string {\n const { nowMs = Date.now(), style = 'long' } = options;\n const rtf = new Intl.RelativeTimeFormat(localeTag, {\n numeric: 'always',\n style,\n });\n // Diferencia en segundos; negativo = pasado. Clamp a -1 para no mostrar\n // \"hace 0 segundos\" ni un tiempo en futuro por desfases de reloj.\n let duration = (epochMs - nowMs) / 1000;\n if (duration > -1) duration = -1;\n for (const division of RELATIVE_DIVISIONS) {\n if (Math.abs(duration) < division.amount) {\n return rtf.format(Math.round(duration), division.unit);\n }\n duration /= division.amount;\n }\n // Inalcanzable (la última división es Infinity); solo por completitud de tipos.\n return rtf.format(Math.round(duration), 'year');\n}\n","import type { AuthPermissionsResponse } from '../services/auth';\nimport type { NavItemPermissions } from '../types/navigation';\n\n/** Operación individual de POST /auth/permissions (forma laxa del CMS). */\ntype AuthOperation = { name?: string; [key: string]: unknown };\n\n/**\n * Decide si el usuario puede acceder a un módulo, replicando el\n * `AccessPermissionsGuard` de cmsmedios: un admin siempre pasa, el comodín\n * `All_VIEWS` siempre pasa, y en el resto el usuario debe tener una operación\n * cuyo `name` coincida con el permiso requerido. La comparación es\n * case-insensitive (cmsmedios pasa el permiso de la ruta a mayúsculas).\n *\n * @param permissions respuesta de POST /auth/permissions (`isAdmin` + `operations`)\n * @param requiredPermission permiso que exige la ruta (p. ej. `'NEWS_VIEW'`)\n * @returns `true` si tiene acceso; `false` si debería redirigirse a `/not-allowed`\n */\nexport function hasModulePermission(\n permissions:\n | Pick<AuthPermissionsResponse, 'isAdmin' | 'operations'>\n | null\n | undefined,\n requiredPermission: string,\n): boolean {\n if (!permissions) return false;\n if (permissions.isAdmin) return true;\n const required = requiredPermission.toUpperCase();\n if (required === 'ALL_VIEWS') return true;\n const operations = (permissions.operations ?? []) as AuthOperation[];\n return operations.some(\n (op) => typeof op?.name === 'string' && op.name.toUpperCase() === required,\n );\n}\n\n/**\n * Filtra los módulos de POST /auth/modulesAvailable dejando solo los que el\n * usuario puede ver, replicando el cruce que hace `parseModuleIntoMenu` de\n * cmsmedios: un admin ve todo; el resto solo ve un módulo si tiene la operación\n * `${module}_VIEW` en POST /auth/permissions. La comparación es case-insensitive.\n *\n * Degrada con seguridad: si `permissions` es null/undefined (p. ej. porque\n * /auth/permissions falló), NO filtra y devuelve los módulos tal cual (misma\n * visibilidad que hoy). El acceso real lo sigue gobernando el guard de ruta\n * (`hasModulePermission`), así que el menú puede degradar sin exponer nada.\n *\n * @param modules módulos crudos de POST /auth/modulesAvailable\n * @param permissions respuesta de POST /auth/permissions (`isAdmin` + `operations`)\n * @returns los módulos visibles para el usuario (preserva `isnew`)\n */\nexport function filterModulesByPermissions(\n modules: NavItemPermissions[],\n permissions:\n | Pick<AuthPermissionsResponse, 'isAdmin' | 'operations'>\n | null\n | undefined,\n): NavItemPermissions[] {\n if (!permissions) return modules;\n if (permissions.isAdmin) return modules;\n const viewNames = new Set(\n ((permissions.operations ?? []) as AuthOperation[])\n .map((op) => (typeof op?.name === 'string' ? op.name.toUpperCase() : ''))\n .filter(Boolean),\n );\n return modules.filter((module) =>\n viewNames.has(`${module.module.toUpperCase()}_VIEW`),\n );\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { ModulesAvailableResponse } from './site';\nimport type { CmsResponse } from './users';\n\n/** Datos de sesión devueltos por los endpoints de login/relogin. */\nexport interface AuthSessionData {\n site?: string;\n publication?: string;\n project?: string;\n locale?: string;\n mustChangePassword?: boolean;\n}\n\n/** Cuerpo de la respuesta de POST /auth/relogin. */\nexport interface AuthReloginResponse extends CmsResponse, AuthSessionData {}\n\n/** Sesión activa del usuario (forma exacta no documentada). */\nexport interface AuthSessionInfo {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /auth/logout. */\nexport interface AuthLogoutResponse extends CmsResponse {\n /** Sesiones activas del usuario. */\n infos?: AuthSessionInfo[];\n}\n\n/**\n * Cuerpo de la respuesta de POST /auth/changePassword.\n *\n * Nota: ante violaciones de reglas de contraseña, `errorCode` puede venir como\n * array de códigos y `errorData` con detalles adicionales.\n */\nexport interface AuthChangePasswordResponse\n extends CmsResponse,\n AuthSessionData {\n /** Nuevo token generado tras el cambio exitoso. */\n newToken?: string;\n errorData?: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /auth/permissions. Incluye operaciones,\n * grupos y flags de integraciones habilitadas.\n */\nexport interface AuthPermissionsResponse extends CmsResponse {\n operations?: unknown[];\n guilds?: unknown[];\n isAdmin?: boolean;\n ID?: string;\n googleSearchConsole?: { integrationEnabled?: boolean; [key: string]: unknown };\n analyticsView?: {\n viewEnabled?: boolean;\n newsFromLastHoursPublish?: number;\n [key: string]: unknown;\n };\n AIEnabledVertex?: boolean;\n AmzTranslateEnabled?: boolean;\n newscheck?: { enabledInManager?: boolean; [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /auth/create. La versión revisada del código\n * no agrega explícitamente los flags `canCreateX` a la raíz, por eso es laxo.\n */\nexport interface AuthCreateResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\ninterface IAuthServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `auth` del CMS (solo endpoints post-login que usan\n * el objeto `authentication` de sesión).\n *\n * Los flujos de login, recuperación de contraseña y 2FA (login, forgotPassword,\n * setNewPassword, validatePassword, loginValid, twoFactor/*, adminBack/login,\n * etc.) no se incluyen por no seguir este patrón.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsAuthServices {\n protected props: IAuthServices;\n protected authentication: Authentication;\n\n constructor(props: IAuthServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /auth/relogin — re-autentica con el token de sesión existente. */\n relogin = async (): Promise<AuthReloginResponse> => {\n try {\n const response = await this.props.axiosApi.post<AuthReloginResponse>(\n '/auth/relogin',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/relogin]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/logout — invalida la sesión y lista sesiones activas. */\n logout = async (): Promise<AuthLogoutResponse> => {\n try {\n const response = await this.props.axiosApi.post<AuthLogoutResponse>(\n '/auth/logout',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/logout]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/changePassword — cambia la contraseña del usuario autenticado. */\n changePassword = async (\n newPassword: string,\n ): Promise<AuthChangePasswordResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<AuthChangePasswordResponse>(\n '/auth/changePassword',\n {\n authentication: this.authentication,\n newPassword,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/changePassword]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/permissions — operaciones/permisos del usuario en la publicación. */\n getPermissions = async (): Promise<AuthPermissionsResponse> => {\n try {\n const response = await this.props.axiosApi.post<AuthPermissionsResponse>(\n '/auth/permissions',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/permissions]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/modulesAvailable — módulos disponibles para el usuario. */\n getModulesAvailable = async (): Promise<ModulesAvailableResponse> => {\n try {\n const response = await this.props.axiosApi.post<ModulesAvailableResponse>(\n '/auth/modulesAvailable',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/modulesAvailable]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/create — permisos de creación por tipo de contenido. */\n getCreatePermissions = async (): Promise<AuthCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<AuthCreateResponse>(\n '/auth/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/create]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Cuerpo de la respuesta de POST /dashboard/countNotifications. */\nexport interface DashboardCountNotificationsResponse extends CmsResponse {\n /** Total de notificaciones no leídas del usuario autenticado. */\n unreadNotifications?: number;\n /**\n * Oportunidades copilot no leídas (NAA-4645). Ya está **sumado** dentro de\n * `unreadNotifications`; solo aparece si copilot aplica al usuario/publicación.\n */\n copilotOpportunities?: number;\n}\n\n/** Evento de encoder de video presente en POST /dashboard/notification. */\nexport interface DashboardVideoNotification {\n actionId?: number;\n description?: string;\n eventId?: string;\n lastModified?: string;\n timeStamp?: string;\n userName?: string;\n /** Indica si el evento ya fue leído según la última lectura del usuario. */\n isRead?: boolean;\n [key: string]: unknown;\n}\n\n/** Tarea asignada activa presente en POST /dashboard/notification. */\nexport interface DashboardNewsTask {\n id?: string;\n isRead?: boolean;\n site?: string;\n publication?: number;\n startdate?: number;\n [key: string]: unknown;\n}\n\n/** Actividad vencida o por vencer presente en POST /dashboard/notification. */\nexport interface DashboardExpireTask {\n id?: string;\n isRead?: boolean;\n site?: string;\n publication?: number;\n startdate?: number;\n [key: string]: unknown;\n}\n\n/**\n * Aviso de desasignación de tarea de planning presente en POST\n * /dashboard/notification (array `unassignTask`, mismos campos que `newsTask`).\n * El back lo despacha solo cuando corresponde (cambio de responsable). El autor\n * de la desasignación es OPCIONAL: puede venir como `userName` o `userCreation`,\n * con `userLogin` entre paréntesis. Si no llega ninguno, se usa el texto genérico.\n */\nexport interface DashboardUnassignTask {\n id?: string;\n /** Título de la tarea de la que se desasignó al usuario. */\n title?: string;\n /** Autor de la desasignación (nombre). Opcional. */\n userName?: string;\n userCreation?: string;\n /** Login del autor (se muestra entre paréntesis). Opcional. */\n userLogin?: string;\n /** Timestamp del aviso (epoch ms o `{ time }`). */\n timeStamp?: unknown;\n isRead?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Oportunidad editorial copilot presente en POST /dashboard/notification\n * (NAA-4645). El back manda hasta 3, ordenadas por `score` desc, y solo si hay.\n */\nexport interface DashboardCopilotOpportunity {\n /** Id de la oportunidad (opportunity_id, requerido para el snooze). */\n id?: string;\n title: string;\n /** Tema/categoría de la oportunidad. */\n topic?: string;\n /** Puntaje de coincidencia editorial (0-100). */\n score?: number;\n /** Fecha de creación (ISO 8601, p. ej. \"2026-06-26T10:15:00Z\"). */\n created_at?: string;\n isRead?: boolean;\n}\n\n/**\n * Cuerpo de la respuesta de POST /dashboard/notification.\n *\n * Los arrays solo aparecen si tienen al menos un elemento.\n */\nexport interface DashboardNotificationsResponse extends CmsResponse {\n /** Eventos de encoder de video. */\n videos?: DashboardVideoNotification[];\n /** Tareas asignadas activas. */\n newsTask?: DashboardNewsTask[];\n /** Actividades vencidas o por vencer. */\n expireTask?: DashboardExpireTask[];\n /** Avisos de desasignación de tarea de planning (`person_remove`). */\n unassignTask?: DashboardUnassignTask[];\n /** Oportunidades editoriales copilot (hasta 3, por `score` desc). NAA-4645. */\n copilot?: DashboardCopilotOpportunity[];\n}\n\ninterface IDashboardServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `dashboard` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsDashboardServices {\n protected props: IDashboardServices;\n protected authentication: Authentication;\n\n constructor(props: IDashboardServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /dashboard/countNotifications — total de notificaciones no leídas. */\n countNotifications =\n async (): Promise<DashboardCountNotificationsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<DashboardCountNotificationsResponse>(\n '/dashboard/countNotifications',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/dashboard/countNotifications]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /dashboard/notification — detalle de notificaciones pendientes. */\n getNotifications = async (): Promise<DashboardNotificationsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<DashboardNotificationsResponse>(\n '/dashboard/notification',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/dashboard/notification]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { ProfileGetResponse } from '../types/profile';\nimport type { CmsResponse } from './users';\n\n/** Campo adicional editable del perfil (`user.data.additionalInfo`). */\nexport interface ProfileAdditionalInfoValue {\n name: string;\n value: string;\n}\n\n/** Datos básicos editables del perfil (`user.data` de POST /profile/update). */\nexport interface ProfileUpdateData {\n firstName?: string;\n lastName?: string;\n email?: string;\n /** Campos adicionales como pares `{ name, value }`. */\n additionalInfo?: ProfileAdditionalInfoValue[];\n /** Pares extra indexados como `extraData0`, `extraData1`, etc. */\n extraDataCount?: { [key: string]: unknown };\n}\n\n/** Preferencias editables del perfil (`user.config` de POST /profile/update). */\nexport interface ProfileUpdateConfig {\n /** ID de publicación a establecer como predeterminada. */\n publication?: string | number;\n /** Sitio predeterminado. */\n site?: string;\n /** Código de idioma (ej: \"es\"). */\n language?: string;\n /** Layout de vista preferido. */\n viewLayout?: string;\n}\n\n/** Payload `user` de POST /profile/update. */\nexport interface ProfileUpdateInput {\n data?: ProfileUpdateData;\n config?: ProfileUpdateConfig;\n}\n\n/** Cuerpo de la respuesta de POST /profile/moduleAlerts/get. */\nexport interface ProfileModuleAlertsResponse extends CmsResponse {\n /** Array de módulos ocultos (\"pines\") del usuario. */\n hiddenModules?: unknown[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /profile/moduleAlerts/hide. */\nexport interface ProfileModuleAlertHideResponse extends CmsResponse {\n /** Lista actualizada de módulos ocultos. */\n hiddenBanners?: unknown[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /profile/pines/add. */\nexport interface ProfilePinAddResponse extends CmsResponse {\n /** ID del pin creado. */\n pinId?: number;\n}\n\n/** Cuerpo de la respuesta de POST /profile/pines/get. */\nexport interface ProfilePinsGetResponse extends CmsResponse {\n /** Identificadores de recursos anclados por el usuario (tipo de recurso 200). */\n pines: unknown[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /profile/twoFactor/showOtc. */\nexport interface ProfileOtcResponse extends CmsResponse {\n /** Códigos de uso único (backup codes) generados. */\n codes?: string[];\n [key: string]: unknown;\n}\n\ninterface IProfileServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `profile` del CMS (perfil, imagen, pines,\n * moduleAlerts y doble factor).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsProfileServices {\n protected props: IProfileServices;\n protected authentication: Authentication;\n\n constructor(props: IProfileServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /profile/get — perfil completo del usuario autenticado. */\n getProfile = async (): Promise<ProfileGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ProfileGetResponse>(\n '/profile/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/update — actualiza datos y preferencias del perfil. */\n updateProfile = async (user: ProfileUpdateInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/update',\n {\n authentication: this.authentication,\n user,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/image/delete — elimina la foto de perfil del usuario. */\n deleteImage = async (): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/image/delete',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/image/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/moduleAlerts/get — módulos ocultos (\"pines\") del usuario. */\n getModuleAlerts = async (): Promise<ProfileModuleAlertsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProfileModuleAlertsResponse>(\n '/profile/moduleAlerts/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/moduleAlerts/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/moduleAlerts/hide — oculta un módulo y devuelve la lista actualizada. */\n hideModuleAlert = async (\n module: string,\n ): Promise<ProfileModuleAlertHideResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProfileModuleAlertHideResponse>(\n '/profile/moduleAlerts/hide',\n {\n authentication: this.authentication,\n module,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/moduleAlerts/hide]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/pines/add — agrega uno o más pines de recurso (tipo 200). */\n addPins = async (pins: string[]): Promise<ProfilePinAddResponse> => {\n try {\n const response = await this.props.axiosApi.post<ProfilePinAddResponse>(\n '/profile/pines/add',\n {\n authentication: this.authentication,\n pines: { pin: pins },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/pines/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/pines/delete — desancla uno o más pines de recurso. */\n deletePins = async (pins: string[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/pines/delete',\n {\n authentication: this.authentication,\n pines: { pin: pins },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/pines/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/pines/get — recursos anclados del usuario en la publicación. */\n getPins = async (): Promise<ProfilePinsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ProfilePinsGetResponse>(\n '/profile/pines/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/pines/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/method/disable — desactiva un método 2FA. */\n disableTwoFactorMethod = async (method: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/twoFactor/method/disable',\n {\n authentication: this.authentication,\n method,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/method/disable]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/method/enable — activa un método 2FA. */\n enableTwoFactorMethod = async (method: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/twoFactor/method/enable',\n {\n authentication: this.authentication,\n method,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/method/enable]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/setActive — activa globalmente el doble factor. */\n setTwoFactorActive = async (): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/twoFactor/setActive',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/setActive]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/setEmail — establece el email del usuario. */\n setTwoFactorEmail = async (email: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/twoFactor/setEmail',\n {\n authentication: this.authentication,\n email,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/setEmail]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/setFavorite — establece el método 2FA favorito. */\n setTwoFactorFavorite = async (method: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/twoFactor/setFavorite',\n {\n authentication: this.authentication,\n method,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/setFavorite]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/setPhone — establece el teléfono para el canal SMS. */\n setTwoFactorPhone = async (phone: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/profile/twoFactor/setPhone',\n {\n authentication: this.authentication,\n phone,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/setPhone]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /profile/twoFactor/showOtc — genera y devuelve los códigos OTC (backup). */\n showOtc = async (): Promise<ProfileOtcResponse> => {\n try {\n const response = await this.props.axiosApi.post<ProfileOtcResponse>(\n '/profile/twoFactor/showOtc',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/profile/twoFactor/showOtc]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Zonas por publicación (hasZoneJson) */\nexport interface PublicationZoneConfig {\n home: boolean;\n section: boolean;\n defaultPublication: string;\n entro: number;\n zones: unknown[];\n}\n\n/** Permisos de la publicación en el CMS */\nexport interface PublicationPermissions {\n hasAccess: boolean;\n NEWS_EDIT: boolean;\n NEWS_SHARE: boolean;\n [key: string]: boolean;\n}\n\n/** Banner / actualizaciones de administración */\nexport interface PublicationUpdateAdmin {\n rebootBannerDate: string;\n rebootBannerDurationMin: string;\n rebootBannerEnable: boolean;\n updateBannerEnable: boolean;\n updateBannerLink: string;\n updateBannerVFSLink: boolean;\n}\n\n/** Publicación devuelta por POST /publications/get y POST /publications/default */\nexport interface Publication {\n baseURL: string;\n ckeditor: string;\n customDomain?: string;\n dateFormat: string;\n description: string;\n gmtRedaction: string;\n gmtRedactionName: string;\n gmtServer: string;\n gmtServerName: string;\n googleApiKey: string;\n hasCategory: boolean;\n hasCategoryData: string;\n hasComplianceActive: boolean;\n hasZone: boolean;\n hasZoneJson: PublicationZoneConfig;\n id: number;\n imagePath: string;\n /** Nombre del campo tal como viene del API */\n languaje: string;\n mercado: string;\n name: string;\n newsFormTarget: string;\n permitions: PublicationPermissions;\n pinedMax: string;\n publication: number;\n site: string;\n sitio: string;\n timeFormat: string;\n type: string;\n updateAdmin: PublicationUpdateAdmin;\n /**\n * ¿La publicación tiene habilitado el servicio de sugerencias CoPilot?\n * Lo devuelve `POST /publications/get` por publicación. Opcional: si el campo\n * no llega, se interpreta como **deshabilitado** (el gestor muestra el aviso\n * \"no configurado\" en lugar de la tabla de sugerencias).\n */\n copilotEnabled?: boolean;\n /**\n * Sub-sitios (multisitio) de esta publicación. Opcional: hoy el servicio no\n * lo devuelve y las publicaciones se listan planas. Cuando el backend lo\n * incluya, el selector los muestra como filas hijas expandibles con contador.\n */\n children?: Publication[];\n}\n\n/** Cuerpo de la respuesta de POST /publications/get */\nexport interface PublicationsGetResponse {\n status: string;\n publications: Publication[];\n}\n\n/**\n * Cuerpo de la respuesta de POST /publications/default.\n *\n * Es el objeto de publicación directamente (mismos campos que cada item de\n * `/publications/get`) más el envelope estándar (`status`, etc.).\n */\nexport interface PublicationDefaultResponse extends Publication, CmsResponse {}\n\ninterface IPublicationsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `publications` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsPublicationsServices {\n protected props: IPublicationsServices;\n protected authentication: Authentication;\n\n constructor(props: IPublicationsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /publications/get — publicaciones accesibles para el usuario autenticado. */\n getPublications = async (): Promise<PublicationsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<PublicationsGetResponse>(\n '/publications/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/publications/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /publications/default — publicación por defecto del usuario autenticado. */\n getDefaultPublication = async (): Promise<PublicationDefaultResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PublicationDefaultResponse>(\n '/publications/default',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/publications/default]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { NavItemPermissions } from '../types/navigation';\nimport type { SiteSection } from '../types/site';\n\n/** Entrada de sitio devuelta por POST /sites/get */\nexport interface Site {\n /** Slug del sitio; cadena vacía para la raíz */\n name: string;\n /** Etiqueta visible (p. ej. \"Generic Site 1\", \"Laboratorio\") */\n title: string;\n}\n\n/** Cuerpo de la respuesta de POST /sites/get */\nexport interface SitesGetResponse {\n /** Ruta del sitio activo (p. ej. \"/sites/generic1\") */\n root: string;\n /** Misma ruta que `root`; el API la repite con esta clave */\n 'root.': string;\n status: string;\n sites: Site[];\n}\n\n/** Cuerpo de la respuesta de POST /auth/modulesAvailable */\nexport interface ModulesAvailableResponse {\n modules: NavItemPermissions[];\n}\n\n/** Resultado de combinar sitios, publicaciones y módulos disponibles */\nexport interface SitesAndPublicationsResult {\n sites: SiteSection[];\n modules: NavItemPermissions[];\n}\n\ninterface ISitesServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `sites` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsSitesServices {\n protected props: ISitesServices;\n protected authentication: Authentication;\n\n constructor(props: ISitesServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /sites/get — lista de sitios disponibles y site root actual. */\n getSites = async (): Promise<SitesGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<SitesGetResponse>(\n '/sites/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/sites/get]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { CmsResponse } from './users';\n\n/** Datos de sesion devueltos por login / setNewPassword. */\nexport interface AuthSessionResult extends CmsResponse {\n token?: string;\n site?: string;\n publication?: string;\n project?: string;\n locale?: string;\n mustChangePassword?: boolean;\n userAccess?: boolean;\n}\n\n/** Respuesta de POST /auth/login (form-urlencoded). */\nexport type AuthLoginResponse = AuthSessionResult;\n\n/** Respuesta de POST /auth/setNewPassword. */\nexport type AuthSetNewPasswordResponse = AuthSessionResult;\n\n/** Respuesta de GET /auth/passwordConfiguration (no trae envelope `status`). */\nexport interface AuthPasswordConfigurationResponse {\n /** Texto descriptivo de las reglas de contrasena. */\n text?: string;\n [key: string]: unknown;\n}\n\n/** Respuesta de POST /auth/loginValid (credenciales encriptadas). */\nexport interface AuthLoginValidResponse extends CmsResponse {\n twoFactor?: unknown;\n dataUser?: {\n token?: string;\n site?: string;\n publication?: string;\n locale?: string;\n mustChangePassword?: boolean;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/** Metodo 2FA usado en verify. */\nexport type TwoFactorMethod = 'hotp-sms' | 'hotp-mail' | 'totp' | 'otc';\n\n/** Canal de envio de codigo HOTP. */\nexport type TwoFactorSendMethod = 'hotp-sms' | 'hotp-mail';\n\n/** Input de POST /auth/twoFactor/generateCode (userName o token+browserId). */\nexport interface TwoFactorGenerateCodeInput {\n userName?: string;\n token?: string;\n browserId?: string;\n project?: string;\n}\n\n/** Respuesta de POST /auth/twoFactor/generateCode. */\nexport interface TwoFactorGenerateCodeResponse extends CmsResponse {\n /** Secreto / data del QR para configurar TOTP. */\n secret?: string;\n}\n\n/** Input de POST /auth/twoFactor/sendCode. */\nexport interface TwoFactorSendCodeInput {\n tempId: string;\n method: TwoFactorSendMethod;\n /** Solo para hotp-sms; si se omite usa el del perfil. */\n phone?: string;\n /** Prefijo/caracteristica del telefono (requerido si se envia phone). */\n phoneFeature?: string;\n /** Solo para hotp-mail; si se omite usa el del perfil. */\n email?: string;\n}\n\n/** Respuesta de POST /auth/twoFactor/sendCode. */\nexport interface TwoFactorSendCodeResponse extends CmsResponse {\n /** Destino enmascarado (ultimos digitos / email). */\n maskedDestiny?: string;\n /** Tiempo de validez en segundos. */\n timeValid?: number;\n}\n\n/** Input de POST /auth/twoFactor/verify. */\nexport interface TwoFactorVerifyInput {\n tempId: string;\n code: string;\n method: TwoFactorMethod;\n /** Login name del usuario en OpenCms. */\n user: string;\n /** ID del navegador (va dentro del objeto authentication). */\n browserId: string;\n /** Proyecto OpenCms destino (va dentro del objeto authentication). */\n project: string;\n}\n\n/** Respuesta de POST /auth/twoFactor/verify (datos completos del usuario). */\nexport interface TwoFactorVerifyResponse extends CmsResponse {\n token?: string;\n userName?: string;\n email?: string;\n firstname?: string;\n lastname?: string;\n phone?: string;\n photo?: string;\n locale?: string;\n publication?: string;\n site?: string;\n project?: string;\n twoFactor?: unknown;\n userAccess?: boolean;\n mustChangePassword?: boolean;\n publicationImagePath?: string;\n [key: string]: unknown;\n}\n\ninterface IAuthLoginServices {\n axiosApi: AxiosInstance;\n}\n\n/**\n * Servicios HTTP del flujo de login / 2FA / recuperacion del CMS.\n *\n * A diferencia de los demas `Cms*Services`, NO se construye con una sesion\n * (`authentication`): estos endpoints son el paso PREVIO a tener token, asi\n * que reciben los datos pre-login en cada metodo. Se construye solo con\n * `{ axiosApi }`.\n */\nexport class CmsAuthLoginServices {\n protected props: IAuthLoginServices;\n\n constructor(props: IAuthLoginServices) {\n this.props = props;\n }\n\n /** POST /auth/login — autentica con usuario/contrasena (form-urlencoded). */\n login = async (\n username: string,\n password: string,\n browserId: string,\n project = 'Online',\n ): Promise<AuthLoginResponse> => {\n try {\n const body = new URLSearchParams({ username, password, browserId, project });\n const response = await this.props.axiosApi.post<AuthLoginResponse>(\n '/auth/login',\n body,\n { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/login]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/forgotPassword — inicia recuperacion de contrasena por email. */\n forgotPassword = async (email: string): Promise<CmsResponse> => {\n try {\n const body = new URLSearchParams({ email });\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/auth/forgotPassword',\n body,\n { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/forgotPassword]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/forgotUsername — recupera el username asociado a un email. */\n forgotUsername = async (email: string): Promise<CmsResponse> => {\n try {\n const body = new URLSearchParams({ email });\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/auth/forgotUsername',\n body,\n { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/forgotUsername]', error);\n return Promise.reject(error);\n }\n };\n\n /** GET /auth/passwordConfiguration — reglas de contrasena del sistema. */\n passwordConfiguration =\n async (): Promise<AuthPasswordConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.get<AuthPasswordConfigurationResponse>(\n '/auth/passwordConfiguration',\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/passwordConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/validatePassword — valida credenciales sin crear sesion. */\n validatePassword = async (\n username: string,\n password: string,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/auth/validatePassword',\n { user: { username, password } },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/validatePassword]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /auth/loginValid — login con credenciales encriptadas (backoffice). */\n loginValid = async (data: string): Promise<AuthLoginValidResponse> => {\n try {\n const response = await this.props.axiosApi.post<AuthLoginValidResponse>(\n '/auth/loginValid',\n { data },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/loginValid]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /auth/setNewPassword — establece nueva contrasena con el codigo\n * temporal de `forgotPassword`. La autenticacion es parcial (solo browserId).\n */\n setNewPassword = async (\n codeTemp: string,\n newPassword: string,\n browserId: string,\n ): Promise<AuthSetNewPasswordResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<AuthSetNewPasswordResponse>(\n '/auth/setNewPassword',\n { authentication: { browserId }, codeTemp, newPassword },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/setNewPassword]', error);\n return Promise.reject(error);\n }\n };\n\n /** Endpoints de Two-Factor Authentication (2FA). */\n twoFactor = {\n /** POST /auth/twoFactor/generateCode — secreto QR para TOTP. */\n generateCode: async (\n input: TwoFactorGenerateCodeInput,\n ): Promise<TwoFactorGenerateCodeResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<TwoFactorGenerateCodeResponse>(\n '/auth/twoFactor/generateCode',\n { authentication: input },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/twoFactor/generateCode]', error);\n return Promise.reject(error);\n }\n },\n\n /** POST /auth/twoFactor/sendCode — envia codigo HOTP por SMS o mail. */\n sendCode: async (\n input: TwoFactorSendCodeInput,\n ): Promise<TwoFactorSendCodeResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<TwoFactorSendCodeResponse>(\n '/auth/twoFactor/sendCode',\n { ...input },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/twoFactor/sendCode]', error);\n return Promise.reject(error);\n }\n },\n\n /** POST /auth/twoFactor/verify — verifica el codigo y completa el login. */\n verify: async (\n input: TwoFactorVerifyInput,\n ): Promise<TwoFactorVerifyResponse> => {\n try {\n const { tempId, code, method, user, browserId, project } = input;\n const response =\n await this.props.axiosApi.post<TwoFactorVerifyResponse>(\n '/auth/twoFactor/verify',\n {\n tempId,\n code,\n method,\n user,\n authentication: { browserId, project },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/auth/twoFactor/verify]', error);\n return Promise.reject(error);\n }\n },\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Item devuelto por los endpoints de upload. Forma laxa segun backend. */\nexport interface UploadItem {\n name?: string;\n size?: number;\n url?: string;\n type?: string;\n [key: string]: unknown;\n}\n\n/** Respuesta comun de los endpoints de upload (clave `files` o `images`). */\nexport interface UploadResponse extends CmsResponse {\n files?: UploadItem[];\n images?: UploadItem[];\n [key: string]: unknown;\n}\n\n/** Campos de formulario adicionales (ej: galUpld, selectManualGalery, autoTag). */\nexport type UploadFields = Record<string, string | Blob>;\n\ninterface IUploadServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/** Codifica el token en Base64 (btoa esta disponible en browser y Node 18+). */\nconst encodeToken = (token: string): string => btoa(token);\n\n/**\n * Helpers de subida de archivos (multipart) del CMS.\n *\n * Estos endpoints NO usan el objeto `authentication` en el body JSON: la\n * autenticacion viaja como query-params (con el `token` en Base64) y el\n * archivo va en un `FormData`. Se construye con `{ axiosApi, authentication }`\n * de sesion; internamente codifica el token y arma los query-params.\n */\nexport class CmsUploadServices {\n protected props: IUploadServices;\n protected authentication: Authentication;\n\n constructor(props: IUploadServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** Arma los query-params de autenticacion (token en Base64). */\n private authParams = () => {\n const { token, browserId, publication, siteName, project } =\n this.authentication;\n return {\n token: encodeToken(token),\n browserId,\n publication,\n siteName,\n project,\n };\n };\n\n /** Subida multipart generica: arma el FormData y postea con auth en params. */\n private upload = async (\n url: string,\n file: File | Blob,\n options?: { fileField?: string; fields?: UploadFields },\n ): Promise<UploadResponse> => {\n try {\n const formData = new FormData();\n formData.append(options?.fileField ?? 'files[]', file);\n if (options?.fields) {\n Object.entries(options.fields).forEach(([key, value]) => {\n formData.append(key, value);\n });\n }\n const response = await this.props.axiosApi.post<UploadResponse>(\n url,\n formData,\n { params: this.authParams() },\n );\n return response.data;\n } catch (error: any) {\n console.error('[' + url + ']', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/uploadVFS — sube una imagen al VFS de OpenCms. */\n uploadImageVFS = (\n file: File | Blob,\n fields?: UploadFields,\n ): Promise<UploadResponse> => this.upload('/images/uploadVFS', file, { fields });\n\n /** POST /images/uploadSERVER — sube una imagen desde el RFS al VFS. */\n uploadImageSERVER = (\n file: File | Blob,\n fields?: UploadFields,\n ): Promise<UploadResponse> =>\n this.upload('/images/uploadSERVER', file, { fields });\n\n /** POST /images/uploadAMZ — sube una imagen a Amazon S3 (+ Rekognition). */\n uploadImageAMZ = (\n file: File | Blob,\n fields?: UploadFields,\n ): Promise<UploadResponse> => this.upload('/images/uploadAMZ', file, { fields });\n\n /** POST /profile/image/uploadUserPicture — sube la foto de perfil del usuario. */\n uploadProfilePicture = (\n file: File | Blob,\n fields?: UploadFields,\n ): Promise<UploadResponse> =>\n this.upload('/profile/image/uploadUserPicture', file, { fields });\n\n /** POST /transcribe/uploadAMZ — sube un audio y lo encola para transcripcion. */\n uploadTranscribeAMZ = (\n file: File | Blob,\n fields?: UploadFields,\n ): Promise<UploadResponse> =>\n this.upload('/transcribe/uploadAMZ', file, { fields });\n\n /**\n * POST /videos/nativos/uploadS3 — sube el binario de video a S3.\n * El `videoPath` se obtiene previamente de `createVideoProcessing`.\n * El archivo se manda en el campo `item[0]` y el path en `videoPath`.\n */\n uploadVideoS3 = (\n file: File | Blob,\n videoPath: string,\n fields?: UploadFields,\n ): Promise<UploadResponse> =>\n this.upload('/videos/nativos/uploadS3', file, {\n fileField: 'item[0]',\n fields: { videoPath, ...(fields ?? {}) },\n });\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\n\n/** Vistas de preview HTML del CKEditor (endpoints GET que devuelven HTML). */\nexport type CkeditorPreviewView =\n | 'audios'\n | 'events'\n | 'image'\n | 'imageComparation'\n | 'polls'\n | 'recipes'\n | 'relatedNews'\n | 'trivias'\n | 'gallery';\n\n/** Parametros propios de una preview de CKEditor (ademas de la autenticacion). */\nexport interface CkeditorPreviewParams {\n /** Path(s) VFS del recurso (separador segun la vista: `;`, `-` o `|`). */\n path: string;\n divId?: string;\n isVideo?: string;\n showDescription?: string;\n isMobile?: string;\n /** Indice de slide inicial (gallery). */\n si?: string;\n playerType?: string;\n [key: string]: string | undefined;\n}\n\ninterface IPreviewServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Constructores de URL para los previews GET-HTML del CMS (para usar como\n * `src` de un `<iframe>`). NO hacen fetch: devuelven el string de la URL con\n * el `authToken` en Base64 y el resto de la autenticacion en query-params.\n *\n * La base se toma de `axiosApi.defaults.baseURL`. Los valores NO se\n * URL-encodean, replicando el comportamiento del consumidor existente.\n */\nexport class CmsPreviewServices {\n protected props: IPreviewServices;\n protected authentication: Authentication;\n\n constructor(props: IPreviewServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** Arma la URL completa (base + path + query) sin URL-encodear valores. */\n private buildUrl = (\n path: string,\n query: Record<string, string | number | undefined>,\n ): string => {\n const base = this.props.axiosApi.defaults.baseURL ?? '';\n const qs = Object.entries(query)\n .filter(([, value]) => value !== undefined && value !== null && value !== '')\n .map(([key, value]) => key + '=' + value)\n .join('&');\n return base + path + '?' + qs;\n };\n\n /**\n * GET /videos/edit/previewEmbedded — URL de preview del embed de un video\n * para mostrar en un `<iframe>`.\n */\n getVideoEmbeddedPreviewUrl = (path: string): string => {\n const { token, browserId, siteName, publication } = this.authentication;\n return this.buildUrl('/videos/edit/previewEmbedded', {\n browserID: browserId,\n authToken: btoa(token),\n siteName,\n publication,\n path,\n });\n };\n\n /**\n * GET /ckeditor/<view> — URL de preview HTML del CKEditor (events, image,\n * gallery, etc.) para mostrar en un `<iframe>`.\n */\n getCkeditorPreviewUrl = (\n view: CkeditorPreviewView,\n params: CkeditorPreviewParams,\n ): string => {\n const { token, browserId, siteName, publication } = this.authentication;\n return this.buildUrl('/ckeditor/' + view, {\n authToken: btoa(token),\n browserID: browserId,\n siteName,\n publication,\n ...params,\n });\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Audio del VFS. Los metadatos exactos no están detallados en el doc. */\nexport interface Audio {\n [key: string]: unknown;\n}\n\n/** Filtros de POST /audios/get. */\nexport interface AudiosGetFilters {\n /** ID de publicación; sobreescribe el de `authentication`. */\n publication?: string;\n /** Tipo de audio a filtrar. */\n type?: string;\n /** Agencia/fuente a filtrar. */\n agency?: string;\n /** Texto libre para búsqueda. */\n text?: string;\n /** Categoría a filtrar. */\n category?: string;\n /** Tags a filtrar. */\n tags?: string;\n /** Cantidad de resultados por página (default: 100). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Fecha desde en milisegundos (epoch) como String. */\n fromDate?: string;\n /** Fecha hasta en milisegundos (epoch) como String. */\n toDate?: string;\n /** Campo de orden (default: \"user-modification-date\"). */\n order?: string;\n /** Dirección del orden: \"asc\" o \"desc\". */\n position?: string;\n /** Si es \"summary\", devuelve items vacíos (sin campos extendidos). */\n fields?: string;\n}\n\n/** Cuerpo de la respuesta de POST /audios/get. */\nexport interface AudiosGetResponse extends CmsResponse {\n /** Listado de audios (clave inferida por convención del módulo). */\n audios?: Audio[];\n total?: number;\n page?: number;\n size?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /audios/adminConfiguration. */\nexport interface AudiosAdminConfigurationResponse extends CmsResponse {\n /** Ruta de categorías de audios configurada. */\n pathCategorias?: string;\n /** Si el upload a VFS está habilitado. */\n isVfsUploadEnabled?: boolean;\n /** Si el upload a RFS (servidor) está habilitado. */\n isRfsUploadEnabled?: boolean;\n /** Si el upload por FTP está habilitado. */\n isFtpUploadEnabled?: boolean;\n /** Si el upload a Amazon S3 está habilitado. */\n isAmzUploadEnabled?: boolean;\n /** Destino de upload por defecto. */\n defaultUploadDestination?: string;\n}\n\ninterface IAudiosServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `audios` del CMS (solo endpoints JSON POST).\n *\n * Los uploads multipart (uploadAMZ/FTP/SERVER/VFS) y los GET de ckeditor\n * (getGallery/getPlayer) no se incluyen por no seguir el patrón estándar.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsAudiosServices {\n protected props: IAudiosServices;\n protected authentication: Authentication;\n\n constructor(props: IAudiosServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /audios/get — listado paginado de audios del VFS, con filtros. */\n getAudios = async (\n filters: AudiosGetFilters = {},\n ): Promise<AudiosGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<AudiosGetResponse>(\n '/audios/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/audios/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /audios/adminConfiguration — configuración de administración de audios. */\n getAdminConfiguration =\n async (): Promise<AudiosAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<AudiosAdminConfigurationResponse>(\n '/audios/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/audios/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/**\n * Categoría del árbol de un módulo. En `categories/test` cada ítem incluye\n * además campos de debug `2_descripcion_N` (cubiertos por la index signature).\n */\nexport interface Category {\n /** Descripción jerarquizada de OpenCms. */\n descripcion?: string;\n /** Título a mostrar. */\n descripcionShow?: string;\n path?: string;\n visibility?: boolean;\n [key: string]: unknown;\n}\n\n/** Filtro de POST /categories/get. */\nexport interface CategoriesGetFilter {\n /**\n * Nombre lógico del módulo (ej: `newsTypes`, `trivias`, `recipes`,\n * `vod-video`, `videos`, `polls`) o path absoluto de categorías.\n */\n module: string;\n}\n\n/** Cuerpo de la respuesta de POST /categories/get. */\nexport interface CategoriesGetResponse extends CmsResponse {\n /** Path raíz de categorías resuelto. */\n basePath?: string;\n categories: Category[];\n}\n\n/** Filtro de POST /categories/refactor. Debe incluir `module` o `parent`. */\nexport interface CategoriesRefactorFilter {\n /** Nombre lógico del módulo para resolver el path raíz. */\n module?: string;\n /**\n * Path absoluto de categoría padre; se usa si no se provee `module` o si\n * `module` no contiene `/`.\n */\n parent?: string;\n}\n\n/** Cuerpo de la respuesta de POST /categories/refactor (hijos directos). */\nexport interface CategoriesRefactorResponse extends CmsResponse {\n categories: Category[];\n}\n\n/** Filtro de POST /categories/test. */\nexport interface CategoriesTestFilter {\n /** Nombre lógico del módulo (default: \"newsTypes\"). */\n module?: string;\n}\n\n/** Cuerpo de la respuesta de POST /categories/test (incluye campos de debug). */\nexport interface CategoriesTestResponse extends CmsResponse {\n categories: Category[];\n}\n\ninterface ICategoriesServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `categories` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsCategoriesServices {\n protected props: ICategoriesServices;\n protected authentication: Authentication;\n\n constructor(props: ICategoriesServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /categories/get — árbol completo (recursivo) de categorías de un módulo. */\n getCategories = async (\n filter: CategoriesGetFilter,\n ): Promise<CategoriesGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<CategoriesGetResponse>(\n '/categories/get',\n {\n authentication: this.authentication,\n filter,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/categories/get]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /categories/refactor — hijos directos (no recursivo) del path raíz.\n * Acepta `module` y/o `parent` (al menos uno).\n */\n refactorCategories = async (\n filter: CategoriesRefactorFilter = {},\n ): Promise<CategoriesRefactorResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CategoriesRefactorResponse>(\n '/categories/refactor',\n {\n authentication: this.authentication,\n filter,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/categories/refactor]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /categories/test — endpoint de diagnóstico (devuelve campos de debug).\n * No debe usarse en producción.\n */\n testCategories = async (\n filter: CategoriesTestFilter = {},\n ): Promise<CategoriesTestResponse> => {\n try {\n const response = await this.props.axiosApi.post<CategoriesTestResponse>(\n '/categories/test',\n {\n authentication: this.authentication,\n filter,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/categories/test]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Prompt de IA disponible en el menú inline del CKEditor. */\nexport interface CkeditorPrompt {\n ckeditorAssistance?: string;\n ckeditorRewrite?: string;\n name?: string;\n group?: string;\n niceName?: string;\n [key: string]: unknown;\n}\n\n/** Configuración de prompts de IA para el CKEditor. */\nexport interface CkeditorParams {\n AIEnabledCkeditor?: string;\n promptsAssistance?: string;\n prompts?: CkeditorPrompt[];\n /** Tonos disponibles, separados por coma (ej: \"alegre,critico,formal\"). */\n tonePrompt?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /ckeditor/adminConfiguration. */\nexport interface CkeditorAdminConfigurationResponse extends CmsResponse {\n ckeditorParams?: CkeditorParams;\n}\n\n/** Input de POST /ckeditor/assistanceAI (legacy). */\nexport interface CkeditorAssistanceAIInput {\n /** Texto seleccionado en el editor a procesar. */\n content: string;\n /** Tipo de prompt a aplicar (ej. \"pulirnotaCk\", \"translate\"). */\n typePrompt?: string;\n /** Opción adicional para el prompt (ej. idioma destino). */\n option?: string | null;\n /** Prompt personalizado a enviar al servicio de IA. */\n prompt?: string;\n}\n\n/** Input de POST /ckeditor/assistanceAINew. */\nexport interface CkeditorAssistanceAINewInput {\n /** Nombre del prompt en el catálogo (ej. \"pulirnotaCk\", \"translate\"). */\n typePrompt: string;\n /** Texto seleccionado a procesar (no puede estar vacío). */\n content: string;\n /** Parámetro opcional para el prompt (ej. idioma destino para \"translate\"). */\n option?: string;\n}\n\n/** Cuerpo de la respuesta de POST /ckeditor/assistanceAI y /assistanceAINew. */\nexport interface CkeditorAssistanceResponse extends CmsResponse {\n /** Texto procesado por la IA. */\n assistanceAI?: string;\n}\n\n/** Input de POST /ckeditor/audioCode. */\nexport interface CkeditorAudioCodeInput {\n /** Paths VFS de los recursos de audio a incluir. */\n audios: string[];\n /** \"true\" para generar una playlist, \"false\" para reproductor single. */\n insertList: string;\n}\n\n/**\n * Cuerpo de la respuesta de POST /ckeditor/audioCode.\n *\n * Nota: este endpoint devuelve `status` en mayúsculas (`\"OK\"`).\n */\nexport interface CkeditorAudioCodeResponse extends CmsResponse {\n /** HTML del reproductor listo para embeber. */\n galleryCode?: string;\n}\n\ninterface ICkeditorServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `ckeditor` del CMS (solo endpoints JSON POST).\n *\n * Los endpoints GET de previsualización HTML (events, image, gallery, etc.) e\n * `imageBase64.jsp` no se incluyen por no seguir el patrón estándar.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsCkeditorServices {\n protected props: ICkeditorServices;\n protected authentication: Authentication;\n\n constructor(props: ICkeditorServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /ckeditor/adminConfiguration — configuración de prompts de IA del CKEditor. */\n getAdminConfiguration =\n async (): Promise<CkeditorAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CkeditorAdminConfigurationResponse>(\n '/ckeditor/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/ckeditor/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /ckeditor/assistanceAI — asistencia de IA legacy (usar `assistanceAINew`). */\n assistanceAI = async (\n input: CkeditorAssistanceAIInput,\n ): Promise<CkeditorAssistanceResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CkeditorAssistanceResponse>(\n '/ckeditor/assistanceAI',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/ckeditor/assistanceAI]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /ckeditor/assistanceAINew — asistencia de IA (versión vigente). */\n assistanceAINew = async (\n input: CkeditorAssistanceAINewInput,\n ): Promise<CkeditorAssistanceResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CkeditorAssistanceResponse>(\n '/ckeditor/assistanceAINew',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/ckeditor/assistanceAINew]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /ckeditor/audioCode — HTML del reproductor de audio (single o playlist). */\n getAudioCode = async (\n input: CkeditorAudioCodeInput,\n ): Promise<CkeditorAudioCodeResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CkeditorAudioCodeResponse>(\n '/ckeditor/audioCode',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/ckeditor/audioCode]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/**\n * Estado de una oportunidad tal como lo entrega el microservicio (passthrough).\n * El único valor documentado hoy es `\"open\"`; se deja abierto para no romper\n * cuando el microservicio agregue estados nuevos.\n */\nexport type CopilotOpportunityStatus = 'open' | (string & {});\n\n/** Acción del editor sobre una oportunidad (POST /copilot/actions). */\nexport type CopilotAction = 'save' | 'like' | 'dislike' | 'assign';\n\n/** Filtros opcionales de POST /copilot/opportunities (passthrough al micro). */\nexport interface CopilotOpportunitiesFilters {\n /** Filtro de estado de las oportunidades (p. ej. \"open\"). */\n status?: CopilotOpportunityStatus;\n /** Cantidad máxima de oportunidades a devolver. */\n limit?: number;\n}\n\n/**\n * Fuente de la que el microservicio detectó la oportunidad. Valor observado en\n * dev hoy: `\"rss\"`. Se deja abierto (passthrough) para no romper cuando el micro\n * agregue fuentes nuevas.\n */\nexport type CopilotOpportunitySource =\n | 'rss'\n | 'gtrends'\n | 'sconsole'\n | 'x'\n | (string & {});\n\n/**\n * Oportunidad editorial del feed de Copilot.\n *\n * La doc del gateway lista `id`, `topic` y `created_at`, pero el microservicio\n * (observado en dev) puede omitirlos: solo `title`, `status` y `score` están\n * garantizados. El consumidor debe tolerar los faltantes. En dev (2026-07-06) el\n * micro también entrega `source`, `type`, `reasons` e `is_followed`.\n */\nexport interface CopilotOpportunity {\n id?: string;\n title: string;\n /** Descripción/resumen de la oportunidad (texto libre). */\n description?: string;\n /** Tema/categoría. */\n topic?: string;\n status: CopilotOpportunityStatus;\n /** Puntaje (el backend lo omite si es nulo). */\n score?: number;\n /** Fecha de creación (ISO 8601, p. ej. \"2026-06-26T10:15:00Z\"). */\n created_at?: string;\n /** Fuente detectada (p. ej. \"rss\"). Verificado en dev 2026-07-06. */\n source?: CopilotOpportunitySource;\n /** Subtipo de match del micro (p. ej. \"rss_match\"). */\n type?: string;\n /** Motivos por los que el micro la propuso (para tooltip/detalle). */\n reasons?: string[];\n /** Si el editor ya la siguió/guardó (acción \"save\" de `copilot/actions`). */\n is_followed?: boolean;\n /**\n * Señal de interés del editor sobre el tema (acciones like/dislike, NAA-4767):\n * `\"positive\"` (like) · `\"negative\"` (dislike) · `null`/ausente (sin señal). El\n * consumidor la usa para dejar el botón de me gusta/no me gusta ya marcado al\n * cargar el feed.\n */\n interest_signal?: string | null;\n /**\n * Redactor asignado (acción \"assign\"). Si viene con valor, la oportunidad está\n * asignada (el consumidor la muestra en estado \"Asignado\"). El micro NO\n * garantiza la forma (se observó que puede no ser string: id numérico, objeto o\n * lista): el consumidor debe evaluar solo si viene \"lleno\", sin asumir el tipo.\n */\n assigned_to?: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /copilot/opportunities.\n *\n * Si la publicación no tiene `KUNDERA_SITE_UUID` (Copilot desactivado) el CMS\n * responde `status:\"ok\"` con `copilotEnabled:false` y lista vacía: NO es un\n * error, el gestor decide qué mostrar.\n */\nexport interface CopilotOpportunitiesResponse extends CmsResponse {\n copilotEnabled?: boolean;\n /** UUID del sitio en Kundera (solo si `copilotEnabled = true`). */\n site_uuid?: string;\n count?: number;\n opportunities?: CopilotOpportunity[];\n}\n\n/** Datos según la acción ejecutada (el backend lo omite si está vacío). */\nexport interface CopilotActionData {\n /** Acción `save` (bookmark, toggle). */\n is_followed?: boolean;\n /** Acciones `like` / `dislike`. */\n interest_signal?: string;\n /** Acción `assign`. */\n assigned_to?: string;\n}\n\n/** Entrada de POST /copilot/actions. */\nexport interface CopilotActionInput {\n action: CopilotAction;\n /** ID de la oportunidad sobre la que se acciona. */\n opportunityId: string;\n /**\n * ID opaco y estable del redactor a asignar (NO el username).\n * Obligatorio solo para `action = \"assign\"` (error 030.005 si falta).\n */\n userExternalId?: string;\n}\n\n/** Cuerpo de la respuesta de POST /copilot/actions. */\nexport interface CopilotActionResponse extends CmsResponse {\n copilotEnabled?: boolean;\n action?: CopilotAction;\n opportunity_id?: string;\n /** Código de resultado devuelto por el microservicio (omitido si es nulo). */\n code?: string;\n data?: CopilotActionData;\n}\n\n/**\n * Cuerpo de la respuesta de POST /copilot/snooze (NAA-4645). El \"recordar luego\"\n * de la campanita: la oportunidad se oculta para ese usuario y reaparece sola al\n * vencer el plazo configurado.\n */\nexport interface CopilotSnoozeResponse extends CmsResponse {\n copilotEnabled?: boolean;\n opportunity_id?: string;\n /** Momento hasta el cual la oportunidad queda oculta (ISO 8601 o epoch). */\n snoozed_until?: string | number;\n}\n\ninterface ICopilotServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `copilot` del CMS (gateway hacia el microservicio\n * Copilot/Kundera). Errores propios en la serie `030.x` (ver `commonErrors`).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsCopilotServices {\n protected props: ICopilotServices;\n protected authentication: Authentication;\n\n constructor(props: ICopilotServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /copilot/opportunities — feed de oportunidades (permiso COPILOT_VIEW). */\n getOpportunities = async (\n filters: CopilotOpportunitiesFilters = {},\n ): Promise<CopilotOpportunitiesResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CopilotOpportunitiesResponse>(\n '/copilot/opportunities',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/copilot/opportunities]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /copilot/actions — ejecuta una acción del editor sobre una\n * oportunidad: `save` | `like` | `dislike` | `assign` (permiso COPILOT_ACTION).\n */\n executeAction = async (\n input: CopilotActionInput,\n ): Promise<CopilotActionResponse> => {\n try {\n const response = await this.props.axiosApi.post<CopilotActionResponse>(\n '/copilot/actions',\n {\n authentication: this.authentication,\n action: input.action,\n opportunity_id: input.opportunityId,\n ...(input.userExternalId !== undefined && {\n user_external_id: input.userExternalId,\n }),\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/copilot/actions]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /copilot/snooze — \"recordar luego\" de una oportunidad de la campanita\n * (permiso COPILOT_VIEW). La oportunidad desaparece de la campanita para el\n * usuario y reaparece sola al vencer el plazo configurado.\n * @param opportunityId - Id de la oportunidad a posponer.\n */\n snooze = async (opportunityId: string): Promise<CopilotSnoozeResponse> => {\n try {\n const response = await this.props.axiosApi.post<CopilotSnoozeResponse>(\n '/copilot/snooze',\n {\n authentication: this.authentication,\n opportunity_id: opportunityId,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/copilot/snooze]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Comentario del CMS. La forma exacta no está documentada. */\nexport interface Comment {\n commentId?: string;\n [key: string]: unknown;\n}\n\n/** Filtros de POST /comments/get. */\nexport interface CommentsGetFilters {\n /** ID de un comentario puntual a obtener. */\n commentId?: string;\n /** Cantidad máxima de resultados. */\n size?: number;\n /** Ruta del recurso al que pertenecen los comentarios. */\n resource?: string;\n /** Identificador del autor del comentario. */\n performer?: string;\n /** ID del comentario padre (para respuestas). */\n parentId?: string;\n /** Filtrar por comentarios destacados (1 = destacado). */\n featured?: number;\n /** Paginación: último ID recibido en la página anterior. */\n lastCommentId?: string;\n /** Estado(s) del comentario, separados por coma (ej: \"1,2\"). */\n status?: string;\n /** Fecha de inicio como timestamp Unix en milisegundos. */\n from?: string;\n /** Fecha de fin como timestamp Unix en milisegundos. */\n to?: string;\n /** Mínimo de reportes para filtrar. */\n numberReport?: string;\n /** Motivo de rechazo por el que filtrar (clave tal cual la espera el back). */\n rejectiontReason?: string;\n /** Texto libre para buscar en el contenido del comentario. */\n text?: string;\n}\n\n/** Cuerpo de la respuesta de POST /comments/get. */\nexport interface CommentsGetResponse extends CmsResponse {\n /** Lista de comentarios cuando no se filtra por `commentId`. */\n comments?: Comment[];\n /** Comentario único cuando se filtra por `commentId`. */\n comment?: Comment;\n [key: string]: unknown;\n}\n\n/**\n * Input de moderación de comentarios (approve / delete). Debe incluir\n * `commentId` o `commentIds`.\n */\nexport interface CommentModerationInput {\n commentId?: string;\n commentIds?: string[];\n}\n\n/** Input de POST /comments/reject. */\nexport interface CommentRejectInput extends CommentModerationInput {\n /** Motivo del rechazo. */\n reason?: string;\n}\n\n/** Input de POST /comments/highlight. */\nexport interface CommentHighlightInput extends CommentModerationInput {\n /** \"true\" para destacar, cualquier otro valor para quitar destaque. */\n highlight?: string;\n}\n\n/** Formato de URL amigable por tipo de noticia. */\nexport interface CommentUrlFriendly {\n newsType?: string;\n UrlFriendlyFormat?: string;\n UrlFriendlyRegExp?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /comments/adminConfiguration. */\nexport interface CommentsAdminConfigurationResponse extends CmsResponse {\n urlFriendlys?: CommentUrlFriendly[];\n}\n\n/** Clasificación de una palabra del diccionario de filtros. */\nexport type DictionaryWordType = 'moderadas' | 'prohibidas';\n\n/** Input de POST /comments/dictionary/add. */\nexport interface DictionaryAddInput {\n word: string;\n type: DictionaryWordType;\n}\n\n/** Input de POST /comments/dictionary/changeType. */\nexport interface DictionaryChangeTypeInput {\n word: string;\n type: DictionaryWordType;\n}\n\n/** Filtros de POST /comments/dictionary/get. */\nexport interface DictionaryGetFilters {\n /** Cantidad máxima de palabras a retornar. */\n size?: number;\n /** Paginación: última palabra recibida. */\n lastWord?: string;\n /** Texto para filtrar palabras por contenido. */\n filter?: string;\n /** Tipo de palabra. */\n type?: DictionaryWordType;\n}\n\n/** Palabra del diccionario de filtros. */\nexport interface DictionaryWord {\n type?: string;\n word?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /comments/dictionary/get. */\nexport interface DictionaryGetResponse extends CmsResponse {\n words: DictionaryWord[];\n}\n\n/** Evento de moderación del historial de un comentario. */\nexport interface CommentEvent {\n commentId?: string;\n eventId?: string;\n date?: string;\n performer?: string;\n description?: string;\n type?: string;\n /** Datos del usuario (Cognito o interno) que realizó la acción. */\n userData?: unknown;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /comments/events/get. */\nexport interface CommentEventsGetResponse extends CmsResponse {\n comments: CommentEvent[];\n}\n\n/** Motivo de reporte de un comentario. */\nexport interface CommentReason {\n id?: number;\n description?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /comments/reasons/get. */\nexport interface CommentReasonsGetResponse extends CmsResponse {\n /** Lista raw del servicio. */\n reasonsDB?: unknown[];\n /** Lista formateada desde DB. */\n reasonsJSON?: unknown[];\n /** Lista hardcodeada de motivos canónicos (ids 0-6). */\n reasons?: CommentReason[];\n}\n\n/** Cuerpo de la respuesta de POST /comments/reasons/prueba. */\nexport interface CommentReasonsTestResponse extends CmsResponse {\n reasons: CommentReason[];\n}\n\n/** Cuerpo de la respuesta de POST /comments/user/get. */\nexport interface CommentUserGetResponse extends CmsResponse {\n username?: string;\n lastname?: string;\n nickname?: string;\n picture?: string;\n email?: string;\n phonenumber?: string;\n}\n\ninterface ICommentsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `comments` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsCommentsServices {\n protected props: ICommentsServices;\n protected authentication: Authentication;\n\n constructor(props: ICommentsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /comments/get — obtiene un comentario o lista comentarios filtrados. */\n getComments = async (\n filters: CommentsGetFilters = {},\n ): Promise<CommentsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<CommentsGetResponse>(\n '/comments/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/approve — aprueba uno o varios comentarios. */\n approveComments = async (\n filters: CommentModerationInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/approve',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/approve]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/reject — rechaza uno o varios comentarios, con motivo opcional. */\n rejectComments = async (\n filters: CommentRejectInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/reject',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/reject]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/delete — elimina uno o varios comentarios. */\n deleteComments = async (\n filters: CommentModerationInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/delete',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/highlight — marca o desmarca comentarios como destacados. */\n highlightComments = async (\n filters: CommentHighlightInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/highlight',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/highlight]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/adminConfiguration — tipos de noticias y formatos de URL amigable. */\n getAdminConfiguration =\n async (): Promise<CommentsAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CommentsAdminConfigurationResponse>(\n '/comments/adminConfiguration',\n {\n authentication: this.authentication,\n filters: {},\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/dictionary/add — agrega una palabra al diccionario de filtros. */\n addDictionaryWord = async (\n filters: DictionaryAddInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/dictionary/add',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/dictionary/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/dictionary/changeType — cambia el tipo de una palabra del diccionario. */\n changeDictionaryWordType = async (\n filters: DictionaryChangeTypeInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/dictionary/changeType',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/dictionary/changeType]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/dictionary/delete — elimina una palabra del diccionario. */\n deleteDictionaryWord = async (word: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/dictionary/delete',\n {\n authentication: this.authentication,\n filters: { word },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/dictionary/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/dictionary/get — lista paginada de palabras del diccionario. */\n getDictionary = async (\n filters: DictionaryGetFilters = {},\n ): Promise<DictionaryGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<DictionaryGetResponse>(\n '/comments/dictionary/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/dictionary/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/events/get — historial de eventos de un comentario. */\n getCommentEvents = async (\n commentId: string,\n ): Promise<CommentEventsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<CommentEventsGetResponse>(\n '/comments/events/get',\n {\n authentication: this.authentication,\n filters: { commentId },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/events/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/reasons/get — motivos de reporte (DB + hardcodeados). */\n getReasons = async (): Promise<CommentReasonsGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CommentReasonsGetResponse>(\n '/comments/reasons/get',\n {\n authentication: this.authentication,\n filters: {},\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/reasons/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/reasons/prueba — solo la lista hardcodeada de motivos de reporte. */\n getReasonsTest = async (): Promise<CommentReasonsTestResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<CommentReasonsTestResponse>(\n '/comments/reasons/prueba',\n {\n authentication: this.authentication,\n filters: {},\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/reasons/prueba]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/user/disable — deshabilita un usuario de Cognito. */\n disableUser = async (username: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/user/disable',\n {\n authentication: this.authentication,\n filters: { username },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/user/disable]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/user/enable — habilita un usuario de Cognito. */\n enableUser = async (username: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/comments/user/enable',\n {\n authentication: this.authentication,\n filters: { username },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/user/enable]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /comments/user/get — datos de un usuario de Cognito por username. */\n getUser = async (username: string): Promise<CommentUserGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<CommentUserGetResponse>(\n '/comments/user/get',\n {\n authentication: this.authentication,\n filters: { username },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/comments/user/get]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Filtros de los endpoints de definiciones de contribuciones. */\nexport interface ContributionsGetFilters {\n /** Filtra por estado de la contribución. */\n state?: string;\n /** Filtra por tipo de contribución. */\n type?: string;\n}\n\n/** Filtros de POST /contributions/getSuscriptions. */\nexport interface SubscriptionsGetFilters {\n /** Filtra por estado de la suscripción. */\n state?: string;\n /** Filtra por tipo de suscripción. */\n type?: string;\n}\n\n/** Filtros de POST /contributions/paymentGateways/get. */\nexport interface PaymentGatewaysGetFilters {\n /** Filtra por tipo de pasarela de pago. */\n type?: string;\n /** Filtra por ID de pasarela de pago. */\n id?: string;\n}\n\n/**\n * Contribución a actualizar (POST /contributions/edit).\n *\n * Su `id` se usa para construir la URL del recurso externo.\n */\nexport interface ContributionEditInput {\n id: string;\n [key: string]: unknown;\n}\n\n/**\n * Respuesta de las definiciones de contribuciones. El cuerpo es un proxy de\n * la API externa, por lo que su forma exacta no está documentada.\n */\nexport interface ContributionsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Respuesta de POST /contributions/edit (proxy de la API externa). */\nexport interface ContributionEditResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Respuesta de POST /contributions/getSuscriptions (proxy de la API externa). */\nexport interface SubscriptionsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Respuesta de POST /contributions/contribuciones/insertCrm (proxy de la API externa). */\nexport interface ContributionsInsertCrmResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Respuesta de POST /contributions/paymentGateways/get (proxy de la API externa). */\nexport interface PaymentGatewaysGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\ninterface IContributionsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `contributions` del CMS.\n *\n * Todos los endpoints actúan como proxy hacia una API externa (AWS API\n * Gateway). Se construye igual que `CmsCommonServices`, con\n * `{ axiosApi, authentication }`.\n */\nexport class CmsContributionsServices {\n protected props: IContributionsServices;\n protected authentication: Authentication;\n\n constructor(props: IContributionsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /contributions/get — definiciones de contribuciones, filtradas. */\n getContributions = async (\n filters: ContributionsGetFilters = {},\n ): Promise<ContributionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ContributionsGetResponse>(\n '/contributions/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /contributions/edit — actualiza una definición de contribución. */\n editContribution = async (\n contribution: ContributionEditInput,\n ): Promise<ContributionEditResponse> => {\n try {\n const response = await this.props.axiosApi.post<ContributionEditResponse>(\n '/contributions/edit',\n {\n authentication: this.authentication,\n contribution,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/edit]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /contributions/getDefinitions — definiciones de contribuciones.\n * Funcionalmente equivalente a `getContributions`.\n */\n getDefinitions = async (\n filters: ContributionsGetFilters = {},\n ): Promise<ContributionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ContributionsGetResponse>(\n '/contributions/getDefinitions',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/getDefinitions]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /contributions/getSuscriptions — suscripciones, filtradas. */\n getSubscriptions = async (\n filters: SubscriptionsGetFilters = {},\n ): Promise<SubscriptionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<SubscriptionsGetResponse>(\n '/contributions/getSuscriptions',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/getSuscriptions]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /contributions/contribuciones/get — definiciones de contribuciones.\n * Funcionalmente equivalente a `getContributions`.\n */\n getContribuciones = async (\n filters: ContributionsGetFilters = {},\n ): Promise<ContributionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ContributionsGetResponse>(\n '/contributions/contribuciones/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/contribuciones/get]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /contributions/contribuciones/insertCrm — inserta un lead de prueba\n * en Zoho CRM. Los filtros se usan en la llamada previa a la API de\n * contribuciones.\n */\n insertCrm = async (\n filters: ContributionsGetFilters = {},\n ): Promise<ContributionsInsertCrmResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ContributionsInsertCrmResponse>(\n '/contributions/contribuciones/insertCrm',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/contribuciones/insertCrm]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /contributions/paymentGateways/get — pasarelas de pago, filtradas. */\n getPaymentGateways = async (\n filters: PaymentGatewaysGetFilters = {},\n ): Promise<PaymentGatewaysGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PaymentGatewaysGetResponse>(\n '/contributions/paymentGateways/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/contributions/paymentGateways/get]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Sección de una publicación del CMS (forma devuelta por get/exist). */\nexport interface Section {\n id?: number;\n name?: string;\n description?: string;\n page?: string;\n order?: number;\n publication?: number;\n visibility?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Payload `section` de POST /sections/add y POST /sections/update.\n *\n * En alta `idSection` es 0 y `new` es `true`; en edición `idSection` es el ID\n * existente y `new` normalmente `false`.\n */\nexport interface SectionInput {\n /** ID de la sección (0 para nueva). */\n idSection: number;\n /** ID de la publicación/tipo de edición (se usa para validar permiso). */\n idTipoEdicion: number;\n /** Nombre de la sección. */\n name: string;\n /** Descripción de la sección. */\n description: string;\n /** Página asociada. */\n page: string;\n /** Orden de la sección. */\n order: number;\n /** Indica si es nueva. */\n new: boolean;\n /** Cuenta de Facebook. */\n facebookAccount?: string;\n /** Cuenta de página de Facebook. */\n facebookPageAccount?: string;\n /** Cuenta de Twitter. */\n twitterAccount?: string;\n}\n\n/** Payload `section` de POST /sections/delete. */\nexport interface SectionDeleteInput {\n /** ID de la sección a eliminar. */\n idSection: number;\n /** ID de la publicación (usado para verificar permiso). */\n idTipoEdicion: number;\n}\n\n/** Cuerpo de la respuesta de POST /sections/get y POST /sections/exist. */\nexport interface SectionsGetResponse extends CmsResponse {\n sections: Section[];\n}\n\ninterface ISectionsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `sections` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsSectionsServices {\n protected props: ISectionsServices;\n protected authentication: Authentication;\n\n constructor(props: ISectionsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /sections/add — crea una nueva sección para una publicación. */\n addSection = async (section: SectionInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/sections/add',\n {\n authentication: this.authentication,\n section,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/sections/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /sections/delete — elimina una sección por `idSection`. */\n deleteSection = async (\n section: SectionDeleteInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/sections/delete',\n {\n authentication: this.authentication,\n section,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/sections/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /sections/get — lista de secciones de la publicación (opcional por visibilidad). */\n getSections = async (\n visibility?: boolean,\n ): Promise<SectionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<SectionsGetResponse>(\n '/sections/get',\n {\n authentication: this.authentication,\n visibility,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/sections/get]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /sections/exist — lista de secciones de la publicación.\n *\n * Idéntico a `getSections` (mismo código en el back); se expone por paridad\n * con el endpoint documentado.\n */\n existSections = async (\n visibility?: boolean,\n ): Promise<SectionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<SectionsGetResponse>(\n '/sections/exist',\n {\n authentication: this.authentication,\n visibility,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/sections/exist]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /sections/update — actualiza los datos de una sección existente. */\n updateSection = async (section: SectionInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/sections/update',\n {\n authentication: this.authentication,\n section,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/sections/update]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Tipo de plan de productividad. */\nexport type ProductivityPlanType = 'group' | 'rol' | 'general' | (string & {});\n\n/** Plan de productividad. La forma exacta depende del recurso y del formato pedido. */\nexport interface ProductivityPlan {\n [key: string]: unknown;\n}\n\n/** Usuario asignado a un plan (`content.users`). */\nexport interface ProductivityPlanUser {\n userName: string;\n /** Día de inicio del usuario en el plan (timestamp). */\n startDay?: number;\n}\n\n/** Rol asignado a un plan (`content.rols`). */\nexport interface ProductivityPlanRol {\n userName: string;\n}\n\n/**\n * Datos del plan a guardar (`content` de POST /productivityPlan/edit/save).\n *\n * `users` es requerido si `type` es \"group\" o \"general\"; `rols` si es \"rol\".\n */\nexport interface ProductivityPlanSaveContent {\n type: ProductivityPlanType;\n /** Usuarios asignados (requerido para \"group\"/\"general\"). */\n users?: ProductivityPlanUser[];\n /** Roles asignados (requerido para \"rol\"). */\n rols?: ProductivityPlanRol[];\n [key: string]: unknown;\n}\n\n/**\n * Excepción de un plan de productividad (POST /exceptions/create y /edit).\n *\n * `id` es requerido solo al editar.\n */\nexport interface ProductivityPlanException {\n /** ID de la excepción (requerido al editar). */\n id?: number;\n /** ID del plan al que aplica. */\n planId: string;\n /** Usuario afectado (usar \"_ALL\" para todos). */\n user: string;\n /** Inicio del período (timestamp en ms). */\n from: number;\n /** Fin del período (timestamp en ms). */\n to: number;\n /** Cantidad de noticias que se exceptúan. */\n news: number;\n /** ID del motivo de la excepción. */\n reasonId?: number;\n comments?: string;\n /** Si la excepción está activa (default: false). */\n enabled?: boolean;\n}\n\n/**\n * Motivo de excepción (POST /exceptions/reasons/create y /update).\n *\n * `id` es requerido solo al actualizar.\n */\nexport interface ProductivityPlanExceptionReason {\n /** ID del motivo (requerido al actualizar). */\n id?: number;\n description: string;\n enabled?: boolean;\n /** Sitio al que aplica (0 para todos). */\n siteName?: string;\n /** Publicación a la que aplica (0 para todas). */\n publication?: number;\n}\n\n/** Filtros de POST /productivityPlan/get. */\nexport interface ProductivityPlansGetFilters {\n /** Filtro por título del plan (LIKE). */\n text?: string;\n /** Filtro por tipo de plan (\"group\", \"rol\", \"general\"). */\n type?: ProductivityPlanType;\n /** Nombres de rol para filtrar planes asignados a esos roles. */\n rol?: string[];\n /** Usuario para filtrar planes asignados a él. */\n user?: string;\n}\n\n/**\n * Filtros de los reportes de frecuencia y métricas\n * (POST /reports/frequencyReports y /reports/metrics).\n *\n * `from`/`to` van en epoch en **segundos** (se ajustan por GMT de redacción).\n */\nexport interface ProductivityPlanFrequencyFilters {\n user: string;\n from: number;\n to: number;\n}\n\n/** Filtros de POST /productivityPlan/reports/complianceDetail. */\nexport interface ProductivityPlanComplianceDetailFilters {\n /** ID del plan de productividad. */\n path: string;\n}\n\n/** Filtros de POST /productivityPlan/exceptions/get. */\nexport interface ProductivityPlanExceptionsGetFilters {\n planId?: string;\n /** Desde esta fecha (timestamp en ms). */\n from?: number;\n /** Hasta esta fecha (timestamp en ms). */\n to?: number;\n /** Filtra por ID de excepción. */\n id?: number;\n /** Filtra solo las activas si es `true`. */\n enabled?: boolean;\n}\n\n/** Filtros de POST /productivityPlan/exceptions/reasons/get. */\nexport interface ProductivityPlanExceptionReasonsGetFilters {\n /** Filtra por usuario creador. */\n userCreation?: string;\n /** Filtra por ID de motivo. */\n id?: number;\n /** Filtra solo activos si es `true`. */\n enabled?: boolean;\n /** Columna y dirección de orden (default: \"DESCRIPTION DESC\"). */\n order?: string;\n}\n\n/**\n * Input de POST /productivityPlan/reports/compliance (campos en la raíz).\n *\n * `from`/`to` en epoch **milisegundos**.\n */\nexport interface ProductivityPlanComplianceInput {\n /** ID del plan de productividad. */\n path: string;\n userName: string;\n from: number;\n to: number;\n}\n\n/**\n * Input de POST /productivityPlan/reports/complianceBackup.\n *\n * Igual que compliance pero `from`/`to` son opcionales (requeridos si el plan\n * es diario).\n */\nexport interface ProductivityPlanComplianceBackupInput {\n path: string;\n userName: string;\n from?: number;\n to?: number;\n}\n\n/** Input de POST /productivityPlan/reports/v2/compliance. */\nexport interface ProductivityPlanComplianceV2Input\n extends ProductivityPlanComplianceInput {\n /** Número de períodos buscados (para calcular el total de notas esperadas). */\n searchedPeriods: number;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/create. */\nexport interface ProductivityPlanCreateResponse extends CmsResponse {\n /** Nombre del archivo de plan creado en el VFS. */\n fileName?: string;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/get. */\nexport interface ProductivityPlansGetResponse extends CmsResponse {\n /** Listado de planes con su estado de cumplimiento, asignados y stats. */\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/read. */\nexport interface ProductivityPlanReadResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/review. */\nexport interface ProductivityPlanReviewResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/edit/adminConfiguration. */\nexport interface ProductivityPlanAdminConfigurationResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/rolsPlans/get. */\nexport interface ProductivityPlanRolsPlansGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /productivityPlan/usersPlans/get y /getInPlan.\n */\nexport interface ProductivityPlanUsersPlansGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /productivityPlan/reports/compliance\n * y /reports/complianceBackup.\n */\nexport interface ProductivityPlanComplianceResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/reports/complianceDetail. */\nexport interface ProductivityPlanComplianceDetailResponse extends CmsResponse {\n /** Ítems del detalle diario del usuario. */\n data?: unknown[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/reports/frequencyReports. */\nexport interface ProductivityPlanFrequencyReportsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/reports/metrics. */\nexport interface ProductivityPlanMetricsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Resumen de cumplimiento de POST /reports/v2/compliance (`data`). */\nexport interface ProductivityPlanComplianceV2Data {\n amountToPublish?: number;\n publishedNews?: number;\n validCount?: number;\n validContentCount?: number;\n validFrecuencyCount?: number;\n /** Estado del resumen (\"ok\"/\"error\"). */\n status?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/reports/v2/compliance. */\nexport interface ProductivityPlanComplianceV2Response extends CmsResponse {\n data?: ProductivityPlanComplianceV2Data;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/exceptions/create. */\nexport interface ProductivityPlanExceptionCreateResponse extends CmsResponse {\n /** ID de la excepción creada. */\n id?: number;\n /** Objeto de la excepción creada. */\n exception?: ProductivityPlanException;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/exceptions/get. */\nexport interface ProductivityPlanExceptionsGetResponse extends CmsResponse {\n exceptions?: unknown[];\n /** Total de excepciones encontradas. */\n size?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/exceptions/reasons/create. */\nexport interface ProductivityPlanExceptionReasonCreateResponse\n extends CmsResponse {\n /** ID del motivo creado. */\n id?: number;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/exceptions/reasons/get. */\nexport interface ProductivityPlanExceptionReasonsGetResponse\n extends CmsResponse {\n exceptions?: unknown[];\n /** Total de motivos encontrados. */\n size?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/exceptions/reasons/update. */\nexport interface ProductivityPlanExceptionReasonUpdateResponse\n extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /productivityPlan/reviewr/detail. */\nexport interface ProductivityPlanReviewrDetailResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\ninterface IProductivityPlanServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `productivityPlan` del CMS (core + edit +\n * rolsPlans + usersPlans + unpublish + reports + exceptions + reviewr).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsProductivityPlanServices {\n protected props: IProductivityPlanServices;\n protected authentication: Authentication;\n\n constructor(props: IProductivityPlanServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /**\n * POST /productivityPlan/create — crea un plan vacío y devuelve su `fileName`.\n *\n * El back arma el plan desde el `jsonRequest` completo; los campos opcionales\n * del plan se pasan en `data` y se serializan en la raíz del body.\n */\n createPlan = async (\n data: Record<string, unknown> = {},\n ): Promise<ProductivityPlanCreateResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanCreateResponse>(\n '/productivityPlan/create',\n {\n authentication: this.authentication,\n ...data,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/get — lista de planes con filtros opcionales. */\n getPlans = async (\n filters: ProductivityPlansGetFilters = {},\n ): Promise<ProductivityPlansGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlansGetResponse>(\n '/productivityPlan/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/read — definición completa de un plan por su path. */\n readPlan = async (path: string): Promise<ProductivityPlanReadResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanReadResponse>(\n '/productivityPlan/read',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/review — cumplimiento por usuario del período anterior. */\n reviewPlan = async (\n path: string,\n type: ProductivityPlanType,\n ): Promise<ProductivityPlanReviewResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanReviewResponse>(\n '/productivityPlan/review',\n {\n authentication: this.authentication,\n path,\n type,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/review]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/edit/save — crea o actualiza un plan. */\n savePlan = async (\n path: string,\n content: ProductivityPlanSaveContent,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/edit/save',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/edit/changeStatus — alterna habilitado/deshabilitado. */\n changeStatus = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/edit/changeStatus',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/edit/changeStatus]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/edit/adminConfiguration — XSD y estados de un recurso VFS. */\n getAdminConfiguration = async (\n path: string,\n ): Promise<ProductivityPlanAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanAdminConfigurationResponse>(\n '/productivityPlan/edit/adminConfiguration',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/edit/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/rolsPlans/get — roles del sistema con su plan asignado. */\n getRolsPlans = async (): Promise<ProductivityPlanRolsPlansGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanRolsPlansGetResponse>(\n '/productivityPlan/rolsPlans/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/rolsPlans/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/rolsPlans/moveToPlan — asigna un rol a un plan. */\n moveRolToPlan = async (\n url: string,\n rolName: string,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/rolsPlans/moveToPlan',\n {\n authentication: this.authentication,\n url,\n rolName,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/rolsPlans/moveToPlan]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/usersPlans/get — usuarios de la publicación con su plan. */\n getUsersPlans = async (): Promise<ProductivityPlanUsersPlansGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanUsersPlansGetResponse>(\n '/productivityPlan/usersPlans/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/usersPlans/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/usersPlans/getInPlan — usuarios asignados a un plan. */\n getUsersInPlan = async (\n planId: string,\n ): Promise<ProductivityPlanUsersPlansGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanUsersPlansGetResponse>(\n '/productivityPlan/usersPlans/getInPlan',\n {\n authentication: this.authentication,\n planId,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/usersPlans/getInPlan]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/usersPlans/moveToPlan — asigna un usuario a un plan. */\n moveUserToPlan = async (\n url: string,\n userName: string,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/usersPlans/moveToPlan',\n {\n authentication: this.authentication,\n url,\n userName,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/usersPlans/moveToPlan]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/unpublish/delete — elimina un plan y sus asignados. */\n deletePlan = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/unpublish/delete',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/unpublish/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reports/compliance — cumplimiento de un usuario en un rango. */\n getComplianceReport = async (\n input: ProductivityPlanComplianceInput,\n ): Promise<ProductivityPlanComplianceResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanComplianceResponse>(\n '/productivityPlan/reports/compliance',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reports/compliance]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reports/complianceBackup — cumplimiento sin excepciones. */\n getComplianceBackupReport = async (\n input: ProductivityPlanComplianceBackupInput,\n ): Promise<ProductivityPlanComplianceResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanComplianceResponse>(\n '/productivityPlan/reports/complianceBackup',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reports/complianceBackup]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reports/complianceDetail — detalle diario de producción. */\n getComplianceDetail = async (\n path: string,\n ): Promise<ProductivityPlanComplianceDetailResponse> => {\n try {\n const filters: ProductivityPlanComplianceDetailFilters = { path };\n const response =\n await this.props.axiosApi.post<ProductivityPlanComplianceDetailResponse>(\n '/productivityPlan/reports/complianceDetail',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reports/complianceDetail]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reports/frequencyReports — frecuencia de publicación. */\n getFrequencyReports = async (\n filters: ProductivityPlanFrequencyFilters,\n ): Promise<ProductivityPlanFrequencyReportsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanFrequencyReportsResponse>(\n '/productivityPlan/reports/frequencyReports',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reports/frequencyReports]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reports/metrics — métricas de producción diaria. */\n getMetrics = async (\n filters: ProductivityPlanFrequencyFilters,\n ): Promise<ProductivityPlanMetricsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanMetricsResponse>(\n '/productivityPlan/reports/metrics',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reports/metrics]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reports/v2/compliance — reporte de cumplimiento v2. */\n getComplianceReportV2 = async (\n input: ProductivityPlanComplianceV2Input,\n ): Promise<ProductivityPlanComplianceV2Response> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanComplianceV2Response>(\n '/productivityPlan/reports/v2/compliance',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reports/v2/compliance]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/create — crea una excepción y devuelve su `id`. */\n createException = async (\n exception: ProductivityPlanException,\n ): Promise<ProductivityPlanExceptionCreateResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanExceptionCreateResponse>(\n '/productivityPlan/exceptions/create',\n {\n authentication: this.authentication,\n exception,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/delete — desactiva una excepción por su ID. */\n deleteException = async (id: number): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/exceptions/delete',\n {\n authentication: this.authentication,\n id,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/edit — actualiza una excepción existente. */\n editException = async (\n exception: ProductivityPlanException,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/exceptions/edit',\n {\n authentication: this.authentication,\n exception,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/edit]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/get — lista excepciones con filtros. */\n getExceptions = async (\n filters: ProductivityPlanExceptionsGetFilters = {},\n ): Promise<ProductivityPlanExceptionsGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanExceptionsGetResponse>(\n '/productivityPlan/exceptions/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/reasons/create — crea un motivo y devuelve su `id`. */\n createExceptionReason = async (\n exceptionReason: ProductivityPlanExceptionReason,\n ): Promise<ProductivityPlanExceptionReasonCreateResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanExceptionReasonCreateResponse>(\n '/productivityPlan/exceptions/reasons/create',\n {\n authentication: this.authentication,\n exceptionReason,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/reasons/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/reasons/delete — elimina un motivo por su ID. */\n deleteExceptionReason = async (id: number): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/productivityPlan/exceptions/reasons/delete',\n {\n authentication: this.authentication,\n id,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/reasons/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/reasons/get — lista motivos con filtros. */\n getExceptionReasons = async (\n filters: ProductivityPlanExceptionReasonsGetFilters = {},\n ): Promise<ProductivityPlanExceptionReasonsGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanExceptionReasonsGetResponse>(\n '/productivityPlan/exceptions/reasons/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/reasons/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/exceptions/reasons/update — actualiza un motivo existente. */\n updateExceptionReason = async (\n exceptionReason: ProductivityPlanExceptionReason,\n ): Promise<ProductivityPlanExceptionReasonUpdateResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanExceptionReasonUpdateResponse>(\n '/productivityPlan/exceptions/reasons/update',\n {\n authentication: this.authentication,\n exceptionReason,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/exceptions/reasons/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /productivityPlan/reviewr/detail — cumplimiento del período anterior por usuario. */\n getReviewrDetail = async (\n path: string,\n type: ProductivityPlanType,\n ): Promise<ProductivityPlanReviewrDetailResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ProductivityPlanReviewrDetailResponse>(\n '/productivityPlan/reviewr/detail',\n {\n authentication: this.authentication,\n path,\n type,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/productivityPlan/reviewr/detail]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Filtros de POST /events/get. */\nexport interface EventsGetFilters {\n /** Publicación a filtrar; si se omite usa la de `authentication`. */\n publication?: string;\n /** Categoría del evento. */\n category?: string;\n /** Lugar del evento. */\n place?: string;\n /** Texto de búsqueda avanzada (full-text). */\n text?: string;\n /** Personas asociadas al evento. */\n people?: string;\n /** Tags del evento. */\n tags?: string;\n /** Cantidad de resultados por página (default: 100). */\n size?: number;\n /** Página de resultados (default: 1). */\n page?: number;\n /** Inicio del rango de eventos (epoch ms); default: fecha actual. */\n fromDate?: string;\n /** Fin del rango de eventos (epoch ms); default: un mes atrás. */\n toDate?: string;\n /** Inicio del rango de última modificación (epoch ms). */\n fromDateModificacion?: string;\n /** Fin del rango de última modificación (epoch ms). */\n toDateModificacion?: string;\n /** Campo de ordenamiento (default: \"user-modification-date\"). */\n order?: string;\n /** Dirección de ordenamiento (default: \" desc \"). */\n position?: string;\n}\n\n/** Evento del CMS. La forma exacta depende del recurso. */\nexport interface CmsEvent {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /events/get. */\nexport interface EventsGetResponse extends CmsResponse {\n /** Colección de eventos que cumplen los filtros. */\n events: CmsEvent[];\n total?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /events/create. */\nexport interface EventCreateResponse extends CmsResponse {\n /** Path del archivo de evento creado. */\n fileName?: string;\n}\n\ninterface IEventsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `events` (eventos) del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsEventsServices {\n protected props: IEventsServices;\n protected authentication: Authentication;\n\n constructor(props: IEventsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /events/create — crea un evento vacío y devuelve su `fileName`. */\n createEvent = async (): Promise<EventCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<EventCreateResponse>(\n '/events/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/events/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /events/get — lista paginada de eventos con filtros (Lucene). */\n getEvents = async (\n filters: EventsGetFilters = {},\n ): Promise<EventsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<EventsGetResponse>(\n '/events/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/events/get]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Archivo del VFS devuelto por POST /fileExplorer/getFiles. */\nexport interface ExplorerFile {\n path?: string;\n name?: string;\n title?: string;\n /** Tipo de recurso (ej. \"image\", \"plain\"). */\n type?: string;\n /** Fecha de última modificación (ej. \"10/06/2024 03:45\"). */\n dateLastModified?: string;\n [key: string]: unknown;\n}\n\n/** Carpeta del VFS devuelta por POST /fileExplorer/getFolders. */\nexport interface ExplorerFolder {\n path?: string;\n name?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /fileExplorer/getFiles. */\nexport interface FileExplorerGetFilesResponse extends CmsResponse {\n /** Archivos (no carpetas) contenidos en la carpeta consultada. */\n files: ExplorerFile[];\n}\n\n/** Cuerpo de la respuesta de POST /fileExplorer/getFolders. */\nexport interface FileExplorerGetFoldersResponse extends CmsResponse {\n /** Subcarpetas directas de la carpeta consultada. */\n folders: ExplorerFolder[];\n}\n\ninterface IFileExplorerServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `fileExplorer` del CMS que usan POST con body JSON\n * y objeto `authentication`.\n *\n * Quedan fuera (multipart/form-data, token Base64 por query-param):\n * `fileExplorer/uploadAMZ`, `fileExplorer/uploadSERVER` y\n * `fileExplorer/uploadVFS`.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsFileExplorerServices {\n protected props: IFileExplorerServices;\n protected authentication: Authentication;\n\n constructor(props: IFileExplorerServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /fileExplorer/getFiles — archivos de una carpeta del VFS. */\n getFiles = async (path: string): Promise<FileExplorerGetFilesResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<FileExplorerGetFilesResponse>(\n '/fileExplorer/getFiles',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/fileExplorer/getFiles]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /fileExplorer/getFolders — subcarpetas directas de una carpeta del VFS. */\n getFolders = async (\n path: string,\n ): Promise<FileExplorerGetFoldersResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<FileExplorerGetFoldersResponse>(\n '/fileExplorer/getFolders',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/fileExplorer/getFolders]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\ninterface IGeneralServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP de la raíz del módulo `general` del CMS que usan POST con body\n * JSON y objeto `authentication`.\n *\n * Queda fuera `adminConfiguration` (GET, sin autenticación ni body).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsGeneralServices {\n protected props: IGeneralServices;\n protected authentication: Authentication;\n\n constructor(props: IGeneralServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /updateCDN — refresca la URL de CDN de un recurso VFS. */\n updateCDN = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/updateCDN',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/updateCDN]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Si `\"all\"`, POST /images/get retorna todos los campos del item. */\nexport type ImagesFieldsFormat = 'all' | (string & {});\n\n/** Método de upload al crear versión/crop en POST /images/edit/save. */\nexport type ImageUploadMethod = 'server' | 'vfs' | 'ftp' | 'amz' | (string & {});\n\n/** Acción a validar en POST /images/unpublish/check (permiso dinámico). */\nexport type ImageUnpublishCheckAction =\n | 'unlock'\n | 'unpublish'\n | 'delete'\n | (string & {});\n\n/** Filtros de POST /images/get. */\nexport interface ImagesGetFilters {\n /** Path exacto de la imagen; si se envía, retorna esa imagen directamente. */\n imagePath?: string;\n /** Alias legacy de `imagePath`. */\n pathImagen?: string;\n /** Texto libre para búsqueda full-text. */\n text?: string;\n /** Filtro por categoría. */\n category?: string;\n /** Filtro por autor. */\n author?: string;\n /** Filtro por agencia. */\n agency?: string;\n /** Índice de búsqueda a usar. */\n searchindex?: string;\n /** Filtrar imágenes usadas en noticias. */\n onnews?: string;\n /** Incluir imágenes recortadas (default: false). */\n includeCropped?: boolean;\n /** Buscar también en el historial. */\n searchinhistory?: boolean;\n /** Filtrar por path de imagen original. */\n originalImage?: string;\n /** Filtrar por keywords/tags. */\n tags?: string;\n /** Cantidad de resultados por página (default: 24). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Fecha de inicio (epoch ms). */\n from?: string;\n /** Fecha de fin (epoch ms). */\n to?: string;\n /** Ordenamiento por fecha de modificación: \"asc\" o \"desc\" (default: \"desc\"). */\n order?: 'asc' | 'desc' | (string & {});\n /** Filtro avanzado en sintaxis Lucene. */\n advancedFilter?: string;\n /** Calidad: `+` alta, `-` baja. */\n quality?: string;\n /** Si true, solo imágenes con etiquetas unsafe; si false, solo sin ellas. */\n unsafe?: boolean;\n /** Filtra imágenes sin descripción o sin título. */\n noDescription?: boolean;\n /** Si `\"all\"`, retorna todos los campos del item. */\n fields?: ImagesFieldsFormat;\n}\n\n/** Imagen del CMS. Los campos presentes dependen del formato pedido. */\nexport interface Image {\n path?: string;\n title?: string;\n description?: string;\n author?: string;\n agency?: string;\n [key: string]: unknown;\n}\n\n/** Punto focal de una imagen (`{ fpx, fpy }`). */\nexport interface ImageFocalPoint {\n fpx: number | string;\n fpy: number | string;\n}\n\n/** Metadatos a guardar en POST /images/edit/save (`content`). */\nexport interface ImageSaveContent {\n /** Título de la imagen (propiedad `Title`). */\n title?: string;\n /** Descripción (propiedad `Description`); no puede estar vacía. */\n description: string;\n /** Keywords/etiquetas (propiedad `Keywords`). */\n tags?: string;\n /** Agencia fotográfica (propiedad `Agency`). */\n agency?: string;\n /** Autor (propiedad `Author`). */\n author?: string;\n /** Categorías; se guardan pipe-separated (propiedad `category`). */\n category?: string[];\n /** Punto focal (propiedad `image.focalPoint`). */\n focalPoint?: ImageFocalPoint;\n /** Sección para determinar carpeta de upload en flujo de versión. */\n section?: string;\n /** Método de upload al crear versión (requerido en flujo versión). */\n method?: ImageUploadMethod;\n /** Coordenada top del crop (flujo versión). */\n top?: number;\n /** Coordenada left del crop (flujo versión). */\n left?: number;\n /** Ancho del crop (flujo versión). */\n width?: number;\n /** Alto del crop (flujo versión). */\n height?: number;\n /** Keywords en flujo de versión. */\n keywords?: string;\n [key: string]: unknown;\n}\n\n/** Opciones de POST /images/edit/save (crear nueva o versión/crop). */\nexport interface ImageSaveOptions {\n /** Si true, crea una imagen nueva con timestamp en el nombre. */\n isNew?: boolean;\n /** Si true, guarda como versión/crop de la imagen original. */\n isVersion?: boolean;\n}\n\n/** Payload de POST /images/edit/inline (`image`). */\nexport interface ImageInlineInput {\n /** Ruta VFS de la imagen a editar. */\n path: string;\n /** Descripción/título a guardar (se sanitiza contra JS). */\n description: string;\n}\n\n/** Ítem de imagen para POST /images/ckeditor/getGallery (`image`). */\nexport interface ImageGalleryItem {\n /** Ruta VFS de la imagen. */\n path: string;\n /** Descripción de la imagen. */\n description: string;\n /** Título de la imagen. */\n title: string;\n}\n\n/** Cuerpo de la respuesta de POST /images/get. */\nexport interface ImagesGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/read (metadatos completos + lock). */\nexport interface ImageReadResponse extends CmsResponse {\n /** Datos del lock si el recurso está bloqueado por otro usuario. */\n isLockData?: { [key: string]: unknown };\n /** Datos de programación si el lock es por proyecto temporal. */\n isScheduleData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/adminConfiguration. */\nexport interface ImagesAdminConfigurationResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/publish/check. */\nexport interface ImagesPublishCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/unlock/check. */\nexport interface ImageUnlockCheckResponse extends CmsResponse {\n isLockData?: { [key: string]: unknown };\n isScheduleData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/unlock/valid. */\nexport interface ImageUnlockValidResponse extends CmsResponse {\n isLockData?: { [key: string]: unknown };\n isScheduleData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/unpublish/check. */\nexport interface ImageUnpublishCheckResponse extends CmsResponse {\n /** Tipo de bloqueo (`999.014` programación / `999.010` otro usuario). */\n typeCode?: string;\n isLockData?: { [key: string]: unknown };\n isScheduleData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/unpublish/now. */\nexport interface ImageUnpublishNowResponse extends CmsResponse {\n /** Resultado de la operación de expiración. */\n unpublish?: unknown;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/edit/setFocalPoint. */\nexport interface ImageSetFocalPointResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /images/ckeditor/getGallery. */\nexport interface ImageGalleryResponse extends CmsResponse {\n /** HTML de la galería generada. */\n code?: string;\n [key: string]: unknown;\n}\n\n/** Ítem de imagen para POST /images/ckeditor/getImageComparation (`image`). */\nexport interface ImageComparationItem {\n /** Ruta VFS de la imagen. */\n path: string;\n /** Descripción de la imagen. */\n description: string;\n /** Título de la imagen. */\n title: string;\n}\n\n/** Par de imágenes (exactamente 2) a comparar en `getImageComparation`. */\nexport type ImageComparationPair = [ImageComparationItem, ImageComparationItem];\n\n/** Cuerpo de la respuesta de POST /images/ckeditor/getImageComparation. */\nexport interface ImageComparationResponse extends CmsResponse {\n /** Código de la galería de comparación generada. */\n galleryCode?: string;\n [key: string]: unknown;\n}\n\ninterface IImagesServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `images` del CMS (core + publish, unlock,\n * unpublish, edit y ckeditor) que usan POST con body JSON y objeto\n * `authentication`.\n *\n * Quedan fuera (autenticación por query-param / multipart): `images/scale`,\n * `images/uploadVFS`, `images/uploadSERVER`, `images/uploadAMZ`,\n * `images/edit/saveAndSERVER`, `images/edit/saveAndUploadAMZ` y\n * `images/edit/uploadVFS`.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsImagesServices {\n protected props: IImagesServices;\n protected authentication: Authentication;\n\n constructor(props: IImagesServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /images/get — busca imágenes por path exacto o filtros indexados. */\n getImages = async (\n filters: ImagesGetFilters = {},\n ): Promise<ImagesGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ImagesGetResponse>(\n '/images/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/read — lee metadatos completos de una imagen y la bloquea. */\n read = async (path: string): Promise<ImageReadResponse> => {\n try {\n const response = await this.props.axiosApi.post<ImageReadResponse>(\n '/images/read',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/adminConfiguration — configuración del módulo de imágenes. */\n getAdminConfiguration =\n async (): Promise<ImagesAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ImagesAdminConfigurationResponse>(\n '/images/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/publish/check — verifica si las imágenes pueden publicarse. */\n publishCheck = async (\n images: string[],\n ): Promise<ImagesPublishCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ImagesPublishCheckResponse>(\n '/images/publish/check',\n {\n authentication: this.authentication,\n images,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/publish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/publish/now — publica efectivamente las imágenes indicadas. */\n publishNow = async (images: string[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/publish/now',\n {\n authentication: this.authentication,\n images,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/publish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/unlock/check — verifica el estado de lock y relaciones. */\n unlockCheck = async (path: string): Promise<ImageUnlockCheckResponse> => {\n try {\n const response = await this.props.axiosApi.post<ImageUnlockCheckResponse>(\n '/images/unlock/check',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unlock/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/unlock/now — transfiere el lock de la imagen al usuario actual. */\n unlockNow = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/unlock/now',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unlock/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/unlock/remove — quita completamente el lock de una imagen. */\n unlockRemove = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/unlock/remove',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unlock/remove]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/unlock/valid — valida el estado de lock de una imagen. */\n unlockValid = async (path: string): Promise<ImageUnlockValidResponse> => {\n try {\n const response = await this.props.axiosApi.post<ImageUnlockValidResponse>(\n '/images/unlock/valid',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unlock/valid]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /images/unpublish/check — verifica lock y relaciones antes de operar.\n *\n * El permiso requerido depende de `action`: `unlock` (default) / `unpublish`\n * / `delete`.\n */\n unpublishCheck = async (\n path: string,\n action?: ImageUnpublishCheckAction,\n ): Promise<ImageUnpublishCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ImageUnpublishCheckResponse>(\n '/images/unpublish/check',\n {\n authentication: this.authentication,\n path,\n action,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unpublish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/unpublish/now — despublica (expira) una imagen y publica el cambio. */\n unpublishNow = async (path: string): Promise<ImageUnpublishNowResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ImageUnpublishNowResponse>(\n '/images/unpublish/now',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unpublish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/unpublish/delete — elimina del VFS una imagen en estado NEW. */\n unpublishDelete = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/unpublish/delete',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/unpublish/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/edit/discardDraft — descarta el draft de una imagen. */\n discardDraft = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/edit/discardDraft',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/edit/discardDraft]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/edit/inline — guarda inline la descripción/título en el VFS. */\n editInline = async (image: ImageInlineInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/edit/inline',\n {\n authentication: this.authentication,\n image,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/edit/inline]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/edit/removelock — fuerza el desbloqueo de un recurso de imagen. */\n editRemoveLock = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/edit/removelock',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/edit/removelock]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /images/edit/save — guarda los metadatos VFS de una imagen.\n *\n * Con `isNew` o `isVersion` delega en el flujo de crop/versión.\n */\n save = async (\n imagePath: string,\n content: ImageSaveContent,\n options: ImageSaveOptions = {},\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/images/edit/save',\n {\n authentication: this.authentication,\n imagePath,\n content,\n ...options,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/edit/setFocalPoint — establece el punto focal de una imagen. */\n setFocalPoint = async (\n path: string,\n ): Promise<ImageSetFocalPointResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ImageSetFocalPointResponse>(\n '/images/edit/setFocalPoint',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/edit/setFocalPoint]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/ckeditor/getGallery — genera el HTML de una galería para CKEditor. */\n getGallery = async (\n image: ImageGalleryItem[],\n ): Promise<ImageGalleryResponse> => {\n try {\n const response = await this.props.axiosApi.post<ImageGalleryResponse>(\n '/images/ckeditor/getGallery',\n {\n authentication: this.authentication,\n image,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/ckeditor/getGallery]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /images/ckeditor/getImageComparation — genera el código de comparación de 2 imágenes para CKEditor. */\n getImageComparation = async (\n image: ImageComparationPair,\n ): Promise<ImageComparationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<ImageComparationResponse>(\n '/images/ckeditor/getImageComparation',\n {\n authentication: this.authentication,\n image,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/images/ckeditor/getImageComparation]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Acción de IA soportada por POST /news/translate. */\nexport type NewsTranslateAction =\n | 'translate'\n | 'rewrite'\n | 'rewriteAndTranslate';\n\n/** Ítem de noticia con solo ruta (sub-objeto `news.new`). */\nexport interface NewsPathItem {\n /** Ruta VFS de la noticia. */\n path: string;\n}\n\n/** Ítem de noticia a copiar (POST /news/copy). */\nexport interface NewsCopyItem {\n /** Ruta VFS de la noticia a copiar. */\n path: string;\n /** ID de publicación destino. */\n publication: string;\n}\n\n/** Ítem de noticia a publicar (POST /news/publish/now y /schedule). */\nexport interface NewsPublishItem {\n /** Ruta VFS de la noticia. */\n path: string;\n /** Si `true` y hay una sola noticia, actualiza el resumen antes de publicar. */\n update?: boolean;\n /** Resumen IA a guardar (requiere `update: true`). */\n resumen?: string;\n}\n\n/** Opciones de fecha para POST /news/publish/now y /schedule. */\nexport interface NewsPublishOptions {\n /** Si `true`, aplica la fecha de publicación al campo `ultimaModificacion`. */\n setLastModification?: boolean;\n /** Fecha a usar como última modificación / publicación programada. */\n publishDate?: string;\n}\n\n/** Ítem de noticia con cambios para POST /news/massive/edit. */\nexport interface NewsMassiveEditItem {\n /** Ruta VFS de la noticia. */\n path: string;\n [key: string]: unknown;\n}\n\n/** Parámetros de POST /news/read_page (paginación de un campo XML). */\nexport interface NewsReadPageInput {\n /** Ruta VFS de la noticia. */\n path: string;\n /** Nombre del campo XML a paginar. */\n field: string;\n /** Tamaño de página. */\n page_size: number;\n /** Número de página (base 1). */\n page: number;\n /** Ordenamiento del campo. */\n order: string;\n}\n\n/** Parámetros de POST /news/translate. */\nexport interface NewsTranslateInput {\n /** Acción: `translate`, `rewrite` o `rewriteAndTranslate`. */\n action: NewsTranslateAction;\n /** Ruta VFS de la noticia origen. */\n path: string;\n /** Prompt adicional para la reescritura (puede ir vacío para translate puro). */\n prompt: string;\n /** ID de publicación destino (puede ser igual a `publication`). */\n pubDestId: string;\n /** Código de idioma destino (aplica solo si `pubDestId == publication`). */\n lang: string;\n}\n\n/** Query de elementos para POST /news/relatedNewsElementsQuery. */\nexport interface NewsRelatedElementsQuery {\n /** Debe estar presente para ejecutar la consulta. */\n tipoContenido: unknown;\n /** Tipo de contenido/noticia. */\n newsType: string;\n /** Nombre de la publicación. */\n publicationName: string;\n}\n\n/** Datos de frescura para POST /news/freshness/create (`detail.freshness`). */\nexport interface NewsFreshness {\n /** Fecha de la frescura (epoch ms). */\n date?: string;\n /** Descripción de la actualización. */\n description?: string;\n [key: string]: unknown;\n}\n\n/** Filtros de POST /news/freshness/get. */\nexport interface NewsFreshnessGetFilters {\n /** Timestamp (ms) de inicio del rango de fecha. */\n fromDate?: number;\n /** Timestamp (ms) de fin del rango de fecha. */\n toDate?: number;\n /** Username del creador de la noticia. */\n newscreator?: string;\n /** Sección a filtrar. */\n section?: string;\n /** `\"true\"` para incluir historial. */\n history?: string;\n}\n\n/** Filtros de POST /news/analytics/getWhitFilters. */\nexport interface NewsAnalyticsFilters {\n /** Ruta VFS de una sola noticia (modo single). */\n pathNote?: string;\n /** Campos XML a retornar (solo con `pathNote`). */\n fields?: unknown[];\n /** URL de una vista configurada para cargar sus filtros. */\n url?: string;\n /** Texto de búsqueda libre. */\n text?: string;\n /** Sección a filtrar. */\n section?: string;\n /** Categoría. */\n category?: string;\n /** Autor. */\n author?: string;\n /** Tipo de noticia. */\n newstype?: string;\n /** Usuario creador. */\n newscreator?: string;\n /** Filtro de portada (home/section). */\n onmainpage?: string;\n /** Zona. */\n zone?: string;\n /** Tags. */\n tags?: string;\n /** Grupo. */\n group?: string;\n /** Incluir temporales. */\n showtemporal?: boolean;\n /** Buscar en historial. */\n searchinhistory?: boolean;\n /** Cantidad máxima de resultados (default 100, máx 100). */\n size?: number;\n /** Número de página (default 1). */\n page?: number;\n /** Campo de ordenamiento (default: \"modification-date\"). */\n orderValue?: string;\n /** Dirección de orden (default: \"desc\"). */\n position?: string;\n /** Página de portada (\"1\" = home). */\n idPage?: string;\n /** Path relativo a excluir del resultado. */\n excludePath?: string;\n}\n\n/** Cuerpo de la respuesta de POST /news/create. */\nexport interface NewsCreateResponse extends CmsResponse {\n /** Ruta del recurso creado. */\n fileName?: string;\n}\n\n/** Cuerpo de la respuesta de POST /news/export (formato tabular). */\nexport interface NewsExportResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/previewFormats. */\nexport interface NewsPreviewFormatsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/read (contenido XML + metadata). */\nexport interface NewsReadResponse extends CmsResponse {\n /** Contenido XML de la noticia. */\n content?: { [key: string]: unknown };\n /** Datos del lock si el recurso está bloqueado por otro usuario. */\n isLockData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/read_page. */\nexport interface NewsReadPageResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/types (configuración de creación). */\nexport interface NewsTypesResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/relatedNewsElementsQuery. */\nexport interface NewsRelatedElementsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/publish/check (validación por noticia). */\nexport interface NewsPublishCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/publish/AISummaryGenerate. */\nexport interface NewsAISummaryResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/unpublish/check. */\nexport interface NewsUnpublishCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/pin/add. */\nexport interface NewsPinAddResponse extends CmsResponse {\n /** ID del pin creado. */\n id?: number;\n}\n\n/** Cuerpo de la respuesta de POST /news/pin/get (noticias pineadas). */\nexport interface NewsPinsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/massive/check. */\nexport interface NewsMassiveCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/freshness/get. */\nexport interface NewsFreshnessGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/views/get. */\nexport interface NewsViewsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/analytics/get y /getWhitFilters. */\nexport interface NewsAnalyticsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Ítem de edición inline para POST /news/edit/inline (`news.new`). */\nexport interface NewsEditInlineItem {\n /** Ruta VFS de la noticia. */\n path: string;\n /** Título de la noticia. */\n title: string;\n /** Zona en home. */\n zoneHome: string;\n /** Prioridad de la zona en home. */\n zoneHomePriority: string;\n /** Zona en la sección. */\n zoneSection: string;\n /** Prioridad de la zona en la sección. */\n zoneSectionPriority: string;\n /** Si oculta publicidad (\"true\"/\"false\" como string). */\n hideAds: string;\n /** Fecha de última modificación. */\n lastModifDate: string;\n}\n\n/** Ítem para ocultar/mostrar banner en POST /news/edit/hideBanner (`news.new`). */\nexport interface NewsHideBannerItem {\n /** Ruta VFS de la noticia. */\n path: string;\n /** Si oculta la publicidad/banner (\"true\"/\"false\" como string). */\n hideAds: string;\n}\n\n/** Filtros de POST /news/refactor/get (todos opcionales). */\nexport interface NewsRefactorFilters {\n /** Lista de noticias a refactorizar (cada una con su ruta). */\n newsList?: NewsPathItem[];\n /** Ruta VFS de una sola noticia. */\n pathNote?: string;\n /** Campos XML a retornar. */\n fields?: string[];\n /** URL de una vista configurada. */\n url?: string;\n /** Texto de búsqueda libre. */\n text?: string;\n /** Sección a filtrar. */\n section?: string;\n /** Estado de la noticia. */\n state?: string;\n /** Tipo de noticia. */\n newstype?: string;\n /** Usuario creador. */\n newscreator?: string;\n /** Autor. */\n author?: string;\n /** Categoría. */\n category?: string;\n /** Tags. */\n tags?: string;\n /** Filtro de portada (home/section). */\n onmainpage?: string;\n /** Grupo. */\n group?: string;\n /** Zona. */\n zone?: string;\n /** Página de portada. */\n idPage?: string;\n /** Incluir temporales. */\n showtemporal?: boolean;\n /** Buscar en historial. */\n searchinhistory?: boolean;\n /** Cantidad máxima de resultados. */\n size?: number;\n /** Número de página. */\n page?: number;\n /** Timestamp (ms) de inicio del rango de fecha. */\n from?: string;\n /** Timestamp (ms) de fin del rango de fecha. */\n to?: string;\n /** Campo de ordenamiento. */\n orderValue?: string;\n /** Dirección de orden. */\n position?: string;\n /** Path relativo a excluir del resultado. */\n excludePath?: string;\n}\n\n/** Parámetros de POST /news/IA/newsCheck (uno de `path` o `nota`). */\nexport interface NewsCheckInput {\n /** Ruta VFS de la noticia a chequear. */\n path?: string;\n /** Nota provista directamente (forma libre). */\n nota?: { [key: string]: unknown };\n}\n\n/** Contenido opcional para POST /news/IAcreate/create. */\nexport interface NewsIaCreateContent {\n /** Título sugerido. */\n titulo?: string;\n /** Subtítulo/copete sugerido. */\n subtitulo?: string;\n /** Cuerpo de la noticia. */\n cuerpo?: string;\n /** Resumen de la noticia. */\n resumen?: string;\n /** Sección destino. */\n seccion?: string;\n /** Lista de noticias asociadas. */\n noticiaLista?: unknown[];\n [key: string]: unknown;\n}\n\n/** Parámetros de POST /news/IAcreate/preview (todos opcionales). */\nexport interface NewsIaPreviewInput {\n /** Tipo de noticia a generar. */\n newsType?: string;\n /** ID de conversación de IA. */\n chatId?: string;\n /** Prompt del modelo. */\n modelPrompt?: string;\n /** IDs de archivos adjuntos. */\n fileIds?: string[];\n /** Idioma del prompt. */\n languagePrompt?: string;\n /** Tono del prompt. */\n tonePrompt?: string;\n /** Prompt adicional. */\n additionalPrompt?: string;\n /** Prompt de longitud/párrafos. */\n paragraphPrompt?: string;\n /** Perfil del redactor para listicle. */\n profileWriterListiclePrompt?: string;\n /** Punto de vista para listicle. */\n viewpointListiclePrompt?: string;\n /** Prompt de transcripción. */\n transcribePrompt?: string;\n /** Tipo de transcripción. */\n transcribeTypePrompt?: string;\n /** Cantidad de items del listicle. */\n cantItemsListiclePrompt?: string;\n /** Item del listicle. */\n itemListiclePrompt?: string;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/save. */\nexport interface NewsEditSaveResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/analizeNews. */\nexport interface NewsAnalizeResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/analizeNewsAI. */\nexport interface NewsAnalizeAIResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/SummaryNewsIA. */\nexport interface NewsSummaryIAResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/adminNewsConfiguration. */\nexport interface NewsAdminConfigurationResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/fieldsDefault. */\nexport interface NewsFieldsDefaultResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/edit/authorConfiguration. */\nexport interface NewsAuthorConfigurationResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/versions/get. */\nexport interface NewsVersionsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/versions/recovery. */\nexport interface NewsVersionRecoveryResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/refactor/get. */\nexport interface NewsRefactorGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/IA/newsCheck. */\nexport interface NewsCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/IAcreate/create. */\nexport interface NewsIaCreateResponse extends CmsResponse {\n /** Ruta del recurso creado. */\n fileName?: string;\n}\n\n/** Cuerpo de la respuesta de POST /news/IAcreate/preview. */\nexport interface NewsIaPreviewResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /news/searchConsole/inspection. */\nexport interface NewsSearchConsoleInspectionResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\ninterface INewsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `news` del CMS (core + publish, unpublish, pin,\n * massive, freshness, views y analytics).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsNewsServices {\n protected props: INewsServices;\n protected authentication: Authentication;\n\n constructor(props: INewsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /news/available — libera fechas de release/expiración y desbloquea. */\n available = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/available',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/available]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/copy — copia una o más noticias a otra publicación. */\n copy = async (items: NewsCopyItem[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/copy',\n {\n authentication: this.authentication,\n news: { new: items },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/copy]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/create — crea una noticia y devuelve su `fileName`. */\n create = async (newsType?: string): Promise<NewsCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsCreateResponse>(\n '/news/create',\n {\n authentication: this.authentication,\n newsType,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/export — exporta los campos XML de noticias en formato tabular. */\n exportNews = async (paths: string[]): Promise<NewsExportResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<NewsExportResponse>(\n '/news/export',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/export]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/previewFormats — formatos de preview de la publicación. */\n getPreviewFormats = async (): Promise<NewsPreviewFormatsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsPreviewFormatsResponse>(\n '/news/previewFormats',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/previewFormats]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/read — lee contenido XML y metadata, y bloquea la noticia. */\n read = async (\n path: string,\n pagination?: unknown[],\n ): Promise<NewsReadResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsReadResponse>(\n '/news/read',\n {\n authentication: this.authentication,\n path,\n pagination,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/read_page — lee un campo XML paginado por página y tamaño. */\n readPage = async (input: NewsReadPageInput): Promise<NewsReadPageResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsReadPageResponse>(\n '/news/read_page',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/read_page]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/removelock — quita el lock (cancela programación si la hay). */\n removeLock = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/removelock',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/removelock]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/unlock — desbloquea la noticia (idéntico a removelock). */\n unlock = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/unlock',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/unlock]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/translate — traduce y/o reescribe una noticia mediante IA. */\n translate = async (input: NewsTranslateInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/translate',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/translate]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/types — configuración inicial para el flujo de creación de nota. */\n getTypes = async (): Promise<NewsTypesResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsTypesResponse>(\n '/news/types',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/types]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/relatedNewsElementsQuery — elementos para queries de relacionadas. */\n relatedNewsElementsQuery = async (\n news: NewsRelatedElementsQuery,\n ): Promise<NewsRelatedElementsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsRelatedElementsResponse>(\n '/news/relatedNewsElementsQuery',\n {\n authentication: this.authentication,\n news,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/relatedNewsElementsQuery]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/publish/check — verifica si las noticias pueden publicarse. */\n publishCheck = async (\n paths: string[],\n ): Promise<NewsPublishCheckResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<NewsPublishCheckResponse>(\n '/news/publish/check',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/publish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/publish/now — publica inmediatamente una o más noticias. */\n publishNow = async (\n items: NewsPublishItem[],\n options: NewsPublishOptions = {},\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/publish/now',\n {\n authentication: this.authentication,\n news: { new: items, ...options },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/publish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/publish/schedule — programa la publicación en fecha futura. */\n publishSchedule = async (\n items: NewsPublishItem[],\n options: NewsPublishOptions = {},\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/publish/schedule',\n {\n authentication: this.authentication,\n news: { new: items, ...options },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/publish/schedule]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/publish/massive — publica masivamente múltiples noticias. */\n publishMassive = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/publish/massive',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/publish/massive]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/publish/AISummaryGenerate — genera el resumen IA de una noticia. */\n generateAISummary = async (\n paths: string[],\n saveInNews?: boolean,\n ): Promise<NewsAISummaryResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<NewsAISummaryResponse>(\n '/news/publish/AISummaryGenerate',\n {\n authentication: this.authentication,\n news: { new: newItems },\n saveInNews,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/publish/AISummaryGenerate]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/unpublish/check — verifica si una noticia puede despublicarse. */\n unpublishCheck = async (\n path: string,\n noteOwner?: boolean,\n ): Promise<NewsUnpublishCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsUnpublishCheckResponse>(\n '/news/unpublish/check',\n {\n authentication: this.authentication,\n path,\n noteOwner,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/unpublish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/unpublish/now — despublica (expira) los recursos indicados. */\n unpublishNow = async (resources: string[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/unpublish/now',\n {\n authentication: this.authentication,\n resources,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/unpublish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/unpublish/delete — elimina una o más noticias del VFS. */\n unpublishDelete = async (\n resources: string[],\n noteOwner?: boolean,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/unpublish/delete',\n {\n authentication: this.authentication,\n resources,\n noteOwner,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/unpublish/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/unpublish/expired — expira noticias limpiando sus zonas XML. */\n unpublishExpired = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/unpublish/expired',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/unpublish/expired]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/pin/add — agrega noticias a los pines del usuario actual. */\n addPins = async (paths: string[]): Promise<NewsPinAddResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<NewsPinAddResponse>(\n '/news/pin/add',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/pin/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/pin/delete — elimina uno o más pines por su ID. */\n deletePins = async (ids: number[]): Promise<CmsResponse> => {\n try {\n const pin = ids.map((id) => ({ id }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/pin/delete',\n {\n authentication: this.authentication,\n pines: { pin },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/pin/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/pin/get — noticias pineadas por el usuario para la publicación. */\n getPins = async (): Promise<NewsPinsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsPinsGetResponse>(\n '/news/pin/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/pin/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/massive/check — verifica noticias para publicación/guardado masivo. */\n massiveCheck = async (\n paths: string[],\n isPublish: boolean,\n ): Promise<NewsMassiveCheckResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<NewsMassiveCheckResponse>(\n '/news/massive/check',\n {\n authentication: this.authentication,\n news: { new: newItems, isPublish },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/massive/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/massive/edit — guarda cambios masivos en múltiples noticias. */\n massiveEdit = async (items: NewsMassiveEditItem[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/massive/edit',\n {\n authentication: this.authentication,\n news: { new: items },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/massive/edit]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/freshness/create — crea o actualiza la frescura de una noticia. */\n createFreshness = async (\n path: string,\n freshness: NewsFreshness,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/freshness/create',\n {\n authentication: this.authentication,\n path,\n detail: { freshness },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/freshness/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/freshness/delete — elimina la frescura de una noticia. */\n deleteFreshness = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/freshness/delete',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/freshness/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/freshness/get — noticias con frescura activa, con filtros. */\n getFreshness = async (\n filters: NewsFreshnessGetFilters = {},\n ): Promise<NewsFreshnessGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsFreshnessGetResponse>(\n '/news/freshness/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/freshness/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/views/get — vistas de noticias configuradas para la publicación. */\n getViews = async (): Promise<NewsViewsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsViewsGetResponse>(\n '/news/views/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/views/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/analytics/get — últimas 100 noticias publicadas con analytics. */\n getAnalytics = async (): Promise<NewsAnalyticsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsAnalyticsGetResponse>(\n '/news/analytics/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/analytics/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/analytics/getWhitFilters — analytics filtrados (single o lista). */\n getAnalyticsWithFilters = async (\n filters: NewsAnalyticsFilters = {},\n ): Promise<NewsAnalyticsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsAnalyticsGetResponse>(\n '/news/analytics/getWhitFilters',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/analytics/getWhitFilters]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/analytics/update — actualiza analytics de una noticia (Search Console). */\n updateAnalytics = async (pathNote: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/analytics/update',\n {\n authentication: this.authentication,\n filters: { pathNote },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/analytics/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/save — guarda los cambios de edición de una noticia (NEWS_EDIT). */\n editSave = async (\n path: string,\n content: { [key: string]: unknown },\n detail: { [key: string]: unknown },\n ): Promise<NewsEditSaveResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsEditSaveResponse>(\n '/news/edit/save',\n {\n authentication: this.authentication,\n path,\n content,\n detail,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/saveTemp — guarda un borrador temporal de la noticia (NEWS_EDIT). */\n saveTempNews = async (\n path: string,\n content: { [key: string]: unknown },\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/saveTemp',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/saveTemp]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/discardDraft — descarta el borrador de una noticia (NEWS_EDIT). */\n discardDraftNews = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/discardDraft',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/discardDraft]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/exit — sale de la edición, opcionalmente descartando el borrador (NEWS_EDIT). */\n exitEdit = async (\n path: string,\n discardDraft?: boolean,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/exit',\n {\n authentication: this.authentication,\n path,\n discardDraft,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/exit]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/hasDraft — indica si la noticia tiene un borrador pendiente (NEWS_EDIT). */\n hasDraft = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/hasDraft',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/hasDraft]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/inline — edita inline campos de zona/título de varias noticias (NEWS_EDIT). */\n editInline = async (items: NewsEditInlineItem[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/inline',\n {\n authentication: this.authentication,\n news: { new: items },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/inline]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/removeZone — elimina una zona de la noticia por posición (NEWS_EDIT). */\n removeZone = async (path: string, pos: number): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/removeZone',\n {\n authentication: this.authentication,\n path,\n pos,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/removeZone]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/analizeNews — analiza la noticia y sugiere personas, tags y secciones (NEWS_EDIT). */\n analizeNews = async (path: string): Promise<NewsAnalizeResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsAnalizeResponse>(\n '/news/edit/analizeNews',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/analizeNews]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/analizeNewsAI — análisis IA de un componente de la noticia (IA_ASSISTANCE). */\n analizeNewsAI = async (\n path: string,\n component: string,\n ): Promise<NewsAnalizeAIResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsAnalizeAIResponse>(\n '/news/edit/analizeNewsAI',\n {\n authentication: this.authentication,\n path,\n component,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/analizeNewsAI]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/SummaryNewsIA — genera el resumen IA de noticias (IA_ASSISTANCE o NEWS_PUBLISH). */\n summaryNewsIA = async (\n paths: string[],\n saveInNews?: boolean,\n ): Promise<NewsSummaryIAResponse> => {\n try {\n const newItems: NewsPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<NewsSummaryIAResponse>(\n '/news/edit/SummaryNewsIA',\n {\n authentication: this.authentication,\n news: { new: newItems },\n saveInNews,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/SummaryNewsIA]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/adminNewsConfiguration — configuración admin de campos de la noticia (NEWS_EDIT). */\n getAdminNewsConfiguration = async (\n path: string,\n ): Promise<NewsAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsAdminConfigurationResponse>(\n '/news/edit/adminNewsConfiguration',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/adminNewsConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/fieldsDefault — campos por defecto para la edición de la noticia (NEWS_EDIT). */\n getFieldsDefault = async (\n path: string,\n ): Promise<NewsFieldsDefaultResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsFieldsDefaultResponse>(\n '/news/edit/fieldsDefault',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/fieldsDefault]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/authorConfiguration — configuración de autor para la publicación (NEWS_EDIT). */\n getAuthorConfiguration =\n async (): Promise<NewsAuthorConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsAuthorConfigurationResponse>(\n '/news/edit/authorConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/authorConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/edit/hideBanner — oculta/muestra el banner de varias noticias (NEWS_HIDE_BANNER). */\n hideBanner = async (items: NewsHideBannerItem[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/edit/hideBanner',\n {\n authentication: this.authentication,\n news: { new: items },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/edit/hideBanner]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/versions/get — lista las versiones de una noticia (NEWS_VIEW). */\n getVersions = async (path: string): Promise<NewsVersionsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsVersionsGetResponse>(\n '/news/versions/get',\n {\n authentication: this.authentication,\n news: { path },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/versions/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/versions/recovery — recupera una versión específica de la noticia (NEWS_VERSION_RECOVERY). */\n recoverVersion = async (\n path: string,\n version: number,\n ): Promise<NewsVersionRecoveryResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsVersionRecoveryResponse>(\n '/news/versions/recovery',\n {\n authentication: this.authentication,\n news: { path, version },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/versions/recovery]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/refactor/get — lista noticias para refactorizar según filtros (NEWS_VIEW). */\n getRefactor = async (\n filters: NewsRefactorFilters = {},\n ): Promise<NewsRefactorGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsRefactorGetResponse>(\n '/news/refactor/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/refactor/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/IA/newsCheck — chequeo editorial IA de una noticia (por `path` o `nota`) (IA_ASSISTANCE). */\n newsCheck = async (input: NewsCheckInput): Promise<NewsCheckResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsCheckResponse>(\n '/news/IA/newsCheck',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/IA/newsCheck]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/IAcreate/create — crea una noticia con IA y devuelve su `fileName` (IA_NEWS_CREATE). */\n iaCreate = async (\n newsType: string,\n content?: NewsIaCreateContent,\n ): Promise<NewsIaCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsIaCreateResponse>(\n '/news/IAcreate/create',\n {\n authentication: this.authentication,\n newsType,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/IAcreate/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/IAcreate/preview — previsualiza el contenido generado por IA (IA_NEWS_CREATE). */\n iaPreview = async (\n input: NewsIaPreviewInput = {},\n ): Promise<NewsIaPreviewResponse> => {\n try {\n const response = await this.props.axiosApi.post<NewsIaPreviewResponse>(\n '/news/IAcreate/preview',\n {\n authentication: this.authentication,\n ...input,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/IAcreate/preview]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/analytics/migrar — migra los analytics de una noticia (ANALYTICS_UPDATED_MANUAL). */\n migrarAnalytics = async (pathNote: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/news/analytics/migrar',\n {\n authentication: this.authentication,\n filters: { pathNote },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/analytics/migrar]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /news/searchConsole/inspection — inspecciona la URL de una noticia en Search Console. */\n searchConsoleInspection = async (\n path: string,\n language?: string,\n ): Promise<NewsSearchConsoleInspectionResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NewsSearchConsoleInspectionResponse>(\n '/news/searchConsole/inspection',\n {\n authentication: this.authentication,\n path,\n language,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/news/searchConsole/inspection]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Tipo de envío de una notificación push. */\nexport type NotificationPushType = 'INMEDIATO' | 'EN_COLA' | 'PROGRAMADO';\n\n/** Tipo de envío disponible (notification/adminConfiguration → `types`). */\nexport interface NotificationSendType {\n name: string;\n value: string;\n}\n\n/** Topic devuelto por notification/adminConfiguration (`{ name, value }`). */\nexport interface NotificationConfigTopic {\n name: string;\n value: string;\n}\n\n/** Topic devuelto por notification/topics (`{ name, description }`). */\nexport interface NotificationTopic {\n name: string;\n description: string;\n}\n\n/** Cuerpo de la respuesta de POST /notification/adminConfiguration. */\nexport interface NotificationAdminConfigurationResponse extends CmsResponse {\n /** Topics configurados para la publicación. */\n topics?: NotificationConfigTopic[];\n /** Tipos de envío disponibles (inmediato, en cola, programado). */\n types?: NotificationSendType[];\n}\n\n/** Cuerpo de la respuesta de POST /notification/topics. */\nexport interface NotificationTopicsResponse extends CmsResponse {\n /** Topics de notificaciones push de la publicación. */\n topics?: NotificationTopic[];\n}\n\n/** Payload de la notificación push para POST /notification/push. */\nexport interface NotificationPushInput {\n /** Tipo de envío: `INMEDIATO`, `EN_COLA` o `PROGRAMADO`. */\n type: NotificationPushType;\n /** Título de la notificación. */\n title: string;\n /** Topics destino; debe tener al menos un elemento. */\n topics: string[];\n /** Fecha de envío (epoch ms). Requerido cuando `type` no es `INMEDIATO`. */\n date?: string;\n /** Subtítulo o cuerpo de la notificación (default: \"\"). */\n subtitle?: string;\n /** Ruta VFS de la noticia asociada (default: \"\"). */\n newsPath?: string;\n /** Ruta o URL de imagen adjunta (default: \"\"). */\n imagePath?: string;\n}\n\ninterface INotificationServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `notification` (notificaciones push) del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsNotificationServices {\n protected props: INotificationServices;\n protected authentication: Authentication;\n\n constructor(props: INotificationServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /notification/adminConfiguration — topics y tipos de envío del panel. */\n getAdminConfiguration =\n async (): Promise<NotificationAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<NotificationAdminConfigurationResponse>(\n '/notification/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/notification/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /notification/push — programa o envía una notificación push. */\n push = async (notification: NotificationPushInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/notification/push',\n {\n authentication: this.authentication,\n notification,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/notification/push]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /notification/topics — topics push configurados para la publicación. */\n getTopics = async (): Promise<NotificationTopicsResponse> => {\n try {\n const response = await this.props.axiosApi.post<NotificationTopicsResponse>(\n '/notification/topics',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/notification/topics]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Formato de campos devueltos por POST /people/get. */\nexport type PeopleFieldsFormat = 'all' | 'summary' | (string & {});\n\n/** Estado de aprobación: -1 = todos, 0 = aprobados, 1 = desaprobados. */\nexport type PeopleApprovalState = -1 | 0 | 1 | (string & {});\n\n/** Filtros de POST /people/get. */\nexport interface PeopleGetFilters {\n /** Texto de búsqueda (nombre o sinónimo). */\n text?: string;\n /** Ruta de categoría OpenCms que filtra por tipo de persona. */\n type?: string;\n /** Estado de aprobación: -1 = todos, 0 = aprobados, 1 = desaprobados. */\n estado?: PeopleApprovalState;\n /** Filtro por nacionalidad. */\n nacionalidad?: string;\n /** Cantidad máxima de resultados (default: 100). */\n size?: number | string;\n /** Filtro por fecha de nacimiento. */\n fecha?: string;\n /** Cláusula ORDER BY SQL (default: \"Name collate <charset> asc\"). */\n order?: string;\n /** Campos a retornar: \"all\", \"summary\" o lista CSV de campos. */\n fields?: PeopleFieldsFormat;\n}\n\n/** Persona del CMS. Los campos presentes dependen del formato `fields`. */\nexport interface Person {\n id?: number;\n name?: string;\n photo?: string;\n nickname?: string;\n shortdescription?: string;\n longdescription?: string;\n synonymous?: string;\n type?: string;\n lastmodified?: string;\n approved?: number;\n email?: string;\n birthdate?: string;\n twitter?: string;\n nacionality?: string;\n facebook?: string;\n google?: string;\n linkedin?: string;\n custom1?: string;\n custom2?: string;\n url?: string;\n [key: string]: unknown;\n}\n\n/**\n * Datos de una persona para POST /people/add.\n *\n * Acepta los campos del modelo Persons; solo `name` es obligatorio. La forma\n * exacta depende del modelo, por eso es un tipo laxo.\n */\nexport interface PersonInput {\n /** Nombre de la persona (obligatorio, no puede estar vacío). */\n name: string;\n photo?: string;\n nickname?: string;\n shortdescription?: string;\n longdescription?: string;\n type?: string;\n email?: string;\n birthdate?: string;\n twitter?: string;\n nacionality?: string;\n facebook?: string;\n google?: string;\n linkedin?: string;\n url?: string;\n custom1?: string;\n custom2?: string;\n synonymous?: string;\n approved?: number;\n [key: string]: unknown;\n}\n\n/** Datos de una persona para POST /people/update (incluye `id_person`). */\nexport interface PersonUpdateInput extends PersonInput {\n /** ID del registro a actualizar. */\n id_person: number;\n}\n\n/** Cuerpo de la respuesta de POST /people/get. */\nexport interface PeopleGetResponse extends CmsResponse {\n /** Lista de personas que cumplen los filtros. */\n persons?: Person[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /people/isExist. */\nexport interface PeopleIsExistResponse extends CmsResponse {\n /** Indica si existe una persona con el nombre exacto buscado. */\n exist?: boolean;\n /** Datos de la persona encontrada (solo si `exist` es `true`). */\n item?: Person;\n [key: string]: unknown;\n}\n\n/** Tipo de persona (categoría OpenCms) devuelto en adminConfiguration. */\nexport interface PersonType {\n path?: string;\n descripcion?: string;\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /people/adminConfiguration.\n *\n * NOTA: el doc indica que la respuesta trae un campo `status` con el array de\n * opciones de estado (`[\"-1\", \"0\", \"1\"]`), pero esa clave colisiona con el\n * `status` del envelope (`\"ok\" | \"fail\" | \"error\"`). Se deja accesible vía el\n * index signature hasta confirmar el nombre real con back.\n */\nexport interface PeopleAdminConfigurationResponse extends CmsResponse {\n /** Categorías de tipo de persona. */\n types?: PersonType[];\n /** Opciones de orden (claves `NAME` y `LASTMODIFIED` con su SQL). */\n order?: { [key: string]: unknown };\n /** Parámetro de configuración del sitio. */\n suggestApprovedPersons?: unknown;\n /** Parámetro de configuración del sitio. */\n showAllSynonymous?: unknown;\n [key: string]: unknown;\n}\n\ninterface IPeopleServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `people` (personas: periodistas, columnistas) del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsPeopleServices {\n protected props: IPeopleServices;\n protected authentication: Authentication;\n\n constructor(props: IPeopleServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /people/get — lista de personas con filtros y selección de campos. */\n getPeople = async (\n filters: PeopleGetFilters = {},\n ): Promise<PeopleGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<PeopleGetResponse>(\n '/people/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /people/add — crea una nueva persona (wrapper `people`). */\n addPerson = async (people: PersonInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/people/add',\n {\n authentication: this.authentication,\n people,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /people/update — actualiza una persona existente (wrapper `person`). */\n updatePerson = async (person: PersonUpdateInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/people/update',\n {\n authentication: this.authentication,\n person,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /people/delete — elimina una persona por su ID. */\n deletePerson = async (id: number | string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/people/delete',\n {\n authentication: this.authentication,\n person: { id },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /people/changeStatus — cambia el estado de aprobación de una persona.\n *\n * `status: 1` aprueba (requiere `PERSONS_APPROVE`); `status: 0` desaprueba\n * (requiere `PERSONS_DISAPPROVE`).\n */\n changeStatus = async (\n id: number | string,\n status: number | string,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/people/changeStatus',\n {\n authentication: this.authentication,\n person: { id, status },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/changeStatus]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /people/isExist — verifica si existe una persona con el nombre exacto. */\n isExist = async (text: string): Promise<PeopleIsExistResponse> => {\n try {\n const response = await this.props.axiosApi.post<PeopleIsExistResponse>(\n '/people/isExist',\n {\n authentication: this.authentication,\n filters: { text },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/isExist]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /people/adminConfiguration — configuración administrativa del módulo. */\n getAdminConfiguration =\n async (): Promise<PeopleAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PeopleAdminConfigurationResponse>(\n '/people/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/people/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Tipo de recurrencia de una actividad del planificador. */\nexport type PlanningActivityRecurrence =\n | 'RECURRENCE'\n | 'DATE_EXACT'\n | 'PERSONAL';\n\n/** Unidad de repetición (`repeat_type`) cuando la recurrencia es `PERSONAL`. */\nexport type PlanningActivityRepeatType = 'D' | 'W' | 'M' | 'Y' | (string & {});\n\n/** Tipo de recurrencia mensual (`type_of_month`) en recurrencia `PERSONAL`. */\nexport type PlanningActivityMonthType =\n | 'ordinalTime'\n | 'timeMonth'\n | (string & {});\n\n/** Filtros de POST /planning/activity/get. */\nexport interface PlanningActivityGetFilters {\n /** Timestamp (ms) de inicio del rango de fechas. */\n from?: number;\n /** Timestamp (ms) de fin del rango de fechas. */\n to?: number;\n /** Username para filtrar actividades asignadas. */\n username?: string;\n /** ID de una actividad específica a recuperar. */\n id?: number;\n}\n\n/** Actividad del planificador. La forma exacta depende del recurso. */\nexport interface PlanningActivity {\n id?: number;\n title?: string;\n description?: string;\n /** Username del usuario asignado. */\n userName?: string;\n /** Username del usuario que creó la actividad. */\n userCreation?: string;\n /** Color de la actividad en el calendario. */\n color?: string;\n type_recurrence?: PlanningActivityRecurrence;\n /** Timestamp (ms) de inicio. */\n start_date?: number;\n /** Timestamp (ms) de fin. */\n date_end?: number;\n publication?: number;\n [key: string]: unknown;\n}\n\n/**\n * Payload para crear una actividad (POST /planning/activity/create).\n *\n * Los campos condicionales aplican según `type_recurrence` (ver doc del módulo).\n */\nexport interface PlanningActivityCreateInput {\n /** Título de la actividad. */\n title: string;\n /** Username del usuario asignado. */\n userName: string;\n /** Username del usuario que crea la actividad. */\n userCreation: string;\n description?: string;\n color?: string;\n type_recurrence: PlanningActivityRecurrence;\n /** Timestamp (ms) de inicio. Requerido salvo en `PERSONAL` sin fecha de fin. */\n start_date?: number;\n /** Timestamp (ms) de fin. Requerido salvo en `PERSONAL` sin fecha de fin. */\n date_end?: number;\n /** Días de recurrencia (`RECURRENCE`: 1=diaria, 7=semanal; `PERSONAL`: cada N días). */\n personal_days?: number;\n /** `PERSONAL`: unidad de repetición (D/W/M/Y). */\n repeat_type?: PlanningActivityRepeatType;\n /** `PERSONAL`: días de la semana separados por coma (1=dom ... 7=sáb). */\n repeat_day?: string;\n /** `PERSONAL`: 0=never, 1=date, 2=latter. */\n repeat_end?: number;\n /** `PERSONAL`: cantidad de días para terminar la recurrencia. */\n repeat_end_days?: number;\n /** `PERSONAL` mensual: `ordinalTime` o `timeMonth`. */\n type_of_month?: PlanningActivityMonthType;\n /** `PERSONAL` con `type_of_month=ordinalTime`: cardinalidad de la fecha. */\n week_position?: number;\n /** ID de publicación (puede tomarse también de `authentication`). */\n publication?: number;\n}\n\n/** Payload para actualizar una actividad (POST /planning/activity/update). */\nexport interface PlanningActivityUpdateInput\n extends PlanningActivityCreateInput {\n /** ID de la actividad a actualizar. */\n id: number;\n}\n\n/** Cuerpo de la respuesta de POST /planning/activity/get. */\nexport interface PlanningActivitiesGetResponse extends CmsResponse {\n /** Lista de actividades que cumplen los filtros. */\n activities?: PlanningActivity[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /planning/activity/create. */\nexport interface PlanningActivityCreateResponse extends CmsResponse {\n /** ID de la actividad creada. */\n id?: number;\n}\n\n/** Cuerpo de la respuesta de POST /planning/activity/copy. */\nexport interface PlanningActivityCopyResponse extends CmsResponse {\n /** ID de la nueva actividad copiada. */\n id?: number;\n}\n\ninterface IPlanningServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `planning` (planificador de actividades) del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsPlanningServices {\n protected props: IPlanningServices;\n protected authentication: Authentication;\n\n constructor(props: IPlanningServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /planning/activity/get — lista de actividades según filtros. */\n getActivities = async (\n filters: PlanningActivityGetFilters = {},\n ): Promise<PlanningActivitiesGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PlanningActivitiesGetResponse>(\n '/planning/activity/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/planning/activity/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /planning/activity/create — crea una actividad y devuelve su `id`. */\n createActivity = async (\n activity: PlanningActivityCreateInput,\n ): Promise<PlanningActivityCreateResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PlanningActivityCreateResponse>(\n '/planning/activity/create',\n {\n authentication: this.authentication,\n activity,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/planning/activity/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /planning/activity/update — actualiza una actividad existente. */\n updateActivity = async (\n activity: PlanningActivityUpdateInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/planning/activity/update',\n {\n authentication: this.authentication,\n activity,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/planning/activity/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /planning/activity/delete — elimina una actividad por su ID. */\n deleteActivity = async (id: number): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/planning/activity/delete',\n {\n authentication: this.authentication,\n id,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/planning/activity/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /planning/activity/copy — duplica una actividad y devuelve el nuevo `id`. */\n copyActivity = async (\n id: number,\n ): Promise<PlanningActivityCopyResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PlanningActivityCopyResponse>(\n '/planning/activity/copy',\n {\n authentication: this.authentication,\n id,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/planning/activity/copy]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Tipo de fecha a filtrar en POST /polls/get (junto a `fromDate`/`toDate`). */\nexport type PollsGetTypeDate =\n | 'creation'\n | 'publication'\n | 'deadline'\n | 'expiration'\n | (string & {});\n\n/**\n * Campos a retornar por POST /polls/get: `\"all\"`, `\"summary\"` o lista separada\n * por comas (`id, url, question, status, dateStart, dateClose, answers,\n * totalVotes`). Si se omite, retorna el objeto completo con info de lock/draft.\n */\nexport type PollsFieldsFormat = 'all' | 'summary' | (string & {});\n\n/** Filtros de POST /polls/get. */\nexport interface PollsGetFilters {\n /** Texto libre para buscar en el campo \"pregunta\". */\n text?: string;\n /** Filtro por categoría. */\n category?: string;\n /** Filtro por estado de la encuesta. */\n state?: string;\n /** Filtro por tags. */\n tags?: string;\n /** Incluir archivos temporales (drafts). */\n showtemporal?: string;\n /** Cantidad de resultados por página (default: 200). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Tipo de fecha a filtrar (default: \"creation\"). */\n typeDate?: PollsGetTypeDate;\n /** Timestamp (ms) de fecha inicial. */\n fromDate?: string;\n /** Timestamp (ms) de fecha final. */\n toDate?: string;\n /** Criterio de orden (default: \"creation-date desc\"). */\n order?: string;\n /** Campos a retornar por encuesta. */\n fields?: PollsFieldsFormat;\n}\n\n/** Encuesta del CMS. La forma exacta depende del recurso y del formato pedido. */\nexport interface Poll {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /polls/get. */\nexport interface PollsGetResponse extends CmsResponse {\n /** Colección de encuestas según el formato `fields` solicitado. */\n polls: Poll[];\n total?: number;\n page?: number;\n size?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /polls/read (contenido XML + estado de edición). */\nexport interface PollReadResponse extends CmsResponse {\n /** Contenido XML completo de la encuesta. */\n content?: { [key: string]: unknown };\n /** Datos del lock si el recurso está bloqueado por otro usuario. */\n isLockData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /polls/review (detalle completo para revisión). */\nexport interface PollReviewResponse extends CmsResponse {\n /** Pregunta, respuestas, resultados/gráfico y noticias relacionadas. */\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /polls/create. */\nexport interface PollCreateResponse extends CmsResponse {\n /** Ruta del archivo de encuesta creado. */\n fileName?: string;\n}\n\n/** Cuerpo de la respuesta de POST /polls/adminConfiguration. */\nexport interface PollsAdminConfigurationResponse extends CmsResponse {\n /** Grupos disponibles del módulo de encuestas. */\n groups?: unknown;\n /** Estilos disponibles. */\n styles?: unknown;\n /** Path de categorías. */\n categoryPath?: string;\n /** Opciones de orden. */\n order?: unknown;\n /** Configuración de autoguardado. */\n autoSave?: unknown;\n /** XSD del recurso (solo si se envía `path`). */\n contentDefinition?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * Contenido editable de una encuesta (POST /polls/edit/save y saveTemp).\n *\n * Se serializa como objeto JSON con los campos del schema de la encuesta; la\n * forma exacta depende del recurso, por eso es un tipo laxo.\n */\nexport interface PollSaveContent {\n /** Pregunta de la encuesta. */\n pregunta?: string;\n /** Estado de la encuesta. */\n estado?: string;\n /** Respuestas posibles. */\n respuesta?: string[];\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /polls/edit/save. */\nexport interface PollSaveResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /polls/unpublish.\n *\n * Si la encuesta ya estaba despublicada, el error 007.003 se devuelve en el\n * campo `code` (no en `errorCode`).\n */\nexport interface PollUnpublishResponse extends CmsResponse {\n /** Código devuelto cuando la encuesta ya estaba despublicada (007.003). */\n code?: string;\n [key: string]: unknown;\n}\n\n/** Ítem del array de encuestas a publicar (sub-objeto `polls.poll`). */\nexport interface PollPathItem {\n /** Ruta VFS de la encuesta. */\n path: string;\n}\n\n/** Cuerpo de la respuesta de POST /polls/publish/check. */\nexport interface PollsPublishCheckResponse extends CmsResponse {\n /** Resultado de la validación por cada encuesta verificada. */\n resources: Array<{ [key: string]: unknown }>;\n [key: string]: unknown;\n}\n\ninterface IPollsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `polls` (encuestas) del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsPollsServices {\n protected props: IPollsServices;\n protected authentication: Authentication;\n\n constructor(props: IPollsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /polls/active — activa una encuesta del grupo indicado. */\n activatePoll = async (path: string, group: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/active',\n {\n authentication: this.authentication,\n path,\n group,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/active]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /polls/adminConfiguration — configuración del módulo de encuestas.\n *\n * Si se envía `path`, la respuesta incluye `contentDefinition` (XSD del recurso).\n */\n getAdminConfiguration = async (\n path?: string,\n ): Promise<PollsAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PollsAdminConfigurationResponse>(\n '/polls/adminConfiguration',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/close — cierra una encuesta activa. */\n closePoll = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/close',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/close]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/create — crea una encuesta vacía y devuelve su `fileName`. */\n createPoll = async (): Promise<PollCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<PollCreateResponse>(\n '/polls/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/get — lista de encuestas con filtros avanzados y paginación. */\n getPolls = async (\n filters: PollsGetFilters = {},\n ): Promise<PollsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<PollsGetResponse>(\n '/polls/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/read — lee y bloquea una encuesta, devolviendo su contenido XML. */\n readPoll = async (path: string): Promise<PollReadResponse> => {\n try {\n const response = await this.props.axiosApi.post<PollReadResponse>(\n '/polls/read',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/review — detalle completo de una encuesta para revisión. */\n reviewPoll = async (path: string): Promise<PollReviewResponse> => {\n try {\n const response = await this.props.axiosApi.post<PollReviewResponse>(\n '/polls/review',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/review]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/unlock — transfiere el lock de la encuesta al usuario actual. */\n unlockPoll = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/unlock',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/unlock]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/unpublish — despublica una encuesta publicada. */\n unpublishPoll = async (path: string): Promise<PollUnpublishResponse> => {\n try {\n const response = await this.props.axiosApi.post<PollUnpublishResponse>(\n '/polls/unpublish',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/unpublish]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/edit/discardDraft — descarta el draft de una encuesta en edición. */\n discardDraft = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/edit/discardDraft',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/edit/discardDraft]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /polls/edit/exit — sale del modo edición de una encuesta.\n *\n * Si existe un draft, requiere `discardDraft: true` para eliminarlo al salir.\n */\n exitEdit = async (\n path: string,\n discardDraft?: boolean,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/edit/exit',\n {\n authentication: this.authentication,\n path,\n discardDraft,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/edit/exit]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/edit/save — guarda y persiste el contenido de una encuesta. */\n savePoll = async (\n path: string,\n content: PollSaveContent,\n ): Promise<PollSaveResponse> => {\n try {\n const response = await this.props.axiosApi.post<PollSaveResponse>(\n '/polls/edit/save',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/edit/saveTemp — guarda el contenido como draft (sin persistir). */\n saveTempPoll = async (\n path: string,\n content: PollSaveContent,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/edit/saveTemp',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/edit/saveTemp]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/publish/check — verifica si las encuestas pueden publicarse. */\n publishCheck = async (\n polls: string[],\n ): Promise<PollsPublishCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<PollsPublishCheckResponse>(\n '/polls/publish/check',\n {\n authentication: this.authentication,\n polls,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/publish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /polls/publish/now — publica inmediatamente una o más encuestas. */\n publishNow = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const poll: PollPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/polls/publish/now',\n {\n authentication: this.authentication,\n polls: { poll },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/polls/publish/now]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Filtros de POST /recipes/get. */\nexport interface RecipesGetFilters {\n /** Búsqueda libre sobre título, ingredientes y keywords (Lucene). */\n text?: string;\n /** Filtrar por autor. */\n author?: string;\n /** ID de publicación alternativa (default: la del authentication). */\n publication?: string;\n /** Tipo de cocción. */\n cookingType?: string;\n /** Tipo de cocina. */\n cousineType?: string;\n /** Dificultad. */\n difficulty?: string;\n /** Ingrediente específico (el doc usa la clave `Ingredients` con mayúscula). */\n Ingredients?: string;\n /** Zona geográfica. */\n zone?: string;\n /** Categoría. */\n category?: string;\n /** Tags asociados. */\n tags?: string;\n /** Estado de la receta. */\n state?: string;\n /** Cantidad de resultados por página (default: 100). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Fecha de publicación desde (timestamp en ms). */\n fromDate?: string;\n /** Fecha de publicación hasta (timestamp en ms). */\n toDate?: string;\n /** Tiempo de preparación desde (timestamp en ms). */\n fromPreparation?: string;\n /** Tiempo de preparación hasta (timestamp en ms). */\n toPreparation?: string;\n /** Calorías desde (timestamp en ms). */\n fromCalories?: string;\n /** Calorías hasta (timestamp en ms). */\n toCalories?: string;\n /** Campo de ordenamiento (default: \"modification-date\"). */\n order?: string;\n /** Dirección del orden (\"asc\" / \"desc\", default: \"desc\"). */\n position?: string;\n}\n\n/** Receta del CMS. La forma exacta depende del recurso y del formato pedido. */\nexport interface Recipe {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/get. */\nexport interface RecipesGetResponse extends CmsResponse {\n /** Colección paginada de recetas con sus metadatos. */\n recipes: Recipe[];\n total?: number;\n page?: number;\n size?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/create. */\nexport interface RecipeCreateResponse extends CmsResponse {\n /** Path del archivo de receta creado en el VFS. */\n fileName?: string;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/adminConfiguration. */\nexport interface RecipesAdminConfigurationResponse extends CmsResponse {\n /** Listas de tipos de cocción, cocina, dificultad, unidades, tiempos y estados. */\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/previewFormats. */\nexport interface RecipesPreviewFormatsResponse extends CmsResponse {\n /** Formatos de preview (desktop/mobile/tablet) con sus dimensiones y protocolo. */\n [key: string]: unknown;\n}\n\n/**\n * Contenido XML editable de una receta (POST /recipes/edit/save y /saveTemp).\n *\n * Se serializa como objeto JSON con los campos del schema de la receta; la\n * forma exacta depende del recurso, por eso es un tipo laxo.\n */\nexport interface RecipeSaveContent {\n /** Título de la receta. */\n titulo?: string;\n /** Ingredientes de la receta. */\n ingredientes?: string;\n /** Tipo de cocción. */\n tipoCoccion?: string;\n /** Dificultad. */\n dificultad?: string;\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /recipes/edit/save.\n *\n * Devuelve los tags, personas y etiquetas de moderación (`UnsafeLabels`)\n * detectadas; la forma exacta depende del contenido guardado.\n */\nexport interface RecipeSaveResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/**\n * Payload de POST /recipes/edit/inline.\n *\n * El body completo es procesado por `TfsNewsAdminJson.save()`; los campos\n * dependen de esa implementación, por eso es un tipo laxo.\n */\nexport interface RecipeEditInlineInput {\n [key: string]: unknown;\n}\n\n/**\n * Payload de POST /recipes/edit/massive.\n *\n * El body completo es procesado por `TfsNewsAdminJson.saveMassive()`; los\n * campos dependen de esa implementación, por eso es un tipo laxo.\n */\nexport interface RecipeEditMassiveInput {\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /recipes/edit/analizeNews.\n *\n * Devuelve sugerencias editoriales y listas ponderadas de personas, tags,\n * lugares, secciones y categorías detectadas; la forma exacta es laxa.\n */\nexport interface RecipeAnalysisResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/edit/authorConfiguration. */\nexport interface RecipeAuthorConfigurationResponse extends CmsResponse {\n /** Modo de autoría, usuario anónimo, texto libre y flags de firma. */\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/edit/fieldsDefault. */\nexport interface RecipeFieldsDefaultResponse extends CmsResponse {\n /** Lista de campos de edición predeterminados (`editFieldsDefault`). */\n [key: string]: unknown;\n}\n\n/**\n * Ítem de los arrays de recetas/recursos (`recipes.recipe` y `news.new`).\n *\n * Ambos sub-objetos comparten la misma forma `{ path }`.\n */\nexport interface RecipePathItem {\n /** Ruta VFS de la receta. */\n path: string;\n}\n\n/** Cuerpo de la respuesta de POST /recipes/publish/check. */\nexport interface RecipesPublishCheckResponse extends CmsResponse {\n /** Relaciones, lock y datos del último modificante por receta. */\n [key: string]: unknown;\n}\n\ninterface IRecipesServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `recipes` del CMS (core + edit/publish).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsRecipesServices {\n protected props: IRecipesServices;\n protected authentication: Authentication;\n\n constructor(props: IRecipesServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /recipes/get — lista paginada de recetas con filtros (Lucene). */\n getRecipes = async (\n filters: RecipesGetFilters = {},\n ): Promise<RecipesGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<RecipesGetResponse>(\n '/recipes/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/create — crea una receta vacía y devuelve su `fileName`. */\n createRecipe = async (): Promise<RecipeCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<RecipeCreateResponse>(\n '/recipes/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/adminConfiguration — configuración administrativa de recetas. */\n getAdminConfiguration =\n async (): Promise<RecipesAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<RecipesAdminConfigurationResponse>(\n '/recipes/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/previewFormats — formatos de previsualización configurados. */\n getPreviewFormats = async (): Promise<RecipesPreviewFormatsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<RecipesPreviewFormatsResponse>(\n '/recipes/previewFormats',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/previewFormats]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/save — guarda el contenido XML completo de una receta. */\n saveRecipe = async (\n path: string,\n content: RecipeSaveContent,\n ): Promise<RecipeSaveResponse> => {\n try {\n const response = await this.props.axiosApi.post<RecipeSaveResponse>(\n '/recipes/edit/save',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/saveTemp — guarda la receta como borrador temporal (`~`). */\n saveTempRecipe = async (\n path: string,\n content: RecipeSaveContent,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/edit/saveTemp',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/saveTemp]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/inline — guarda cambios inline (delegado a TfsNewsAdminJson). */\n editInline = async (data: RecipeEditInlineInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/edit/inline',\n {\n authentication: this.authentication,\n ...data,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/inline]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/massive — guarda cambios masivos sobre varias recetas. */\n editMassive = async (data: RecipeEditMassiveInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/edit/massive',\n {\n authentication: this.authentication,\n ...data,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/massive]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /recipes/edit/exit — sale del modo edición y desbloquea la receta.\n *\n * Si existe un draft temporal, solo lo descarta cuando `discardDraft` es `true`.\n */\n exitEdit = async (\n path: string,\n discardDraft?: boolean,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/edit/exit',\n {\n authentication: this.authentication,\n path,\n discardDraft,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/exit]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/discardDraft — descarta el borrador temporal sin cancelar el lock. */\n discardDraft = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/edit/discardDraft',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/discardDraft]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/analizeNews — analiza la receta y devuelve sugerencias. */\n analizeNews = async (path: string): Promise<RecipeAnalysisResponse> => {\n try {\n const response = await this.props.axiosApi.post<RecipeAnalysisResponse>(\n '/recipes/edit/analizeNews',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/analizeNews]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/authorConfiguration — configuración de firma de autores. */\n getAuthorConfiguration =\n async (): Promise<RecipeAuthorConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<RecipeAuthorConfigurationResponse>(\n '/recipes/edit/authorConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/authorConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/edit/fieldsDefault — campos de edición predeterminados. */\n getFieldsDefault = async (): Promise<RecipeFieldsDefaultResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<RecipeFieldsDefaultResponse>(\n '/recipes/edit/fieldsDefault',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/edit/fieldsDefault]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/publish/check — relaciones y estado de una lista de recetas. */\n checkPublish = async (\n paths: string[],\n ): Promise<RecipesPublishCheckResponse> => {\n try {\n const recipe: RecipePathItem[] = paths.map((path) => ({ path }));\n const response =\n await this.props.axiosApi.post<RecipesPublishCheckResponse>(\n '/recipes/publish/check',\n {\n authentication: this.authentication,\n recipes: { recipe },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/publish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /recipes/publish/now — publica inmediatamente una o más recetas. */\n publishNow = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const recipe: RecipePathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/publish/now',\n {\n authentication: this.authentication,\n recipes: { recipe },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/publish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /recipes/publish/massive — publica masivamente recursos (esquema noticias).\n *\n * El endpoint usa la estructura `news.new` (no `recipes.recipe`).\n */\n publishMassive = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const newItems: RecipePathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/publish/massive',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/publish/massive]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /recipes/publish/schedule — programa la publicación diferida de recursos.\n *\n * Al igual que `massive`, usa la estructura `news.new`. La fecha programada\n * debe ser futura (ver MENSAJE PARA BACK: el parámetro de fecha no está en el doc).\n */\n schedulePublish = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const newItems: RecipePathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/recipes/publish/schedule',\n {\n authentication: this.authentication,\n news: { new: newItems },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/recipes/publish/schedule]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\n\n/** Envelope común de respuesta de los webservices de OpenCms. */\nexport interface CmsResponse {\n status: 'ok' | 'fail' | 'error';\n errorCode?: string;\n error?: string;\n}\n\n/** Estado posible de un usuario del sistema. */\nexport type UserStatus = 'active' | 'block' | 'pending';\n\n/** Formato de respuesta soportado por POST /users/get. */\nexport type UsersFieldsFormat = 'all' | 'FullName' | 'detail' | '';\n\n/**\n * Ámbito de publicación: `\"pub\"` (solo publicación), `\"admin\"` (solo admins\n * globales) o cualquier otro valor (ambos).\n */\nexport type PublicationScope = 'pub' | 'admin' | (string & {});\n\n/** Filtro sobre campos adicionales del usuario (`filters.advance`). */\nexport interface UsersAdvanceFilter {\n name: string;\n value: string;\n}\n\n/** Filtros de POST /users/get. */\nexport interface UsersGetFilters {\n /** Cantidad de resultados por página (default: 100). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Fuerza búsqueda global (default: false). */\n searchGlobal?: boolean;\n /**\n * Campo + dirección. Campos válidos: `username`, `firstname`, `lastname`,\n * `email`, `datecreated`. Ej: `\"datecreated desc\"`.\n */\n order?: string;\n /** Nombre del grupo para filtrar usuarios. */\n grupo?: string;\n /** Organizational Unit (default: \"/\"). */\n ou?: string;\n /** Estado del usuario. */\n status?: UserStatus;\n /** Timestamp en milisegundos (inicio del rango de fecha de creación). */\n fromDate?: string;\n /** Timestamp en milisegundos (fin del rango de fecha de creación). */\n toDate?: string;\n /** Filtra por ámbito de publicación. */\n publicationScope?: PublicationScope;\n /** Formato de respuesta. */\n fields?: UsersFieldsFormat;\n /** Búsqueda libre por email, username, apellido o nombre (LIKE). */\n text?: string;\n /** Filtros sobre campos adicionales del usuario. */\n advance?: UsersAdvanceFilter[];\n}\n\n/** Usuario del CMS. Los campos presentes dependen del formato `fields`. */\nexport interface CmsUser {\n username?: string;\n firstname?: string;\n lastname?: string;\n fullName?: string;\n email?: string;\n datecreated?: string;\n status?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /users/get. */\nexport interface UsersGetResponse extends CmsResponse {\n users: CmsUser[];\n total?: number;\n page?: number;\n size?: number;\n}\n\n/** Formato de respuesta soportado por POST /users/publication. */\nexport type UsersPublicationFieldsFormat = 'all' | 'summary' | 'FullName' | '';\n\n/** Filtros de POST /users/publication. */\nexport interface UsersPublicationFilters {\n /** Texto libre para búsqueda de usuario. */\n text?: string;\n /** Formato de respuesta. */\n fields?: UsersPublicationFieldsFormat;\n}\n\n/** Cuerpo de la respuesta de POST /users/publication. */\nexport interface UsersPublicationResponse extends CmsResponse {\n users: CmsUser[];\n}\n\n/** Grupo del sistema devuelto por POST /users/groups/get. */\nexport interface UserGroup {\n id: string;\n name: string;\n}\n\n/** Cuerpo de la respuesta de POST /users/groups/get. */\nexport interface UserGroupsResponse extends CmsResponse {\n groups: UserGroup[];\n}\n\n/** Pin (recurso fijado) de un usuario. */\nexport interface UserPin {\n id: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /users/pin/get. */\nexport interface UserPinsGetResponse extends CmsResponse {\n pins: UserPin[];\n total?: number;\n}\n\n/** Cuerpo de la respuesta de POST /users/pin/add. */\nexport interface UserPinAddResponse extends CmsResponse {\n /** ID del pin creado. */\n id?: number;\n}\n\n/** Pin a eliminar en POST /users/pin/delete. */\nexport interface UserPinDeleteInput {\n id: number;\n}\n\n/** Acción soportada por POST /users/actions/setStatus. */\nexport type UserStatusAction = 'activate' | 'deactivate';\n\ninterface IUsersServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `users` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsUsersServices {\n protected props: IUsersServices;\n protected authentication: Authentication;\n\n constructor(props: IUsersServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /users/get — lista paginada de usuarios con filtros. */\n getUsers = async (\n filters: UsersGetFilters = {},\n ): Promise<UsersGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<UsersGetResponse>(\n '/users/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/publication — usuarios asociados a la publicación. */\n getPublicationUsers = async (\n filters: UsersPublicationFilters = {},\n ): Promise<UsersPublicationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<UsersPublicationResponse>(\n '/users/publication',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/publication]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/groups/get — grupos disponibles del sistema. */\n getGroups = async (ou = '/'): Promise<UserGroupsResponse> => {\n try {\n const response = await this.props.axiosApi.post<UserGroupsResponse>(\n '/users/groups/get',\n {\n authentication: this.authentication,\n ou,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/groups/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/pin/get — pins del usuario autenticado. */\n getPins = async (): Promise<UserPinsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<UserPinsGetResponse>(\n '/users/pin/get',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/pin/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/pin/add — agrega un pin de recurso. */\n addPin = async (pin: string): Promise<UserPinAddResponse> => {\n try {\n const response = await this.props.axiosApi.post<UserPinAddResponse>(\n '/users/pin/add',\n {\n authentication: this.authentication,\n pines: { pin: [pin] },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/pin/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/pin/delete — elimina uno o más pins por ID. */\n deletePins = async (ids: number[]): Promise<CmsResponse> => {\n try {\n const pin: UserPinDeleteInput[] = ids.map((id) => ({ id }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/users/pin/delete',\n {\n authentication: this.authentication,\n pines: { pin },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/pin/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/actions/setStatus — activa o desactiva un usuario. */\n setUserStatus = async (\n username: string,\n action: UserStatusAction,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/users/actions/setStatus',\n {\n authentication: this.authentication,\n username,\n action,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/actions/setStatus]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/actions/resetPass — restablece la contraseña de un usuario. */\n resetPassword = async (username: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/users/actions/resetPass',\n {\n authentication: this.authentication,\n username,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/actions/resetPass]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /users/actions/resetMfa — resetea la configuración MFA de un usuario. */\n resetMfa = async (username: string, reason: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/users/actions/resetMfa',\n {\n authentication: this.authentication,\n username,\n reason,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/users/actions/resetMfa]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Zona de una publicación del CMS. */\nexport interface Zone {\n id?: number;\n /** ID de publicación (idTipoEdicion). Requerido al crear. */\n idTipoEdicion?: number;\n name?: string;\n description?: string;\n color?: string;\n idPage?: number;\n order?: number;\n orderDefault?: number;\n sizeDefault?: number;\n publication?: number;\n visibility?: number;\n [key: string]: unknown;\n}\n\n/** Payload para crear una zona (POST /zones/add). */\nexport interface ZoneAddInput {\n /** ID de publicación (usado para validar permiso). */\n idTipoEdicion: number;\n name: string;\n description: string;\n color: string;\n idPage?: number;\n orderDefault?: number;\n sizeDefault?: number;\n visibility?: number;\n}\n\n/** Payload para actualizar una zona (POST /zones/update). */\nexport interface ZoneUpdateInput {\n id: number;\n name: string;\n description: string;\n color?: string;\n idPage?: number;\n orderDefault?: number;\n sizeDefault?: number;\n visibility?: number;\n idTipoEdicion?: number;\n}\n\n/** Formato de campos devueltos por POST /zones/get. */\nexport type ZonesFieldsFormat = 'all' | 'summary' | (string & {});\n\n/** Filtros de POST /zones/get. */\nexport interface ZonesGetFilters {\n /** Filtra zonas por ID de página; si se omite devuelve todas. */\n idPage?: number;\n /** Filtra por texto contenido en nombre/descripción (búsqueda `%texto%`). */\n text?: string;\n /** Campos a devolver por zona. */\n fields?: ZonesFieldsFormat;\n}\n\n/** Cuerpo de la respuesta de POST /zones/get. */\nexport interface ZonesGetResponse extends CmsResponse {\n zones: Zone[];\n}\n\n/** Cuerpo de la respuesta de POST /zones/add. */\nexport interface ZoneAddResponse extends CmsResponse {\n /** ID de la zona creada. */\n id?: number;\n}\n\ninterface IZonesServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `zones` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsZonesServices {\n protected props: IZonesServices;\n protected authentication: Authentication;\n\n constructor(props: IZonesServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /zones/get — lista de zonas de la publicación, con filtros. */\n getZones = async (filters: ZonesGetFilters = {}): Promise<ZonesGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<ZonesGetResponse>(\n '/zones/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/zones/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /zones/add — crea una nueva zona. */\n addZone = async (zone: ZoneAddInput): Promise<ZoneAddResponse> => {\n try {\n const response = await this.props.axiosApi.post<ZoneAddResponse>(\n '/zones/add',\n {\n authentication: this.authentication,\n zone,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/zones/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /zones/update — actualiza una zona existente. */\n updateZone = async (zone: ZoneUpdateInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/zones/update',\n {\n authentication: this.authentication,\n zone,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/zones/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /zones/delete — elimina una zona por su ID. */\n deleteZone = async (id: number): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/zones/delete',\n {\n authentication: this.authentication,\n zone: { id },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/zones/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /zones/order — actualiza el orden de varias zonas.\n *\n * @param ids IDs de zonas en el nuevo orden deseado. Se serializan como CSV\n * (ej: `[5, 3, 8, 1]` → `\"5,3,8,1\"`). Con un solo ID el endpoint no modifica\n * nada (devuelve `status: ok`).\n */\n orderZones = async (ids: number[]): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/zones/order',\n {\n authentication: this.authentication,\n zone: {},\n zones: { order: ids.join(',') },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/zones/order]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Estado de la integración con Drive devuelto por POST /workpaper/check. */\nexport type WorkpaperCheckState =\n | 'NOT_ENABLED'\n | 'GUI_WORKPAPERS_NO_ACCOUNT_USER_1'\n | 'GUI_WORKPAPERS_NO_ACCOUNT_SYSTEM'\n | (string & {});\n\n/** Estado de vinculación de Drive por edición (POST /workpaper/status). */\nexport type WorkpaperEditionStatus =\n | 'NOT_ENABLED'\n | 'YES_USER_LINKED'\n | 'USER_LINK'\n | 'YES_ACCOUNT_SYSTEM.'\n | 'NO_ACCOUNT_LINK'\n | (string & {});\n\n/** Cuerpo de la respuesta de POST /workpaper/check. */\nexport interface WorkpaperCheckResponse extends CmsResponse {\n /** Estado de la integración con Drive para la noticia consultada. */\n state?: WorkpaperCheckState;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /workpaper/login. */\nexport interface WorkpaperLoginResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Tipo de edición con su estado de vinculación a Drive. */\nexport interface WorkpaperEdition {\n id?: number;\n description?: string;\n image?: string;\n link?: string;\n status?: WorkpaperEditionStatus;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /workpaper/status. */\nexport interface WorkpaperStatusResponse extends CmsResponse {\n ediciones: WorkpaperEdition[];\n}\n\ninterface IWorkpaperServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `workpaper` del CMS (integración Google Drive).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsWorkpaperServices {\n protected props: IWorkpaperServices;\n protected authentication: Authentication;\n\n constructor(props: IWorkpaperServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /workpaper/check — estado de la integración con Drive de una noticia. */\n check = async (path: string): Promise<WorkpaperCheckResponse> => {\n try {\n const response = await this.props.axiosApi.post<WorkpaperCheckResponse>(\n '/workpaper/check',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/workpaper/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /workpaper/login — verifica la autorización de Drive para una URL. */\n login = async (url: string): Promise<WorkpaperLoginResponse> => {\n try {\n const response = await this.props.axiosApi.post<WorkpaperLoginResponse>(\n '/workpaper/login',\n {\n authentication: this.authentication,\n link: { url },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/workpaper/login]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /workpaper/status — ediciones disponibles y su estado de Drive. */\n status = async (): Promise<WorkpaperStatusResponse> => {\n try {\n const response = await this.props.axiosApi.post<WorkpaperStatusResponse>(\n '/workpaper/status',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/workpaper/status]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Filtros de POST /vods/get. */\nexport interface VodsGetFilters {\n /** Publicación a filtrar; si se omite usa la de `authentication`. */\n publication?: string;\n /** Tipo de VOD a filtrar. */\n type?: number;\n /** Categoría a filtrar. */\n category?: string;\n /** Texto de búsqueda avanzada. */\n text?: string;\n /** Filtro por personas. */\n people?: string;\n /** Filtro por tags. */\n tags?: string;\n /** Cantidad de resultados por página (default: 100). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Fecha de inicio en milisegundos epoch (default: hoy). */\n fromDate?: string;\n /** Fecha de fin en milisegundos epoch (default: hace 1 mes). */\n toDate?: string;\n /** Campo de ordenamiento (default: \"user-modification-date\"). */\n order?: string;\n /** Dirección de ordenamiento (default: \" desc \"). */\n position?: string;\n}\n\n/** VOD (video bajo demanda) del CMS. La forma exacta depende del recurso. */\nexport interface Vod {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /vods/get. */\nexport interface VodsGetResponse extends CmsResponse {\n vods: Vod[];\n total?: number;\n page?: number;\n size?: number;\n}\n\n/** Tipo de VOD disponible en el sistema (pelicula, serie, temporada, capitulo). */\nexport interface VodType {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /vods/types. */\nexport interface VodsTypesResponse extends CmsResponse {\n types: VodType[];\n}\n\n/** Cuerpo de la respuesta de los endpoints de creación de VODs. */\nexport interface VodCreateResponse extends CmsResponse {\n /** Path del archivo creado en el VFS. */\n fileName?: string;\n}\n\ninterface IVodsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `vods` del CMS (videos bajo demanda).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsVodsServices {\n protected props: IVodsServices;\n protected authentication: Authentication;\n\n constructor(props: IVodsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /vods/get — lista paginada de VODs con filtros. */\n getVods = async (filters: VodsGetFilters = {}): Promise<VodsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<VodsGetResponse>(\n '/vods/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/vods/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /vods/types — tipos de VOD disponibles en el sistema. */\n getTypes = async (): Promise<VodsTypesResponse> => {\n try {\n const response = await this.props.axiosApi.post<VodsTypesResponse>(\n '/vods/types',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/vods/types]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /vods/movie/create — crea una película (VOD tipo pelicula). */\n createMovie = async (): Promise<VodCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<VodCreateResponse>(\n '/vods/movie/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/vods/movie/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /vods/serie/create — crea una serie (VOD tipo serie). */\n createSerie = async (): Promise<VodCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<VodCreateResponse>(\n '/vods/serie/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/vods/serie/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /vods/playlist/create — crea una playlist de VODs. */\n createPlaylist = async (): Promise<VodCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<VodCreateResponse>(\n '/vods/playlist/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/vods/playlist/create]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Tipo (subtipo) de video soportado por el módulo. */\nexport type VideoType =\n | 'video-youtube'\n | 'video-embedded'\n | 'video-link'\n | 'video-youtube-short'\n | (string & {});\n\n/** Dirección de ordenamiento de POST /videos/get. */\nexport type VideosGetOrder = 'asc' | 'desc' | (string & {});\n\n/** Filtros de POST /videos/get. */\nexport interface VideosGetFilters {\n /** Path absoluto de un video específico; si se envía, ignora los demás filtros. */\n videoPath?: string;\n /** Filtrar por noticia asociada. */\n onnews?: string;\n /** Filtrar por agencia. */\n agency?: string;\n /** Texto libre de búsqueda. */\n text?: string;\n /** Incluir histórico en la búsqueda. */\n searchinhistory?: boolean;\n /** Filtrar por categoría. */\n category?: string;\n /** Filtrar por formatos de video. */\n formats?: string;\n /** Filtrar por tags/keywords. */\n tags?: string;\n /** Filtrar por clasificación (rated). */\n classification?: string;\n /** Filtrar por ID interno. */\n id?: string;\n /** Tipo de video a filtrar. */\n type?: VideoType;\n /** Cantidad de resultados por página (default: 24). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Fecha de inicio (timestamp en ms). */\n fromDate?: string;\n /** Fecha de fin (timestamp en ms). */\n toDate?: string;\n /** Filtrar por nombre de archivo (búsqueda parcial). */\n filename?: string;\n /** Si es \"true\", excluye videos con keywords. */\n notags?: string;\n /** Si es \"true\", excluye videos con título. */\n notitle?: string;\n /** Orden por fecha de modificación (default: desc). */\n order?: VideosGetOrder;\n /** Si es \"path\", la respuesta incluye solo el campo `videoPath` por ítem. */\n fields?: 'path' | (string & {});\n}\n\n/** Video del CMS. La forma exacta depende del recurso y del formato pedido. */\nexport interface Video {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/get. */\nexport interface VideosGetResponse extends CmsResponse {\n /** Colección paginada de videos (ausente si se pidió un `videoPath` puntual). */\n videos?: Video[];\n total?: number;\n page?: number;\n size?: number;\n /** Campos de la ficha individual cuando se pide un `videoPath`. */\n [key: string]: unknown;\n}\n\n/** Ficha completa de un video (POST /videos/read). */\nexport interface VideoDetailResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Configuración del módulo de videos (POST /videos/adminConfiguration). */\nexport interface VideosAdminConfigurationResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Metadatos editables de un video (POST /videos/edit/save). */\nexport interface VideoSaveContent {\n /** Título del video (obligatorio, no puede estar vacío). */\n title: string;\n description?: string;\n agency?: string;\n author?: string;\n /** Autoplay (\"true\"/\"false\"). */\n autoplay?: string;\n /** Silenciar (\"true\"/\"false\"). */\n mute?: string;\n /** Array de strings con las categorías. */\n category?: string[];\n /** Clasificación de contenido (G, PG, PG-13, R, NC-17). */\n classification?: string;\n /** Keywords/tags separados por comas. */\n tags?: string;\n /** Path o URL de la imagen de preview. */\n prevImage?: string;\n /** Tipo de video (necesario para la lógica de duración de YouTube). */\n type?: VideoType;\n /** Duración (solo se usa si tipo es video-youtube y no hay duración previa). */\n duration?: string;\n /** Timestamp de última modificación del usuario. */\n userModificationDate?: string;\n}\n\n/** Payload de POST /videos/edit/hideBanner. */\nexport interface VideoHideBannerInput {\n path: string;\n /** \"true\" para ocultar publicidad, \"false\" para mostrarla. */\n hideAdvertising: string;\n}\n\n/** Payload de POST /videos/edit/inline. */\nexport interface VideoInlineInput {\n path: string;\n /** Nuevo título; solo se guarda si viene y no está vacío. */\n title?: string;\n /** Array de strings con las categorías. */\n category?: string[];\n /** Timestamp de última modificación del usuario. */\n userModificationDate?: string;\n}\n\n/** Cuerpo de la respuesta de POST /videos/embedded/exists. */\nexport interface VideoEmbeddedExistsResponse extends CmsResponse {\n /** Path del video si existe; vacío si no. */\n path?: string;\n}\n\n/** Payload de POST /videos/embedded/upload. */\nexport interface VideoEmbeddedUploadInput {\n title?: string;\n description?: string;\n agency?: string;\n author?: string;\n /** Clasificación (G, PG, etc.). */\n rated?: string;\n keywords?: string;\n category?: string[];\n /** Código embed del video. */\n code?: string;\n /** Carpeta de destino en el VFS. */\n folder?: string;\n /** Sección CMS. */\n section?: string;\n /** Path o URL de imagen de preview. */\n imagePath?: string;\n /** Código Rudo (para subir imagen desde rudo.video). */\n rudoCode?: string;\n autoplay?: string;\n mute?: string;\n /** Subtipo de video embedded. */\n videoType?: string;\n moduleConfig?: string;\n}\n\n/** Payload de POST /videos/youtube/upload. */\nexport interface VideoYoutubeUploadInput {\n /** ID o URL del video de YouTube. */\n youtubeId?: string;\n title?: string;\n description?: string;\n agency?: string;\n author?: string;\n /** Clasificación (G, PG, etc.). */\n rated?: string;\n keywords?: string;\n category?: string[];\n /** Path o URL de imagen de preview. */\n imagePath?: string;\n /** Carpeta de destino en el VFS. */\n folder?: string;\n /** Sección CMS. */\n section?: string;\n /** URL completa del video (para detectar YouTube Shorts). */\n codeValue?: string;\n autoplay?: string;\n mute?: string;\n /** Subtipo de video YouTube. */\n videoType?: string;\n moduleConfig?: string;\n}\n\n/** Cuerpo de la respuesta de los endpoints de creación/subida de videos. */\nexport interface VideoUploadResponse extends CmsResponse {\n /** Path del video creado en el VFS. */\n path?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/publish/check. */\nexport interface VideosPublishCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Item del array de POST /videos/publish/schedule. */\nexport interface VideoScheduleItem {\n path: string;\n}\n\n/** Sub-objeto `videos` de POST /videos/publish/schedule. */\nexport interface VideosScheduleInput {\n /** Array de objetos con el path VFS de cada video. */\n video: VideoScheduleItem[];\n /** Fecha/hora de publicación programada. */\n publishDate: string;\n /** Si true, actualiza `ultimaModificacion` con la fecha programada. */\n setLastModification?: boolean;\n}\n\n/** Cuerpo de la respuesta de POST /videos/rudo/getThumbnails. */\nexport interface VideoRudoThumbnailsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/unlock/check. */\nexport interface VideoUnlockCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/unpublish/check. */\nexport interface VideoUnpublishCheckResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/youtube/getThumbnails. */\nexport interface YoutubeThumbnailsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Estado de conversión de un video nativo. */\nexport type VideoConvertStatus =\n | 'OnQueue'\n | 'OnProcess'\n | 'Converted'\n | 'NoFormats'\n | (string & {});\n\n/** Cuerpo de la respuesta de POST /videos/nativos/convertStatus. */\nexport interface VideoConvertStatusResponse extends CmsResponse {\n convertStatus?: VideoConvertStatus;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/uploadS3Progress. */\nexport interface VideoUploadProgressResponse extends CmsResponse {\n /** Porcentaje de avance (ej: \"47\"). */\n uploadProgress?: string;\n /** Nota: en este endpoint `status` puede traer texto del proceso (ej: \"Converting\"). */\n [key: string]: unknown;\n}\n\n/** Payload `video` de POST /videos/nativos/updateVideoProcessing. */\nexport interface VideoUpdateProcessingInput {\n path: string;\n /** Título (property Title). */\n title?: string;\n /** Descripción (property Description). */\n description?: string;\n /** Keywords separados por comas (property Keywords). */\n tags?: string;\n /** Agencia (property Agency). */\n agency?: string;\n /** Autor (property Author). */\n author?: string;\n /** Clasificación de contenido (property video-rated). */\n rated?: string;\n /** Categorías separadas por coma; se convierten a pipe-separated. */\n categoryStr?: string;\n /** Autoplay (property video-autoplay; default: \"false\"). */\n autoplay?: string;\n /** Silenciar (property video-mute; default: \"false\"). */\n mute?: string;\n /** Path VFS de la imagen de preview (agrega relación videoImage). */\n prevImage?: string;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/createVideoProcessing. */\nexport interface VideoCreateProcessingResponse extends CmsResponse {\n /** Path VFS donde se almacenará el video. */\n path?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/preUploadAMZ. */\nexport interface VideoPreUploadAMZResponse extends CmsResponse {\n /** URL prefirmada para subir el archivo a AMZ. */\n presignedUrl?: string;\n /** Path VFS de destino del archivo. */\n vfsPath?: string;\n siteName?: string;\n publication?: string;\n language?: string;\n user?: string;\n filename?: string;\n path?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/preMultiUploadAMZ. */\nexport interface VideoPreMultiUploadAMZResponse extends CmsResponse {\n /** ID de la subida multiparte. */\n uploadId?: string;\n /** URLs prefirmadas, una por parte. */\n presignedUrls?: string[];\n /** Cantidad de partes en las que se divide el archivo. */\n numberOfParts?: number;\n /** Tamaño de cada parte. */\n partsSize?: number;\n user?: string;\n vfsPath?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/preMultiCompleteAMZ. */\nexport interface VideoPreMultiCompleteAMZResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/preMultiAbortAMZ. */\nexport interface VideoPreMultiAbortAMZResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/preMultiResignAMZ. */\nexport interface VideoPreMultiResignAMZResponse extends CmsResponse {\n /** URLs prefirmadas regeneradas, una por parte. */\n presignedUrls?: string[];\n /** Cantidad de partes regeneradas. */\n numberOfParts?: number;\n /** Path VFS del archivo. */\n vfspath?: string;\n /** ID de la subida multiparte. */\n uploadId?: string;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /videos/nativos/converter. */\nexport interface VideoConverterResponse extends CmsResponse {\n /** Porcentaje de avance de la conversión. */\n percent?: number;\n [key: string]: unknown;\n}\n\ninterface IVideosServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `videos` del CMS (core + edit/embedded/publish/\n * rudo/unlock/unpublish/youtube + nativos).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsVideosServices {\n protected props: IVideosServices;\n protected authentication: Authentication;\n\n constructor(props: IVideosServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /videos/get — lista videos del VFS con filtros (o ficha si hay videoPath). */\n getVideos = async (\n filters: VideosGetFilters = {},\n ): Promise<VideosGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<VideosGetResponse>(\n '/videos/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/read — lee y bloquea un video, devolviendo su ficha completa. */\n readVideo = async (path: string): Promise<VideoDetailResponse> => {\n try {\n const response = await this.props.axiosApi.post<VideoDetailResponse>(\n '/videos/read',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/adminConfiguration — configuración del módulo para la publicación. */\n getAdminConfiguration =\n async (): Promise<VideosAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideosAdminConfigurationResponse>(\n '/videos/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/available — resetea fechas de expiración/disponibilidad del video. */\n setAvailable = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/available',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/available]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/edit/save — guarda los metadatos de un video existente. */\n saveVideo = async (\n path: string,\n content: VideoSaveContent,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/edit/save',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/edit/discardDraft — descarta el borrador de un video. */\n discardDraft = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/edit/discardDraft',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/edit/discardDraft]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/edit/hideBanner — activa/desactiva el ocultamiento de publicidad. */\n hideBanner = async (video: VideoHideBannerInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/edit/hideBanner',\n {\n authentication: this.authentication,\n video,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/edit/hideBanner]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/edit/inline — edición inline de un video desde el listado. */\n editInline = async (video: VideoInlineInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/edit/inline',\n {\n authentication: this.authentication,\n video,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/edit/inline]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/embedded/exists — verifica si existe un video-embedded por código. */\n embeddedExists = async (\n code: string,\n ): Promise<VideoEmbeddedExistsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoEmbeddedExistsResponse>(\n '/videos/embedded/exists',\n {\n authentication: this.authentication,\n code,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/embedded/exists]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/embedded/upload — crea un nuevo video-embedded en el VFS. */\n uploadEmbedded = async (\n video: VideoEmbeddedUploadInput,\n ): Promise<VideoUploadResponse> => {\n try {\n const response = await this.props.axiosApi.post<VideoUploadResponse>(\n '/videos/embedded/upload',\n {\n authentication: this.authentication,\n video,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/embedded/upload]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/publish/check — informa el estado de publicación de una lista de videos. */\n checkPublish = async (\n videos: string[],\n ): Promise<VideosPublishCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideosPublishCheckResponse>(\n '/videos/publish/check',\n {\n authentication: this.authentication,\n videos,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/publish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/publish/now — publica inmediatamente una lista de videos. */\n publishNow = async (\n videos: string[],\n setLastModification?: boolean,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/publish/now',\n {\n authentication: this.authentication,\n videos,\n setLastModification,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/publish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/publish/republish — resetea fechas del video (requiere VIDEOS_EDIT). */\n republish = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/publish/republish',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/publish/republish]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/publish/schedule — programa la publicación de uno o más videos. */\n schedulePublish = async (videos: VideosScheduleInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/publish/schedule',\n {\n authentication: this.authentication,\n videos,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/publish/schedule]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/rudo/getThumbnails — URL del thumbnail de un video de Rudo. */\n getRudoThumbnails = async (\n rudoCode: string,\n ): Promise<VideoRudoThumbnailsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoRudoThumbnailsResponse>(\n '/videos/rudo/getThumbnails',\n {\n authentication: this.authentication,\n rudoCode,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/rudo/getThumbnails]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/unlock/check — estado de lock y recursos relacionados de un video. */\n checkUnlock = async (path: string): Promise<VideoUnlockCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoUnlockCheckResponse>(\n '/videos/unlock/check',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/unlock/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/unlock/now — desbloquea un video y sus recursos relacionados. */\n unlockNow = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/unlock/now',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/unlock/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/unlock/remove — idéntico a unlock/now (desbloqueo + cancelar programación). */\n unlockRemove = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/unlock/remove',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/unlock/remove]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/unpublish/check — relaciones de un video antes de despublicarlo. */\n checkUnpublish = async (\n path: string,\n ): Promise<VideoUnpublishCheckResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoUnpublishCheckResponse>(\n '/videos/unpublish/check',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/unpublish/check]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/unpublish/delete — elimina un video del VFS (si no tiene relaciones). */\n deleteVideo = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/unpublish/delete',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/unpublish/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /videos/unpublish/now — despublica un video (expira y publica el cambio).\n *\n * Los parámetros del video se consumen internamente por `TfsVideosAdminJson`\n * y no están determinados en el código visible; se aceptan como `extra`.\n */\n unpublishNow = async (\n extra: Record<string, unknown> = {},\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/unpublish/now',\n {\n authentication: this.authentication,\n ...extra,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/unpublish/now]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/youtube/getThumbnails — thumbnails de un video de YouTube. */\n getYoutubeThumbnails = async (\n youtubeId: string,\n ): Promise<YoutubeThumbnailsResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<YoutubeThumbnailsResponse>(\n '/videos/youtube/getThumbnails',\n {\n authentication: this.authentication,\n youtubeId,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/youtube/getThumbnails]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/youtube/upload — crea un nuevo video-youtube en el VFS. */\n uploadYoutube = async (\n video: VideoYoutubeUploadInput,\n ): Promise<VideoUploadResponse> => {\n try {\n const response = await this.props.axiosApi.post<VideoUploadResponse>(\n '/videos/youtube/upload',\n {\n authentication: this.authentication,\n video,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/youtube/upload]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/convertStatus — estado de conversión de un video nativo. */\n getConvertStatus = async (\n path: string,\n ): Promise<VideoConvertStatusResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoConvertStatusResponse>(\n '/videos/nativos/convertStatus',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/convertStatus]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/uploadS3Cancel — cancela una subida en curso hacia S3. */\n cancelUploadS3 = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/nativos/uploadS3Cancel',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/uploadS3Cancel]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/uploadS3Progress — progreso de una subida a S3 en curso. */\n getUploadS3Progress = async (\n path: string,\n ): Promise<VideoUploadProgressResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoUploadProgressResponse>(\n '/videos/nativos/uploadS3Progress',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/uploadS3Progress]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/updateVideoProcessing — actualiza metadatos de un video existente. */\n updateVideoProcessing = async (\n video: VideoUpdateProcessingInput,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/videos/nativos/updateVideoProcessing',\n {\n authentication: this.authentication,\n video,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/updateVideoProcessing]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/createVideoProcessing — crea un placeholder video-processing. */\n createVideoProcessing = async (\n videoName: string,\n moduleConfig?: string,\n ): Promise<VideoCreateProcessingResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoCreateProcessingResponse>(\n '/videos/nativos/createVideoProcessing',\n {\n authentication: this.authentication,\n videoName,\n moduleConfig,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/createVideoProcessing]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/preUploadAMZ — genera la URL prefirmada para subir un archivo a AMZ. */\n preUploadAMZ = async (\n fileName: string,\n ): Promise<VideoPreUploadAMZResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoPreUploadAMZResponse>(\n '/videos/nativos/preUploadAMZ',\n {\n authentication: this.authentication,\n fileName,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/preUploadAMZ]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/preMultiUploadAMZ — inicia una subida multiparte a AMZ y devuelve las URLs prefirmadas. */\n preMultiUploadAMZ = async (\n fileName: string,\n size: string,\n contentType: string,\n ): Promise<VideoPreMultiUploadAMZResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoPreMultiUploadAMZResponse>(\n '/videos/nativos/preMultiUploadAMZ',\n {\n authentication: this.authentication,\n fileName,\n size,\n contentType,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/preMultiUploadAMZ]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/preMultiCompleteAMZ — finaliza una subida multiparte a AMZ. */\n preMultiCompleteAMZ = async (\n vfspath: string,\n uploadId: string,\n ): Promise<VideoPreMultiCompleteAMZResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoPreMultiCompleteAMZResponse>(\n '/videos/nativos/preMultiCompleteAMZ',\n {\n authentication: this.authentication,\n vfspath,\n uploadId,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/preMultiCompleteAMZ]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/preMultiAbortAMZ — aborta una subida multiparte a AMZ en curso. */\n preMultiAbortAMZ = async (\n vfspath: string,\n uploadId: string,\n ): Promise<VideoPreMultiAbortAMZResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoPreMultiAbortAMZResponse>(\n '/videos/nativos/preMultiAbortAMZ',\n {\n authentication: this.authentication,\n vfspath,\n uploadId,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/preMultiAbortAMZ]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/preMultiResignAMZ — regenera las URLs prefirmadas de una subida multiparte a AMZ. */\n preMultiResignAMZ = async (\n vfspath: string,\n uploadId: string,\n numberOfParts: number,\n ): Promise<VideoPreMultiResignAMZResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoPreMultiResignAMZResponse>(\n '/videos/nativos/preMultiResignAMZ',\n {\n authentication: this.authentication,\n vfspath,\n uploadId,\n numberOfParts,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/preMultiResignAMZ]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /videos/nativos/converter — dispara la conversión de un video nativo (requiere VIDEOS_UPLOAD + VIDEOS_NATIVE). */\n converter = async (path: string): Promise<VideoConverterResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<VideoConverterResponse>(\n '/videos/nativos/converter',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/converter]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /videos/nativos/download — descarga el binario de un video nativo\n * (requiere VIDEOS_UPLOAD + VIDEOS_NATIVE).\n *\n * En éxito el server responde con el contenido BINARIO del video, por eso\n * se pide `responseType: 'blob'` y se retorna el `Blob`. En caso de error\n * el server devuelve un envelope JSON (`CmsResponse`), que llegará como el\n * `error` del `catch` (p. ej. en `error.response.data`).\n */\n downloadNative = async (path: string): Promise<Blob> => {\n try {\n const response = await this.props.axiosApi.post<Blob>(\n '/videos/nativos/download',\n {\n authentication: this.authentication,\n path,\n },\n {\n responseType: 'blob',\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/videos/nativos/download]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Estado posible de una trivia. */\nexport type TriviaStatus = 'inactiva' | 'abierta' | 'cerrada';\n\n/** Tipo de fecha a filtrar en POST /trivias/get (se usa junto a `from`/`to`). */\nexport type TriviasGetTypeDate = 'start' | 'close' | (string & {});\n\n/** Filtros de POST /trivias/get. */\nexport interface TriviasGetFilters {\n /** Filtrar por categoría. */\n category?: string;\n /** Filtrar por tags. */\n tags?: string;\n /** Búsqueda de texto libre en título y descripción. */\n text?: string;\n /** Índice de búsqueda a utilizar. */\n searchIndex?: string;\n /** Filtrar por estado. */\n status?: TriviaStatus;\n /** Filtrar por autor. */\n author?: string;\n /** Filtrar por modo de juego múltiple. */\n multipleGame?: string;\n /** Filtrar por almacenamiento de resultados. */\n storeResults?: string;\n /** Filtrar por requerimiento de usuario registrado. */\n registeredUser?: string;\n /** Filtrar por tipo de resultado. */\n resultType?: string;\n /** Mostrar trivias temporales. */\n showtemporal?: string;\n /** Cantidad de resultados (default: 100). */\n size?: number;\n /** Número de página (default: 1). */\n page?: number;\n /** Tipo de fecha a filtrar: \"start\" o \"close\". */\n typeDate?: TriviasGetTypeDate;\n /** Fecha inicio del rango (timestamp en ms), usado junto a `typeDate`. */\n from?: string;\n /** Fecha fin del rango (timestamp en ms), usado junto a `typeDate`. */\n to?: string;\n /** Campo de ordenamiento (default: \"modification-date\"). */\n order?: string;\n /** Dirección de orden (default: \" desc\"). */\n position?: string;\n}\n\n/** Trivia del CMS. La forma exacta depende del recurso y del formato pedido. */\nexport interface Trivia {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /trivias/get. */\nexport interface TriviasGetResponse extends CmsResponse {\n /** Colección de trivias con sus metadatos básicos. */\n trivias: Trivia[];\n total?: number;\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /trivias/read (detalle + contenido XML). */\nexport interface TriviaReadResponse extends CmsResponse {\n /** Metadatos básicos de la trivia. */\n detail?: Trivia;\n /** Contenido XML completo del recurso. */\n content?: { [key: string]: unknown };\n /** Datos del lock si el recurso está bloqueado por otro usuario. */\n isLockData?: { [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /trivias/create. */\nexport interface TriviaCreateResponse extends CmsResponse {\n /** Nombre de archivo de la trivia creada. */\n fileName?: string;\n}\n\n/** Ítem del array de trivias (sub-objeto `trivias.trivia`). */\nexport interface TriviaPathItem {\n /** Ruta VFS de la trivia. */\n path: string;\n}\n\n/** Cuerpo de la respuesta de POST /trivias/adminConfiguration. */\nexport interface TriviasAdminConfigurationResponse extends CmsResponse {\n categoryPath?: string;\n styles?: unknown;\n autoSave?: unknown;\n /** XSD del recurso (solo si se envía `path`). */\n contentDefinition?: unknown;\n /** Incluye además la lista de estados posibles (`status` de trivias). */\n [key: string]: unknown;\n}\n\n/**\n * Contenido XML editable de una trivia (POST /trivias/edit/save).\n *\n * Se serializa como objeto JSON con los campos del schema de la trivia; la\n * forma exacta depende del recurso, por eso es un tipo laxo.\n */\nexport interface TriviaSaveContent {\n /** Título de la trivia. */\n Title?: string;\n /** Estado de la trivia. */\n Status?: TriviaStatus;\n /** Tags separados por comas. */\n Tags?: string;\n [key: string]: unknown;\n}\n\n/**\n * Cuerpo de la respuesta de POST /trivias/edit/save.\n *\n * Devuelve los tags, personas y etiquetas de moderación (`UnsafeLabels`)\n * resultantes; la forma exacta depende del contenido guardado.\n */\nexport interface TriviaSaveResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/**\n * Payload de POST /trivias/edit/inline.\n *\n * El body completo es procesado por `TfsNewsAdminJson.save()`; salvo `path`\n * los campos dependen de esa implementación, por eso es un tipo laxo.\n */\nexport interface TriviaEditInlineInput {\n /** Ruta VFS de la trivia. */\n path: string;\n [key: string]: unknown;\n}\n\ninterface ITriviasServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `trivias` del CMS (core + edit/save/exit/inline).\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsTriviasServices {\n protected props: ITriviasServices;\n protected authentication: Authentication;\n\n constructor(props: ITriviasServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /trivias/get — lista paginada de trivias con filtros (Lucene). */\n getTrivias = async (\n filters: TriviasGetFilters = {},\n ): Promise<TriviasGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<TriviasGetResponse>(\n '/trivias/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/read — lee y bloquea una trivia, devolviendo su detalle y contenido. */\n readTrivia = async (path: string): Promise<TriviaReadResponse> => {\n try {\n const response = await this.props.axiosApi.post<TriviaReadResponse>(\n '/trivias/read',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/create — crea una trivia vacía y devuelve su `fileName`. */\n createTrivia = async (): Promise<TriviaCreateResponse> => {\n try {\n const response = await this.props.axiosApi.post<TriviaCreateResponse>(\n '/trivias/create',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/create]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/publish — activa (\"abierta\") y publica una trivia individual. */\n publishTrivia = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/trivias/publish',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/publish]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/publishOnly — publica una lista de trivias sin cambiar su estado. */\n publishOnlyTrivias = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const trivia: TriviaPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/trivias/publishOnly',\n {\n authentication: this.authentication,\n trivias: { trivia },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/publishOnly]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/despublish — cierra (\"cerrada\") y republica una trivia individual. */\n despublishTrivia = async (path: string): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/trivias/despublish',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/despublish]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/massive — activa y publica masivamente una lista de trivias. */\n publishMassive = async (paths: string[]): Promise<CmsResponse> => {\n try {\n const trivia: TriviaPathItem[] = paths.map((path) => ({ path }));\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/trivias/massive',\n {\n authentication: this.authentication,\n trivias: { trivia },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/massive]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /trivias/adminConfiguration — configuración del módulo de trivias.\n *\n * Si se envía `path`, la respuesta incluye `contentDefinition` (XSD del recurso).\n */\n getAdminConfiguration = async (\n path?: string,\n ): Promise<TriviasAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<TriviasAdminConfigurationResponse>(\n '/trivias/adminConfiguration',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/edit/save — guarda el contenido XML de una trivia. */\n saveTrivia = async (\n path: string,\n content: TriviaSaveContent,\n ): Promise<TriviaSaveResponse> => {\n try {\n const response = await this.props.axiosApi.post<TriviaSaveResponse>(\n '/trivias/edit/save',\n {\n authentication: this.authentication,\n path,\n content,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/edit/save]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /trivias/edit/exit — desbloquea la trivia y cancela el modo de edición.\n *\n * Si existe un draft temporal, solo lo descarta cuando `discardDraft` es `true`.\n */\n exitEdit = async (\n path: string,\n discardDraft?: boolean,\n ): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/trivias/edit/exit',\n {\n authentication: this.authentication,\n path,\n discardDraft,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/edit/exit]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /trivias/edit/inline — guarda cambios inline (delegado a TfsNewsAdminJson). */\n editInline = async (data: TriviaEditInlineInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/trivias/edit/inline',\n {\n authentication: this.authentication,\n ...data,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/trivias/edit/inline]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/**\n * Cuerpo de la respuesta de POST /transcribe/get.\n *\n * Si el recurso es una transcripción válida, devuelve el texto y los códigos de\n * idioma; si la transcripción falló es de tipo error/unknown; en cualquier otro\n * estado se marca `incomplete: true`. La forma exacta de los campos depende del\n * estado del recurso, por eso es un tipo laxo.\n */\nexport interface TranscriptionGetResponse extends CmsResponse {\n /** `true` si la transcripción aún no está completa. */\n incomplete?: boolean;\n [key: string]: unknown;\n}\n\ninterface ITranscribeServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `transcribe` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n *\n * Nota: solo se incluye `transcribe/get` (POST JSON con `authentication`). Los\n * endpoints `transcribe/transcribeCallback` (sin autenticación, callback externo)\n * y `transcribe/uploadAMZ` (multipart/form-data, token en Base64 por query/form)\n * no encajan en este molde y quedan fuera del servicio.\n */\nexport class CmsTranscribeServices {\n protected props: ITranscribeServices;\n protected authentication: Authentication;\n\n constructor(props: ITranscribeServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /transcribe/get — lee el contenido de un archivo de transcripción del VFS. */\n getTranscription = async (\n path: string,\n ): Promise<TranscriptionGetResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<TranscriptionGetResponse>(\n '/transcribe/get',\n {\n authentication: this.authentication,\n path,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/transcribe/get]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type { CmsResponse } from './users';\n\n/** Tipo de términos a buscar/gestionar. */\nexport type TagTermsKind =\n | 'claves'\n | 'ingredientes'\n | 'personas'\n | (string & {});\n\n/** Estado de aprobación de un término: 1=aprobado, 0=desaprobado. */\nexport type TagApproved = 0 | 1;\n\n/** Término/tag del CMS. La forma exacta depende del tipo y del endpoint. */\nexport interface Tag {\n id?: number;\n id_term?: number;\n name?: string;\n type?: number;\n approved?: number;\n synonymous?: string;\n [key: string]: unknown;\n}\n\n/** Filtros de POST /tags/get. */\nexport interface TagsGetFilters {\n /** Tipo de términos: \"claves\" (default) o \"ingredientes\". */\n tipoTerminos?: TagTermsKind;\n /** Texto a buscar (default: \"\"). */\n text?: string;\n /** Si es `true`, activa el modo gestor (búsqueda avanzada). */\n gestor?: boolean;\n /** Tipo de noticia para determinar el tipo de término (default: \"news\"). */\n newsType?: string;\n /** ID numérico del tipo de término (solo modo gestor). */\n type?: number;\n /** Estado: 1=aprobado, 0=desaprobado, -1=todos (default: -1, solo gestor). */\n status?: number;\n /** Fecha de inicio en ms (timestamp unix, solo gestor). */\n from?: string;\n /** Fecha de fin en ms (timestamp unix, solo gestor). */\n to?: string;\n /** Cantidad máxima de resultados (solo gestor). */\n size?: number;\n /** Letra o prefijo inicial para filtrar (solo gestor). */\n startWith?: string;\n}\n\n/** Cuerpo de la respuesta de POST /tags/get. */\nexport interface TagsGetResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Filtros de POST /tags/getInNews. */\nexport interface TagsGetInNewsFilters {\n /** Tipo de términos: \"claves\" (default), \"ingredientes\" o \"personas\". */\n tipoTerminos?: TagTermsKind;\n /** Texto a buscar (obligatorio). */\n text: string;\n /** Tipo de noticia para determinar el tipo de término (default: \"news\"). */\n newsType?: string;\n}\n\n/** Cuerpo de la respuesta de POST /tags/getInNews. */\nexport interface TagsGetInNewsResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Filtros de POST /tags/isExist. */\nexport interface TagsIsExistFilters {\n /** Nombre del término a buscar (default: \"\"). */\n text?: string;\n /** ID numérico del tipo de término; si se omite usa el de la publicación. */\n type?: string;\n /** Filtro por estado: -1=todos (default). */\n status?: number;\n /** Fecha de inicio en ms (timestamp unix). */\n from?: string;\n /** Fecha de fin en ms (timestamp unix). */\n to?: string;\n /** Máximo de resultados (default: 100). */\n size?: number;\n}\n\n/** Cuerpo de la respuesta de POST /tags/isExist. */\nexport interface TagsIsExistResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /tags/read (detalle del término + sinónimos). */\nexport interface TagReadResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /tags/types (tipos de términos configurados). */\nexport interface TagsTypesResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /tags/adminConfiguration. */\nexport interface TagsAdminConfigurationResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\n/** Payload `tag` de POST /tags/add. */\nexport interface TagAddInput {\n /** Nombre del término. */\n name: string;\n /** ID del tipo de término (0 es inválido). */\n type: number;\n /** Estado de aprobación: 1=aprobado, 0=desaprobado. */\n approved: TagApproved;\n /** Ruta VFS de la imagen asociada (se publica si se envía). */\n image?: string;\n /** Sinónimos del término. */\n synonymous?: string;\n /** Otros campos del modelo Terms que se mapean automáticamente. */\n [key: string]: unknown;\n}\n\n/** Cuerpo de la respuesta de POST /tags/add. */\nexport interface TagAddResponse extends CmsResponse {\n /** ID del término creado (o existente, en modo inNews). */\n id?: number;\n [key: string]: unknown;\n}\n\n/** Payload `tag` de POST /tags/update. */\nexport interface TagUpdateInput {\n /** ID del término a actualizar. */\n id_term: number;\n /** Nombre del término. */\n name: string;\n /** ID del tipo de término. */\n type: number;\n /** Estado de aprobación: 1=aprobado, 0=desaprobado. */\n approved: TagApproved;\n /** Ruta VFS de la imagen asociada (se publica si se envía). */\n image?: string;\n /** Sinónimos del término. */\n synonymous?: string;\n /** Otros campos del modelo Terms que se mapean automáticamente. */\n [key: string]: unknown;\n}\n\n/**\n * Payload `tag` de POST /tags/delete.\n *\n * Usar `id` para borrar uno solo o `ids` para borrar en batch (`ids` tiene\n * precedencia). `type` es siempre obligatorio.\n */\nexport interface TagDeleteInput {\n /** ID del término a eliminar (borrado individual). */\n id?: string;\n /** Lista de IDs a eliminar en batch (precede a `id`). */\n ids?: number[];\n /** ID del tipo de término (requerido). */\n type: string;\n}\n\n/**\n * Payload `tag` de POST /tags/changeStatus.\n *\n * Usar `id` para cambiar uno solo o `ids` para batch (`ids` tiene precedencia).\n */\nexport interface TagChangeStatusInput {\n /** Nuevo estado: \"1\"=aprobar, \"0\"=desaprobar. */\n status: string;\n /** ID del tipo de término. */\n type: string;\n /** ID del término a modificar (cambio individual). */\n id?: string;\n /** Lista de IDs a modificar en batch (precede a `id`). */\n ids?: number[];\n}\n\n/** Cuerpo de la respuesta de POST /tags/changeStatus (términos actualizados). */\nexport interface TagChangeStatusResponse extends CmsResponse {\n [key: string]: unknown;\n}\n\ninterface ITagsServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\n/**\n * Servicios HTTP del módulo `tags` del CMS.\n *\n * Se construye igual que `CmsCommonServices`, con `{ axiosApi, authentication }`.\n */\nexport class CmsTagsServices {\n protected props: ITagsServices;\n protected authentication: Authentication;\n\n constructor(props: ITagsServices) {\n this.props = props;\n this.authentication = props.authentication;\n }\n\n /** POST /tags/get — busca y lista términos por texto (modo gestor o sugerencia). */\n getTags = async (filters: TagsGetFilters = {}): Promise<TagsGetResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagsGetResponse>(\n '/tags/get',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/get]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/getInNews — busca términos para autocompletar en edición de noticias. */\n getTagsInNews = async (\n filters: TagsGetInNewsFilters,\n ): Promise<TagsGetInNewsResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagsGetInNewsResponse>(\n '/tags/getInNews',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/getInNews]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/isExist — verifica si existe un término por nombre exacto y tipo. */\n isExist = async (\n filters: TagsIsExistFilters = {},\n ): Promise<TagsIsExistResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagsIsExistResponse>(\n '/tags/isExist',\n {\n authentication: this.authentication,\n filters,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/isExist]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/read — detalle completo de un término por ID y tipo (con sinónimos). */\n readTag = async (\n idTerm?: string | number,\n type?: string | number,\n ): Promise<TagReadResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagReadResponse>(\n '/tags/read',\n {\n authentication: this.authentication,\n tag: { id_term: idTerm, type },\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/read]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/types — tipos de términos configurados para la publicación. */\n getTypes = async (): Promise<TagsTypesResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagsTypesResponse>(\n '/tags/types',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/types]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/adminConfiguration — configuración de tags para el panel de admin. */\n getAdminConfiguration =\n async (): Promise<TagsAdminConfigurationResponse> => {\n try {\n const response =\n await this.props.axiosApi.post<TagsAdminConfigurationResponse>(\n '/tags/adminConfiguration',\n {\n authentication: this.authentication,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/adminConfiguration]', error);\n return Promise.reject(error);\n }\n };\n\n /**\n * POST /tags/add — crea un nuevo término.\n *\n * @param tag Datos del término a crear.\n * @param url URL de origen; si contiene `/new_post/` activa el modo \"inNews\"\n * (permisos reducidos). Viaja dentro del objeto `authentication`.\n */\n addTag = async (tag: TagAddInput, url?: string): Promise<TagAddResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagAddResponse>(\n '/tags/add',\n {\n authentication: url\n ? { ...this.authentication, url }\n : this.authentication,\n tag,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/add]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/update — actualiza un término existente. */\n updateTag = async (tag: TagUpdateInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/tags/update',\n {\n authentication: this.authentication,\n tag,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/update]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/delete — elimina uno o varios términos por ID (requiere `type`). */\n deleteTags = async (tag: TagDeleteInput): Promise<CmsResponse> => {\n try {\n const response = await this.props.axiosApi.post<CmsResponse>(\n '/tags/delete',\n {\n authentication: this.authentication,\n tag,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/delete]', error);\n return Promise.reject(error);\n }\n };\n\n /** POST /tags/changeStatus — aprueba/desaprueba uno o varios términos. */\n changeStatus = async (\n tag: TagChangeStatusInput,\n ): Promise<TagChangeStatusResponse> => {\n try {\n const response = await this.props.axiosApi.post<TagChangeStatusResponse>(\n '/tags/changeStatus',\n {\n authentication: this.authentication,\n tag,\n },\n );\n return response.data;\n } catch (error: any) {\n console.error('[/tags/changeStatus]', error);\n return Promise.reject(error);\n }\n };\n}\n","import type { AxiosInstance } from 'axios';\n\nimport type { Authentication } from '../types/authentication';\nimport type {\n CountNotificationsResponse,\n NotificationsListResponse,\n} from '../types/notification';\nimport type { ProfileGetResponse } from '../types/profile';\nimport type { SiteSection } from '../types/site';\nimport type { Publication } from './publication';\nimport type { SitesAndPublicationsResult } from './site';\n\nimport { filterModulesByPermissions } from '../utils/permissions';\nimport { CmsAuthServices } from './auth';\nimport { CmsDashboardServices } from './dashboard';\nimport { CmsProfileServices } from './profile';\nimport { CmsPublicationsServices } from './publication';\nimport { CmsSitesServices } from './site';\n\nexport { CmsAuthLoginServices } from './authLogin';\nexport type {\n AuthLoginResponse,\n AuthLoginValidResponse,\n AuthPasswordConfigurationResponse,\n AuthSessionResult,\n AuthSetNewPasswordResponse,\n TwoFactorGenerateCodeInput,\n TwoFactorGenerateCodeResponse,\n TwoFactorMethod,\n TwoFactorSendCodeInput,\n TwoFactorSendCodeResponse,\n TwoFactorSendMethod,\n TwoFactorVerifyInput,\n TwoFactorVerifyResponse,\n} from './authLogin';\n\nexport { CmsUploadServices } from './upload';\nexport type { UploadFields, UploadItem, UploadResponse } from './upload';\n\nexport { CmsPreviewServices } from './preview';\nexport type { CkeditorPreviewParams, CkeditorPreviewView } from './preview';\n\nexport { CmsAudiosServices } from './audios';\nexport type {\n Audio,\n AudiosAdminConfigurationResponse,\n AudiosGetFilters,\n AudiosGetResponse,\n} from './audios';\n\nexport { CmsAuthServices } from './auth';\nexport type {\n AuthChangePasswordResponse,\n AuthCreateResponse,\n AuthLogoutResponse,\n AuthPermissionsResponse,\n AuthReloginResponse,\n AuthSessionData,\n AuthSessionInfo,\n} from './auth';\n\nexport { CmsCategoriesServices } from './categories';\nexport type {\n CategoriesGetFilter,\n CategoriesGetResponse,\n CategoriesRefactorFilter,\n CategoriesRefactorResponse,\n CategoriesTestFilter,\n CategoriesTestResponse,\n Category,\n} from './categories';\n\nexport { CmsCkeditorServices } from './ckeditor';\nexport type {\n CkeditorAdminConfigurationResponse,\n CkeditorAssistanceAIInput,\n CkeditorAssistanceAINewInput,\n CkeditorAssistanceResponse,\n CkeditorAudioCodeInput,\n CkeditorAudioCodeResponse,\n CkeditorParams,\n CkeditorPrompt,\n} from './ckeditor';\n\nexport { CmsCopilotServices } from './copilot';\nexport type {\n CopilotAction,\n CopilotActionData,\n CopilotActionInput,\n CopilotActionResponse,\n CopilotOpportunitiesFilters,\n CopilotOpportunitiesResponse,\n CopilotOpportunity,\n CopilotOpportunityStatus,\n CopilotSnoozeResponse,\n} from './copilot';\n\nexport { CmsCommentsServices } from './comments';\nexport type {\n Comment,\n CommentEvent,\n CommentEventsGetResponse,\n CommentHighlightInput,\n CommentModerationInput,\n CommentReason,\n CommentReasonsGetResponse,\n CommentReasonsTestResponse,\n CommentRejectInput,\n CommentsAdminConfigurationResponse,\n CommentsGetFilters,\n CommentsGetResponse,\n CommentUrlFriendly,\n CommentUserGetResponse,\n DictionaryAddInput,\n DictionaryChangeTypeInput,\n DictionaryGetFilters,\n DictionaryGetResponse,\n DictionaryWord,\n DictionaryWordType,\n} from './comments';\n\nexport { CmsContributionsServices } from './contributions';\nexport type {\n ContributionEditInput,\n ContributionEditResponse,\n ContributionsGetFilters,\n ContributionsGetResponse,\n ContributionsInsertCrmResponse,\n PaymentGatewaysGetFilters,\n PaymentGatewaysGetResponse,\n SubscriptionsGetFilters,\n SubscriptionsGetResponse,\n} from './contributions';\n\nexport { CmsDashboardServices } from './dashboard';\nexport type {\n DashboardCopilotOpportunity,\n DashboardCountNotificationsResponse,\n DashboardExpireTask,\n DashboardNewsTask,\n DashboardNotificationsResponse,\n DashboardUnassignTask,\n DashboardVideoNotification,\n} from './dashboard';\n\nexport { CmsPublicationsServices } from './publication';\nexport type {\n Publication,\n PublicationDefaultResponse,\n PublicationPermissions,\n PublicationsGetResponse,\n PublicationUpdateAdmin,\n PublicationZoneConfig,\n} from './publication';\n\nexport { CmsSitesServices } from './site';\nexport type {\n ModulesAvailableResponse,\n Site,\n SitesAndPublicationsResult,\n SitesGetResponse,\n} from './site';\n\nexport { CmsSectionsServices } from './sections';\nexport type {\n Section,\n SectionDeleteInput,\n SectionInput,\n SectionsGetResponse,\n} from './sections';\n\nexport { CmsProductivityPlanServices } from './productivityPlan';\nexport type {\n ProductivityPlan,\n ProductivityPlanAdminConfigurationResponse,\n ProductivityPlanComplianceBackupInput,\n ProductivityPlanComplianceDetailFilters,\n ProductivityPlanComplianceDetailResponse,\n ProductivityPlanComplianceInput,\n ProductivityPlanComplianceResponse,\n ProductivityPlanComplianceV2Data,\n ProductivityPlanComplianceV2Input,\n ProductivityPlanComplianceV2Response,\n ProductivityPlanCreateResponse,\n ProductivityPlanException,\n ProductivityPlanExceptionCreateResponse,\n ProductivityPlanExceptionReason,\n ProductivityPlanExceptionReasonCreateResponse,\n ProductivityPlanExceptionReasonsGetFilters,\n ProductivityPlanExceptionReasonsGetResponse,\n ProductivityPlanExceptionReasonUpdateResponse,\n ProductivityPlanExceptionsGetFilters,\n ProductivityPlanExceptionsGetResponse,\n ProductivityPlanFrequencyFilters,\n ProductivityPlanFrequencyReportsResponse,\n ProductivityPlanMetricsResponse,\n ProductivityPlanReadResponse,\n ProductivityPlanReviewResponse,\n ProductivityPlanReviewrDetailResponse,\n ProductivityPlanRol,\n ProductivityPlanRolsPlansGetResponse,\n ProductivityPlanSaveContent,\n ProductivityPlanType,\n ProductivityPlanUser,\n ProductivityPlanUsersPlansGetResponse,\n ProductivityPlansGetFilters,\n ProductivityPlansGetResponse,\n} from './productivityPlan';\n\nexport { CmsEventsServices } from './events';\nexport type {\n CmsEvent,\n EventCreateResponse,\n EventsGetFilters,\n EventsGetResponse,\n} from './events';\n\nexport { CmsFileExplorerServices } from './fileExplorer';\nexport type {\n ExplorerFile,\n ExplorerFolder,\n FileExplorerGetFilesResponse,\n FileExplorerGetFoldersResponse,\n} from './fileExplorer';\n\nexport { CmsGeneralServices } from './general';\n\nexport { CmsImagesServices } from './images';\nexport type {\n ImageComparationItem,\n ImageComparationPair,\n ImageComparationResponse,\n Image,\n ImageFocalPoint,\n ImageGalleryItem,\n ImageGalleryResponse,\n ImageInlineInput,\n ImageReadResponse,\n ImageSaveContent,\n ImageSaveOptions,\n ImageSetFocalPointResponse,\n ImageUnlockCheckResponse,\n ImageUnlockValidResponse,\n ImageUnpublishCheckAction,\n ImageUnpublishCheckResponse,\n ImageUnpublishNowResponse,\n ImageUploadMethod,\n ImagesAdminConfigurationResponse,\n ImagesFieldsFormat,\n ImagesGetFilters,\n ImagesGetResponse,\n ImagesPublishCheckResponse,\n} from './images';\n\nexport { CmsNewsServices } from './news';\nexport type {\n NewsEditInlineItem,\n NewsHideBannerItem,\n NewsRefactorFilters,\n NewsCheckInput,\n NewsIaCreateContent,\n NewsIaPreviewInput,\n NewsEditSaveResponse,\n NewsAnalizeResponse,\n NewsAnalizeAIResponse,\n NewsSummaryIAResponse,\n NewsAdminConfigurationResponse,\n NewsFieldsDefaultResponse,\n NewsAuthorConfigurationResponse,\n NewsVersionsGetResponse,\n NewsVersionRecoveryResponse,\n NewsRefactorGetResponse,\n NewsCheckResponse,\n NewsIaCreateResponse,\n NewsIaPreviewResponse,\n NewsSearchConsoleInspectionResponse,\n NewsAISummaryResponse,\n NewsAnalyticsFilters,\n NewsAnalyticsGetResponse,\n NewsCopyItem,\n NewsCreateResponse,\n NewsExportResponse,\n NewsFreshness,\n NewsFreshnessGetFilters,\n NewsFreshnessGetResponse,\n NewsMassiveCheckResponse,\n NewsMassiveEditItem,\n NewsPathItem,\n NewsPinAddResponse,\n NewsPinsGetResponse,\n NewsPreviewFormatsResponse,\n NewsPublishCheckResponse,\n NewsPublishItem,\n NewsPublishOptions,\n NewsReadPageInput,\n NewsReadPageResponse,\n NewsReadResponse,\n NewsRelatedElementsQuery,\n NewsRelatedElementsResponse,\n NewsTranslateAction,\n NewsTranslateInput,\n NewsTypesResponse,\n NewsUnpublishCheckResponse,\n NewsViewsGetResponse,\n} from './news';\n\nexport { CmsNotificationServices } from './notification';\nexport type {\n NotificationAdminConfigurationResponse,\n NotificationConfigTopic,\n NotificationPushInput,\n NotificationPushType,\n NotificationSendType,\n NotificationTopic,\n NotificationTopicsResponse,\n} from './notification';\n\nexport { CmsPeopleServices } from './people';\nexport type {\n PeopleAdminConfigurationResponse,\n PeopleApprovalState,\n PeopleFieldsFormat,\n PeopleGetFilters,\n PeopleGetResponse,\n PeopleIsExistResponse,\n Person,\n PersonInput,\n PersonType,\n PersonUpdateInput,\n} from './people';\n\nexport { CmsPlanningServices } from './planning';\nexport type {\n PlanningActivitiesGetResponse,\n PlanningActivity,\n PlanningActivityCopyResponse,\n PlanningActivityCreateInput,\n PlanningActivityCreateResponse,\n PlanningActivityGetFilters,\n PlanningActivityMonthType,\n PlanningActivityRecurrence,\n PlanningActivityRepeatType,\n PlanningActivityUpdateInput,\n} from './planning';\n\nexport { CmsPollsServices } from './polls';\nexport type {\n Poll,\n PollCreateResponse,\n PollPathItem,\n PollReadResponse,\n PollReviewResponse,\n PollSaveContent,\n PollSaveResponse,\n PollUnpublishResponse,\n PollsAdminConfigurationResponse,\n PollsFieldsFormat,\n PollsGetFilters,\n PollsGetResponse,\n PollsGetTypeDate,\n PollsPublishCheckResponse,\n} from './polls';\n\nexport { CmsProfileServices } from './profile';\nexport type {\n ProfileAdditionalInfoValue,\n ProfileModuleAlertHideResponse,\n ProfileModuleAlertsResponse,\n ProfileOtcResponse,\n ProfilePinAddResponse,\n ProfilePinsGetResponse,\n ProfileUpdateConfig,\n ProfileUpdateData,\n ProfileUpdateInput,\n} from './profile';\n\nexport { CmsRecipesServices } from './recipes';\nexport type {\n Recipe,\n RecipeAnalysisResponse,\n RecipeAuthorConfigurationResponse,\n RecipeCreateResponse,\n RecipeEditInlineInput,\n RecipeEditMassiveInput,\n RecipeFieldsDefaultResponse,\n RecipePathItem,\n RecipeSaveContent,\n RecipeSaveResponse,\n RecipesAdminConfigurationResponse,\n RecipesGetFilters,\n RecipesGetResponse,\n RecipesPreviewFormatsResponse,\n RecipesPublishCheckResponse,\n} from './recipes';\n\nexport { CmsUsersServices } from './users';\nexport type {\n CmsResponse,\n CmsUser,\n PublicationScope,\n UserGroup,\n UserGroupsResponse,\n UserPin,\n UserPinAddResponse,\n UserPinDeleteInput,\n UserPinsGetResponse,\n UserStatus,\n UserStatusAction,\n UsersAdvanceFilter,\n UsersFieldsFormat,\n UsersGetFilters,\n UsersGetResponse,\n UsersPublicationFieldsFormat,\n UsersPublicationFilters,\n UsersPublicationResponse,\n} from './users';\n\nexport { CmsZonesServices } from './zones';\nexport type {\n Zone,\n ZoneAddInput,\n ZoneAddResponse,\n ZonesFieldsFormat,\n ZonesGetFilters,\n ZonesGetResponse,\n ZoneUpdateInput,\n} from './zones';\n\nexport { CmsWorkpaperServices } from './workpaper';\nexport type {\n WorkpaperCheckResponse,\n WorkpaperCheckState,\n WorkpaperEdition,\n WorkpaperEditionStatus,\n WorkpaperLoginResponse,\n WorkpaperStatusResponse,\n} from './workpaper';\n\nexport { CmsVodsServices } from './vods';\nexport type {\n Vod,\n VodCreateResponse,\n VodsGetFilters,\n VodsGetResponse,\n VodsTypesResponse,\n VodType,\n} from './vods';\n\nexport { CmsVideosServices } from './videos';\nexport type {\n VideoPreUploadAMZResponse,\n VideoPreMultiUploadAMZResponse,\n VideoPreMultiCompleteAMZResponse,\n VideoPreMultiAbortAMZResponse,\n VideoPreMultiResignAMZResponse,\n VideoConverterResponse,\n Video,\n VideoConvertStatus,\n VideoConvertStatusResponse,\n VideoCreateProcessingResponse,\n VideoDetailResponse,\n VideoEmbeddedExistsResponse,\n VideoEmbeddedUploadInput,\n VideoHideBannerInput,\n VideoInlineInput,\n VideoRudoThumbnailsResponse,\n VideoSaveContent,\n VideoScheduleItem,\n VideoType,\n VideoUnlockCheckResponse,\n VideoUnpublishCheckResponse,\n VideoUpdateProcessingInput,\n VideoUploadProgressResponse,\n VideoUploadResponse,\n VideoYoutubeUploadInput,\n VideosAdminConfigurationResponse,\n VideosGetFilters,\n VideosGetOrder,\n VideosGetResponse,\n VideosPublishCheckResponse,\n VideosScheduleInput,\n YoutubeThumbnailsResponse,\n} from './videos';\n\nexport { CmsTriviasServices } from './trivias';\nexport type {\n Trivia,\n TriviaCreateResponse,\n TriviaEditInlineInput,\n TriviaPathItem,\n TriviaReadResponse,\n TriviaSaveContent,\n TriviaSaveResponse,\n TriviaStatus,\n TriviasAdminConfigurationResponse,\n TriviasGetFilters,\n TriviasGetResponse,\n TriviasGetTypeDate,\n} from './trivias';\n\nexport { CmsTranscribeServices } from './transcribe';\nexport type { TranscriptionGetResponse } from './transcribe';\n\nexport { CmsTagsServices } from './tags';\nexport type {\n Tag,\n TagAddInput,\n TagAddResponse,\n TagApproved,\n TagChangeStatusInput,\n TagChangeStatusResponse,\n TagDeleteInput,\n TagReadResponse,\n TagTermsKind,\n TagUpdateInput,\n TagsAdminConfigurationResponse,\n TagsGetFilters,\n TagsGetInNewsFilters,\n TagsGetInNewsResponse,\n TagsGetResponse,\n TagsIsExistFilters,\n TagsIsExistResponse,\n TagsTypesResponse,\n} from './tags';\n\ninterface ICommonServices {\n axiosApi: AxiosInstance;\n authentication: Authentication;\n}\n\nexport class CmsCommonServices {\n protected props: ICommonServices;\n protected authentication: Authentication;\n\n protected publications: CmsPublicationsServices;\n protected profileServices: CmsProfileServices;\n protected dashboard: CmsDashboardServices;\n protected sites: CmsSitesServices;\n protected auth: CmsAuthServices;\n\n constructor(props: ICommonServices) {\n this.props = props;\n this.authentication = props.authentication;\n this.publications = new CmsPublicationsServices(props);\n this.profileServices = new CmsProfileServices(props);\n this.dashboard = new CmsDashboardServices(props);\n this.sites = new CmsSitesServices(props);\n this.auth = new CmsAuthServices(props);\n }\n\n /** POST /publications/default — delega en `CmsPublicationsServices`. */\n getDefaultPublication = (): Promise<Publication> =>\n this.publications.getDefaultPublication();\n\n /** POST /profile/get — delega en `CmsProfileServices`. */\n getProfile = (): Promise<ProfileGetResponse> =>\n this.profileServices.getProfile();\n\n /**\n * POST /dashboard/countNotifications — delega en `CmsDashboardServices`.\n * Mantiene el tipo legacy `CountNotificationsResponse` por compatibilidad.\n */\n getCountNotifications = async (): Promise<CountNotificationsResponse> =>\n (await this.dashboard.countNotifications()) as unknown as CountNotificationsResponse;\n\n /**\n * POST /dashboard/notification — delega en `CmsDashboardServices`.\n * Mantiene el tipo legacy `NotificationsListResponse` por compatibilidad.\n */\n getNotifications = async (): Promise<NotificationsListResponse> =>\n (await this.dashboard.getNotifications()) as unknown as NotificationsListResponse;\n\n /**\n * Combina sitios, publicaciones y módulos disponibles en un único resultado.\n * Reusa los servicios dedicados (`sites`, `publications`, `auth`).\n */\n getSitesAndPublications = async (): Promise<SitesAndPublicationsResult> => {\n // No se traga el error: si sites/publications/modules fallan, se propaga\n // para que el host pueda mostrar feedback (toast) y decidir el fallback.\n // /auth/permissions es la excepción: se pide con `.catch` para no derribar\n // el layout entero si falla. Si no llega, no se filtra el menú (degrada a la\n // visibilidad de modulesAvailable); el guard de ruta sigue protegiendo el\n // acceso real. Ver `filterModulesByPermissions`.\n const [sitesRes, publicationsRes, modulesRes, permissionsRes] =\n await Promise.all([\n this.sites.getSites(),\n this.publications.getPublications(),\n this.auth.getModulesAvailable(),\n this.auth.getPermissions().catch(() => null),\n ]);\n\n const sites: SiteSection[] = sitesRes.sites.map((site) => ({\n title: site.title,\n publications: publicationsRes.publications.filter(\n (publication) => publication.site === site.name,\n ),\n }));\n\n return {\n sites: sites.filter((site) => site.publications.length > 0),\n // Réplica de cmsmedios: los módulos se cruzan con las operaciones `_VIEW`\n // (o `isAdmin`) del usuario antes de armar el menú.\n modules: filterModulesByPermissions(modulesRes.modules, permissionsRes),\n };\n };\n}\n"],"mappings":"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AW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CAEX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,YACE;CACF,YAAY;CACZ,YAAY;CACZ,YAAY;CACZ,YAAY;CAEZ,eACE;CACF,eAAe;CACf,mBAAmB;CACnB,cAAc;AAChB,GCjGa,IAAyC;CACpD,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CAEX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,YACE;CACF,YAAY;CACZ,YAAY;CACZ,YAAY;CACZ,YAAY;CAEZ,eACE;CACF,eAAe;CACf,mBAAmB;CACnB,cAAc;AAChB,GC9Ga,IAAyC;CACpD,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WACE;CACF,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CAEX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;CACX,YACE;CACF,YAAY;CACZ,YAAY;CACZ,YAAY;CACZ,YAAY;CAEZ,eACE;CACF,eAAe;CACf,mBAAmB;CACnB,cAAc;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"}
|