Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR-13012 - support-angular-16-signals #450

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,5 +238,36 @@ export class AppComponent implements OnInit {
}
}
```
### 6. Using signals

6. Enjoy!
In order to use frontegg signals you will have to call it from the frontegg services and assign them to the component state

```
import { Component, OnInit, Signal } from '@angular/core';
import { FronteggAppService, FronteggAuthService, AuthState } from '@frontegg/angular';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
})
export class AppComponent implements OnInit {
user: Signal<AuthState['user'] | undefined>
authenticated: Signal<boolean | undefined>
constructor(private fronteggAppService: FronteggAppService,
private fronteggAuthService: FronteggAuthService,
private router: Router) {
this.user = this.fronteggAuthService.userSignal
this.authenticated = this.fronteggAppService.isAuthenticatedSignal
}
}
```

Then access it from the html component file
```
<div>
<p>Authenticated: {{authenticated()}}</p>
<p>Authenticated as: {{user()?.name}}</p>
</div>
```

7. Enjoy!
33 changes: 32 additions & 1 deletion projects/frontegg-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,5 +197,36 @@ export class AppComponent implements OnInit {
}
}
```
### 6. Using signals

6. Enjoy!
In order to use frontegg signals you will have to call it from the frontegg services and assign them to the component state

```
import { Component, OnInit, Signal } from '@angular/core';
import { FronteggAppService, FronteggAuthService, AuthState } from '@frontegg/angular';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
})
export class AppComponent implements OnInit {
user: Signal<AuthState['user'] | undefined>
authenticated: Signal<boolean | undefined>
constructor(private fronteggAppService: FronteggAppService,
private fronteggAuthService: FronteggAuthService,
private router: Router) {
this.user = this.fronteggAuthService.userSignal
this.authenticated = this.fronteggAppService.isAuthenticatedSignal
}
}
```

Then access it from the html component file
```
<div>
<p>Authenticated: {{authenticated()}}</p>
<p>Authenticated as: {{user()?.name}}</p>
</div>
```

7. Enjoy!
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { FronteggState } from '@frontegg/redux-store';
import { BehaviorSubject, Observable } from 'rxjs';

export class FronteggAppObservables {
isLoadingSubject = new BehaviorSubject<boolean>(true);
isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
stateSubject = new BehaviorSubject<FronteggState>({} as FronteggState);
authStateSubject = new BehaviorSubject<FronteggState['auth']>({
isLoading: true,
isAuthenticated: false,
} as FronteggState['auth']);
auditsStateSubject = new BehaviorSubject<FronteggState['audits']>({} as FronteggState['audits']);
connectivityStateSubject = new BehaviorSubject<FronteggState['connectivity']>({} as FronteggState['connectivity']);
subscriptionsStateSubject = new BehaviorSubject<FronteggState['subscriptions']>({} as FronteggState['subscriptions']);
vendorStateSubject = new BehaviorSubject<FronteggState['vendor']>({} as FronteggState['vendor']);


get state$(): Observable<FronteggState> {
return this.stateSubject.asObservable();
}

get authState$(): Observable<FronteggState['auth']> {
return this.authStateSubject.asObservable();
}

get auditsState$(): Observable<FronteggState['audits']> {
return this.auditsStateSubject.asObservable();
}

get connectivityState$(): Observable<FronteggState['connectivity']> {
return this.connectivityStateSubject.asObservable();
}

get subscriptionsState$(): Observable<FronteggState['subscriptions']> {
return this.subscriptionsStateSubject.asObservable();
}

get vendorState$(): Observable<FronteggState['vendor']> {
return this.vendorStateSubject.asObservable();
}

get isLoading$(): Observable<boolean> {
return this.isLoadingSubject.asObservable();
};

get isAuthenticated$(): Observable<boolean> {
return this.isAuthenticatedSubject.asObservable();
};

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Injectable, NgZone, Inject } from '@angular/core';
import angularCoreVersion from '@angular/core/package.json';
import { Route, Router, ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { FronteggApp, initialize } from '@frontegg/js';
import { AuthPageRoutes,FronteggState, isAuthRoute } from '@frontegg/redux-store';
import { AuthPageRoutes, FronteggState, isAuthRoute } from '@frontegg/redux-store';
import { ContextHolder, FronteggFrameworks, RedirectOptions } from '@frontegg/rest-api';
import { FronteggAppOptions, FronteggCheckoutDialogOptions } from '@frontegg/types';
import { BehaviorSubject, Observable } from 'rxjs';
import { ContextHolder, RedirectOptions, FronteggFrameworks } from '@frontegg/rest-api';
import { FronteggComponent } from './frontegg.component';
import sdkVersion from '../sdkVersion';
import angularCoreVersion from '@angular/core/package.json';
import sdkVersion from '../../sdkVersion';
import { FronteggComponent } from '../frontegg.component';
import { FronteggAppSignals } from './frontegg-app.signals';
import { Observable } from 'rxjs';

export class FronteggAppOptionsClass implements FronteggAppOptions {
contextOptions: FronteggAppOptions['contextOptions'] = {
Expand All @@ -18,55 +19,11 @@ export class FronteggAppOptionsClass implements FronteggAppOptions {
@Injectable({
providedIn: 'root',
})
export class FronteggAppService {
export class FronteggAppService extends FronteggAppSignals {
fronteggApp: FronteggApp;

private isLoadingSubject = new BehaviorSubject<boolean>(true);
private isAuthenticatedSubject = new BehaviorSubject<boolean>(false);
private stateSubject = new BehaviorSubject<FronteggState>({} as FronteggState);
private authStateSubject = new BehaviorSubject<FronteggState['auth']>({
isLoading: true,
isAuthenticated: false,
} as FronteggState['auth']);
private auditsStateSubject = new BehaviorSubject<FronteggState['audits']>({} as FronteggState['audits']);
private connectivityStateSubject = new BehaviorSubject<FronteggState['connectivity']>({} as FronteggState['connectivity']);
private subscriptionsStateSubject = new BehaviorSubject<FronteggState['subscriptions']>({} as FronteggState['subscriptions']);
private vendorStateSubject = new BehaviorSubject<FronteggState['vendor']>({} as FronteggState['vendor']);


get state$(): Observable<FronteggState> {
return this.stateSubject.asObservable();
}

get authState$(): Observable<FronteggState['auth']> {
return this.authStateSubject.asObservable();
}

get auditsState$(): Observable<FronteggState['audits']> {
return this.auditsStateSubject.asObservable();
}

get connectivityState$(): Observable<FronteggState['connectivity']> {
return this.connectivityStateSubject.asObservable();
}

get subscriptionsState$(): Observable<FronteggState['subscriptions']> {
return this.subscriptionsStateSubject.asObservable();
}

get vendorState$(): Observable<FronteggState['vendor']> {
return this.vendorStateSubject.asObservable();
}

get isLoading$(): Observable<boolean> {
return this.isLoadingSubject.asObservable();
};

get isAuthenticated$(): Observable<boolean> {
return this.isAuthenticatedSubject.asObservable();
};

constructor(@Inject(FronteggAppOptionsClass) private config: FronteggAppOptions, public router: Router, private ngZone: NgZone) {
super();
if (!this.config) {
throw Error('Need to pass config: FronteggConfigOptions in FronteggAppModule.forRoot(config)');
}
Expand Down Expand Up @@ -117,8 +74,8 @@ export class FronteggAppService {
...this.mapAuthComponents,
{
path: '',
canActivate: [ FronteggLoadGuard ],
children: [ ...this.router.config ],
canActivate: [FronteggLoadGuard],
children: [...this.router.config],
},
]);
const initialFronteggState = this.fronteggApp.store.getState() as FronteggState;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FronteggState } from '@frontegg/redux-store';
import { Signal, toSignal } from '../v16';
import { FronteggAppObservables } from './frontegg-app.observables';

export class FronteggAppSignals extends FronteggAppObservables {
get authStateSignal(): Signal<FronteggState['auth'] | undefined> {
return toSignal(this.authState$);
}

get auditsStateSignal(): Signal<FronteggState['audits'] | undefined> {
return toSignal(this.auditsState$);
}

get connectivityStateSignal(): Signal<FronteggState['connectivity'] | undefined> {
return toSignal(this.connectivityState$);
}

get subscriptionsStateSignal(): Signal<FronteggState['subscriptions'] | undefined> {
return toSignal(this.subscriptionsState$);
}

get vendorStateSignal(): Signal<FronteggState['vendor'] | undefined> {
return toSignal(this.vendorState$);
}

get isLoadingSignal(): Signal<boolean | undefined> {
return toSignal(this.isLoading$);
}

get isAuthenticatedSignal(): Signal<boolean | undefined> {
return toSignal(this.isAuthenticated$);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './frontegg-app.service'
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import {
AuthState
} from '@frontegg/redux-store';
import { BehaviorSubject, Observable } from 'rxjs';

export class FronteggAuthObservables {
authStateSubject = new BehaviorSubject<AuthState>({ isAuthenticated: false, isLoading: true } as AuthState);
acceptInvitationStateSubject = new BehaviorSubject<AuthState['acceptInvitationState']>({} as AuthState['acceptInvitationState']);
accountSettingsStateSubject = new BehaviorSubject<AuthState['accountSettingsState']>({} as AuthState['accountSettingsState']);
activateStateSubject = new BehaviorSubject<AuthState['activateState']>({} as AuthState['activateState']);
apiTokensStateSubject = new BehaviorSubject<AuthState['apiTokensState']>({} as AuthState['apiTokensState']);
forgotPasswordStateSubject = new BehaviorSubject<AuthState['forgotPasswordState']>({} as AuthState['forgotPasswordState']);
loginStateSubject = new BehaviorSubject<AuthState['loginState']>({} as AuthState['loginState']);
mfaStateSubject = new BehaviorSubject<AuthState['mfaState']>({} as AuthState['mfaState']);
profileStateSubject = new BehaviorSubject<AuthState['profileState']>({} as AuthState['profileState']);
rolesStateSubject = new BehaviorSubject<AuthState['rolesState']>({} as AuthState['rolesState']);
routesSubject = new BehaviorSubject<AuthState['routes']>({} as AuthState['routes']);
securityPolicyStateSubject = new BehaviorSubject<AuthState['securityPolicyState']>({} as AuthState['securityPolicyState']);
signUpStateSubject = new BehaviorSubject<AuthState['signUpState']>({} as AuthState['signUpState']);
socialLoginStateSubject = new BehaviorSubject<AuthState['socialLoginState']>({} as AuthState['socialLoginState']);
ssoStateSubject = new BehaviorSubject<AuthState['ssoState']>({} as AuthState['ssoState']);
teamStateSubject = new BehaviorSubject<AuthState['teamState']>({} as AuthState['teamState']);
tenantsStateSubject = new BehaviorSubject<AuthState['tenantsState']>({} as AuthState['tenantsState']);
userSubject = new BehaviorSubject<AuthState['user']>({} as AuthState['user']);
isAuthenticatedSubject = new BehaviorSubject<AuthState['isAuthenticated']>(false);
isLoadingSubject = new BehaviorSubject<AuthState['isLoading']>(true);
isSSOAuthSubject = new BehaviorSubject<AuthState['isSSOAuth']>(false);
ssoACSSubject = new BehaviorSubject<AuthState['ssoACS']>('');

get authState$(): Observable<AuthState> {
return this.authStateSubject.asObservable();
}

get acceptInvitationState$(): Observable<AuthState['acceptInvitationState']> {
return this.acceptInvitationStateSubject.asObservable();
}

get accountSettingsState$(): Observable<AuthState['accountSettingsState']> {
return this.accountSettingsStateSubject.asObservable();
}

get activateState$(): Observable<AuthState['activateState']> {
return this.activateStateSubject.asObservable();
}

get apiTokensState$(): Observable<AuthState['apiTokensState']> {
return this.apiTokensStateSubject.asObservable();
}

get forgotPasswordState$(): Observable<AuthState['forgotPasswordState']> {
return this.forgotPasswordStateSubject.asObservable();
}

get loginState$(): Observable<AuthState['loginState']> {
return this.loginStateSubject.asObservable();
}

get mfaState$(): Observable<AuthState['mfaState']> {
return this.mfaStateSubject.asObservable();
}

get profileState$(): Observable<AuthState['profileState']> {
return this.profileStateSubject.asObservable();
}

get rolesState$(): Observable<AuthState['rolesState']> {
return this.rolesStateSubject.asObservable();
}

get routesState$(): Observable<AuthState['routes']> {
return this.routesSubject.asObservable();
}

get securityPolicyState$(): Observable<AuthState['securityPolicyState']> {
return this.securityPolicyStateSubject.asObservable();
}

get signUpState$(): Observable<AuthState['signUpState']> {
return this.signUpStateSubject.asObservable();
}

get socialLoginState$(): Observable<AuthState['socialLoginState']> {
return this.socialLoginStateSubject.asObservable();
}

get ssoState$(): Observable<AuthState['ssoState']> {
return this.ssoStateSubject.asObservable();
}

get teamState$(): Observable<AuthState['teamState']> {
return this.teamStateSubject.asObservable();
}

get tenantsState$(): Observable<AuthState['tenantsState']> {
return this.tenantsStateSubject.asObservable();
}

get user$(): Observable<AuthState['user']> {
return this.userSubject.asObservable();
}

get isAuthenticated$(): Observable<AuthState['isAuthenticated']> {
return this.isAuthenticatedSubject.asObservable();
}

get isLoading$(): Observable<AuthState['isLoading']> {
return this.isLoadingSubject.asObservable();
}

get isSSOAuth$(): Observable<AuthState['isSSOAuth']> {
return this.isSSOAuthSubject.asObservable();
}

get ssoACS$(): Observable<AuthState['ssoACS']> {
return this.ssoACSSubject.asObservable();
}

}
Loading