noti
This commit is contained in:
parent
c1a5179bfc
commit
65cb4454d8
|
@ -7,7 +7,7 @@
|
|||
</button>
|
||||
<span class="spacer"></span>
|
||||
|
||||
<of-notification [notifications]="toolbarHelpers?.notifications"></of-notification>
|
||||
<of-notification-badge [notifications]="toolbarHelpers?.notifications"></of-notification-badge>
|
||||
<div class="menu-section">
|
||||
<button mat-icon-button [matMenuTriggerFor]="countryMenu" aria-label="Open x-positioned menu">
|
||||
<mat-icon>translate</mat-icon>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { NotificationPageComponent } from './notification-page.component';
|
||||
import { ListComponent as TargetListComponent } from 'packages/target/component/list/list.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: NotificationPageComponent,
|
||||
children: [
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class NotificationPageRoutingModule { }
|
|
@ -0,0 +1 @@
|
|||
<of-notification></of-notification>
|
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NotificationPageComponent } from './notification-page.component';
|
||||
|
||||
describe('NotificationPageComponent', () => {
|
||||
let component: NotificationPageComponent;
|
||||
let fixture: ComponentFixture<NotificationPageComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NotificationPageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NotificationPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
18
src/app/pages/notification/notification-page.component.ts
Normal file
18
src/app/pages/notification/notification-page.component.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'of-pages-notification',
|
||||
templateUrl: './notification-page.component.html',
|
||||
styleUrls: ['./notification-page.component.scss']
|
||||
})
|
||||
export class NotificationPageComponent implements OnInit {
|
||||
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
19
src/app/pages/notification/notification-page.module.ts
Normal file
19
src/app/pages/notification/notification-page.module.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NotificationPageComponent } from './notification-page.component';
|
||||
import { NotificationPageRoutingModule } from './notification-page-routing.module';
|
||||
import { MaterialModule } from 'app/commons/ui/material/material.module';
|
||||
import { NotificationModule } from 'packages/notification/notification.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
NotificationPageRoutingModule,
|
||||
MaterialModule,
|
||||
NotificationModule,
|
||||
],
|
||||
declarations: [
|
||||
NotificationPageComponent,
|
||||
]
|
||||
})
|
||||
export class NotificationPageModule { }
|
|
@ -20,6 +20,7 @@ const routes: Routes = [
|
|||
{ path: 'target', loadChildren: './target/target-page.module#TargetPageModule' },
|
||||
{ path: 'overview', loadChildren: './overview/overview-page.module#OverviewPageModule' },
|
||||
{ path: 'dashboard', loadChildren: './dashboard/dashboard-page.module#DashboardPageModule' },
|
||||
{ path: 'notification', loadChildren: './notification/notification-page.module#NotificationPageModule' },
|
||||
{ path: 'settings/member', loadChildren: './settings/member/member-page.module#MemberPageModule' },
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<div class="toolbar-notification-container">
|
||||
<button mat-icon-button (click)="isOpen = !isOpen;" [ngClass]="[cssPrefix+'-btn']" [class.open]="isOpen">
|
||||
<mat-icon>notifications_none</mat-icon>
|
||||
<span class="badge" *ngIf="notifications && notifications?.length !== 0">{{ notifications?.length }}</span>
|
||||
</button>
|
||||
|
||||
<div class="dropdown mat-elevation-z4" [class.open]="isOpen">
|
||||
|
||||
<div class="card">
|
||||
<div class="header" fxLayout="row" fxLayoutAlign="space-between center">
|
||||
<div class="title">
|
||||
<div class="name">Notifications</div>
|
||||
<div class="extra">
|
||||
<button mat-button (click)="handleMarkAllAsRead()">Mark all as read</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" mat-icon-button>
|
||||
<mat-icon class="icon">settings</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="notifications?.length !== 0; then thenBlock else elseBlock;"></div>
|
||||
<div class="footer" fxLayout="row" fxLayoutAlign="center center">
|
||||
<div class="action" (click)="handleViewAll()">View All</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ng-template #thenBlock>
|
||||
<perfect-scrollbar class="content">
|
||||
<div *ngFor="let notification of notifications; last as isLast">
|
||||
<div class="notification" fxLayout="row" fxLayoutAlign="start center" mat-ripple>
|
||||
<mat-icon class="icon">notifications</mat-icon>
|
||||
<div class="title" fxLayout="column">
|
||||
<div class="name">{{ notification.title }}</div>
|
||||
<div class="time">{{ notification.lastTime }}</div>
|
||||
</div>
|
||||
<span fxFlex></span>
|
||||
<button type="button" mat-icon-button (click)="delete(notification)">
|
||||
<mat-icon class="close">close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="divider" *ngIf="!isLast"></div>
|
||||
</div>
|
||||
</perfect-scrollbar>
|
||||
</ng-template>
|
||||
|
||||
<!-- <ng-template #elseBlock> -->
|
||||
<!-- <div class="no" fxLayout="row" fxLayoutAlign="center center">No notification found.</div>
|
||||
</ng-template> -->
|
|
@ -0,0 +1,165 @@
|
|||
$prefix: 'notification';
|
||||
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
font-weight: 700;
|
||||
line-height: 13px;
|
||||
height: 13px;
|
||||
padding: 5px;
|
||||
border-radius: 26%;
|
||||
width: 30%;
|
||||
background-color: #f44336;
|
||||
color: #fff;
|
||||
border-color:#f44336
|
||||
}
|
||||
|
||||
.#{$prefix} {
|
||||
&-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.dropdown {
|
||||
background: white;
|
||||
position: absolute;
|
||||
top: 42px;
|
||||
right: 28px;
|
||||
min-width: 350px;
|
||||
z-index: 2;
|
||||
transform: translateY(0) scale(0);
|
||||
transform-origin: top right;
|
||||
visibility: hidden;
|
||||
transition: transform .4s cubic-bezier(.25, .8, .25, 1), visibility .4s cubic-bezier(.25, .8, .25, 1);
|
||||
|
||||
@media screen and (max-width: 599px) {
|
||||
min-width: 50vw;
|
||||
right: 5px;
|
||||
transform: translateY(0);
|
||||
visibility: hidden;
|
||||
transition: transform .4s cubic-bezier(.25,.8,.25,1), visibility .4s cubic-bezier(.25,.8,.25,1);
|
||||
}
|
||||
|
||||
&.open {
|
||||
transform: translateY(0) scale(1);
|
||||
visibility: visible;
|
||||
}
|
||||
.card {
|
||||
|
||||
.header {
|
||||
background: #EEEEEE;
|
||||
min-height: 54px;
|
||||
padding-left: 16px;
|
||||
padding-right: 8px;
|
||||
color: #555;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
|
||||
.extra {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
overflow: hidden;
|
||||
max-height: 256px;
|
||||
|
||||
.notification {
|
||||
min-height: 64px;
|
||||
padding: 0 16px 0 14px;
|
||||
position: relative;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
line-height: 28px;
|
||||
font-size: 18px;
|
||||
margin-right: 13px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
background: #FFF;
|
||||
color: #888;
|
||||
border: 1px solid #EEE;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.close {
|
||||
font-size: 18px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
.icon {
|
||||
background: #ccc;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
&.accent {
|
||||
.icon {
|
||||
background: #aaa;
|
||||
color: #bbb;
|
||||
}
|
||||
}
|
||||
|
||||
&.warn {
|
||||
.icon {
|
||||
background: #eee;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
&.read {
|
||||
color: #999;
|
||||
|
||||
.name {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
min-height: 42px;
|
||||
border-top: 1px solid #EEE;
|
||||
|
||||
.action {
|
||||
cursor: pointer;
|
||||
color: #AAA;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: calc(100% - 30px);
|
||||
height: 1px;
|
||||
background: #EEE;
|
||||
margin: 0 16px 0 14px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NotificationBadgeComponent } from './notification.component';
|
||||
|
||||
describe('NotificationBadgeComponent', () => {
|
||||
let component: NotificationBadgeComponent;
|
||||
let fixture: ComponentFixture<NotificationBadgeComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ NotificationBadgeComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NotificationBadgeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'of-notification-badge',
|
||||
templateUrl: './notification.component.html',
|
||||
styleUrls: ['./notification.component.scss']
|
||||
})
|
||||
export class NotificationBadgeComponent implements OnInit {
|
||||
|
||||
cssPrefix = 'toolbar-notification';
|
||||
isOpen = false;
|
||||
@Input() notifications = [];
|
||||
|
||||
constructor(
|
||||
private router: Router
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
select() {
|
||||
|
||||
}
|
||||
|
||||
delete(notification) {
|
||||
|
||||
}
|
||||
|
||||
handleMarkAllAsRead() {
|
||||
console.log('Mark All');
|
||||
}
|
||||
|
||||
handleViewAll() {
|
||||
this.isOpen = false;
|
||||
this.router.navigate(['notification']);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import { NotificationComponent } from './notification/notification.component';
|
||||
import { NotificationBadgeComponent } from './badge/notification.component';
|
||||
|
||||
export const COMPONENTS = [
|
||||
NotificationComponent,
|
||||
NotificationBadgeComponent,
|
||||
];
|
||||
|
|
|
@ -1,52 +1 @@
|
|||
|
||||
<div class="toolbar-notification-container">
|
||||
<button mat-icon-button (click)="isOpen = !isOpen;" [ngClass]="[cssPrefix+'-btn']" [class.open]="isOpen">
|
||||
<mat-icon>notifications_none</mat-icon>
|
||||
<span class="badge" *ngIf="notifications && notifications?.length !== 0">{{ notifications?.length }}</span>
|
||||
</button>
|
||||
|
||||
<div class="dropdown mat-elevation-z4" [class.open]="isOpen">
|
||||
|
||||
<div class="card">
|
||||
<div class="header" fxLayout="row" fxLayoutAlign="space-between center">
|
||||
<div class="title">
|
||||
<div class="name">Notifications</div>
|
||||
<div class="extra">
|
||||
You have {{ notifications?.length }} new notifications</div>
|
||||
</div>
|
||||
<button type="button" mat-icon-button>
|
||||
<mat-icon class="icon">settings</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="notifications?.length !== 0; then thenBlock else elseBlock;"></div>
|
||||
<div class="footer" fxLayout="row" fxLayoutAlign="center center">
|
||||
<div class="action">Mark all as read</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ng-template #thenBlock>
|
||||
<perfect-scrollbar class="content">
|
||||
<div *ngFor="let notification of notifications; last as isLast">
|
||||
<div class="notification" fxLayout="row" fxLayoutAlign="start center" mat-ripple>
|
||||
<mat-icon class="icon">notifications</mat-icon>
|
||||
<div class="title" fxLayout="column">
|
||||
<div class="name">{{ notification.title }}</div>
|
||||
<div class="time">{{ notification.lastTime }}</div>
|
||||
</div>
|
||||
<span fxFlex></span>
|
||||
<button type="button" mat-icon-button (click)="delete(notification)">
|
||||
<mat-icon class="close">close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="divider" *ngIf="!isLast"></div>
|
||||
</div>
|
||||
</perfect-scrollbar>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #elseBlock>
|
||||
<div class="no" fxLayout="row" fxLayoutAlign="center center">????</div>
|
||||
</ng-template>
|
||||
<div>list</div>
|
|
@ -1,4 +1,5 @@
|
|||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'of-notification',
|
||||
|
@ -7,21 +8,11 @@ import { Component, OnInit, Input } from '@angular/core';
|
|||
})
|
||||
export class NotificationComponent implements OnInit {
|
||||
|
||||
cssPrefix = 'toolbar-notification';
|
||||
isOpen = false;
|
||||
@Input() notifications = [];
|
||||
|
||||
constructor() { }
|
||||
constructor(
|
||||
private router: Router
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
select() {
|
||||
|
||||
}
|
||||
|
||||
delete(notification) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div><h3>{{probeAlias}}</h3></div>
|
||||
<!-- <div><h3>{{probeAlias}}</h3></div>
|
||||
|
||||
<div fxLayout="row" fxLayoutWrap fxLayoutAlign="space-between center">
|
||||
<mat-card [style.padding]="'15px 50px'">Status: UP</mat-card>
|
||||
|
@ -20,4 +20,5 @@
|
|||
<mat-card fxFlex="30%" fxFlex.lt-sm="100" fxFlex.sm="30">
|
||||
<of-info-table [title]="'Title3'" [data]="probeInfo"></of-info-table>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div> -->
|
||||
<div>aaa</div>
|
|
@ -1,14 +1,22 @@
|
|||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import { Component, OnInit, Inject, AfterContentInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
||||
import { ConfirmDialogComponent } from 'app/commons/component/confirm-dialog/confirm-dialog.component';
|
||||
import * as DetailStore from '../../store/detail';
|
||||
import { DetailSelector } from '../../store';
|
||||
import { Store, select } from '@ngrx/store';
|
||||
import { Probe } from '../../model';
|
||||
import { RPCError } from 'packages/core/rpc/error';
|
||||
|
||||
@Component({
|
||||
selector: 'of-probe-detail',
|
||||
templateUrl: './detail.component.html',
|
||||
styleUrls: ['./detail.component.scss']
|
||||
})
|
||||
export class DetailComponent implements OnInit {
|
||||
export class DetailComponent implements OnInit, AfterContentInit {
|
||||
|
||||
probe$ = this.store.pipe(select(DetailSelector.select('probe')));
|
||||
probe: Probe = null;
|
||||
|
||||
probeAlias = '';
|
||||
probeId = undefined;
|
||||
|
@ -67,6 +75,7 @@ export class DetailComponent implements OnInit {
|
|||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private store: Store<DetailStore.State>
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -74,6 +83,23 @@ export class DetailComponent implements OnInit {
|
|||
this.probeAlias = 'Probe Alias 블라블라';
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.store.dispatch(
|
||||
new DetailStore.Read(
|
||||
{ id: this.probeId }
|
||||
)
|
||||
);
|
||||
this.probe$.subscribe(
|
||||
(probe: Probe) => {
|
||||
console.log(probe);
|
||||
this.probe = probe;
|
||||
},
|
||||
(error: RPCError) => {
|
||||
console.log(error.message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
handleStartStop() {
|
||||
this.isUpState = !this.isUpState;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { MetaProbeStatus } from 'packages/meta/model';
|
||||
import { Domain } from 'packages/domain/model';
|
||||
import { Member } from 'packages/member/model';
|
||||
import { Target } from 'packages/target/model';
|
||||
import { InfraHost } from 'packages/infra/model';
|
||||
import { Infra } from 'packages/infra/model';
|
||||
|
||||
export interface Probe {
|
||||
id?: number;
|
||||
|
@ -17,5 +16,5 @@ export interface Probe {
|
|||
authorizeDate?: Date;
|
||||
authorizeMember?: Member;
|
||||
// host?: InfraHost;
|
||||
targets?: Target[];
|
||||
targets?: Infra[];
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
import {
|
||||
State,
|
||||
initialState,
|
||||
adapter,
|
||||
} from './detail.state';
|
||||
|
||||
import { Probe } from '../../model';
|
||||
|
|
|
@ -14,9 +14,6 @@ import { Probe } from '../../model';
|
|||
// probe: null,
|
||||
// };
|
||||
|
||||
// export const getProbe = (state: State) => state.probe;
|
||||
// export const getError = (state: State) => state.error;
|
||||
// export const isPending = (state: State) => state.isPending;
|
||||
|
||||
import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity';
|
||||
|
||||
|
@ -32,6 +29,10 @@ export const initialState: State = adapter.getInitialState({
|
|||
probe: null,
|
||||
});
|
||||
|
||||
export const getProbe = (state: State) => state.probe;
|
||||
export const getError = (state: State) => state.error;
|
||||
export const isPending = (state: State) => state.isPending;
|
||||
|
||||
// export const {
|
||||
// selectIds,
|
||||
// selectEntities,
|
||||
|
|
Loading…
Reference in New Issue
Block a user