From caf08da2aff9d9dcd99c26e903a9c8ace896ef7f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira da Silva Date: Fri, 25 Oct 2019 20:34:36 +0100 Subject: [PATCH] [KEYCLOAK-10962] Application screen for the new account console --- .../account/messages/messages_en.properties | 18 ++ .../applications-page/ApplicationsPage.tsx | 198 ++++++++++++++++-- .../account/resources/systemjs.config.js | 8 +- 3 files changed, 205 insertions(+), 19 deletions(-) diff --git a/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties b/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties index 5c377daf05..5c4db85122 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties +++ b/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties @@ -69,3 +69,21 @@ setUp=Set Up passwordless=Passwordless lastUpdate=Last Update unknown=Unknown + +# Applications page +applicationsPageTitle=Applications +internalApp=Internal +thirdPartyApp=Third-party +offlineAccess=Offline Access +inUse=In use +notInUse=Not in use +applicationDetails=Application Details +client=Client +description=Description +baseUrl=URL +accessGrantedOn=Access granted on +removeButton=Remove access +removeModalTitle=Remove Access +removeModalMessage=This will remove the currently granted access permission for {0}. You will need to grant access again if you want to use this app. +confirmButton=Confirm +infoMessage=By clicking 'Remove Access', you will remove granted permissions of this application. This application will no longer use your information. diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/applications-page/ApplicationsPage.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/applications-page/ApplicationsPage.tsx index 9e4a9f9876..5ac1768063 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/applications-page/ApplicationsPage.tsx +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/applications-page/ApplicationsPage.tsx @@ -15,21 +15,189 @@ */ import * as React from 'react'; - +import { AxiosResponse } from 'axios'; + +import { + DataList, + DataListItem, + DataListItemRow, + DataListCell, + DataListToggle, + DataListContent, + DataListItemCells, + Grid, + GridItem, +} from '@patternfly/react-core'; + +import { InfoAltIcon, CheckIcon, LinkIcon, BuilderImageIcon } from '@patternfly/react-icons'; +import { ContentPage } from '../ContentPage'; +import { ContinueCancelModal } from '../../widgets/ContinueCancelModal'; +import { AccountServiceClient } from '../../account-service/account.service'; +import {Msg} from '../../widgets/Msg'; + +declare const locale: string; + export interface ApplicationsPageProps { } - -export class ApplicationsPage extends React.Component { - - public constructor(props: ApplicationsPageProps) { - super(props); - } - public render(): React.ReactNode { - return ( -
-

Hello Applications Page

-
- ); - } -}; \ No newline at end of file +export interface ApplicationsPageState { + isRowOpen: boolean[]; + applications: Application[]; +} + +export interface GrantedScope { + displayTest: string; + id: string; + name: string; +} + +export interface Consent { + createDate: number; + grantedScopes: GrantedScope[]; + lastUpdatedDate: number; +} + +interface Application { + baseUrl: string; + clientId: string; + clientName: string; + consent: Consent; + description: string; + inUse: boolean; + offlineAccess: boolean; + userConsentRequired: boolean; + scope: string[]; +} + +export class ApplicationsPage extends React.Component { + + public constructor(props: ApplicationsPageProps) { + super(props); + this.state = { + isRowOpen: [], + applications: [] + }; + + this.fetchApplications(); + } + + private removeConsent = (clientId: string) => { + AccountServiceClient.Instance.doDelete("/applications/" + clientId + "/consent") + .then(() => { + this.fetchApplications(); + }); + } + + private onToggle = (row: number): void => { + const newIsRowOpen: boolean[] = this.state.isRowOpen; + newIsRowOpen[row] = !newIsRowOpen[row]; + this.setState({ isRowOpen: newIsRowOpen }); + }; + + private fetchApplications(): void { + AccountServiceClient.Instance.doGet("/applications") + .then((response: AxiosResponse) => { + const applications = response.data; + this.setState({ + isRowOpen: new Array(applications.length).fill(false), + applications: applications + }); + }); + } + + public render(): React.ReactNode { + return ( + + + {this.state.applications.map((application: Application, appIndex: number) => { + return ( + + + this.onToggle(appIndex)} + isExpanded={this.state.isRowOpen[appIndex]} + id={'applicationToggle' + appIndex} + aria-controls="expandable" + /> + + {application.clientName ? application.clientName : application.clientId} + , + + {application.userConsentRequired ? Msg.localize('thirdPartyApp') : Msg.localize('internalApp')} + {application.offlineAccess ? ', ' + Msg.localize('offlineAccess') : ''} + , + + {application.inUse ? Msg.localize('inUse') : Msg.localize('notInUse')} + , + + {application.baseUrl} + , + ]} + /> + + + +
+ {Msg.localize('client') + ': '} {application.clientId} + {application.description && + {Msg.localize('description') + ': '} {application.description} + } + {Msg.localize('baseUrl') + ': '} {application.baseUrl} + {application.consent && + + + Has access to: + + {application.consent.grantedScopes.map((scope: GrantedScope, scopeIndex: number) => { + return ( + + {scope.name} + + ) + })} + {Msg.localize('accessGrantedOn') + ': '} + {new Intl.DateTimeFormat(locale, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric' + }).format(application.consent.createDate)} + + + } +
+
+ +
+ + + this.removeConsent(application.clientId)} // required + /> + + + {Msg.localize('infoMessage')} +
+
+
+ ) + })} +
+
+ ); + } +}; 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 f00c75f7e5..a7e75bef1a 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 @@ -122,7 +122,7 @@ './SkipToContent': '@empty', //'./SkipToContent/index.js', './Switch': './Switch/index.js', './Tabs': './Tabs/index.js', //'./Tabs/index.js', - './Text': '@empty', //'./Text/index.js', + './Text': './Text/index.js', //'./Text/index.js', './TextArea': '@empty', //'./TextArea/index.js', './TextInput': './TextInput/index.js', './Title': './Title/index.js', @@ -360,7 +360,7 @@ './icons/buffer-icon.js': '@empty', './icons/bug-icon.js': '@empty', './icons/build-icon.js': '@empty', - './icons/builder-image-icon.js': '@empty', + //'./icons/builder-image-icon.js': '@empty', './icons/building-icon.js': '@empty', './icons/bullhorn-icon.js': '@empty', './icons/bullseye-icon.js': '@empty', @@ -431,7 +431,7 @@ './icons/chat-icon.js': '@empty', //'./icons/check-circle-icon.js': '@empty', './icons/check-double-icon.js': '@empty', - './icons/check-icon.js': '@empty', + //'./icons/check-icon.js': '@empty', './icons/check-square-icon.js': '@empty', './icons/cheese-icon.js': '@empty', './icons/chess-bishop-icon.js': '@empty', @@ -906,7 +906,7 @@ './icons/indent-icon.js': '@empty', './icons/industry-icon.js': '@empty', './icons/infinity-icon.js': '@empty', - './icons/info-alt-icon.js': '@empty', + //'./icons/info-alt-icon.js': '@empty', //'./icons/info-circle-icon.js': '@empty', './icons/info-icon.js': '@empty', './icons/infrastructure-icon.js': '@empty',