UI: Implement navigation widget settings form
This commit is contained in:
parent
aebe4c5b20
commit
03ddc2c378
@ -19,8 +19,9 @@
|
|||||||
"templateHtml": "<tb-navigation-cards-widget [ctx]=\"ctx\"></tb-navigation-cards-widget>",
|
"templateHtml": "<tb-navigation-cards-widget [ctx]=\"ctx\"></tb-navigation-cards-widget>",
|
||||||
"templateCss": "/*#widget-container {\n overflow-y: auto;\n box-sizing: content-box !important;\n cursor: auto;\n}*/\n\n#widget-container #container {\n overflow-y: auto;\n box-sizing: content-box;\n cursor: auto;\n}",
|
"templateCss": "/*#widget-container {\n overflow-y: auto;\n box-sizing: content-box !important;\n cursor: auto;\n}*/\n\n#widget-container #container {\n overflow-y: auto;\n box-sizing: content-box;\n cursor: auto;\n}",
|
||||||
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onResize = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onDestroy = function() {\n}\n",
|
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onResize = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onDestroy = function() {\n}\n",
|
||||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"filterType\": {\n \"title\": \"Filter type\",\n \"type\": \"string\",\n \"default\": \"all\"\n },\n \"filter\": {\n \"title\": \"Items\",\n \"type\": \"array\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"filterType\",\n \"type\": \"radios\",\n \"direction\": \"row\",\n \"titleMap\": [\n {\n \"value\": \"all\",\n \"name\": \"All items\"\n },\n {\n \"value\": \"include\",\n \"name\": \"Include items\"\n },\n {\n \"value\": \"exclude\",\n \"name\": \"Exclude items\"\n }\n ]\n },\n {\n \"key\": \"filter\",\n \"type\": \"rc-select\",\n \"condition\": \"model.filterType !== 'all'\",\n \"tags\": true,\n \"placeholder\": \"Enter urls to filter\",\n \"items\": [{\"value\": \"/devices\", \"label\": \"/devices\"}, {\"value\": \"/assets\", \"label\": \"/assets\"}, {\"value\": \"/deviceProfiles\", \"label\": \"/deviceProfiles\"}]\n }\n ]\n}\n",
|
"settingsSchema": "",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
|
"settingsDirective": "tb-navigation-cards-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\":\"rgba(255,255,255,0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"filterType\":\"all\"},\"title\":\"Navigation cards\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
|
"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\":\"rgba(255,255,255,0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"filterType\":\"all\"},\"title\":\"Navigation cards\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -37,8 +38,9 @@
|
|||||||
"templateHtml": "<tb-navigation-card-widget [ctx]=\"ctx\"></tb-navigation-card-widget>",
|
"templateHtml": "<tb-navigation-card-widget [ctx]=\"ctx\"></tb-navigation-card-widget>",
|
||||||
"templateCss": "",
|
"templateCss": "",
|
||||||
"controllerScript": "self.onInit = function() {\n\n}\n\n\nself.onDestroy = function() {\n}\n",
|
"controllerScript": "self.onInit = function() {\n\n}\n\n\nself.onDestroy = function() {\n}\n",
|
||||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"name\": {\n \"title\": \"Title\",\n \"type\": \"string\",\n \"default\": \"{i18n:device.devices}\"\n },\n \"icon\": {\n \"title\": \"icon\",\n \"type\": \"string\",\n \"default\": \"devices_other\"\n },\n \"path\": {\n \"title\": \"Navigation path\",\n \"type\": \"string\",\n \"default\": \"/devices\"\n }\n },\n \"required\": [\"name\", \"icon\", \"path\"]\n },\n \"form\": [\n \"name\",\n {\n \"key\": \"icon\",\n \"type\": \"icon\"\n },\n \"path\"\n ]\n}\n",
|
"settingsSchema": "",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
|
"settingsDirective": "tb-navigation-card-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\":\"rgba(255,255,255,0)\",\"color\":\"rgba(255,255,255,0.87)\",\"padding\":\"8px\",\"settings\":{\"name\":\"{i18n:device.devices}\",\"icon\":\"devices_other\",\"path\":\"/devices\"},\"title\":\"Navigation card\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
|
"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\":\"rgba(255,255,255,0)\",\"color\":\"rgba(255,255,255,0.87)\",\"padding\":\"8px\",\"settings\":{\"name\":\"{i18n:device.devices}\",\"icon\":\"devices_other\",\"path\":\"/devices\"},\"title\":\"Navigation card\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2022 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]="navigationCardWidgetSettingsForm" fxLayout="column">
|
||||||
|
<mat-form-field fxFlex class="mat-block">
|
||||||
|
<mat-label translate>widgets.navigation.title</mat-label>
|
||||||
|
<input required matInput formControlName="name">
|
||||||
|
</mat-form-field>
|
||||||
|
<tb-material-icon-select fxFlex
|
||||||
|
iconClearButton
|
||||||
|
required
|
||||||
|
formControlName="icon">
|
||||||
|
</tb-material-icon-select>
|
||||||
|
<mat-form-field fxFlex class="mat-block">
|
||||||
|
<mat-label translate>widgets.navigation.navigation-path</mat-label>
|
||||||
|
<input required matInput formControlName="path">
|
||||||
|
</mat-form-field>
|
||||||
|
</section>
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2022 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 { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-navigation-card-widget-settings',
|
||||||
|
templateUrl: './navigation-card-widget-settings.component.html',
|
||||||
|
styleUrls: ['./../widget-settings.scss']
|
||||||
|
})
|
||||||
|
export class NavigationCardWidgetSettingsComponent extends WidgetSettingsComponent {
|
||||||
|
|
||||||
|
navigationCardWidgetSettingsForm: FormGroup;
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>,
|
||||||
|
private fb: FormBuilder) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected settingsForm(): FormGroup {
|
||||||
|
return this.navigationCardWidgetSettingsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected defaultSettings(): WidgetSettings {
|
||||||
|
return {
|
||||||
|
name: '{i18n:device.devices}',
|
||||||
|
icon: 'devices_other',
|
||||||
|
path: '/devices'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onSettingsSet(settings: WidgetSettings) {
|
||||||
|
this.navigationCardWidgetSettingsForm = this.fb.group({
|
||||||
|
name: [settings.name, [Validators.required]],
|
||||||
|
icon: [settings.icon, [Validators.required]],
|
||||||
|
path: [settings.path, [Validators.required]]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2022 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]="navigationCardsWidgetSettingsForm" fxLayout="column">
|
||||||
|
<section style="margin-bottom: 16px;">
|
||||||
|
<div class="mat-caption" style="margin: -8px 0 8px;" translate>widgets.navigation.filter-type</div>
|
||||||
|
<mat-radio-group formControlName="filterType" fxLayoutGap="16px">
|
||||||
|
<mat-radio-button [value]="'all'">{{ 'widgets.navigation.filter-type-all' | translate }}</mat-radio-button>
|
||||||
|
<mat-radio-button [value]="'include'">{{ 'widgets.navigation.filter-type-include' | translate }}</mat-radio-button>
|
||||||
|
<mat-radio-button [value]="'exclude'">{{ 'widgets.navigation.filter-type-exclude' | translate }}</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
</section>
|
||||||
|
<mat-form-field [fxShow]="navigationCardsWidgetSettingsForm.get('filterType').value !== 'all'" fxFlex class="mat-block" floatLabel="always">
|
||||||
|
<mat-label translate>widgets.navigation.items</mat-label>
|
||||||
|
<mat-chip-list #filterItemsChipList>
|
||||||
|
<mat-chip *ngFor="let filterItem of navigationCardsWidgetSettingsForm.get('filter').value"
|
||||||
|
[removable]="true" (removed)="onFilterItemRemoved(filterItem)">
|
||||||
|
{{ filterItem }}
|
||||||
|
<mat-icon matChipRemove>cancel</mat-icon>
|
||||||
|
</mat-chip>
|
||||||
|
<input matInput type="text" placeholder="{{ 'widgets.navigation.enter-urls-to-filter' | translate }}"
|
||||||
|
style="max-width: 200px;"
|
||||||
|
#filterItemInput
|
||||||
|
(focusin)="onFilterItemInputFocus()"
|
||||||
|
matAutocompleteOrigin
|
||||||
|
#origin="matAutocompleteOrigin"
|
||||||
|
(input)="filterItemInputChange.next(filterItemInput.value)"
|
||||||
|
[matAutocompleteConnectedTo]="origin"
|
||||||
|
[matAutocomplete]="filterItemAutocomplete"
|
||||||
|
[matChipInputFor]="filterItemsChipList"
|
||||||
|
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
|
||||||
|
(matChipInputTokenEnd)="addFilterItemFromChipInput($event)">
|
||||||
|
</mat-chip-list>
|
||||||
|
<mat-autocomplete #filterItemAutocomplete="matAutocomplete"
|
||||||
|
class="tb-autocomplete"
|
||||||
|
(optionSelected)="filterItemSelected($event)">
|
||||||
|
<mat-option *ngFor="let filterItem of filteredFilterItems | async" [value]="filterItem">
|
||||||
|
<span [innerHTML]="filterItem | highlight:filterItemSearchText"></span>
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-form-field>
|
||||||
|
</section>
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2022 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, ElementRef, ViewChild } from '@angular/core';
|
||||||
|
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { MatChipInputEvent, MatChipList } from '@angular/material/chips';
|
||||||
|
import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
||||||
|
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
|
||||||
|
import { Observable, of, Subject } from 'rxjs';
|
||||||
|
import { map, mergeMap, share, startWith } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-navigation-cards-widget-settings',
|
||||||
|
templateUrl: './navigation-cards-widget-settings.component.html',
|
||||||
|
styleUrls: ['./../widget-settings.scss']
|
||||||
|
})
|
||||||
|
export class NavigationCardsWidgetSettingsComponent extends WidgetSettingsComponent {
|
||||||
|
|
||||||
|
@ViewChild('filterItemsChipList') filterItemsChipList: MatChipList;
|
||||||
|
@ViewChild('filterItemAutocomplete') filterItemAutocomplete: MatAutocomplete;
|
||||||
|
@ViewChild('filterItemInput') filterItemInput: ElementRef<HTMLInputElement>;
|
||||||
|
|
||||||
|
filterItems: Array<string> = ['/devices', '/assets', '/deviceProfiles'];
|
||||||
|
|
||||||
|
separatorKeysCodes = [ENTER, COMMA, SEMICOLON];
|
||||||
|
|
||||||
|
navigationCardsWidgetSettingsForm: FormGroup;
|
||||||
|
|
||||||
|
filteredFilterItems: Observable<Array<string>>;
|
||||||
|
|
||||||
|
filterItemSearchText = '';
|
||||||
|
|
||||||
|
filterItemInputChange = new Subject<string>();
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>,
|
||||||
|
private fb: FormBuilder) {
|
||||||
|
super(store);
|
||||||
|
this.filteredFilterItems = this.filterItemInputChange
|
||||||
|
.pipe(
|
||||||
|
startWith(''),
|
||||||
|
map((value) => value ? value : ''),
|
||||||
|
mergeMap(name => this.fetchFilterItems(name) ),
|
||||||
|
share()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected settingsForm(): FormGroup {
|
||||||
|
return this.navigationCardsWidgetSettingsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected defaultSettings(): WidgetSettings {
|
||||||
|
return {
|
||||||
|
filterType: 'all',
|
||||||
|
filter: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onSettingsSet(settings: WidgetSettings) {
|
||||||
|
this.navigationCardsWidgetSettingsForm = this.fb.group({
|
||||||
|
filterType: [settings.filterType, []],
|
||||||
|
filter: [settings.filter, []]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected validatorTriggers(): string[] {
|
||||||
|
return ['filterType'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateValidators(emitEvent: boolean) {
|
||||||
|
const filterType: string = this.navigationCardsWidgetSettingsForm.get('filterType').value;
|
||||||
|
if (filterType === 'all') {
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').disable();
|
||||||
|
} else {
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').enable();
|
||||||
|
}
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').updateValueAndValidity({emitEvent});
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchFilterItems(searchText?: string): Observable<Array<string>> {
|
||||||
|
this.filterItemSearchText = searchText;
|
||||||
|
let result = [...this.filterItems];
|
||||||
|
if (this.filterItemSearchText && this.filterItemSearchText.length) {
|
||||||
|
result.unshift(this.filterItemSearchText);
|
||||||
|
result = result.filter(item => item.includes(this.filterItemSearchText));
|
||||||
|
}
|
||||||
|
return of(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFilterItem(filterItem: string): boolean {
|
||||||
|
if (filterItem) {
|
||||||
|
const filterItems: string[] = this.navigationCardsWidgetSettingsForm.get('filter').value;
|
||||||
|
const index = filterItems.indexOf(filterItem);
|
||||||
|
if (index === -1) {
|
||||||
|
filterItems.push(filterItem);
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').setValue(filterItems);
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').markAsDirty();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFilterItemRemoved(filterItem: string): void {
|
||||||
|
const filterItems: string[] = this.navigationCardsWidgetSettingsForm.get('filter').value;
|
||||||
|
const index = filterItems.indexOf(filterItem);
|
||||||
|
if (index > -1) {
|
||||||
|
filterItems.splice(index, 1);
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').setValue(filterItems);
|
||||||
|
this.navigationCardsWidgetSettingsForm.get('filter').markAsDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFilterItemInputFocus() {
|
||||||
|
this.filterItemInputChange.next(this.filterItemInput.nativeElement.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
addFilterItemFromChipInput(event: MatChipInputEvent): void {
|
||||||
|
const value = event.value;
|
||||||
|
if ((value || '').trim()) {
|
||||||
|
const filterItem = value.trim();
|
||||||
|
if (this.addFilterItem(filterItem)) {
|
||||||
|
this.clearFilterItemInput('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterItemSelected(event: MatAutocompleteSelectedEvent): void {
|
||||||
|
this.addFilterItem(event.option.value);
|
||||||
|
this.clearFilterItemInput('');
|
||||||
|
}
|
||||||
|
|
||||||
|
clearFilterItemInput(value: string = '') {
|
||||||
|
this.filterItemInput.nativeElement.value = value;
|
||||||
|
this.filterItemInputChange.next(null);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.filterItemInput.nativeElement.blur();
|
||||||
|
this.filterItemInput.nativeElement.focus();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -163,6 +163,12 @@ import {
|
|||||||
import {
|
import {
|
||||||
GpioPanelWidgetSettingsComponent
|
GpioPanelWidgetSettingsComponent
|
||||||
} from '@home/components/widget/lib/settings/gpio/gpio-panel-widget-settings.component';
|
} from '@home/components/widget/lib/settings/gpio/gpio-panel-widget-settings.component';
|
||||||
|
import {
|
||||||
|
NavigationCardWidgetSettingsComponent
|
||||||
|
} from '@home/components/widget/lib/settings/navigation/navigation-card-widget-settings.component';
|
||||||
|
import {
|
||||||
|
NavigationCardsWidgetSettingsComponent
|
||||||
|
} from '@home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -223,7 +229,9 @@ import {
|
|||||||
GatewayEventsWidgetSettingsComponent,
|
GatewayEventsWidgetSettingsComponent,
|
||||||
GpioItemComponent,
|
GpioItemComponent,
|
||||||
GpioControlWidgetSettingsComponent,
|
GpioControlWidgetSettingsComponent,
|
||||||
GpioPanelWidgetSettingsComponent
|
GpioPanelWidgetSettingsComponent,
|
||||||
|
NavigationCardWidgetSettingsComponent,
|
||||||
|
NavigationCardsWidgetSettingsComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -288,7 +296,9 @@ import {
|
|||||||
GatewayEventsWidgetSettingsComponent,
|
GatewayEventsWidgetSettingsComponent,
|
||||||
GpioItemComponent,
|
GpioItemComponent,
|
||||||
GpioControlWidgetSettingsComponent,
|
GpioControlWidgetSettingsComponent,
|
||||||
GpioPanelWidgetSettingsComponent
|
GpioPanelWidgetSettingsComponent,
|
||||||
|
NavigationCardWidgetSettingsComponent,
|
||||||
|
NavigationCardsWidgetSettingsComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class WidgetSettingsModule {
|
export class WidgetSettingsModule {
|
||||||
@ -338,5 +348,7 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
|
|||||||
'tb-gateway-config-single-device-widget-settings': GatewayConfigSingleDeviceWidgetSettingsComponent,
|
'tb-gateway-config-single-device-widget-settings': GatewayConfigSingleDeviceWidgetSettingsComponent,
|
||||||
'tb-gateway-events-widget-settings': GatewayEventsWidgetSettingsComponent,
|
'tb-gateway-events-widget-settings': GatewayEventsWidgetSettingsComponent,
|
||||||
'tb-gpio-control-widget-settings': GpioControlWidgetSettingsComponent,
|
'tb-gpio-control-widget-settings': GpioControlWidgetSettingsComponent,
|
||||||
'tb-gpio-panel-widget-settings': GpioPanelWidgetSettingsComponent
|
'tb-gpio-panel-widget-settings': GpioPanelWidgetSettingsComponent,
|
||||||
|
'tb-navigation-card-widget-settings': NavigationCardWidgetSettingsComponent,
|
||||||
|
'tb-navigation-cards-widget-settings': NavigationCardsWidgetSettingsComponent
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,9 +16,15 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<div fxLayout="row" [formGroup]="materialIconFormGroup">
|
<div fxLayout="row" [formGroup]="materialIconFormGroup">
|
||||||
<mat-icon (click)="openIconDialog()">{{materialIconFormGroup.get('icon').value}}</mat-icon>
|
<mat-icon class="icon-value" (click)="openIconDialog()">{{materialIconFormGroup.get('icon').value}}</mat-icon>
|
||||||
<mat-form-field fxFlex>
|
<mat-form-field fxFlex>
|
||||||
<mat-label translate>icon.icon</mat-label>
|
<mat-label translate>icon.icon</mat-label>
|
||||||
<input matInput formControlName="icon" (mousedown)="openIconDialog()">
|
<input [required]="required" matInput formControlName="icon" (mousedown)="openIconDialog()">
|
||||||
|
<button *ngIf="iconClearButton"
|
||||||
|
type="button"
|
||||||
|
matSuffix mat-button mat-icon-button aria-label="Clear"
|
||||||
|
(click)="clear()">
|
||||||
|
<mat-icon class="material-icons">close</mat-icon>
|
||||||
|
</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
:host {
|
:host {
|
||||||
.mat-icon {
|
.mat-icon.icon-value {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
margin: 8px 4px 4px;
|
margin: 8px 4px 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { Store } from '@ngrx/store';
|
|||||||
import { AppState } from '@core/core.state';
|
import { AppState } from '@core/core.state';
|
||||||
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { DialogService } from '@core/services/dialog.service';
|
import { DialogService } from '@core/services/dialog.service';
|
||||||
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-material-icon-select',
|
selector: 'tb-material-icon-select',
|
||||||
@ -38,6 +39,27 @@ export class MaterialIconSelectComponent extends PageComponent implements OnInit
|
|||||||
@Input()
|
@Input()
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
|
||||||
|
private iconClearButtonValue: boolean;
|
||||||
|
get iconClearButton(): boolean {
|
||||||
|
return this.iconClearButtonValue;
|
||||||
|
}
|
||||||
|
@Input()
|
||||||
|
set iconClearButton(value: boolean) {
|
||||||
|
const newVal = coerceBooleanProperty(value);
|
||||||
|
if (this.iconClearButtonValue !== newVal) {
|
||||||
|
this.iconClearButtonValue = newVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private requiredValue: boolean;
|
||||||
|
get required(): boolean {
|
||||||
|
return this.requiredValue;
|
||||||
|
}
|
||||||
|
@Input()
|
||||||
|
set required(value: boolean) {
|
||||||
|
this.requiredValue = coerceBooleanProperty(value);
|
||||||
|
}
|
||||||
|
|
||||||
private modelValue: string;
|
private modelValue: string;
|
||||||
|
|
||||||
private propagateChange = null;
|
private propagateChange = null;
|
||||||
@ -104,4 +126,8 @@ export class MaterialIconSelectComponent extends PageComponent implements OnInit
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.materialIconFormGroup.get('icon').patchValue(null, {emitEvent: true});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3615,6 +3615,16 @@
|
|||||||
"no-labels": "No labels configured",
|
"no-labels": "No labels configured",
|
||||||
"add-label": "Add label"
|
"add-label": "Add label"
|
||||||
},
|
},
|
||||||
|
"navigation": {
|
||||||
|
"title": "Title",
|
||||||
|
"navigation-path": "Navigation path",
|
||||||
|
"filter-type": "Filter type",
|
||||||
|
"filter-type-all": "All items",
|
||||||
|
"filter-type-include": "Include items",
|
||||||
|
"filter-type-exclude": "Exclude items",
|
||||||
|
"items": "Items",
|
||||||
|
"enter-urls-to-filter": "Enter urls to filter..."
|
||||||
|
},
|
||||||
"persistent-table": {
|
"persistent-table": {
|
||||||
"rpc-id": "RPC ID",
|
"rpc-id": "RPC ID",
|
||||||
"message-type": "Message type",
|
"message-type": "Message type",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user