akveo/ngx-admin
May 5, 2026
Application: ngx-admin Document Title: Architecture Overview Date: May 2026
This document is organized to serve multiple audiences. Use the guide below to navigate to the sections most relevant to your role.
| Stakeholder | Recommended Reading |
|---|---|
| Executives and project managers | Section 4: Executive Summary, Section 5: Stakeholders & Concerns, Section 13: Quality Attributes, Section 14: Risks & Technical Debt |
| Developers joining the team | Section 4: Executive Summary, Section 7: Solution Strategy, Section 8: Building Block View, Section 9: Runtime View, Section 10: Data Flow & State Management, Section 15: Glossary |
| Architects evaluating the system | All sections |
| QA engineers and testers | Section 9: Runtime View, Section 11: Cross-Cutting Concerns, Section 13: Quality Attributes, Section 14: Risks & Technical Debt |
| Security reviewers | Section 11: Cross-Cutting Concerns (specifically 11.2 and 11.8), Section 14: Risks & Technical Debt |
| DevOps and infrastructure engineers | Section 6: System Context, Section 7: Solution Strategy, Section 14: Risks & Technical Debt |
ngx-admin is an Angular-based administrative dashboard application that serves as both a functional dashboard and a comprehensive UI component showcase. The application provides two primary value propositions: a set of operational dashboard screens (IoT device monitoring, e-commerce analytics, energy consumption tracking, and media playback) and an extensive library of interactive demonstrations covering forms, charts, maps, modal overlays, tables, and UI component variants. The application is built on the open-source Nebular design system by Akveo and is publicly available as a reference implementation and starter template for Angular-based enterprise dashboards.
The primary users of this application are developers and technical teams who use it as a starting point for building Angular dashboards, as well as end users of any application derived from this template. The application targets a broad range of screen sizes and supports four distinct visual themes (Default, Dark, Cosmic, and Corporate), with all UI components adapting dynamically to the active theme at runtime.
The technical approach is a single-page application (SPA) built with Angular 15, using the Nebular component library for UI primitives, Apache ECharts and Chart.js for data visualization, and Leaflet and Google Maps for geographic features. The application is organized into feature modules grouped by domain (dashboard, e-commerce, forms, charts, maps, tables, modal overlays, extra components, editors, and UI features), each accessible via Angular's lazy-loaded routing. Data is provided through an abstract service layer that decouples the UI from its data sources, enabling the application to run with mock data while remaining structurally ready for real backend integration.
The most significant architectural characteristics are: (1) a pervasive reactive theming system where every chart, map, and UI component subscribes to NbThemeService and re-renders when the theme changes; (2) an abstract data service pattern where all data-fetching contracts are defined as abstract Angular classes, with concrete implementations injected at the module level; (3) a consistent use of shell components with <router-outlet> for feature grouping, enabling clean lazy loading boundaries; and (4) a heavy reliance on static and mock data throughout the demonstration screens, with no live backend integration visible in the assessed code.
This Architecture Overview covers 100 screens of the ngx-admin application. The screens and routes assessed are: Earning Card (/e-commerce/earning-card), D3 (/charts/d3), Chartjs (/charts/chartjs), Tiny Mce (/@theme/components/tiny-mce), Dashboard (/dashboard), Charts (/charts), Footer (/@theme/components/footer), Search Input (/@theme/components/search-input), Header (/@theme/components/header), Echarts (/charts/echarts), Temperature Dragger (/dashboard/temperature/temperature-dragger), Solar (/dashboard/solar), E Commerce (/e-commerce), Status Card (/dashboard/status-card), Chart Panel Summary (/e-commerce/charts-panel/chart-panel-summary), Country Orders (/e-commerce/country-orders), Room Selector (/dashboard/rooms/room-selector), Traffic (/dashboard/traffic), Weather (/dashboard/weather), Chart Panel Header (/e-commerce/charts-panel/chart-panel-header), Contacts (/dashboard/contacts), Rooms (/dashboard/rooms), Player (/dashboard/rooms/player), Chart (/e-commerce/country-orders/chart), Electricity Chart (/dashboard/electricity/electricity-chart), Kitten (/dashboard/kitten), Temperature (/dashboard/temperature), Ckeditor (/editors/ckeditor), User Activity (/e-commerce/user-activity), Front Side (/e-commerce/profit-card/front-side), Visitors Analytics (/e-commerce/visitors-analytics), Slide Out (/e-commerce/slide-out), Traffic Cards Header (/e-commerce/traffic-reveal-card/traffic-cards-header), Traffic Bar (/e-commerce/traffic-reveal-card/front-side/traffic-bar), Back Side (/e-commerce/traffic-reveal-card/back-side), Front Side (/e-commerce/traffic-reveal-card/front-side), Progress Section (/e-commerce/progress-section), Back Side (/e-commerce/profit-card/back-side), Form Layouts (/forms/form-layouts), Spinner Sizes (/extra-components/spinner/spinner-sizes), Progress Bar (/extra-components/progress-bar), Spinner (/extra-components/spinner), Interactive Progress Bar (/extra-components/progress-bar/interactive-progress-bar), Buttons (/forms/buttons), Spinner Color (/extra-components/spinner/spinner-color), Spinner In Buttons (/extra-components/spinner/spinner-in-buttons), Forms (/forms), Spinner In Tabs (/extra-components/spinner/spinner-in-tabs), Datepicker (/forms/datepicker), Maps (/maps), Bubble (/maps/bubble), Form Inputs (/forms/form-inputs), Dialog Name Prompt (/modal-overlays/dialog/dialog-name-prompt), Window (/modal-overlays/window), Window Form (/modal-overlays/window/window-form), Smart Table (/tables/smart-table), Toastr (/modal-overlays/toastr), Tooltip (/modal-overlays/tooltip), Grid (/ui-features/grid), Ui Features (/ui-features), Tables (/tables), Showcase Dialog (/modal-overlays/dialog/showcase-dialog), Search Map (/maps/search-map), Icons (/ui-features/icons), Pages (/pages), Tree Grid (/tables/tree-grid), Popovers (/modal-overlays/popovers), Typography (/ui-features/typography), Charts Panel (/e-commerce/charts-panel), Extra Components (/extra-components), Visitors Analytics Chart (/e-commerce/visitors-analytics/visitors-analytics-chart), Electricity (/dashboard/electricity), Map (/e-commerce/country-orders/map), Security Cameras (/dashboard/security-cameras), Nebular Select (/extra-components/form-inputs/nebular-select), Charts (/e-commerce/charts-panel/charts), Modal Overlays (/modal-overlays), Back Side (/e-commerce/earning-card/back-side), Legend Chart (/e-commerce/legend-chart), Alert (/extra-components/alert), Traffic Reveal Card (/e-commerce/traffic-reveal-card), Map (/maps/search-map/map), Front Side (/e-commerce/earning-card/front-side), Calendar (/extra-components/calendar), Calendar Kit (/extra-components/calendar-kit), Visitors Statistics (/e-commerce/visitors-analytics/visitors-statistics), Miscellaneous (/miscellaneous), Profit Card (/e-commerce/profit-card), Search (/maps/search-map/search), Editors (/editors), Chat (/extra-components/chat), Search Fields (/ui-features/search-fields), Tiny Mce (/editors/tiny-mce), Day Cell (/extra-components/calendar/day-cell), Leaflet (/maps/leaflet), Month Cell (/extra-components/calendar-kit/month-cell), Not Found (/miscellaneous/not-found), Form Inputs (/extra-components/form-inputs), Dialog (/modal-overlays/dialog), and Gmaps (/maps/gmaps).
Components, patterns, and features not included in the assessed documentation are outside the scope of this document.
Generated by Inkwell Forge — automated codebase documentation analysis. Subject matter expert review is recommended before distribution.
| Stakeholder | Role | Key Concerns |
|---|---|---|
| End Users / Dashboard Operators | Users of derived applications built on ngx-admin | Responsiveness, theme consistency, data accuracy, real-time updates |
| Frontend Developers | Engineers building features on top of this template | Component reusability, data service contracts, routing structure, theming API |
| Technical Leads / Architects | Engineers evaluating or extending the architecture | Scalability of the abstract service pattern, consistency of patterns, technical debt |
| Engineering Managers | Overseeing delivery and quality | Risk areas, maintainability, test coverage, dependency health |
| Security Reviewers | Assessing the application's security posture | Authentication enforcement, XSS risks from rich-text editors, API key exposure |
| DevOps / Infrastructure Engineers | Deploying and operating the application | Build configuration, environment variable management, CDN dependencies |
The following quality goals are derived from patterns consistently observed across the 100 assessed screens:
Theme Consistency — Every visual component must adapt to the active Nebular theme at runtime. This is the most pervasively enforced quality goal in the codebase, evidenced by NbThemeService subscriptions in virtually every chart, map, and widget component.
Component Reusability — The application is structured as a showcase and starter template; components must be self-contained, accept @Input() data, and emit @Output() events rather than coupling to global state.
Separation of Data and Presentation — The abstract service pattern (e.g., SolarData, UserData, ElectricityData) enforces that UI components are decoupled from their data sources, enabling mock-to-real backend substitution without component changes.
Maintainability — Consistent use of shell components, feature module grouping, and the Nebular component library reduces the surface area for custom code and makes the codebase navigable.
Responsiveness — Multiple screens subscribe to NbMediaBreakpointsService and NbThemeService.onMediaQueryChange() to adapt layouts and component sizes to the active viewport breakpoint.
The ngx-admin application is a client-side single-page application that runs entirely in the browser. The system boundary encompasses the Angular application bundle, the Nebular component library, and all feature modules. Outside the boundary are: the browser's native APIs (Geolocation, HTMLAudioElement), third-party CDN-hosted libraries (CKEditor, TinyMCE), external map tile providers (OpenStreetMap, Google Maps), external media CDNs (Spotify preview URLs), and any backend data services that would be connected via the abstract service layer in a production deployment.
[Diagram: System Context — show the ngx-admin Angular SPA as a central box; connect it to: Browser Native APIs (Geolocation, HTMLAudioElement), OpenStreetMap Tile CDN, Google Maps JavaScript API, CKEditor CDN (cdn.ckeditor.com), Spotify CDN (p.scdn.co), Backend Data Services (abstract — not implemented in assessed code), and the user's browser as the runtime host]
| External System | Direction | Protocol | Purpose |
|---|---|---|---|
OpenStreetMap Tile CDN (tile.openstreetmap.org) |
Outbound | HTTP GET | Fetches map tile images for Leaflet map rendering |
| Google Maps JavaScript API | Outbound | HTTPS (SDK) | Renders Google Maps and provides Places Autocomplete for address search |
CKEditor CDN (cdn.ckeditor.com/4.6.2/full-all/) |
Outbound | HTTPS GET | Loads CKEditor 4 editor assets (JS, CSS, plugins, skins) |
TinyMCE (global tinymce object) |
Outbound | Static asset | Loads TinyMCE skin CSS from assets/skins/lightgray |
Spotify CDN (p.scdn.co) |
Outbound | HTTPS GET | Streams MP3 audio preview files for the Player widget |
Akveo Attribution Link (akveo.page.link) |
Outbound | HTTPS | Firebase Dynamic Link in the Footer component |
Application Static Assets (assets/) |
Inbound | HTTP GET | Serves world.json GeoJSON, countries.geo.json, map assets, and cover images |
| Backend Data Services (abstract) | Outbound | Not specified | Concrete implementations of abstract data services (e.g., SolarData, UserData, ElectricityData) would connect to real backends; currently backed by mock/in-memory providers |
| Browser Geolocation API | Inbound | Browser API | Provides device latitude/longitude for the Search Map screen |
| Browser HTMLAudioElement | Inbound | Browser API | Streams audio from Spotify CDN URLs for the Player widget |
The following technology choices are directly evidenced in package.json and the screen documentation:
| Layer | Technology | Version | Notes |
|---|---|---|---|
| Framework | Angular | 15.2.x | Core SPA framework; uses NgModules, not standalone components |
| Language | TypeScript | ~4.9.5 | Compiled to ES2022 target |
| UI Component Library | Nebular (@nebular/theme) |
11.0.1 | Primary component library; provides layout, cards, menus, forms, overlays, icons |
| Charting (primary) | Apache ECharts via ngx-echarts |
4.9.0 / 4.2.2 | Used for area charts, bar charts, pie charts, donut charts, stacked area charts, and maps |
| Charting (secondary) | Chart.js via angular2-chartjs |
2.7.1 / 0.4.1 | Used for horizontal bar chart demonstrations |
| Charting (tertiary) | @swimlane/ngx-charts |
14.0.0 | Used for advanced pie chart (D3-based) |
| Mapping | Leaflet via @asymmetrik/ngx-leaflet |
1.2.0 / 3.0.1 | Interactive map with GeoJSON country layers |
| Mapping | @angular/google-maps |
12.2.13 | Google Maps integration |
| Data Grid | ng2-smart-table |
1.6.0 | CRUD-capable data table with in-memory LocalDataSource |
| Rich Text Editor | CKEditor 4 via ng2-ckeditor |
4.7.3 / 1.2.9 | Loaded from CDN |
| Rich Text Editor | TinyMCE 4 | 4.5.7 | Loaded as global script; skin from local assets |
| Reactive Programming | RxJS | 6.6.2 | Observable streams, operators, subscription management |
| CSS Preprocessor | SCSS (node-sass) | 4.14.1 | Component-scoped and global styles |
| Authentication | @nebular/auth |
11.0.1 | Present as a dependency; not directly observed in assessed screens |
| Security | @nebular/security |
11.0.1 | Present as a dependency; not directly observed in assessed screens |
| Linting | ESLint with @angular-eslint |
15.2.1 | Enforces ngx prefix for component selectors |
| Testing | Karma + Jasmine | 6.3.x / 3.6.x | Unit test runner |
| E2E Testing | Protractor | 7.0.0 | End-to-end test runner |
| Documentation | Compodoc | 1.0.1 | API documentation generator |
The application is organized as an Angular NgModule-based SPA with a hierarchical routing structure. The top-level decomposition is:
AppModule — Root module; bootstraps the application.PagesModule — The authenticated shell; hosts the ngx-one-column-layout with sidebar navigation and a <router-outlet> for all feature modules.DashboardModule, ECommerceModule, ChartsModule, FormsModule, MapsModule, TablesModule, ModalOverlaysModule, ExtraComponentsModule, EditorsModule, UiFeaturesModule, MiscellaneousModule.@theme Module — Shared layout components: HeaderComponent, FooterComponent, SearchInputComponent, and layout wrappers.@core Module — Shared services: abstract data service classes, LayoutService, AnalyticsService, and utility services.Shell Component Pattern — Feature group routes (e.g., /charts, /forms, /maps, /tables) are handled by empty shell components containing only <router-outlet>. This creates clean lazy-loading boundaries and allows child routes to be independently navigable.
Abstract Service / Dependency Injection Pattern — All data-fetching contracts are defined as abstract Angular classes (e.g., SolarData, UserData, ElectricityData, CountryOrderData). Concrete implementations are registered in module providers. UI components depend only on the abstract class, enabling mock-to-real substitution without component changes.
Reactive Theming Pattern — Components subscribe to NbThemeService.getJsTheme() or NbThemeService.onThemeChange() to receive theme variable maps at runtime. Chart options, map styles, and component colors are constructed from these variables rather than hardcoded values.
Presentational / Container Component Split — Data-fetching and state management occur in container components (e.g., DashboardComponent, CountryOrdersComponent, ECommerceChartsPanelComponent). Leaf components (e.g., StatusCardComponent, ChartPanelSummaryComponent, TrafficBarComponent) are purely presentational, receiving all data via @Input().
takeWhile Subscription Lifecycle Pattern — The majority of components manage RxJS subscription cleanup using a boolean alive flag combined with takeWhile(() => this.alive), set to false in ngOnDestroy().
forkJoin for Parallel Data Loading — Multiple screens (ContactsComponent, TemperatureComponent, VisitorsAnalyticsComponent, ElectricityComponent) use forkJoin to fetch multiple data streams simultaneously, ensuring the UI renders only when all data is available.
| Quality Goal | Architectural Approach |
|---|---|
| Theme Consistency | NbThemeService subscriptions in every chart and widget; chart options constructed from theme variable maps at runtime |
| Component Reusability | @Input()/@Output() contracts; no direct service injection in leaf components; Nebular component library for consistent primitives |
| Separation of Data and Presentation | Abstract service classes as DI tokens; concrete implementations registered at module level |
| Maintainability | Shell component pattern for routing; Nebular for UI primitives; ESLint with @angular-eslint enforcing naming conventions |
| Responsiveness | NbMediaBreakpointsService and NbThemeService.onMediaQueryChange() subscriptions; LayoutService debounced resize bus for chart reflow |
[Diagram: Building Block View — show the following containers: Browser (hosts the SPA), Angular SPA (contains PagesModule, feature modules, @theme module, @core module), External Services (OpenStreetMap, Google Maps, CKEditor CDN, Spotify CDN, Backend Data Services). Show dependency arrows from Angular SPA to External Services. Within Angular SPA, show PagesModule containing feature module boxes (Dashboard, E-Commerce, Charts, Forms, Maps, Tables, Modal Overlays, Extra Components, Editors, UI Features, Miscellaneous) and shared modules (@theme, @core).]
| Container | Responsibility | Technology |
|---|---|---|
| Angular SPA | Entire client-side application; routing, rendering, state management | Angular 15, TypeScript, SCSS |
| Nebular Theme System | UI component library, theming bus, layout primitives, overlay services | @nebular/theme 11.0.1 |
| Abstract Data Layer | Defines data-fetching contracts; concrete implementations provide mock or real data | Angular DI, RxJS Observables |
| ECharts Rendering Engine | Canvas/SVG chart rendering for area, bar, pie, donut, and map charts | Apache ECharts 4.9.0 via ngx-echarts |
| Leaflet Map Engine | Interactive vector map rendering with GeoJSON overlays | Leaflet 1.2.0 via @asymmetrik/ngx-leaflet |
| Google Maps Engine | Google Maps tile rendering and Places Autocomplete | @angular/google-maps 12.2.13 |
| CKEditor Instance | Rich text editing via CDN-loaded CKEditor 4 | ckeditor 4.7.3 / ng2-ckeditor |
| TinyMCE Instance | Rich text editing via globally loaded TinyMCE 4 | tinymce 4.5.7 |
@theme Module (Shared Layout Shell)
| Component | Responsibility |
|---|---|
HeaderComponent |
Top navigation bar; theme selector, user menu, sidebar toggle, responsive user display |
FooterComponent |
Static attribution footer with social links |
SearchInputComponent |
Expand-on-demand search input; emits keystrokes to parent via @Output() search |
OneColumnLayoutComponent |
Full-height shell with sidebar and main content area |
@core Module (Shared Services)
| Service | Responsibility |
|---|---|
LayoutService |
Debounced resize event bus; onSafeChangeLayoutSize() with 350ms debounceTime |
AnalyticsService |
Wraps Google Analytics ga() global; disabled by default (enabled = false) |
| Abstract data services | SolarData, UserData, ElectricityData, CountryOrderData, TemperatureHumidityData, SecurityCamerasData, EarningData, TrafficListData, TrafficBarData, OrdersProfitChartData, VisitorsAnalyticsData, StatsProgressBarData, UserActivityData, SmartTableData |
Dashboard Module
| Component | Responsibility |
|---|---|
DashboardComponent |
Container; subscribes to SolarData and NbThemeService; manages status card theme mapping |
StatusCardComponent |
Presentational card with ON/OFF toggle; receives title, type, on via @Input() |
SolarComponent |
ECharts donut chart; receives chartValue via @Input(); theme-driven gradient |
TrafficChartComponent |
ECharts area chart; receives points via @Input(); subscribes to LayoutService for resize |
TemperatureComponent |
Container; uses forkJoin to load temperature and humidity data |
TemperatureDraggerComponent |
SVG-based arc slider; pure @Input()/@Output() widget; handles mouse drag geometry |
ElectricityComponent |
Container; uses forkJoin to load list and chart data |
ElectricityChartComponent |
ECharts line chart; receives data via @Input() |
RoomsComponent |
Container; manages room selection and player collapsed state |
RoomSelectorComponent |
SVG floor plan; pre-selects room 2; emits selectEvent |
PlayerComponent |
Native HTMLAudioElement media player; static playlist from PlayerService |
ContactsComponent |
Container; uses forkJoin to load contacts and recent users |
SecurityCamerasComponent |
Container; loads camera list; manages single/grid view toggle |
WeatherComponent |
Empty shell; no logic in assessed code |
KittenComponent |
Theme-aware display; subscribes to NbThemeService |
E-Commerce Module
| Component | Responsibility |
|---|---|
ECommerceComponent |
Empty shell; no logic in assessed code |
EarningCardComponent |
Flip card container; manages flipped boolean |
EarningCardFrontComponent |
Live-updating chart; polls EarningData every 200ms via interval(200) + switchMap |
EarningCardBackComponent |
Pie chart; loads data from EarningData once on init |
ProfitCardComponent |
Flip card container; manages flipped boolean |
TrafficRevealCardComponent |
Flip card; loads TrafficListData and TrafficBarData per period |
CountryOrdersComponent |
Container; loads categories on init; loads country data on map selection |
CountryOrdersMapComponent |
Leaflet GeoJSON map; fetches countries.geo.json; emits country selection |
CountryOrdersChartComponent |
ECharts horizontal bar chart; receives data via @Input(); incremental updates via setOption() |
ECommerceChartsPanelComponent |
Container; loads orders and profit chart data per period |
OrdersChartComponent |
ECharts multi-line area chart; receives ordersChartData via @Input() |
ProfitChartComponent |
ECharts grouped bar chart; receives profitChartData via @Input() |
VisitorsAnalyticsComponent |
Container; uses forkJoin for three data streams |
VisitorsAnalyticsChartComponent |
ECharts dual-line area chart; receives chartData via @Input() |
VisitorsStatisticsComponent |
ECharts concentric pie chart; receives value via @Input() |
ChartPanelSummaryComponent |
Stateless list renderer; receives summary array via @Input() |
LegendChartComponent |
Stateless legend renderer; receives legendItems via @Input() |
ProgressSectionComponent |
Loads StatsProgressBarData; renders progress bars |
UserActivityComponent |
Loads UserActivityData per period; renders activity list |
SlideOutComponent |
Toggle panel; manages showVisitorsStatistics boolean |
Charts Module
| Component | Responsibility |
|---|---|
ChartsComponent |
Empty shell with <router-outlet> |
EchartsComponent |
ECharts stacked area chart; static data; theme-driven colors |
ChartjsBarHorizontalComponent |
Chart.js horizontal bar chart; random data; theme-driven colors |
D3Component |
ngx-charts advanced pie chart; static data; theme-driven colors |
Maps Module
| Component | Responsibility |
|---|---|
MapsComponent |
Empty shell with <router-outlet> |
LeafletComponent |
Static Leaflet map centered on Maryland, USA |
BubbleMapComponent |
ECharts world bubble map; fetches world.json; static population data |
SearchMapComponent |
Container; manages searchedPosition state |
MapComponent |
Leaflet map; uses browser Geolocation API on init; receives searchedPosition via @Input() |
SearchComponent |
Google Maps Places Autocomplete; emits PositionModel via @Output() |
GmapsComponent |
Static Google Maps view centered on Hamm, Germany |
Tables Module
| Component | Responsibility |
|---|---|
TablesComponent |
Empty shell with <router-outlet> |
SmartTableComponent |
ng2-smart-table with LocalDataSource; CRUD with window.confirm() delete guard |
TreeGridComponent |
Nebular nb-tree-grid with static file system data; sortable columns |
Modal Overlays Module
| Component | Responsibility |
|---|---|
ModalOverlaysComponent |
Empty shell with <router-outlet> |
DialogComponent |
Demonstrates NbDialogService with multiple configurations; collects names from prompt |
ShowcaseDialogComponent |
Reusable titled dialog; closes via NbDialogRef |
DialogNamePromptComponent |
Name input dialog; returns value via NbDialogRef.close(name) |
WindowComponent |
Demonstrates NbWindowService with template and component content |
WindowFormComponent |
Uncontrolled form inside a Nebular window overlay |
ToastrComponent |
Demonstrates NbToastrService with configurable options |
TooltipComponent |
Static tooltip showcase |
PopoversComponent |
Three static popover content components |
Extra Components Module
| Component | Responsibility |
|---|---|
ExtraComponentsComponent |
Empty shell with <router-outlet> |
SpinnerComponent |
Simulated loading state with 3-second setTimeout |
SpinnerInButtonsComponent |
Two independent 3-second spinner simulations |
SpinnerInTabsComponent |
1-second spinner simulation |
InteractiveProgressBarComponent |
Progress bar with step-based increment/decrement; status derived from value |
CalendarComponent |
Demonstrates nb-calendar and nb-calendar-range with custom day cell |
DayCellComponent |
Custom Nebular calendar day cell; extends NbCalendarDayCellComponent |
CalendarKitComponent |
Demonstrates custom month cell renderer |
CalendarKitMonthCellComponent |
Custom month cell; extends NbCalendarDayPickerComponent |
ChatComponent |
In-memory chat with regex-based bot reply engine |
NebularSelectComponent |
Static nb-select showcase |
NebularFormInputsComponent |
Static Nebular form inputs showcase |
AlertComponent |
Static alert showcase |
Editors Module
| Component | Responsibility |
|---|---|
EditorsComponent |
Empty shell with <router-outlet> |
CKEditorComponent |
Hosts ng2-ckeditor; loads assets from CDN |
TinyMCEPageComponent |
Hosts ngx-tiny-mce child component |
TinyMceComponent |
Wraps TinyMCE 4; manages editor lifecycle; emits content on keyup |
UI Features Module
| Component | Responsibility |
|---|---|
UiFeaturesComponent |
Empty shell with <router-outlet> |
IconsComponent |
Registers font icon packs; renders Eva, Ionicons, and Font Awesome icon catalogs |
GridComponent |
Static grid layout showcase |
TypographyComponent |
Subscribes to breakpoints; renders typography specimens |
SearchFieldsComponent |
Static search field showcase |
Miscellaneous Module
| Component | Responsibility |
|---|---|
MiscellaneousComponent |
Empty shell with <router-outlet> |
NotFoundComponent |
404 page; navigates home via NbMenuService |
Pages Module
| Component | Responsibility |
|---|---|
PagesComponent |
Application shell; renders ngx-one-column-layout with nb-menu and <router-outlet> |
| Building Block | Type | Used By | Responsibility |
|---|---|---|---|
NbThemeService |
Service (Nebular) | All chart components, Header, Dashboard, Rooms, Typography, Kitten, and 30+ others | Provides reactive theme variable maps; emits on theme change and media query change |
LayoutService |
Internal Service | TrafficChartComponent, ElectricityChartComponent, CountryOrdersChartComponent, OrdersChartComponent, ProfitChartComponent, VisitorsAnalyticsChartComponent, VisitorsStatisticsComponent, StatsAreaChartComponent | Debounced resize event bus; triggers ECharts .resize() on layout changes |
NbMediaBreakpointsService |
Service (Nebular) | Header, CountryOrders, Rooms, Typography, SecurityCameras, ChartPanelHeader | Provides breakpoint pixel-width map for responsive layout decisions |
NbDialogService |
Service (Nebular) | DialogComponent | Opens modal dialog overlays with component or template content |
NbWindowService |
Service (Nebular) | WindowComponent | Opens floating window overlays |
NbToastrService |
Service (Nebular) | ToastrComponent | Renders toast notification overlays |
NbSidebarService |
Service (Nebular) | HeaderComponent | Controls sidebar visibility |
NbMenuService |
Service (Nebular) | HeaderComponent, NotFoundComponent | Navigation and home routing |
NbIconLibraries |
Service (Nebular) | IconsComponent | Registers and retrieves icon packs |
NbDateService |
Service (Nebular) | DatepickerComponent, CalendarComponent, CalendarKitMonthCellComponent | Date arithmetic and locale-aware formatting |
echarts directive |
Directive (ngx-echarts) |
All ECharts-based chart components | Binds ECharts option object to a DOM element |
leaflet directive |
Directive (@asymmetrik/ngx-leaflet) |
LeafletComponent, CountryOrdersMapComponent, MapComponent | Binds Leaflet map options and layers to a DOM element |
PositionModel |
Data Class | SearchMapComponent, MapComponent, SearchComponent | Holds lat/lng coordinates; defaults to Minsk, Belarus |
NgxLegendItemColor |
Enum | LegendChartComponent | Constrains legend icon colors to five predefined values |
Participants: Browser, Angular Router, PagesComponent, HeaderComponent, NbThemeService, any chart component (e.g., EchartsComponent)
Sequence:
/charts/echarts).PagesComponent, which renders ngx-one-column-layout with nb-menu and <router-outlet>.HeaderComponent initializes; reads themeService.currentTheme synchronously to set currentTheme; subscribes to themeService.onThemeChange() and themeService.onMediaQueryChange().ChartsComponent (empty shell) and then EchartsComponent inside the nested outlet.EchartsComponent.ngAfterViewInit() fires; subscribes to NbThemeService.getJsTheme().NbThemeService emits the current theme's JS variable map.EchartsComponent constructs the ECharts option object using theme color variables.echarts directive detects the option change and renders the chart canvas.Error path: If NbThemeService.getJsTheme() fails to emit (e.g., theme configuration is malformed), the option object remains {} and the chart renders as an empty container with no user-facing error message.
[Diagram: Sequence — Page Load and Theme Hydration]
Participants: User, Angular Router, PagesComponent, Feature Module Shell Component, Child Route Component
Sequence:
nb-menu (e.g., "Forms").NbMenuService triggers navigation to /pages/forms.FormsModule if not already loaded.FormsComponent (shell) is activated; renders <router-outlet>.FormLayoutsComponent).FormLayoutsComponent renders its static template.FormInputsComponent without re-loading FormsModule.Error path: If the lazy-loaded module fails to load (e.g., network error), Angular's router error handling applies. No custom error UI is defined at the shell level.
[Diagram: Sequence — User Navigates Between Feature Sections]
Participants: DashboardComponent, SolarData (abstract), Concrete SolarService, NbThemeService
Sequence:
DashboardComponent is constructed.SolarData.getSolarData() — emits numeric solar readings.NbThemeService.getJsTheme() — emits the current theme object.SolarData emission, solarValue is updated; the template re-renders the solar widget.NbThemeService emission, theme.name is used as a key into statusCardsByThemes; the resolved CardSettings[] is assigned to statusCards.takeWhile(() => this.alive).ngOnDestroy, alive is set to false; both subscriptions complete on their next emission.Error path: No catchError or error callback is present on either subscription. If SolarData.getSolarData() errors, solarValue remains undefined and the solar widget renders in an empty/zero state.
[Diagram: Sequence — Dashboard Data Loading via Abstract Service]
Participants: EarningCardFrontComponent, EarningData (abstract), interval(200), switchMap
Sequence:
EarningCardFrontComponent.ngOnInit() calls getEarningCardData(selectedCurrency).earningLiveUpdateCardData and liveUpdateChartData are populated.startReceivingLiveData(currency) is called; creates interval(200) observable.switchMap cancels any in-flight request and calls EarningData.getEarningLiveUpdateCardData(currency).liveUpdateChartData is replaced with a new array reference ([...data]), triggering Angular change detection and chart re-render.changeCurrency() unsubscribes the existing intervalSubscription and restarts from step 1.ngOnDestroy, alive is set to false; all subscriptions complete.Error path: If getEarningLiveUpdateCardData() errors, switchMap propagates the error and terminates the interval subscription. No error recovery or retry logic is implemented.
[Diagram: Sequence — High-Frequency Live Data Polling]
Participants: DialogComponent, NbDialogService, DialogNamePromptComponent, NbDialogRef
Sequence:
DialogComponent.open3() is called.NbDialogService.open(DialogNamePromptComponent) creates and renders the dialog overlay; returns a NbDialogRef.DialogComponent subscribes to dialogRef.onClose.DialogNamePromptComponent renders with a text input and Cancel/Submit buttons.DialogNamePromptComponent.submit(name) calls this.ref.close(name).NbDialogRef.close(name) emits name through the onClose observable and destroys the overlay.DialogComponent's subscription callback receives name; if truthy, pushes it to this.names.Error path: If the user clicks Cancel, ref.close() is called with no argument; the onClose observable emits undefined; the guard name => name && this.names.push(name) prevents undefined from being added to the list.
[Diagram: Sequence — Dialog Interaction with Return Value]
[Diagram: Data Flow — show data sources (Abstract Services, NbThemeService, Static/Hardcoded Data, Browser APIs) flowing through Container Components (which hold state) to Presentational Components (which receive @Input() and emit @Output()), with ECharts/Leaflet/Chart.js rendering engines at the leaf level]
The application draws data from four categories of sources:
Abstract Data Services — The primary data source for operational screens. Services such as SolarData, UserData, ElectricityData, CountryOrderData, and EarningData are abstract Angular classes. Concrete implementations (not included in the assessed code) are registered in module providers and may connect to REST APIs, WebSockets, or mock data generators.
Static / Hardcoded Data — The majority of chart demonstration screens use hardcoded data arrays defined directly in component classes (e.g., the D3 chart's Germany/USA/France values, the ECharts stacked area chart's marketing channel data, the Player's playlist). This is consistent with the application's role as a UI showcase.
Nebular Theme Service — NbThemeService.getJsTheme() is a data source for all chart and widget styling. It emits a JavaScript object containing color tokens, font settings, and component-specific variables that components use to construct their visual configurations.
Browser Native APIs — The Geolocation API provides coordinates for the Search Map screen. The HTMLAudioElement streams audio from Spotify CDN URLs for the Player widget.
The application uses Angular class property state exclusively — there is no NgRx store, Akita, or other global state management library. State is managed at three levels:
flipped, revealed, isInputShown, loading), numeric values (value, solarValue), and data arrays (messages, cameras, contacts) are held as class properties on the component instance.NbThemeService acts as a shared reactive state bus for the active theme. LayoutService acts as a shared event bus for layout resize events. NbSidebarService manages sidebar visibility.The typical data transformation pipeline for a data-driven screen is:
Abstract Service Observable
→ Container Component subscription (takeWhile / takeUntil)
→ Component state property assignment
→ @Input() binding to presentational child component
→ Child component constructs ECharts/Leaflet option object
→ Chart directive renders to canvas/SVG
For theme-driven styling, the pipeline is:
NbThemeService.getJsTheme() Observable (with delay(1))
→ Component subscription
→ Theme variable extraction (config.variables.*)
→ Chart option object construction (inline or via setOptions())
→ [options] binding triggers ECharts re-render
No client-side caching layer is present. No TanStack Query, SWR, Apollo Client, or similar data-fetching library with cache management is used anywhere in the assessed screens. Each component instantiation triggers fresh service calls with no deduplication or stale-time management.
No client-side persistence is used. No localStorage, sessionStorage, cookies, or IndexedDB are read or written by any assessed component. All state is ephemeral and resets on navigation away or page refresh.
The browser's native HTTP cache will cache static assets (GeoJSON files, map tiles, audio files) according to the cache headers returned by their respective servers, but this is not controlled by the application.
Cross-screen data sharing occurs through three mechanisms:
Shared Services — NbThemeService, LayoutService, NbSidebarService, and NbMenuService are application-scoped singletons that broadcast state changes to all subscribers regardless of which screen is active.
Parent-Child @Input() Bindings — Within a feature module, container components fetch data and pass it to child presentational components via @Input(). For example, ECommerceChartsPanelComponent fetches chart data and passes it to OrdersChartComponent and ProfitChartComponent.
Router Navigation — The PagesComponent menu configuration (MENU_ITEMS) defines the navigation structure. NbMenuService.navigateHome() provides a cross-screen navigation mechanism.
No shared global state store (NgRx, Akita, etc.) is used. Data is not shared between sibling feature modules.
Observed pattern: Error handling is largely absent across the assessed screens. The dominant pattern is to subscribe to observables without providing an error callback or catchError operator.
Specific observations:
DashboardComponent, ContactsComponent, TemperatureComponent, ElectricityComponent, VisitorsAnalyticsComponent, CountryOrdersComponent, SecurityCamerasComponent, EarningCardFrontComponent, and ProgressSectionComponent all subscribe to data observables without error handling. If the underlying service fails, the component silently remains in its loading/empty state.BubbleMapComponent fetches world.json via HttpClient without catchError; a 404 would leave the map without country polygons.CountryOrdersMapComponent fetches countries.geo.json without error handling.SmartTableComponent uses window.confirm() for delete confirmation, which is a synchronous blocking call.Inconsistency: No consistent error state UI pattern (error banners, retry buttons, toast notifications) is applied to data-loading failures. This is architecturally significant for any production deployment.
Observed pattern: No authentication or authorization logic is implemented within any of the 100 assessed component files. Every component explicitly notes that security is "delegated to Angular route guards at the router level."
The @nebular/auth (11.0.1) and @nebular/security (11.0.1) packages are present in package.json, indicating the infrastructure for authentication exists in the project. However, no route guard implementations, JWT handling, or session management are visible in the assessed screens.
[Not documented — WHO: Backend/security engineer or the developer who configured the routing module; WHAT: Are Angular route guards (CanActivate, CanLoad) applied to the /pages route group or any feature module routes? What authentication strategy (JWT, session cookie, OAuth) is used with @nebular/auth?; WHERE: Insert answer in Section 11.2: Authentication & Authorization and Section 12: Architecture Decisions]
Observed pattern: Loading and empty state handling is inconsistent across screens.
DashboardComponent, ContactsComponent, TemperatureComponent) have no explicit loading spinner, skeleton, or placeholder. The template renders with undefined data until the observable emits.*ngFor on undefined arrays will render nothing, which may appear as a blank area to the user.SpinnerComponent, SpinnerInButtonsComponent, and SpinnerInTabsComponent demonstrate loading state patterns using setTimeout simulations, but these are showcase components, not applied to real data-loading flows.Observed pattern: The Nebular component library (@nebular/theme) is the universal UI primitive layer. Across all 100 screens, the following Nebular components appear consistently:
nb-card, nb-card-header, nb-card-body, nb-card-footer — Card layout containersnb-icon — Icon rendering (Eva Icons, Ionicons, Font Awesome)nb-menu — Sidebar navigationnb-tabset, nb-tab — Tab containersnb-dialog, nb-window, nb-toastr — Overlay servicesnb-spinner — Loading indicatorsnb-progress-bar — Progress visualizationnb-calendar, nb-calendar-range — Date pickersnb-select, nb-option — Dropdown selectsnb-chat, nb-chat-form — Chat UICSS naming convention: All custom components use the ngx- selector prefix, enforced by the ESLint rule @angular-eslint/component-selector with prefix: "ngx".
SCSS: Component-scoped SCSS files are used universally. No CSS-in-JS or utility-class framework (Tailwind, etc.) is used.
Observed pattern: Form validation is not a prominent concern in the assessed screens. The FormLayoutsComponent, FormInputsComponent, and NebularFormInputsComponent are static showcases with no form submission logic. The WindowFormComponent contains uncontrolled inputs with no ngModel or ReactiveFormsModule bindings. The DialogNamePromptComponent captures input via a template reference variable without validation.
No Validators, FormGroup, FormControl, or ReactiveFormsModule patterns are observed in the assessed component classes.
[Not documented — WHO: Frontend developer responsible for the forms module; WHAT: Are reactive forms with validation used in any non-showcase form screens not included in this assessment?; WHERE: Insert answer in Section 11.5: Validation Approach]
Observed pattern: AnalyticsService is present in the @core/utils module and wraps a declare const ga: any global reference (Google Analytics Universal Analytics). However, AnalyticsService.enabled is hardcoded to false, meaning no analytics events are tracked in the assessed code. The service is referenced in TrafficChartComponent's service imports but is not injected into any assessed component.
No observability SDK identified in available project context beyond the disabled AnalyticsService. The package.json manifest contains no error tracking (Sentry, Bugsnag, Rollbar), APM (Datadog, New Relic), or structured logging packages.
[Not documented — WHO: DevOps or infrastructure engineer; WHAT: Is any error tracking, APM, or logging service configured at the deployment level (e.g., via environment variables or a separate configuration file not included in the assessed code)?; WHERE: Insert answer in Section 11.6: Logging & Observability]
Observed patterns applied consistently:
LayoutService debounced resize bus — All ECharts-based chart components subscribe to LayoutService.onSafeChangeLayoutSize(), which applies debounceTime(350) before triggering echartsIntance.resize(). This prevents excessive canvas reflow during sidebar animations or window resizing. Observed in: TrafficChartComponent, ElectricityChartComponent, CountryOrdersChartComponent, OrdersChartComponent, ProfitChartComponent, VisitorsAnalyticsChartComponent, VisitorsStatisticsComponent, StatsAreaChartComponent.
ECharts sampling: 'average' — Line series in TrafficChartComponent and StatsAreaChartComponent use sampling: 'average' to downsample data when there are more points than pixels.
forkJoin for parallel data loading — ContactsComponent, TemperatureComponent, VisitorsAnalyticsComponent, and ElectricityComponent use forkJoin to minimize total load time.
trackByDate in TrafficFrontCardComponent — A trackBy function is provided for the traffic list *ngFor, preventing unnecessary DOM re-creation on data updates.
ChangeDetectionStrategy.OnPush in IconsComponent — The only screen in the assessment that explicitly applies OnPush change detection, appropriate given its static data.
Patterns notably absent: OnPush change detection is not applied to any other component in the assessment, including components with frequent updates (e.g., EarningCardFrontComponent polling at 200ms). No virtual scrolling is used for any list.
The following cross-cutting concerns are architecturally significant by their absence:
| Concern | Observation |
|---|---|
| Centralized error handling | No ErrorHandler override, no catchError operators on data subscriptions, no error state UI. Failed data loads result in silent empty states. |
| Authentication enforcement | No route guards observed in assessed screens. @nebular/auth is a dependency but its integration is not visible in the assessed code. |
| Internationalization (i18n) | No Angular i18n, ngx-translate, or similar library is present. All user-facing strings are hardcoded in English. Legend titles, button labels, and card headers are static string literals. |
| Centralized loading state | No application-level loading indicator (beyond the disabled pace-js dependency in package.json). Individual screens have no consistent loading skeleton or spinner pattern. |
| HTTP interceptors | No HTTP interceptors for auth headers, error normalization, or request logging are visible in the assessed code. |
| Content Security Policy | No CSP configuration is visible in the assessed code. The application loads scripts from external CDNs (CKEditor, Google Maps) without Subresource Integrity (SRI) hashes. |
rel="noopener noreferrer" on external links |
The FooterComponent uses target="_blank" without rel="noopener noreferrer", creating a reverse tabnapping risk. |
@nebular/theme 11.0.1) is used as the sole UI component library for all structural and interactive UI elements.NbThemeService reactive theming bus that all chart and widget components depend on. As the application is an Akveo product, Nebular is the natural choice.SolarData, UserData, ElectricityData). Concrete implementations are registered in module providers and injected at runtime.<router-outlet>. The shell component has no logic, no state, and no data fetching./charts) renders a blank page unless a default child route redirect is configured. The shell components add a layer of component instantiation with no functional benefit beyond routing.ngx-echarts 4.2.2) is the primary charting library, used for the majority of charts across the Dashboard, E-Commerce, and Charts modules.option object API that integrates naturally with Angular's change detection, and supports the sampling: 'average' performance optimization for large datasets. Chart.js and ngx-charts are used for specific demonstration screens but are not the primary engine.ngx-echarts directive and directly as a global (echarts.graphic.LinearGradient), creating an implicit dependency on the global echarts object. The ngx-echarts version (4.2.2) is pinned to an older ECharts 4.x API, which may limit access to newer ECharts 5.x features.alive flag initialized to true, used as the predicate for takeWhile(() => this.alive), set to false in ngOnDestroy().Subscription references. It is consistently applied across the majority of components.takeWhile predicate is evaluated on every emission, which is slightly less efficient than takeUntil(destroy$). More critically, the subscription completes only on the next emission after alive is set to false, meaning a component that is destroyed between emissions may briefly process one more value. A Subject + takeUntil pattern would be more reliable. Additionally, ProgressSectionComponent has a bug where ngOnDestroy sets alive = true instead of false, permanently preventing cleanup.NbThemeService.getJsTheme() in ngAfterViewInit (with a delay(1)) to receive theme-specific color variables and construct their visual configurations.NbThemeService ensures a single source of truth for all visual tokens. The delay(1) pattern ensures the DOM is fully rendered before ECharts attempts to mount, avoiding race conditions.NbThemeService. If the theme service is slow or unavailable, charts render as empty containers. Theme changes trigger full option object reconstruction and chart re-render across all active chart components simultaneously.Math.random() to generate data on each instantiation.Math.random() pattern in ChartjsBarHorizontalComponent means chart data changes on every theme switch, which is a confusing side effect.TinyMceComponent uses ElementRef.nativeElement and ngAfterViewInit to pass the host DOM element to tinymce.init(). CKEditor is integrated via the ng2-ckeditor Angular wrapper.window.tinymce), bypassing Angular's module system and making it impossible to verify library integrity via Subresource Integrity. The keyup-only content emission in TinyMceComponent means paste-only actions do not propagate to the parent. The emitted HTML is raw and must be sanitized before storage or rendering..resize() when their container dimensions change (e.g., sidebar toggle, window resize). Multiple chart components on the same page need to respond to the same resize event.LayoutService with a Subject-based layoutSizeChange$ observable, wrapped with shareReplay({ refCount: true }) and debounceTime(350), is used as a centralized resize event bus.debounceTime(350) prevents excessive .resize() calls during animated layout transitions. shareReplay ensures all subscribers receive the same debounced event without redundant upstream subscriptions.LayoutService. The shareReplay({ refCount: true }) configuration without an explicit bufferSize defaults to replaying 1 value to new subscribers, which may cause a chart to resize immediately on subscription even if no layout change has occurred recently. (inferred from RxJS shareReplay behavior — verify against the LayoutService source and confirm whether the replay behavior is intentional)TemperatureDraggerComponent and RoomSelectorComponent use SVG <clipPath> and <pattern> elements that reference fragment IDs via CSS url(#id). Angular's router changes the browser URL, breaking bare fragment references.Location and LocationStrategy services to construct url(baseHref + path + id) strings that remain valid regardless of the current route.url(#id) references break. Prepending the full path is the standard workaround.getUrlPath(id) method is called from the template on every change detection cycle without memoization, calling location.path() repeatedly. This is a minor performance concern. The fix is also required for hash-based routing strategies.| Quality Attribute | Current State | Evidence | Risk Level |
|---|---|---|---|
| Performance | Moderate — debounced resize and ECharts sampling are applied; high-frequency polling (200ms) and absence of OnPush are concerns |
LayoutService.debounceTime(350) used by 8+ chart components; EarningCardFrontComponent polls at 200ms with no OnPush; IconsComponent is the only component using OnPush |
Medium |
| Maintainability | Good — consistent patterns, Nebular primitives, ESLint enforcement; weakened by any typing and inconsistent subscription cleanup |
Abstract service pattern applied to 14+ data services; ESLint ngx prefix rule enforced; any typing on colorScheme, themeSubscription, option, echartsIntance across many components; ProgressSectionComponent has ngOnDestroy bug |
Low–Medium |
| Reliability | Low — no error handling on data subscriptions; silent failures on API errors | Zero catchError operators observed across all 100 screens; no retry logic; no error state UI; forkJoin will silently fail if any one observable errors |
High |
| Security | Low — no observable auth enforcement; XSS risks from TinyMCE output; CDN scripts without SRI; HTTP tile URLs | @nebular/auth present but no route guards observed; TinyMceComponent emits raw HTML; CKEditor CDN loaded without SRI; OpenStreetMap tiles use http://; FooterComponent missing rel="noopener noreferrer" |
High |
| Usability | Good — four themes, responsive breakpoints, consistent Nebular component usage | NbMediaBreakpointsService used in 6+ components for responsive layout; four themes with per-theme card color mappings in DashboardComponent; TemperatureDraggerComponent provides accessible arc slider |
Low |
| Testability | Not assessable — no test files were included in the assessed documentation | Unit test infrastructure (Karma + Jasmine) is present in package.json; Protractor for E2E; no test coverage data available |
[Not documented — WHO: QA lead or developer; WHAT: What is the current unit test coverage percentage, and are there tests for the abstract service pattern and component @Input()/@Output() contracts?; WHERE: Insert answer in Section 13: Quality Attributes] |
| Scalability | Not assessable from client-side code alone | All data services are abstract; the concrete implementations determine actual scalability; no server-side rendering (SSR) is configured | [Not documented — WHO: Backend/infrastructure engineer; WHAT: What are the expected concurrent user counts and data volumes for the production deployment?; WHERE: Insert answer in Section 13: Quality Attributes] |
| ID | Category | Description | Severity | Recommendation |
|---|---|---|---|---|
| R-1 | Architectural Risk | No error handling on data subscriptions. All 100 assessed screens subscribe to data observables without catchError or error callbacks. API failures result in silent empty states with no user feedback. |
High | Add catchError operators to all data subscriptions; implement a consistent error state UI pattern (e.g., an error banner component); consider a global ErrorHandler override. |
| R-2 | Architectural Risk | No observable authentication enforcement. No route guards are visible in the assessed code despite @nebular/auth being a dependency. Any user who knows a route URL can access it directly. |
High | Verify that CanActivate guards are applied to the /pages route group in the routing module. If not, implement guards using @nebular/auth's NbAuthGuard or a custom implementation. |
| R-3 | Security | TinyMCE emits raw HTML without sanitization. TinyMceComponent emits editor.getContent() as a raw HTML string via editorKeyup. If a parent renders this via [innerHTML] or stores it without server-side sanitization, XSS is possible. |
High | Document that all consumers of TinyMceComponent's editorKeyup output must sanitize the HTML before rendering or persisting. Apply Angular's DomSanitizer or a server-side HTML sanitizer. |
| R-4 | Security | CKEditor CDN loaded without Subresource Integrity (SRI). ckeditor.loader.ts sets window['CKEDITOR_BASEPATH'] to //cdn.ckeditor.com/4.6.2/full-all/ with no integrity verification. A compromised CDN response could inject malicious scripts. |
High | Add SRI integrity attributes to the CKEditor <script> tag in index.html, or migrate to a self-hosted or npm-bundled version of CKEditor. |
| R-5 | Technical Debt | ProgressSectionComponent.ngOnDestroy bug. The ngOnDestroy lifecycle hook sets this.alive = true instead of false, permanently preventing the takeWhile subscription from completing. This is a memory leak. |
High | Fix the bug: change this.alive = true to this.alive = false in ProgressSectionComponent.ngOnDestroy(). |
| R-6 | Technical Debt | Pervasive any typing on theme and chart state. Properties such as colorScheme, themeSubscription, option, echartsIntance, bubbleTheme, and currentTheme are typed as any across dozens of components. This bypasses TypeScript's type safety and can mask runtime errors. |
Medium | Define TypeScript interfaces for Nebular theme variable maps (e.g., NbJsThemeVariables) and ECharts option objects. Replace any with typed interfaces progressively. |
| R-7 | Technical Debt | takeWhile subscription pattern is less reliable than takeUntil. The takeWhile(() => this.alive) pattern requires one additional emission after ngOnDestroy to complete, and the ProgressSectionComponent bug demonstrates how easily it can be misconfigured. |
Medium | Migrate to the Subject + takeUntil(this.destroy$) pattern, which completes subscriptions immediately and is more idiomatic in modern Angular. |
| R-8 | Architectural Risk | High-frequency polling (200ms) with no OnPush change detection. EarningCardFrontComponent polls at 200ms and uses default CheckAlways change detection. This triggers Angular's full change detection cycle 5 times per second for the component subtree. |
Medium | Apply ChangeDetectionStrategy.OnPush to EarningCardFrontComponent and its child components. Ensure liveUpdateChartData is always replaced with a new array reference (already done) to trigger OnPush detection. |
| R-9 | Security | OpenStreetMap tile layer uses http:// protocol. LeafletComponent configures the tile URL as http://{s}.tile.openstreetmap.org/.... When the application is served over HTTPS, browsers will block this as mixed content. |
Medium | Change the tile URL to https://{s}.tile.openstreetmap.org/.... |
| R-10 | Security | FooterComponent missing rel="noopener noreferrer". All anchor tags with target="_blank" in FooterComponent lack rel="noopener noreferrer", enabling reverse tabnapping. |
Medium | Add rel="noopener noreferrer" to all target="_blank" anchor elements in FooterComponent. |
| R-11 | Technical Debt | Hardcoded copyright year in FooterComponent. The footer displays "2019" as a static string literal. This will not update automatically. |
Low | Replace the static year with a dynamically computed value using Angular's DatePipe or a simple new Date().getFullYear() expression. |
| R-12 | Technical Debt | SmartTableComponent uses window.confirm() for delete confirmation. window.confirm() is a synchronous blocking call that freezes the JavaScript event loop and is suppressed in some browser environments (iframes, mobile browsers). |
Low | Replace window.confirm() with a Nebular NbDialogService confirmation dialog for a non-blocking, consistent UX. |
| R-13 | Technical Debt | BubbleMapComponent uses out-of-bounds array index in getRandomGeoColor(). Math.round(Math.random() * this.geoColors.length) can return an index equal to geoColors.length, producing undefined for some bubble colors. |
Low | Change to Math.floor(Math.random() * this.geoColors.length) to ensure the index is always within bounds. |
| R-14 | Technical Debt | SolarComponent hardcodes energy values in template. The displayed text "6.421 kWh" and "out of 8.421 kWh" are hardcoded and do not respond to the chartValue input, creating a disconnect between the chart percentage and the displayed values. |
Low | Derive the displayed kWh values from the same data source as chartValue, or document that these are intentionally static demonstration values. |
| R-15 | Documentation Gap | Concrete data service implementations are not documented. All 14+ abstract data services have no concrete implementation visible in the assessed code. The actual HTTP endpoints, database queries, and error handling behaviors are unknown. | Medium | Document the concrete service implementations (or confirm they are mock-only) and add them to the architecture documentation. |
| Term | Definition |
|---|---|
| CardSettings | A data object used in DashboardComponent containing title, iconClass, and type properties that define the appearance of a status card widget. |
| EarningData | Abstract Angular service class defining the contract for fetching cryptocurrency earnings data, including live update streams. |
| ElectricityChart | A data transfer object with label: string and value: number fields representing a single data point in the electricity consumption chart. |
| FSEntry | A data interface representing a file system entry (file or directory) in the Tree Grid screen, with name, size, kind, and optional items fields. |
| LiveUpdateChart | A data object returned by EarningData.getEarningCardData(), containing liveChart, delta (with up boolean and value number), and dailyIncome fields. |
| MENU_ITEMS | A compile-time constant array of NbMenuItem objects defined in pages-menu.ts that drives the application's sidebar navigation structure. |
| OrdersChart | A data transfer object containing chartLabel: string[] and linesData: number[][] for the orders multi-line area chart. |
| OutlineData | A data transfer object with label: string and value: number fields used for the outer line series in the Visitors Analytics chart. |
| PieChart | A data transfer object with value and name properties representing a single slice in the Earning Card back-side pie chart. |
| PositionModel | A data class holding lat and lng geographic coordinates; defaults to Minsk, Belarus (lat: 53.9, lng: 27.5667). |
| ProfitChart | A data transfer object containing chartLabel: string[] and data: number[][] for the profit grouped bar chart. |
| StatusCardsByThemes | A static mapping in DashboardComponent that associates Nebular theme names with arrays of CardSettings, enabling per-theme color assignments for device status cards. |
| TrafficBar | A data transfer object with data: number[], labels: string[], and formatter: string fields for the traffic bar chart. |
| TrafficList | A data transfer object containing date, value, delta (with up and value), and comparison (with prevDate, prevValue, nextDate, nextValue) fields for the traffic front card. |
| TreeNode | A generic wrapper type used by Nebular's tree grid, containing a data payload of type T and optional children and expanded properties. |
| UserActive | A data interface with date, pagesVisitCount, deltaUp, and newVisits fields representing a single user activity record. |
| Term | Definition |
|---|---|
| Abstract Service Pattern | An Angular dependency injection pattern where a data-fetching contract is defined as an abstract class (used as a DI token), and a concrete implementation is registered in a module's providers array. UI components depend only on the abstract class. |
alive flag |
A boolean class property initialized to true and set to false in ngOnDestroy(), used as the predicate for takeWhile(() => this.alive) to manage RxJS subscription cleanup. |
combineLatest |
An RxJS operator that combines multiple observables and emits an array of their latest values whenever any source emits. Used in BubbleMapComponent and CountryOrdersMapComponent to synchronize HTTP data fetching with theme loading. |
delay(1) |
An RxJS operator that defers an observable emission by 1 millisecond. Used consistently before chart initialization to ensure the DOM is fully rendered before ECharts attempts to mount. |
forkJoin |
An RxJS operator that waits for all source observables to complete and emits a single array of their final values. Used for parallel data loading in ContactsComponent, TemperatureComponent, VisitorsAnalyticsComponent, and ElectricityComponent. |
interval(200) |
An RxJS creation operator that emits an incrementing integer every 200 milliseconds. Used in EarningCardFrontComponent to drive high-frequency data polling. |
LayoutService |
An internal Angular service in @core/utils that acts as a debounced resize event bus. Components call changeLayoutSize() to signal a layout change; subscribers receive the event via onSafeChangeLayoutSize() after a 350ms debounceTime. |
LocalDataSource |
A class from ng2-smart-table that wraps an in-memory array and provides filtering, sorting, and pagination operations for the Smart Table component. |
NbDialogRef |
A Nebular class injected into dialog components that provides a reference to the open dialog overlay, enabling programmatic closing and return value passing via ref.close(value). |
NbDialogService |
A Nebular service that programmatically opens modal dialog overlays with either a component class or a TemplateRef as content. |
NbGlobalPhysicalPosition / NbGlobalLogicalPosition |
Nebular enums defining screen positions for toast notifications (e.g., TOP_RIGHT, BOTTOM_LEFT, TOP_END). |
NbIconLibraries |
A Nebular service that manages registration and retrieval of icon packs (SVG-based Eva Icons and CSS font-based Ionicons, Font Awesome). |
NbMediaBreakpointsService |
A Nebular service that provides a synchronous map of breakpoint names to pixel-width thresholds, used for responsive layout decisions. |
NbThemeService |
The central Nebular service for reactive theming. getJsTheme() returns an Observable of the current theme's JavaScript variable map. onThemeChange() and onMediaQueryChange() provide continuous streams for theme and viewport changes. |
NbToastrService |
A Nebular service that renders toast notification overlays with configurable position, duration, status, and dismiss behavior. |
NbWindowService |
A Nebular service that opens floating, draggable window overlays with component or template content. |
ngx-echarts directive |
An Angular attribute directive (selector: echarts) from the ngx-echarts package that binds an Apache ECharts option object to a DOM element and manages the ECharts instance lifecycle. |
ngx-leaflet directive |
An Angular attribute directive (selector: leaflet) from @asymmetrik/ngx-leaflet that binds Leaflet map options and layer arrays to a DOM element. |
ngx-smart-table |
The ng2-smart-table Angular component that renders a feature-rich data grid with built-in filtering, sorting, pagination, and inline CRUD operations. |
OnPush change detection |
Angular's ChangeDetectionStrategy.OnPush mode, which restricts change detection to run only when @Input() references change or an event originates from within the component. Applied only to IconsComponent in the assessed code. |
| Shell Component | An Angular component with an empty class body and a template containing only <router-outlet>. Used for feature group routing boundaries (e.g., ChartsComponent, FormsComponent, MapsComponent). |
shareReplay |
An RxJS operator that multicasts an observable to multiple subscribers and replays the most recent emission to new subscribers. Used in LayoutService to share the resize event stream. |
switchMap |
An RxJS operator that maps each source emission to an inner observable, cancelling any previous inner observable. Used in EarningCardFrontComponent to ensure only the latest polling response is processed. |
takeUntil |
An RxJS operator that completes a subscription when a notifier observable emits. The more reliable alternative to takeWhile for subscription cleanup; not used in the assessed code. |
takeWhile |
An RxJS operator that completes a subscription when a predicate function returns false. Used universally in the assessed code for subscription cleanup via the alive flag pattern. |