feat(notification): Add undoable notification, close #318 (#338)

* feat(notification): Add undoable notification

* feat(notification): Add undoable notification

* feat(notification): Use uhk-header to the notification

* half ready solution

* - fix: "Keymap has been deleted" is displayed for macros.
- When a keymap/macro deletion gets undone, please set the route of the restored keymap/macro.
- When the user switches to another route, please make the undo notification disappear.

* fix(keymap): Store prev user configuration in the application reducer

Store the previous state in application reducer, because refactoring the
user-config reducer is not easy

* feat(keymap): Fix review request
This commit is contained in:
Róbert Kiss
2017-07-23 22:17:53 +02:00
committed by László Monda
parent ce55cac380
commit 42683e32f9
19 changed files with 295 additions and 64 deletions

View File

@@ -14,4 +14,4 @@
<div *ngIf="!macro" class="not-found">
There is no macro with id {{ route.params.select('id') | async }}.
</div>
</div>

View File

@@ -1,4 +1,8 @@
<uhk-header></uhk-header>
<div class="not-found">
You don't have any macros. Try to add one!
<div class="container-fluid">
<uhk-header>
<h1>&nbsp;</h1>
</uhk-header>
<div class="not-found">
You don't have any macros. Try to add one!
</div>
</div>

View File

@@ -1,3 +1,12 @@
<div>
<ng-content></ng-content>
</div>
<div class="row">
<div class="col-xs-12">
<undoable-notifier [notification]="undoableNotification$ | async"
(close)="onDismissLastNotification()"
(undo)="onUndoLastNotification($event)">
</undoable-notifier>
</div>
</div>

View File

@@ -1,4 +1,10 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { Notification } from '../../models/notification';
import { AppState, getUndoableNotification } from '../../store/index';
import { DismissUndoNotificationAction, UndoLastAction } from '../../store/actions/app.action';
@Component({
selector: 'uhk-header',
@@ -6,4 +12,18 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UhkHeader {
undoableNotification$: Observable<Notification>;
constructor(private store: Store<AppState>) {
this.undoableNotification$ = this.store.select(getUndoableNotification);
}
onUndoLastNotification(data: any): void {
this.store.dispatch(new UndoLastAction(data));
}
onDismissLastNotification(): void {
this.store.dispatch(new DismissUndoNotificationAction());
}
}

View File

@@ -0,0 +1 @@
export * from './undoable-notifier.component';

View File

@@ -0,0 +1,12 @@
<div class="pull-right">
<div class="alert alert-warning alert-dismissible" role="alert" [@slideInOut]="slideInOut">
<button type="button"
class="close"
aria-label="Close"
(click)="clickOnClose()">
<span aria-hidden="true">&times;</span>
</button>
{{text}}
<a *ngIf="undoable" (click)="clickOnUndo()" class="undo-button">Undo</a>
</div>
</div>

View File

@@ -0,0 +1,13 @@
.alert {
padding: 5px 10px 5px 5px;
margin-bottom: 0.25em;
margin-top: -2em;
.close {
right: -5px;
}
.undo-button {
cursor: pointer;
}
}

View File

@@ -0,0 +1,52 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { Notification } from '../../models/notification';
@Component({
selector: 'undoable-notifier',
templateUrl: './undoable-notifier.component.html',
styleUrls: ['./undoable-notifier.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger('slideInOut', [
state('in', style({
transform: 'translate3d(0, 0, 0)'
})),
state('out', style({
transform: 'translate3d(200%, 0, 0)'
})),
transition('in => out', animate('400ms ease-in-out')),
transition('out => in', animate('400ms ease-in-out'))
])
]
})
export class UndoableNotifierComponent implements OnChanges {
text: string;
undoable: boolean;
@Input() notification: Notification;
@Output() close = new EventEmitter();
@Output() undo = new EventEmitter();
get slideInOut() {
return this.notification ? 'in' : 'out';
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['notification']) {
const not: Notification = changes['notification'].currentValue;
if (not) {
this.text = not.message;
this.undoable = !!not.extra;
}
}
}
clickOnClose(): void {
this.close.emit();
}
clickOnUndo(): void {
this.undo.emit(this.notification.extra);
}
}