Browse Source

Merge pull request #10162 from thingsboard/feature/power-button

Power button widget
pull/10184/head
Igor Kulikov 3 years ago
committed by GitHub
parent
commit
08b2a9d6b2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      application/src/main/data/json/system/widget_bundles/buttons.json
  2. 2
      application/src/main/data/json/system/widget_bundles/control_widgets.json
  3. 36
      application/src/main/data/json/system/widget_types/power_button.json
  4. 1
      ui-ngx/package.json
  5. 12
      ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts
  6. 197
      ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.html
  7. 195
      ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.ts
  8. 2
      ui-ngx/src/app/modules/home/components/widget/lib/action/action-widget.models.ts
  9. 32
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.html
  10. 64
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.scss
  11. 203
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.ts
  12. 953
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts
  13. 142
      ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.html
  14. 88
      ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.ts
  15. 12
      ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts
  16. 7
      ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts
  17. 22
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  18. 22
      ui-ngx/src/assets/widget/power-button/default-layout.svg
  19. 50
      ui-ngx/src/assets/widget/power-button/default-volume-layout.svg
  20. 23
      ui-ngx/src/assets/widget/power-button/outlined-layout.svg
  21. 37
      ui-ngx/src/assets/widget/power-button/outlined-volume-layout.svg
  22. 20
      ui-ngx/src/assets/widget/power-button/simplified-layout.svg
  23. 33
      ui-ngx/src/assets/widget/power-button/simplified-volume-layout.svg
  24. 9
      ui-ngx/yarn.lock

3
application/src/main/data/json/system/widget_bundles/buttons.json

@ -9,6 +9,7 @@
},
"widgetTypeFqns": [
"action_button",
"command_button"
"command_button",
"power_button"
]
}

2
application/src/main/data/json/system/widget_bundles/control_widgets.json

@ -9,6 +9,8 @@
},
"widgetTypeFqns": [
"single_switch",
"command_button",
"power_button",
"control_widgets.switch_control",
"control_widgets.slide_toggle_control",
"control_widgets.round_switch",

36
application/src/main/data/json/system/widget_types/power_button.json

File diff suppressed because one or more lines are too long

1
ui-ngx/package.json

@ -44,6 +44,7 @@
"@ngrx/store-devtools": "^15.4.0",
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@svgdotjs/svg.filter.js": "^3.0.8",
"@svgdotjs/svg.js": "^3.2.0",
"@tinymce/tinymce-angular": "^7.0.0",
"ace-builds": "1.4.13",

12
ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts

@ -100,6 +100,9 @@ import {
import {
CommandButtonBasicConfigComponent
} from '@home/components/widget/config/basic/button/command-button-basic-config.component';
import {
PowerButtonBasicConfigComponent
} from '@home/components/widget/config/basic/button/power-button-basic-config.component';
@NgModule({
declarations: [
@ -131,7 +134,8 @@ import {
BarChartWithLabelsBasicConfigComponent,
SingleSwitchBasicConfigComponent,
ActionButtonBasicConfigComponent,
CommandButtonBasicConfigComponent
CommandButtonBasicConfigComponent,
PowerButtonBasicConfigComponent
],
imports: [
CommonModule,
@ -167,7 +171,8 @@ import {
BarChartWithLabelsBasicConfigComponent,
SingleSwitchBasicConfigComponent,
ActionButtonBasicConfigComponent,
CommandButtonBasicConfigComponent
CommandButtonBasicConfigComponent,
PowerButtonBasicConfigComponent
]
})
export class BasicWidgetConfigModule {
@ -197,5 +202,6 @@ export const basicWidgetConfigComponentsMap: {[key: string]: Type<IBasicWidgetCo
'tb-bar-chart-with-labels-basic-config': BarChartWithLabelsBasicConfigComponent,
'tb-single-switch-basic-config': SingleSwitchBasicConfigComponent,
'tb-action-button-basic-config': ActionButtonBasicConfigComponent,
'tb-command-button-basic-config': CommandButtonBasicConfigComponent
'tb-command-button-basic-config': CommandButtonBasicConfigComponent,
'tb-power-button-basic-config': PowerButtonBasicConfigComponent
};

197
ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.html

@ -0,0 +1,197 @@
<!--
Copyright © 2016-2024 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.
-->
<ng-container [formGroup]="powerButtonWidgetConfigForm">
<tb-target-device formControlName="targetDevice"></tb-target-device>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widgets.power-button.behavior</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.initial-state-hint' | translate}}" translate>widgets.rpc-state.initial-state</div>
<tb-get-value-action-settings fxFlex
panelTitle="widgets.rpc-state.initial-state"
[valueType]="valueType.BOOLEAN"
trueLabel="widgets.rpc-state.on"
falseLabel="widgets.rpc-state.off"
stateLabel="widgets.rpc-state.on"
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="initialState"></tb-get-value-action-settings>
</div>
<div class="tb-form-row space-between">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.power-button.power-on-hint' | translate}}" translate>widgets.power-button.power-on</div>
<tb-set-value-action-settings fxFlex
panelTitle="widgets.power-button.power-on "
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="onUpdateState"></tb-set-value-action-settings>
</div>
<div class="tb-form-row space-between">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.power-button.power-off-hint' | translate}}" translate>widgets.power-button.power-off</div>
<tb-set-value-action-settings fxFlex
panelTitle="widgets.power-button.power-off"
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="offUpdateState"></tb-set-value-action-settings>
</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.disabled-state-hint' | translate}}" translate>widgets.rpc-state.disabled-state</div>
<tb-get-value-action-settings fxFlex
panelTitle="widgets.rpc-state.disabled-state"
[valueType]="valueType.BOOLEAN"
stateLabel="widgets.rpc-state.disabled"
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="disabledState"></tb-get-value-action-settings>
</div>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.appearance</div>
<tb-image-cards-select rowHeight="1:1"
[cols]="{columns: 3,
breakpoints: {
'lt-sm': 1,
'lt-md': 2
}}"
label="{{ 'widgets.power-button.layout' | translate }}" formControlName="layout">
<tb-image-cards-select-option *ngFor="let layout of powerButtonLayouts"
[value]="layout"
[image]="powerButtonLayoutImageMap.get(layout)">
{{ powerButtonLayoutTranslationMap.get(layout) | translate }}
</tb-image-cards-select-option>
</tb-image-cards-select>
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.title' | translate }}
</mat-slide-toggle>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="powerButtonWidgetConfigForm.get('title').value"
[initialPreviewStyle]="widgetConfig.config.titleStyle">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showIcon">
{{ 'widget-config.card-icon' | translate }}
</mat-slide-toggle>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field appearance="outline" class="flex number" subscriptSizing="dynamic">
<input matInput type="number" min="0" formControlName="iconSize" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-css-unit-select fxFlex formControlName="iconSizeUnit"></tb-css-unit-select>
<tb-material-icon-select asBoxInput
iconClearButton
[color]="powerButtonWidgetConfigForm.get('iconColor').value"
formControlName="icon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.power-button.power-on-colors' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.main</div>
<tb-color-input asBoxInput
formControlName="mainColorOn">
</tb-color-input>
</div>
<mat-divider vertical></mat-divider>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.background</div>
<tb-color-input asBoxInput
formControlName="backgroundColorOn">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.power-button.power-off-colors' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.main</div>
<tb-color-input asBoxInput
formControlName="mainColorOff">
</tb-color-input>
</div>
<mat-divider vertical></mat-divider>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.background</div>
<tb-color-input asBoxInput
formControlName="backgroundColorOff">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.power-button.disabled-colors' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.main</div>
<tb-color-input asBoxInput
formControlName="mainColorDisabled">
</tb-color-input>
</div>
<mat-divider vertical></mat-divider>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.background</div>
<tb-color-input asBoxInput
formControlName="backgroundColorDisabled">
</tb-color-input>
</div>
</div>
</div>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.background.background' | translate }}</div>
<tb-background-settings formControlName="background">
</tb-background-settings>
</div>
<div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>
</mat-chip-listbox>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.card-border-radius' | translate }}</div>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
</div>
<tb-widget-actions-panel
formControlName="actions">
</tb-widget-actions-panel>
</ng-container>

195
ui-ngx/src/app/modules/home/components/widget/config/basic/button/power-button-basic-config.component.ts

@ -0,0 +1,195 @@
///
/// Copyright © 2016-2024 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models';
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { TargetDevice, WidgetConfig, } from '@shared/models/widget.models';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { isUndefined } from '@core/utils';
import { ValueType } from '@shared/models/constants';
import {
powerButtonDefaultSettings,
powerButtonLayoutImages,
powerButtonLayouts,
powerButtonLayoutTranslations,
PowerButtonWidgetSettings
} from '@home/components/widget/lib/rpc/power-button-widget.models';
import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings.models';
@Component({
selector: 'tb-power-button-basic-config',
templateUrl: './power-button-basic-config.component.html',
styleUrls: ['../basic-config.scss']
})
export class PowerButtonBasicConfigComponent extends BasicWidgetConfigComponent {
get targetDevice(): TargetDevice {
return this.powerButtonWidgetConfigForm.get('targetDevice').value;
}
powerButtonLayouts = powerButtonLayouts;
powerButtonLayoutTranslationMap = powerButtonLayoutTranslations;
powerButtonLayoutImageMap = powerButtonLayoutImages;
valueType = ValueType;
powerButtonWidgetConfigForm: UntypedFormGroup;
constructor(protected store: Store<AppState>,
protected widgetConfigComponent: WidgetConfigComponent,
private fb: UntypedFormBuilder) {
super(store, widgetConfigComponent);
}
protected configForm(): UntypedFormGroup {
return this.powerButtonWidgetConfigForm;
}
protected onConfigSet(configData: WidgetConfigComponentData) {
const settings: PowerButtonWidgetSettings = {...powerButtonDefaultSettings, ...(configData.config.settings || {})};
const iconSize = resolveCssSize(configData.config.iconSize);
this.powerButtonWidgetConfigForm = this.fb.group({
targetDevice: [configData.config.targetDevice, []],
initialState: [settings.initialState, []],
onUpdateState: [settings.onUpdateState, []],
offUpdateState: [settings.offUpdateState, []],
disabledState: [settings.disabledState, []],
layout: [settings.layout, []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
titleFont: [configData.config.titleFont, []],
titleColor: [configData.config.titleColor, []],
showIcon: [configData.config.showTitleIcon, []],
iconSize: [iconSize[0], [Validators.min(0)]],
iconSizeUnit: [iconSize[1], []],
icon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
mainColorOn: [settings.mainColorOn, []],
backgroundColorOn: [settings.backgroundColorOn, []],
mainColorOff: [settings.mainColorOff, []],
backgroundColorOff: [settings.backgroundColorOff, []],
mainColorDisabled: [settings.mainColorDisabled, []],
backgroundColorDisabled: [settings.backgroundColorDisabled, []],
background: [settings.background, []],
cardButtons: [this.getCardButtons(configData.config), []],
borderRadius: [configData.config.borderRadius, []],
actions: [configData.config.actions || {}, []]
});
}
protected prepareOutputConfig(config: any): WidgetConfigComponentData {
this.widgetConfig.config.targetDevice = config.targetDevice;
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.title = config.title;
this.widgetConfig.config.titleFont = config.titleFont;
this.widgetConfig.config.titleColor = config.titleColor;
this.widgetConfig.config.showTitleIcon = config.showIcon;
this.widgetConfig.config.iconSize = cssSizeToStrSize(config.iconSize, config.iconSizeUnit);
this.widgetConfig.config.titleIcon = config.icon;
this.widgetConfig.config.iconColor = config.iconColor;
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
this.widgetConfig.config.settings.initialState = config.initialState;
this.widgetConfig.config.settings.onUpdateState = config.onUpdateState;
this.widgetConfig.config.settings.offUpdateState = config.offUpdateState;
this.widgetConfig.config.settings.disabledState = config.disabledState;
this.widgetConfig.config.settings.layout = config.layout;
this.widgetConfig.config.settings.mainColorOn = config.mainColorOn;
this.widgetConfig.config.settings.backgroundColorOn = config.backgroundColorOn;
this.widgetConfig.config.settings.mainColorOff = config.mainColorOff;
this.widgetConfig.config.settings.backgroundColorOff = config.backgroundColorOff;
this.widgetConfig.config.settings.mainColorDisabled = config.mainColorDisabled;
this.widgetConfig.config.settings.backgroundColorDisabled = config.backgroundColorDisabled;
this.widgetConfig.config.settings.background = config.background;
this.setCardButtons(config.cardButtons, this.widgetConfig.config);
this.widgetConfig.config.borderRadius = config.borderRadius;
this.widgetConfig.config.actions = config.actions;
return this.widgetConfig;
}
protected validatorTriggers(): string[] {
return ['showTitle', 'showIcon'];
}
protected updateValidators(emitEvent: boolean, trigger?: string) {
const showTitle: boolean = this.powerButtonWidgetConfigForm.get('showTitle').value;
const showIcon: boolean = this.powerButtonWidgetConfigForm.get('showIcon').value;
if (showTitle) {
this.powerButtonWidgetConfigForm.get('title').enable();
this.powerButtonWidgetConfigForm.get('titleFont').enable();
this.powerButtonWidgetConfigForm.get('titleColor').enable();
this.powerButtonWidgetConfigForm.get('showIcon').enable({emitEvent: false});
if (showIcon) {
this.powerButtonWidgetConfigForm.get('iconSize').enable();
this.powerButtonWidgetConfigForm.get('iconSizeUnit').enable();
this.powerButtonWidgetConfigForm.get('icon').enable();
this.powerButtonWidgetConfigForm.get('iconColor').enable();
} else {
this.powerButtonWidgetConfigForm.get('iconSize').disable();
this.powerButtonWidgetConfigForm.get('iconSizeUnit').disable();
this.powerButtonWidgetConfigForm.get('icon').disable();
this.powerButtonWidgetConfigForm.get('iconColor').disable();
}
} else {
this.powerButtonWidgetConfigForm.get('title').disable();
this.powerButtonWidgetConfigForm.get('titleFont').disable();
this.powerButtonWidgetConfigForm.get('titleColor').disable();
this.powerButtonWidgetConfigForm.get('showIcon').disable({emitEvent: false});
this.powerButtonWidgetConfigForm.get('iconSize').disable();
this.powerButtonWidgetConfigForm.get('iconSizeUnit').disable();
this.powerButtonWidgetConfigForm.get('icon').disable();
this.powerButtonWidgetConfigForm.get('iconColor').disable();
}
}
private getCardButtons(config: WidgetConfig): string[] {
const buttons: string[] = [];
if (isUndefined(config.enableFullscreen) || config.enableFullscreen) {
buttons.push('fullscreen');
}
return buttons;
}
private setCardButtons(buttons: string[], config: WidgetConfig) {
config.enableFullscreen = buttons.includes('fullscreen');
}
}

2
ui-ngx/src/app/modules/home/components/widget/lib/action/action-widget.models.ts

@ -91,6 +91,8 @@ export abstract class BasicActionWidgetComponent implements OnInit, OnDestroy, A
ngOnDestroy() {
this.valueActions.forEach(v => v.destroy());
this.loadingSubject.complete();
this.loadingSubject.unsubscribe();
}
public onInit() {

32
ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.html

@ -0,0 +1,32 @@
<!--
Copyright © 2016-2024 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-power-button-panel" [style]="backgroundStyle$ | async">
<div class="tb-power-button-overlay" [style]="overlayStyle"></div>
<ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container>
<div class="tb-power-button-content">
<div #powerButtonShape class="tb-power-button-shape" [class.tb-power-button-pointer]="!disabled && (loading$ | async) === false">
</div>
</div>
<mat-progress-bar class="tb-action-widget-progress" style="height: 4px;" color="accent" mode="indeterminate" *ngIf="loading$ | async"></mat-progress-bar>
<div *ngIf="error" class="tb-action-widget-error-container">
<div class="tb-action-widget-error-panel">
<div class="tb-action-widget-error-text" [innerHTML]="error | safe: 'html'"></div>
<button class="tb-action-widget-error-clear tb-mat-20" mat-icon-button (click)="clearError()"><mat-icon>close</mat-icon></button>
</div>
</div>
</div>

64
ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.scss

@ -0,0 +1,64 @@
/**
* Copyright © 2016-2024 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.
*/
.tb-power-button-panel {
width: 100%;
height: 100%;
position: relative;
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 24px 24px 24px;
> div:not(.tb-power-button-overlay) {
z-index: 1;
}
.tb-power-button-overlay {
position: absolute;
top: 12px;
left: 12px;
bottom: 12px;
right: 12px;
}
div.tb-widget-title {
padding: 0;
}
.tb-power-button-content {
flex: 1;
min-width: 0;
min-height: 0;
.tb-power-button-shape {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
svg {
.tb-small-shadow {
filter: drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.2));
}
.tb-shadow {
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.15));
}
}
&.tb-power-button-pointer {
svg {
.tb-hover-circle {
cursor: pointer;
}
}
}
}
}
}

203
ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.component.ts

@ -0,0 +1,203 @@
///
/// Copyright © 2016-2024 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 {
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
OnDestroy,
OnInit,
Renderer2,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { BasicActionWidgetComponent, ValueSetter } from '@home/components/widget/lib/action/action-widget.models';
import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models';
import { Observable } from 'rxjs';
import { ResizeObserver } from '@juggle/resize-observer';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser';
import { ValueType } from '@shared/models/constants';
import {
powerButtonDefaultSettings,
PowerButtonShape,
powerButtonShapeSize,
PowerButtonWidgetSettings
} from '@home/components/widget/lib/rpc/power-button-widget.models';
import { SVG, Svg } from '@svgdotjs/svg.js';
@Component({
selector: 'tb-power-button-widget',
templateUrl: './power-button-widget.component.html',
styleUrls: ['../action/action-widget.scss', './power-button-widget.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class PowerButtonWidgetComponent extends
BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('powerButtonShape', {static: false})
powerButtonShape: ElementRef<HTMLElement>;
settings: PowerButtonWidgetSettings;
backgroundStyle$: Observable<ComponentStyle>;
overlayStyle: ComponentStyle = {};
value = false;
disabled = false;
private shapeResize$: ResizeObserver;
private drawSvgShapePending = false;
private svgShape: Svg;
private powerButtonSvgShape: PowerButtonShape;
private disabledState = false;
private onValueSetter: ValueSetter<boolean>;
private offValueSetter: ValueSetter<boolean>;
constructor(protected imagePipe: ImagePipe,
protected sanitizer: DomSanitizer,
private renderer: Renderer2,
protected cd: ChangeDetectorRef) {
super(cd);
}
ngOnInit(): void {
super.ngOnInit();
this.settings = {...powerButtonDefaultSettings, ...this.ctx.settings};
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
this.overlayStyle = overlayStyle(this.settings.background.overlay);
const getInitialStateSettings =
{...this.settings.initialState, actionLabel: this.ctx.translate.instant('widgets.rpc-state.initial-state')};
this.createValueGetter(getInitialStateSettings, ValueType.BOOLEAN, {
next: (value) => this.onValue(value)
});
const disabledStateSettings =
{...this.settings.disabledState, actionLabel: this.ctx.translate.instant('widgets.rpc-state.disabled-state')};
this.createValueGetter(disabledStateSettings, ValueType.BOOLEAN, {
next: (value) => this.onDisabled(value)
});
const onUpdateStateSettings = {...this.settings.onUpdateState,
actionLabel: this.ctx.translate.instant('widgets.power-button.power-on')};
this.onValueSetter = this.createValueSetter(onUpdateStateSettings);
const offUpdateStateSettings = {...this.settings.offUpdateState,
actionLabel: this.ctx.translate.instant('widgets.power-button.power-off')};
this.offValueSetter = this.createValueSetter(offUpdateStateSettings);
this.loading$.subscribe((loading) => {
this.updateDisabledState(loading || this.disabled);
this.cd.markForCheck();
});
}
ngAfterViewInit(): void {
if (this.drawSvgShapePending) {
this.drawSvg();
}
super.ngAfterViewInit();
}
ngOnDestroy() {
if (this.shapeResize$) {
this.shapeResize$.disconnect();
}
super.ngOnDestroy();
}
public onInit() {
super.onInit();
const borderRadius = this.ctx.$widgetElement.css('borderRadius');
this.overlayStyle = {...this.overlayStyle, ...{borderRadius}};
if (this.powerButtonShape) {
this.drawSvg();
} else {
this.drawSvgShapePending = true;
}
this.cd.detectChanges();
}
private onValue(value: boolean): void {
const newValue = !!value;
if (this.value !== newValue) {
this.value = newValue;
this.powerButtonSvgShape?.setValue(this.value);
this.cd.markForCheck();
}
}
private onDisabled(value: boolean): void {
const newDisabled = !!value;
if (this.disabled !== newDisabled) {
this.disabled = newDisabled;
this.updateDisabledState(this.disabled);
this.cd.markForCheck();
}
}
private onClick() {
if (!this.ctx.isEdit && !this.ctx.isPreview && !this.disabledState) {
this.onValue(!this.value);
const targetValue = this.value;
const targetSetter = targetValue ? this.onValueSetter : this.offValueSetter;
this.powerButtonSvgShape?.setPressed(true);
this.updateValue(targetSetter, targetValue, {
next: () => {
this.powerButtonSvgShape?.setPressed(false);
this.onValue(targetValue);
},
error: () => {
this.powerButtonSvgShape?.setPressed(false);
this.onValue(!targetValue);
}
});
}
}
private drawSvg() {
this.svgShape = SVG().addTo(this.powerButtonShape.nativeElement).size(powerButtonShapeSize, powerButtonShapeSize);
this.renderer.setStyle(this.svgShape.node, 'overflow', 'visible');
this.renderer.setStyle(this.svgShape.node, 'user-select', 'none');
this.powerButtonSvgShape = PowerButtonShape.fromSettings(this.ctx, this.svgShape,
this.settings, this.value, this.disabledState, () => this.onClick());
this.shapeResize$ = new ResizeObserver(() => {
this.onResize();
});
this.shapeResize$.observe(this.powerButtonShape.nativeElement);
this.onResize();
}
private updateDisabledState(disabled: boolean) {
this.disabledState = disabled;
this.powerButtonSvgShape?.setDisabled(this.disabledState);
}
private onResize() {
const shapeWidth = this.powerButtonShape.nativeElement.getBoundingClientRect().width;
const shapeHeight = this.powerButtonShape.nativeElement.getBoundingClientRect().height;
const size = Math.min(shapeWidth, shapeHeight);
const scale = size / powerButtonShapeSize;
this.renderer.setStyle(this.svgShape.node, 'transform', `scale(${scale})`);
}
}

953
ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts

@ -0,0 +1,953 @@
///
/// Copyright © 2016-2024 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 { BackgroundSettings, BackgroundType } from '@shared/models/widget-settings.models';
import { AttributeScope } from '@shared/models/telemetry/telemetry.models';
import {
DataToValueType,
GetValueAction,
GetValueSettings,
SetValueAction,
SetValueSettings,
ValueToDataType
} from '@shared/models/action-widget-settings.models';
import { Circle, Effect, Element, G, Gradient, Runner, Svg, Text, Timeline } from '@svgdotjs/svg.js';
import '@svgdotjs/svg.filter.js';
import tinycolor from 'tinycolor2';
import { WidgetContext } from '@home/models/widget-component.models';
export enum PowerButtonLayout {
default = 'default',
simplified = 'simplified',
outlined = 'outlined',
default_volume = 'default_volume',
simplified_volume = 'simplified_volume',
outlined_volume = 'outlined_volume'
}
export const powerButtonLayouts = Object.keys(PowerButtonLayout) as PowerButtonLayout[];
export const powerButtonLayoutTranslations = new Map<PowerButtonLayout, string>(
[
[PowerButtonLayout.default, 'widgets.power-button.layout-default'],
[PowerButtonLayout.simplified, 'widgets.power-button.layout-simplified'],
[PowerButtonLayout.outlined, 'widgets.power-button.layout-outlined'],
[PowerButtonLayout.default_volume, 'widgets.power-button.layout-default-volume'],
[PowerButtonLayout.simplified_volume, 'widgets.power-button.layout-simplified-volume'],
[PowerButtonLayout.outlined_volume, 'widgets.power-button.layout-outlined-volume']
]
);
export const powerButtonLayoutImages = new Map<PowerButtonLayout, string>(
[
[PowerButtonLayout.default, 'assets/widget/power-button/default-layout.svg'],
[PowerButtonLayout.simplified, 'assets/widget/power-button/simplified-layout.svg'],
[PowerButtonLayout.outlined, 'assets/widget/power-button/outlined-layout.svg'],
[PowerButtonLayout.default_volume, 'assets/widget/power-button/default-volume-layout.svg'],
[PowerButtonLayout.simplified_volume, 'assets/widget/power-button/simplified-volume-layout.svg'],
[PowerButtonLayout.outlined_volume, 'assets/widget/power-button/outlined-volume-layout.svg']
]
);
export interface PowerButtonWidgetSettings {
initialState: GetValueSettings<boolean>;
disabledState: GetValueSettings<boolean>;
onUpdateState: SetValueSettings;
offUpdateState: SetValueSettings;
layout: PowerButtonLayout;
mainColorOn: string;
backgroundColorOn: string;
mainColorOff: string;
backgroundColorOff: string;
mainColorDisabled: string;
backgroundColorDisabled: string;
background: BackgroundSettings;
}
export const powerButtonDefaultSettings: PowerButtonWidgetSettings = {
initialState: {
action: GetValueAction.EXECUTE_RPC,
defaultValue: false,
executeRpc: {
method: 'getState',
requestTimeout: 5000,
requestPersistent: false,
persistentPollingInterval: 1000
},
getAttribute: {
key: 'state',
scope: null
},
getTimeSeries: {
key: 'state'
},
dataToValue: {
type: DataToValueType.NONE,
compareToValue: true,
dataToValueFunction: '/* Should return boolean value */\nreturn data;'
}
},
disabledState: {
action: GetValueAction.DO_NOTHING,
defaultValue: false,
getAttribute: {
key: 'state',
scope: null
},
getTimeSeries: {
key: 'state'
},
dataToValue: {
type: DataToValueType.NONE,
compareToValue: true,
dataToValueFunction: '/* Should return boolean value */\nreturn data;'
}
},
onUpdateState: {
action: SetValueAction.EXECUTE_RPC,
executeRpc: {
method: 'setState',
requestTimeout: 5000,
requestPersistent: false,
persistentPollingInterval: 1000
},
setAttribute: {
key: 'state',
scope: AttributeScope.SHARED_SCOPE
},
putTimeSeries: {
key: 'state'
},
valueToData: {
type: ValueToDataType.CONSTANT,
constantValue: true,
valueToDataFunction: '/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;'
}
},
offUpdateState: {
action: SetValueAction.EXECUTE_RPC,
executeRpc: {
method: 'setState',
requestTimeout: 5000,
requestPersistent: false,
persistentPollingInterval: 1000
},
setAttribute: {
key: 'state',
scope: AttributeScope.SHARED_SCOPE
},
putTimeSeries: {
key: 'state'
},
valueToData: {
type: ValueToDataType.CONSTANT,
constantValue: false,
valueToDataFunction: '/* Convert input boolean value to RPC parameters or attribute/time-series value */ \n return value;'
}
},
layout: PowerButtonLayout.default,
mainColorOn: '#3F52DD',
backgroundColorOn: '#FFFFFF',
mainColorOff: '#A2A2A2',
backgroundColorOff: '#FFFFFF',
mainColorDisabled: 'rgba(0,0,0,0.12)',
backgroundColorDisabled: '#FFFFFF',
background: {
type: BackgroundType.color,
color: '#fff',
overlay: {
enabled: false,
color: 'rgba(255,255,255,0.72)',
blur: 3
}
}
};
interface PowerButtonColor {
hex: string;
opacity: number;
}
type PowerButtonState = 'on' | 'off' | 'disabled';
interface PowerButtonColorState {
mainColor: PowerButtonColor;
backgroundColor: PowerButtonColor;
}
type PowerButtonShapeColors = Record<PowerButtonState, PowerButtonColorState>;
const createPowerButtonShapeColors = (settings: PowerButtonWidgetSettings): PowerButtonShapeColors => {
const mainColorOn = tinycolor(settings.mainColorOn);
const backgroundColorOn = tinycolor(settings.backgroundColorOn);
const mainColorOff = tinycolor(settings.mainColorOff);
const backgroundColorOff = tinycolor(settings.backgroundColorOff);
const mainColorDisabled = tinycolor(settings.mainColorDisabled);
const backgroundColorDisabled = tinycolor(settings.backgroundColorDisabled);
return {
on: {
mainColor: {hex: mainColorOn.toHexString(), opacity: mainColorOn.getAlpha()},
backgroundColor: {hex: backgroundColorOn.toHexString(), opacity: backgroundColorOn.getAlpha()},
},
off: {
mainColor: {hex: mainColorOff.toHexString(), opacity: mainColorOff.getAlpha()},
backgroundColor: {hex: backgroundColorOff.toHexString(), opacity: backgroundColorOff.getAlpha()},
},
disabled: {
mainColor: {hex: mainColorDisabled.toHexString(), opacity: mainColorDisabled.getAlpha()},
backgroundColor: {hex: backgroundColorDisabled.toHexString(), opacity: backgroundColorDisabled.getAlpha()},
}
};
};
export const powerButtonShapeSize = 110;
const cx = powerButtonShapeSize / 2;
const cy = powerButtonShapeSize / 2;
const powerButtonAnimation = (element: Element): Runner => element.animate(200, 0, 'now');
export abstract class PowerButtonShape {
static fromSettings(ctx: WidgetContext,
svgShape: Svg,
settings: PowerButtonWidgetSettings,
value: boolean,
disabled: boolean,
onClick: () => void): PowerButtonShape {
switch (settings.layout) {
case PowerButtonLayout.default:
return new DefaultPowerButtonShape(ctx, svgShape, settings, value, disabled, onClick);
case PowerButtonLayout.simplified:
return new SimplifiedPowerButtonShape(ctx, svgShape, settings, value, disabled, onClick);
case PowerButtonLayout.outlined:
return new OutlinedPowerButtonShape(ctx, svgShape, settings, value, disabled, onClick);
case PowerButtonLayout.default_volume:
return new DefaultVolumePowerButtonShape(ctx, svgShape, settings, value, disabled, onClick);
case PowerButtonLayout.simplified_volume:
return new SimplifiedVolumePowerButtonShape(ctx, svgShape, settings, value, disabled, onClick);
case PowerButtonLayout.outlined_volume:
return new OutlinedVolumePowerButtonShape(ctx, svgShape, settings, value, disabled, onClick);
}
}
protected readonly colors: PowerButtonShapeColors;
protected readonly onLabel: string;
protected readonly offLabel: string;
protected backgroundShape: Circle;
protected hoverShape: Circle;
protected hovered = false;
protected pressed = false;
protected forcePressed = false;
protected constructor(protected widgetContext: WidgetContext,
protected svgShape: Svg,
protected settings: PowerButtonWidgetSettings,
protected value: boolean,
protected disabled: boolean,
protected onClick: () => void) {
this.colors = createPowerButtonShapeColors(this.settings);
this.onLabel = this.widgetContext.translate.instant('widgets.power-button.on-label').toUpperCase();
this.offLabel = this.widgetContext.translate.instant('widgets.power-button.off-label').toUpperCase();
this._drawShape();
}
public setValue(value: boolean) {
if (this.value !== value) {
this.value = value;
this._drawState();
}
}
public setDisabled(disabled: boolean) {
if (this.disabled !== disabled) {
this.disabled = disabled;
this._drawState();
}
}
public setPressed(pressed: boolean) {
if (this.forcePressed !== pressed) {
this.forcePressed = pressed;
if (this.forcePressed && !this.pressed) {
this.onPressStart();
} else if (!this.forcePressed && !this.pressed) {
this.onPressEnd();
}
}
}
private _drawShape() {
this.backgroundShape = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.drawShape();
this.hoverShape = this.svgShape.circle(powerButtonShapeSize).center(cx, cy).addClass('tb-hover-circle')
.fill({color: '#000000', opacity: 0});
this.hoverShape.on('mouseover', () => {
this.hovered = true;
if (!this.disabled) {
this.hoverShape.timeline().finish();
this.hoverShape.animate(200).attr({'fill-opacity': 0.06});
}
});
this.hoverShape.on('mouseout', () => {
this.hovered = false;
this.hoverShape.timeline().finish();
this.hoverShape.animate(200).attr({'fill-opacity': 0});
this._cancelPressed();
});
this.hoverShape.on('touchmove', (event: TouchEvent) => {
const touch = event.touches[0];
const element = document.elementFromPoint(touch.pageX,touch.pageY);
if (this.hoverShape.node !== element) {
this._cancelPressed();
}
});
this.hoverShape.on('touchcancel', () => {
this._cancelPressed();
});
this.hoverShape.on('mousedown touchstart', (event: Event) => {
if (event.type === 'mousedown') {
if ((event as MouseEvent).button !== 0) {
return;
}
}
if (!this.disabled && !this.pressed) {
this.pressed = true;
if (!this.forcePressed) {
this.onPressStart();
}
}
});
this.hoverShape.on('mouseup touchend touchcancel', () => {
if (this.pressed && !this.disabled) {
this.onClick();
}
this._cancelPressed();
});
this._drawState();
}
private _cancelPressed() {
if (this.pressed) {
this.pressed = false;
if (!this.forcePressed) {
this.onPressEnd();
}
}
}
private _drawState() {
let colorState: PowerButtonColorState;
if (this.disabled) {
colorState = this.colors.disabled;
} else {
colorState = this.value ? this.colors.on : this.colors.off;
}
this.drawBackgroundState(colorState.backgroundColor);
this.drawColorState(colorState.mainColor);
if (this.value) {
this.drawOn();
} else {
this.drawOff();
}
if (this.disabled) {
this.hoverShape.timeline().finish();
this.hoverShape.attr({'fill-opacity': 0});
} else if (this.hovered) {
this.hoverShape.timeline().finish();
this.hoverShape.animate(200).attr({'fill-opacity': 0.06});
}
}
private drawBackgroundState(backgroundColor: PowerButtonColor) {
this.backgroundShape.attr({ fill: backgroundColor.hex, 'fill-opacity': backgroundColor.opacity});
}
protected drawShape() {}
protected drawColorState(_mainColor: PowerButtonColor) {}
protected drawOff() {}
protected drawOn() {}
protected onPressStart() {}
protected onPressEnd() {}
protected createMask(shape: Element, maskElements: Element[]) {
const mask =
this.svgShape.mask().add(this.svgShape.rect().width('100%').height('100%').fill('#fff'));
maskElements.forEach(e => {
mask.add(e.fill('#000').attr({'fill-opacity': 1}));
});
shape.maskWith(mask);
}
protected createOnLabel(fontWeight = '500'): Text {
return this.createLabel(this.onLabel, fontWeight);
}
protected createOffLabel(fontWeight = '500'): Text {
return this.createLabel(this.offLabel, fontWeight);
}
private createLabel(text: string, fontWeight = '500'): Text {
return this.svgShape.text(text).font({
family: 'Roboto',
weight: fontWeight,
style: 'normal',
size: '22px'
}).attr({x: '50%', y: '50%', 'text-anchor': 'middle', 'dominant-baseline': 'middle'});
}
}
class InnerShadowCircle {
private shadowCircle: Circle;
private blurEffect: Effect;
private offsetEffect: Effect;
private floodEffect: Effect;
constructor(private svgShape: Svg,
private diameter: number,
private centerX: number,
private centerY: number,
private blur = 6,
private shadowOpacity = 0.6,
private dx = 0,
private dy = 0,
private shadowColor = '#000') {
this.shadowCircle = this.svgShape.circle(this.diameter).center(this.centerX, this.centerY)
.fill({color: '#fff', opacity: 1}).stroke({width: 0});
this.shadowCircle.filterWith(add => {
add.x('-50%').y('-50%').width('200%').height('200%');
let effect: Effect = add.componentTransfer(components => {
components.funcA({ type: 'table', tableValues: '1 0' });
}).in(add.$fill);
effect = effect.gaussianBlur(this.blur, this.blur).attr({stdDeviation: this.blur});
this.blurEffect = effect;
effect = effect.offset(this.dx, this.dy);
this.offsetEffect = effect;
effect = effect.flood(this.shadowColor, this.shadowOpacity);
this.floodEffect = effect;
effect = effect.composite(this.offsetEffect, 'in');
effect.composite(add.$sourceAlpha, 'in');
add.merge(m => {
m.mergeNode(add.$fill);
m.mergeNode();
});
});
}
public timeline(tl: Timeline): void {
this.blurEffect.timeline(tl);
this.offsetEffect.timeline(tl);
this.floodEffect.timeline(tl);
}
public animate(blur: number, opacity: number, dx = 0, dy = 0): Runner {
powerButtonAnimation(this.blurEffect).attr({stdDeviation: blur});
powerButtonAnimation(this.offsetEffect).attr({dx, dy});
return powerButtonAnimation(this.floodEffect).attr({'flood-opacity': opacity});
}
public animateRestore(): Runner {
return this.animate(this.blur, this.shadowOpacity, this.dx, this.dy);
}
public show(): void {
this.shadowCircle.show();
}
public hide(): void {
this.shadowCircle.hide();
}
}
class DefaultPowerButtonShape extends PowerButtonShape {
private outerBorder: Circle;
private outerBorderMask: Circle;
private offLabelShape: Text;
private onCircleShape: Circle;
private onLabelShape: Text;
private pressedShadow: InnerShadowCircle;
private pressedTimeline: Timeline;
private centerGroup: G;
protected drawShape() {
this.outerBorder = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.outerBorderMask = this.svgShape.circle(powerButtonShapeSize - 20).center(cx, cy);
this.createMask(this.outerBorder, [this.outerBorderMask]);
this.centerGroup = this.svgShape.group();
this.offLabelShape = this.createOffLabel().addTo(this.centerGroup);
this.onCircleShape = this.svgShape.circle(powerButtonShapeSize - 20)
.center(cx, cy);
this.onLabelShape = this.createOnLabel();
this.createMask(this.onCircleShape, [this.onLabelShape]);
this.pressedShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 20, cx, cy, 0, 0);
this.pressedTimeline = new Timeline();
this.centerGroup.timeline(this.pressedTimeline);
this.onLabelShape.timeline(this.pressedTimeline);
this.pressedShadow.timeline(this.pressedTimeline);
}
protected drawColorState(mainColor: PowerButtonColor) {
this.outerBorder.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.onCircleShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
}
protected drawOff() {
this.outerBorderMask.radius((powerButtonShapeSize - 20)/2);
this.onCircleShape.hide();
this.centerGroup.show();
}
protected drawOn() {
this.outerBorderMask.radius((powerButtonShapeSize - 2)/2);
this.centerGroup.hide();
this.onCircleShape.show();
}
protected onPressStart() {
this.pressedTimeline.finish();
const pressedScale = 0.75;
powerButtonAnimation(this.centerGroup).transform({scale: pressedScale});
powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale});
this.pressedShadow.animate(6, 0.6);
}
protected onPressEnd() {
this.pressedTimeline.finish();
powerButtonAnimation(this.centerGroup).transform({scale: 1});
powerButtonAnimation(this.onLabelShape).transform({scale: 1});
this.pressedShadow.animateRestore();
}
}
class SimplifiedPowerButtonShape extends PowerButtonShape {
private outerBorder: Circle;
private outerBorderMask: Circle;
private onCircleShape: Circle;
private offLabelShape: Text;
private onLabelShape: Text;
private pressedShadow: InnerShadowCircle;
private pressedTimeline: Timeline;
private centerGroup: G;
protected drawShape() {
this.outerBorder = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.outerBorderMask = this.svgShape.circle(powerButtonShapeSize - 4).center(cx, cy);
this.createMask(this.outerBorder, [this.outerBorderMask]);
this.centerGroup = this.svgShape.group();
this.offLabelShape = this.createOffLabel().addTo(this.centerGroup);
this.onCircleShape = this.svgShape.circle(powerButtonShapeSize).center(cx, cy);
this.onLabelShape = this.createOnLabel();
this.createMask(this.onCircleShape, [this.onLabelShape]);
this.pressedShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 4, cx, cy, 0, 0);
this.pressedTimeline = new Timeline();
this.centerGroup.timeline(this.pressedTimeline);
this.onLabelShape.timeline(this.pressedTimeline);
this.pressedShadow.timeline(this.pressedTimeline);
}
protected drawColorState(mainColor: PowerButtonColor) {
this.outerBorder.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.onCircleShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
}
protected drawOff() {
this.onCircleShape.hide();
this.outerBorder.show();
this.centerGroup.show();
}
protected drawOn() {
this.centerGroup.hide();
this.outerBorder.hide();
this.onCircleShape.show();
}
protected onPressStart() {
this.pressedTimeline.finish();
const pressedScale = 0.75;
powerButtonAnimation(this.centerGroup).transform({scale: pressedScale});
powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale});
this.pressedShadow.animate(6, 0.6);
}
protected onPressEnd() {
this.pressedTimeline.finish();
powerButtonAnimation(this.centerGroup).transform({scale: 1});
powerButtonAnimation(this.onLabelShape).transform({scale: 1});
this.pressedShadow.animateRestore();
}
}
class OutlinedPowerButtonShape extends PowerButtonShape {
private outerBorder: Circle;
private outerBorderMask: Circle;
private innerBorder: Circle;
private innerBorderMask: Circle;
private offLabelShape: Text;
private onCircleShape: Circle;
private onLabelShape: Text;
private pressedShadow: InnerShadowCircle;
private pressedTimeline: Timeline;
private centerGroup: G;
private onCenterGroup: G;
protected drawShape() {
this.outerBorder = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.outerBorderMask = this.svgShape.circle(powerButtonShapeSize - 2).center(cx, cy);
this.createMask(this.outerBorder, [this.outerBorderMask]);
this.innerBorder = this.svgShape.circle(powerButtonShapeSize - 20).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.innerBorderMask = this.svgShape.circle(powerButtonShapeSize - 24).center(cx, cy);
this.createMask(this.innerBorder, [this.innerBorderMask]);
this.centerGroup = this.svgShape.group();
this.offLabelShape = this.createOffLabel().addTo(this.centerGroup);
this.onCenterGroup = this.svgShape.group();
this.onCircleShape = this.svgShape.circle(powerButtonShapeSize - 28).center(cx, cy)
.addTo(this.onCenterGroup);
this.onLabelShape = this.createOnLabel();
this.createMask(this.onCircleShape, [this.onLabelShape]);
this.pressedShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 24, cx, cy, 0, 0);
this.pressedTimeline = new Timeline();
this.centerGroup.timeline(this.pressedTimeline);
this.onCenterGroup.timeline(this.pressedTimeline);
this.onLabelShape.timeline(this.pressedTimeline);
this.pressedShadow.timeline(this.pressedTimeline);
}
protected drawColorState(mainColor: PowerButtonColor) {
this.outerBorder.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.innerBorder.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.onCircleShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
}
protected drawOff() {
this.onCenterGroup.hide();
this.centerGroup.show();
}
protected drawOn() {
this.centerGroup.hide();
this.onCenterGroup.show();
}
protected onPressStart() {
this.pressedTimeline.finish();
const pressedScale = 0.75;
powerButtonAnimation(this.centerGroup).transform({scale: pressedScale});
powerButtonAnimation(this.onCenterGroup).transform({scale: 0.98});
powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale / 0.98});
this.pressedShadow.animate(6, 0.6);
}
protected onPressEnd() {
this.pressedTimeline.finish();
powerButtonAnimation(this.centerGroup).transform({scale: 1});
powerButtonAnimation(this.onCenterGroup).transform({scale: 1});
powerButtonAnimation(this.onLabelShape).transform({scale: 1});
this.pressedShadow.animateRestore();
}
}
class DefaultVolumePowerButtonShape extends PowerButtonShape {
private outerBorder: Circle;
private outerBorderMask: Circle;
private outerBorderGradient: Gradient;
private innerBorder: Circle;
private innerBorderMask: Circle;
private innerBorderGradient: Gradient;
private innerShadow: InnerShadowCircle;
//private innerShadowGradient: Gradient;
//private innerShadowGradientStop: Stop;
private offLabelShape: Text;
private onCircleShape: Circle;
private onLabelShape: Text;
private pressedTimeline: Timeline;
private centerGroup: G;
protected drawShape() {
this.outerBorder = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.outerBorderMask = this.svgShape.circle(powerButtonShapeSize - 20).center(cx, cy);
this.createMask(this.outerBorder, [this.outerBorderMask]);
this.outerBorderGradient = this.svgShape.gradient('linear', (add) => {
add.stop(0, '#CCCCCC', 1);
add.stop(1, '#FFFFFF', 1);
}).from(0.268, 0.92).to(0.832, 0.1188);
this.innerBorder = this.svgShape.circle(powerButtonShapeSize - 20).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.innerBorderMask = this.svgShape.circle(powerButtonShapeSize - 24).center(cx, cy);
this.createMask(this.innerBorder, [this.innerBorderMask]);
this.innerBorderGradient = this.svgShape.gradient('linear', (add) => {
add.stop(0, '#CCCCCC', 1);
add.stop(1, '#FFFFFF', 1);
}).from(0.832, 0.1188).to(0.268, 0.92);
this.centerGroup = this.svgShape.group();
this.offLabelShape = this.createOffLabel('400').addTo(this.centerGroup);
this.onCircleShape = this.svgShape.circle(powerButtonShapeSize - 24).center(cx, cy);
this.onLabelShape = this.createOnLabel('400');
this.createMask(this.onCircleShape, [this.onLabelShape]);
this.innerShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 24, cx, cy, 3, 0.3);
this.pressedTimeline = new Timeline();
this.centerGroup.timeline(this.pressedTimeline);
this.onLabelShape.timeline(this.pressedTimeline);
this.innerShadow.timeline(this.pressedTimeline);
}
protected drawColorState(mainColor: PowerButtonColor){
if (this.disabled) {
this.backgroundShape.removeClass('tb-small-shadow');
if (!this.forcePressed) {
this.innerShadow.hide();
}
this.outerBorder.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.innerBorder.attr({fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
} else {
this.backgroundShape.addClass('tb-small-shadow');
this.innerShadow.show();
this.outerBorder.fill(this.outerBorderGradient);
this.outerBorder.attr({ 'fill-opacity': 1 });
this.innerBorder.fill(this.innerBorderGradient);
this.innerBorder.attr({ 'fill-opacity': 1 });
}
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.onCircleShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
}
protected drawOff() {
this.onCircleShape.hide();
this.centerGroup.show();
this.innerBorder.show();
}
protected drawOn() {
if (this.disabled) {
this.innerBorder.hide();
} else {
this.innerBorder.show();
}
this.centerGroup.hide();
this.onCircleShape.show();
}
protected onPressStart() {
this.pressedTimeline.finish();
this.innerShadow.show();
const pressedScale = 0.75;
powerButtonAnimation(this.centerGroup).transform({scale: pressedScale});
powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale});
this.innerShadow.animate(6, 0.6);
}
protected onPressEnd() {
this.pressedTimeline.finish();
powerButtonAnimation(this.centerGroup).transform({scale: 1});
powerButtonAnimation(this.onLabelShape).transform({scale: 1});
this.innerShadow.animateRestore().after(() => {
if (this.disabled) {
this.innerShadow.hide();
}
});
}
}
class SimplifiedVolumePowerButtonShape extends PowerButtonShape {
private outerBorder: Circle;
private outerBorderMask: Circle;
private offLabelShape: Text;
private onLabelShape: Text;
private innerShadow: InnerShadowCircle;
private pressedShadow: InnerShadowCircle;
private pressedTimeline: Timeline;
private centerGroup: G;
private onCenterGroup: G;
protected drawShape() {
this.outerBorder = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({color: '#FAFAFA', opacity: 1}).stroke({width: 0});
this.outerBorderMask = this.svgShape.circle(powerButtonShapeSize - 4).center(cx, cy);
this.createMask(this.outerBorder, [this.outerBorderMask]);
this.centerGroup = this.svgShape.group();
this.offLabelShape = this.createOffLabel().addTo(this.centerGroup);
this.onCenterGroup = this.svgShape.group();
this.onLabelShape = this.createOnLabel().addTo(this.onCenterGroup);
this.innerShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 4, cx, cy, 3, 0.3);
this.pressedShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 4, cx, cy, 0, 0);
this.pressedTimeline = new Timeline();
this.centerGroup.timeline(this.pressedTimeline);
this.onCenterGroup.timeline(this.pressedTimeline);
this.pressedShadow.timeline(this.pressedTimeline);
}
protected drawColorState(mainColor: PowerButtonColor){
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.onLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
}
protected drawOff() {
if (!this.pressed) {
this.backgroundShape.addClass('tb-shadow');
}
this.innerShadow.hide();
this.onCenterGroup.hide();
this.centerGroup.show();
}
protected drawOn() {
this.backgroundShape.removeClass('tb-shadow');
this.centerGroup.hide();
this.onCenterGroup.show();
this.innerShadow.show();
}
protected onPressStart() {
this.pressedTimeline.finish();
const pressedScale = 0.75;
if (!this.value) {
this.backgroundShape.removeClass('tb-shadow');
}
powerButtonAnimation(this.centerGroup).transform({scale: pressedScale});
powerButtonAnimation(this.onCenterGroup).transform({scale: pressedScale});
this.pressedShadow.animate(8, 0.4);
}
protected onPressEnd() {
this.pressedTimeline.finish();
powerButtonAnimation(this.centerGroup).transform({scale: 1});
powerButtonAnimation(this.onCenterGroup).transform({scale: 1});
this.pressedShadow.animateRestore().after(() => {
if (!this.value) {
this.backgroundShape.addClass('tb-shadow');
}
});
}
}
class OutlinedVolumePowerButtonShape extends PowerButtonShape {
private outerBorder: Circle;
private outerBorderMask: Circle;
private outerBorderGradient: Gradient;
private innerBorder: Circle;
private innerBorderMask: Circle;
private offLabelShape: Text;
private onCircleShape: Circle;
private onLabelShape: Text;
private pressedShadow: InnerShadowCircle;
private pressedTimeline: Timeline;
private centerGroup: G;
private onCenterGroup: G;
protected drawShape() {
this.outerBorder = this.svgShape.circle(powerButtonShapeSize).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.outerBorderMask = this.svgShape.circle(powerButtonShapeSize - 20).center(cx, cy);
this.createMask(this.outerBorder, [this.outerBorderMask]);
this.outerBorderGradient = this.svgShape.gradient('linear', (add) => {
add.stop(0, '#CCCCCC', 1);
add.stop(1, '#FFFFFF', 1);
}).from(0.268, 0.92).to(0.832, 0.1188);
this.innerBorder = this.svgShape.circle(powerButtonShapeSize - 20).center(cx, cy)
.fill({opacity: 0}).stroke({width: 0});
this.innerBorderMask = this.svgShape.circle(powerButtonShapeSize - 30).center(cx, cy);
this.createMask(this.innerBorder, [this.innerBorderMask]);
this.centerGroup = this.svgShape.group();
this.offLabelShape = this.createOffLabel('800').addTo(this.centerGroup);
this.onCenterGroup = this.svgShape.group();
this.onCircleShape = this.svgShape.circle(powerButtonShapeSize - 30).center(cx, cy)
.addTo(this.onCenterGroup);
this.onLabelShape = this.createOnLabel('800');
this.createMask(this.onCircleShape, [this.onLabelShape]);
this.pressedShadow = new InnerShadowCircle(this.svgShape, powerButtonShapeSize - 30, cx, cy, 0, 0);
this.backgroundShape.addClass('tb-small-shadow');
this.pressedTimeline = new Timeline();
this.centerGroup.timeline(this.pressedTimeline);
this.onCenterGroup.timeline(this.pressedTimeline);
this.onLabelShape.timeline(this.pressedTimeline);
this.pressedShadow.timeline(this.pressedTimeline);
}
protected drawColorState(mainColor: PowerButtonColor){
if (this.disabled) {
this.outerBorder.attr({ fill: '#000000', 'fill-opacity': 0.03});
} else {
this.outerBorder.fill(this.outerBorderGradient);
this.outerBorder.attr({ 'fill-opacity': 1 });
}
this.innerBorder.attr({fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.offLabelShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
this.onCircleShape.attr({ fill: mainColor.hex, 'fill-opacity': mainColor.opacity});
}
protected drawOff() {
this.onCenterGroup.hide();
this.centerGroup.show();
this.innerBorder.show();
}
protected drawOn() {
this.innerBorder.hide();
this.centerGroup.hide();
this.onCenterGroup.show();
}
protected onPressStart() {
this.pressedTimeline.finish();
const pressedScale = 0.75;
powerButtonAnimation(this.centerGroup).transform({scale: pressedScale});
powerButtonAnimation(this.onCenterGroup).transform({scale: 0.98});
powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale / 0.98});
this.pressedShadow.animate(6, 0.6);
}
protected onPressEnd() {
this.pressedTimeline.finish();
powerButtonAnimation(this.centerGroup).transform({scale: 1});
powerButtonAnimation(this.onCenterGroup).transform({scale: 1});
powerButtonAnimation(this.onLabelShape).transform({scale: 1});
this.pressedShadow.animateRestore();
}
}

142
ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.html

@ -0,0 +1,142 @@
<!--
Copyright © 2016-2024 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.
-->
<ng-container [formGroup]="powerButtonWidgetSettingsForm">
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widgets.power-button.behavior</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.initial-state-hint' | translate}}" translate>widgets.rpc-state.initial-state</div>
<tb-get-value-action-settings fxFlex
panelTitle="widgets.rpc-state.initial-state"
[valueType]="valueType.BOOLEAN"
trueLabel="widgets.rpc-state.on"
falseLabel="widgets.rpc-state.off"
stateLabel="widgets.rpc-state.on"
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="initialState"></tb-get-value-action-settings>
</div>
<div class="tb-form-row space-between">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.power-button.power-on-hint' | translate}}" translate>widgets.power-button.power-on</div>
<tb-set-value-action-settings fxFlex
panelTitle="widgets.power-button.power-on "
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="onUpdateState"></tb-set-value-action-settings>
</div>
<div class="tb-form-row space-between">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.power-button.power-off-hint' | translate}}" translate>widgets.power-button.power-off</div>
<tb-set-value-action-settings fxFlex
panelTitle="widgets.power-button.power-off"
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="offUpdateState"></tb-set-value-action-settings>
</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.disabled-state-hint' | translate}}" translate>widgets.rpc-state.disabled-state</div>
<tb-get-value-action-settings fxFlex
panelTitle="widgets.rpc-state.disabled-state"
[valueType]="valueType.BOOLEAN"
stateLabel="widgets.rpc-state.disabled"
[aliasController]="aliasController"
[targetDevice]="targetDevice"
[widgetType]="widgetType"
formControlName="disabledState"></tb-get-value-action-settings>
</div>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-style</div>
<tb-image-cards-select rowHeight="1:1"
[cols]="{columns: 3,
breakpoints: {
'lt-sm': 1,
'lt-md': 2
}}"
label="{{ 'widgets.power-button.layout' | translate }}" formControlName="layout">
<tb-image-cards-select-option *ngFor="let layout of powerButtonLayouts"
[value]="layout"
[image]="powerButtonLayoutImageMap.get(layout)">
{{ powerButtonLayoutTranslationMap.get(layout) | translate }}
</tb-image-cards-select-option>
</tb-image-cards-select>
<div class="tb-form-row space-between">
<div>{{ 'widgets.background.background' | translate }}</div>
<tb-background-settings formControlName="background">
</tb-background-settings>
</div>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widgets.power-button.button</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.power-button.power-on-colors' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.main</div>
<tb-color-input asBoxInput
formControlName="mainColorOn">
</tb-color-input>
</div>
<mat-divider vertical></mat-divider>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.background</div>
<tb-color-input asBoxInput
formControlName="backgroundColorOn">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.power-button.power-off-colors' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.main</div>
<tb-color-input asBoxInput
formControlName="mainColorOff">
</tb-color-input>
</div>
<mat-divider vertical></mat-divider>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.background</div>
<tb-color-input asBoxInput
formControlName="backgroundColorOff">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.power-button.disabled-colors' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.main</div>
<tb-color-input asBoxInput
formControlName="mainColorDisabled">
</tb-color-input>
</div>
<mat-divider vertical></mat-divider>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<div translate>widgets.power-button.background</div>
<tb-color-input asBoxInput
formControlName="backgroundColorDisabled">
</tb-color-input>
</div>
</div>
</div>
</div>
</ng-container>

88
ui-ngx/src/app/modules/home/components/widget/lib/settings/button/power-button-widget-settings.component.ts

@ -0,0 +1,88 @@
///
/// Copyright © 2016-2024 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 { TargetDevice, WidgetSettings, WidgetSettingsComponent, widgetType } from '@shared/models/widget.models';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { ValueType } from '@shared/models/constants';
import {
powerButtonDefaultSettings,
powerButtonLayoutImages,
powerButtonLayouts,
powerButtonLayoutTranslations
} from '@home/components/widget/lib/rpc/power-button-widget.models';
@Component({
selector: 'tb-power-button-widget-settings',
templateUrl: './power-button-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class PowerButtonWidgetSettingsComponent extends WidgetSettingsComponent {
get targetDevice(): TargetDevice {
return this.widgetConfig?.config?.targetDevice;
}
get widgetType(): widgetType {
return this.widgetConfig?.widgetType;
}
powerButtonLayouts = powerButtonLayouts;
powerButtonLayoutTranslationMap = powerButtonLayoutTranslations;
powerButtonLayoutImageMap = powerButtonLayoutImages;
valueType = ValueType;
powerButtonWidgetSettingsForm: UntypedFormGroup;
constructor(protected store: Store<AppState>,
private fb: UntypedFormBuilder) {
super(store);
}
protected settingsForm(): UntypedFormGroup {
return this.powerButtonWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {...powerButtonDefaultSettings};
}
protected onSettingsSet(settings: WidgetSettings) {
this.powerButtonWidgetSettingsForm = this.fb.group({
initialState: [settings.initialState, []],
onUpdateState: [settings.onUpdateState, []],
offUpdateState: [settings.offUpdateState, []],
disabledState: [settings.disabledState, []],
layout: [settings.layout, []],
mainColorOn: [settings.mainColorOn, []],
backgroundColorOn: [settings.backgroundColorOn, []],
mainColorOff: [settings.mainColorOff, []],
backgroundColorOff: [settings.backgroundColorOff, []],
mainColorDisabled: [settings.mainColorDisabled, []],
backgroundColorDisabled: [settings.backgroundColorDisabled, []],
background: [settings.background, []]
});
}
}

12
ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts

@ -321,6 +321,9 @@ import {
import {
CommandButtonWidgetSettingsComponent
} from '@home/components/widget/lib/settings/button/command-button-widget-settings.component';
import {
PowerButtonWidgetSettingsComponent
} from '@home/components/widget/lib/settings/button/power-button-widget-settings.component';
@NgModule({
declarations: [
@ -436,7 +439,8 @@ import {
BarChartWithLabelsWidgetSettingsComponent,
SingleSwitchWidgetSettingsComponent,
ActionButtonWidgetSettingsComponent,
CommandButtonWidgetSettingsComponent
CommandButtonWidgetSettingsComponent,
PowerButtonWidgetSettingsComponent
],
imports: [
CommonModule,
@ -557,7 +561,8 @@ import {
BarChartWithLabelsWidgetSettingsComponent,
SingleSwitchWidgetSettingsComponent,
ActionButtonWidgetSettingsComponent,
CommandButtonWidgetSettingsComponent
CommandButtonWidgetSettingsComponent,
PowerButtonWidgetSettingsComponent
]
})
export class WidgetSettingsModule {
@ -645,5 +650,6 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
'tb-bar-chart-with-labels-widget-settings': BarChartWithLabelsWidgetSettingsComponent,
'tb-single-switch-widget-settings': SingleSwitchWidgetSettingsComponent,
'tb-action-button-widget-settings': ActionButtonWidgetSettingsComponent,
'tb-command-button-widget-settings': CommandButtonWidgetSettingsComponent
'tb-command-button-widget-settings': CommandButtonWidgetSettingsComponent,
'tb-power-button-widget-settings': PowerButtonWidgetSettingsComponent
};

7
ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts

@ -73,6 +73,7 @@ import {
import { SingleSwitchWidgetComponent } from '@home/components/widget/lib/rpc/single-switch-widget.component';
import { ActionButtonWidgetComponent } from '@home/components/widget/lib/button/action-button-widget.component';
import { CommandButtonWidgetComponent } from '@home/components/widget/lib/button/command-button-widget.component';
import { PowerButtonWidgetComponent } from '@home/components/widget/lib/rpc/power-button-widget.component';
@NgModule({
declarations:
@ -118,7 +119,8 @@ import { CommandButtonWidgetComponent } from '@home/components/widget/lib/button
BarChartWithLabelsWidgetComponent,
SingleSwitchWidgetComponent,
ActionButtonWidgetComponent,
CommandButtonWidgetComponent
CommandButtonWidgetComponent,
PowerButtonWidgetComponent
],
imports: [
CommonModule,
@ -168,7 +170,8 @@ import { CommandButtonWidgetComponent } from '@home/components/widget/lib/button
BarChartWithLabelsWidgetComponent,
SingleSwitchWidgetComponent,
ActionButtonWidgetComponent,
CommandButtonWidgetComponent
CommandButtonWidgetComponent,
PowerButtonWidgetComponent
],
providers: [
{provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule }

22
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -5206,6 +5206,28 @@
"on-click": "On click",
"on-click-hint": "Action performed when the button is clicked."
},
"power-button": {
"behavior": "Behavior",
"power-on": "Power 'On'",
"power-on-hint": "Action performed to power ON the component.",
"power-off": "Power 'Off'",
"power-off-hint": "Action performed to power OFF the component.",
"on-label": "On",
"off-label": "Off",
"layout": "Layout",
"layout-default": "Default",
"layout-simplified": "Simplified",
"layout-outlined": "Outlined",
"layout-default-volume": "Default.Volume",
"layout-simplified-volume": "Simplified.Volume",
"layout-outlined-volume": "Outlined.Volume",
"main": "Main",
"background": "Background",
"power-on-colors": "Power 'On' colors",
"power-off-colors": "Power 'Off' colors",
"disabled-colors": "Disabled colors",
"button": "Button"
},
"button": {
"layout": "Layout",
"outlined": "Outlined",

22
ui-ngx/src/assets/widget/power-button/default-layout.svg

@ -0,0 +1,22 @@
<svg width="160" height="159" viewBox="0 0 160 159" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4488_87637)">
<rect x="6.8335" y="3" width="147" height="147" rx="2.98477" fill="white" shape-rendering="crispEdges"/>
<path d="M28.8288 27.7583H26.6193V26.5982H28.8288C29.2135 26.5982 29.5244 26.5361 29.7615 26.4117C29.9986 26.2873 30.1715 26.1163 30.2803 25.8987C30.393 25.6772 30.4494 25.4245 30.4494 25.1408C30.4494 24.8727 30.393 24.622 30.2803 24.3888C30.1715 24.1517 29.9986 23.9613 29.7615 23.8175C29.5244 23.6737 29.2135 23.6018 28.8288 23.6018H27.0682V30.9238H25.605V22.4359H28.8288C29.4856 22.4359 30.0433 22.5525 30.5019 22.7857C30.9643 23.015 31.3161 23.3336 31.557 23.7417C31.798 24.1459 31.9185 24.6084 31.9185 25.1292C31.9185 25.6772 31.798 26.1474 31.557 26.5399C31.3161 26.9325 30.9643 27.2337 30.5019 27.4435C30.0433 27.6534 29.4856 27.7583 28.8288 27.7583ZM32.927 27.84V27.7059C32.927 27.2512 32.9931 26.8295 33.1252 26.4408C33.2573 26.0483 33.4478 25.7083 33.6965 25.4207C33.9491 25.1292 34.2561 24.9038 34.6176 24.7444C34.9829 24.5812 35.3949 24.4996 35.8535 24.4996C36.3159 24.4996 36.7279 24.5812 37.0893 24.7444C37.4547 24.9038 37.7636 25.1292 38.0163 25.4207C38.2689 25.7083 38.4613 26.0483 38.5934 26.4408C38.7255 26.8295 38.7916 27.2512 38.7916 27.7059V27.84C38.7916 28.2947 38.7255 28.7163 38.5934 29.105C38.4613 29.4936 38.2689 29.8337 38.0163 30.1252C37.7636 30.4128 37.4566 30.6382 37.0952 30.8014C36.7337 30.9607 36.3237 31.0404 35.8651 31.0404C35.4026 31.0404 34.9887 30.9607 34.6234 30.8014C34.262 30.6382 33.9549 30.4128 33.7023 30.1252C33.4497 29.8337 33.2573 29.4936 33.1252 29.105C32.9931 28.7163 32.927 28.2947 32.927 27.84ZM34.3319 27.7059V27.84C34.3319 28.1237 34.3611 28.3918 34.4194 28.6444C34.4777 28.8971 34.569 29.1186 34.6934 29.309C34.8177 29.4995 34.9771 29.6491 35.1714 29.7579C35.3657 29.8667 35.597 29.9211 35.8651 29.9211C36.1255 29.9211 36.3509 29.8667 36.5414 29.7579C36.7357 29.6491 36.895 29.4995 37.0194 29.309C37.1438 29.1186 37.2351 28.8971 37.2934 28.6444C37.3556 28.3918 37.3867 28.1237 37.3867 27.84V27.7059C37.3867 27.426 37.3556 27.1618 37.2934 26.913C37.2351 26.6604 37.1418 26.437 37.0136 26.2426C36.8892 26.0483 36.7299 25.8967 36.5355 25.7879C36.3451 25.6752 36.1177 25.6189 35.8535 25.6189C35.5892 25.6189 35.3599 25.6752 35.1656 25.7879C34.9751 25.8967 34.8177 26.0483 34.6934 26.2426C34.569 26.437 34.4777 26.6604 34.4194 26.913C34.3611 27.1618 34.3319 27.426 34.3319 27.7059ZM41.8696 29.5247L43.3271 24.6162H44.2248L43.98 26.0852L42.5109 30.9238H41.7064L41.8696 29.5247ZM41.0127 24.6162L42.1495 29.548L42.2427 30.9238H41.345L39.6369 24.6162H41.0127ZM45.589 29.4897L46.6908 24.6162H48.0607L46.3585 30.9238H45.4607L45.589 29.4897ZM44.3764 24.6162L45.8163 29.4664L45.997 30.9238H45.1925L43.706 26.0794L43.4611 24.6162H44.3764ZM51.9841 31.0404C51.5177 31.0404 51.096 30.9646 50.719 30.8131C50.3459 30.6576 50.0272 30.4419 49.763 30.166C49.5026 29.89 49.3024 29.5655 49.1625 29.1924C49.0226 28.8193 48.9526 28.4171 48.9526 27.9857V27.7525C48.9526 27.2589 49.0245 26.812 49.1683 26.4117C49.3121 26.0114 49.5123 25.6694 49.7688 25.3857C50.0253 25.0981 50.3284 24.8785 50.6782 24.7269C51.028 24.5754 51.4069 24.4996 51.815 24.4996C52.2658 24.4996 52.6603 24.5754 52.9984 24.7269C53.3365 24.8785 53.6164 25.0923 53.8379 25.3682C54.0633 25.6402 54.2304 25.9648 54.3392 26.3417C54.4519 26.7187 54.5083 27.1346 54.5083 27.5893V28.1897H49.6347V27.1812H53.1208V27.0704C53.1131 26.8178 53.0625 26.5808 52.9693 26.3592C52.8799 26.1377 52.7419 25.9589 52.5554 25.8229C52.3688 25.6869 52.1201 25.6189 51.8092 25.6189C51.576 25.6189 51.3681 25.6694 51.1854 25.7704C51.0066 25.8676 50.857 26.0094 50.7365 26.196C50.616 26.3825 50.5228 26.608 50.4567 26.8722C50.3945 27.1326 50.3634 27.426 50.3634 27.7525V27.9857C50.3634 28.2616 50.4003 28.5181 50.4742 28.7552C50.5519 28.9884 50.6646 29.1924 50.8123 29.3673C50.96 29.5422 51.1388 29.6802 51.3486 29.7812C51.5585 29.8784 51.7975 29.927 52.0657 29.927C52.4038 29.927 52.705 29.8589 52.9693 29.7229C53.2335 29.5869 53.4628 29.3945 53.6572 29.1458L54.3975 29.8628C54.2615 30.061 54.0847 30.2515 53.867 30.4341C53.6494 30.6129 53.3832 30.7587 53.0684 30.8714C52.7575 30.9841 52.396 31.0404 51.9841 31.0404ZM57.2016 25.8171V30.9238H55.7966V24.6162H57.1375L57.2016 25.8171ZM59.1312 24.5754L59.1195 25.8812C59.034 25.8657 58.9408 25.854 58.8397 25.8462C58.7425 25.8384 58.6454 25.8346 58.5482 25.8346C58.3073 25.8346 58.0955 25.8695 57.9128 25.9395C57.7301 26.0056 57.5766 26.1027 57.4523 26.231C57.3318 26.3553 57.2385 26.5069 57.1724 26.6857C57.1064 26.8645 57.0675 27.0646 57.0558 27.2861L56.7352 27.3095C56.7352 26.913 56.7741 26.5458 56.8518 26.2077C56.9295 25.8695 57.0461 25.5722 57.2016 25.3157C57.3609 25.0592 57.5591 24.8591 57.7962 24.7153C58.0372 24.5715 58.315 24.4996 58.6298 24.4996C58.7153 24.4996 58.8067 24.5073 58.9038 24.5229C59.0049 24.5384 59.0807 24.5559 59.1312 24.5754Z" fill="black" fill-opacity="0.87"/>
<path d="M114.285 89.9774C114.285 108.728 99.0847 123.929 80.3336 123.929C61.5826 123.929 46.3818 108.728 46.3818 89.9774C46.3818 71.2264 61.5826 56.0256 80.3336 56.0256C99.0847 56.0256 114.285 71.2264 114.285 89.9774Z" fill="#3F52DD"/>
<path d="M122.121 89.9773C122.121 113.055 103.412 131.764 80.3337 131.764C57.2555 131.764 38.5469 113.055 38.5469 89.9773C38.5469 66.8991 57.2555 48.1905 80.3337 48.1905C103.412 48.1905 122.121 66.8991 122.121 89.9773Z" fill="white" stroke="#3F52DD" stroke-width="0.746193"/>
<path d="M114.285 89.9774C114.285 108.728 99.0847 123.929 80.3336 123.929C61.5826 123.929 46.3818 108.728 46.3818 89.9774C46.3818 71.2264 61.5826 56.0256 80.3336 56.0256C99.0847 56.0256 114.285 71.2264 114.285 89.9774Z" fill="#3F52DD"/>
<path d="M79.2736 88.7629V89.4041C79.2736 90.2858 79.1587 91.0767 78.9289 91.7768C78.6992 92.4768 78.3705 93.0727 77.943 93.5643C77.5208 94.0559 77.0132 94.4327 76.42 94.6945C75.8269 94.951 75.1696 95.0793 74.4481 95.0793C73.7321 95.0793 73.0775 94.951 72.4843 94.6945C71.8965 94.4327 71.3861 94.0559 70.9533 93.5643C70.5204 93.0727 70.1838 92.4768 69.9433 91.7768C69.7082 91.0767 69.5906 90.2858 69.5906 89.4041V88.7629C69.5906 87.8811 69.7082 87.0929 69.9433 86.3982C70.1784 85.6982 70.5097 85.1023 70.9373 84.6107C71.3701 84.1137 71.8804 83.737 72.4683 83.4805C73.0614 83.2186 73.716 83.0877 74.4321 83.0877C75.1535 83.0877 75.8108 83.2186 76.404 83.4805C76.9972 83.737 77.5075 84.1137 77.935 84.6107C78.3625 85.1023 78.6911 85.6982 78.9209 86.3982C79.1561 87.0929 79.2736 87.8811 79.2736 88.7629ZM77.2617 89.4041V88.7468C77.2617 88.0949 77.1975 87.5204 77.0693 87.0234C76.9464 86.5211 76.762 86.1016 76.5162 85.765C76.2757 85.423 75.9792 85.1665 75.6265 84.9955C75.2738 84.8191 74.8757 84.7309 74.4321 84.7309C73.9886 84.7309 73.5931 84.8191 73.2458 84.9955C72.8984 85.1665 72.6019 85.423 72.356 85.765C72.1156 86.1016 71.9312 86.5211 71.803 87.0234C71.6747 87.5204 71.6106 88.0949 71.6106 88.7468V89.4041C71.6106 90.0561 71.6747 90.6332 71.803 91.1355C71.9312 91.6378 72.1182 92.0627 72.3641 92.41C72.6152 92.752 72.9145 93.0112 73.2618 93.1875C73.6092 93.3585 74.0046 93.444 74.4481 93.444C74.897 93.444 75.2951 93.3585 75.6425 93.1875C75.9898 93.0112 76.2838 92.752 76.5242 92.41C76.7647 92.0627 76.9464 91.6378 77.0693 91.1355C77.1975 90.6332 77.2617 90.0561 77.2617 89.4041ZM90.5438 83.248V94.9189H88.5318L83.2975 86.5585V94.9189H81.2856V83.248H83.2975L88.5478 91.6245V83.248H90.5438Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4488_87637" x="0.863953" y="0.0152285" width="158.939" height="158.939" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_87637"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_87637" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

50
ui-ngx/src/assets/widget/power-button/default-volume-layout.svg

@ -0,0 +1,50 @@
<svg width="160" height="159" viewBox="0 0 160 159" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4488_87673)">
<rect x="6.8335" y="3" width="147" height="147" rx="2.98477" fill="white" shape-rendering="crispEdges"/>
<path d="M28.8288 27.7583H26.6193V26.5982H28.8288C29.2135 26.5982 29.5244 26.5361 29.7615 26.4117C29.9986 26.2873 30.1715 26.1163 30.2803 25.8987C30.393 25.6772 30.4494 25.4245 30.4494 25.1408C30.4494 24.8727 30.393 24.622 30.2803 24.3888C30.1715 24.1517 29.9986 23.9613 29.7615 23.8175C29.5244 23.6737 29.2135 23.6018 28.8288 23.6018H27.0682V30.9238H25.605V22.4359H28.8288C29.4856 22.4359 30.0433 22.5525 30.5019 22.7857C30.9643 23.015 31.3161 23.3336 31.557 23.7417C31.798 24.1459 31.9185 24.6084 31.9185 25.1292C31.9185 25.6772 31.798 26.1474 31.557 26.5399C31.3161 26.9325 30.9643 27.2337 30.5019 27.4435C30.0433 27.6534 29.4856 27.7583 28.8288 27.7583ZM32.927 27.84V27.7059C32.927 27.2512 32.9931 26.8295 33.1252 26.4408C33.2573 26.0483 33.4478 25.7083 33.6965 25.4207C33.9491 25.1292 34.2561 24.9038 34.6176 24.7444C34.9829 24.5812 35.3949 24.4996 35.8535 24.4996C36.3159 24.4996 36.7279 24.5812 37.0893 24.7444C37.4547 24.9038 37.7636 25.1292 38.0163 25.4207C38.2689 25.7083 38.4613 26.0483 38.5934 26.4408C38.7255 26.8295 38.7916 27.2512 38.7916 27.7059V27.84C38.7916 28.2947 38.7255 28.7163 38.5934 29.105C38.4613 29.4936 38.2689 29.8337 38.0163 30.1252C37.7636 30.4128 37.4566 30.6382 37.0952 30.8014C36.7337 30.9607 36.3237 31.0404 35.8651 31.0404C35.4026 31.0404 34.9887 30.9607 34.6234 30.8014C34.262 30.6382 33.9549 30.4128 33.7023 30.1252C33.4497 29.8337 33.2573 29.4936 33.1252 29.105C32.9931 28.7163 32.927 28.2947 32.927 27.84ZM34.3319 27.7059V27.84C34.3319 28.1237 34.3611 28.3918 34.4194 28.6444C34.4777 28.8971 34.569 29.1186 34.6934 29.309C34.8177 29.4995 34.9771 29.6491 35.1714 29.7579C35.3657 29.8667 35.597 29.9211 35.8651 29.9211C36.1255 29.9211 36.3509 29.8667 36.5414 29.7579C36.7357 29.6491 36.895 29.4995 37.0194 29.309C37.1438 29.1186 37.2351 28.8971 37.2934 28.6444C37.3556 28.3918 37.3867 28.1237 37.3867 27.84V27.7059C37.3867 27.426 37.3556 27.1618 37.2934 26.913C37.2351 26.6604 37.1418 26.437 37.0136 26.2426C36.8892 26.0483 36.7299 25.8967 36.5355 25.7879C36.3451 25.6752 36.1177 25.6189 35.8535 25.6189C35.5892 25.6189 35.3599 25.6752 35.1656 25.7879C34.9751 25.8967 34.8177 26.0483 34.6934 26.2426C34.569 26.437 34.4777 26.6604 34.4194 26.913C34.3611 27.1618 34.3319 27.426 34.3319 27.7059ZM41.8696 29.5247L43.3271 24.6162H44.2248L43.98 26.0852L42.5109 30.9238H41.7064L41.8696 29.5247ZM41.0127 24.6162L42.1495 29.548L42.2427 30.9238H41.345L39.6369 24.6162H41.0127ZM45.589 29.4897L46.6908 24.6162H48.0607L46.3585 30.9238H45.4607L45.589 29.4897ZM44.3764 24.6162L45.8163 29.4664L45.997 30.9238H45.1925L43.706 26.0794L43.4611 24.6162H44.3764ZM51.9841 31.0404C51.5177 31.0404 51.096 30.9646 50.719 30.8131C50.3459 30.6576 50.0272 30.4419 49.763 30.166C49.5026 29.89 49.3024 29.5655 49.1625 29.1924C49.0226 28.8193 48.9526 28.4171 48.9526 27.9857V27.7525C48.9526 27.2589 49.0245 26.812 49.1683 26.4117C49.3121 26.0114 49.5123 25.6694 49.7688 25.3857C50.0253 25.0981 50.3284 24.8785 50.6782 24.7269C51.028 24.5754 51.4069 24.4996 51.815 24.4996C52.2658 24.4996 52.6603 24.5754 52.9984 24.7269C53.3365 24.8785 53.6164 25.0923 53.8379 25.3682C54.0633 25.6402 54.2304 25.9648 54.3392 26.3417C54.4519 26.7187 54.5083 27.1346 54.5083 27.5893V28.1897H49.6347V27.1812H53.1208V27.0704C53.1131 26.8178 53.0625 26.5808 52.9693 26.3592C52.8799 26.1377 52.7419 25.9589 52.5554 25.8229C52.3688 25.6869 52.1201 25.6189 51.8092 25.6189C51.576 25.6189 51.3681 25.6694 51.1854 25.7704C51.0066 25.8676 50.857 26.0094 50.7365 26.196C50.616 26.3825 50.5228 26.608 50.4567 26.8722C50.3945 27.1326 50.3634 27.426 50.3634 27.7525V27.9857C50.3634 28.2616 50.4003 28.5181 50.4742 28.7552C50.5519 28.9884 50.6646 29.1924 50.8123 29.3673C50.96 29.5422 51.1388 29.6802 51.3486 29.7812C51.5585 29.8784 51.7975 29.927 52.0657 29.927C52.4038 29.927 52.705 29.8589 52.9693 29.7229C53.2335 29.5869 53.4628 29.3945 53.6572 29.1458L54.3975 29.8628C54.2615 30.061 54.0847 30.2515 53.867 30.4341C53.6494 30.6129 53.3832 30.7587 53.0684 30.8714C52.7575 30.9841 52.396 31.0404 51.9841 31.0404ZM57.2016 25.8171V30.9238H55.7966V24.6162H57.1375L57.2016 25.8171ZM59.1312 24.5754L59.1195 25.8812C59.034 25.8657 58.9408 25.854 58.8397 25.8462C58.7425 25.8384 58.6454 25.8346 58.5482 25.8346C58.3073 25.8346 58.0955 25.8695 57.9128 25.9395C57.7301 26.0056 57.5766 26.1027 57.4523 26.231C57.3318 26.3553 57.2385 26.5069 57.1724 26.6857C57.1064 26.8645 57.0675 27.0646 57.0558 27.2861L56.7352 27.3095C56.7352 26.913 56.7741 26.5458 56.8518 26.2077C56.9295 25.8695 57.0461 25.5722 57.2016 25.3157C57.3609 25.0592 57.5591 24.8591 57.7962 24.7153C58.0372 24.5715 58.315 24.4996 58.6298 24.4996C58.7153 24.4996 58.8067 24.5073 58.9038 24.5229C59.0049 24.5384 59.0807 24.5559 59.1312 24.5754Z" fill="black" fill-opacity="0.87"/>
<g filter="url(#filter1_i_4488_87673)">
<path d="M115.032 89.9774C115.032 108.728 99.4969 123.929 80.3337 123.929C61.1706 123.929 45.6357 108.728 45.6357 89.9774C45.6357 71.2264 61.1706 56.0256 80.3337 56.0256C99.4969 56.0256 115.032 71.2264 115.032 89.9774Z" fill="#3F52DD"/>
</g>
<path d="M114.285 89.9774C114.285 108.301 99.1001 123.183 80.3337 123.183C61.5673 123.183 46.3819 108.301 46.3819 89.9774C46.3819 71.6537 61.5673 56.7718 80.3337 56.7718C99.1001 56.7718 114.285 71.6537 114.285 89.9774Z" stroke="white" stroke-width="1.49239"/>
<g filter="url(#filter2_d_4488_87673)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M80.3337 131.391C103.618 131.391 122.494 112.849 122.494 89.9772C122.494 67.105 103.618 48.5635 80.3337 48.5635C57.0495 48.5635 38.1738 67.105 38.1738 89.9772C38.1738 112.849 57.0495 131.391 80.3337 131.391ZM80.3335 123.929C99.4967 123.929 115.031 108.728 115.031 89.9774C115.031 71.2263 99.4967 56.0256 80.3335 56.0256C61.1703 56.0256 45.6355 71.2263 45.6355 89.9774C45.6355 108.728 61.1703 123.929 80.3335 123.929Z" fill="url(#paint0_linear_4488_87673)"/>
</g>
<path d="M79.1079 89.4611V90.1985C79.1079 91.0749 78.9983 91.8605 78.7792 92.5552C78.5601 93.2499 78.2449 93.8404 77.8334 94.3267C77.4219 94.8129 76.9276 95.1843 76.3505 95.4408C75.7787 95.6973 75.1374 95.8256 74.4267 95.8256C73.7373 95.8256 73.1041 95.6973 72.527 95.4408C71.9552 95.1843 71.4582 94.8129 71.036 94.3267C70.6192 93.8404 70.2959 93.2499 70.0661 92.5552C69.8363 91.8605 69.7215 91.0749 69.7215 90.1985V89.4611C69.7215 88.5847 69.8337 87.8018 70.0581 87.1125C70.2879 86.4178 70.6112 85.8273 71.028 85.341C71.4448 84.8494 71.9391 84.4753 72.5109 84.2188C73.0881 83.9623 73.7213 83.834 74.4107 83.834C75.1214 83.834 75.7627 83.9623 76.3344 84.2188C76.9116 84.4753 77.4059 84.8494 77.8174 85.341C78.2342 85.8273 78.5521 86.4178 78.7712 87.1125C78.9957 87.8018 79.1079 88.5847 79.1079 89.4611ZM77.5769 90.1985V89.4451C77.5769 88.7504 77.5047 88.1358 77.3605 87.6014C77.2215 87.0671 77.0158 86.6182 76.7432 86.2548C76.4707 85.8914 76.1367 85.6162 75.7413 85.4292C75.3512 85.2421 74.9076 85.1486 74.4107 85.1486C73.9297 85.1486 73.4942 85.2421 73.1041 85.4292C72.7193 85.6162 72.388 85.8914 72.1101 86.2548C71.8376 86.6182 71.6265 87.0671 71.4769 87.6014C71.3273 88.1358 71.2525 88.7504 71.2525 89.4451V90.1985C71.2525 90.8986 71.3273 91.5185 71.4769 92.0582C71.6265 92.5926 71.8403 93.0441 72.1182 93.4129C72.4014 93.7762 72.7354 94.0514 73.1201 94.2385C73.5102 94.4255 73.9457 94.519 74.4267 94.519C74.929 94.519 75.3752 94.4255 75.7653 94.2385C76.1554 94.0514 76.4841 93.7762 76.7513 93.4129C77.0238 93.0441 77.2295 92.5926 77.3685 92.0582C77.5074 91.5185 77.5769 90.8986 77.5769 90.1985ZM90.4021 83.9944V95.6653H88.847L82.9715 86.6636V95.6653H81.4244V83.9944H82.9715L88.8711 93.0201V83.9944H90.4021Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4488_87673" x="0.863953" y="0.0152285" width="158.939" height="158.939" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_87673"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_87673" result="shape"/>
</filter>
<filter id="filter1_i_4488_87673" x="41.9048" y="56.0256" width="73.127" height="71.6345" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3.73096" dy="3.73096"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_4488_87673"/>
</filter>
<filter id="filter2_d_4488_87673" x="32.2043" y="45.5787" width="96.2589" height="94.7665" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_87673"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_87673" result="shape"/>
</filter>
<linearGradient id="paint0_linear_4488_87673" x1="54.8859" y1="123.183" x2="102.361" y2="55.5962" gradientUnits="userSpaceOnUse">
<stop stop-color="#CCCCCC"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

23
ui-ngx/src/assets/widget/power-button/outlined-layout.svg

@ -0,0 +1,23 @@
<svg width="160" height="159" viewBox="0 0 160 159" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4488_87619)">
<rect x="6.16699" y="3" width="147" height="147" rx="2.98477" fill="white" shape-rendering="crispEdges"/>
<path d="M28.1618 27.7583H25.9523V26.5982H28.1618C28.5465 26.5982 28.8574 26.5361 29.0945 26.4117C29.3316 26.2873 29.5045 26.1163 29.6133 25.8987C29.7261 25.6772 29.7824 25.4245 29.7824 25.1408C29.7824 24.8727 29.7261 24.622 29.6133 24.3888C29.5045 24.1517 29.3316 23.9613 29.0945 23.8175C28.8574 23.6737 28.5465 23.6018 28.1618 23.6018H26.4012V30.9238H24.938V22.4359H28.1618C28.8186 22.4359 29.3763 22.5525 29.8349 22.7857C30.2974 23.015 30.6491 23.3336 30.89 23.7417C31.131 24.1459 31.2515 24.6084 31.2515 25.1292C31.2515 25.6772 31.131 26.1474 30.89 26.5399C30.6491 26.9325 30.2974 27.2337 29.8349 27.4435C29.3763 27.6534 28.8186 27.7583 28.1618 27.7583ZM32.26 27.84V27.7059C32.26 27.2512 32.3261 26.8295 32.4582 26.4408C32.5903 26.0483 32.7808 25.7083 33.0295 25.4207C33.2821 25.1292 33.5892 24.9038 33.9506 24.7444C34.3159 24.5812 34.7279 24.4996 35.1865 24.4996C35.649 24.4996 36.0609 24.5812 36.4224 24.7444C36.7877 24.9038 37.0966 25.1292 37.3493 25.4207C37.6019 25.7083 37.7943 26.0483 37.9264 26.4408C38.0585 26.8295 38.1246 27.2512 38.1246 27.7059V27.84C38.1246 28.2947 38.0585 28.7163 37.9264 29.105C37.7943 29.4936 37.6019 29.8337 37.3493 30.1252C37.0966 30.4128 36.7896 30.6382 36.4282 30.8014C36.0667 30.9607 35.6567 31.0404 35.1981 31.0404C34.7356 31.0404 34.3217 30.9607 33.9564 30.8014C33.595 30.6382 33.288 30.4128 33.0353 30.1252C32.7827 29.8337 32.5903 29.4936 32.4582 29.105C32.3261 28.7163 32.26 28.2947 32.26 27.84ZM33.6649 27.7059V27.84C33.6649 28.1237 33.6941 28.3918 33.7524 28.6444C33.8107 28.8971 33.902 29.1186 34.0264 29.309C34.1507 29.4995 34.3101 29.6491 34.5044 29.7579C34.6987 29.8667 34.93 29.9211 35.1981 29.9211C35.4585 29.9211 35.6839 29.8667 35.8744 29.7579C36.0687 29.6491 36.228 29.4995 36.3524 29.309C36.4768 29.1186 36.5681 28.8971 36.6264 28.6444C36.6886 28.3918 36.7197 28.1237 36.7197 27.84V27.7059C36.7197 27.426 36.6886 27.1618 36.6264 26.913C36.5681 26.6604 36.4748 26.437 36.3466 26.2426C36.2222 26.0483 36.0629 25.8967 35.8685 25.7879C35.6781 25.6752 35.4507 25.6189 35.1865 25.6189C34.9222 25.6189 34.6929 25.6752 34.4986 25.7879C34.3081 25.8967 34.1507 26.0483 34.0264 26.2426C33.902 26.437 33.8107 26.6604 33.7524 26.913C33.6941 27.1618 33.6649 27.426 33.6649 27.7059ZM41.2027 29.5247L42.6601 24.6162H43.5578L43.313 26.0852L41.8439 30.9238H41.0394L41.2027 29.5247ZM40.3457 24.6162L41.4825 29.548L41.5757 30.9238H40.678L38.9699 24.6162H40.3457ZM44.922 29.4897L46.0238 24.6162H47.3937L45.6915 30.9238H44.7937L44.922 29.4897ZM43.7094 24.6162L45.1493 29.4664L45.33 30.9238H44.5255L43.039 26.0794L42.7941 24.6162H43.7094ZM51.3171 31.0404C50.8507 31.0404 50.429 30.9646 50.052 30.8131C49.6789 30.6576 49.3603 30.4419 49.096 30.166C48.8356 29.89 48.6354 29.5655 48.4955 29.1924C48.3556 28.8193 48.2857 28.4171 48.2857 27.9857V27.7525C48.2857 27.2589 48.3576 26.812 48.5014 26.4117C48.6451 26.0114 48.8453 25.6694 49.1018 25.3857C49.3583 25.0981 49.6614 24.8785 50.0112 24.7269C50.361 24.5754 50.7399 24.4996 51.148 24.4996C51.5988 24.4996 51.9933 24.5754 52.3314 24.7269C52.6695 24.8785 52.9494 25.0923 53.1709 25.3682C53.3963 25.6402 53.5634 25.9648 53.6722 26.3417C53.7849 26.7187 53.8413 27.1346 53.8413 27.5893V28.1897H48.9677V27.1812H52.4538V27.0704C52.4461 26.8178 52.3955 26.5808 52.3023 26.3592C52.2129 26.1377 52.0749 25.9589 51.8884 25.8229C51.7018 25.6869 51.4531 25.6189 51.1422 25.6189C50.909 25.6189 50.7011 25.6694 50.5184 25.7704C50.3396 25.8676 50.19 26.0094 50.0695 26.196C49.949 26.3825 49.8558 26.608 49.7897 26.8722C49.7275 27.1326 49.6964 27.426 49.6964 27.7525V27.9857C49.6964 28.2616 49.7333 28.5181 49.8072 28.7552C49.8849 28.9884 49.9976 29.1924 50.1453 29.3673C50.293 29.5422 50.4718 29.6802 50.6816 29.7812C50.8915 29.8784 51.1305 29.927 51.3987 29.927C51.7368 29.927 52.038 29.8589 52.3023 29.7229C52.5665 29.5869 52.7958 29.3945 52.9902 29.1458L53.7305 29.8628C53.5945 30.061 53.4177 30.2515 53.2 30.4341C52.9824 30.6129 52.7162 30.7587 52.4014 30.8714C52.0905 30.9841 51.729 31.0404 51.3171 31.0404ZM56.5346 25.8171V30.9238H55.1296V24.6162H56.4705L56.5346 25.8171ZM58.4642 24.5754L58.4525 25.8812C58.367 25.8657 58.2738 25.854 58.1727 25.8462C58.0756 25.8384 57.9784 25.8346 57.8812 25.8346C57.6403 25.8346 57.4285 25.8695 57.2458 25.9395C57.0631 26.0056 56.9096 26.1027 56.7853 26.231C56.6648 26.3553 56.5715 26.5069 56.5054 26.6857C56.4394 26.8645 56.4005 27.0646 56.3888 27.2861L56.0682 27.3095C56.0682 26.913 56.1071 26.5458 56.1848 26.2077C56.2625 25.8695 56.3791 25.5722 56.5346 25.3157C56.6939 25.0592 56.8921 24.8591 57.1292 24.7153C57.3702 24.5715 57.648 24.4996 57.9628 24.4996C58.0483 24.4996 58.1397 24.5073 58.2368 24.5229C58.3379 24.5384 58.4137 24.5559 58.4642 24.5754Z" fill="black" fill-opacity="0.87"/>
<path d="M112.873 89.9774C112.873 108.316 98.0061 123.183 79.6671 123.183C61.3282 123.183 46.4615 108.316 46.4615 89.9774C46.4615 71.6385 61.3282 56.7718 79.6671 56.7718C98.0061 56.7718 112.873 71.6385 112.873 89.9774Z" stroke="#3F52DD" stroke-width="1.49239"/>
<path d="M121.454 89.9773C121.454 113.055 102.745 131.764 79.6672 131.764C56.589 131.764 37.8804 113.055 37.8804 89.9773C37.8804 66.8991 56.589 48.1905 79.6672 48.1905C102.745 48.1905 121.454 66.8991 121.454 89.9773Z" stroke="#3F52DD" stroke-width="0.746193"/>
<path d="M112.873 89.9774C112.873 108.316 98.0061 123.183 79.6671 123.183C61.3282 123.183 46.4615 108.316 46.4615 89.9774C46.4615 71.6385 61.3282 56.7718 79.6671 56.7718C98.0061 56.7718 112.873 71.6385 112.873 89.9774Z" stroke="#3F52DD" stroke-width="1.49239"/>
<path d="M110.634 89.9777C110.634 107.08 96.7698 120.945 79.6672 120.945C62.5646 120.945 48.7002 107.08 48.7002 89.9777C48.7002 72.8751 62.5646 59.0107 79.6672 59.0107C96.7698 59.0107 110.634 72.8751 110.634 89.9777Z" fill="#3F52DD"/>
<path d="M78.6071 89.5094V90.1507C78.6071 91.0324 78.4922 91.8233 78.2624 92.5234C78.0327 93.2234 77.704 93.8192 77.2765 94.3109C76.8543 94.8025 76.3467 95.1792 75.7535 95.4411C75.1604 95.6976 74.5031 95.8258 73.7816 95.8258C73.0656 95.8258 72.411 95.6976 71.8178 95.4411C71.23 95.1792 70.7196 94.8025 70.2868 94.3109C69.8539 93.8192 69.5173 93.2234 69.2768 92.5234C69.0417 91.8233 68.9241 91.0324 68.9241 90.1507V89.5094C68.9241 88.6277 69.0417 87.8395 69.2768 87.1448C69.5119 86.4447 69.8432 85.8489 70.2707 85.3573C70.7036 84.8603 71.2139 84.4836 71.8018 84.2271C72.3949 83.9652 73.0495 83.8343 73.7656 83.8343C74.487 83.8343 75.1443 83.9652 75.7375 84.2271C76.3307 84.4836 76.841 84.8603 77.2685 85.3573C77.696 85.8489 78.0246 86.4447 78.2544 87.1448C78.4896 87.8395 78.6071 88.6277 78.6071 89.5094ZM76.5952 90.1507V89.4934C76.5952 88.8415 76.531 88.267 76.4028 87.77C76.2799 87.2677 76.0955 86.8482 75.8497 86.5115C75.6092 86.1695 75.3127 85.913 74.96 85.742C74.6073 85.5657 74.2092 85.4775 73.7656 85.4775C73.3221 85.4775 72.9266 85.5657 72.5793 85.742C72.2319 85.913 71.9354 86.1695 71.6895 86.5115C71.4491 86.8482 71.2647 87.2677 71.1364 87.77C71.0082 88.267 70.9441 88.8415 70.9441 89.4934V90.1507C70.9441 90.8026 71.0082 91.3798 71.1364 91.8821C71.2647 92.3844 71.4517 92.8093 71.6976 93.1566C71.9487 93.4986 72.248 93.7578 72.5953 93.9341C72.9427 94.1051 73.3381 94.1906 73.7816 94.1906C74.2305 94.1906 74.6286 94.1051 74.976 93.9341C75.3233 93.7578 75.6173 93.4986 75.8577 93.1566C76.0982 92.8093 76.2799 92.3844 76.4028 91.8821C76.531 91.3798 76.5952 90.8026 76.5952 90.1507ZM89.8773 83.9946V95.6655H87.8653L82.631 87.3051V95.6655H80.6191V83.9946H82.631L87.8813 92.3711V83.9946H89.8773Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4488_87619" x="0.197449" y="0.0152285" width="158.939" height="158.939" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_87619"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_87619" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.2 KiB

37
ui-ngx/src/assets/widget/power-button/outlined-volume-layout.svg

@ -0,0 +1,37 @@
<svg width="160" height="159" viewBox="0 0 160 159" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4488_88106)">
<rect x="6.16699" y="3" width="147" height="147" rx="2.98477" fill="white" shape-rendering="crispEdges"/>
<path d="M28.1623 27.7583H25.9528V26.5982H28.1623C28.547 26.5982 28.8579 26.5361 29.095 26.4117C29.3321 26.2873 29.505 26.1163 29.6138 25.8987C29.7265 25.6772 29.7829 25.4245 29.7829 25.1408C29.7829 24.8727 29.7265 24.622 29.6138 24.3888C29.505 24.1517 29.3321 23.9613 29.095 23.8175C28.8579 23.6737 28.547 23.6018 28.1623 23.6018H26.4017V30.9238H24.9385V22.4359H28.1623C28.8191 22.4359 29.3768 22.5525 29.8354 22.7857C30.2978 23.015 30.6496 23.3336 30.8905 23.7417C31.1315 24.1459 31.252 24.6084 31.252 25.1292C31.252 25.6772 31.1315 26.1474 30.8905 26.5399C30.6496 26.9325 30.2978 27.2337 29.8354 27.4435C29.3768 27.6534 28.8191 27.7583 28.1623 27.7583ZM32.2605 27.84V27.7059C32.2605 27.2512 32.3266 26.8295 32.4587 26.4408C32.5908 26.0483 32.7813 25.7083 33.03 25.4207C33.2826 25.1292 33.5896 24.9038 33.9511 24.7444C34.3164 24.5812 34.7284 24.4996 35.187 24.4996C35.6494 24.4996 36.0614 24.5812 36.4228 24.7444C36.7882 24.9038 37.0971 25.1292 37.3498 25.4207C37.6024 25.7083 37.7948 26.0483 37.9269 26.4408C38.059 26.8295 38.1251 27.2512 38.1251 27.7059V27.84C38.1251 28.2947 38.059 28.7163 37.9269 29.105C37.7948 29.4936 37.6024 29.8337 37.3498 30.1252C37.0971 30.4128 36.7901 30.6382 36.4287 30.8014C36.0672 30.9607 35.6572 31.0404 35.1986 31.0404C34.7361 31.0404 34.3222 30.9607 33.9569 30.8014C33.5955 30.6382 33.2884 30.4128 33.0358 30.1252C32.7832 29.8337 32.5908 29.4936 32.4587 29.105C32.3266 28.7163 32.2605 28.2947 32.2605 27.84ZM33.6654 27.7059V27.84C33.6654 28.1237 33.6946 28.3918 33.7529 28.6444C33.8112 28.8971 33.9025 29.1186 34.0269 29.309C34.1512 29.4995 34.3106 29.6491 34.5049 29.7579C34.6992 29.8667 34.9305 29.9211 35.1986 29.9211C35.459 29.9211 35.6844 29.8667 35.8749 29.7579C36.0692 29.6491 36.2285 29.4995 36.3529 29.309C36.4773 29.1186 36.5686 28.8971 36.6269 28.6444C36.6891 28.3918 36.7202 28.1237 36.7202 27.84V27.7059C36.7202 27.426 36.6891 27.1618 36.6269 26.913C36.5686 26.6604 36.4753 26.437 36.3471 26.2426C36.2227 26.0483 36.0633 25.8967 35.869 25.7879C35.6786 25.6752 35.4512 25.6189 35.187 25.6189C34.9227 25.6189 34.6934 25.6752 34.4991 25.7879C34.3086 25.8967 34.1512 26.0483 34.0269 26.2426C33.9025 26.437 33.8112 26.6604 33.7529 26.913C33.6946 27.1618 33.6654 27.426 33.6654 27.7059ZM41.2031 29.5247L42.6605 24.6162H43.5583L43.3135 26.0852L41.8444 30.9238H41.0399L41.2031 29.5247ZM40.3462 24.6162L41.483 29.548L41.5762 30.9238H40.6785L38.9704 24.6162H40.3462ZM44.9224 29.4897L46.0242 24.6162H47.3942L45.692 30.9238H44.7942L44.9224 29.4897ZM43.7099 24.6162L45.1498 29.4664L45.3305 30.9238H44.526L43.0395 26.0794L42.7946 24.6162H43.7099ZM51.3176 31.0404C50.8512 31.0404 50.4295 30.9646 50.0525 30.8131C49.6794 30.6576 49.3607 30.4419 49.0965 30.166C48.8361 29.89 48.6359 29.5655 48.496 29.1924C48.3561 28.8193 48.2861 28.4171 48.2861 27.9857V27.7525C48.2861 27.2589 48.358 26.812 48.5018 26.4117C48.6456 26.0114 48.8458 25.6694 49.1023 25.3857C49.3588 25.0981 49.6619 24.8785 50.0117 24.7269C50.3615 24.5754 50.7404 24.4996 51.1485 24.4996C51.5993 24.4996 51.9938 24.5754 52.3319 24.7269C52.67 24.8785 52.9498 25.0923 53.1714 25.3682C53.3968 25.6402 53.5639 25.9648 53.6727 26.3417C53.7854 26.7187 53.8418 27.1346 53.8418 27.5893V28.1897H48.9682V27.1812H52.4543V27.0704C52.4466 26.8178 52.396 26.5808 52.3028 26.3592C52.2134 26.1377 52.0754 25.9589 51.8889 25.8229C51.7023 25.6869 51.4536 25.6189 51.1427 25.6189C50.9095 25.6189 50.7016 25.6694 50.5189 25.7704C50.3401 25.8676 50.1905 26.0094 50.07 26.196C49.9495 26.3825 49.8563 26.608 49.7902 26.8722C49.728 27.1326 49.6969 27.426 49.6969 27.7525V27.9857C49.6969 28.2616 49.7338 28.5181 49.8077 28.7552C49.8854 28.9884 49.9981 29.1924 50.1458 29.3673C50.2935 29.5422 50.4723 29.6802 50.6821 29.7812C50.892 29.8784 51.131 29.927 51.3992 29.927C51.7373 29.927 52.0385 29.8589 52.3028 29.7229C52.567 29.5869 52.7963 29.3945 52.9907 29.1458L53.731 29.8628C53.595 30.061 53.4182 30.2515 53.2005 30.4341C52.9829 30.6129 52.7167 30.7587 52.4019 30.8714C52.091 30.9841 51.7295 31.0404 51.3176 31.0404ZM56.5351 25.8171V30.9238H55.1301V24.6162H56.4709L56.5351 25.8171ZM58.4647 24.5754L58.453 25.8812C58.3675 25.8657 58.2742 25.854 58.1732 25.8462C58.076 25.8384 57.9789 25.8346 57.8817 25.8346C57.6408 25.8346 57.429 25.8695 57.2463 25.9395C57.0636 26.0056 56.9101 26.1027 56.7857 26.231C56.6653 26.3553 56.572 26.5069 56.5059 26.6857C56.4399 26.8645 56.401 27.0646 56.3893 27.2861L56.0687 27.3095C56.0687 26.913 56.1076 26.5458 56.1853 26.2077C56.263 25.8695 56.3796 25.5722 56.5351 25.3157C56.6944 25.0592 56.8926 24.8591 57.1297 24.7153C57.3707 24.5715 57.6485 24.4996 57.9633 24.4996C58.0488 24.4996 58.1402 24.5073 58.2373 24.5229C58.3384 24.5384 58.4142 24.5559 58.4647 24.5754Z" fill="black" fill-opacity="0.87"/>
<g filter="url(#filter1_d_4488_88106)">
<path d="M120.708 89.9772C120.708 112.849 102.333 131.391 79.6671 131.391C57.001 131.391 38.6265 112.849 38.6265 89.9772C38.6265 67.105 57.001 48.5635 79.6671 48.5635C102.333 48.5635 120.708 67.105 120.708 89.9772Z" fill="url(#paint0_linear_4488_88106)"/>
</g>
<path d="M109.515 89.9775C109.515 106.894 95.964 120.571 79.2938 120.571C62.6236 120.571 49.073 106.894 49.073 89.9775C49.073 73.0605 62.6236 59.3835 79.2938 59.3835C95.964 59.3835 109.515 73.0605 109.515 89.9775Z" fill="#3F52DD" stroke="white" stroke-width="3.73096"/>
<path d="M78.0294 91.0495V91.6026C78.0294 92.4896 77.9091 93.2859 77.6687 93.9913C77.4282 94.6966 77.0888 95.2978 76.6507 95.7948C76.2125 96.2864 75.6888 96.6632 75.0796 96.925C74.4757 97.1869 73.8051 97.3178 73.0676 97.3178C72.3355 97.3178 71.6649 97.1869 71.0557 96.925C70.4518 96.6632 69.9281 96.2864 69.4846 95.7948C69.041 95.2978 68.6964 94.6966 68.4505 93.9913C68.2101 93.2859 68.0898 92.4896 68.0898 91.6026V91.0495C68.0898 90.1571 68.2101 89.3608 68.4505 88.6608C68.691 87.9554 69.0304 87.3542 69.4685 86.8572C69.9121 86.3603 70.4358 85.9809 71.0396 85.719C71.6488 85.4572 72.3195 85.3262 73.0516 85.3262C73.789 85.3262 74.4597 85.4572 75.0635 85.719C75.6727 85.9809 76.1964 86.3603 76.6346 86.8572C77.0782 87.3542 77.4202 87.9554 77.6606 88.6608C77.9065 89.3608 78.0294 90.1571 78.0294 91.0495ZM75.6006 91.6026V91.0334C75.6006 90.4136 75.5445 89.8685 75.4323 89.3982C75.32 88.928 75.1544 88.5325 74.9353 88.2119C74.7162 87.8913 74.449 87.6508 74.1337 87.4905C73.8184 87.3248 73.4577 87.242 73.0516 87.242C72.6455 87.242 72.2847 87.3248 71.9695 87.4905C71.6595 87.6508 71.395 87.8913 71.1759 88.2119C70.9621 88.5325 70.7992 88.928 70.6869 89.3982C70.5747 89.8685 70.5186 90.4136 70.5186 91.0334V91.6026C70.5186 92.2171 70.5747 92.7622 70.6869 93.2378C70.7992 93.708 70.9648 94.1061 71.1839 94.4321C71.403 94.7527 71.6702 94.9959 71.9855 95.1616C72.3008 95.3272 72.6615 95.41 73.0676 95.41C73.4737 95.41 73.8345 95.3272 74.1497 95.1616C74.465 94.9959 74.7295 94.7527 74.9433 94.4321C75.1571 94.1061 75.32 93.708 75.4323 93.2378C75.5445 92.7622 75.6006 92.2171 75.6006 91.6026ZM89.2594 85.4865V97.1575H86.8547L82.1655 89.3341V97.1575H79.7608V85.4865H82.1655L86.8627 93.3179V85.4865H89.2594Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4488_88106" x="0.197449" y="0.0152285" width="158.939" height="158.939" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_88106"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_88106" result="shape"/>
</filter>
<filter id="filter1_d_4488_88106" x="32.6569" y="45.5787" width="94.0201" height="94.7665" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_88106"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_88106" result="shape"/>
</filter>
<linearGradient id="paint0_linear_4488_88106" x1="54.8948" y1="123.183" x2="102.789" y2="56.8087" gradientUnits="userSpaceOnUse">
<stop stop-color="#CCCCCC"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.7 KiB

20
ui-ngx/src/assets/widget/power-button/simplified-layout.svg

@ -0,0 +1,20 @@
<svg width="160" height="159" viewBox="0 0 160 159" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4488_87655)">
<rect x="6.5" y="3" width="147" height="147" rx="2.98477" fill="white" shape-rendering="crispEdges"/>
<path d="M28.4953 27.7583H26.2858V26.5982H28.4953C28.88 26.5982 29.1909 26.5361 29.428 26.4117C29.6651 26.2873 29.838 26.1163 29.9468 25.8987C30.0595 25.6772 30.1159 25.4245 30.1159 25.1408C30.1159 24.8727 30.0595 24.622 29.9468 24.3888C29.838 24.1517 29.6651 23.9613 29.428 23.8175C29.1909 23.6737 28.88 23.6018 28.4953 23.6018H26.7347V30.9238H25.2715V22.4359H28.4953C29.1521 22.4359 29.7098 22.5525 30.1684 22.7857C30.6309 23.015 30.9826 23.3336 31.2235 23.7417C31.4645 24.1459 31.585 24.6084 31.585 25.1292C31.585 25.6772 31.4645 26.1474 31.2235 26.5399C30.9826 26.9325 30.6309 27.2337 30.1684 27.4435C29.7098 27.6534 29.1521 27.7583 28.4953 27.7583ZM32.5935 27.84V27.7059C32.5935 27.2512 32.6596 26.8295 32.7917 26.4408C32.9238 26.0483 33.1143 25.7083 33.363 25.4207C33.6156 25.1292 33.9227 24.9038 34.2841 24.7444C34.6494 24.5812 35.0614 24.4996 35.52 24.4996C35.9825 24.4996 36.3944 24.5812 36.7559 24.7444C37.1212 24.9038 37.4301 25.1292 37.6828 25.4207C37.9354 25.7083 38.1278 26.0483 38.2599 26.4408C38.392 26.8295 38.4581 27.2512 38.4581 27.7059V27.84C38.4581 28.2947 38.392 28.7163 38.2599 29.105C38.1278 29.4936 37.9354 29.8337 37.6828 30.1252C37.4301 30.4128 37.1231 30.6382 36.7617 30.8014C36.4002 30.9607 35.9902 31.0404 35.5316 31.0404C35.0691 31.0404 34.6552 30.9607 34.2899 30.8014C33.9285 30.6382 33.6215 30.4128 33.3688 30.1252C33.1162 29.8337 32.9238 29.4936 32.7917 29.105C32.6596 28.7163 32.5935 28.2947 32.5935 27.84ZM33.9984 27.7059V27.84C33.9984 28.1237 34.0276 28.3918 34.0859 28.6444C34.1442 28.8971 34.2355 29.1186 34.3599 29.309C34.4842 29.4995 34.6436 29.6491 34.8379 29.7579C35.0322 29.8667 35.2635 29.9211 35.5316 29.9211C35.792 29.9211 36.0174 29.8667 36.2079 29.7579C36.4022 29.6491 36.5615 29.4995 36.6859 29.309C36.8103 29.1186 36.9016 28.8971 36.9599 28.6444C37.0221 28.3918 37.0532 28.1237 37.0532 27.84V27.7059C37.0532 27.426 37.0221 27.1618 36.9599 26.913C36.9016 26.6604 36.8083 26.437 36.6801 26.2426C36.5557 26.0483 36.3964 25.8967 36.202 25.7879C36.0116 25.6752 35.7842 25.6189 35.52 25.6189C35.2557 25.6189 35.0264 25.6752 34.8321 25.7879C34.6416 25.8967 34.4842 26.0483 34.3599 26.2426C34.2355 26.437 34.1442 26.6604 34.0859 26.913C34.0276 27.1618 33.9984 27.426 33.9984 27.7059ZM41.5361 29.5247L42.9936 24.6162H43.8913L43.6465 26.0852L42.1774 30.9238H41.3729L41.5361 29.5247ZM40.6792 24.6162L41.816 29.548L41.9092 30.9238H41.0115L39.3034 24.6162H40.6792ZM45.2555 29.4897L46.3573 24.6162H47.7272L46.025 30.9238H45.1272L45.2555 29.4897ZM44.0429 24.6162L45.4828 29.4664L45.6635 30.9238H44.859L43.3725 26.0794L43.1276 24.6162H44.0429ZM51.6506 31.0404C51.1842 31.0404 50.7625 30.9646 50.3855 30.8131C50.0124 30.6576 49.6937 30.4419 49.4295 30.166C49.1691 29.89 48.9689 29.5655 48.829 29.1924C48.6891 28.8193 48.6192 28.4171 48.6192 27.9857V27.7525C48.6192 27.2589 48.6911 26.812 48.8348 26.4117C48.9786 26.0114 49.1788 25.6694 49.4353 25.3857C49.6918 25.0981 49.9949 24.8785 50.3447 24.7269C50.6945 24.5754 51.0734 24.4996 51.4815 24.4996C51.9323 24.4996 52.3268 24.5754 52.6649 24.7269C53.003 24.8785 53.2829 25.0923 53.5044 25.3682C53.7298 25.6402 53.8969 25.9648 54.0057 26.3417C54.1184 26.7187 54.1748 27.1346 54.1748 27.5893V28.1897H49.3012V27.1812H52.7873V27.0704C52.7796 26.8178 52.729 26.5808 52.6358 26.3592C52.5464 26.1377 52.4084 25.9589 52.2219 25.8229C52.0353 25.6869 51.7866 25.6189 51.4757 25.6189C51.2425 25.6189 51.0346 25.6694 50.8519 25.7704C50.6731 25.8676 50.5235 26.0094 50.403 26.196C50.2825 26.3825 50.1893 26.608 50.1232 26.8722C50.061 27.1326 50.0299 27.426 50.0299 27.7525V27.9857C50.0299 28.2616 50.0668 28.5181 50.1407 28.7552C50.2184 28.9884 50.3311 29.1924 50.4788 29.3673C50.6265 29.5422 50.8053 29.6802 51.0151 29.7812C51.225 29.8784 51.464 29.927 51.7322 29.927C52.0703 29.927 52.3715 29.8589 52.6358 29.7229C52.9 29.5869 53.1293 29.3945 53.3237 29.1458L54.064 29.8628C53.928 30.061 53.7512 30.2515 53.5335 30.4341C53.3159 30.6129 53.0497 30.7587 52.7349 30.8714C52.424 30.9841 52.0625 31.0404 51.6506 31.0404ZM56.8681 25.8171V30.9238H55.4631V24.6162H56.804L56.8681 25.8171ZM58.7977 24.5754L58.786 25.8812C58.7005 25.8657 58.6073 25.854 58.5062 25.8462C58.409 25.8384 58.3119 25.8346 58.2147 25.8346C57.9738 25.8346 57.762 25.8695 57.5793 25.9395C57.3966 26.0056 57.2431 26.1027 57.1188 26.231C56.9983 26.3553 56.905 26.5069 56.8389 26.6857C56.7729 26.8645 56.734 27.0646 56.7223 27.2861L56.4017 27.3095C56.4017 26.913 56.4406 26.5458 56.5183 26.2077C56.596 25.8695 56.7126 25.5722 56.8681 25.3157C57.0274 25.0592 57.2256 24.8591 57.4627 24.7153C57.7037 24.5715 57.9815 24.4996 58.2963 24.4996C58.3818 24.4996 58.4732 24.5073 58.5703 24.5229C58.6714 24.5384 58.7472 24.5559 58.7977 24.5754Z" fill="black" fill-opacity="0.87"/>
<path d="M122.16 89.9773C122.16 113.262 103.285 132.137 80.0002 132.137C56.716 132.137 37.8403 113.262 37.8403 89.9773C37.8403 66.693 56.716 47.8174 80.0002 47.8174C103.285 47.8174 122.16 66.693 122.16 89.9773Z" fill="#3F52DD"/>
<path d="M78.9401 88.7629V89.4041C78.9401 90.2858 78.8252 91.0767 78.5955 91.7768C78.3657 92.4768 78.037 93.0727 77.6095 93.5643C77.1874 94.0559 76.6797 94.4327 76.0865 94.6945C75.4934 94.951 74.8361 95.0793 74.1147 95.0793C73.3986 95.0793 72.744 94.951 72.1508 94.6945C71.563 94.4327 71.0526 94.0559 70.6198 93.5643C70.1869 93.0727 69.8503 92.4768 69.6098 91.7768C69.3747 91.0767 69.2571 90.2858 69.2571 89.4041V88.7629C69.2571 87.8811 69.3747 87.0929 69.6098 86.3982C69.8449 85.6982 70.1762 85.1023 70.6038 84.6107C71.0366 84.1137 71.5469 83.737 72.1348 83.4805C72.7279 83.2186 73.3825 83.0877 74.0986 83.0877C74.82 83.0877 75.4773 83.2186 76.0705 83.4805C76.6637 83.737 77.174 84.1137 77.6015 84.6107C78.029 85.1023 78.3577 85.6982 78.5874 86.3982C78.8226 87.0929 78.9401 87.8811 78.9401 88.7629ZM76.9282 89.4041V88.7468C76.9282 88.0949 76.8641 87.5204 76.7358 87.0234C76.6129 86.5211 76.4285 86.1016 76.1827 85.765C75.9422 85.423 75.6457 85.1665 75.293 84.9955C74.9403 84.8191 74.5422 84.7309 74.0986 84.7309C73.6551 84.7309 73.2596 84.8191 72.9123 84.9955C72.5649 85.1665 72.2684 85.423 72.0225 85.765C71.7821 86.1016 71.5977 86.5211 71.4695 87.0234C71.3412 87.5204 71.2771 88.0949 71.2771 88.7468V89.4041C71.2771 90.0561 71.3412 90.6332 71.4695 91.1355C71.5977 91.6378 71.7847 92.0627 72.0306 92.41C72.2817 92.752 72.581 93.0112 72.9283 93.1875C73.2757 93.3585 73.6711 93.444 74.1147 93.444C74.5635 93.444 74.9616 93.3585 75.309 93.1875C75.6563 93.0112 75.9503 92.752 76.1907 92.41C76.4312 92.0627 76.6129 91.6378 76.7358 91.1355C76.8641 90.6332 76.9282 90.0561 76.9282 89.4041ZM90.2103 83.248V94.9189H88.1983L82.964 86.5585V94.9189H80.9521V83.248H82.964L88.2143 91.6245V83.248H90.2103Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4488_87655" x="0.530457" y="0.0152285" width="158.939" height="158.939" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_87655"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_87655" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

33
ui-ngx/src/assets/widget/power-button/simplified-volume-layout.svg

@ -0,0 +1,33 @@
<svg width="160" height="159" viewBox="0 0 160 159" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4488_88089)">
<rect x="6.5" y="3" width="147" height="147" rx="2.98477" fill="white" shape-rendering="crispEdges"/>
<path d="M28.4953 27.7583H26.2858V26.5982H28.4953C28.88 26.5982 29.1909 26.5361 29.428 26.4117C29.6651 26.2873 29.838 26.1163 29.9468 25.8987C30.0595 25.6772 30.1159 25.4245 30.1159 25.1408C30.1159 24.8727 30.0595 24.622 29.9468 24.3888C29.838 24.1517 29.6651 23.9613 29.428 23.8175C29.1909 23.6737 28.88 23.6018 28.4953 23.6018H26.7347V30.9238H25.2715V22.4359H28.4953C29.1521 22.4359 29.7098 22.5525 30.1684 22.7857C30.6309 23.015 30.9826 23.3336 31.2235 23.7417C31.4645 24.1459 31.585 24.6084 31.585 25.1292C31.585 25.6772 31.4645 26.1474 31.2235 26.5399C30.9826 26.9325 30.6309 27.2337 30.1684 27.4435C29.7098 27.6534 29.1521 27.7583 28.4953 27.7583ZM32.5935 27.84V27.7059C32.5935 27.2512 32.6596 26.8295 32.7917 26.4408C32.9238 26.0483 33.1143 25.7083 33.363 25.4207C33.6156 25.1292 33.9227 24.9038 34.2841 24.7444C34.6494 24.5812 35.0614 24.4996 35.52 24.4996C35.9825 24.4996 36.3944 24.5812 36.7559 24.7444C37.1212 24.9038 37.4301 25.1292 37.6828 25.4207C37.9354 25.7083 38.1278 26.0483 38.2599 26.4408C38.392 26.8295 38.4581 27.2512 38.4581 27.7059V27.84C38.4581 28.2947 38.392 28.7163 38.2599 29.105C38.1278 29.4936 37.9354 29.8337 37.6828 30.1252C37.4301 30.4128 37.1231 30.6382 36.7617 30.8014C36.4002 30.9607 35.9902 31.0404 35.5316 31.0404C35.0691 31.0404 34.6552 30.9607 34.2899 30.8014C33.9285 30.6382 33.6215 30.4128 33.3688 30.1252C33.1162 29.8337 32.9238 29.4936 32.7917 29.105C32.6596 28.7163 32.5935 28.2947 32.5935 27.84ZM33.9984 27.7059V27.84C33.9984 28.1237 34.0276 28.3918 34.0859 28.6444C34.1442 28.8971 34.2355 29.1186 34.3599 29.309C34.4842 29.4995 34.6436 29.6491 34.8379 29.7579C35.0322 29.8667 35.2635 29.9211 35.5316 29.9211C35.792 29.9211 36.0174 29.8667 36.2079 29.7579C36.4022 29.6491 36.5615 29.4995 36.6859 29.309C36.8103 29.1186 36.9016 28.8971 36.9599 28.6444C37.0221 28.3918 37.0532 28.1237 37.0532 27.84V27.7059C37.0532 27.426 37.0221 27.1618 36.9599 26.913C36.9016 26.6604 36.8083 26.437 36.6801 26.2426C36.5557 26.0483 36.3964 25.8967 36.202 25.7879C36.0116 25.6752 35.7842 25.6189 35.52 25.6189C35.2557 25.6189 35.0264 25.6752 34.8321 25.7879C34.6416 25.8967 34.4842 26.0483 34.3599 26.2426C34.2355 26.437 34.1442 26.6604 34.0859 26.913C34.0276 27.1618 33.9984 27.426 33.9984 27.7059ZM41.5361 29.5247L42.9936 24.6162H43.8913L43.6465 26.0852L42.1774 30.9238H41.3729L41.5361 29.5247ZM40.6792 24.6162L41.816 29.548L41.9092 30.9238H41.0115L39.3034 24.6162H40.6792ZM45.2555 29.4897L46.3573 24.6162H47.7272L46.025 30.9238H45.1272L45.2555 29.4897ZM44.0429 24.6162L45.4828 29.4664L45.6635 30.9238H44.859L43.3725 26.0794L43.1276 24.6162H44.0429ZM51.6506 31.0404C51.1842 31.0404 50.7625 30.9646 50.3855 30.8131C50.0124 30.6576 49.6937 30.4419 49.4295 30.166C49.1691 29.89 48.9689 29.5655 48.829 29.1924C48.6891 28.8193 48.6192 28.4171 48.6192 27.9857V27.7525C48.6192 27.2589 48.6911 26.812 48.8348 26.4117C48.9786 26.0114 49.1788 25.6694 49.4353 25.3857C49.6918 25.0981 49.9949 24.8785 50.3447 24.7269C50.6945 24.5754 51.0734 24.4996 51.4815 24.4996C51.9323 24.4996 52.3268 24.5754 52.6649 24.7269C53.003 24.8785 53.2829 25.0923 53.5044 25.3682C53.7298 25.6402 53.8969 25.9648 54.0057 26.3417C54.1184 26.7187 54.1748 27.1346 54.1748 27.5893V28.1897H49.3012V27.1812H52.7873V27.0704C52.7796 26.8178 52.729 26.5808 52.6358 26.3592C52.5464 26.1377 52.4084 25.9589 52.2219 25.8229C52.0353 25.6869 51.7866 25.6189 51.4757 25.6189C51.2425 25.6189 51.0346 25.6694 50.8519 25.7704C50.6731 25.8676 50.5235 26.0094 50.403 26.196C50.2825 26.3825 50.1893 26.608 50.1232 26.8722C50.061 27.1326 50.0299 27.426 50.0299 27.7525V27.9857C50.0299 28.2616 50.0668 28.5181 50.1407 28.7552C50.2184 28.9884 50.3311 29.1924 50.4788 29.3673C50.6265 29.5422 50.8053 29.6802 51.0151 29.7812C51.225 29.8784 51.464 29.927 51.7322 29.927C52.0703 29.927 52.3715 29.8589 52.6358 29.7229C52.9 29.5869 53.1293 29.3945 53.3237 29.1458L54.064 29.8628C53.928 30.061 53.7512 30.2515 53.5335 30.4341C53.3159 30.6129 53.0497 30.7587 52.7349 30.8714C52.424 30.9841 52.0625 31.0404 51.6506 31.0404ZM56.8681 25.8171V30.9238H55.4631V24.6162H56.804L56.8681 25.8171ZM58.7977 24.5754L58.786 25.8812C58.7005 25.8657 58.6073 25.854 58.5062 25.8462C58.409 25.8384 58.3119 25.8346 58.2147 25.8346C57.9738 25.8346 57.762 25.8695 57.5793 25.9395C57.3966 26.0056 57.2431 26.1027 57.1188 26.231C56.9983 26.3553 56.905 26.5069 56.8389 26.6857C56.7729 26.8645 56.734 27.0646 56.7223 27.2861L56.4017 27.3095C56.4017 26.913 56.4406 26.5458 56.5183 26.2077C56.596 25.8695 56.7126 25.5722 56.8681 25.3157C57.0274 25.0592 57.2256 24.8591 57.4627 24.7153C57.7037 24.5715 57.9815 24.4996 58.2963 24.4996C58.3818 24.4996 58.4732 24.5073 58.5703 24.5229C58.6714 24.5384 58.7472 24.5559 58.7977 24.5754Z" fill="black" fill-opacity="0.87"/>
<g filter="url(#filter1_i_4488_88089)">
<path d="M121.041 89.9772C121.041 112.849 102.666 131.391 80.0001 131.391C57.334 131.391 38.9595 112.849 38.9595 89.9772C38.9595 67.105 57.334 48.5635 80.0001 48.5635C102.666 48.5635 121.041 67.105 121.041 89.9772Z" fill="white"/>
</g>
<path d="M120.295 89.9772C120.295 112.444 102.248 130.645 80.0001 130.645C57.7524 130.645 39.7057 112.444 39.7057 89.9772C39.7057 67.5108 57.7524 49.3097 80.0001 49.3097C102.248 49.3097 120.295 67.5108 120.295 89.9772Z" stroke="#FAFAFA" stroke-width="1.49239"/>
<path d="M78.9406 89.5089V90.1502C78.9406 91.0319 78.8257 91.8228 78.5959 92.5229C78.3662 93.2229 78.0375 93.8187 77.61 94.3104C77.1878 94.802 76.6802 95.1788 76.087 95.4406C75.4938 95.6971 74.8366 95.8254 74.1151 95.8254C73.3991 95.8254 72.7444 95.6971 72.1513 95.4406C71.5635 95.1788 71.0531 94.802 70.6203 94.3104C70.1874 93.8187 69.8508 93.2229 69.6103 92.5229C69.3752 91.8228 69.2576 91.0319 69.2576 90.1502V89.5089C69.2576 88.6272 69.3752 87.839 69.6103 87.1443C69.8454 86.4443 70.1767 85.8484 70.6042 85.3568C71.0371 84.8598 71.5474 84.4831 72.1353 84.2266C72.7284 83.9647 73.383 83.8338 74.0991 83.8338C74.8205 83.8338 75.4778 83.9647 76.071 84.2266C76.6641 84.4831 77.1745 84.8598 77.602 85.3568C78.0295 85.8484 78.3581 86.4443 78.5879 87.1443C78.8231 87.839 78.9406 88.6272 78.9406 89.5089ZM76.9287 90.1502V89.4929C76.9287 88.841 76.8645 88.2665 76.7363 87.7695C76.6134 87.2672 76.429 86.8477 76.1832 86.5111C75.9427 86.1691 75.6461 85.9126 75.2935 85.7415C74.9408 85.5652 74.5426 85.477 74.0991 85.477C73.6556 85.477 73.2601 85.5652 72.9128 85.7415C72.5654 85.9126 72.2688 86.1691 72.023 86.5111C71.7826 86.8477 71.5982 87.2672 71.4699 87.7695C71.3417 88.2665 71.2776 88.841 71.2776 89.4929V90.1502C71.2776 90.8022 71.3417 91.3793 71.4699 91.8816C71.5982 92.3839 71.7852 92.8088 72.031 93.1561C72.2822 93.4981 72.5815 93.7573 72.9288 93.9336C73.2762 94.1046 73.6716 94.1901 74.1151 94.1901C74.564 94.1901 74.9621 94.1046 75.3095 93.9336C75.6568 93.7573 75.9507 93.4981 76.1912 93.1561C76.4317 92.8088 76.6134 92.3839 76.7363 91.8816C76.8645 91.3793 76.9287 90.8022 76.9287 90.1502ZM90.2108 83.9941V95.665H88.1988L82.9645 87.3046V95.665H80.9526V83.9941H82.9645L88.2148 92.3706V83.9941H90.2108Z" fill="#3F52DD"/>
</g>
<defs>
<filter id="filter0_d_4488_88089" x="0.530457" y="0.0152285" width="158.939" height="158.939" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2.98477"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4488_88089"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4488_88089" result="shape"/>
</filter>
<filter id="filter1_i_4488_88089" x="38.9595" y="48.5635" width="85.812" height="86.5584" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="3.73096" dy="3.73096"/>
<feGaussianBlur stdDeviation="2.98477"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_4488_88089"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.5 KiB

9
ui-ngx/yarn.lock

@ -2747,7 +2747,14 @@
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
"@svgdotjs/svg.js@^3.2.0":
"@svgdotjs/svg.filter.js@^3.0.8":
version "3.0.8"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.8.tgz#998cb2481a871fa70d7dbaa891c886b335c562d7"
integrity sha512-YshF2YDaeRA2StyzAs5nUPrev7npQ38oWD0eTRwnsciSL2KrRPMoUw8BzjIXItb3+dccKGTX3IQOd2NFzmHkog==
dependencies:
"@svgdotjs/svg.js" "^3.1.1"
"@svgdotjs/svg.js@^3.1.1", "@svgdotjs/svg.js@^3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@svgdotjs/svg.js/-/svg.js-3.2.0.tgz#6baa8cef6778a93818ac18faa2055222e60aa644"
integrity sha512-Tr8p+QVP7y+QT1GBlq1Tt57IvedVH8zCPoYxdHLX0Oof3a/PqnC/tXAkVufv1JQJfsDHlH/UrjcDfgxSofqSNA==

Loading…
Cancel
Save