48 changed files with 856 additions and 173 deletions
@ -0,0 +1,28 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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-editable-switch { |
|||
padding-left: 10px; |
|||
|
|||
.editable-switch { |
|||
margin: 0; |
|||
} |
|||
|
|||
.editable-label { |
|||
margin: 5px 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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 { |
|||
.predicate-list { |
|||
overflow: auto; |
|||
max-height: 350px; |
|||
.no-data-found { |
|||
height: 50px; |
|||
} |
|||
} |
|||
.filters-operation { |
|||
margin-top: -40px; |
|||
color: #666; |
|||
font-weight: 500; |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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 ::ng-deep { |
|||
mat-form-field { |
|||
.mat-form-field-wrapper { |
|||
padding-bottom: 0; |
|||
.mat-form-field-infix { |
|||
border-top-width: 0.2em; |
|||
width: auto; |
|||
} |
|||
.mat-form-field-underline { |
|||
bottom: 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 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 fxLayout="column" class="mat-content mat-padding"> |
|||
<div fxLayout="column" *ngFor="let filter of filtersInfo | keyvalue"> |
|||
<div fxFlex fxLayout="row" fxLayoutAlign="start center"> |
|||
<mat-label fxFlex>{{filter.value.filter}}</mat-label> |
|||
<button mat-icon-button color="primary" |
|||
style="min-width: 40px;" |
|||
type="button" |
|||
(click)="editFilter(filter.key, filter.value)" |
|||
matTooltip="{{ 'filter.edit' | translate }}" |
|||
matTooltipPosition="above"> |
|||
<mat-icon>edit</mat-icon> |
|||
</button> |
|||
</div> |
|||
<mat-divider></mat-divider> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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 { |
|||
min-width: 300px; |
|||
max-height: 150px; |
|||
overflow-x: hidden; |
|||
overflow-y: auto; |
|||
background: #fff; |
|||
border-radius: 4px; |
|||
box-shadow: |
|||
0 7px 8px -4px rgba(0, 0, 0, .2), |
|||
0 13px 19px 2px rgba(0, 0, 0, .14), |
|||
0 5px 24px 4px rgba(0, 0, 0, .12); |
|||
|
|||
@media (min-height: 350px) { |
|||
max-height: 250px; |
|||
} |
|||
|
|||
.mat-content { |
|||
background-color: #fff; |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
///
|
|||
/// Copyright © 2016-2020 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, Inject, InjectionToken } from '@angular/core'; |
|||
import { IAliasController } from '@core/api/widget-api.models'; |
|||
import { Filter, FilterInfo } from '@shared/models/query/query.models'; |
|||
import { MatDialog } from '@angular/material/dialog'; |
|||
import { FilterDialogComponent, FilterDialogData } from '@home/components/filter/filter-dialog.component'; |
|||
import { deepClone } from '@core/utils'; |
|||
|
|||
export const FILTER_EDIT_PANEL_DATA = new InjectionToken<any>('FiltersEditPanelData'); |
|||
|
|||
export interface FiltersEditPanelData { |
|||
aliasController: IAliasController; |
|||
filtersInfo: {[filterId: string]: FilterInfo}; |
|||
} |
|||
|
|||
@Component({ |
|||
selector: 'tb-filters-edit-panel', |
|||
templateUrl: './filters-edit-panel.component.html', |
|||
styleUrls: ['./filters-edit-panel.component.scss'] |
|||
}) |
|||
export class FiltersEditPanelComponent { |
|||
|
|||
filtersInfo: {[filterId: string]: FilterInfo}; |
|||
|
|||
constructor(@Inject(FILTER_EDIT_PANEL_DATA) public data: FiltersEditPanelData, |
|||
private dialog: MatDialog) { |
|||
this.filtersInfo = this.data.filtersInfo; |
|||
} |
|||
|
|||
public editFilter(filterId: string, filter: FilterInfo) { |
|||
const singleFilter: Filter = {id: filterId, ...deepClone(filter)}; |
|||
this.dialog.open<FilterDialogComponent, FilterDialogData, |
|||
Filter>(FilterDialogComponent, { |
|||
disableClose: true, |
|||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], |
|||
data: { |
|||
isAdd: false, |
|||
filters: [], |
|||
filter: singleFilter, |
|||
userMode: true |
|||
} |
|||
}).afterClosed().subscribe( |
|||
(result) => { |
|||
if (result) { |
|||
this.filtersInfo[result.id] = result; |
|||
this.data.aliasController.updateUserFilter(result); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 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-filters-edit" fxLayout="row" fxLayoutAlign="start center" *ngIf="hasEditableFilters"> |
|||
<button mat-icon-button |
|||
cdkOverlayOrigin #filtersEditPanelOrigin="cdkOverlayOrigin" |
|||
(click)="openEditMode()" |
|||
matTooltip="{{ 'filter.filters' | translate }}" |
|||
[matTooltipPosition]="tooltipPosition"> |
|||
<mat-icon>filter_list</mat-icon> |
|||
</button> |
|||
<span fxHide.lt-lg |
|||
(click)="openEditMode()" |
|||
matTooltip="{{ 'filter.filters' | translate }}" |
|||
[matTooltipPosition]="tooltipPosition"> |
|||
{{ 'filter.filters' | translate }} |
|||
</span> |
|||
</section> |
|||
@ -0,0 +1,36 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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 { |
|||
section.tb-filters-edit { |
|||
min-height: 32px; |
|||
padding: 0 6px; |
|||
|
|||
@media #{$mat-lt-md} { |
|||
padding: 0; |
|||
} |
|||
|
|||
span { |
|||
max-width: 200px; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
white-space: nowrap; |
|||
pointer-events: all; |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,154 @@ |
|||
///
|
|||
/// Copyright © 2016-2020 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, Input, OnDestroy, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; |
|||
import { TooltipPosition } from '@angular/material/tooltip'; |
|||
import { IAliasController } from '@core/api/widget-api.models'; |
|||
import { CdkOverlayOrigin, ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'; |
|||
import { TranslateService } from '@ngx-translate/core'; |
|||
import { Subscription } from 'rxjs'; |
|||
import { BreakpointObserver } from '@angular/cdk/layout'; |
|||
import { deepClone } from '@core/utils'; |
|||
import { FilterInfo } from '@shared/models/query/query.models'; |
|||
import { |
|||
FILTER_EDIT_PANEL_DATA, |
|||
FiltersEditPanelComponent, |
|||
FiltersEditPanelData |
|||
} from '@home/components/filter/filters-edit-panel.component'; |
|||
import { ComponentPortal, PortalInjector } from '@angular/cdk/portal'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-filters-edit', |
|||
templateUrl: './filters-edit.component.html', |
|||
styleUrls: ['./filters-edit.component.scss'] |
|||
}) |
|||
export class FiltersEditComponent implements OnInit, OnDestroy { |
|||
|
|||
aliasControllerValue: IAliasController; |
|||
|
|||
@Input() |
|||
set aliasController(aliasController: IAliasController) { |
|||
this.aliasControllerValue = aliasController; |
|||
this.setupAliasController(this.aliasControllerValue); |
|||
} |
|||
|
|||
get aliasController(): IAliasController { |
|||
return this.aliasControllerValue; |
|||
} |
|||
|
|||
@Input() |
|||
tooltipPosition: TooltipPosition = 'above'; |
|||
|
|||
@Input() disabled: boolean; |
|||
|
|||
@ViewChild('filtersEditPanelOrigin') filtersEditPanelOrigin: CdkOverlayOrigin; |
|||
|
|||
displayValue: string; |
|||
filtersInfo: {[filterId: string]: FilterInfo} = {}; |
|||
hasEditableFilters = false; |
|||
|
|||
private rxSubscriptions = new Array<Subscription>(); |
|||
|
|||
constructor(private translate: TranslateService, |
|||
private overlay: Overlay, |
|||
private breakpointObserver: BreakpointObserver, |
|||
private viewContainerRef: ViewContainerRef) { |
|||
} |
|||
|
|||
private setupAliasController(aliasController: IAliasController) { |
|||
this.rxSubscriptions.forEach((subscription) => { |
|||
subscription.unsubscribe(); |
|||
}); |
|||
this.rxSubscriptions.length = 0; |
|||
if (aliasController) { |
|||
this.rxSubscriptions.push(aliasController.filtersChanged.subscribe( |
|||
() => { |
|||
setTimeout(() => { |
|||
this.updateFiltersInfo(); |
|||
}, 0); |
|||
} |
|||
)); |
|||
setTimeout(() => { |
|||
this.updateFiltersInfo(); |
|||
}, 0); |
|||
} |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
} |
|||
|
|||
ngOnDestroy(): void { |
|||
this.rxSubscriptions.forEach((subscription) => { |
|||
subscription.unsubscribe(); |
|||
}); |
|||
this.rxSubscriptions.length = 0; |
|||
} |
|||
|
|||
openEditMode() { |
|||
if (this.disabled || !this.hasEditableFilters) { |
|||
return; |
|||
} |
|||
const position = this.overlay.position(); |
|||
const config = new OverlayConfig({ |
|||
panelClass: 'tb-filters-edit-panel', |
|||
backdropClass: 'cdk-overlay-transparent-backdrop', |
|||
hasBackdrop: true, |
|||
}); |
|||
const connectedPosition: ConnectedPosition = { |
|||
originX: 'start', |
|||
originY: 'bottom', |
|||
overlayX: 'start', |
|||
overlayY: 'top' |
|||
}; |
|||
config.positionStrategy = position.flexibleConnectedTo(this.filtersEditPanelOrigin.elementRef) |
|||
.withPositions([connectedPosition]); |
|||
const overlayRef = this.overlay.create(config); |
|||
overlayRef.backdropClick().subscribe(() => { |
|||
overlayRef.dispose(); |
|||
}); |
|||
|
|||
const injector = this._createFiltersEditPanelInjector( |
|||
overlayRef, |
|||
{ |
|||
aliasController: this.aliasController, |
|||
filtersInfo: deepClone(this.filtersInfo) |
|||
} |
|||
); |
|||
overlayRef.attach(new ComponentPortal(FiltersEditPanelComponent, this.viewContainerRef, injector)); |
|||
} |
|||
|
|||
private _createFiltersEditPanelInjector(overlayRef: OverlayRef, data: FiltersEditPanelData): PortalInjector { |
|||
const injectionTokens = new WeakMap<any, any>([ |
|||
[FILTER_EDIT_PANEL_DATA, data], |
|||
[OverlayRef, overlayRef] |
|||
]); |
|||
return new PortalInjector(this.viewContainerRef.injector, injectionTokens); |
|||
} |
|||
|
|||
private updateFiltersInfo() { |
|||
const allFilters = this.aliasController.getFilters(); |
|||
this.filtersInfo = {}; |
|||
this.hasEditableFilters = false; |
|||
for (const filterId of Object.keys(allFilters)) { |
|||
const filterInfo = this.aliasController.getFilterInfo(filterId); |
|||
if (filterInfo && filterInfo.editable) { |
|||
this.filtersInfo[filterId] = deepClone(filterInfo); |
|||
this.hasEditableFilters = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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 ::ng-deep { |
|||
.entity-key { |
|||
mat-form-field { |
|||
.mat-form-field-wrapper { |
|||
.mat-form-field-infix { |
|||
width: auto; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
/** |
|||
* Copyright © 2016-2020 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 { |
|||
.key-filter-list { |
|||
overflow: auto; |
|||
max-height: 300px; |
|||
.no-data-found { |
|||
height: 50px; |
|||
} |
|||
} |
|||
.filters-operation { |
|||
margin-top: -40px; |
|||
color: #666; |
|||
font-weight: 500; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue