18 changed files with 536 additions and 41 deletions
@ -0,0 +1,31 @@ |
|||
{ |
|||
"widgetsBundle": { |
|||
"alias": "home_page_widgets", |
|||
"title": "Home page widgets", |
|||
"image": null, |
|||
"description": null, |
|||
"externalId": null, |
|||
"name": "Home page widgets" |
|||
}, |
|||
"widgetTypes": [ |
|||
{ |
|||
"alias": "documentation_links", |
|||
"name": "Documentation links", |
|||
"image": null, |
|||
"description": null, |
|||
"descriptor": { |
|||
"type": "static", |
|||
"sizeX": 7.5, |
|||
"sizeY": 3, |
|||
"resources": [], |
|||
"templateHtml": "<tb-doc-links-widget\n [ctx]=\"ctx\">\n</tb-doc-links-widget>\n", |
|||
"templateCss": "", |
|||
"controllerScript": "self.onInit = function() {\n}", |
|||
"settingsSchema": "", |
|||
"dataKeySettingsSchema": "", |
|||
"settingsDirective": "tb-doc-links-widget-settings", |
|||
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"columns\":3},\"title\":\"Documentation links\",\"dropShadow\":true}" |
|||
} |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
<!-- |
|||
|
|||
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. |
|||
|
|||
--> |
|||
<div class="tb-card-content" fxLayout="column" fxLayoutGap="8px"> |
|||
<div class="tb-card-header"> |
|||
<a class="tb-title-link" href="https://thingsboard.io/docs/" target="_blank">Documentation</a> |
|||
<button class="tb-title-icon" |
|||
matTooltip="Edit" |
|||
matTooltipPosition="above" |
|||
mat-icon-button |
|||
(click)="edit()"> |
|||
<mat-icon>edit</mat-icon> |
|||
</button> |
|||
</div> |
|||
<mat-grid-list fxFlex [cols]="columns" rowHeight="fit" gutterSize="12px"> |
|||
<mat-grid-tile class="tb-docs-tile" *ngFor="let docLink of documentationLinks?.links"> |
|||
<a fxFlex class="tb-doc-button" |
|||
[href]="docLink.link" target="_blank"> |
|||
<div class="tb-doc-container"> |
|||
<div class="tb-doc-icon-container"> |
|||
<mat-icon color="primary">{{ docLink.icon }}</mat-icon> |
|||
</div> |
|||
<div class="tb-doc-text">{{ docLink.name }}</div> |
|||
</div> |
|||
</a> |
|||
</mat-grid-tile> |
|||
<mat-grid-tile class="tb-docs-tile"> |
|||
<div fxFlex class="tb-add-doc-button" |
|||
matTooltip="Add link" |
|||
matTooltipPosition="above" |
|||
(click)="addLink()"> |
|||
<mat-icon class="tb-add-icon">add</mat-icon> |
|||
</div> |
|||
</mat-grid-tile> |
|||
</mat-grid-list> |
|||
</div> |
|||
@ -0,0 +1,124 @@ |
|||
/** |
|||
* 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. |
|||
*/ |
|||
:host { |
|||
.tb-card-content { |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
.tb-card-header { |
|||
display: flex; |
|||
flex-direction: row; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.tb-title-link { |
|||
font-style: normal; |
|||
font-weight: 500; |
|||
font-size: 14px; |
|||
line-height: 20px; |
|||
letter-spacing: 0.25px; |
|||
color: rgba(0, 0, 0, 0.54); |
|||
position: relative; |
|||
border-bottom: none; |
|||
&:hover, &:focus { |
|||
border-bottom: none; |
|||
} |
|||
&::after { |
|||
content: 'arrow_forward'; |
|||
display: inline-block; |
|||
position: absolute; |
|||
top: -2px; |
|||
right: -28px; |
|||
transform: rotate(315deg); |
|||
font-family: 'Material Icons'; |
|||
font-weight: normal; |
|||
font-style: normal; |
|||
font-size: 18px; |
|||
color: rgba(0, 0, 0, 0.12); |
|||
} |
|||
&:hover::after { |
|||
color: inherit; |
|||
} |
|||
} |
|||
|
|||
.tb-title-icon { |
|||
color: rgba(0, 0, 0, 0.38); |
|||
width: 32px; |
|||
height: 32px; |
|||
padding: 4px; |
|||
} |
|||
|
|||
.mat-grid-tile.tb-docs-tile { |
|||
overflow: visible; |
|||
} |
|||
|
|||
.tb-doc-button { |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
padding: 12px; |
|||
background: #FFFFFF; |
|||
border: 1px solid rgba(0, 0, 0, 0.05); |
|||
box-shadow: 0 5px 16px rgba(0, 0, 0, 0.04); |
|||
border-radius: 10px; |
|||
&:hover { |
|||
border: 1px solid rgba(0, 0, 0, 0.12); |
|||
box-shadow: 0 4px 10px rgba(23, 33, 90, 0.08); |
|||
} |
|||
.tb-doc-container { |
|||
display: flex; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
.tb-doc-icon-container { |
|||
height: 40px; |
|||
padding: 8px; |
|||
background: #F3F6FA; |
|||
border-radius: 6px; |
|||
margin-right: 8px; |
|||
} |
|||
.tb-doc-text { |
|||
font-weight: 400; |
|||
font-size: 14px; |
|||
line-height: 20px; |
|||
letter-spacing: 0.2px; |
|||
color: rgba(0, 0, 0, 0.87); |
|||
} |
|||
} |
|||
} |
|||
|
|||
.tb-add-doc-button { |
|||
height: 100%; |
|||
cursor: pointer; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
background: #FFFFFF; |
|||
padding: 12px; |
|||
border: 2px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 10px; |
|||
.tb-add-icon { |
|||
color: rgba(0, 0, 0, 0.12); |
|||
} |
|||
&:hover { |
|||
.tb-add-icon { |
|||
color: rgba(0, 0, 0, 0.38); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,136 @@ |
|||
///
|
|||
/// 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 { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; |
|||
import { PageComponent } from '@shared/components/page.component'; |
|||
import { Store } from '@ngrx/store'; |
|||
import { AppState } from '@core/core.state'; |
|||
import { Authority } from '@shared/models/authority.enum'; |
|||
import { map } from 'rxjs'; |
|||
import { DocumentationLinks } from '@shared/models/user-settings.models'; |
|||
import { UserSettingsService } from '@core/http/user-settings.service'; |
|||
import { getCurrentAuthUser } from '@core/auth/auth.selectors'; |
|||
import { WidgetContext } from '@home/models/widget-component.models'; |
|||
|
|||
const defaultDocLinksMap = new Map<Authority, DocumentationLinks>( |
|||
[ |
|||
[Authority.SYS_ADMIN, { |
|||
links: [ |
|||
{ |
|||
icon: 'rocket', |
|||
name: 'Getting started', |
|||
link: 'https://thingsboard.io/docs/getting-started-guides/helloworld/' |
|||
}, |
|||
{ |
|||
icon: 'title', |
|||
name: 'Tenant profiles', |
|||
link: 'https://thingsboard.io/docs/user-guide/tenant-profiles/' |
|||
}, |
|||
{ |
|||
icon: 'insert_chart', |
|||
name: 'API', |
|||
link: 'https://thingsboard.io/docs/api/' |
|||
}, |
|||
{ |
|||
icon: 'now_widgets', |
|||
name: 'Widgets Library', |
|||
link: 'https://thingsboard.io/docs/user-guide/ui/widget-library/' |
|||
} |
|||
] |
|||
}], |
|||
[Authority.TENANT_ADMIN, { |
|||
links: [ |
|||
{ |
|||
icon: 'rocket', |
|||
name: 'Getting started', |
|||
link: 'https://thingsboard.io/docs/getting-started-guides/helloworld/' |
|||
}, |
|||
{ |
|||
icon: 'settings_ethernet', |
|||
name: 'Rule engine', |
|||
link: 'https://thingsboard.io/docs/user-guide/rule-engine-2-0/re-getting-started/' |
|||
}, |
|||
{ |
|||
icon: 'insert_chart', |
|||
name: 'API', |
|||
link: 'https://thingsboard.io/docs/api/' |
|||
}, |
|||
{ |
|||
icon: 'devices', |
|||
name: 'Device profiles', |
|||
link: 'https://thingsboard.io/docs/user-guide/device-profiles/' |
|||
} |
|||
] |
|||
}], |
|||
[Authority.CUSTOMER_USER, { |
|||
links: [] |
|||
}] |
|||
] |
|||
); |
|||
|
|||
interface DocLinksWidgetSettings { |
|||
columns: number; |
|||
} |
|||
|
|||
@Component({ |
|||
selector: 'tb-doc-links-widget', |
|||
templateUrl: './doc-links-widget.component.html', |
|||
styleUrls: ['./doc-links-widget.component.scss'] |
|||
}) |
|||
export class DocLinksWidgetComponent extends PageComponent implements OnInit { |
|||
|
|||
@Input() |
|||
ctx: WidgetContext; |
|||
|
|||
settings: DocLinksWidgetSettings; |
|||
columns: number; |
|||
|
|||
documentationLinks: DocumentationLinks; |
|||
authUser = getCurrentAuthUser(this.store); |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
private cd: ChangeDetectorRef, |
|||
private userSettingsService: UserSettingsService) { |
|||
super(store); |
|||
} |
|||
|
|||
ngOnInit() { |
|||
this.settings = this.ctx.settings; |
|||
this.columns = this.settings.columns || 3; |
|||
this.userSettingsService.getDocumentationLinks().pipe( |
|||
map((documentationLinks) => { |
|||
if (!documentationLinks || !documentationLinks.links) { |
|||
return defaultDocLinksMap.get(this.authUser.authority); |
|||
} else { |
|||
return documentationLinks; |
|||
} |
|||
}) |
|||
).subscribe( |
|||
(documentationLinks) => { |
|||
this.documentationLinks = documentationLinks; |
|||
this.cd.markForCheck(); |
|||
} |
|||
); |
|||
} |
|||
|
|||
edit() { |
|||
|
|||
} |
|||
|
|||
addLink() { |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
<!-- |
|||
|
|||
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. |
|||
|
|||
--> |
|||
<section class="tb-widget-settings" [formGroup]="docLinksWidgetSettingsForm" fxLayout="column"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label>Columns</mat-label> |
|||
<input required matInput type="number" step="1" min="1" max="20" formControlName="columns"> |
|||
</mat-form-field> |
|||
</section> |
|||
@ -0,0 +1,52 @@ |
|||
///
|
|||
/// 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 { Component } from '@angular/core'; |
|||
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; |
|||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; |
|||
import { Store } from '@ngrx/store'; |
|||
import { AppState } from '@core/core.state'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-doc-links-widget-settings', |
|||
templateUrl: './doc-links-widget-settings.component.html', |
|||
styleUrls: ['./../widget-settings.scss'] |
|||
}) |
|||
export class DocLinksWidgetSettingsComponent extends WidgetSettingsComponent { |
|||
|
|||
docLinksWidgetSettingsForm: UntypedFormGroup; |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
private fb: UntypedFormBuilder) { |
|||
super(store); |
|||
} |
|||
|
|||
protected settingsForm(): UntypedFormGroup { |
|||
return this.docLinksWidgetSettingsForm; |
|||
} |
|||
|
|||
protected defaultSettings(): WidgetSettings { |
|||
return { |
|||
columns: 3 |
|||
}; |
|||
} |
|||
|
|||
protected onSettingsSet(settings: WidgetSettings) { |
|||
this.docLinksWidgetSettingsForm = this.fb.group({ |
|||
columns: [settings.columns, [Validators.required, Validators.min(1), Validators.max(20)]] |
|||
}); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue