Skip to main content

Estado global con NgRx

core/states/app.state.ts registra ocho slices en StoreModule.forRoot(ROOT_REDUCERS) y sus efectos en EffectsModule.forRoot(ROOT_EFFECTS). Cada slice vive en core/states/<slice>/ con *.actions.ts, *.reducers.ts, *.effects.ts y *.selectors.ts.

Clave de AppStateCarpetaContenido
themestates/themeTema light-only / dark-only; persiste en localStorage (clave Theme); por defecto light-only
languagestates/languageIdioma activo (es / en)
authstates/authuser, message, loading; sesión y login
ticketsstates/ticketLista de tickets, paginación, filtro activo
departmentsstates/departmentsDepartamentos (CRUD)
internalChatstates/internal-chatConversaciones, agentes, miembros y mensajes del chat interno
scheduledMessagesstates/scheduled-messageMensajes programados (mis envíos, por ticket)
settingsstates/settingsAjustes del tenant (TenantSettings)

auth​

UserActions (auth.actions.ts) cubre: loadUserSession, userAuthenticationRequest/Success/Failure, frameAuthenticateRequest, preAuthenticateUser, preAuthenticationSuccess, userLogout y completeUserLogout. Los efectos (auth.effects.ts):

  • loadUserSession$: lee USER_SESSION del storage cifrado; si hay token llama a getMeUser() (GET /users/get-me) y emite userAuthenticationSuccess; si falla, limpia la sesión.
  • loginUser$: POST /auth/login, guarda { token }, consulta get-me, guarda el usuario completo y navega a /whaticket/chat.
  • frameLogin$: POST /auth/frame-login para el modo iframe (ver Frame); en error navega a /auth/reconnect.
  • logoutUser$: AuthService.logout() (borra la sesión y navega a login).

Selectores relevantes: selectUser, selectUserId, selectLoading, selectErrorMessage y selectScheduledMessagesEnabled, que lee user.featureFlags.scheduledMessagesEnabled del perfil (get-me) y es false hasta que carga el usuario; no depende del slice settings, que requiere permiso SETTINGS_READ.

language​

Al terminar la autenticación (userAuthenticationSuccess), LanguageEffects.tenantAuthenticatedLanguage$ aplica user.tenantPreferences.language si es es o en; en otro caso es. Ver i18n y tema.

tickets​

Es el slice más grande: 54 acciones en ticket.actions.ts. Estado (TicketState):

{ tickets, totalCount, currentPage, hasMore, isLoading,
isInitialLoad, isLoadingMore, error, activeFilter }

Familias de acciones:

FamiliaAcciones
CargaloadTickets, loadMoreTickets, resetTickets (y Success/Failure)
Acciones de agenteresolveTicket, resolveNoFarewellTicket, returnTicket, unassignTicket, transferTicket, postponeTicket, cancelPostponeTicket, deleteTicket, changeTicketStatus, markUnread
Bloqueo ("Mantener conmigo")lockTicket, unlockTicket, ticketLockChangedFromSocket, ticketLockConflict
Desde socketticketUpdatedFromSocket, ticketAssignedFromSocket, ticketStatusChangedFromSocket, ticketReactivatedFromSocket, ticketDeletedFromSocket, contactPresenceChangedFromSocket
No leídos / acuseticketIncrementUnread, ticketClearUnread, ticketLastMessageAckChanged

Los efectos (ticket.effects.ts) llaman a TicketService (/tickets/...) para cada acción y despachan las acciones Success / Failure correspondientes. Los eventos de socket se vuelcan al store directamente desde ChatSocketService (ver Sockets).

Cambios de la rama feat/meta_connections en este slice​

  • ticketUpdatedFromSocket incorpora messageId? y ack?; el reducer los copia en lastMessage (_id y ack) cuando vienen.
  • Nueva acción ticketLastMessageAckChanged({ ticketId, messageIds, ack }): el reducer actualiza lastMessage.ack solo si el _id del último mensaje está en messageIds. Se despacha desde ChatListComponent en cada message_ack_changed, lo que permite que la lista pinte el estado failed del último mensaje (ver Estado failed).

internalChat, scheduledMessages, settings, departments​

  • internalChat: loadConversations, loadAgents, loadMembers, loadMessages, loadMoreMessages, resetMessages, leaveConversation, altas/bajas de miembros. Se carga al entrar al layout autenticado.
  • scheduledMessages: loadMine, loadByTicket, create, cancel, reset.
  • settings: loadSettings / loadSettingsSuccess / loadSettingsFailure; el comentario de settings.actions.ts indica que se creó porque no existía un slice de ajustes del tenant (la página de settings los pedía por HTTP).
  • departments: CRUD con Load, Create, Update, Delete y sus Success / Failure.

Qué no está en NgRx​

Conexiones, contactos, usuarios, etiquetas, respuestas rápidas, roles/permisos y dashboard se consultan por HTTP desde sus tablas o servicios, sin slice. El estado de la sesión de WhatsApp de una conexión se mantiene en el componente ConnectionsTableComponent a partir del socket (ver Conexiones Meta).