1.5.44 • Published 10 months ago

@smartbit4all/view-context v1.5.44

Weekly downloads
-
License
-
Repository
-
Last release
10 months ago

Smart View Context

References

These packages must be updated in case of a new version:

  • There are no references yet

How to use

Installation

First you must install the @smartbit4all/session in order to use this package.

Secondly, you must install the @smartbit4all/authentication in order to use this package.

Go to your project, open the terminal and use the following command:

npm i @smartbit4all/view-context

Then import it in the AppModule:

app.module.ts:

import { SmartViewContextModule, SmartViewContextService } from '@smartbit4all/view-context';
...
@NgModule({
    declarations: [...]
    imports: [
        ...
        SmartViewContextModule,
    ],
    providers: [
        ...
	    SmartViewContextService,
    ]
    ...
})

Prerequisites

If you have installed and done the required steps to use the SmartSessionService and SmartAuthentication, please complete the generated AuthenticationService with these new features belove.

However, if you have not, please follow the guides of the @smartbit4all/session and @smartbit4all/authentication.

Usage

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"
        }
    ]
}

The AuthenticationService must be prepared to use the SmartViewContextService. The ">>>" marks the snippets you have to add.

authentication.service.ts:

@Injectable({
    providedIn: 'root'
})
export class AuthenticationService {
    ...

>>> headersUpdated: Subject<void> = new Subject();
>>> bffApisHaveBeenSetUp: boolean = false;

    // The value of this property has to match with the one in the backend.
>>> messageDialogViewName: string = "messageDialog";

    constructor(
        ...,
    >>> private viewContext: SmartViewContextService,
    >>> private anyBffApi: AnyBffApiService,
    >>> private platformLocation: PlatformLocation
    ) {
    >>> this.viewContext.setViewHandlers(viewContextHandlers);
    >>> this.viewContext.setViewApiErrors(viewContextApiErrors);
    >>> this.viewContext.setMessageDialogName(this.messageDialogViewName);

        // set up SmartSessionService
    >>> this.url = (this.platformLocation as any).location.origin + '/api';
        ...
    >>> this.viewContext.setUrl(this.url);
        ...

    >>> this.setBffApis();
    }

>>> private setBffApis(): void {
        this.anyBffApi.configuration.basePath = this.url;
        ...
    }

>>> private updateHeaderOfBffApi(bffApi: any): void {
        bffApi.defaultHeaders = this.session.setUpDefaultHeaders(bffApi.defaultHeaders);
    }

    async startSession(): Promise<void> {
    >>> this.session.apiCanBeSetUp.subscribe(() => {
    >>>     this.updateHeaderOfBffApi(this.anyBffApi);
    >>>     ...

    >>>     // Replace anyBffApi with the first bffApi you set up above
    >>>     if (this.anyBffApi.defaultHeaders.get(Pages.VIEW_CONTEXT)) {
    >>>         this.bffApisHaveBeenSetUp = true;
    >>>     }

    >>>     this.headersUpdated.next();
    >>> });

        await this.session.initialize();

    >>> let isAuthenticated = await this.session.getIsAuthenticated();
    >>> if (isAuthenticated) {
    >>>     let uuid = this.viewContext.getUuidOfPage(Pages.VIEW_CONTEXT);
    >>>     await this.viewContext.initialize(uuid);
	>>>     this.viewContext.getAndSyncViewContext(uuid);
    >>> }
    }

    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();
    >>>     let uuid = this.viewContext.getUuidOfPage(Pages.VIEW_CONTEXT);
    >>>     await this.viewContext.getAndSyncViewContext(uuid);
        }
        return isAuth;
    }

    ...

}

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>

Version logs

@smartbit4all/view-context v1.5.1

Type: Update

Requires "@smartbit4all/dialog": "^1.1.0".

@smartbit4all/view-context v1.5.0

Type: Update

From now on the @smartbit4all/view-context includes a new module which manages the UiActions.

@smartbit4all/view-context v1.4.14

Type: Update

This update contains a solutions for the viewContext error handling after session expiration.

How to use:

In your project your authentication service must implement the SmartViewContextHandlerService interface. After that inject the authentication service into the SmartViewContextService with the setViewContextHandlerService function.

@smartbit4all/view-context v1.4.9

Type: Update

The UiAction interface got a new property:

export interface UiAction {
    ...
    /**
    * Additional parameters for executing the UI action.
    */
    params?: { [key: string]: any; };
}

@smartbit4all/view-context v1.4.7

Type: Bugfix

Simultaneously opened dialogs could cause an issue when closing them.

@smartbit4all/view-context v1.4.1

Type: Update

The SmartRedirectConfiguration has been removed.

The SmartViewRedirect became to a component.

@smartbit4all/view-context v1.4.0

Type: Update

Opening a page in our website using a custom link became as easy as it should be.

To apply this new functionality in your application, follow the instructions above.

New type has been introduced:

This SmartRedirectConfiguration interface is designed to directly set the path variable names for the SmartViewRedirect class.

export interface SmartRedirectConfiguration {
    channelInUrl: string;
    uuidInUrl: string;
}

@smartbit4all/view-context v1.3.3

Type: Update

The UiActionInputType enum got a new option: Textarea.

@smartbit4all/view-context v1.3.2

Type: Update

New feature introduced: getViewConstraint

Gets related constraints by the uuid of the page.

@smartbit4all/view-context v1.3.1

Type: Update

Major changes have been made in the models:

  • The original ViewContext has been renamed to ViewContextData
  • The new ViewContext is only for backend purposes
  • The ViewData no longer contains the property parameters
  • The ViewData got a new property: message?: MessageData;

@smartbit4all/view-context v1.2.6

Type: Update

New type introduced: UiActionRequest.

Some of the existing objects have been changed:

  • UiAction no longer contains apiName and apiFunction
  • ViewData got a model property

@smartbit4all/view-context v1.2.5

Type: Update

New types introduced: ViewConstraint and ComponentConstraint.

@smartbit4all/view-context v1.2.4

Type: Update

New type introduced: UiActionSource.

The UiAction got an identifier property.

@smartbit4all/view-context v1.2.0

Type: Feature

This version extends the basic features of the SmartViewContext with built-in error handling.

Requirements:

In case of an error, the backend has to return a ViewApiError with the error code 409.

export interface ViewApiError {
    code?: string;
    message?: string;
}

The package uses an interceptor which catches this error and shows it in a dialog. The settings of the error dialogs can be injected into the SmartViewContextService, just like the SmartViewHandlerModel.

export interface SmartViewContextApiError {
    code: string;
    dialogTitle?: string;
    message: string;
    buttonLabel?: string;
    customAction?: () => void;
}

export interface SmartViewContextApiErrors {
    viewContextApiErrors: Array<SmartViewContextApiError>;
}

@smartbit4all/view-context v1.1.0

Type: Feature

This update contains a new function which help to show and handle messages provided by the ViewContext. The flow is thoroughly handled by this package.

Type: Update

From now on the uuid parameter of the getAndSyncViewContext function is optional.

public async getAndSyncViewContext(uuid?: string): Promise<void> {
    if (!uuid) {
        uuid = this.getUuidOfPage(this.tabIdName);
    }
    ...
}

@smartbit4all/view-context v1.0.8

Type: Feature

In this update SmartViewContextService got a new Subject property (viewContextHasBeenSynced) which emits an event when the syncView was called.

@smartbit4all/view-context v1.0.7

Type: Feature

In this update SmartViewContextService got a new functionality which helps to restore the opened view data after a refresh:

SmartViewContextService:

public restoreViews(): void

@smartbit4all/view-context v1.0.6

Type: Feature

In this update SmartViewContextService got a new functionality which helps to get the ViewData object by page name:

SmartViewContextService:

public async getViewContextDataByPageName(pageName: string): Promise<ViewData>

@smartbit4all/view-context v1.0.5

Type: Feature

In this update SmartViewContextService got a new functionality which helps to detect uuid changes of certain pages.

SmartViewContextService:

public uuidOfPageHasBeenChanged: Subject<string> = new Subject();

@smartbit4all/view-context v1.0.4

Type: Bugfix

ViewContextUUID was not added to HeaderParameters when the viewContext was initialized as an existing one.

@smartbit4all/view-context v1.0.3

Type: Bugfix

Two bug has been fixed in this update:

  • The addig header parameters to SmartSession
  • Routing with query parameters

@smartbit4all/view-context v1.0.1

Type: Update

The package has been published.

@smartbit4all/view-context v0.1.2

Type: Feature

In this update several changes have been done:

  1. model changes
  2. function publicity changes
  3. function implementation

Model changes

The SmartViewHandlerModel has been rethinked, hence the service property has been changed to component, while the type has been removed.

smart-view-context.model.ts:

export interface SmartViewHandlerModel {
    name: string;
    route?: string;
    component?: ComponentType<any>;
}

Function publicity changes

In the SmartViewContextService the publicity of the openView and closeView has been changed from private to public.

Function implementation

The closeView has been implemented, however, it only closes dialogs.

public closeView(view: ViewData): void {
    let viewHandler: SmartViewHandlerModel | undefined = this.viewHandlers.find(
        (handler) => handler.name === view.viewName
    );

    if (!viewHandler) {
        throw new Error(`SmartViewHandlerModel was not found by view name: ${view.viewName}`);
    }

    if (view.type === ViewType.Dialog) {
        this.dialog.closeDialog();
    } else if (view.type === ViewType.Normal) {
        // TODO: close normal page???
    } else {
        throw new Error("The type of the view and its viewHandler is not the same!");
    }

    view.state = ViewState.Closed;

    this.openedViewUuids.slice(this.openedViewUuids.indexOf(view.uuid), 1);

    sessionStorage.removeItem(view.viewName);

    this.updateViewContext({
        updates: [
            {
                state: ViewState.Closed,
                uuid: view.uuid,
            },
        ],
        uuid: this.viewContext?.uuid,
    });
}

@smartbit4all/view-context v0.1.1

Type: Feature

The SmartViewContext has been created.

1.5.44

10 months ago

1.5.43

11 months ago

1.5.30

1 year ago

1.5.32

1 year ago

1.4.20

1 year ago

1.5.31

1 year ago

1.5.34

1 year ago

1.5.33

1 year ago

1.4.21

1 year ago

1.5.36

1 year ago

1.5.35

1 year ago

1.5.38

1 year ago

1.5.37

1 year ago

1.5.39

1 year ago

1.5.41

1 year ago

1.5.40

1 year ago

1.5.9

1 year ago

1.5.42

1 year ago

1.5.8

1 year ago

1.5.7

1 year ago

1.5.6

1 year ago

1.5.5

1 year ago

1.5.4

1 year ago

1.5.3

1 year ago

1.5.2

1 year ago

1.5.1

1 year ago

1.5.0

1 year ago

1.5.10

1 year ago

1.5.12

1 year ago

1.5.11

1 year ago

1.5.14

1 year ago

1.5.13

1 year ago

1.5.16

1 year ago

1.5.15

1 year ago

1.5.18

1 year ago

1.5.17

1 year ago

1.5.19

1 year ago

1.5.21

1 year ago

1.5.20

1 year ago

1.4.9

1 year ago

1.5.23

1 year ago

1.4.11

1 year ago

1.5.22

1 year ago

1.4.10

1 year ago

1.5.25

1 year ago

1.4.13

1 year ago

1.5.24

1 year ago

1.4.12

1 year ago

1.5.27

1 year ago

1.4.15

1 year ago

1.5.26

1 year ago

1.4.14

1 year ago

1.5.29

1 year ago

1.4.17

1 year ago

1.5.28

1 year ago

1.4.16

1 year ago

1.4.19

1 year ago

1.4.18

1 year ago

1.4.6

1 year ago

1.4.5

1 year ago

1.4.4

1 year ago

1.4.3

1 year ago

1.4.2

1 year ago

1.4.1

1 year ago

1.4.0

1 year ago

1.4.8

1 year ago

1.4.7

1 year ago

1.2.7

1 year ago

1.2.6

1 year ago

1.3.3

1 year ago

1.3.2

1 year ago

1.3.1

1 year ago

1.2.9

1 year ago

1.2.12

1 year ago

1.2.10

1 year ago

1.2.11

1 year ago

1.2.0

1 year ago

1.1.0

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.2.5

1 year ago

1.0.7

2 years ago

1.2.4

1 year ago

1.0.6

2 years ago

1.2.3

1 year ago

1.0.5

2 years ago

1.2.2

1 year ago

1.0.4

2 years ago

1.2.1

1 year ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago