@indesad/feedback-widget 0.0.0-stage → 1.1.1

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/README.md CHANGED
@@ -1,3 +1,93 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # @indesad/feedback-widget
2
+
3
+ Botón de **opiniones de producto** para cualquier aplicación web: la persona reporta un problema, sugiere una mejora, hace una pregunta o felicita, y la opinión llega a la bandeja **Opiniones** de IndeFlow con folio, seguimiento y respuesta por correo en su idioma.
4
+
5
+ - Sin dependencias. Vive en un Shadow DOM: no hereda ni rompe los estilos de la app.
6
+ - Claro y oscuro: en los productos Indesad toma los tokens `--if-*` de la app (y su modo oscuro `html.dark`); en otras apps usa su paleta y sigue `data-theme`, la clase `dark` o `prefers-color-scheme`.
7
+ - Español, inglés y portugués (`locale: 'auto'` usa el del navegador).
8
+ - Si IndeFlow no responde, el botón no aparece y la app sigue igual.
9
+ - Una opinión **no es un caso de soporte**: si la app tiene soporte, `supportUrl` agrega el enlace «Necesito ayuda».
10
+
11
+ ## 1. Activar opiniones en IndeFlow
12
+
13
+ Proyecto → Observabilidad → fuente de la app → pestaña **Opiniones**: activar, agregar los orígenes desde los que se usará (por ejemplo `https://app.cliente.cl`) y copiar el código. La clave es el mismo token de la fuente (`if_obs_...`); al activar opiniones recibe el permiso `ingest:feedback`. Es pública por naturaleza (va en el navegador): solo sirve para enviar opiniones desde los orígenes permitidos.
14
+
15
+ ## 2a. Script listo para pegar (cualquier web)
16
+
17
+ ```html
18
+ <script src="https://admin.indeflow.app/downloads/sdk/indeflow-feedback-1.1.1.js"
19
+ data-api="https://api.indeflow.app/api"
20
+ data-token="if_obs_prod_..."
21
+ data-locale="auto"></script>
22
+ ```
23
+
24
+ Con la persona que ya inició sesión en tu app (recomendado):
25
+
26
+ ```html
27
+ <script src="https://admin.indeflow.app/downloads/sdk/indeflow-feedback-1.1.1.js"></script>
28
+ <script>
29
+ const feedback = IndeFlowFeedback.init({
30
+ apiUrl: 'https://api.indeflow.app/api',
31
+ sourceToken: 'if_obs_prod_...',
32
+ user: { name: 'Ana Pérez', email: 'ana@cliente.cl', company: 'Cliente S.A.', externalUserId: '42' },
33
+ locale: 'auto', theme: 'auto', supportUrl: '/soporte'
34
+ });
35
+ // Al cerrar sesión: feedback.setUser(null)
36
+ </script>
37
+ ```
38
+
39
+ ## 2b. Angular (o React, Vue…)
40
+
41
+ ```bash
42
+ npm install @indesad/feedback-widget@1.1.1
43
+ ```
44
+
45
+ ```ts
46
+ import { createIndeFlowFeedback, IndeFlowFeedbackController } from '@indesad/feedback-widget';
47
+
48
+ @Injectable({ providedIn: 'root' })
49
+ export class FeedbackWidgetService {
50
+ private widget?: IndeFlowFeedbackController;
51
+ start(user: { name: string; email: string; company?: string; id: string }) {
52
+ this.widget ??= createIndeFlowFeedback({
53
+ apiUrl: environment.indeflowApi, sourceToken: environment.indeflowFeedbackToken,
54
+ user: { name: user.name, email: user.email, company: user.company, externalUserId: user.id },
55
+ locale: 'auto', theme: 'auto', brandLabel: 'InDeLedger'
56
+ });
57
+ }
58
+ stop() { this.widget?.destroy(); this.widget = undefined; }
59
+ }
60
+ ```
61
+
62
+ ## Configuración
63
+
64
+ | Opción | Por defecto | Qué hace |
65
+ |---|---|---|
66
+ | `apiUrl`, `sourceToken` | — | Obligatorias. |
67
+ | `user` | — | `{ name, email, company, externalUserId }` de la sesión. Sin `user`, el formulario pide nombre y correo (si la fuente admite anónimos). La identidad la declara la app; IndeFlow no la verifica. |
68
+ | `locale` | `'auto'` | `es-419`, `en`, `pt-BR` o `auto`. También define el idioma de los correos al reportante. |
69
+ | `theme`, `themeSelector` | `'auto'` | `light`, `dark` o `auto`. `themeSelector` (por ejemplo `'[data-mode="night"]'`) indica cuándo la app está en oscuro. |
70
+ | `colors` | tokens `--if-*` | `accent`, `accentContrast`, `background`, `surface`, `text`, `muted`, `border`, `danger`, `success`, `radius`, `font`. |
71
+ | `brandLabel`, `title` | los de la fuente | Nombre de la app arriba del panel y título. |
72
+ | `position`, `offset` | `bottom-right`, 20 px | Lugar del botón; `offset` para no tapar otros botones flotantes. |
73
+ | `launcher` | `'bubble'` | `'none'` oculta el botón: abre el panel con `open()` desde tu menú. |
74
+ | `launcherLabel`, `launcherIcon`, `launcherIconType` | «Opiniones» | Texto e icono (`emoji`, `image`, `svg`). |
75
+ | `kinds` | los de la fuente | Subconjunto de `bug`, `improvement`, `question`, `praise`. |
76
+ | `supportUrl`, `supportLabel` | — | Enlace «Necesito ayuda» hacia tu soporte. |
77
+ | `screenshot` | `true` | Permite adjuntar hasta 5 imágenes PNG, JPG o WebP de hasta 5 MB cada una (también pegadas con Ctrl+V). |
78
+ | `context`, `appVersion`, `collectRoute` | — / — / `true` | Datos fijos del envío (máx. 20 claves, sin secretos), versión y ruta actual (sin parámetros). |
79
+ | `zIndex`, `showPoweredBy` | `2147483000`, `true` | Capa y pie «Con tecnología de IndeFlow». |
80
+ | `onSubmitted`, `onError` | — | Callbacks con `{ folio, trackingUrl }` o `{ code, message }`. |
81
+
82
+ Controlador: `open(kind?)`, `close()`, `toggle()`, `setUser(user)`, `setContext(ctx)`, `update(config)`, `destroy()` y `ready` (promesa: `false` si quedó desactivado).
83
+
84
+ ## Qué se envía
85
+
86
+ Tipo, mensaje, idioma, la identidad declarada, la URL **sin parámetros ni fragmento**, la ruta, versión, navegador, tamaño de pantalla, tema y el `context` que pongas. El servidor descarta claves de `context` que parezcan secretos (`token`, `password`, `apiKey`…), guarda la IP solo como huella y exige un desafío anti-robots por envío. Nunca se leen cookies, almacenamiento ni el contenido de la página.
87
+
88
+ ## Desarrollo
89
+
90
+ ```bash
91
+ cd packages/web/feedback-widget && npm test # jsdom + fetch simulado
92
+ node scripts/build-feedback-widget.mjs # genera las descargas en frontend/IndeFlow.Admin/public/downloads/sdk
93
+ ```
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import type { FeedbackKind, FeedbackLocale } from './types';
2
+ type Copy = {
3
+ launcher: string;
4
+ title: string;
5
+ subtitle: string;
6
+ close: string;
7
+ back: string;
8
+ kinds: Record<FeedbackKind, {
9
+ label: string;
10
+ hint: string;
11
+ placeholder: string;
12
+ }>;
13
+ needHelp: string;
14
+ message: string;
15
+ name: string;
16
+ email: string;
17
+ emailOptional: string;
18
+ sendingAs: string;
19
+ attach: string;
20
+ attachMore: string;
21
+ attachHint: string;
22
+ remove: string;
23
+ send: string;
24
+ sending: string;
25
+ privacy: string;
26
+ successTitle: string;
27
+ successBody: string;
28
+ successEmail: string;
29
+ viewStatus: string;
30
+ another: string;
31
+ errorGeneric: string;
32
+ errorMessage: string;
33
+ errorName: string;
34
+ errorEmail: string;
35
+ errorAttachmentType: string;
36
+ errorAttachmentSize: string;
37
+ errorAttachmentCount: string;
38
+ poweredBy: string;
39
+ counter: string;
40
+ };
41
+ export declare const COPY: Record<FeedbackLocale, Copy>;
42
+ export declare function resolveLocale(requested?: string | null, fallback?: string | null): FeedbackLocale;
43
+ export declare function format(text: string, values: Record<string, string | number>): string;
44
+ export {};
@@ -0,0 +1,4 @@
1
+ export { createIndeFlowFeedback, IndeFlowFeedbackWidget, VERSION } from './widget';
2
+ export { sha256Hex, solveChallenge } from './sha256';
3
+ export { COPY, resolveLocale } from './i18n';
4
+ export type { FeedbackKind, FeedbackLocale, FeedbackTheme, FeedbackUser, IndeFlowFeedbackConfig, IndeFlowFeedbackController, RemoteConfig } from './types';