KEYCLOAK-10205: Alerts and Notifications

This commit is contained in:
Stan Silvert 2019-05-17 13:37:38 -04:00 committed by Bruno Oliveira da Silva
parent a050e70389
commit 38933fdfed
6 changed files with 115 additions and 10 deletions

View file

@ -18,6 +18,7 @@
//import {KeycloakNotificationService} from '../notification/keycloak-notification.service'; //import {KeycloakNotificationService} from '../notification/keycloak-notification.service';
import {KeycloakService} from '../keycloak-service/keycloak.service'; import {KeycloakService} from '../keycloak-service/keycloak.service';
import Axios, {AxiosRequestConfig, AxiosResponse} from 'axios'; import Axios, {AxiosRequestConfig, AxiosResponse} from 'axios';
import {ContentAlert} from '../content/ContentAlert';
//import {NotificationType} from 'patternfly-ng/notification';*/ //import {NotificationType} from 'patternfly-ng/notification';*/
@ -86,6 +87,7 @@ export class AccountServiceClient {
private handleError(error: Error): void { private handleError(error: Error): void {
console.log(error); console.log(error);
ContentAlert.danger(error.name + ': ' + error.message);
} }
private makeConfig(endpoint: string, config: AxiosRequestConfig = {}): Promise<AxiosRequestConfig> { private makeConfig(endpoint: string, config: AxiosRequestConfig = {}): Promise<AxiosRequestConfig> {

View file

@ -0,0 +1,100 @@
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates.
*
* 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 * as React from 'react';
import {Alert, AlertActionCloseButton} from '@patternfly/react-core';
import {Msg} from '../widgets/Msg';
interface ContentAlertProps {}
type AlertVariant = 'success' | 'danger' | 'warning' | 'info';
interface ContentAlertState {
isVisible: boolean;
message: string;
variant: AlertVariant;
}
export class ContentAlert extends React.Component<ContentAlertProps, ContentAlertState> {
private static instance: ContentAlert;
private constructor(props: ContentAlertProps) {
super(props);
this.state = {isVisible: false, message: '', variant: 'success'};
ContentAlert.instance = this;
}
/**
* @param message A literal text message or localization key.
*/
public static success(message: string) {
ContentAlert.instance.postAlert(message, 'success');
}
/**
* @param message A literal text message or localization key.
*/
public static danger(message: string) {
ContentAlert.instance.postAlert(message, 'danger');
}
/**
* @param message A literal text message or localization key.
*/
public static warning(message: string) {
ContentAlert.instance.postAlert(message, 'warning');
}
/**
* @param message A literal text message or localization key.
*/
public static info(message: string) {
ContentAlert.instance.postAlert(message, 'info');
}
private hideAlert = () => {
this.setState({isVisible: false});
}
private postAlert = (message: string, variant: AlertVariant) => {
this.setState({isVisible: true,
message: Msg.localize(message),
variant});
if (variant !== 'danger') {
setTimeout(() => this.setState({isVisible: false}), 5000);
}
}
public render(): React.ReactNode {
return (
<React.Fragment>
{ this.state.isVisible &&
<section className="pf-c-page__main-section pf-m-light">
<Alert
title=''
variant={this.state.variant}
variantLabel=''
aria-label=''
action={<AlertActionCloseButton onClose={this.hideAlert} />}
>
{this.state.message}
</Alert>
</section>
}
</React.Fragment>
);
}
}

View file

@ -16,6 +16,7 @@
import * as React from 'react'; import * as React from 'react';
import {Msg} from '../widgets/Msg'; import {Msg} from '../widgets/Msg';
import {ContentAlert} from './ContentAlert';
interface ContentPageProps { interface ContentPageProps {
title: string; // Literal title or key into message bundle title: string; // Literal title or key into message bundle
@ -35,6 +36,7 @@ export class ContentPage extends React.Component<ContentPageProps> {
public render(): React.ReactNode { public render(): React.ReactNode {
return ( return (
<React.Fragment> <React.Fragment>
<ContentAlert/>
<section className="pf-c-page__main-section pf-m-light"> <section className="pf-c-page__main-section pf-m-light">
<div className="pf-c-content"> <div className="pf-c-content">
<h1><Msg msgKey={this.props.title}/></h1> <h1><Msg msgKey={this.props.title}/></h1>

View file

@ -22,6 +22,7 @@ import {AccountServiceClient} from '../../account-service/account.service';
import {Features} from '../../widgets/features'; import {Features} from '../../widgets/features';
import {Msg} from '../../widgets/Msg'; import {Msg} from '../../widgets/Msg';
import {ContentPage} from '../ContentPage'; import {ContentPage} from '../ContentPage';
import {ContentAlert} from '../ContentAlert';
declare const features: Features; declare const features: Features;
@ -88,7 +89,7 @@ export class AccountPage extends React.Component<AccountPageProps, AccountPageSt
AccountServiceClient.Instance.doPost("/", {data: reqData}) AccountServiceClient.Instance.doPost("/", {data: reqData})
.then((response: AxiosResponse<FormFields>) => { .then((response: AxiosResponse<FormFields>) => {
this.setState({canSubmit: false}); this.setState({canSubmit: false});
alert('Data posted:' + response.statusText); ContentAlert.success('accountUpdatedMessage');
}); });
} }

View file

@ -74,7 +74,7 @@
map: { map: {
'./Accordion': '@empty', //'./Accordion/index.js, './Accordion': '@empty', //'./Accordion/index.js,
'./ActionGroup': './ActionGroup/index.js', './ActionGroup': './ActionGroup/index.js',
'./Alert': '@empty', //'./Alert/index.js', './Alert': './Alert/index.js',
'./AboutModal': '@empty', //'./AboutModal/index.js', './AboutModal': '@empty', //'./AboutModal/index.js',
'./ApplicationLauncher': '@empty', //'./ApplicationLauncher/index.js', './ApplicationLauncher': '@empty', //'./ApplicationLauncher/index.js',
'./Avatar': './Avatar/index.js', './Avatar': './Avatar/index.js',
@ -154,7 +154,7 @@
'./Gallery': '@empty', //'./Gallery/index.js', './Gallery': '@empty', //'./Gallery/index.js',
'./Level': '@empty', //'./Level/index.js', './Level': '@empty', //'./Level/index.js',
'./Grid': '@empty', //'./Grid/index.js', './Grid': '@empty', //'./Grid/index.js',
'./Stack': '@empty', //'./Stack/index.js', './Stack': './Stack/index.js',
'./Split': '@empty', //'./Split/index.js', './Split': '@empty', //'./Split/index.js',
'./Toolbar': './Toolbar/index.js', './Toolbar': './Toolbar/index.js',
} }
@ -332,7 +332,7 @@
'./icons/chart-line-icon.js': '@empty', './icons/chart-line-icon.js': '@empty',
'./icons/chart-pie-icon.js': '@empty', './icons/chart-pie-icon.js': '@empty',
'./icons/check-icon.js': '@empty', './icons/check-icon.js': '@empty',
'./icons/check-circle-icon.js': '@empty', //'./icons/check-circle-icon.js': '@empty',
'./icons/check-double-icon.js': '@empty', './icons/check-double-icon.js': '@empty',
'./icons/check-square-icon.js': '@empty', './icons/check-square-icon.js': '@empty',
'./icons/cheese-icon.js': '@empty', './icons/cheese-icon.js': '@empty',
@ -466,8 +466,8 @@
'./icons/euro-sign-icon.js': '@empty', './icons/euro-sign-icon.js': '@empty',
'./icons/exchange-alt-icon.js': '@empty', './icons/exchange-alt-icon.js': '@empty',
'./icons/exclamation-icon.js': '@empty', './icons/exclamation-icon.js': '@empty',
'./icons/exclamation-circle-icon.js': '@empty', //'./icons/exclamation-circle-icon.js': '@empty',
'./icons/exclamation-triangle-icon.js': '@empty', //'./icons/exclamation-triangle-icon.js': '@empty',
'./icons/expand-icon.js': '@empty', './icons/expand-icon.js': '@empty',
'./icons/expand-arrows-alt-icon.js': '@empty', './icons/expand-arrows-alt-icon.js': '@empty',
'./icons/external-link-alt-icon.js': '@empty', './icons/external-link-alt-icon.js': '@empty',
@ -647,7 +647,7 @@
'./icons/industry-icon.js': '@empty', './icons/industry-icon.js': '@empty',
'./icons/infinity-icon.js': '@empty', './icons/infinity-icon.js': '@empty',
'./icons/info-icon.js': '@empty', './icons/info-icon.js': '@empty',
'./icons/info-circle-icon.js': '@empty', //'./icons/info-circle-icon.js': '@empty',
'./icons/italic-icon.js': '@empty', './icons/italic-icon.js': '@empty',
'./icons/jedi-icon.js': '@empty', './icons/jedi-icon.js': '@empty',
'./icons/joint-icon.js': '@empty', './icons/joint-icon.js': '@empty',
@ -1004,7 +1004,7 @@
'./icons/thumbs-up-icon.js': '@empty', './icons/thumbs-up-icon.js': '@empty',
'./icons/thumbtack-icon.js': '@empty', './icons/thumbtack-icon.js': '@empty',
'./icons/ticket-alt-icon.js': '@empty', './icons/ticket-alt-icon.js': '@empty',
'./icons/times-icon.js': '@empty', //'./icons/times-icon.js': '@empty',
'./icons/times-circle-icon.js': '@empty', './icons/times-circle-icon.js': '@empty',
'./icons/tint-icon.js': '@empty', './icons/tint-icon.js': '@empty',
'./icons/tint-slash-icon.js': '@empty', './icons/tint-slash-icon.js': '@empty',