Skip to content

Commit 37f3bf1

Browse files
committed
[APIM-11537] Fix PR comments: responsive login form, move forceLogin to authGuard, fix redirection after SSO login.
1 parent 283af7d commit 37f3bf1

25 files changed

+320
-269
lines changed

gravitee-apim-portal-webui-next/src/app/app.component.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
*/
1616
import { Component, effect, inject } from '@angular/core';
1717
import { Title } from '@angular/platform-browser';
18-
import { NavigationStart, Router, RouterOutlet } from '@angular/router';
19-
import { isEmpty } from 'lodash';
18+
import { RouterOutlet } from '@angular/router';
2019
import { BreadcrumbService } from 'xng-breadcrumb';
2120

2221
import { FooterComponent } from '../components/footer/footer.component';
@@ -26,12 +25,6 @@ import { CurrentUserService } from '../services/current-user.service';
2625
import { PortalMenuLinksService } from '../services/portal-menu-links.service';
2726
import { ThemeService } from '../services/theme.service';
2827

29-
const PATHS = {
30-
LOGIN: '/log-in',
31-
SIGNUP: '/sign-up',
32-
RESET_PASSWORD: '/log-in/reset-password',
33-
};
34-
3528
@Component({
3629
selector: 'app-root',
3730
imports: [RouterOutlet, NavBarComponent, FooterComponent],
@@ -50,7 +43,6 @@ export class AppComponent {
5043
// Don't delete BreadcrumbService from here - it's responsible for correct breadcrumb navigation
5144
private breadcrumbService: BreadcrumbService,
5245
private title: Title,
53-
private router: Router,
5446
) {
5547
this.siteTitle = configService.configuration?.portalNext?.siteTitle ?? 'Developer Portal';
5648
this.title.setTitle(this.siteTitle);
@@ -59,19 +51,6 @@ export class AppComponent {
5951
this.updateFavicon();
6052
}
6153
});
62-
63-
this.router.events.subscribe(event => {
64-
if (event instanceof NavigationStart) {
65-
if (isEmpty(this.currentUser()) && !this.isInLoginOrRegistration(event.url) && this.forceLogin()) {
66-
const redirectUrl = event.url;
67-
this.router.navigate([PATHS.LOGIN], { replaceUrl: true, queryParams: { redirectUrl } });
68-
}
69-
}
70-
});
71-
}
72-
73-
isInLoginOrRegistration(url: string = this.router.routerState.snapshot.url): boolean {
74-
return url.startsWith(PATHS.LOGIN) || url.startsWith(PATHS.SIGNUP) || url.startsWith(PATHS.RESET_PASSWORD);
7554
}
7655

7756
forceLogin(): boolean {

gravitee-apim-portal-webui-next/src/app/app.config.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import { ApplicationConfig, inject, provideAppInitializer } from '@angular/core'
1919
import { MAT_RIPPLE_GLOBAL_OPTIONS } from '@angular/material/core';
2020
import { provideAnimations } from '@angular/platform-browser/animations';
2121
import { provideRouter, Router, withComponentInputBinding, withRouterConfig } from '@angular/router';
22-
import { provideCharts, withDefaultRegisterables } from 'ng2-charts';
2322
import { provideOAuthClient } from 'angular-oauth2-oidc';
23+
import { provideCharts, withDefaultRegisterables } from 'ng2-charts';
2424
import { catchError, combineLatest, Observable, switchMap } from 'rxjs';
2525
import { of } from 'rxjs/internal/observable/of';
2626

@@ -43,13 +43,12 @@ function initApp(
4343
): () => Observable<unknown> {
4444
return () =>
4545
configService.initBaseURL().pipe(
46-
switchMap(_ => authService.load()),
4746
switchMap(_ =>
4847
combineLatest([
4948
themeService.loadTheme(),
50-
currentUserService.loadUser(),
5149
configService.loadConfiguration(),
5250
portalMenuLinksService.loadCustomLinks(),
51+
authService.load().pipe(switchMap(_ => currentUserService.loadUser())),
5352
]),
5453
),
5554
catchError(error => {

gravitee-apim-portal-webui-next/src/app/app.routes.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,13 @@ const apiRoutes: Routes = [
131131
export const routes: Routes = [
132132
{
133133
path: '',
134-
canActivate: [redirectGuard],
134+
canActivate: [redirectGuard, authGuard],
135135
resolve: { homepage: homepageResolver },
136136
component: HomepageComponent,
137137
},
138138
{
139139
path: 'catalog',
140-
canActivateChild: [redirectGuard],
140+
canActivateChild: [redirectGuard, authGuard],
141141
data: { breadcrumb: 'Catalog' },
142142
children: [
143143
{
@@ -178,7 +178,7 @@ export const routes: Routes = [
178178
},
179179
{
180180
path: 'applications',
181-
canActivateChild: [authGuard, redirectGuard],
181+
canActivateChild: [redirectGuard, authGuard],
182182
children: [
183183
{ path: '', component: ApplicationsComponent, data: { breadcrumb: 'Applications' } },
184184
{
@@ -220,6 +220,7 @@ export const routes: Routes = [
220220
},
221221
{
222222
path: 'guides',
223+
canActivate: [redirectGuard, authGuard],
223224
component: GuidesComponent,
224225
data: { breadcrumb: { label: 'Documentation', disable: true } },
225226
resolve: { pages: environmentPagesResolver },
@@ -252,7 +253,7 @@ export const routes: Routes = [
252253
},
253254
],
254255
},
255-
{ path: 'log-out', component: LogOutComponent, canActivate: [redirectGuard, authGuard] },
256+
{ path: 'log-out', component: LogOutComponent, canActivate: [redirectGuard] },
256257
{ path: '404', component: NotFoundComponent },
257258
{ path: '503', component: ServiceUnavailableComponent },
258259
{ path: 'gravitee-md', component: GraviteeMarkdownComponent },

gravitee-apim-portal-webui-next/src/app/log-in/log-in.component.html

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
limitations under the License.
1616
1717
-->
18-
<form [formGroup]="logInForm" (ngSubmit)="logIn()" class="log-in__form__container">
18+
<form [formGroup]="logInForm" (ngSubmit)="logIn()" class="log-in__form__container" [appIsMobile]="'log-in__form__container--mobile'">
1919
<mat-card appearance="outlined" class="log-in">
2020
<mat-card-header class="log-in__form__header">
2121
<mat-card-title class="log-in__form__title" i18n="@@logInTitle">Login</mat-card-title>
2222
</mat-card-header>
2323
<mat-card-content class="log-in__form__content">
24-
@if (isLocalLoginEnabled()) {
24+
@let identityProviders = identityProviders$ | async;
25+
@if (isLocalLoginEnabled) {
2526
<div class="log-in__form">
2627
<div class="log-in__form__fields">
2728
<mat-form-field appearance="outline" class="log-in__form__input">
@@ -39,44 +40,35 @@
3940
}
4041
</mat-form-field>
4142
@if (error() === 401) {
42-
<mat-error class="log-in__form__error" i18n="@@logInError401"
43+
<mat-error class="log-in__form__error m3-label-large" i18n="@@logInError401"
4344
>The username or password you entered is incorrect, please try again.</mat-error
4445
>
4546
}
4647
</div>
4748
<div class="log-in__form__buttons">
48-
<button
49-
[disabled]="logInForm.invalid"
50-
type="submit"
51-
mat-flat-button
52-
i18n="@@logInAction"
53-
class="log-in__form__submit primary-button">
49+
<button [disabled]="logInForm.invalid" type="submit" mat-flat-button i18n="@@logInAction" class="log-in__form__submit">
5450
Log in
5551
</button>
56-
<a class="log-in__form__forgot-password" i18n="@@resetPasswordAction" routerLink="reset-password"> Forgot password? </a>
52+
<a class="log-in__form__forgot-password m3-label-large" i18n="@@resetPasswordAction" routerLink="reset-password">
53+
Forgot password?
54+
</a>
5755
</div>
5856
</div>
59-
}
60-
<div class="log-in__sso">
61-
@if (isLocalLoginEnabled() && identityProviders.length > 0) {
62-
<div class="log-in__sso__separator">
63-
<div class="log-in__sso__separator__line"></div>
64-
<div class="log-in__sso__separator__label" i18n="@@orSeparator">OR</div>
57+
@if ((identityProviders ?? []).length > 0) {
58+
<div class="log-in__or-separator m3-label-large">
59+
<div class="log-in__or-separator__line"></div>
60+
<div class="log-in__or-separator__label" i18n="@@orSeparator">OR</div>
6561
</div>
6662
}
67-
@for (provider of identityProviders; track provider.id) {
68-
<button
69-
type="button"
70-
mat-stroked-button
71-
class="log-in__sso__idp secondary-button"
72-
(click)="authenticateSSO(provider)">
73-
<div class="log-in__sso__idp__container">
74-
<img class="log-in__sso__idp__logo" [src]="'assets/images/idp/' + getProviderLogo(provider)" alt="Provider Logo" />
75-
<span class="log-in__sso__idp__label" i18n="@@logInSsoLabelPrefix">Continue with {{ provider.name }}</span>
76-
</div>
77-
</button>
78-
}
79-
</div>
63+
}
64+
@for (provider of identityProviders; track provider.id) {
65+
<button type="button" mat-stroked-button class="log-in__sso-provider secondary-button" (click)="authenticateSSO(provider)">
66+
<div class="log-in__sso-provider__container">
67+
<img class="log-in__sso-provider__logo" [src]="'assets/images/idp/' + getProviderLogo(provider)" alt="Provider Logo" />
68+
<span class="log-in__sso-provider__label m3-label-large" i18n="@@logInSsoLabelPrefix">Continue with {{ provider.name }}</span>
69+
</div>
70+
</button>
71+
}
8072
</mat-card-content>
8173
</mat-card>
8274
</form>

gravitee-apim-portal-webui-next/src/app/log-in/log-in.component.scss

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
.log-in {
2424
display: flex;
2525
flex-flow: column;
26-
background: #{theme.$background-color};
2726
gap: 20px;
2827

2928
&__form {
@@ -35,15 +34,13 @@
3534
padding: 20px 20px 0;
3635
}
3736

38-
&__title {
39-
font-size: 18px;
40-
font-weight: 700;
41-
}
42-
4337
&__container {
4438
width: 400px;
45-
max-width: 500px;
4639
border-radius: 8px;
40+
41+
&--mobile {
42+
max-width: 75vw;
43+
}
4744
}
4845

4946
&__content:last-child {
@@ -69,7 +66,6 @@
6966
&__forgot-password {
7067
margin-top: 5px;
7168
color: #{theme.$primary-main-color};
72-
font-size: 14px;
7369
text-align: center;
7470
text-decoration: none;
7571

@@ -79,70 +75,54 @@
7975
}
8076

8177
&__error {
82-
font-size: 14px;
8378
text-align: center;
8479
}
8580
}
8681

87-
&__sso {
82+
&__or-separator {
83+
position: relative;
8884
display: flex;
89-
flex-flow: column;
90-
gap: 16px;
85+
height: 30px;
86+
align-items: center;
87+
margin: 20px 0;
9188

92-
&__separator {
93-
position: relative;
89+
&__line {
90+
width: 100%;
91+
border-top: 1px solid #{theme.$card-border-color};
92+
}
93+
94+
&__label {
95+
position: absolute;
9496
display: flex;
95-
height: 30px;
97+
width: 40px;
98+
height: 100%;
9699
align-items: center;
97-
margin: 20px 0 4px;
98-
font-size: 14px;
99-
100-
&__line {
101-
width: 100%;
102-
border-top: 1px solid #{theme.$card-border-color};
103-
}
104-
105-
&__label {
106-
position: absolute;
107-
display: flex;
108-
width: 40px;
109-
height: 100%;
110-
align-items: center;
111-
justify-content: center;
112-
margin: auto;
113-
background: #{theme.$background-color};
114-
inset: 0;
115-
}
100+
justify-content: center;
101+
margin: auto;
102+
background: #{theme.$card-background-color};
103+
inset: 0;
116104
}
105+
}
117106

118-
&__idp {
119-
overflow: hidden;
120-
width: 100%;
121-
padding: 0 18px;
122-
color: #{theme.$button-text-text-color};
123-
font-weight: bold;
124-
white-space: nowrap;
125-
126-
&__container {
127-
display: flex;
128-
align-items: center;
129-
gap: 7px;
130-
}
107+
&__sso-provider {
108+
width: 100%;
109+
padding: 0 18px;
110+
margin-bottom: 16px;
111+
color: #{theme.$button-text-text-color};
131112

132-
&__logo {
133-
width: 23px;
134-
height: 23px;
135-
}
113+
&:last-of-type {
114+
margin-bottom: 0;
115+
}
136116

137-
::ng-deep .mdc-button__label {
138-
overflow: hidden;
139-
white-space: nowrap;
140-
}
117+
&__container {
118+
display: flex;
119+
align-items: center;
120+
gap: 7px;
121+
}
141122

142-
&__label {
143-
overflow: hidden;
144-
text-overflow: ellipsis;
145-
}
123+
&__logo {
124+
width: 23px;
125+
height: 23px;
146126
}
147127
}
148128
}

0 commit comments

Comments
 (0)