KEYCLOAK-10205: Alerts and Notifications
This commit is contained in:
parent
a050e70389
commit
38933fdfed
6 changed files with 115 additions and 10 deletions
|
@ -18,6 +18,7 @@
|
|||
//import {KeycloakNotificationService} from '../notification/keycloak-notification.service';
|
||||
import {KeycloakService} from '../keycloak-service/keycloak.service';
|
||||
import Axios, {AxiosRequestConfig, AxiosResponse} from 'axios';
|
||||
import {ContentAlert} from '../content/ContentAlert';
|
||||
|
||||
//import {NotificationType} from 'patternfly-ng/notification';*/
|
||||
|
||||
|
@ -86,6 +87,7 @@ export class AccountServiceClient {
|
|||
|
||||
private handleError(error: Error): void {
|
||||
console.log(error);
|
||||
ContentAlert.danger(error.name + ': ' + error.message);
|
||||
}
|
||||
|
||||
private makeConfig(endpoint: string, config: AxiosRequestConfig = {}): Promise<AxiosRequestConfig> {
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import {Msg} from '../widgets/Msg';
|
||||
import {ContentAlert} from './ContentAlert';
|
||||
|
||||
interface ContentPageProps {
|
||||
title: string; // Literal title or key into message bundle
|
||||
|
@ -35,6 +36,7 @@ export class ContentPage extends React.Component<ContentPageProps> {
|
|||
public render(): React.ReactNode {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ContentAlert/>
|
||||
<section className="pf-c-page__main-section pf-m-light">
|
||||
<div className="pf-c-content">
|
||||
<h1><Msg msgKey={this.props.title}/></h1>
|
||||
|
|
|
@ -22,6 +22,7 @@ import {AccountServiceClient} from '../../account-service/account.service';
|
|||
import {Features} from '../../widgets/features';
|
||||
import {Msg} from '../../widgets/Msg';
|
||||
import {ContentPage} from '../ContentPage';
|
||||
import {ContentAlert} from '../ContentAlert';
|
||||
|
||||
declare const features: Features;
|
||||
|
||||
|
@ -88,7 +89,7 @@ export class AccountPage extends React.Component<AccountPageProps, AccountPageSt
|
|||
AccountServiceClient.Instance.doPost("/", {data: reqData})
|
||||
.then((response: AxiosResponse<FormFields>) => {
|
||||
this.setState({canSubmit: false});
|
||||
alert('Data posted:' + response.statusText);
|
||||
ContentAlert.success('accountUpdatedMessage');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
map: {
|
||||
'./Accordion': '@empty', //'./Accordion/index.js,
|
||||
'./ActionGroup': './ActionGroup/index.js',
|
||||
'./Alert': '@empty', //'./Alert/index.js',
|
||||
'./Alert': './Alert/index.js',
|
||||
'./AboutModal': '@empty', //'./AboutModal/index.js',
|
||||
'./ApplicationLauncher': '@empty', //'./ApplicationLauncher/index.js',
|
||||
'./Avatar': './Avatar/index.js',
|
||||
|
@ -154,7 +154,7 @@
|
|||
'./Gallery': '@empty', //'./Gallery/index.js',
|
||||
'./Level': '@empty', //'./Level/index.js',
|
||||
'./Grid': '@empty', //'./Grid/index.js',
|
||||
'./Stack': '@empty', //'./Stack/index.js',
|
||||
'./Stack': './Stack/index.js',
|
||||
'./Split': '@empty', //'./Split/index.js',
|
||||
'./Toolbar': './Toolbar/index.js',
|
||||
}
|
||||
|
@ -332,7 +332,7 @@
|
|||
'./icons/chart-line-icon.js': '@empty',
|
||||
'./icons/chart-pie-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-square-icon.js': '@empty',
|
||||
'./icons/cheese-icon.js': '@empty',
|
||||
|
@ -466,8 +466,8 @@
|
|||
'./icons/euro-sign-icon.js': '@empty',
|
||||
'./icons/exchange-alt-icon.js': '@empty',
|
||||
'./icons/exclamation-icon.js': '@empty',
|
||||
'./icons/exclamation-circle-icon.js': '@empty',
|
||||
'./icons/exclamation-triangle-icon.js': '@empty',
|
||||
//'./icons/exclamation-circle-icon.js': '@empty',
|
||||
//'./icons/exclamation-triangle-icon.js': '@empty',
|
||||
'./icons/expand-icon.js': '@empty',
|
||||
'./icons/expand-arrows-alt-icon.js': '@empty',
|
||||
'./icons/external-link-alt-icon.js': '@empty',
|
||||
|
@ -647,7 +647,7 @@
|
|||
'./icons/industry-icon.js': '@empty',
|
||||
'./icons/infinity-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/jedi-icon.js': '@empty',
|
||||
'./icons/joint-icon.js': '@empty',
|
||||
|
@ -1004,7 +1004,7 @@
|
|||
'./icons/thumbs-up-icon.js': '@empty',
|
||||
'./icons/thumbtack-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/tint-icon.js': '@empty',
|
||||
'./icons/tint-slash-icon.js': '@empty',
|
||||
|
|
Loading…
Reference in a new issue