UI: Tenant admin home page initial implementation
This commit is contained in:
parent
0f5f8ee714
commit
bcc5eba8e6
@ -91,6 +91,118 @@
|
|||||||
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.sys-admin.step6.how-to-configure-notifications' | translate }}</a>
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.sys-admin.step6.how-to-configure-notifications' | translate }}</a>
|
||||||
</mat-step>
|
</mat-step>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
<ng-template [ngSwitchCase]="authority.TENANT_ADMIN">
|
||||||
|
<mat-step [completed]="gettingStarted.maxSelectedIndex > -1">
|
||||||
|
<ng-template matStepLabel>
|
||||||
|
<div style="width: 100%;" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div translate>widgets.getting-started.tenant-admin.step1.title</div>
|
||||||
|
<a *ngIf="matStepper.selectedIndex === 0" mat-button color="primary" routerLink="/entities/devices">{{ 'device.devices' | translate }}</a>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step1.content' | translate | safe: 'html'"></div>
|
||||||
|
<a mat-stroked-button color="primary" href="https://thingsboard.io/docs/getting-started-guides/helloworld/#step-1-provision-device" target="_blank">
|
||||||
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.tenant-admin.step1.how-to-create-device' | translate }}</a>
|
||||||
|
</mat-step>
|
||||||
|
<mat-step [completed]="gettingStarted.maxSelectedIndex > 0">
|
||||||
|
<ng-template matStepLabel>
|
||||||
|
<div style="width: 100%;" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div translate>widgets.getting-started.tenant-admin.step2.title</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step2.content-before' | translate | safe: 'html'"></div>
|
||||||
|
<div class="tb-bordered-content">
|
||||||
|
<tb-toggle-header #publishCommandSteps value="ubuntu" name="publishCommandSteps">
|
||||||
|
<mat-button-toggle value="ubuntu">Ubuntu</mat-button-toggle>
|
||||||
|
<mat-button-toggle value="macos">MacOS</mat-button-toggle>
|
||||||
|
<mat-button-toggle value="windows">Windows</mat-button-toggle>
|
||||||
|
</tb-toggle-header>
|
||||||
|
<ng-container [ngSwitch]="publishCommandSteps.value">
|
||||||
|
<ng-template [ngSwitchCase]="'ubuntu'">
|
||||||
|
<p [innerHTML]="'widgets.getting-started.tenant-admin.step2.ubuntu.install-curl' | translate | safe: 'html'"></p>
|
||||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data="
|
||||||
|
```bash
|
||||||
|
sudo apt-get install curl
|
||||||
|
{:copy-code}
|
||||||
|
```
|
||||||
|
"></tb-markdown>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template [ngSwitchCase]="'macos'">
|
||||||
|
<p [innerHTML]="'widgets.getting-started.tenant-admin.step2.macos.install-curl' | translate | safe: 'html'"></p>
|
||||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data="
|
||||||
|
```bash
|
||||||
|
brew install curl
|
||||||
|
{:copy-code}
|
||||||
|
```
|
||||||
|
"></tb-markdown>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template [ngSwitchCase]="'windows'">
|
||||||
|
<p [innerHTML]="'widgets.getting-started.tenant-admin.step2.windows.install-curl' | translate | safe: 'html'"></p>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
<p [innerHTML]="'widgets.getting-started.tenant-admin.step2.replace-access-token' | translate | safe: 'html'"></p>
|
||||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data="
|
||||||
|
```bash
|
||||||
|
curl -v -X POST -d "{\"temperature\": 25}" {{baseUrl}}/api/v1/$ACCESS_TOKEN/telemetry --header "Content-Type:application/json"
|
||||||
|
{:copy-code}
|
||||||
|
```
|
||||||
|
"></tb-markdown>
|
||||||
|
</div>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step2.content-after' | translate | safe: 'html'"></div>
|
||||||
|
<a mat-stroked-button color="primary" href="https://thingsboard.io/docs/getting-started-guides/helloworld/#step-2-connect-device" target="_blank">
|
||||||
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.tenant-admin.step2.how-to-connect-device' | translate }}</a>
|
||||||
|
</mat-step>
|
||||||
|
<mat-step [completed]="gettingStarted.maxSelectedIndex > 1">
|
||||||
|
<ng-template matStepLabel>
|
||||||
|
<div style="width: 100%;" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div translate>widgets.getting-started.tenant-admin.step3.title</div>
|
||||||
|
<a *ngIf="matStepper.selectedIndex === 2" mat-button color="primary" routerLink="/dashboards">{{ 'dashboard.dashboards' | translate }}</a>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step3.content' | translate | safe: 'html'"></div>
|
||||||
|
<a mat-stroked-button color="primary" href="https://thingsboard.io/docs/getting-started-guides/helloworld/#step-3-create-dashboard" target="_blank">
|
||||||
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.tenant-admin.step3.how-to-create-dashboard' | translate }}</a>
|
||||||
|
</mat-step>
|
||||||
|
<mat-step [completed]="gettingStarted.maxSelectedIndex > 2">
|
||||||
|
<ng-template matStepLabel>
|
||||||
|
<div style="width: 100%;" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div translate>widgets.getting-started.tenant-admin.step4.title</div>
|
||||||
|
<a *ngIf="matStepper.selectedIndex === 3" mat-button color="primary" routerLink="/profiles/deviceProfiles">{{ 'widgets.getting-started.tenant-admin.step4.alarm-rules' | translate }}</a>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step4.content' | translate | safe: 'html'"></div>
|
||||||
|
<a mat-stroked-button color="primary" href="https://thingsboard.io/docs/getting-started-guides/helloworld/#step-4-configure-alarm-rules" target="_blank">
|
||||||
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.tenant-admin.step4.how-to-configure-alarm-rules' | translate }}</a>
|
||||||
|
</mat-step>
|
||||||
|
<mat-step [completed]="gettingStarted.maxSelectedIndex > 3">
|
||||||
|
<ng-template matStepLabel>
|
||||||
|
<div style="width: 100%;" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div translate>widgets.getting-started.tenant-admin.step5.title</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step5.content-before' | translate | safe: 'html'"></div>
|
||||||
|
<p [innerHTML]="'widgets.getting-started.tenant-admin.step5.replace-access-token' | translate | safe: 'html'"></p>
|
||||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data="
|
||||||
|
```bash
|
||||||
|
curl -v -X POST -d "{\"temperature\": 26}" {{baseUrl}}/api/v1/$ACCESS_TOKEN/telemetry --header "Content-Type:application/json"
|
||||||
|
{:copy-code}
|
||||||
|
```
|
||||||
|
"></tb-markdown>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step5.content-after' | translate | safe: 'html'"></div>
|
||||||
|
<a mat-stroked-button color="primary" href="https://thingsboard.io/docs/getting-started-guides/helloworld/#step-5-create-alarm" target="_blank">
|
||||||
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.tenant-admin.step5.how-to-create-alarm' | translate }}</a>
|
||||||
|
</mat-step>
|
||||||
|
<mat-step [completed]="gettingStarted.maxSelectedIndex > 4">
|
||||||
|
<ng-template matStepLabel>
|
||||||
|
<div style="width: 100%;" fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div translate>widgets.getting-started.tenant-admin.step6.title</div>
|
||||||
|
<a *ngIf="matStepper.selectedIndex === 5" mat-button color="primary" routerLink="/customers">{{ 'customer.customers' | translate }}</a>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
<div [innerHTML]="'widgets.getting-started.tenant-admin.step6.content' | translate | safe: 'html'"></div>
|
||||||
|
<a mat-stroked-button color="primary" href="https://thingsboard.io/docs/getting-started-guides/helloworld/#step-7-assign-device-and-dashboard-to-customer" target="_blank">
|
||||||
|
<mat-icon>description</mat-icon>{{ 'widgets.getting-started.tenant-admin.step6.how-to-create-customer-and-assign-dashboard' | translate }}</a>
|
||||||
|
</mat-step>
|
||||||
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</mat-stepper>
|
</mat-stepper>
|
||||||
<div *ngIf="allCompleted" fxLayout="column" fxLayoutAlign="center center" style="padding-top: 24px;">
|
<div *ngIf="allCompleted" fxLayout="column" fxLayoutAlign="center center" style="padding-top: 24px;">
|
||||||
|
|||||||
@ -83,13 +83,105 @@
|
|||||||
color: rgba(0, 0, 0, 0.87);
|
color: rgba(0, 0, 0, 0.87);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tb-get-started .mat-vertical-content p {
|
.tb-get-started .mat-vertical-content {
|
||||||
font-style: normal;
|
p, li {
|
||||||
font-weight: 400;
|
font-style: normal;
|
||||||
font-size: 14px;
|
font-weight: 400;
|
||||||
line-height: 20px;
|
font-size: 14px;
|
||||||
letter-spacing: 0.2px;
|
line-height: 20px;
|
||||||
color: rgba(0, 0, 0, 0.54);
|
letter-spacing: 0.2px;
|
||||||
|
color: rgba(0, 0, 0, 0.54);
|
||||||
|
em {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(0, 0, 0, 0.38);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
padding-inline-start: 20px;
|
||||||
|
}
|
||||||
|
.tb-bordered-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
p {
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tb-markdown-view {
|
||||||
|
.tb-getting-started-code {
|
||||||
|
.code-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
pre[class*=language-] {
|
||||||
|
margin: 0;
|
||||||
|
padding: 9px 38px 9px 16px;
|
||||||
|
background: rgba(0, 0, 0, 0.03);
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
code[class*="language-"], pre[class*="language-"] {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.25px;
|
||||||
|
color: rgba(0, 0, 0, 0.38);
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: break-spaces;
|
||||||
|
word-break: break-all;
|
||||||
|
& * {
|
||||||
|
color: rgba(0, 0, 0, 0.38);
|
||||||
|
cursor: inherit;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button.clipboard-btn {
|
||||||
|
right: 0;
|
||||||
|
height: 34px;
|
||||||
|
p, div {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 7px;
|
||||||
|
color: #305680;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
top: 0;
|
||||||
|
padding: 8px;
|
||||||
|
height: 34px;
|
||||||
|
width: 34px;
|
||||||
|
img {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
position: initial;
|
||||||
|
display: block;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background: #305680;
|
||||||
|
-webkit-mask-image: url(/assets/copy-code-icon.svg);
|
||||||
|
-webkit-mask-repeat: no-repeat;
|
||||||
|
mask-image: url(/assets/copy-code-icon.svg);
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media #{$mat-md-lg} {
|
||||||
|
.tb-bordered-content {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media #{$mat-md-lg} {
|
@media #{$mat-md-lg} {
|
||||||
@ -107,15 +199,16 @@
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tb-get-started .mat-vertical-content p {
|
.tb-get-started .mat-vertical-content {
|
||||||
font-size: 12px;
|
p, li {
|
||||||
line-height: 16px;
|
font-size: 12px;
|
||||||
letter-spacing: 0.25px;
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.25px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tb-get-started .mat-vertical-content {
|
.tb-get-started .mat-vertical-content {
|
||||||
padding: 0 16px 16px 16px;
|
padding: 0 16px 16px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import {
|
|||||||
} from '@home/components/widget/lib/home-page/getting-started-completed-dialog.component';
|
} from '@home/components/widget/lib/home-page/getting-started-completed-dialog.component';
|
||||||
import { GettingStarted } from '@shared/models/user-settings.models';
|
import { GettingStarted } from '@shared/models/user-settings.models';
|
||||||
import { CdkStep, StepperSelectionEvent } from '@angular/cdk/stepper';
|
import { CdkStep, StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||||
import { isUndefined } from '@core/utils';
|
import { baseUrl, isUndefined } from '@core/utils';
|
||||||
import { MatStepper } from '@angular/material/stepper';
|
import { MatStepper } from '@angular/material/stepper';
|
||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
import { Authority } from '@shared/models/authority.enum';
|
import { Authority } from '@shared/models/authority.enum';
|
||||||
@ -54,6 +54,8 @@ export class GettingStartedWidgetComponent extends PageComponent implements OnIn
|
|||||||
};
|
};
|
||||||
allCompleted = false;
|
allCompleted = false;
|
||||||
|
|
||||||
|
baseUrl = baseUrl();
|
||||||
|
|
||||||
constructor(protected store: Store<AppState>,
|
constructor(protected store: Store<AppState>,
|
||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
private userSettingsService: UserSettingsService,
|
private userSettingsService: UserSettingsService,
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import { GettingStartedWidgetComponent } from '@home/components/widget/lib/home-
|
|||||||
import {
|
import {
|
||||||
GettingStartedCompletedDialogComponent
|
GettingStartedCompletedDialogComponent
|
||||||
} from '@home/components/widget/lib/home-page/getting-started-completed-dialog.component';
|
} from '@home/components/widget/lib/home-page/getting-started-completed-dialog.component';
|
||||||
|
import { ToggleHeaderComponent } from '@home/components/widget/lib/home-page/toggle-header.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations:
|
declarations:
|
||||||
@ -40,7 +41,8 @@ import {
|
|||||||
AddDocLinkDialogComponent,
|
AddDocLinkDialogComponent,
|
||||||
EditDocLinksDialogComponent,
|
EditDocLinksDialogComponent,
|
||||||
GettingStartedWidgetComponent,
|
GettingStartedWidgetComponent,
|
||||||
GettingStartedCompletedDialogComponent
|
GettingStartedCompletedDialogComponent,
|
||||||
|
ToggleHeaderComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -55,7 +57,8 @@ import {
|
|||||||
AddDocLinkDialogComponent,
|
AddDocLinkDialogComponent,
|
||||||
EditDocLinksDialogComponent,
|
EditDocLinksDialogComponent,
|
||||||
GettingStartedWidgetComponent,
|
GettingStartedWidgetComponent,
|
||||||
GettingStartedCompletedDialogComponent
|
GettingStartedCompletedDialogComponent,
|
||||||
|
ToggleHeaderComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class HomePageWidgetsModule { }
|
export class HomePageWidgetsModule { }
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2023 The Thingsboard Authors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<mat-button-toggle-group class="tb-toggle-header" #toggleGroup="matButtonToggleGroup" [name]="name">
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</mat-button-toggle-group>
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2023 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import "../../../../../../../scss/constants";
|
||||||
|
|
||||||
|
:host ::ng-deep {
|
||||||
|
.mat-button-toggle-group.mat-button-toggle-group-appearance-standard.tb-toggle-header {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 100px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 2px;
|
||||||
|
border: none;
|
||||||
|
background: rgba(0, 0, 0, 0.06);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
.mat-button-toggle + .mat-button-toggle {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
.mat-button-toggle.mat-button-toggle-appearance-standard {
|
||||||
|
flex: 1;
|
||||||
|
color: rgba(0, 0, 0, 0.38);
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
.mat-button-toggle-focus-overlay, .mat-button-toggle-ripple {
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
.mat-button-toggle-button {
|
||||||
|
height: 28px;
|
||||||
|
.mat-button-toggle-label-content {
|
||||||
|
line-height: 26px;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 0.2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.mat-button-toggle-checked {
|
||||||
|
.mat-button-toggle-button {
|
||||||
|
background: #F3F6FA;
|
||||||
|
color: #305680;
|
||||||
|
border: 1px solid #305680;
|
||||||
|
border-radius: 20px;
|
||||||
|
|
||||||
|
.mat-button-toggle-label-content {
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media #{$mat-md-lg} {
|
||||||
|
.mat-button-toggle-group.mat-button-toggle-group-appearance-standard.tb-toggle-header {
|
||||||
|
height: 24px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
.mat-button-toggle.mat-button-toggle-appearance-standard {
|
||||||
|
.mat-button-toggle-button {
|
||||||
|
height: 20px;
|
||||||
|
display: grid;
|
||||||
|
.mat-button-toggle-label-content {
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.mat-button-toggle-checked {
|
||||||
|
.mat-button-toggle-button {
|
||||||
|
.mat-button-toggle-label-content {
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2023 The Thingsboard Authors
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
|
||||||
|
import {
|
||||||
|
AfterContentInit,
|
||||||
|
AfterViewInit,
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
ContentChildren,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
QueryList,
|
||||||
|
ViewChild
|
||||||
|
} from '@angular/core';
|
||||||
|
import { PageComponent } from '@shared/components/page.component';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { AdminService } from '@core/http/admin.service';
|
||||||
|
import { UpdateMessage } from '@shared/models/settings.models';
|
||||||
|
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
|
||||||
|
import { Authority } from '@shared/models/authority.enum';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { MatStepper } from '@angular/material/stepper';
|
||||||
|
import { MatButtonToggle, MatButtonToggleGroup } from '@angular/material/button-toggle';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-toggle-header',
|
||||||
|
templateUrl: './toggle-header.component.html',
|
||||||
|
styleUrls: ['./toggle-header.component.scss']
|
||||||
|
})
|
||||||
|
export class ToggleHeaderComponent extends PageComponent implements OnInit, AfterViewInit {
|
||||||
|
|
||||||
|
@ViewChild('toggleGroup')
|
||||||
|
toggleGroup: MatButtonToggleGroup;
|
||||||
|
|
||||||
|
@ContentChildren(MatButtonToggle)
|
||||||
|
_buttonToggles: QueryList<MatButtonToggle>;
|
||||||
|
|
||||||
|
innerValue: any;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
set value(value: any) {
|
||||||
|
this.innerValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get value(): any {
|
||||||
|
return this.toggleGroup?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
for (const toggle of this._buttonToggles) {
|
||||||
|
toggle.buttonToggleGroup = this.toggleGroup;
|
||||||
|
if (this.innerValue === toggle.value) {
|
||||||
|
toggle.checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -27,6 +27,7 @@ import { AppState } from '@core/core.state';
|
|||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
|
import { getCurrentAuthUser } from '@core/auth/auth.selectors';
|
||||||
import sysAdminHomePageDashboardJson from '!raw-loader!./sys_admin_home_page.raw';
|
import sysAdminHomePageDashboardJson from '!raw-loader!./sys_admin_home_page.raw';
|
||||||
|
import tenantAdminHomePageDashboardJson from '!raw-loader!./tenant_admin_home_page.raw';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HomeDashboardResolver implements Resolve<HomeDashboard> {
|
export class HomeDashboardResolver implements Resolve<HomeDashboard> {
|
||||||
@ -39,8 +40,18 @@ export class HomeDashboardResolver implements Resolve<HomeDashboard> {
|
|||||||
return this.dashboardService.getHomeDashboard().pipe(
|
return this.dashboardService.getHomeDashboard().pipe(
|
||||||
map((dashboard) => {
|
map((dashboard) => {
|
||||||
if (!dashboard) {
|
if (!dashboard) {
|
||||||
if (getCurrentAuthUser(this.store).authority === Authority.SYS_ADMIN) {
|
const authority = getCurrentAuthUser(this.store).authority;
|
||||||
dashboard = JSON.parse(sysAdminHomePageDashboardJson);
|
switch (authority) {
|
||||||
|
case Authority.SYS_ADMIN:
|
||||||
|
dashboard = JSON.parse(sysAdminHomePageDashboardJson);
|
||||||
|
break;
|
||||||
|
case Authority.TENANT_ADMIN:
|
||||||
|
dashboard = JSON.parse(tenantAdminHomePageDashboardJson);
|
||||||
|
break;
|
||||||
|
case Authority.CUSTOMER_USER:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dashboard) {
|
||||||
dashboard.hideDashboardToolbar = true;
|
dashboard.hideDashboardToolbar = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,667 @@
|
|||||||
|
{
|
||||||
|
"title": "Tenant Administrator Home Page",
|
||||||
|
"image": null,
|
||||||
|
"mobileHide": false,
|
||||||
|
"mobileOrder": null,
|
||||||
|
"configuration": {
|
||||||
|
"description": "",
|
||||||
|
"widgets": {
|
||||||
|
"d70cc256-4c7b-ee06-9905-b8c5e546605f": {
|
||||||
|
"isSystemType": true,
|
||||||
|
"bundleAlias": "cards",
|
||||||
|
"typeAlias": "markdown_card",
|
||||||
|
"type": "latest",
|
||||||
|
"title": "New widget",
|
||||||
|
"image": null,
|
||||||
|
"description": null,
|
||||||
|
"sizeX": 5,
|
||||||
|
"sizeY": 3.5,
|
||||||
|
"config": {
|
||||||
|
"datasources": [],
|
||||||
|
"timewindow": {
|
||||||
|
"displayValue": "",
|
||||||
|
"selectedTab": 0,
|
||||||
|
"realtime": {
|
||||||
|
"realtimeType": 1,
|
||||||
|
"interval": 1000,
|
||||||
|
"timewindowMs": 60000,
|
||||||
|
"quickInterval": "CURRENT_DAY"
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"historyType": 0,
|
||||||
|
"interval": 1000,
|
||||||
|
"timewindowMs": 60000,
|
||||||
|
"fixedTimewindow": {
|
||||||
|
"startTimeMs": 1680168340431,
|
||||||
|
"endTimeMs": 1680254740431
|
||||||
|
},
|
||||||
|
"quickInterval": "CURRENT_DAY"
|
||||||
|
},
|
||||||
|
"aggregation": {
|
||||||
|
"type": "AVG",
|
||||||
|
"limit": 25000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"showTitle": false,
|
||||||
|
"backgroundColor": "#fff",
|
||||||
|
"color": "rgba(0, 0, 0, 0.87)",
|
||||||
|
"padding": "16px",
|
||||||
|
"settings": {
|
||||||
|
"useMarkdownTextFunction": false,
|
||||||
|
"markdownTextPattern": "<div class=\"tb-card-content\">\n <div fxLayout=\"row\" fxLayoutAlign=\"space-between start\">\n <div class=\"tb-home-widget-title\">{{ 'widgets.activity.title' | translate }}</div>\n <tb-toggle-header #activityStates value=\"devices\" name=\"activityStates\">\n <mat-button-toggle value=\"devices\">{{ 'device.devices' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"transportMessages\">{{ 'widgets.transport-messages.title' | translate }}</mat-button-toggle>\n </tb-toggle-header>\n </div>\n <ng-container [ngSwitch]=\"activityStates.value\">\n <ng-template [ngSwitchCase]=\"'devices'\">\n <tb-dashboard-state fxFlex stateId=\"devices_activity\" [ctx]=\"ctx\"></tb-dashboard-state>\n </ng-template>\n <ng-template [ngSwitchCase]=\"'transportMessages'\">\n <tb-dashboard-state fxFlex stateId=\"transport_messages\" [ctx]=\"ctx\"></tb-dashboard-state>\n </ng-template>\n </ng-container>\n</div>",
|
||||||
|
"applyDefaultMarkdownStyle": false,
|
||||||
|
"markdownCss": ".tb-card-content {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n}\n"
|
||||||
|
},
|
||||||
|
"title": "Transport messages",
|
||||||
|
"showTitleIcon": false,
|
||||||
|
"iconColor": "rgba(0, 0, 0, 0.87)",
|
||||||
|
"iconSize": "24px",
|
||||||
|
"titleTooltip": "",
|
||||||
|
"dropShadow": false,
|
||||||
|
"enableFullscreen": false,
|
||||||
|
"widgetStyle": {},
|
||||||
|
"titleStyle": {
|
||||||
|
"fontSize": "16px",
|
||||||
|
"fontWeight": 400
|
||||||
|
},
|
||||||
|
"showLegend": false,
|
||||||
|
"useDashboardTimewindow": true,
|
||||||
|
"widgetCss": "",
|
||||||
|
"pageSize": 1024,
|
||||||
|
"noDataDisplayMessage": ""
|
||||||
|
},
|
||||||
|
"row": 0,
|
||||||
|
"col": 0,
|
||||||
|
"id": "d70cc256-4c7b-ee06-9905-b8c5e546605f"
|
||||||
|
},
|
||||||
|
"8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e": {
|
||||||
|
"isSystemType": true,
|
||||||
|
"bundleAlias": "charts",
|
||||||
|
"typeAlias": "timeseries_bars_flot",
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "New widget",
|
||||||
|
"image": null,
|
||||||
|
"description": null,
|
||||||
|
"sizeX": 8,
|
||||||
|
"sizeY": 5,
|
||||||
|
"config": {
|
||||||
|
"datasources": [
|
||||||
|
{
|
||||||
|
"type": "entity",
|
||||||
|
"name": null,
|
||||||
|
"entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079",
|
||||||
|
"filterId": null,
|
||||||
|
"dataKeys": [
|
||||||
|
{
|
||||||
|
"name": "transportMsgCountHourly",
|
||||||
|
"type": "timeseries",
|
||||||
|
"label": "{i18n:widgets.transport-messages.title}",
|
||||||
|
"color": "#305680",
|
||||||
|
"settings": {},
|
||||||
|
"_hash": 0.2880464219129071,
|
||||||
|
"aggregationType": null,
|
||||||
|
"units": null,
|
||||||
|
"decimals": null,
|
||||||
|
"funcBody": null,
|
||||||
|
"usePostProcessing": null,
|
||||||
|
"postFuncBody": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"latestDataKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timewindow": {
|
||||||
|
"hideInterval": false,
|
||||||
|
"hideLastInterval": false,
|
||||||
|
"hideQuickInterval": false,
|
||||||
|
"hideAggregation": true,
|
||||||
|
"hideAggInterval": false,
|
||||||
|
"hideTimezone": false,
|
||||||
|
"selectedTab": 1,
|
||||||
|
"history": {
|
||||||
|
"historyType": 0,
|
||||||
|
"timewindowMs": 2592000000,
|
||||||
|
"interval": 86400000,
|
||||||
|
"fixedTimewindow": {
|
||||||
|
"startTimeMs": 1680443065451,
|
||||||
|
"endTimeMs": 1680529465451
|
||||||
|
},
|
||||||
|
"quickInterval": "CURRENT_DAY"
|
||||||
|
},
|
||||||
|
"aggregation": {
|
||||||
|
"type": "SUM",
|
||||||
|
"limit": 50000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"showTitle": false,
|
||||||
|
"backgroundColor": "#fff",
|
||||||
|
"color": "rgba(0, 0, 0, 0.87)",
|
||||||
|
"padding": "0px",
|
||||||
|
"settings": {
|
||||||
|
"stack": true,
|
||||||
|
"fontSize": 10,
|
||||||
|
"fontColor": "#545454",
|
||||||
|
"showTooltip": true,
|
||||||
|
"tooltipIndividual": false,
|
||||||
|
"tooltipCumulative": false,
|
||||||
|
"hideZeros": false,
|
||||||
|
"grid": {
|
||||||
|
"verticalLines": false,
|
||||||
|
"horizontalLines": false,
|
||||||
|
"outlineWidth": 0,
|
||||||
|
"color": "#545454",
|
||||||
|
"backgroundColor": null,
|
||||||
|
"tickColor": "#DDDDDD"
|
||||||
|
},
|
||||||
|
"xaxis": {
|
||||||
|
"title": null,
|
||||||
|
"showLabels": true,
|
||||||
|
"color": "#545454"
|
||||||
|
},
|
||||||
|
"yaxis": {
|
||||||
|
"min": 0,
|
||||||
|
"max": null,
|
||||||
|
"title": null,
|
||||||
|
"showLabels": true,
|
||||||
|
"color": "#545454",
|
||||||
|
"tickSize": null,
|
||||||
|
"tickDecimals": 0,
|
||||||
|
"ticksFormatter": "return value % 1000 === 0 ? ((value / 1000) + 'k') : '';"
|
||||||
|
},
|
||||||
|
"defaultBarWidth": 1800000,
|
||||||
|
"barAlignment": "left",
|
||||||
|
"comparisonEnabled": false,
|
||||||
|
"timeForComparison": "previousInterval",
|
||||||
|
"comparisonCustomIntervalValue": 7200000,
|
||||||
|
"xaxisSecond": {
|
||||||
|
"axisPosition": "top",
|
||||||
|
"title": null,
|
||||||
|
"showLabels": true
|
||||||
|
},
|
||||||
|
"customLegendEnabled": false,
|
||||||
|
"dataKeysListForLabels": []
|
||||||
|
},
|
||||||
|
"title": "Transport messages",
|
||||||
|
"dropShadow": false,
|
||||||
|
"enableFullscreen": false,
|
||||||
|
"titleStyle": {
|
||||||
|
"fontSize": "16px",
|
||||||
|
"fontWeight": 400
|
||||||
|
},
|
||||||
|
"widgetStyle": {
|
||||||
|
"padding": "0"
|
||||||
|
},
|
||||||
|
"useDashboardTimewindow": false,
|
||||||
|
"showLegend": false,
|
||||||
|
"actions": {},
|
||||||
|
"displayTimewindow": true,
|
||||||
|
"showTitleIcon": false,
|
||||||
|
"titleTooltip": "",
|
||||||
|
"widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-widget-container > .tb-widget .flot-base {\n opacity: 0.48;\n}\n",
|
||||||
|
"pageSize": 1024,
|
||||||
|
"noDataDisplayMessage": "",
|
||||||
|
"legendConfig": {
|
||||||
|
"direction": "column",
|
||||||
|
"position": "bottom",
|
||||||
|
"sortDataKeys": false,
|
||||||
|
"showMin": false,
|
||||||
|
"showMax": false,
|
||||||
|
"showAvg": true,
|
||||||
|
"showTotal": false,
|
||||||
|
"showLatest": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"row": 0,
|
||||||
|
"col": 0,
|
||||||
|
"id": "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e"
|
||||||
|
},
|
||||||
|
"867f82cf-ecf2-2d5c-35cb-08c6f2edc3a4": {
|
||||||
|
"isSystemType": true,
|
||||||
|
"bundleAlias": "home_page_widgets",
|
||||||
|
"typeAlias": "documentation_links",
|
||||||
|
"type": "static",
|
||||||
|
"title": "New widget",
|
||||||
|
"image": null,
|
||||||
|
"description": null,
|
||||||
|
"sizeX": 7.5,
|
||||||
|
"sizeY": 3,
|
||||||
|
"config": {
|
||||||
|
"datasources": [],
|
||||||
|
"timewindow": {
|
||||||
|
"realtime": {
|
||||||
|
"timewindowMs": 60000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"showTitle": false,
|
||||||
|
"backgroundColor": "rgb(255, 255, 255)",
|
||||||
|
"color": "rgba(0, 0, 0, 0.87)",
|
||||||
|
"padding": "16px",
|
||||||
|
"settings": {
|
||||||
|
"columns": 2
|
||||||
|
},
|
||||||
|
"title": "Documentation",
|
||||||
|
"dropShadow": false,
|
||||||
|
"enableFullscreen": false,
|
||||||
|
"widgetStyle": {},
|
||||||
|
"widgetCss": "",
|
||||||
|
"pageSize": 1024,
|
||||||
|
"noDataDisplayMessage": "",
|
||||||
|
"showLegend": false
|
||||||
|
},
|
||||||
|
"row": 0,
|
||||||
|
"col": 0,
|
||||||
|
"id": "867f82cf-ecf2-2d5c-35cb-08c6f2edc3a4"
|
||||||
|
},
|
||||||
|
"a23185ad-dc46-806c-0e50-5b21fb080ace": {
|
||||||
|
"isSystemType": true,
|
||||||
|
"bundleAlias": "home_page_widgets",
|
||||||
|
"typeAlias": "getting_started",
|
||||||
|
"type": "static",
|
||||||
|
"title": "New widget",
|
||||||
|
"image": null,
|
||||||
|
"description": null,
|
||||||
|
"sizeX": 7.5,
|
||||||
|
"sizeY": 6.5,
|
||||||
|
"config": {
|
||||||
|
"datasources": [],
|
||||||
|
"timewindow": {
|
||||||
|
"realtime": {
|
||||||
|
"timewindowMs": 60000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"showTitle": false,
|
||||||
|
"backgroundColor": "rgb(255, 255, 255)",
|
||||||
|
"color": "rgba(0, 0, 0, 0.87)",
|
||||||
|
"padding": "16px",
|
||||||
|
"settings": {
|
||||||
|
"columns": 3
|
||||||
|
},
|
||||||
|
"title": "Getting started",
|
||||||
|
"dropShadow": false,
|
||||||
|
"enableFullscreen": false,
|
||||||
|
"widgetStyle": {},
|
||||||
|
"widgetCss": "",
|
||||||
|
"pageSize": 1024,
|
||||||
|
"noDataDisplayMessage": "",
|
||||||
|
"showLegend": false
|
||||||
|
},
|
||||||
|
"row": 0,
|
||||||
|
"col": 0,
|
||||||
|
"id": "a23185ad-dc46-806c-0e50-5b21fb080ace"
|
||||||
|
},
|
||||||
|
"d26e5cd7-75ef-d475-00c7-1a2d1114efe8": {
|
||||||
|
"isSystemType": true,
|
||||||
|
"bundleAlias": "charts",
|
||||||
|
"typeAlias": "basic_timeseries",
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "New widget",
|
||||||
|
"image": null,
|
||||||
|
"description": null,
|
||||||
|
"sizeX": 8,
|
||||||
|
"sizeY": 5,
|
||||||
|
"config": {
|
||||||
|
"datasources": [
|
||||||
|
{
|
||||||
|
"type": "entity",
|
||||||
|
"name": null,
|
||||||
|
"entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079",
|
||||||
|
"filterId": null,
|
||||||
|
"dataKeys": [
|
||||||
|
{
|
||||||
|
"name": "activeDevicesCount",
|
||||||
|
"type": "timeseries",
|
||||||
|
"label": "{i18n:device.devices}",
|
||||||
|
"color": "#305680",
|
||||||
|
"settings": {
|
||||||
|
"hideDataByDefault": false,
|
||||||
|
"disableDataHiding": false,
|
||||||
|
"removeFromLegend": false,
|
||||||
|
"excludeFromStacking": false,
|
||||||
|
"showLines": true,
|
||||||
|
"lineWidth": 3,
|
||||||
|
"fillLines": true,
|
||||||
|
"showPoints": false,
|
||||||
|
"showPointsLineWidth": 5,
|
||||||
|
"showPointsRadius": 3,
|
||||||
|
"showPointShape": "circle",
|
||||||
|
"pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
|
||||||
|
"showSeparateAxis": false,
|
||||||
|
"axisPosition": "left",
|
||||||
|
"comparisonSettings": {
|
||||||
|
"showValuesForComparison": true,
|
||||||
|
"comparisonValuesLabel": "",
|
||||||
|
"color": ""
|
||||||
|
},
|
||||||
|
"thresholds": []
|
||||||
|
},
|
||||||
|
"_hash": 0.9688095820365725,
|
||||||
|
"aggregationType": null,
|
||||||
|
"units": null,
|
||||||
|
"decimals": null,
|
||||||
|
"funcBody": null,
|
||||||
|
"usePostProcessing": null,
|
||||||
|
"postFuncBody": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"latestDataKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timewindow": {
|
||||||
|
"hideInterval": false,
|
||||||
|
"hideLastInterval": false,
|
||||||
|
"hideQuickInterval": false,
|
||||||
|
"hideAggregation": true,
|
||||||
|
"hideAggInterval": true,
|
||||||
|
"hideTimezone": false,
|
||||||
|
"selectedTab": 1,
|
||||||
|
"history": {
|
||||||
|
"historyType": 0,
|
||||||
|
"timewindowMs": 2592000000,
|
||||||
|
"interval": 7200000,
|
||||||
|
"fixedTimewindow": {
|
||||||
|
"startTimeMs": 1681400576338,
|
||||||
|
"endTimeMs": 1681486976338
|
||||||
|
},
|
||||||
|
"quickInterval": "CURRENT_DAY"
|
||||||
|
},
|
||||||
|
"aggregation": {
|
||||||
|
"type": "NONE",
|
||||||
|
"limit": 25000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"showTitle": false,
|
||||||
|
"backgroundColor": "#fff",
|
||||||
|
"color": "rgba(0, 0, 0, 0.87)",
|
||||||
|
"padding": "0px",
|
||||||
|
"settings": {
|
||||||
|
"stack": false,
|
||||||
|
"fontSize": 10,
|
||||||
|
"fontColor": "#545454",
|
||||||
|
"showTooltip": true,
|
||||||
|
"tooltipIndividual": false,
|
||||||
|
"tooltipCumulative": false,
|
||||||
|
"hideZeros": false,
|
||||||
|
"grid": {
|
||||||
|
"verticalLines": false,
|
||||||
|
"horizontalLines": false,
|
||||||
|
"outlineWidth": 0,
|
||||||
|
"color": "#545454",
|
||||||
|
"backgroundColor": null,
|
||||||
|
"tickColor": "#DDDDDD"
|
||||||
|
},
|
||||||
|
"xaxis": {
|
||||||
|
"title": null,
|
||||||
|
"showLabels": true,
|
||||||
|
"color": "#545454"
|
||||||
|
},
|
||||||
|
"yaxis": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"title": null,
|
||||||
|
"showLabels": true,
|
||||||
|
"color": "#545454",
|
||||||
|
"tickSize": null,
|
||||||
|
"tickDecimals": 0,
|
||||||
|
"ticksFormatter": ""
|
||||||
|
},
|
||||||
|
"shadowSize": 0,
|
||||||
|
"smoothLines": true,
|
||||||
|
"comparisonEnabled": false,
|
||||||
|
"timeForComparison": "previousInterval",
|
||||||
|
"comparisonCustomIntervalValue": 7200000,
|
||||||
|
"xaxisSecond": {
|
||||||
|
"axisPosition": "top",
|
||||||
|
"title": null,
|
||||||
|
"showLabels": true
|
||||||
|
},
|
||||||
|
"customLegendEnabled": false,
|
||||||
|
"dataKeysListForLabels": []
|
||||||
|
},
|
||||||
|
"title": "Devices activity",
|
||||||
|
"dropShadow": false,
|
||||||
|
"enableFullscreen": false,
|
||||||
|
"titleStyle": {
|
||||||
|
"fontSize": "16px",
|
||||||
|
"fontWeight": 400
|
||||||
|
},
|
||||||
|
"useDashboardTimewindow": false,
|
||||||
|
"displayTimewindow": true,
|
||||||
|
"showTitleIcon": false,
|
||||||
|
"titleTooltip": "",
|
||||||
|
"widgetStyle": {
|
||||||
|
"padding": "0"
|
||||||
|
},
|
||||||
|
"widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}",
|
||||||
|
"pageSize": 1024,
|
||||||
|
"noDataDisplayMessage": "",
|
||||||
|
"showLegend": false,
|
||||||
|
"legendConfig": {
|
||||||
|
"direction": "column",
|
||||||
|
"position": "bottom",
|
||||||
|
"sortDataKeys": false,
|
||||||
|
"showMin": false,
|
||||||
|
"showMax": false,
|
||||||
|
"showAvg": true,
|
||||||
|
"showTotal": false,
|
||||||
|
"showLatest": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"row": 0,
|
||||||
|
"col": 0,
|
||||||
|
"id": "d26e5cd7-75ef-d475-00c7-1a2d1114efe8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"states": {
|
||||||
|
"default": {
|
||||||
|
"name": "Tenant Administrator Home Page",
|
||||||
|
"root": true,
|
||||||
|
"layouts": {
|
||||||
|
"main": {
|
||||||
|
"widgets": {
|
||||||
|
"d70cc256-4c7b-ee06-9905-b8c5e546605f": {
|
||||||
|
"sizeX": 41,
|
||||||
|
"sizeY": 16,
|
||||||
|
"row": 26,
|
||||||
|
"col": 44,
|
||||||
|
"mobileOrder": 7,
|
||||||
|
"mobileHeight": 8
|
||||||
|
},
|
||||||
|
"867f82cf-ecf2-2d5c-35cb-08c6f2edc3a4": {
|
||||||
|
"sizeX": 31,
|
||||||
|
"sizeY": 16,
|
||||||
|
"row": 42,
|
||||||
|
"col": 26,
|
||||||
|
"mobileHide": true
|
||||||
|
},
|
||||||
|
"a23185ad-dc46-806c-0e50-5b21fb080ace": {
|
||||||
|
"sizeX": 35,
|
||||||
|
"sizeY": 58,
|
||||||
|
"row": 0,
|
||||||
|
"col": 85,
|
||||||
|
"mobileHide": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridSettings": {
|
||||||
|
"backgroundColor": "#eeeeee",
|
||||||
|
"columns": 120,
|
||||||
|
"margin": 12,
|
||||||
|
"backgroundSizeMode": "100%",
|
||||||
|
"autoFillHeight": true,
|
||||||
|
"backgroundImageUrl": null,
|
||||||
|
"mobileAutoFillHeight": false,
|
||||||
|
"mobileRowHeight": 20,
|
||||||
|
"outerMargin": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transport_messages": {
|
||||||
|
"name": "Transport messages",
|
||||||
|
"root": false,
|
||||||
|
"layouts": {
|
||||||
|
"main": {
|
||||||
|
"widgets": {
|
||||||
|
"8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e": {
|
||||||
|
"sizeX": 24,
|
||||||
|
"sizeY": 11,
|
||||||
|
"row": 0,
|
||||||
|
"col": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridSettings": {
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
"columns": 24,
|
||||||
|
"margin": 0,
|
||||||
|
"backgroundSizeMode": "100%",
|
||||||
|
"autoFillHeight": true,
|
||||||
|
"backgroundImageUrl": null,
|
||||||
|
"mobileAutoFillHeight": true,
|
||||||
|
"mobileRowHeight": 70,
|
||||||
|
"outerMargin": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devices_activity": {
|
||||||
|
"name": "Devices activity",
|
||||||
|
"root": false,
|
||||||
|
"layouts": {
|
||||||
|
"main": {
|
||||||
|
"widgets": {
|
||||||
|
"d26e5cd7-75ef-d475-00c7-1a2d1114efe8": {
|
||||||
|
"sizeX": 24,
|
||||||
|
"sizeY": 11,
|
||||||
|
"row": 0,
|
||||||
|
"col": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridSettings": {
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
"columns": 24,
|
||||||
|
"margin": 0,
|
||||||
|
"outerMargin": true,
|
||||||
|
"backgroundSizeMode": "100%",
|
||||||
|
"autoFillHeight": true,
|
||||||
|
"backgroundImageUrl": null,
|
||||||
|
"mobileAutoFillHeight": true,
|
||||||
|
"mobileRowHeight": 70
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entityAliases": {
|
||||||
|
"ae870700-071f-b3bc-406c-16ba554c5a55": {
|
||||||
|
"id": "ae870700-071f-b3bc-406c-16ba554c5a55",
|
||||||
|
"alias": "Tenants",
|
||||||
|
"filter": {
|
||||||
|
"type": "entityType",
|
||||||
|
"resolveMultiple": true,
|
||||||
|
"entityType": "TENANT"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ca4d90e4-f9ae-6fca-6b09-85815a48d52b": {
|
||||||
|
"id": "ca4d90e4-f9ae-6fca-6b09-85815a48d52b",
|
||||||
|
"alias": "TenantProfiles",
|
||||||
|
"filter": {
|
||||||
|
"type": "entityType",
|
||||||
|
"resolveMultiple": true,
|
||||||
|
"entityType": "TENANT"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"a1ddb8fa-90ff-5598-e7f2-e254194d055d": {
|
||||||
|
"id": "a1ddb8fa-90ff-5598-e7f2-e254194d055d",
|
||||||
|
"alias": "Devices",
|
||||||
|
"filter": {
|
||||||
|
"type": "entityType",
|
||||||
|
"resolveMultiple": true,
|
||||||
|
"entityType": "DEVICE"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"619cdf00-a042-3b55-124e-194c1b28c236": {
|
||||||
|
"id": "619cdf00-a042-3b55-124e-194c1b28c236",
|
||||||
|
"alias": "Assets",
|
||||||
|
"filter": {
|
||||||
|
"type": "entityType",
|
||||||
|
"resolveMultiple": true,
|
||||||
|
"entityType": "ASSET"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1d97ff7f-8b42-5882-f87b-16f3d0dee4f2": {
|
||||||
|
"id": "1d97ff7f-8b42-5882-f87b-16f3d0dee4f2",
|
||||||
|
"alias": "Users",
|
||||||
|
"filter": {
|
||||||
|
"type": "entityType",
|
||||||
|
"resolveMultiple": true,
|
||||||
|
"entityType": "USER"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0dd2b154-59f4-0f97-da1a-d85f5b5cfe31": {
|
||||||
|
"id": "0dd2b154-59f4-0f97-da1a-d85f5b5cfe31",
|
||||||
|
"alias": "Customers",
|
||||||
|
"filter": {
|
||||||
|
"type": "entityType",
|
||||||
|
"resolveMultiple": true,
|
||||||
|
"entityType": "CUSTOMER"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d9229b29-3f46-de8d-7fe8-eb0c43c75079": {
|
||||||
|
"id": "d9229b29-3f46-de8d-7fe8-eb0c43c75079",
|
||||||
|
"alias": "Api Usage State",
|
||||||
|
"filter": {
|
||||||
|
"type": "apiUsageState",
|
||||||
|
"resolveMultiple": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"filters": {},
|
||||||
|
"timewindow": {
|
||||||
|
"displayValue": "",
|
||||||
|
"hideInterval": false,
|
||||||
|
"hideLastInterval": false,
|
||||||
|
"hideQuickInterval": false,
|
||||||
|
"hideAggregation": false,
|
||||||
|
"hideAggInterval": false,
|
||||||
|
"hideTimezone": false,
|
||||||
|
"selectedTab": 0,
|
||||||
|
"realtime": {
|
||||||
|
"realtimeType": 0,
|
||||||
|
"interval": 1000,
|
||||||
|
"timewindowMs": 60000,
|
||||||
|
"quickInterval": "CURRENT_DAY"
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"historyType": 0,
|
||||||
|
"interval": 1000,
|
||||||
|
"timewindowMs": 60000,
|
||||||
|
"fixedTimewindow": {
|
||||||
|
"startTimeMs": 1680168326072,
|
||||||
|
"endTimeMs": 1680254726072
|
||||||
|
},
|
||||||
|
"quickInterval": "CURRENT_DAY"
|
||||||
|
},
|
||||||
|
"aggregation": {
|
||||||
|
"type": "AVG",
|
||||||
|
"limit": 25000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"stateControllerId": "entity",
|
||||||
|
"showTitle": false,
|
||||||
|
"showDashboardsSelect": true,
|
||||||
|
"showEntitiesSelect": true,
|
||||||
|
"showDashboardTimewindow": true,
|
||||||
|
"showDashboardExport": true,
|
||||||
|
"toolbarAlwaysOpen": true,
|
||||||
|
"titleColor": "rgba(0,0,0,0.870588)",
|
||||||
|
"showDashboardLogo": false,
|
||||||
|
"dashboardLogoUrl": null,
|
||||||
|
"hideToolbar": true,
|
||||||
|
"showFilters": true,
|
||||||
|
"showUpdateDashboardImage": true,
|
||||||
|
"dashboardCss": ".tb-widget-container > .tb-widget {\n border: 1px solid rgba(0, 0, 0, 0.05);\n box-shadow: 0px 5px 16px rgba(0, 0, 0, 0.04);\n border-radius: 12px;\n}\n\n.tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 16px !important;\n}\n\n.tb-card-title {\n display: grid;\n}\n\n.tb-home-widget-title {\n font-style: normal;\n font-weight: 500;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.25px;\n color: rgba(0, 0, 0, 0.54);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tb-home-widget-link {\n position: relative;\n border-bottom: none;\n}\n\n.tb-home-widget-link:hover {\n border-bottom: none;\n}\n\n.tb-home-widget-link:focus {\n border-bottom: none;\n}\n\n.tb-home-widget-link::after {\n content: 'arrow_forward';\n display: inline-block;\n transform: rotate(315deg);\n font-family: 'Material Icons';\n font-weight: normal;\n font-style: normal;\n font-size: 18px;\n color: rgba(0, 0, 0, 0.12);\n vertical-align: bottom;\n margin-left: 6px; \n}\n\n.tb-home-widget-link:hover::after {\n color: inherit;\n}\n\n.tb-home-widget-info-icon {\n color: rgba(0, 0, 0, 0.12);\n font-size: 16px;\n width: 16px;\n height: 16px;\n line-height: 15px;\n vertical-align: middle;\n}\n\n.tb-widget-container > .tb-widget .tb-timewindow {\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.25px;\n color: rgba(0, 0, 0, 0.54);\n padding: 0;\n}\n\n.tb-widget-container > .tb-widget .tb-legend-keys .tb-legend-label {\n cursor: pointer;\n user-select: none;\n font-weight: 400;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.2px;\n color: rgba(0, 0, 0, 0.54);\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .tb-widget-container > .tb-widget {\n border-radius: 4px;\n }\n .tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 2px !important;\n }\n .tb-hide-md {\n display: none;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 8px !important;\n }\n .tb-hide-lg {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-hide-md-lg {\n display: none;\n }\n\n .tb-home-widget-title {\n font-size: 12px;\n line-height: 16px;\n }\n \n .tb-widget-container > .tb-widget .tb-widget-title {\n padding: 0;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow {\n font-size: 12px;\n line-height: 16px;\n min-height: 24px;\n padding: 0;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow .mat-mdc-icon-button.tb-mat-32 {\n width: 24px;\n height: 24px;\n line-height: 24px;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow .mat-mdc-icon-button.tb-mat-32 .mat-icon {\n width: 18px;\n height: 18px;\n font-size: 18px;\n }\n \n .tb-widget-container > .tb-widget tb-legend {\n padding-bottom: 0 !important;\n }\n \n .tb-widget-container > .tb-widget .tb-legend-keys .tb-legend-label {\n font-size: 11px;\n line-height: 16px;\n letter-spacing: 0.25px;\n }\n}\n\n@media screen and (max-width: 959px), screen and (min-width: 1820px) {\n .tb-hide-not-md-lg {\n display: none;\n }\n}\n"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"externalId": null,
|
||||||
|
"name": "Tenant Administrator Home Page"
|
||||||
|
}
|
||||||
@ -22,5 +22,5 @@
|
|||||||
background: #efefef;">
|
background: #efefef;">
|
||||||
{{error}}
|
{{error}}
|
||||||
</div>
|
</div>
|
||||||
<div #fallbackElement [fxShow]="error && fallbackToPlainMarkdown" class="tb-markdown-view" [ngClass]="markdownClass" [ngStyle]="style">
|
<div #fallbackElement [fxShow]="usePlainMarkdown || (error && fallbackToPlainMarkdown)" class="tb-markdown-view" [ngClass]="markdownClass" [ngStyle]="style">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|||||||
import { SHARED_MODULE_TOKEN } from '@shared/components/tokens';
|
import { SHARED_MODULE_TOKEN } from '@shared/components/tokens';
|
||||||
import { deepClone, guid, isDefinedAndNotNull } from '@core/utils';
|
import { deepClone, guid, isDefinedAndNotNull } from '@core/utils';
|
||||||
import { Observable, of, ReplaySubject } from 'rxjs';
|
import { Observable, of, ReplaySubject } from 'rxjs';
|
||||||
|
import { coerceBoolean } from '@shared/decorators/coerce-boolean';
|
||||||
|
|
||||||
let defaultMarkdownStyle;
|
let defaultMarkdownStyle;
|
||||||
|
|
||||||
@ -76,6 +77,10 @@ export class TbMarkdownComponent implements OnChanges {
|
|||||||
get fallbackToPlainMarkdown(): boolean { return this.fallbackToPlainMarkdownValue; }
|
get fallbackToPlainMarkdown(): boolean { return this.fallbackToPlainMarkdownValue; }
|
||||||
set fallbackToPlainMarkdown(value: boolean) { this.fallbackToPlainMarkdownValue = coerceBooleanProperty(value); }
|
set fallbackToPlainMarkdown(value: boolean) { this.fallbackToPlainMarkdownValue = coerceBooleanProperty(value); }
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
@coerceBoolean()
|
||||||
|
usePlainMarkdown = false;
|
||||||
|
|
||||||
@Output() ready = new EventEmitter<void>();
|
@Output() ready = new EventEmitter<void>();
|
||||||
|
|
||||||
private lineNumbersValue = false;
|
private lineNumbersValue = false;
|
||||||
@ -124,13 +129,8 @@ export class TbMarkdownComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
template = this.sanitizeCurlyBraces(template);
|
template = this.sanitizeCurlyBraces(template);
|
||||||
this.markdownContainer.clear();
|
this.markdownContainer.clear();
|
||||||
const parent = this;
|
|
||||||
let readyObservable: Observable<void>;
|
|
||||||
let compileModules = [this.sharedModule];
|
|
||||||
if (this.additionalCompileModules) {
|
|
||||||
compileModules = compileModules.concat(this.additionalCompileModules);
|
|
||||||
}
|
|
||||||
let styles: string[] = [];
|
let styles: string[] = [];
|
||||||
|
let readyObservable: Observable<void>;
|
||||||
if (this.applyDefaultMarkdownStyle) {
|
if (this.applyDefaultMarkdownStyle) {
|
||||||
if (!defaultMarkdownStyle) {
|
if (!defaultMarkdownStyle) {
|
||||||
defaultMarkdownStyle = deepClone(TbMarkdownComponent['ɵcmp'].styles)[0].replace(/\[_nghost\-%COMP%\]/g, '')
|
defaultMarkdownStyle = deepClone(TbMarkdownComponent['ɵcmp'].styles)[0].replace(/\[_nghost\-%COMP%\]/g, '')
|
||||||
@ -141,70 +141,87 @@ export class TbMarkdownComponent implements OnChanges {
|
|||||||
if (this.additionalStyles) {
|
if (this.additionalStyles) {
|
||||||
styles = styles.concat(this.additionalStyles);
|
styles = styles.concat(this.additionalStyles);
|
||||||
}
|
}
|
||||||
this.dynamicComponentFactoryService.createDynamicComponentFactory(
|
if (this.usePlainMarkdown) {
|
||||||
class TbMarkdownInstance {
|
readyObservable = this.plainMarkdown(template, styles);
|
||||||
ngOnDestroy(): void {
|
|
||||||
parent.destroyMarkdownInstanceResources();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
template,
|
|
||||||
compileModules,
|
|
||||||
true, 1, styles
|
|
||||||
).subscribe((factory) => {
|
|
||||||
this.tbMarkdownInstanceComponentFactory = factory;
|
|
||||||
const injector: Injector = Injector.create({providers: [], parent: this.markdownContainer.injector});
|
|
||||||
try {
|
|
||||||
this.tbMarkdownInstanceComponentRef =
|
|
||||||
this.markdownContainer.createComponent(this.tbMarkdownInstanceComponentFactory, 0, injector);
|
|
||||||
if (this.context) {
|
|
||||||
for (const propName of Object.keys(this.context)) {
|
|
||||||
this.tbMarkdownInstanceComponentRef.instance[propName] = this.context[propName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.tbMarkdownInstanceComponentRef.instance.style = this.style;
|
|
||||||
readyObservable = this.handleImages(this.tbMarkdownInstanceComponentRef.location.nativeElement);
|
|
||||||
this.cd.detectChanges();
|
|
||||||
this.error = null;
|
|
||||||
} catch (error) {
|
|
||||||
readyObservable = this.handleError(template, error, styles);
|
|
||||||
}
|
|
||||||
readyObservable.subscribe(() => {
|
|
||||||
this.ready.emit();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
readyObservable = this.handleError(template, error, styles);
|
|
||||||
this.cd.detectChanges();
|
this.cd.detectChanges();
|
||||||
readyObservable.subscribe(() => {
|
readyObservable.subscribe(() => {
|
||||||
this.ready.emit();
|
this.ready.emit();
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
const parent = this;
|
||||||
|
let compileModules = [this.sharedModule];
|
||||||
|
if (this.additionalCompileModules) {
|
||||||
|
compileModules = compileModules.concat(this.additionalCompileModules);
|
||||||
|
}
|
||||||
|
this.dynamicComponentFactoryService.createDynamicComponentFactory(
|
||||||
|
class TbMarkdownInstance {
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
parent.destroyMarkdownInstanceResources();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template,
|
||||||
|
compileModules,
|
||||||
|
true, 1, styles
|
||||||
|
).subscribe((factory) => {
|
||||||
|
this.tbMarkdownInstanceComponentFactory = factory;
|
||||||
|
const injector: Injector = Injector.create({providers: [], parent: this.markdownContainer.injector});
|
||||||
|
try {
|
||||||
|
this.tbMarkdownInstanceComponentRef =
|
||||||
|
this.markdownContainer.createComponent(this.tbMarkdownInstanceComponentFactory, 0, injector);
|
||||||
|
if (this.context) {
|
||||||
|
for (const propName of Object.keys(this.context)) {
|
||||||
|
this.tbMarkdownInstanceComponentRef.instance[propName] = this.context[propName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tbMarkdownInstanceComponentRef.instance.style = this.style;
|
||||||
|
readyObservable = this.handleImages(this.tbMarkdownInstanceComponentRef.location.nativeElement);
|
||||||
|
this.cd.detectChanges();
|
||||||
|
this.error = null;
|
||||||
|
} catch (error) {
|
||||||
|
readyObservable = this.handleError(template, error, styles);
|
||||||
|
}
|
||||||
|
readyObservable.subscribe(() => {
|
||||||
|
this.ready.emit();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
readyObservable = this.handleError(template, error, styles);
|
||||||
|
this.cd.detectChanges();
|
||||||
|
readyObservable.subscribe(() => {
|
||||||
|
this.ready.emit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleError(template: string, error, styles?: string[]): Observable<void> {
|
private handleError(template: string, error, styles?: string[]): Observable<void> {
|
||||||
this.error = (error ? error + '' : 'Failed to render markdown!').replace(/\n/g, '<br>');
|
this.error = (error ? error + '' : 'Failed to render markdown!').replace(/\n/g, '<br>');
|
||||||
this.markdownContainer.clear();
|
this.markdownContainer.clear();
|
||||||
if (this.fallbackToPlainMarkdownValue) {
|
if (this.fallbackToPlainMarkdownValue) {
|
||||||
const element = this.fallbackElement.nativeElement;
|
return this.plainMarkdown(template, styles);
|
||||||
let styleElement;
|
|
||||||
if (styles?.length) {
|
|
||||||
const markdownClass = 'tb-markdown-view-' + guid();
|
|
||||||
let innerStyle = styles.join('\n');
|
|
||||||
innerStyle = innerStyle.replace(/\.tb-markdown-view/g, '.' + markdownClass);
|
|
||||||
template = template.replace(/tb-markdown-view/g, markdownClass);
|
|
||||||
styleElement = this.renderer.createElement('style');
|
|
||||||
styleElement.innerHTML = innerStyle;
|
|
||||||
}
|
|
||||||
element.innerHTML = template;
|
|
||||||
if (styleElement) {
|
|
||||||
this.renderer.appendChild(element, styleElement);
|
|
||||||
}
|
|
||||||
return this.handleImages(element);
|
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private plainMarkdown(template: string, styles?: string[]): Observable<void> {
|
||||||
|
const element = this.fallbackElement.nativeElement;
|
||||||
|
let styleElement;
|
||||||
|
if (styles?.length) {
|
||||||
|
const markdownClass = 'tb-markdown-view-' + guid();
|
||||||
|
let innerStyle = styles.join('\n');
|
||||||
|
innerStyle = innerStyle.replace(/\.tb-markdown-view/g, '.' + markdownClass);
|
||||||
|
template = template.replace(/tb-markdown-view/g, markdownClass);
|
||||||
|
styleElement = this.renderer.createElement('style');
|
||||||
|
styleElement.innerHTML = innerStyle;
|
||||||
|
}
|
||||||
|
element.innerHTML = template;
|
||||||
|
if (styleElement) {
|
||||||
|
this.renderer.appendChild(element, styleElement);
|
||||||
|
}
|
||||||
|
return this.handleImages(element);
|
||||||
|
}
|
||||||
|
|
||||||
private handlePlugins(element: HTMLElement): void {
|
private handlePlugins(element: HTMLElement): void {
|
||||||
if (this.lineNumbers) {
|
if (this.lineNumbers) {
|
||||||
this.setPluginClass(element, PrismPlugin.LineNumbers);
|
this.setPluginClass(element, PrismPlugin.LineNumbers);
|
||||||
|
|||||||
@ -5114,6 +5114,9 @@
|
|||||||
"title": "Transport messages",
|
"title": "Transport messages",
|
||||||
"info": "All the messages that came from devices"
|
"info": "All the messages that came from devices"
|
||||||
},
|
},
|
||||||
|
"activity": {
|
||||||
|
"title": "Activity"
|
||||||
|
},
|
||||||
"documentation": {
|
"documentation": {
|
||||||
"title": "Documentation",
|
"title": "Documentation",
|
||||||
"add-link": "Add link",
|
"add-link": "Add link",
|
||||||
@ -5201,6 +5204,52 @@
|
|||||||
"content": "<p>Some text</p><p>Follow the documentation on how to do it:</p>",
|
"content": "<p>Some text</p><p>Follow the documentation on how to do it:</p>",
|
||||||
"how-to-configure-notifications": "How to configure Notifications"
|
"how-to-configure-notifications": "How to configure Notifications"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tenant-admin": {
|
||||||
|
"step1": {
|
||||||
|
"title": "Create device",
|
||||||
|
"content": "<p>We will manually provision the device using the UI. Follow the documentation on how to do it:</p>",
|
||||||
|
"how-to-create-device": "How to create Device"
|
||||||
|
},
|
||||||
|
"step2": {
|
||||||
|
"title": "Connect device",
|
||||||
|
"content-before": "<p>To connect the device you need to get the device credentials. But we recommend using the default auto-generated one.</p><ul><li>Go to device table</li><li>Click on the device row to open device details</li><li>Press the button \"Copy access token\"</li></ul><p>Use simple commands to publish data over HTTP:</p>",
|
||||||
|
"ubuntu": {
|
||||||
|
"install-curl": "Install cURL for Ubuntu:"
|
||||||
|
},
|
||||||
|
"macos": {
|
||||||
|
"install-curl": "Install cURL for MacOS:"
|
||||||
|
},
|
||||||
|
"windows": {
|
||||||
|
"install-curl": "Starting Windows 10 b17063, cURL is available by default."
|
||||||
|
},
|
||||||
|
"replace-access-token": "Replace <em>$ACCESS_TOKEN</em> with your device's token:",
|
||||||
|
"content-after": "<p>You can also use other protocols such as MQTT, CoAP, etc.</p><p>Follow the documentation on how to do it:</p>",
|
||||||
|
"how-to-connect-device": "How to connect Device"
|
||||||
|
},
|
||||||
|
"step3": {
|
||||||
|
"title": "Create dashboard",
|
||||||
|
"content": "<p>Create a dashboard to visualize data from entities such as assets, devices, etc.</p><p>Follow the documentation on how to do it:</p>",
|
||||||
|
"how-to-create-dashboard": "How to create Dashboard"
|
||||||
|
},
|
||||||
|
"step4": {
|
||||||
|
"title": "Configure alarm rules",
|
||||||
|
"alarm-rules": "Alarm rules",
|
||||||
|
"content": "<p>When the temperature reaches 25°C, we will raise an alarm. Follow the documentation on how to do it:</p>",
|
||||||
|
"how-to-configure-alarm-rules": "How to configure Alarm rules"
|
||||||
|
},
|
||||||
|
"step5": {
|
||||||
|
"title": "Create alarm",
|
||||||
|
"content-before": "<p>To trigger the alarm, send a new telemetry value of 26°C or higher.</p>",
|
||||||
|
"replace-access-token": "Replace <em>$ACCESS_TOKEN</em> with your device's token:",
|
||||||
|
"content-after": "<p>Follow the documentation on how to do it:</p>",
|
||||||
|
"how-to-create-alarm": "How to create Alarm"
|
||||||
|
},
|
||||||
|
"step6": {
|
||||||
|
"title": "Create customer and assign dashboard",
|
||||||
|
"content": "<p>By creating end-user dashboards, a customer user can only see his own devices, and data from another customer will be hidden.</p><p>Follow the documentation on how to do it:</p>",
|
||||||
|
"how-to-create-customer-and-assign-dashboard": "How to create Customer and assign Dashboard"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user