@smartbit4all/ng-client
v4.2.1
Published
---
Downloads
4,825
Keywords
Readme
Smart Ng Client
How to use
Installation
Go to your project, open the terminal and use the following command:
npm i @smartbit4all/ng-client
Provide the SmartNgClientModule
in the app.module:
app.module.ts:
@NgModule({
declarations: [...],
imports: [
SmartNgClientModule,
...
],
providers: [
SmartSessionService,
SmartViewContextService,
...
],
...
})
Usage
In order to use the SmartSessionService I recommend to follow the guideline belove.
Generate a service which will handle the session and the authentication.
Terminal:
>>> cd src/app
>>> mkdir services
>>> cd ./services
>>> ng g s authentication
Provide this new service as a global service:
app.module.ts:
@NgModule({
declarations: [...],
imports: [...],
providers: [
SmartSessionService,
AuthenticationService,
...
],
...
})
Authentication state changed
The change of authentication state can be detected in any components. To handle it you must subscribe to the change itself.
Note that in this version a user is authenticated when the response of the GET session contains a list of authentications.
this.isAuthenticated = response.authentications.length > 0
any.component.ts:
constructor(
private auth: AuthenticationService,
private session: SmartSessionService
) {
this.session.authenticationStateChanged.subscribe((isAuth: boolean) => {
if (!isAuth) {
this.router.navigate(['/login']);
}
});
}
Using locales
The SmartSessionService
supports the usage of locales in you application. It is important to note that the language is related to the session!
This example uses the NgxTranslate/core package.
authentication.service.ts:
import { TranslateService } from '@ngx-translate/core';
...
export class AuthenticationService {
...
constructor(
...
private translate: TranslateService
) {
this.session.localeChanged.subscribe(() => {
this.translate.use(this.session.getLocale());
});
}
async changeLocale(locale: string): Promise<void> {
await this.session.changeLocale(locale);
}
getLocale(): string {
return this.session.getLocale();
}
}
SmartDevTool usage
Turn on and off the devTool:
// active
localStorage.setItem('smartDevToolActive', 'true');
// inactive
localStorage.setItem('smartDevToolActive', 'false');
Set the devTool's button visibility
// visible
localStorage.setItem('useDevTool', 'true');
// invisible
localStorage.setItem('useDevTool', 'false');
In order to use this package properly, please create a folder called viewcontext
in which a view-context.pages.model.ts
shall be created:
- src/app/viewcontext/
- view-context.pages.ts
- view-context.handlers.ts
view-context.pages.ts:
export enum Pages {
// mandatory
VIEW_CONTEXT = 'viewContextUuid',
// optionals
ANY_PAGE = 'anyPage',
ANY_DIALOG = 'anyDialog,
ANY_COMPONENT = 'anyComponent,
...
}
view-context.handlers.ts:
import { SmartViewHandlerModel, ViewType } from '@smartbit4all/view-context';
import { Pages } from './view-context.pages';
import { AnyDialogService } from '../any-dialog/any-dialog.service';
export const viewContextHandlers: SmartViewHandlerModel[] = [
// ViewType.Normal
{
name: Pages.ANY_PAGE,
route: 'any'
},
// ViewType.Dialog
{
name: Pages.ANY_DIALOG,
component: AnyDialogComponent
},
// ViewType.Normal or ViewType.Dialog
{
name: Pages.ANY_COMPONENT,
route: 'any',
component: AnyComponent
}
];
Don't forget to define some ApiErrors and inject it into the AuthenticationService:
view-context.api-errors.ts:
const viewContextApiErrors: SmartViewContextApiErrors = {
viewContextApiErrors: [
{
code: "001",
dialogTitle?: "Error"
message: "An error message"
buttonLabel?: "Ok"
}
]
}
SmartLink
In order to use SmartLinks in your application, follow the instruction:
Firstly, set up the routing:
app-routing.module.ts:
const routes: Routes = [
// Out of the box solution
{
path: `redirect/:${SmartLinkChannelVariableInPath}/:${SmartLinkUuidVariableInPath}`,
component: SmartViewRedirect,
},
// Custom solution
{
path: `customRedirect/:${SmartLinkChannelVariableInPath}/:${SmartLinkUuidVariableInPath}`,
component: RedirectComponent,
},
...
]
Then you can set up your custom redirect component as you wish:
redirect.component.ts:
@Component({
selector: "app-redirect",
templateUrl: "./redirect.component.html",
styleUrls: ["./redirect.component.css"],
})
export class RedirectComponent extends SmartViewRedirect {
constructor(
service: SmartViewContextService,
navigation: SmartNavigationService,
route: ActivatedRoute
) {
super(
service,
navigation,
route
);
}
}
Then subscribe for the openSmartLink event and handle it in your AuthenticationService:
authentication.service.ts:
constructor(...) {
...
this.viewContext.openSmartLink.subscribe(() => {
this.handleOpenSmartLinkEvent();
})
}
private async handleOpenSmartLinkEvent(): Promise<void> {
// Do your business logic here
// If authentication is needed to open the link:
let isAuthenticated = await this.isAuthenticated();
if (isAuthenticated) {
this.viewContext.openSmartLink.complete();
} else {
// Navigate to login screen without reloading the site!
}
}
// Modify this if authentication is needed to open links
async login(request: LocalAuthenticationLoginRequest): Promise<boolean> {
await this.auth.login(request);
let isAuth = await this.session.getIsAuthenticated();
if (isAuth) {
await this.viewContext.initialize();
await this.anyBffApi.startAnyPage().toPromise();
// If there is a smart link waiting for opening...
if (this.viewContext.isOpeningSmartLink) {
this.viewContext.openSmartLink.complete();
return isAuth;
}
let uuid = this.viewContext.getUuidOfPage(Pages.VIEW_CONTEXT);
await this.viewContext.getAndSyncViewContext(uuid);
}
return isAuth;
}
UiActions
The ViewContext package contains a common manager for the UiActions. To use this tool, please follow the instructions.
action.descriptors.ts:
import {
UiActionButtonIconPos,
UiActionButtonType,
UiActionDescriptor
} from '@smartbit4all/view-context';
// Build your own action descriptors
export const ActionDescriptors: Map<string, UiActionDescriptor> = new Map([
[
'EXAMPLE',
{
title: 'Example action',
type: UiActionButtonType.Raised,
color: 'primary',
dialog: {
title: 'Example dialog title',
text: 'Example dialog text',
actionButton: {
caption: 'Example action',
color: 'primary'
},
cancelButton: {
caption: 'Cancel',
color: ''
}
},
inputDialog: { ... },
confirmDialog: { ... },
feedbackType: UiActionFeedbackType.SNACKBAR;
feedbackText: "Example feedback";
}
]
])
authentication.service.ts:
constructor(...) {
...
// Set your descriptors
this.viewContext.setActionDescriptors(ActionDescriptors);
// Set basic feedback
this.viewContext.commonFeedbackText = "Basic feedback."
...
}
example.component.ts:
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent implements UseUiAction {
possibleActions: UiAction[]; // Comes from the backend
actions: UiActionModel[] = [];
// UseUiAction properties
submit: Subject<void> = new Subject();
reSubscribeToChange: Subject<void> = new Subject();
constructor(private service: ExampleService) {}
// UseUiAction functions
getAdditionalParams(uiAction: UiAction): UiActionAdditionalParams {
// return additional parameters if needed
throw new Error('Method not implemented.');
}
getModel() {
// return the model of the page
throw new Error('Method not implemented.');
}
async performUiActionRequest(uiActionRequest: UiActionRequest): Promise<any> {
// perform the uiActionRequest on the proper service
await this.service.performAction(uiActionRequest)
}
handleSpecificDemandsAsynchronously(uiAction: UiAction): Promise<UiActionSpecificDemandResponse> {
// handle specific demands if needed
throw new Error('Method not implemented.');
}
// Construct
constructActions(): void {
this.actions = [];
let exceptions = ['EXCEPTION'];
this.possibleActions.map((uiAction: UiAction) => {
this.actions?.push({
uiAction,
serviceToUse: this, // bind a class which implements the UseUiAction
exception: exceptions.includes(uiAction.code!)
});
});
}
}
example.component.html:
<smart-ui-action-toolbar [uiActionModels]="actions"></smart-ui-action-toolbar>