Web Components

Introduction

Web components are plain javascript elements which are introduced in order to achieve:

  • sharing of application components (e.g. time-range selectors) across different javascript frameworks
  • building cross-module frontend components, by exporting them as a web-component they can be included as a black-box by any other component to render the presentation.

Web components are created in separate repositories, with separate Angular projects for every web component. Projects are separated into two repositories:

  • non-gxp repository (implementing non-gxp functionality)
  • gxp repository (implementing gxp/shared functionality)

Accordingly web-components will be deployed to the non-gxp or gxp node of DCP.

The @angular/elements library is used to register every web component in window object. Details can be found here or here The compiled web components neither use NGRX Store, or session/local store, but instead they work as a black box with @Inputs/@Outpus.

To add unique identifications for every one component @angular-builders/custom-webpack and custom-webpack configs are used. This allows to use more than one Angular web components inside the apps The build process for every web component includes standard ng build and a gulp bundle task, which concatenates the files into a single JS file.

The built JS file is imported into the base app index.html, and use of the registered tag. See the example below:

<script type="text/javascript" src="./web-components/mvda/dashboard-model-presentation/dashboard-model-presentation.js"></script>

<dc-model-presentation-view></dc-model-presentation-view>

Available Components

This section briefly describes the available components and how to use them.

Time Range

The TimeRangeComponent is styled and ready to use time range web component based on @danielmoncada/angular-datetime-picker It extends the component with the following:

  • pre-applied DCP styling
  • user option to select/configure pre-defined time ranges.

All inputs and outputs of the component use UTC date time strings. The visualization of the date is based on given UTC dates and given timezone.

The component javascript is loaded inside DCP Base App to be used inside Angular and VueJS application(s). The component emits a custom event timeRangeChange which other parts of the application can subscribe to, the selected time is delivered in the event details.

Attributes

Name Type Default Description
language string en Current language code, used to switch implemented translations. Currently implemented languages codes are en and de for English and German.
timezone string Europe/Berlin Timezone identifier used by moment-timezone for properly show dates if there is an date offset.
timeRange ITimeRange {StartTime: moment().subtract(4, 'hours').toISOString(), EndTime: moment().toDate().toISOString()} Preselected time range class with start and end time
placeholder (optional) string Select time range
translated on current language (en/de)
String to be used as a input label.
minmax (optional) ITimeRange undefined Time range class used to set up min and max selectable dates. When is not used, min date will not be set, and max date will be set to current time.
disabled (optional) boolean false Change Time Range component disable state
showPredefinedPeriods (optional) boolean true Show/hide predefined periods selectors
listedPeriods (optional) predefinedPeriodsTypes[] ['Today','Yesterday',
'CurrentWeek','PreviousWeek',
'CurrentMonth','PreviousMonth',
'CurrentQuarter','PreviousQuarter',
'CurrentYear','PreviousYear']
List of predefined options to be shown to user.

Events

Name Type Description
timeRangeChange EventEmitter<{StartTime: string; EndTime: string;}> Return time range class after time range selection

Types and Models

Name Value
predefinedPeriodsTypes 'Today', 'Yesterday', 'CurrentWeek', 'PreviousWeek', 'CurrentMonth', 'PreviousMonth', 'CurrentQuarter', 'PreviousQuarter', 'CurrentYear', 'PreviousYear', 'Last2Years', 'Last3Years'
ITimeRange {StartTime: string; EndTime: string;}

Usage

Because TimeRangeComponent is Web Component timeRangeChange create CustomEvent. This way the data that will be received is inside $event.detail;

<dcp-time-range [language]="uiFacade.language$ | async"
                [timezone]="uiFacade.siteTimeZoneName$ | async"
                [timeRange]="timeRange"
                [disabled]="uiFacade.isLoading$ | async"
                (timeRangeChange)="timeRangeChanged($event.detail)">
</dcp-time-range>
class Component {
  timeRange = {
    StartTime: moment().subtract(4, 'hours').toISOString(),
    EndTime: moment().toDate().toISOString()
  };

  timeRangeChanged(data: ITimeRange) {
    console.log(data.detail);
    // This will print something like
    // {StartTime: '2023-08-24T08:51:31.000Z', EndTime: '2023-08-24T11:51:31.000Z'}
  }
}

Inside VueJS the comonent can be used as following:

<dcp-time-range :language="store.state.ui.language"
                :timezone="store.state.ui.timeZoneName"
                :disabled="disabled"
                :timeRange="timeRange"
                ref="timeRangeEl">
</dcp-time-range>
mounted() {
  (this.$refs.timeRangeEl as HTMLElement)?.addEventListener('timeRangeChange', this.timeRangeChanged);
}
unmounted() {
  (this.$refs.timeRangeEl as HTMLElement)?.removeEventListener('timeRangeChange', this.timeRangeChanged);
}

timeRangeChanged(data: any) {
  console.log(data.detail);
// This will print something like
// {StartTime: '2023-08-24T08:51:31.000Z', EndTime: '2023-08-24T11:51:31.000Z'}
}

User Banners

The purpose of User Info Banners is to show user information (e.g. system downtime, new updated functionality etc.). The visualization is similar to the one that can be found in many other systems like GitLab. The implementation of banners is split inside two applications - Administration and Base, and WebComponents where is situated User Banner Info web component.

Inside the Administration application all CRUD operations are implemented (responsible for visualize list, edit, create, delete and also activate or deactivate banners). UserInfoBannersComponent is responsible to show User Info Banners to end users by making API call from component to UserInfoBanner/GetAllActiveBanners. To ensure that users will see new banners, a API call is performed every 5 minutes, to updated available banners. Closed banners are stored in the localStorage, so that they are no visible on re-load.

Attributes

Attribute Data type Description
Id number
Name string Name that is visible for administration purpose
Category number Used for different UI styles. Info = 1, Downtime = 2, Error = 3
Description string This field is used as a banner text visualization
IsActive boolean Is the banner active or not
StartTime string Start time for the banner visualization in UI
EndTime string End time for the banner visualization in UI
SiteId (optional) number If is presented the banner will be visible only for selected Site
ModuleName (optional) string If is presented the banner will be visible only for selected Module
LastModifiedAt string Time of last edit
LastModifiedBy string User name of the user that made the last edit

Usage

UserInfoBannersComponent is responsible to show User Info Banners to end users by making API call from component to UserInfoBanner/GetAllActiveBanners.

To achieve that we need to know to which server we need to make this API call. Because UserInfoBannersComponent is a WebComponent and it is not part of the building process for any application, we get that information with @Input baseUrl.

To be sure that user will see new banners we make API call every 5 minutes, to updated available banners.

User have available close button for every banner, that will add banner Id to localStorage.dcpDisabledBanners list. We use localStorage to save this data, to be sure, that on browser refresh user will not see again same browser.

dcpDisabledBanners list and banners ModuleName, SiteId, StartTime and EndTime are used to filter visible for user banners in the UI, based on user activity, current time and current url.

  fillActiveBanners(): void {
    const currentSite = this.getCurrentSite();
    const currentModule = this.getCurrentModule();
    this.activeBanners = [...this.banners.filter(b => {
        const disabledBanners = this.getDisabledBanners();
        const start = moment(b.StartTime);
        const end = moment(b.EndTime);
        const current = moment();
        return current.isBetween(start, end)
            && !disabledBanners.includes(b.Id)
            && (!b.ModuleName || b.ModuleName === currentModule)
            && (!b.SiteId || b.SiteId.toString() === currentSite);
    })];
}

index.html file in Base Application import UserInfoBannersComponent as a web component, display it and set base-url to be used to get available User Info Banners.

<script type="text/javascript" 
        src="https://domain.com/web-components/shared/dcp-user-info-banners/dcp-user-info-banners.js">
</script>

<dcp-user-info-banners base-url="https://dc-dev-gxp.domain.com"></dcp-user-info-banners>

User Banner records

erDiagram

UserInfoBanner  {
 	int(4) ID "UniqueId"
	nvarchar Name "The name used by the admins for easy identification"
	tinyint(1) Category "The catregory (Downtime/etc. used for the styling of the banner)"
	nvarchar Description "The description/info text shown to the users"
	bit(1) IsActive 
	datetime(8) StartTime "The start of the period where this banner should be shown (UTC)"
	datetime(8) EndTime "The end of the period where this banner should be shown (UTC)"
	int(4) LastModifiedBy 
	int(4) OwnerUserId 
	datetime2(8) SysStartTime 
	datetime2(8) SysEndTime 
	int(4) SiteId "If set the banner will be only shown to users in the context of this production site"
	nvarchar ModuleName "If set the banner will be only shown to users in the context of this module"
}

Records classification and audit trail

Specification Value
Content/Overview The configured banners
Data classification Convenience records
Change Tracking SystemVersioned table features inside SQL
Audit Trail N/A
Retention period 3 years

Quill text editor

Quill Text Editor component is a wrapper of ngx-quill. This way the same visual and functional Rich text editor can be used inside the different javascript frameworks (e.g. Angular an VueJS).

Usage

<dcp-quill-text-editor [value]="initialValue"
                       (updateValue)="updateValue($event)">
</dcp-quill-text-editor>

Attributes

Name Type Data type Description
control Input FormControl Used if we need to connect the editor with existing Angular FormControl
value Input string Initial value
updateValue Output string Event triggered when value is updated.

Dashboard model presentation

This ModelPresentationViewComponent is designed to present data in a chart format, considering various attributes like timezone, validation status, and user-specific settings.

The component javascript is loaded inside DCP Base App to be used inside Angular and VueJS application(s). The component emits a custom event timeRangeChange which other parts of the application can subscribe to, the selected time is delivered in the event details.

Attributes

Name Type Default Description
chart DashboardListResponseModel A data configuration for the chart to be displayed.
limits LimitsModel[] An object defining the limit lines for the chart.
timezone string Timezone identifier used by moment-timezone for properly show dates if there is an date offset.
isValidated boolean A boolean indicating whether the data presented in the chart has been validated.
translations TranslationsModel An object containing key-value pairs for multi-language support.
userSettings {dateFormat: string; timeFormat: string;} An object that includes user-specific settings for date and time formats.
height (optional) number null A numeric value (in pixels) defining the height of the component. If empty the height will be set to auto. This allows for a flexible layout that adapts to different screen sizes and container dimensions.

Events

Name Type Description
navigateToData EventEmitter<DashboardListResponseModel> Return chart object after navigate to is triggered

Usage

  1. Allow Custom elements scheme: First, allow custom element scheme in the module that will use the ModelPresentationViewComponent component.

        ...
        schemas: [CUSTOM_ELEMENTS_SCHEMA]
        ...
    
  2. Component Setup: In your dashboard view, set up the ModelPresentationViewComponent component by passing the required attributes.

    <dc-model-presentation-view
      chart={}
      limits={}
      timezone="Europe/Berlin"
      isValidated={true}
      translations={
                     TOOLTIP: "",
                     NUMBER_OF_VIOLATIONS: "",
                     LAST_RESET_TIME: "",
                     UNDEFINED: "",
                     CONDITIONS: "",
                     VIOLATION_IN_ROW: "",
                     VIOLATION_NUMBER: ""
                   }
      userSettings={
                     dateFormat: 'YYYY MMM dd',
                     timeFormat: 'hh:mm:ss'
                   }
      height={300}></dc-model-presentation-view>
    
  3. Data Handling: Ensure that the data passed to the chart attribute is in the correct format. Fetch or compute the data as necessary.

  4. Dynamic Properties: Utilize state management or props to dynamically update the attributes like isValidated translations or userSettings based on user interactions or data changes.

This page was last edited on 19 August 2024, 15:10 (UTC).