Pipes compartidos
src/app/shared/pipes/ contiene 13 archivos: 12 pipes y una directiva (lowercase.pipe.ts, ver más abajo). Visión general del módulo en Compartido; directivas en Directivas.
:::caution Solo dos están declarados
SharedModule declara y exporta TruncatePipe y WhatsappMarkupPipe. Los demás (y LowercasePipe) no pertenecen a ningún NgModule ni son standalone, y ningún template los usa. Varios devuelven claves de traducción que habría que pasar por el pipe translate.
:::
Tabla de pipes
| Nombre en plantilla | Clase | Archivo | Entrada y salida | Declarado | Usado |
|---|---|---|---|---|---|
truncate | TruncatePipe | truncate.pipe.ts | string o null o undefined, maxLength = 100 a string | si | si |
whatsappMarkup | WhatsappMarkupPipe | whatsapp-markup.pipe.ts | string o null o undefined a HTML string | si | si |
sanitizeHtml | SanitizeHtmlPipe | sanitize-html.pipe.ts | string a SafeHtml | no | no |
statusToActiveInactive | StatusToActiveInactivePipe | active-descative.pipe.ts | number a clave words.active o words.inactive | no | no |
booleanToActiveInactive | BooleanToActiveInactivePipe | boolean-to-active-inactive.pipe.ts | boolean a clave words.active o words.inactive | no | no |
booleanToYesNo | BooleanToYesNoPipe | boolean-to-yes-no.pipe.ts | boolean a clave words.yes o words.no | no | no |
genderToLabel | GenderToLabelPipe | gender.pipe.ts | string a clave words.male, words.female o words.notDefined | no | no |
statusMessage | StatusMessagePipe | status-message.pipe.ts | clave de MESSAGE_STATE a clave i18n | no | no |
socialNetworkBadge | SocialNetworkBadgePipe | social-network-badge.pipe.ts | string a clases CSS de badge | no | no |
clientEnvironment | BuildClientEnvironmentPipe | build-client-environment.pipe.ts | fila con clientHints a texto de navegador, plataforma y dispositivo | no | no |
cashdeskType | CashdeskTypePipe | cashdesk-type.pipe.ts | enum CASHDESK_TYPE a clave i18n | no | no |
cashdeskCommisionType | CashdeskCommisionTypePipe | cashdesk-commision-type.pipe.ts | enum CASHDESK_COMMISION_TYPE a clave i18n | no | no |
Los 12 pipes son puros (valor por defecto de @Pipe).
truncate
transform(value: string | null | undefined, maxLength: number = 100): string
- Valor falso (
null,undefined,'') devuelve''. - Si
value.length <= maxLengthdevuelve el texto tal cual. - Si no, devuelve
value.slice(0, maxLength) + '…'(carácter único…, no tres puntos). maxLength = 0produce solo….
Uso real, encadenado con whatsappMarkup en la tabla de respuestas rápidas (quick-responses-table.component.html):
<span class="small" [innerHTML]="value | truncate: 25 | whatsappMarkup"></span>
Spec: truncate.pipe.spec.ts (8 casos: nulos, vacío, texto corto, longitud exacta, truncado con …, valor por defecto 100 y maxLength 0). Es el único pipe con spec.
Gotcha: al truncar antes del marcado puede cortarse una pareja *negrita* y el asterisco se mostrará literal.
whatsappMarkup
transform(value: string | null | undefined): string
Llama a renderWhatsappMarkup(value) (ver Compartido) y reemplaza los saltos de línea \n por <br>. renderWhatsappMarkup escapa &, < y > antes de aplicar el formato (*negrita*, _cursiva_, ~tachado~), de modo que el resultado es seguro para [innerHTML] (Angular además lo sanea).
Este pipe no activa la opción { linkify: true } de la rama feat/meta_connections; los enlaces clicables solo los produce ChatConversationComponent.renderMessageMarkup.
Dónde se usa (3 plantillas): labels-table.component.html (descripción de la etiqueta, (value | whatsappMarkup) || '—'), quick-responses-table.component.html (con truncate) y chat-labels-bar.component.html (label.description | whatsappMarkup).
Sin spec propio.
sanitizeHtml
DomSanitizer.bypassSecurityTrustHtml(content). Desactiva el saneado de Angular: cualquier HTML que reciba se inyecta tal cual. Ninguna plantilla lo usa; el código con necesidades similares llama a SanitizationService.sanitizeHtml (core/services/ui/sanitization.service.ts) desde chat-conversation.component.ts y chat-list.component.ts. Evita usarlo con texto controlado por usuarios.
Pipes de etiquetas y estados
Devuelven claves de traducción, no texto:
| Pipe | Lógica exacta |
|---|---|
statusToActiveInactive | value === 1 da words.active; cualquier otro (incluido true o '1') da words.inactive |
booleanToActiveInactive | valor verdadero da words.active; si no, words.inactive |
booleanToYesNo | valor verdadero da words.yes; si no, words.no |
genderToLabel | busca value en GENDER_OPTIONS (male, female, notDefined) y devuelve su label; si no encuentra, words.notDefined |
statusMessage | MESSAGE_STATE[value] (0 a players.messages.sentTo, 2 a players.messages.read, 3 a players.messages.unread); si no existe, words.notDefined. Vienen del dominio de mensajería de jugadores heredado, no del estado de mensajes del chat |
socialNetworkBadge | value.toLowerCase(): facebook, instagram, youtube, tiktok devuelven badge bg-<nombre>; cualquier otra devuelve badge bg-default. value nulo lanza error |
Ejemplo de uso previsto (la salida iría a translate o a [class]):
<span [class]="network | socialNetworkBadge">{{ network }}</span>
<span>{{ user.isActive | booleanToActiveInactive | translate }}</span>
clientEnvironment
transform(row: any): string. Lee row.clientHints; sin él devuelve '—'. Construye Navegador N · Plataforma · Dispositivo:
- Navegador: busca en
secChUa(en minúsculas), por este orden,microsoft edge,brave,google chrome,opera,chromium; extrae la versión mayor con la regex"<Nombre>";v="(\d+)". Sin coincidencia,Unknown. - Plataforma:
clientHints.secChUaPlatformoUnknown. - Dispositivo:
MobilesisecChUaMobile === trueo'?1', si noDesktop.
Constantes en core/helpers/ui/ui.constant.ts (AVAILABLE_BROWSERS, BROWSERS_VERSION, TECHNOLOGICAL_PLATFORM). El orden importa: los navegadores basados en Chromium (Edge, Brave, Opera) incluyen también "Chromium" en Sec-CH-UA, por eso se comprueban antes que el genérico.
Restos de otro dominio
cashdeskType y cashdeskCommisionType convierten los enums CASHDESK_TYPE y CASHDESK_COMMISION_TYPE (core/helpers/global/betshop-management.constant.ts) en la clave betshopManagement.cashdesks.<clave en minúsculas>, o devuelven el valor original si no se encuentra. Pertenecen al producto de apuestas de origen del frontend, igual que statusMessage y parte de las interfaces de core/interfaces/api (betshop, casino, player...). No tienen relación con el CRM.
LowercasePipe (directiva appLowercase)
Archivo lowercase.pipe.ts, pero es una @Directive({ selector: '[appLowercase]' }) que implementa ControlValueAccessor (provee NG_VALUE_ACCESSOR con forwardRef). Convierte a minúsculas lo que se escribe y el valor que llega del modelo:
writeValue:String(value).toLowerCase()(o'').input: pone el valor en minúsculas en el elemento y llama aonChangecon el valor transformado.blurllama aonTouched;setDisabledStatedeshabilita elinput.
<input appLowercase formControlName="email" />
Al ser un ControlValueAccessor reemplaza al DefaultValueAccessor; no usarla junto a otro accessor en el mismo elemento. No está declarada ni usada, y su nombre es engañoso (no es un pipe).