UI: Move send notification button router tabs panel.

This commit is contained in:
Igor Kulikov 2023-03-24 19:24:31 +02:00
parent 5f3e277ca1
commit 97278c9ef2
10 changed files with 132 additions and 91 deletions

View File

@ -178,6 +178,7 @@ import { modulesMap } from '@modules/common/modules-map';
import { SlackConversationAutocompleteComponent } from '@home/components/notification/slack-conversation-autocomplete.component';
import { AlarmAssigneePanelComponent } from '@home/components/alarm/alarm-assignee-panel.component';
import { RouterTabsComponent } from '@home/components/router-tabs.component';
import { SendNotificationButtonComponent } from '@home/components/notification/send-notification-button.component';
@NgModule({
declarations:
@ -324,7 +325,8 @@ import { RouterTabsComponent } from '@home/components/router-tabs.component';
RateLimitsComponent,
RateLimitsTextComponent,
RateLimitsDetailsDialogComponent,
SlackConversationAutocompleteComponent
SlackConversationAutocompleteComponent,
SendNotificationButtonComponent
],
imports: [
CommonModule,
@ -464,7 +466,8 @@ import { RouterTabsComponent } from '@home/components/router-tabs.component';
RateLimitsComponent,
RateLimitsTextComponent,
RateLimitsDetailsDialogComponent,
SlackConversationAutocompleteComponent
SlackConversationAutocompleteComponent,
SendNotificationButtonComponent
],
providers: [
WidgetComponentService,

View File

@ -15,10 +15,12 @@
limitations under the License.
-->
<div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
<button mat-flat-button color="primary" (click)="sendNotification($event)">
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon>send</mat-icon>{{ 'notification.send-notification' | translate }}
</div>
<div *ngIf="show()" fxLayout="row" fxLayoutAlign="end end" style="height: 100%; padding: 0 16px;">
<button fxHide.lt-md mat-flat-button color="primary" (click)="sendNotification($event)">
<mat-icon>send</mat-icon>
<span translate>notification.send-notification</span>
</button>
<button class="mat-elevation-z0" fxHide.gt-sm mat-mini-fab color="primary" (click)="sendNotification($event)">
<mat-icon>send</mat-icon>
</button>
</div>

View File

@ -0,0 +1,73 @@
///
/// 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 { Component } from '@angular/core';
import {
RequestNotificationDialogData,
SentNotificationDialogComponent
} from '@home/pages/notification/sent/sent-notification-dialog.componet';
import { NotificationTemplate } from '@shared/models/notification.models';
import { MatDialog } from '@angular/material/dialog';
import { ActiveComponentService } from '@core/services/active-component.service';
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
import { EntityType } from '@shared/models/entity-type.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
import { Authority } from '@shared/models/authority.enum';
@Component({
selector: 'tb-send-notification-button',
templateUrl: './send-notification-button.component.html',
})
export class SendNotificationButtonComponent {
authUser = getCurrentAuthUser(this.store);
constructor(private dialog: MatDialog,
private store: Store<AppState>,
private activeComponentService: ActiveComponentService) {
}
sendNotification($event: Event) {
if ($event) {
$event.stopPropagation();
}
this.dialog.open<SentNotificationDialogComponent, RequestNotificationDialogData,
NotificationTemplate>(SentNotificationDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
isAdd: true
}
}).afterClosed().subscribe((res) => {
if (res) {
const comp = this.activeComponentService.getCurrentActiveComponent();
if (comp instanceof EntitiesTableComponent) {
const entitiesTableComponent = comp as EntitiesTableComponent;
if (entitiesTableComponent.entitiesTableConfig.entityType === EntityType.NOTIFICATION_REQUEST) {
entitiesTableComponent.entitiesTableConfig.updateData();
}
}
}
});
}
public show(): boolean {
return this.authUser.authority !== Authority.CUSTOMER_USER;
}
}

View File

@ -16,18 +16,21 @@
-->
<div fxFlex fxLayout="column" style="width: 100%;">
<nav *ngIf="!routerOutlet?.activatedRouteData?.hideTabs && !hideCurrentTabs && (tabs$ | async).length > 1" mat-tab-nav-bar mat-stretch-tabs="false" class="tb-router-tabs" [tabPanel]="tabPanel">
<a *ngFor="let tab of tabs$ | async"
routerLink="{{tab.path}}"
routerLinkActive
#rla="routerLinkActive"
mat-tab-link
[active]="rla.isActive">
<mat-icon *ngIf="!tab.isMdiIcon && tab.icon !== null" class="tb-mat-18">{{tab.icon}}</mat-icon>
<mat-icon *ngIf="tab.isMdiIcon && tab.icon !== null" [svgIcon]="tab.icon" class="tb-mat-18"></mat-icon>
<span>{{tab.name | translate}}</span>
</a>
</nav>
<div fxLayout="row" style="width: 100%;">
<nav fxFlex *ngIf="!routerOutlet?.activatedRouteData?.hideTabs && !hideCurrentTabs && (tabs$ | async).length > 1" mat-tab-nav-bar mat-stretch-tabs="false" class="tb-router-tabs" [tabPanel]="tabPanel">
<a *ngFor="let tab of tabs$ | async"
routerLink="{{tab.path}}"
routerLinkActive
#rla="routerLinkActive"
mat-tab-link
[active]="rla.isActive">
<mat-icon *ngIf="!tab.isMdiIcon && tab.icon !== null" class="tb-mat-18">{{tab.icon}}</mat-icon>
<mat-icon *ngIf="tab.isMdiIcon && tab.icon !== null" [svgIcon]="tab.icon" class="tb-mat-18"></mat-icon>
<span>{{tab.name | translate}}</span>
</a>
</nav>
<tb-anchor #tabsHeaderComponent></tb-anchor>
</div>
<mat-tab-nav-panel #tabPanel fxFlex fxLayout="column" class="tb-router-tabs-content">
<router-outlet #routerOutlet="outlet" (activate)="activeComponentChanged($event)"></router-outlet>
</mat-tab-nav-panel>

View File

@ -14,33 +14,35 @@
/// limitations under the License.
///
import { Component, Inject } from '@angular/core';
import { Component, ComponentRef, OnInit, Type, ViewChild } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { WINDOW } from '@core/services/window.service';
import { BreakpointObserver } from '@angular/cdk/layout';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { MenuService } from '@core/services/menu.service';
import { distinctUntilChanged, filter, map, mergeMap, take } from 'rxjs/operators';
import { merge } from 'rxjs';
import { MenuSection } from '@core/services/menu.models';
import { ActiveComponentService } from '@core/services/active-component.service';
import { TbAnchorComponent } from '@shared/components/tb-anchor.component';
@Component({
selector: 'tb-router-tabs',
templateUrl: './router-tabs.component.html',
styleUrls: ['./router-tabs.component.scss']
})
export class RouterTabsComponent extends PageComponent {
export class RouterTabsComponent extends PageComponent implements OnInit {
@ViewChild('tabsHeaderComponent', {static: true}) tabsHeaderComponentAnchor: TbAnchorComponent;
tabsHeaderComponentRef: ComponentRef<any>;
hideCurrentTabs = false;
tabs$ = merge(this.menuService.menuSections(),
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd ),
distinctUntilChanged()
)
distinctUntilChanged())
).pipe(
mergeMap(() => this.menuService.menuSections().pipe(take(1))),
map((sections) => this.buildTabs(this.activatedRoute, sections))
@ -50,12 +52,16 @@ export class RouterTabsComponent extends PageComponent {
private activatedRoute: ActivatedRoute,
public router: Router,
private menuService: MenuService,
private activeComponentService: ActiveComponentService,
@Inject(WINDOW) private window: Window,
public breakpointObserver: BreakpointObserver) {
private activeComponentService: ActiveComponentService) {
super(store);
}
ngOnInit() {
this.activatedRoute.data.subscribe(
(data) => this.buildTabsHeaderComponent(data)
);
}
activeComponentChanged(activeComponent: any) {
this.activeComponentService.setCurrentActiveComponent(activeComponent);
let snapshot = this.router.routerState.snapshot.root;
@ -103,4 +109,17 @@ export class RouterTabsComponent extends PageComponent {
return null;
}
private buildTabsHeaderComponent(snapshotData: any) {
const viewContainerRef = this.tabsHeaderComponentAnchor.viewContainerRef;
if (this.tabsHeaderComponentRef) {
this.tabsHeaderComponentRef.destroy();
this.tabsHeaderComponentRef = null;
viewContainerRef.clear();
}
const tabsHeaderComponentType: Type<any> = snapshotData.routerTabsHeaderComponent;
if (tabsHeaderComponentType) {
this.tabsHeaderComponentRef = viewContainerRef.createComponent(tabsHeaderComponentType, {index: 0});
}
}
}

View File

@ -24,6 +24,7 @@ import { SentTableConfigResolver } from '@home/pages/notification/sent/sent-tabl
import { RecipientTableConfigResolver } from '@home/pages/notification/recipient/recipient-table-config.resolver';
import { TemplateTableConfigResolver } from '@home/pages/notification/template/template-table-config.resolver';
import { RuleTableConfigResolver } from '@home/pages/notification/rule/rule-table-config.resolver';
import { SendNotificationButtonComponent } from '@home/components/notification/send-notification-button.component';
const routes: Routes = [
{
@ -34,7 +35,8 @@ const routes: Routes = [
breadcrumb: {
label: 'notification.notification-center',
icon: 'mdi:message-badge'
}
},
routerTabsHeaderComponent: SendNotificationButtonComponent
},
children: [
{

View File

@ -36,7 +36,6 @@ import { EscalationFormComponent } from '@home/pages/notification/rule/escalatio
import { EscalationsComponent } from '@home/pages/notification/rule/escalations.component';
import { RuleNotificationDialogComponent } from '@home/pages/notification/rule/rule-notification-dialog.component';
import { RuleTableHeaderComponent } from '@home/pages/notification/rule/rule-table-header.component';
import { SentTableHeaderComponent } from '@home/pages/notification/sent/sent-table-header.component';
@NgModule({
declarations: [
@ -52,8 +51,7 @@ import { SentTableHeaderComponent } from '@home/pages/notification/sent/sent-tab
EscalationFormComponent,
EscalationsComponent,
RuleNotificationDialogComponent,
RuleTableHeaderComponent,
SentTableHeaderComponent
RuleTableHeaderComponent
],
imports: [
CommonModule,

View File

@ -47,7 +47,6 @@ import {
} from '@home/pages/notification/sent/sent-error-dialog.component';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
import { Injectable } from '@angular/core';
import { SentTableHeaderComponent } from '@home/pages/notification/sent/sent-table-header.component';
@Injectable()
export class SentTableConfigResolver implements Resolve<EntityTableConfig<NotificationRequest, PageLink, NotificationRequestInfo>> {
@ -77,7 +76,6 @@ export class SentTableConfigResolver implements Resolve<EntityTableConfig<Notifi
this.config.cellActionDescriptors = this.configureCellActions();
this.config.headerComponent = SentTableHeaderComponent;
this.config.onEntityAction = action => this.onRequestAction(action);
this.config.handleRowClick = (event, entity) => {

View File

@ -1,18 +0,0 @@
/**
* 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.
*/
:host{
width: 10000px;
}

View File

@ -1,39 +0,0 @@
///
/// 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 { Component } from '@angular/core';
import { EntityTableHeaderComponent } from '@home/components/entity/entity-table-header.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { NotificationRequest, NotificationRequestInfo } from '@shared/models/notification.models';
import { PageLink } from '@shared/models/page/page-link';
@Component({
selector: 'tb-sent-table-header',
templateUrl: './sent-table-header.component.html',
styleUrls: ['sent-table-header.component.scss']
})
export class SentTableHeaderComponent extends EntityTableHeaderComponent<NotificationRequest, PageLink, NotificationRequestInfo> {
constructor(protected store: Store<AppState>) {
super(store);
}
sendNotification($event: Event) {
this.entitiesTableConfig.onEntityAction({event: $event, action: 'add', entity: null});
}
}