- + + fxFlex class="mat-toolbar-tools">
@@ -73,7 +73,7 @@ + *ngIf="!hideLoadingBar && (isLoading$ | async)">
diff --git a/ui-ngx/src/app/modules/home/home.component.ts b/ui-ngx/src/app/modules/home/home.component.ts index 5f59c2a9a9..6e045b9786 100644 --- a/ui-ngx/src/app/modules/home/home.component.ts +++ b/ui-ngx/src/app/modules/home/home.component.ts @@ -15,21 +15,22 @@ /// import { AfterViewInit, Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core'; -import { fromEvent, Observable } from 'rxjs'; -import { select, Store } from '@ngrx/store'; -import { debounceTime, distinctUntilChanged, map, tap } from 'rxjs/operators'; +import { fromEvent } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators'; import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout'; -import { User } from '@shared/models/user.model'; import { PageComponent } from '@shared/components/page.component'; import { AppState } from '@core/core.state'; -import { getCurrentAuthState, selectAuthUser, selectUserDetails } from '@core/auth/auth.selectors'; +import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { MediaBreakpoints } from '@shared/models/constants'; import screenfull from 'screenfull'; import { MatSidenav } from '@angular/material/sidenav'; import { AuthState } from '@core/auth/auth.models'; import { WINDOW } from '@core/services/window.service'; import { instanceOfSearchableComponent, ISearchableComponent } from '@home/models/searchable-component.models'; +import { ActiveComponentService } from '@core/services/active-component.service'; +import { RouterTabsComponent } from '@home/components/router-tabs.component'; @Component({ selector: 'tb-home', @@ -57,28 +58,21 @@ export class HomeComponent extends PageComponent implements AfterViewInit, OnIni fullscreenEnabled = screenfull.isEnabled; - authUser$: Observable; - userDetails$: Observable; - userDetailsString: Observable; - searchEnabled = false; showSearch = false; searchText = ''; + hideLoadingBar = false; + constructor(protected store: Store, @Inject(WINDOW) private window: Window, + private activeComponentService: ActiveComponentService, public breakpointObserver: BreakpointObserver) { super(store); } ngOnInit() { - this.authUser$ = this.store.pipe(select(selectAuthUser)); - this.userDetails$ = this.store.pipe(select(selectUserDetails)); - this.userDetailsString = this.userDetails$.pipe(map((user: User) => { - return JSON.stringify(user); - })); - const isGtSm = this.breakpointObserver.isMatched(MediaBreakpoints['gt-sm']); this.sidenavMode = isGtSm ? 'side' : 'over'; this.sidenavOpened = isGtSm; @@ -130,6 +124,7 @@ export class HomeComponent extends PageComponent implements AfterViewInit, OnIni } activeComponentChanged(activeComponent: any) { + this.activeComponentService.setCurrentActiveComponent(activeComponent); if (!this.activeComponent) { setTimeout(() => { this.updateActiveComponent(activeComponent); @@ -143,6 +138,7 @@ export class HomeComponent extends PageComponent implements AfterViewInit, OnIni this.showSearch = false; this.searchText = ''; this.activeComponent = activeComponent; + this.hideLoadingBar = activeComponent && activeComponent instanceof RouterTabsComponent; if (this.activeComponent && instanceOfSearchableComponent(this.activeComponent)) { this.searchEnabled = true; this.searchableComponent = this.activeComponent; diff --git a/ui-ngx/src/app/modules/home/menu/menu-link.component.html b/ui-ngx/src/app/modules/home/menu/menu-link.component.html index d07dc16b7e..ab5b1faa27 100644 --- a/ui-ngx/src/app/modules/home/menu/menu-link.component.html +++ b/ui-ngx/src/app/modules/home/menu/menu-link.component.html @@ -15,8 +15,8 @@ limitations under the License. --> - - {{section.icon}} - + + {{section.icon}} + {{section.name | translate}} diff --git a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.html b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.html index 3cd9922707..de4f16b163 100644 --- a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.html +++ b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.html @@ -15,13 +15,12 @@ limitations under the License. --> - - {{section.icon}} - + + {{section.icon}} + {{section.name | translate}} + [ngClass]="{'tb-toggled' : section.opened}">
  • diff --git a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.scss b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.scss index 85c5dfa42e..93d0276639 100644 --- a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.scss +++ b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.scss @@ -33,7 +33,7 @@ z-index: 1; overflow: hidden; - transition: .75s cubic-bezier(.35, 0, .25, 1); + transition: .45s cubic-bezier(.35, 0, .25, 1); transition-property: height; diff --git a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts index eedc09612b..70d711469a 100644 --- a/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts +++ b/ui-ngx/src/app/modules/home/menu/menu-toggle.component.ts @@ -17,6 +17,9 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; import { MenuSection } from '@core/services/menu.models'; import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { ActionPreferencesUpdateOpenedMenuSection } from '@core/auth/auth.actions'; @Component({ selector: 'tb-menu-toggle', @@ -28,24 +31,27 @@ export class MenuToggleComponent implements OnInit { @Input() section: MenuSection; - constructor(private router: Router) { + constructor(private router: Router, + private store: Store) { } ngOnInit() { } - sectionActive(): boolean { - return this.router.isActive(this.section.path, false); - } - sectionHeight(): string { - if (this.router.isActive(this.section.path, false)) { - return this.section.height; + if (this.section.opened) { + return this.section.pages.length * 40 + 'px'; } else { return '0px'; } } + toggleSection(event: MouseEvent) { + event.stopPropagation(); + this.section.opened = !this.section.opened; + this.store.dispatch(new ActionPreferencesUpdateOpenedMenuSection({path: this.section.path, opened: this.section.opened})); + } + trackBySectionPages(index: number, section: MenuSection){ return section.id; } diff --git a/ui-ngx/src/app/modules/home/menu/side-menu.component.scss b/ui-ngx/src/app/modules/home/menu/side-menu.component.scss index 54cbf11c53..533c1e2fea 100644 --- a/ui-ngx/src/app/modules/home/menu/side-menu.component.scss +++ b/ui-ngx/src/app/modules/home/menu/side-menu.component.scss @@ -63,6 +63,7 @@ white-space: nowrap; display: inline-flex; & > span { + letter-spacing: .03125em; overflow: hidden; text-overflow: ellipsis; } diff --git a/ui-ngx/src/app/modules/home/models/services.map.ts b/ui-ngx/src/app/modules/home/models/services.map.ts index 40655bfc33..d623a0abc3 100644 --- a/ui-ngx/src/app/modules/home/models/services.map.ts +++ b/ui-ngx/src/app/modules/home/models/services.map.ts @@ -42,6 +42,7 @@ import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentica import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service'; import { NotificationService } from '@core/http/notification.service'; import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe'; +import { UserSettingsService } from '@core/http/user-settings.service'; export const ServicesMap = new Map>( [ @@ -71,6 +72,7 @@ export const ServicesMap = new Map>( ['resourceService', ResourceService], ['twoFactorAuthenticationService', TwoFactorAuthenticationService], ['telemetryWsService', TelemetryWebsocketService], + ['userSettingsService', UserSettingsService], ['notificationService', NotificationService] ] ); diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index 09949a29b3..8ddb3d6218 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -90,6 +90,7 @@ import { EntityId } from '@shared/models/id/entity-id'; import { AlarmQuery, AlarmSearchStatus, AlarmStatus} from '@app/shared/models/alarm.models'; import { MillisecondsToTimeStringPipe, TelemetrySubscriber } from '@app/shared/public-api'; import { UserId } from '@shared/models/id/user-id'; +import { UserSettingsService } from '@core/http/user-settings.service'; export interface IWidgetAction { name: string; @@ -180,6 +181,7 @@ export class WidgetContext { dialogs: DialogService; customDialog: CustomDialogService; resourceService: ResourceService; + userSettingsService: UserSettingsService; telemetryWsService: TelemetryWebsocketService; telemetrySubscribers?: TelemetrySubscriber[]; date: DatePipe; diff --git a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts index 56fa9ca307..a5215cabfc 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts @@ -36,6 +36,9 @@ import { QueuesTableConfigResolver } from '@home/pages/admin/queue/queues-table- import { RepositoryAdminSettingsComponent } from '@home/pages/admin/repository-admin-settings.component'; import { AutoCommitAdminSettingsComponent } from '@home/pages/admin/auto-commit-admin-settings.component'; import { TwoFactorAuthSettingsComponent } from '@home/pages/admin/two-factor-auth-settings.component'; +import { widgetsBundlesRoutes } from '@home/pages/widget/widget-library-routing.module'; +import { RouterTabsComponent } from '@home/components/router-tabs.component'; +import { auditLogsRoutes } from '@home/pages/audit-log/audit-log-routing.module'; import { NotificationSettingsComponent } from '@home/pages/admin/notification-settings.component'; @Injectable() @@ -50,12 +53,72 @@ export class OAuth2LoginProcessingUrlResolver implements Resolve { } const routes: Routes = [ + { + path: 'resources', + data: { + auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN], + breadcrumb: { + label: 'admin.resources', + icon: 'folder' + } + }, + children: [ + { + path: '', + children: [], + data: { + auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN], + redirectTo: '/resources/widgets-bundles' + } + }, + ...widgetsBundlesRoutes, + { + path: 'resources-library', + data: { + breadcrumb: { + label: 'resource.resources-library', + icon: 'mdi:rhombus-split' + } + }, + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], + title: 'resource.resources-library', + }, + resolve: { + entitiesTableConfig: ResourcesLibraryTableConfigResolver + } + }, + { + path: ':entityId', + component: EntityDetailsPageComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + breadcrumb: { + labelFunction: entityDetailsPageBreadcrumbLabelFunction, + icon: 'mdi:rhombus-split' + } as BreadCrumbConfig, + auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], + title: 'resource.resources-library' + }, + resolve: { + entitiesTableConfig: ResourcesLibraryTableConfigResolver + } + } + ] + } + ] + }, { path: 'settings', + component: RouterTabsComponent, data: { auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN], breadcrumb: { - label: 'admin.system-settings', + label: 'admin.settings', icon: 'settings' } }, @@ -98,111 +161,18 @@ const routes: Routes = [ } }, { - path: 'sms-provider', + path: 'notifications', component: SmsProviderComponent, canDeactivate: [ConfirmOnExitGuard], data: { auth: [Authority.SYS_ADMIN], - title: 'admin.sms-provider-settings', - breadcrumb: { - label: 'admin.sms-provider', - icon: 'sms' - } - } - }, - { - path: 'security-settings', - component: SecuritySettingsComponent, - canDeactivate: [ConfirmOnExitGuard], - data: { - auth: [Authority.SYS_ADMIN], - title: 'admin.security-settings', - breadcrumb: { - label: 'admin.security-settings', - icon: 'security' - } - } - }, - { - path: 'oauth2', - component: OAuth2SettingsComponent, - canDeactivate: [ConfirmOnExitGuard], - data: { - auth: [Authority.SYS_ADMIN], - title: 'admin.oauth2.oauth2', + title: 'admin.notifications-settings', breadcrumb: { - label: 'admin.oauth2.oauth2', - icon: 'security' + label: 'admin.notifications', + icon: 'mdi:message-badge' } - }, - resolve: { - loginProcessingUrl: OAuth2LoginProcessingUrlResolver } }, - { - path: 'home', - component: HomeSettingsComponent, - canDeactivate: [ConfirmOnExitGuard], - data: { - auth: [Authority.TENANT_ADMIN], - title: 'admin.home-settings', - breadcrumb: { - label: 'admin.home-settings', - icon: 'settings_applications' - } - } - }, - { - path: 'notification', - component: NotificationSettingsComponent, - canDeactivate: [ConfirmOnExitGuard], - data: { - auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], - title: 'admin.notification.notification-settings', - breadcrumb: { - label: 'admin.notification.notification-settings', - icon: 'notifications' - } - } - }, - { - path: 'resources-library', - data: { - breadcrumb: { - label: 'resource.resources-library', - icon: 'folder' - } - }, - children: [ - { - path: '', - component: EntitiesTableComponent, - data: { - auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], - title: 'resource.resources-library', - }, - resolve: { - entitiesTableConfig: ResourcesLibraryTableConfigResolver - } - }, - { - path: ':entityId', - component: EntityDetailsPageComponent, - canDeactivate: [ConfirmOnExitGuard], - data: { - breadcrumb: { - labelFunction: entityDetailsPageBreadcrumbLabelFunction, - icon: 'folder' - } as BreadCrumbConfig, - auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], - title: 'resource.resources-library' - }, - resolve: { - entitiesTableConfig: ResourcesLibraryTableConfigResolver - } - } - ] - }, { path: 'queues', data: { @@ -242,16 +212,15 @@ const routes: Routes = [ ] }, { - path: '2fa', - component: TwoFactorAuthSettingsComponent, + path: 'home', + component: HomeSettingsComponent, canDeactivate: [ConfirmOnExitGuard], data: { - auth: [Authority.SYS_ADMIN], - title: 'admin.2fa.2fa', + auth: [Authority.TENANT_ADMIN], + title: 'admin.home-settings', breadcrumb: { - label: 'admin.2fa.2fa', - icon: 'mdi:two-factor-authentication', - isMdiIcon: true + label: 'admin.home', + icon: 'settings_applications' } } }, @@ -263,7 +232,7 @@ const routes: Routes = [ auth: [Authority.TENANT_ADMIN], title: 'admin.repository-settings', breadcrumb: { - label: 'admin.repository-settings', + label: 'admin.repository', icon: 'manage_history' } } @@ -276,12 +245,104 @@ const routes: Routes = [ auth: [Authority.TENANT_ADMIN], title: 'admin.auto-commit-settings', breadcrumb: { - label: 'admin.auto-commit-settings', + label: 'admin.auto-commit', icon: 'settings_backup_restore' } } + }, + { + path: 'security-settings', + redirectTo: '/security-settings/general' + }, + { + path: 'oauth2', + redirectTo: '/security-settings/oauth2' + }, + { + path: 'resources-library', + pathMatch: 'full', + redirectTo: '/resources/resources-library' + }, + { + path: 'resources-library/:entityId', + redirectTo: '/resources/resources-library/:entityId' + }, + { + path: '2fa', + redirectTo: '/security-settings/2fa' + }, + { + path: 'sms-provider', + redirectTo: '/settings/notifications' } ] + }, + { + path: 'security-settings', + data: { + auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN], + breadcrumb: { + label: 'security.security', + icon: 'security' + } + }, + children: [ + { + path: '', + children: [], + data: { + auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN], + redirectTo: { + SYS_ADMIN: '/security-settings/general', + TENANT_ADMIN: '/security-settings/auditLogs' + } + } + }, + { + path: 'general', + component: SecuritySettingsComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + auth: [Authority.SYS_ADMIN], + title: 'admin.general', + breadcrumb: { + label: 'admin.general', + icon: 'settings_applications' + } + } + }, + { + path: '2fa', + component: TwoFactorAuthSettingsComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + auth: [Authority.SYS_ADMIN], + title: 'admin.2fa.2fa', + breadcrumb: { + label: 'admin.2fa.2fa', + icon: 'mdi:two-factor-authentication', + isMdiIcon: true + } + } + }, + { + path: 'oauth2', + component: OAuth2SettingsComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + auth: [Authority.SYS_ADMIN], + title: 'admin.oauth2.oauth2', + breadcrumb: { + label: 'admin.oauth2.oauth2', + icon: 'mdi:shield-account' + } + }, + resolve: { + loginProcessingUrl: OAuth2LoginProcessingUrlResolver + } + }, + ...auditLogsRoutes + ] } ]; diff --git a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss index 66df772d2d..4b2d51d1e9 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss +++ b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss @@ -14,5 +14,10 @@ * limitations under the License. */ :host { +} +:host ::ng-deep { + .mat-checkbox-layout { + white-space: normal; + } } diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts index da85bde598..a488bd3807 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts @@ -123,7 +123,7 @@ export class ResourcesLibraryTableConfigResolver implements Resolve - admin.sms-provider-settings + admin.notifications-settings
    diff --git a/ui-ngx/src/app/modules/home/pages/alarm/alarm-routing.module.ts b/ui-ngx/src/app/modules/home/pages/alarm/alarm-routing.module.ts new file mode 100644 index 0000000000..30a6cbb8fd --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/alarm/alarm-routing.module.ts @@ -0,0 +1,58 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Injectable, NgModule } from '@angular/core'; +import { Resolve, RouterModule, Routes } from '@angular/router'; +import { Authority } from '@shared/models/authority.enum'; +import { Observable } from 'rxjs'; +import { OAuth2Service } from '@core/http/oauth2.service'; +import { AlarmTableComponent } from '@home/components/alarm/alarm-table.component'; +import { AlarmsMode } from '@shared/models/alarm.models'; + +@Injectable() +export class OAuth2LoginProcessingUrlResolver implements Resolve { + + constructor(private oauth2Service: OAuth2Service) { + } + + resolve(): Observable { + return this.oauth2Service.getLoginProcessingUrl(); + } +} + +const routes: Routes = [ + { + path: 'alarms', + component: AlarmTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'alarm.alarms', + breadcrumb: { + label: 'alarm.alarms', + icon: 'notifications' + }, + isPage: true, + alarmsMode: AlarmsMode.ALL + } + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [] +}) +export class AlarmRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/alarm/alarm.module.ts b/ui-ngx/src/app/modules/home/pages/alarm/alarm.module.ts new file mode 100644 index 0000000000..cd6f257833 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/alarm/alarm.module.ts @@ -0,0 +1,34 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { HomeDialogsModule } from '../../dialogs/home-dialogs.module'; +import { HomeComponentsModule } from '@modules/home/components/home-components.module'; +import { AlarmRoutingModule } from '@home/pages/alarm/alarm-routing.module'; + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + SharedModule, + HomeComponentsModule, + HomeDialogsModule, + AlarmRoutingModule + ] +}) +export class AlarmModule { } diff --git a/ui-ngx/src/app/modules/home/pages/asset/asset-routing.module.ts b/ui-ngx/src/app/modules/home/pages/asset/asset-routing.module.ts index b93125758a..1821acbf6c 100644 --- a/ui-ngx/src/app/modules/home/pages/asset/asset-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/asset/asset-routing.module.ts @@ -25,7 +25,7 @@ import { BreadCrumbConfig } from '@shared/components/breadcrumb'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models'; -const routes: Routes = [ +export const assetRoutes: Routes = [ { path: 'assets', data: { @@ -68,6 +68,18 @@ const routes: Routes = [ } ]; +const routes: Routes = [ + { + path: 'assets', + pathMatch: 'full', + redirectTo: '/entities/assets' + }, + { + path: 'assets/:entityId', + redirectTo: '/entities/assets/:entityId' + } +]; + @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], diff --git a/ui-ngx/src/app/modules/home/pages/audit-log/audit-log-routing.module.ts b/ui-ngx/src/app/modules/home/pages/audit-log/audit-log-routing.module.ts index 17e5b8c84f..557311181a 100644 --- a/ui-ngx/src/app/modules/home/pages/audit-log/audit-log-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/audit-log/audit-log-routing.module.ts @@ -19,7 +19,7 @@ import { RouterModule, Routes } from '@angular/router'; import { Authority } from '@shared/models/authority.enum'; import { AuditLogTableComponent } from '@home/components/audit-log/audit-log-table.component'; -const routes: Routes = [ +export const auditLogsRoutes: Routes = [ { path: 'auditLogs', component: AuditLogTableComponent, @@ -35,8 +35,16 @@ const routes: Routes = [ } ]; +const routes: Routes = [ + { + path: 'auditLogs', + redirectTo: '/security-settings/auditLogs' + } +]; + @NgModule({ imports: [RouterModule.forChild(routes)], - exports: [RouterModule] + exports: [RouterModule], + providers: [] }) export class AuditLogRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/device/device-routing.module.ts b/ui-ngx/src/app/modules/home/pages/device/device-routing.module.ts index ac29871576..220f9fd623 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/device/device-routing.module.ts @@ -24,8 +24,10 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models'; import { BreadCrumbConfig } from '@shared/components/breadcrumb'; +import { assetRoutes } from '@home/pages/asset/asset-routing.module'; +import { entityViewRoutes } from '@home/pages/entity-view/entity-view-routing.module'; -const routes: Routes = [ +export const deviceRoutes: Routes = [ { path: 'devices', data: { @@ -68,6 +70,18 @@ const routes: Routes = [ } ]; +const routes: Routes = [ + { + path: 'devices', + pathMatch: 'full', + redirectTo: '/entities/devices' + }, + { + path: 'devices/:entityId', + redirectTo: '/entities/devices/:entityId' + } +]; + @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts index 44e0c9c00f..5dcdee3169 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts @@ -44,49 +44,28 @@ import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages const routes: Routes = [ { - path: 'edgeInstances', + path: 'edgeManagement', data: { breadcrumb: { - label: 'edge.edge-instances', - icon: 'router' + label: 'edge.management', + icon: 'settings_input_antenna' } }, children: [ { path: '', - component: EntitiesTableComponent, + children: [], data: { auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.edge-instances', - edgesType: 'tenant' - }, - resolve: { - entitiesTableConfig: EdgesTableConfigResolver + redirectTo: '/edgeManagement/instances' } }, { - path: ':entityId', - component: EntityDetailsPageComponent, - canDeactivate: [ConfirmOnExitGuard], + path: 'instances', data: { breadcrumb: { - labelFunction: entityDetailsPageBreadcrumbLabelFunction, + label: 'edge.instances', icon: 'router' - } as BreadCrumbConfig, - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.edge-instances', - edgesType: 'tenant' - }, - resolve: { - entitiesTableConfig: EdgesTableConfigResolver - } - }, - { - path: ':edgeId/assets', - data: { - breadcrumb: { - label: 'edge.assets', - icon: 'domain' } }, children: [ @@ -95,11 +74,11 @@ const routes: Routes = [ component: EntitiesTableComponent, data: { auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.assets', - assetsType: 'edge' + title: 'edge.edge-instances', + edgesType: 'tenant' }, resolve: { - entitiesTableConfig: AssetsTableConfigResolver + entitiesTableConfig: EdgesTableConfigResolver } }, { @@ -109,198 +88,219 @@ const routes: Routes = [ data: { breadcrumb: { labelFunction: entityDetailsPageBreadcrumbLabelFunction, - icon: 'domain' + icon: 'router' } as BreadCrumbConfig, auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.assets', - assetsType: 'edge' + title: 'edge.edge-instances', + edgesType: 'tenant' }, resolve: { - entitiesTableConfig: AssetsTableConfigResolver - } - } - ] - }, - { - path: ':edgeId/devices', - data: { - breadcrumb: { - label: 'edge.devices', - icon: 'devices_other' - } - }, - children: [ - { - path: '', - component: EntitiesTableComponent, - data: { - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.devices', - devicesType: 'edge' - }, - resolve: { - entitiesTableConfig: DevicesTableConfigResolver + entitiesTableConfig: EdgesTableConfigResolver } }, { - path: ':entityId', - component: EntityDetailsPageComponent, - canDeactivate: [ConfirmOnExitGuard], + path: ':edgeId/assets', data: { breadcrumb: { - labelFunction: entityDetailsPageBreadcrumbLabelFunction, - icon: 'devices_other' - } as BreadCrumbConfig, - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.devices', - devicesType: 'edge' - }, - resolve: { - entitiesTableConfig: DevicesTableConfigResolver - } - } - ] - }, - { - path: ':edgeId/entityViews', - data: { - breadcrumb: { - label: 'edge.entity-views', - icon: 'view_quilt' - }, - }, - children: [ - { - path: '', - component: EntitiesTableComponent, - data: { - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.entity-views', - entityViewsType: 'edge' + label: 'edge.assets', + icon: 'domain' + } }, - resolve: { - entitiesTableConfig: EntityViewsTableConfigResolver - } + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.assets', + assetsType: 'edge' + }, + resolve: { + entitiesTableConfig: AssetsTableConfigResolver + } + }, + { + path: ':entityId', + component: EntityDetailsPageComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + breadcrumb: { + labelFunction: entityDetailsPageBreadcrumbLabelFunction, + icon: 'domain' + } as BreadCrumbConfig, + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.assets', + assetsType: 'edge' + }, + resolve: { + entitiesTableConfig: AssetsTableConfigResolver + } + } + ] }, { - path: ':entityId', - component: EntityDetailsPageComponent, - canDeactivate: [ConfirmOnExitGuard], + path: ':edgeId/devices', data: { breadcrumb: { - labelFunction: entityDetailsPageBreadcrumbLabelFunction, + label: 'edge.devices', icon: 'devices_other' - } as BreadCrumbConfig, - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.entity-views', - entityViewsType: 'edge' + } }, - resolve: { - entitiesTableConfig: EntityViewsTableConfigResolver - } - } - ] - }, - { - path: ':edgeId/dashboards', - data: { - breadcrumb: { - label: 'edge.dashboards', - icon: 'dashboard' - } - }, - children: [ + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.devices', + devicesType: 'edge' + }, + resolve: { + entitiesTableConfig: DevicesTableConfigResolver + } + }, + { + path: ':entityId', + component: EntityDetailsPageComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + breadcrumb: { + labelFunction: entityDetailsPageBreadcrumbLabelFunction, + icon: 'devices_other' + } as BreadCrumbConfig, + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.devices', + devicesType: 'edge' + }, + resolve: { + entitiesTableConfig: DevicesTableConfigResolver + } + } + ] + }, { - path: '', - component: EntitiesTableComponent, + path: ':edgeId/entityViews', data: { - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - dashboardsType: 'edge' - }, - resolve: { - entitiesTableConfig: DashboardsTableConfigResolver + breadcrumb: { + label: 'edge.entity-views', + icon: 'view_quilt' + }, }, + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.entity-views', + entityViewsType: 'edge' + }, + resolve: { + entitiesTableConfig: EntityViewsTableConfigResolver + } + }, + { + path: ':entityId', + component: EntityDetailsPageComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + breadcrumb: { + labelFunction: entityDetailsPageBreadcrumbLabelFunction, + icon: 'devices_other' + } as BreadCrumbConfig, + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.entity-views', + entityViewsType: 'edge' + }, + resolve: { + entitiesTableConfig: EntityViewsTableConfigResolver + } + } + ] }, { - path: ':dashboardId', - component: DashboardPageComponent, + path: ':edgeId/dashboards', data: { breadcrumb: { - labelFunction: dashboardBreadcumbLabelFunction, + label: 'edge.dashboards', icon: 'dashboard' - } as BreadCrumbConfig, - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - title: 'edge.dashboard', - widgetEditMode: false + } }, - resolve: { - dashboard: DashboardResolver - } - } - ] - }, - { - path: ':edgeId/ruleChains', - data: { - breadcrumb: { - label: 'edge.edge-rulechains', - icon: 'settings_ethernet' - } - }, - children: [ - { - path: '', - component: EntitiesTableComponent, - data: { - auth: [Authority.TENANT_ADMIN], - title: 'edge.rulechains', - ruleChainsType: 'edge' - }, - resolve: { - entitiesTableConfig: RuleChainsTableConfigResolver - } + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + dashboardsType: 'edge' + }, + resolve: { + entitiesTableConfig: DashboardsTableConfigResolver + }, + }, + { + path: ':dashboardId', + component: DashboardPageComponent, + data: { + breadcrumb: { + labelFunction: dashboardBreadcumbLabelFunction, + icon: 'dashboard' + } as BreadCrumbConfig, + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'edge.dashboard', + widgetEditMode: false + }, + resolve: { + dashboard: DashboardResolver + } + } + ] }, { - path: ':ruleChainId', - component: RuleChainPageComponent, - canDeactivate: [ConfirmOnExitGuard], + path: ':edgeId/ruleChains', data: { breadcrumb: { - labelFunction: ruleChainBreadcumbLabelFunction, + label: 'edge.edge-rulechains', icon: 'settings_ethernet' - } as BreadCrumbConfig, - auth: [Authority.TENANT_ADMIN], - title: 'rulechain.edge-rulechain', - import: false, - ruleChainType: RuleChainType.EDGE + } }, - resolve: { - ruleChain: RuleChainResolver, - ruleChainMetaData: RuleChainMetaDataResolver, - ruleNodeComponents: RuleNodeComponentsResolver, - tooltipster: TooltipsterResolver - } + children: [ + { + path: '', + component: EntitiesTableComponent, + data: { + auth: [Authority.TENANT_ADMIN], + title: 'edge.rulechains', + ruleChainsType: 'edge' + }, + resolve: { + entitiesTableConfig: RuleChainsTableConfigResolver + } + }, + { + path: ':ruleChainId', + component: RuleChainPageComponent, + canDeactivate: [ConfirmOnExitGuard], + data: { + breadcrumb: { + labelFunction: ruleChainBreadcumbLabelFunction, + icon: 'settings_ethernet' + } as BreadCrumbConfig, + auth: [Authority.TENANT_ADMIN], + title: 'rulechain.edge-rulechain', + import: false, + ruleChainType: RuleChainType.EDGE + }, + resolve: { + ruleChain: RuleChainResolver, + ruleChainMetaData: RuleChainMetaDataResolver, + ruleNodeComponents: RuleNodeComponentsResolver, + tooltipster: TooltipsterResolver + } + } + ] } ] - } - ] - }, - { - path: 'edgeManagement', - data: { - breadcrumb: { - label: 'edge.management', - icon: 'settings_input_antenna' - } - }, - children: [ - { - path: '', - children: [], - data: { - auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], - redirectTo: '/edgeManagement/ruleChains' - } }, { path: 'ruleChains', @@ -367,7 +367,63 @@ const routes: Routes = [ ] } ] - }]; + }, + { + path: 'edgeInstances', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances' + }, + { + path: 'edgeInstances/:entityId', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances/:entityId' + }, + { + path: 'edgeInstances/:edgeId/assets', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances/:edgeId/assets' + }, + { + path: 'edgeInstances/:edgeId/assets/:entityId', + redirectTo: '/edgeManagement/instances/:edgeId/assets/:entityId' + }, + { + path: 'edgeInstances/:edgeId/devices', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances/:edgeId/devices' + }, + { + path: 'edgeInstances/:edgeId/devices/:entityId', + redirectTo: '/edgeManagement/instances/:edgeId/devices/:entityId' + }, + { + path: 'edgeInstances/:edgeId/entityViews', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances/:edgeId/entityViews' + }, + { + path: 'edgeInstances/:edgeId/entityViews/:entityId', + redirectTo: '/edgeManagement/instances/:edgeId/entityViews/:entityId' + }, + { + path: 'edgeInstances/:edgeId/dashboards', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances/:edgeId/dashboards' + }, + { + path: 'edgeInstances/:edgeId/dashboards/:dashboardId', + redirectTo: '/edgeManagement/instances/:edgeId/dashboards/:dashboardId' + }, + { + path: 'edgeInstances/:edgeId/ruleChains', + pathMatch: 'full', + redirectTo: '/edgeManagement/instances/:edgeId/ruleChains' + }, + { + path: 'edgeInstances/:edgeId/ruleChains/:ruleChainId', + redirectTo: '/edgeManagement/instances/:edgeId/ruleChains/:ruleChainId' + } +]; @NgModule({ imports: [RouterModule.forChild(routes)], diff --git a/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts index fa44be34c3..e73bae7c7a 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts @@ -429,7 +429,7 @@ export class EdgesTableConfigResolver implements Resolve) { diff --git a/ui-ngx/src/app/modules/home/pages/entities/entities-routing.module.ts b/ui-ngx/src/app/modules/home/pages/entities/entities-routing.module.ts new file mode 100644 index 0000000000..c071a294b1 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/entities/entities-routing.module.ts @@ -0,0 +1,53 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { RouterModule, Routes } from '@angular/router'; +import { Authority } from '@shared/models/authority.enum'; +import { NgModule } from '@angular/core'; +import { deviceRoutes } from '@home/pages/device/device-routing.module'; +import { assetRoutes } from '@home/pages/asset/asset-routing.module'; +import { entityViewRoutes } from '@home/pages/entity-view/entity-view-routing.module'; + +const routes: Routes = [ + { + path: 'entities', + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + breadcrumb: { + skip: true + } + }, + children: [ + { + path: '', + children: [], + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + redirectTo: '/entities/devices' + } + }, + ...deviceRoutes, + ...assetRoutes, + ...entityViewRoutes + ] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class EntitiesRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/entities/entities.module.ts b/ui-ngx/src/app/modules/home/pages/entities/entities.module.ts new file mode 100644 index 0000000000..8aa4bd21a0 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/entities/entities.module.ts @@ -0,0 +1,30 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { EntitiesRoutingModule } from '@home/pages/entities/entities-routing.module'; + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + SharedModule, + EntitiesRoutingModule + ] +}) +export class EntitiesModule { } diff --git a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-routing.module.ts b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-routing.module.ts index a083e8fb4b..98a1bc3379 100644 --- a/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/entity-view/entity-view-routing.module.ts @@ -25,7 +25,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models'; import { BreadCrumbConfig } from '@shared/components/breadcrumb'; -const routes: Routes = [ +export const entityViewRoutes: Routes = [ { path: 'entityViews', data: { @@ -68,6 +68,18 @@ const routes: Routes = [ } ]; +const routes: Routes = [ + { + path: 'entityViews', + pathMatch: 'full', + redirectTo: '/entities/entityViews' + }, + { + path: 'entityViews/:entityId', + redirectTo: '/entities/entityViews/:entityId' + } +]; + @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], diff --git a/ui-ngx/src/app/modules/home/pages/features/features-routing.module.ts b/ui-ngx/src/app/modules/home/pages/features/features-routing.module.ts new file mode 100644 index 0000000000..4448f8a559 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/features/features-routing.module.ts @@ -0,0 +1,54 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { RouterModule, Routes } from '@angular/router'; +import { Authority } from '@shared/models/authority.enum'; +import { NgModule } from '@angular/core'; +import { ruleChainsRoutes } from '@home/pages/rulechain/rulechain-routing.module'; +import { otaUpdatesRoutes } from '@home/pages/ota-update/ota-update-routing.module'; +import { vcRoutes } from '@home/pages/vc/vc-routing.module'; + +const routes: Routes = [ + { + path: 'features', + data: { + auth: [Authority.TENANT_ADMIN], + breadcrumb: { + label: 'feature.advanced-features', + icon: 'construction' + } + }, + children: [ + { + path: '', + children: [], + data: { + auth: [Authority.TENANT_ADMIN], + redirectTo: '/features/ruleChains' + } + }, + ...ruleChainsRoutes, + ...otaUpdatesRoutes, + ...vcRoutes + ] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class FeaturesRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/features/features.module.ts b/ui-ngx/src/app/modules/home/pages/features/features.module.ts new file mode 100644 index 0000000000..aa3a3d9174 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/features/features.module.ts @@ -0,0 +1,30 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { FeaturesRoutingModule } from '@home/pages/features/features-routing.module'; + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + SharedModule, + FeaturesRoutingModule + ] +}) +export class FeaturesModule { } diff --git a/ui-ngx/src/app/modules/home/pages/home-pages.models.ts b/ui-ngx/src/app/modules/home/pages/home-pages.models.ts index 2d43c56a49..cd6190bb00 100644 --- a/ui-ngx/src/app/modules/home/pages/home-pages.models.ts +++ b/ui-ngx/src/app/modules/home/pages/home-pages.models.ts @@ -19,6 +19,6 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai export const entityDetailsPageBreadcrumbLabelFunction: BreadCrumbLabelFunction = ((route, translate, component) => { - return component.entity?.name || component.headerSubtitle; + return component.entity?.name; }); diff --git a/ui-ngx/src/app/modules/home/pages/home-pages.module.ts b/ui-ngx/src/app/modules/home/pages/home-pages.module.ts index 311442899d..84f1c7e518 100644 --- a/ui-ngx/src/app/modules/home/pages/home-pages.module.ts +++ b/ui-ngx/src/app/modules/home/pages/home-pages.module.ts @@ -38,6 +38,10 @@ import { OtaUpdateModule } from '@home/pages/ota-update/ota-update.module'; import { VcModule } from '@home/pages/vc/vc.module'; import { AssetProfileModule } from '@home/pages/asset-profile/asset-profile.module'; import { ProfilesModule } from '@home/pages/profiles/profiles.module'; +import { AlarmModule } from '@home/pages/alarm/alarm.module'; +import { EntitiesModule } from '@home/pages/entities/entities.module'; +import { FeaturesModule } from '@home/pages/features/features.module'; +import { NotificationModule } from '@home/pages/notification/notification.module'; import { NotificationCenterModule } from '@home/pages/notification-center/notification-center.module'; @NgModule({ @@ -51,8 +55,12 @@ import { NotificationCenterModule } from '@home/pages/notification-center/notifi DeviceProfileModule, AssetProfileModule, ProfilesModule, + EntitiesModule, + FeaturesModule, + NotificationModule, DeviceModule, AssetModule, + AlarmModule, EdgeModule, EntityViewModule, CustomerModule, @@ -63,7 +71,6 @@ import { NotificationCenterModule } from '@home/pages/notification-center/notifi ApiUsageModule, OtaUpdateModule, UserModule, - NotificationCenterModule, VcModule ] }) diff --git a/ui-ngx/src/app/modules/home/pages/notification/notification-routing.module.ts b/ui-ngx/src/app/modules/home/pages/notification/notification-routing.module.ts new file mode 100644 index 0000000000..4101f61411 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/notification/notification-routing.module.ts @@ -0,0 +1,135 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { ActivatedRoute, RouterModule, Routes } from '@angular/router'; +import { Authority } from '@shared/models/authority.enum'; +import { Component, NgModule, OnInit } from '@angular/core'; +import { RouterTabsComponent } from '@home/components/router-tabs.component'; +import { isDefinedAndNotNull } from '@core/utils'; + +@Component({ + selector: 'tb-notification-temp-component', + template: '
    {{text}}
    ', + styleUrls: [] +}) +class NotificationTempComponent implements OnInit { + + text: string; + + constructor(private route: ActivatedRoute) {} + + ngOnInit() { + if (isDefinedAndNotNull(this.route.snapshot.data.text)) { + this.text = this.route.snapshot.data.text; + } + } +} + +const routes: Routes = [ + { + path: 'notification', + component: RouterTabsComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + breadcrumb: { + label: 'notification.notification-center', + icon: 'mdi:message-badge' + } + }, + children: [ + { + path: '', + children: [], + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + redirectTo: '/notification/inbox' + } + }, + { + path: 'inbox', + component: NotificationTempComponent, + data: { + auth: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER], + title: 'notification.inbox', + breadcrumb: { + label: 'notification.inbox', + icon: 'inbox' + }, + text: 'TODO: Implement inbox' + } + }, + { + path: 'sent', + component: NotificationTempComponent, + data: { + auth: [Authority.TENANT_ADMIN], + title: 'notification.sent', + breadcrumb: { + label: 'notification.sent', + icon: 'outbox' + }, + text: 'TODO: Implement sent' + } + }, + { + path: 'templates', + component: NotificationTempComponent, + data: { + auth: [Authority.TENANT_ADMIN], + title: 'notification.templates', + breadcrumb: { + label: 'notification.templates', + icon: 'mdi:message-draw' + }, + text: 'TODO: Implement templates' + } + }, + { + path: 'recipients', + component: NotificationTempComponent, + data: { + auth: [Authority.TENANT_ADMIN], + title: 'notification.recipients', + breadcrumb: { + label: 'notification.recipients', + icon: 'contacts' + }, + text: 'TODO: Implement recipients' + } + }, + { + path: 'rules', + component: NotificationTempComponent, + data: { + auth: [Authority.TENANT_ADMIN], + title: 'notification.rules', + breadcrumb: { + label: 'notification.rules', + icon: 'mdi:message-cog' + }, + text: 'TODO: Implement rules' + } + } + ] + } +]; + +@NgModule({ + declarations: [NotificationTempComponent], + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class NotificationRoutingModule { } diff --git a/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts b/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts new file mode 100644 index 0000000000..b81855b79d --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts @@ -0,0 +1,30 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { NotificationRoutingModule } from '@home/pages/notification/notification-routing.module'; + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + SharedModule, + NotificationRoutingModule + ] +}) +export class NotificationModule { } diff --git a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-routing.module.ts b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-routing.module.ts index f83aca1841..2af6910e23 100644 --- a/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/ota-update/ota-update-routing.module.ts @@ -24,7 +24,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models'; import { BreadCrumbConfig } from '@shared/components/breadcrumb'; -const routes: Routes = [ +export const otaUpdatesRoutes: Routes = [ { path: 'otaUpdates', data: { @@ -65,6 +65,18 @@ const routes: Routes = [ } ]; +const routes: Routes = [ + { + path: 'otaUpdates', + pathMatch: 'full', + redirectTo: '/features/otaUpdates' + }, + { + path: 'otaUpdates/:entityId', + redirectTo: '/features/otaUpdates/:entityId' + } +]; + @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index ab553793fc..5efc23a85b 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -1456,7 +1456,7 @@ export class RuleChainPageComponent extends PageComponent this.isDirtyValue = false; this.isImport = false; if (this.ruleChainType !== RuleChainType.EDGE) { - this.router.navigateByUrl(`ruleChains/${this.ruleChain.id.id}`); + this.router.navigateByUrl(`features/ruleChains/${this.ruleChain.id.id}`); } else { this.router.navigateByUrl(`edgeManagement/ruleChains/${this.ruleChain.id.id}`); } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts index d8a22c67db..ec2148b576 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts @@ -122,7 +122,7 @@ export const importRuleChainBreadcumbLabelFunction: BreadCrumbLabelFunction - - - diff --git a/ui-ngx/src/app/modules/home/pages/vc/vc-routing.module.ts b/ui-ngx/src/app/modules/home/pages/vc/vc-routing.module.ts index 9117e7d0c4..9687d60973 100644 --- a/ui-ngx/src/app/modules/home/pages/vc/vc-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/vc/vc-routing.module.ts @@ -20,7 +20,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { Authority } from '@shared/models/authority.enum'; import { VersionControlComponent } from '@home/components/vc/version-control.component'; -const routes: Routes = [ +export const vcRoutes: Routes = [ { path: 'vc', component: VersionControlComponent, @@ -36,6 +36,13 @@ const routes: Routes = [ } ]; +const routes: Routes = [ + { + path: 'vc', + redirectTo: '/features/vc' + } +]; + @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts index 974f0f0ae7..368ce8b138 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-library-routing.module.ts @@ -27,8 +27,8 @@ import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { WidgetService } from '@core/http/widget.service'; import { WidgetEditorComponent } from '@home/pages/widget/widget-editor.component'; import { map } from 'rxjs/operators'; -import { detailsToWidgetInfo, toWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; -import { widgetType, WidgetType, WidgetTypeDetails } from '@app/shared/models/widget.models'; +import { detailsToWidgetInfo, WidgetInfo } from '@home/models/widget-component.models'; +import { widgetType, WidgetTypeDetails } from '@app/shared/models/widget.models'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { WidgetsData } from '@home/models/dashboard-component.models'; import { NULL_UUID } from '@shared/models/id/has-uuid'; @@ -120,7 +120,7 @@ export const widgetTypesBreadcumbLabelFunction: BreadCrumbLabelFunction = ( export const widgetEditorBreadcumbLabelFunction: BreadCrumbLabelFunction = ((route, translate, component) => component ? component.widget.widgetName : ''); -export const routes: Routes = [ +export const widgetsBundlesRoutes: Routes = [ { path: 'widgets-bundles', data: { @@ -199,6 +199,28 @@ export const routes: Routes = [ ] } ] + }, +]; + +const routes: Routes = [ + { + path: 'widgets-bundles', + pathMatch: 'full', + redirectTo: '/resources/widgets-bundles' + }, + { + path: 'widgets-bundles/:widgetsBundleId/widgetTypes', + pathMatch: 'full', + redirectTo: '/resources/widgets-bundles/:widgetsBundleId/widgetTypes', + }, + { + path: 'widgets-bundles/:widgetsBundleId/widgetTypes/:widgetTypeId', + pathMatch: 'full', + redirectTo: '/resources/widgets-bundles/:widgetsBundleId/widgetTypes/:widgetTypeId', + }, + { + path: 'widgets-bundles/:widgetsBundleId/widgetTypes/add/:widgetType', + redirectTo: '/resources/widgets-bundles/:widgetsBundleId/widgetTypes/add/:widgetType', } ]; diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundles-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundles-table-config.resolver.ts index f501007883..6fd2804ae3 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundles-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundles-table-config.resolver.ts @@ -160,7 +160,7 @@ export class WidgetsBundlesTableConfigResolver implements Resolve

    - {{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }} + {{ breadcrumb.ignoreTranslate + ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : utils.customTranslation(breadcrumb.label, breadcrumb.label)) + : (breadcrumb.label | translate) }}

    - - - - {{ breadcrumb.icon }} - - {{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }} + + - - - - {{ breadcrumb.icon }} - - {{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }} + + >
    + + + + + + {{ breadcrumb.icon }} + + {{ breadcrumb.ignoreTranslate + ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : utils.customTranslation(breadcrumb.label, breadcrumb.label)) + : (breadcrumb.label | translate) }} + diff --git a/ui-ngx/src/app/shared/components/breadcrumb.component.ts b/ui-ngx/src/app/shared/components/breadcrumb.component.ts index 10050c4826..2542f58871 100644 --- a/ui-ngx/src/app/shared/components/breadcrumb.component.ts +++ b/ui-ngx/src/app/shared/components/breadcrumb.component.ts @@ -18,10 +18,12 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy import { BehaviorSubject, Subject, Subscription } from 'rxjs'; import { BreadCrumb, BreadCrumbConfig } from './breadcrumb'; import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router'; -import { distinctUntilChanged, filter, map } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { guid } from '@core/utils'; import { BroadcastService } from '@core/services/broadcast.service'; +import { ActiveComponentService } from '@core/services/active-component.service'; +import { UtilsService } from '@core/services/utils.service'; @Component({ selector: 'tb-breadcrumb', @@ -34,8 +36,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { activeComponentValue: any; updateBreadcrumbsSubscription: Subscription = null; - @Input() - set activeComponent(activeComponent: any) { + setActiveComponent(activeComponent: any) { if (this.updateBreadcrumbsSubscription) { this.updateBreadcrumbsSubscription.unsubscribe(); this.updateBreadcrumbsSubscription = null; @@ -48,7 +49,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { } } - breadcrumbs$: Subject> = new BehaviorSubject>(this.buildBreadCrumbs(this.activatedRoute.snapshot)); + breadcrumbs$: Subject> = new BehaviorSubject>([]); routerEventsSubscription = this.router.events.pipe( filter((event) => event instanceof NavigationEnd ), @@ -56,6 +57,8 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { map( () => this.buildBreadCrumbs(this.activatedRoute.snapshot) ) ).subscribe(breadcrumns => this.breadcrumbs$.next(breadcrumns) ); + activeComponentSubscription = this.activeComponentService.onActiveComponentChanged().subscribe(comp => this.setActiveComponent(comp)); + lastBreadcrumb$ = this.breadcrumbs$.pipe( map( breadcrumbs => breadcrumbs[breadcrumbs.length - 1]) ); @@ -63,20 +66,26 @@ export class BreadcrumbComponent implements OnInit, OnDestroy { constructor(private router: Router, private activatedRoute: ActivatedRoute, private broadcast: BroadcastService, + private activeComponentService: ActiveComponentService, private cd: ChangeDetectorRef, - private translate: TranslateService) { + private translate: TranslateService, + public utils: UtilsService) { } ngOnInit(): void { this.broadcast.on('updateBreadcrumb', () => { this.cd.markForCheck(); }); + this.setActiveComponent(this.activeComponentService.getCurrentActiveComponent()); } ngOnDestroy(): void { if (this.routerEventsSubscription) { this.routerEventsSubscription.unsubscribe(); } + if (this.activeComponentSubscription) { + this.activeComponentSubscription.unsubscribe(); + } } private lastChild(route: ActivatedRouteSnapshot) { diff --git a/ui-ngx/src/app/shared/models/alarm.models.ts b/ui-ngx/src/app/shared/models/alarm.models.ts index 5f0f7f37ef..a176d2a69a 100644 --- a/ui-ngx/src/app/shared/models/alarm.models.ts +++ b/ui-ngx/src/app/shared/models/alarm.models.ts @@ -26,6 +26,11 @@ import { TableCellButtonActionDescriptor } from '@home/components/widget/lib/tab import { AlarmCommentId } from '@shared/models/id/alarm-comment-id'; import { UserId } from '@shared/models/id/user-id'; +export enum AlarmsMode { + ALL, + ENTITY +} + export enum AlarmSeverity { CRITICAL = 'CRITICAL', MAJOR = 'MAJOR', @@ -278,7 +283,7 @@ export class AlarmQuery { } public toQuery(): string { - let query = `/${this.affectedEntityId.entityType}/${this.affectedEntityId.id}`; + let query = this.affectedEntityId ? `/${this.affectedEntityId.entityType}/${this.affectedEntityId.id}` : ''; query += this.pageLink.toQuery(); if (this.searchStatus) { query += `&searchStatus=${this.searchStatus}`; diff --git a/ui-ngx/src/app/shared/models/asset.models.ts b/ui-ngx/src/app/shared/models/asset.models.ts index 4e7f24e284..a1ab16fdc8 100644 --- a/ui-ngx/src/app/shared/models/asset.models.ts +++ b/ui-ngx/src/app/shared/models/asset.models.ts @@ -39,6 +39,7 @@ export interface AssetProfile extends BaseData, ExportableEntity } export interface AssetProfileInfo extends EntityInfoData { + tenantId?: TenantId; image?: string; defaultDashboardId?: DashboardId; } diff --git a/ui-ngx/src/app/shared/models/device.models.ts b/ui-ngx/src/app/shared/models/device.models.ts index df7ba701c7..ae601b0039 100644 --- a/ui-ngx/src/app/shared/models/device.models.ts +++ b/ui-ngx/src/app/shared/models/device.models.ts @@ -500,13 +500,15 @@ export interface CustomTimeSchedulerItem{ endsOn: number; } -export interface AlarmRule { +interface AlarmRule { condition: AlarmCondition; alarmDetails?: string; dashboardId?: DashboardId; schedule?: AlarmSchedule; } +export { AlarmRule as DeviceProfileAlarmRule }; + export function alarmRuleValidator(control: AbstractControl): ValidationErrors | null { const alarmRule: AlarmRule = control.value; return alarmRuleValid(alarmRule) ? null : {alarmRule: true}; @@ -585,6 +587,7 @@ export interface DeviceProfile extends BaseData, ExportableEnti } export interface DeviceProfileInfo extends EntityInfoData { + tenantId?: TenantId; type: DeviceProfileType; transportType: DeviceTransportType; image?: string; diff --git a/ui-ngx/src/app/shared/models/entity-type.models.ts b/ui-ngx/src/app/shared/models/entity-type.models.ts index f421626082..fb40b78944 100644 --- a/ui-ngx/src/app/shared/models/entity-type.models.ts +++ b/ui-ngx/src/app/shared/models/entity-type.models.ts @@ -256,7 +256,7 @@ export const entityTypeTranslations = new Map([ [EntityType.CUSTOMER, '/customers'], [EntityType.USER, '/users'], [EntityType.DASHBOARD, '/dashboards'], - [EntityType.ASSET, '/assets'], - [EntityType.DEVICE, '/devices'], + [EntityType.ASSET, '/entities/assets'], + [EntityType.DEVICE, '/entities/devices'], [EntityType.DEVICE_PROFILE, '/profiles/deviceProfiles'], [EntityType.ASSET_PROFILE, '/profiles/assetProfiles'], - [EntityType.RULE_CHAIN, '/ruleChains'], - [EntityType.EDGE, '/edgeInstances'], - [EntityType.ENTITY_VIEW, '/entityViews'], - [EntityType.TB_RESOURCE, '/settings/resources-library'], - [EntityType.OTA_PACKAGE, '/otaUpdates'], + [EntityType.RULE_CHAIN, '/features/ruleChains'], + [EntityType.EDGE, '/edgeManagement/instances'], + [EntityType.ENTITY_VIEW, '/entities/entityViews'], + [EntityType.TB_RESOURCE, '/resources/resources-library'], + [EntityType.OTA_PACKAGE, '/features/otaUpdates'], [EntityType.QUEUE, '/settings/queues'] ]); diff --git a/ui-ngx/src/app/shared/models/public-api.ts b/ui-ngx/src/app/shared/models/public-api.ts index e9495fde50..bfc430db09 100644 --- a/ui-ngx/src/app/shared/models/public-api.ts +++ b/ui-ngx/src/app/shared/models/public-api.ts @@ -51,6 +51,7 @@ export * from './rule-node.models'; export * from './settings.models'; export * from './tenant.model'; export * from './user.model'; +export * from './user-settings.models'; export * from './widget.models'; export * from './widgets-bundle.model'; export * from './window-message.model'; diff --git a/ui-ngx/src/app/shared/models/user-settings.models.ts b/ui-ngx/src/app/shared/models/user-settings.models.ts new file mode 100644 index 0000000000..f64b12ea71 --- /dev/null +++ b/ui-ngx/src/app/shared/models/user-settings.models.ts @@ -0,0 +1,23 @@ +/// +/// Copyright © 2016-2023 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +export interface UserSettings { + openedMenuSections?: string[]; +} + +export const initialUserSettings: UserSettings = { + openedMenuSections: [] +}; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index f706a30d46..60c3c395fd 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -79,9 +79,11 @@ "none": "None" }, "admin": { + "settings": "Settings", "general": "General", "general-settings": "General Settings", "home-settings": "Home Settings", + "home": "Home", "outgoing-mail": "Mail Server", "outgoing-mail-settings": "Outgoing Mail Server Settings", "system-settings": "System Settings", @@ -328,6 +330,7 @@ "queue-processing-strategy": "Processing strategy", "queue-configuration": "Queue configuration", "repository-settings": "Repository settings", + "repository": "Repository", "repository-url": "Repository URL", "repository-url-required": "Repository URL is required.", "default-branch": "Default branch name", @@ -349,6 +352,7 @@ "delete-repository-settings-title": "Are you sure you want to delete repository settings?", "delete-repository-settings-text": "Be careful, after the confirmation the repository settings will be removed and version control feature will be unavailable.", "auto-commit-settings": "Auto-commit settings", + "auto-commit": "Auto-commit", "auto-commit-entities": "Auto-commit entities", "no-auto-commit-entities-prompt": "No entities configured for auto-commit", "delete-auto-commit-settings-title": "Are you sure you want to delete auto-commit settings?", @@ -408,6 +412,9 @@ "info-header": "All users will be to re-logined", "info-message": "Change of the JWT Signing Key will cause all issued tokens to be invalid. All users will need to re-login. This will also affect scripts that use Rest API/Websockets." }, + "resources": "Resources", + "notifications": "Notifications", + "notifications-settings": "Notifications settings", "notification": { "notification-settings": "Notification settings", "slack-api-token": "Slack api token", @@ -417,6 +424,7 @@ "alarm": { "alarm": "Alarm", "alarms": "Alarms", + "all-alarms": "All alarms", "select-alarm": "Select alarm", "no-alarms-matching": "No alarms matching '{{entity}}' were found.", "alarm-required": "Alarm is required", @@ -1737,6 +1745,7 @@ "edge": { "edge": "Edge", "edge-instances": "Edge instances", + "instances": "Instances", "edge-file": "Edge file", "name-max-length": "Name should be less than 256", "label-max-length": "Label should be less than 256", @@ -1960,7 +1969,7 @@ "dashboard-name-starts-with": "Dashboards whose names start with '{{prefix}}'", "type-alarm": "Alarm", "type-alarms": "Alarms", - "list-of-alarms": "{ count, plural, =1 {One alarms} other {List of # alarms} }", + "list-of-alarms": "{ count, plural, =1 {One alarm} other {List of # alarms} }", "alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'", "type-rulechain": "Rule chain", "type-rulechains": "Rule chains", @@ -2336,6 +2345,9 @@ "file": "Extensions file", "invalid-file-error": "Invalid extension file" }, + "feature": { + "advanced-features": "Advanced features" + }, "filter": { "add": "Add filter", "edit": "Edit filter", @@ -2831,6 +2843,7 @@ "notify-on-unassign": "Notify on unassign", "platform-users": "Platform users", "recipient": "Recipient", + "recipients": "Recipients", "recipient-type": "Recipient type", "recipients-count": "{ count, plural, =1 {1 Recipient} other {# Recipients} }", "request-status": { diff --git a/ui-ngx/src/assets/mdi.svg b/ui-ngx/src/assets/mdi.svg deleted file mode 100644 index abc8408067..0000000000 --- a/ui-ngx/src/assets/mdi.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index 6955a940a4..f784cc0de0 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -2443,6 +2443,11 @@ "@material/theme" "15.0.0-canary.684e33d25.0" tslib "^2.1.0" +"@mdi/svg@^7.1.96": + version "7.1.96" + resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-7.1.96.tgz#4911ee6d2f3457f016be8b7a454cf1a8e5c361f0" + integrity sha512-QO+CyF7eZsYBJpyb9Q77r1O6PFdp/Ircx8FMV7+cFS7g0p5rF55PA9zrmzuZqi1LyPKANDpr0oULNLHgeQuXZQ== + "@messageformat/core@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@messageformat/core/-/core-3.0.1.tgz#191e12cf9643704d1fd32e592a3fbdc194dd588e"