Skip to content

Latest commit

 

History

History
108 lines (71 loc) · 10.2 KB

File metadata and controls

108 lines (71 loc) · 10.2 KB

Frontend

This project was generated using Angular CLI version 21.2.11.

How to run

From frontend/ (repository root → cd frontend):

npm install
npm start

npm start runs ng serve. Open http://localhost:4200/; the app reloads when you change source files.

Design tokens: UI colors, typography (Inter), spacing, and component cues align with design/DESIGN.md; global CSS variables live in src/styles/_design-tokens.scss. The Stitch UI reference mocks live in design/stitch_chateando_ui_redesign/ (applied to the Angular templates via SCSS + Material Symbols, without Tailwind).

If the Angular CLI is on your PATH, you can use ng serve instead of npm start. The backend API is expected at the URLs configured in your Angular environment files; for local full-stack work, run the .NET API (for example https://localhost:7118) alongside this app.

Language (English / Spanish)

The header includes an EN | ES control. The default locale is English; your choice is stored in localStorage under hc_locale (en or es) and applied on the next visit without rebuilding. DevExtreme widgets and formatted times follow the active locale. User-written chat text and API error bodies are not translated.

When running via Docker, rebuild images after i18n or UI changes so the container serves the latest assets:

docker compose up --build

The admin app on :4201 uses the same mechanism (see admin/README.md).

Notifications (in-app + desktop)

  • Notifications tab (/notifications) lists server-backed notification history (messages, buzz, @mentions, announcements) with read/unread state and a nav badge.
  • Notify when available (client sync): the API persists inbox rows in the database; live delivery uses SignalR once. ConnectivitySyncService (started from authGuard after ensureSession, not inside it) pulls missed notifications on login, hub reconnect, and browser online via NotificationsInboxService.syncFromServer() (GET /api/notifications + unread count). Scenario A (logged in but offline): badge and liveItems refresh when connectivity returns. Scenario B (logged out then login): full fetch on first guarded route without catch-up toasts for backlog. Open chat threads can append missed messages after reconnect (ChatState.catchUpOpenConversation).
  • Desktop toasts (Windows Action Center via Edge/Chrome): use the bell icon in the header to enable push. Requires browser permission; persisted as hc_push_enabled in localStorage.
  • Web Push (offline): when you are not connected to SignalR, the API can send VAPID push via public/sw.js. Configure backend WebPush:PublicKey, WebPush:PrivateKey, and WebPush:Subject (see root .env.example). Generate keys: npx web-push generate-vapid-keys. HTTPS or localhost is required for push subscription.
  • Sidebar DM/group unread badges (LocalReadStateService) are separate from the notifications inbox and from server read receipts (checkmarks on your outgoing bubbles).
  • Read receipts: grey/blue done_all on your sent messages (DM + groups, including BUZZ); click for readers + times (GET /api/chat/messages/{id}/readers). Server cursor sync is debounced in ChatThreadReadSyncService via ChatState (POST /api/chat/mark-read + inbox mark-read) — not injected into LocalReadStateService (avoids circular DI). Live updates: SignalR ConversationReadUpdated (ignores events for your own userId in groups). Loading older pages does not advance the server cursor. Tooltip/README: read time is cursor readAtUtc, not per-message delivery time.

After changing sw.js or notification APIs: docker compose up --build.

Source layout

  • src/app/shared/auth-session/ — Cross-cutting pieces used by multiple features: access token storage, the HTTP Authorization interceptor, and route guards (auth, guest). authGuard calls AuthenticatedSessionBootstrapService.ensureSession() then ConnectivitySyncService.ensureStarted(userId) (non-blocking).
  • src/app/shared/connectivity/ConnectivitySyncService: debounced inbox sync on reconnect/online; coordinates with NotificationsInboxService and optional chat tail catch-up.
  • src/app/shared/session/ChatSessionSyncService (providedIn: 'root') keeps groups and people directory in sync for the whole login session via SignalR: GroupMembershipChanged, GroupUpdated, and DirectoryChanged (admin user/department changes and public register). Started from ChatUnreadRealtimeService; survives leaving /chat. ChatState and AnnouncementsState mirror its signals; chat-only hub handlers (presence, reactions, buzz) stay in ChatState and are cleared with offUiHandlers() on leave.
  • src/app/shared/read-state/Local unread counters (per signed-in user, localStorage key chateando_read_state_v1:{userId}): DM watermarks (dm:{peerUserId}), group watermarks (group:{conversationId}), and read announcement IDs. ChatUnreadRealtimeService (providedIn: 'root') keeps a single SignalR connection for MessageReceived so badges update even on /announcements. Sidebar badges on People, Groups, and Announcements (cap 99+); app nav shows an announcements total. Opening a DM/group marks that thread read; visiting /announcements marks all items in the loaded feed as read; your own messages and announcements never increment counts. Bootstrap on login refetches group history for all groups and DM history only for peers with a prior watermark (max 30 peers).
  • src/app/features/chat/ — Chat UI (/chat): fixed profile block at the top of the sidebar (avatar, name, @username; links to /profile). Announcements feed in the sidebar (shared AnnouncementsFeedService, REST list + AnnouncementPublished in real time; View all/announcements to publish). People (DM by peerUserId) and Groups (multi-user rooms). Sidebar lists directory and groups (live via ChatSessionSyncService); New group creates a room (optional initial members). Outgoing messages show read checkmarks; MessageReadersPopupComponent lists who read (sender-only API). ChatThreadReadSyncService orchestrates server mark-read when viewing a thread. Senders can delete their own messages (not BUZZ); DELETE /api/chat/messages/{id} removes DB row and file; peers receive MessageDeleted on SignalR. Thread anchors with replies cannot be deleted.
  • src/app/features/profile/ — Read-only profile page (/profile, GET /api/auth/me): name, username, email, phone, department, photo URL, optional Admin badge. Same app shell and top nav as Chat and Announcements. Group header opens a Members panel (add/remove only for the creator). REST + SignalR: DM uses SendMessage; groups use SendGroupMessage(conversationId, body); membership and directory updates are pushed session-wide (see ChatSessionSyncService). Same multipart upload/download flow as DM. Buzz in DM: send with Ctrl+G or the header button; persists a red BUZZ message in the thread and shakes the recipient's chat area for ~2s (SendBuzz → message + BuzzReceived). Presence (PresenceSnapshot / PresenceChanged, client Heartbeat every 60s) applies to the people list.
  • src/app/features/announcements/ — Announcements UI (/announcements) and shared AnnouncementsFeedService (also used in the chat sidebar). Choose audience (all / department / selected people), title, optional message and/or file attachment, then publish via multipart POST. List shows only announcements you receive; Download uses blob fetch + fileUrl from the API (same pattern as chat file downloads). Real time: AnnouncementPublished (recipients only). Top navigation: Chat | Announcements.
  • src/app/shared/ui/app-nav/ — Shared header links (announcements link shows unread badge when total > 0) and sign-out (disconnects SignalR via SessionLogoutService, clears in-memory read state).
  • src/app/features/<name>/ — Feature slices. Each feature groups its logic in one place with three layers:
    • services/ — HTTP clients and API types (e.g. auth and departments under features/auth/services/).
    • state/ — Injectable page/session state (signals, orchestration, validation messaging) scoped to a route where appropriate.
    • ui/ — Standalone route components, templates, and styles.

Code scaffolding

Angular CLI includes powerful code scaffolding tools. To generate a new component, run:

ng generate component component-name

For a complete list of available schematics (such as components, directives, or pipes), run:

ng generate --help

Building

To build the project run:

ng build

This will compile your project and store the build artifacts in the dist/ directory. By default, the production build optimizes your application for performance and speed.

Running unit tests

To execute unit tests with the Vitest test runner, use the following command:

ng test

Test file layout

  • Spec files live under test/app/, mirroring src/app/ (same subfolders and file names with .spec.ts).
  • tsconfig.spec.json maps @app/* to src/app/* and @environments/* to src/environments/* so specs import production code without deep relative paths.
  • Because the Angular project sourceRoot is src, angular.json uses include: ["../test/**/*.spec.ts"] so the unit-test builder discovers specs next to src/.

Running end-to-end tests

For end-to-end (e2e) testing, run:

ng e2e

Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.

Additional Resources

For more information on using the Angular CLI, including detailed command references, visit the Angular CLI Overview and Command Reference page.