From 38933fdfed78836f3938cdc7842bac2259e79b82 Mon Sep 17 00:00:00 2001 From: Stan Silvert Date: Fri, 17 May 2019 13:37:38 -0400 Subject: [PATCH] KEYCLOAK-10205: Alerts and Notifications --- .../app/account-service/account.service.ts | 2 + .../resources/app/content/ContentAlert.tsx | 100 ++++++++++++++++++ .../resources/app/content/ContentPage.tsx | 4 +- .../app/content/account-page/AccountPage.tsx | 3 +- .../my-resources-page/MyResourcesPage.tsx | 2 +- .../account/resources/systemjs.config.js | 14 +-- 6 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentAlert.tsx diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/account-service/account.service.ts b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/account-service/account.service.ts index 4b68501d81..430e71c698 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/account-service/account.service.ts +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/account-service/account.service.ts @@ -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 { diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentAlert.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentAlert.tsx new file mode 100644 index 0000000000..3c2cf796f7 --- /dev/null +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentAlert.tsx @@ -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 { + 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 ( + + { this.state.isVisible && +
+ } + > + {this.state.message} + +
+ } +
+ ); + } +} \ No newline at end of file diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentPage.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentPage.tsx index 8551b0d3ac..6a4f90165c 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentPage.tsx +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/ContentPage.tsx @@ -16,7 +16,8 @@ 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 introMessage?: string; // Literal message or key into message bundle @@ -35,6 +36,7 @@ export class ContentPage extends React.Component { public render(): React.ReactNode { return ( +

diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx index 2a48c9d18f..65c7f2bc15 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx @@ -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) => { this.setState({canSubmit: false}); - alert('Data posted:' + response.statusText); + ContentAlert.success('accountUpdatedMessage'); }); } diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/my-resources-page/MyResourcesPage.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/my-resources-page/MyResourcesPage.tsx index 8a4e0a8d76..fc6d835007 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/my-resources-page/MyResourcesPage.tsx +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/my-resources-page/MyResourcesPage.tsx @@ -24,7 +24,7 @@ export class MyResourcesPage extends React.Component { public constructor(props: MyResourcesPageProps) { super(props); } - + public render(): React.ReactNode { return (
diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/systemjs.config.js b/themes/src/main/resources/theme/keycloak-preview/account/resources/systemjs.config.js index 365ec2f406..a017a888ab 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/systemjs.config.js +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/systemjs.config.js @@ -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',