feat: set disable style of device name in side menu (#656)
* feat: visualise disabled state of the 'Device name' input control * fix: original value handling
This commit is contained in:
committed by
László Monda
parent
8e20c85e07
commit
ee53a0df9b
@@ -0,0 +1,10 @@
|
||||
<input #inputControl
|
||||
cancelable
|
||||
[class]="css"
|
||||
type="text"
|
||||
[disabled]="disabled"
|
||||
[(ngModel)]="model"
|
||||
(blur)="blur()"
|
||||
(focus)="focus()"
|
||||
(keyup.enter)="keyEnter($event)"
|
||||
(keyup)="calculateTextWidth($event.target.value)">
|
||||
@@ -0,0 +1,118 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
forwardRef, HostListener,
|
||||
Input,
|
||||
Renderer2,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import * as util from '../../util';
|
||||
|
||||
const noop = (_: any) => {
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'auto-grow-input',
|
||||
templateUrl: './auto-grow-input.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => AutoGrowInputComponent),
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class AutoGrowInputComponent implements ControlValueAccessor {
|
||||
@Input() maxParentWidthPercent = 1;
|
||||
@Input() css: string;
|
||||
|
||||
@ViewChild('inputControl') inputControl: ElementRef;
|
||||
|
||||
disabled: boolean;
|
||||
|
||||
get model(): string {
|
||||
return this._model;
|
||||
}
|
||||
|
||||
set model(value: string) {
|
||||
if (this._model === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._model = value;
|
||||
}
|
||||
|
||||
private _model: string;
|
||||
private _originalModel: string;
|
||||
private _onChanged = noop;
|
||||
private _onTouched = noop;
|
||||
|
||||
constructor(private _cdRef: ChangeDetectorRef,
|
||||
private _renderer: Renderer2) {
|
||||
}
|
||||
|
||||
registerOnChange(fn: any): void {
|
||||
this._onChanged = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void {
|
||||
this._onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
if (this.disabled === isDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.disabled = isDisabled;
|
||||
this._cdRef.markForCheck();
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
windowResize(): void {
|
||||
this.calculateTextWidth(this._model);
|
||||
}
|
||||
|
||||
writeValue(obj: any): void {
|
||||
console.log('write', new Date());
|
||||
if (this.model === obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._model = obj;
|
||||
this._originalModel = obj;
|
||||
this.calculateTextWidth(this._model);
|
||||
this._cdRef.markForCheck();
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
this._onTouched(this);
|
||||
}
|
||||
|
||||
blur(): void {
|
||||
if (!util.isValidName(this._model) || this._model.trim() === this._originalModel) {
|
||||
this._model = this._originalModel;
|
||||
this.calculateTextWidth(this._model);
|
||||
this._cdRef.markForCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
this._originalModel = this._model;
|
||||
this._onChanged(this._model);
|
||||
}
|
||||
|
||||
keyEnter(event): void {
|
||||
event.target.blur();
|
||||
}
|
||||
|
||||
calculateTextWidth(text: string): void {
|
||||
const htmlInput = this.inputControl.nativeElement as HTMLInputElement;
|
||||
const maxWidth = htmlInput.parentElement.parentElement.offsetWidth * this.maxParentWidthPercent;
|
||||
const textWidth = util.getContentWidth(window.getComputedStyle(htmlInput), text);
|
||||
this._renderer.setStyle(htmlInput, 'width', Math.min(maxWidth, textWidth) + 'px');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './auto-grow-input.component';
|
||||
@@ -2,13 +2,11 @@
|
||||
<li class="sidebar__level-0--item">
|
||||
<div class="sidebar__level-0">
|
||||
<i class="uhk-icon uhk-icon-0401-usb-stick rotate-right"></i>
|
||||
<input #deviceName cancelable
|
||||
class="pane-title__name"
|
||||
type="text"
|
||||
[readonly]="state.restoreUserConfiguration"
|
||||
(change)="editDeviceName($event.target.value)"
|
||||
(keyup.enter)="deviceName.blur()"
|
||||
(keyup)="calculateHeaderTextWidth($event.target.value)">
|
||||
<auto-grow-input [ngModel]="state.deviceName"
|
||||
[maxParentWidthPercent]="0.65"
|
||||
[css]="'side-menu-pane-title__name'"
|
||||
[disabled]="state.restoreUserConfiguration || state.updatingFirmware"
|
||||
(ngModelChange)="editDeviceName($event)"></auto-grow-input>
|
||||
<i class="fa fa-chevron-up pull-right" (click)="toggleHide($event, 'device')"></i>
|
||||
</div>
|
||||
<ul [@toggler]="animation['device']">
|
||||
|
||||
@@ -162,22 +162,3 @@ ul {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pane-title {
|
||||
margin-bottom: 1em;
|
||||
|
||||
&__name {
|
||||
border: none;
|
||||
border-bottom: 2px dotted #999;
|
||||
padding: 0;
|
||||
margin: 0 0.25rem;
|
||||
text-overflow: ellipsis;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px #ccc, 0 0 5px 0 #ccc;
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
AfterContentInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
@@ -19,7 +18,6 @@ import 'rxjs/add/operator/let';
|
||||
|
||||
import { AppState, getSideMenuPageState } from '../../store';
|
||||
import { MacroActions } from '../../store/actions';
|
||||
import * as util from '../../util';
|
||||
import { RenameUserConfigurationAction } from '../../store/actions/user-config';
|
||||
import { SideMenuPageState } from '../../models/side-menu-page-state';
|
||||
|
||||
@@ -40,7 +38,7 @@ import { SideMenuPageState } from '../../models/side-menu-page-state';
|
||||
styleUrls: ['./side-menu.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SideMenuComponent implements AfterContentInit, OnInit, OnDestroy {
|
||||
export class SideMenuComponent implements OnInit, OnDestroy {
|
||||
state: SideMenuPageState;
|
||||
animation: { [key: string]: 'active' | 'inactive' };
|
||||
@ViewChild('deviceName') deviceName: ElementRef;
|
||||
@@ -62,15 +60,10 @@ export class SideMenuComponent implements AfterContentInit, OnInit, OnDestroy {
|
||||
ngOnInit(): void {
|
||||
this.stateSubscription = this.store.select(getSideMenuPageState).subscribe(data => {
|
||||
this.state = data;
|
||||
this.setDeviceName();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterContentInit(): void {
|
||||
this.setDeviceName();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.stateSubscription) {
|
||||
this.stateSubscription.unsubscribe();
|
||||
@@ -106,24 +99,6 @@ export class SideMenuComponent implements AfterContentInit, OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
editDeviceName(name: string): void {
|
||||
if (!util.isValidName(name) || name.trim() === this.state.deviceName) {
|
||||
this.setDeviceName();
|
||||
return;
|
||||
}
|
||||
this.store.dispatch(new RenameUserConfigurationAction(name));
|
||||
}
|
||||
|
||||
calculateHeaderTextWidth(text): void {
|
||||
const htmlInput = this.deviceName.nativeElement as HTMLInputElement;
|
||||
const maxWidth = htmlInput.parentElement.offsetWidth * 0.66;
|
||||
const textWidth = util.getContentWidth(window.getComputedStyle(htmlInput), text);
|
||||
this.renderer.setStyle(htmlInput, 'width', Math.min(maxWidth, textWidth) + 'px');
|
||||
}
|
||||
|
||||
private setDeviceName(): void {
|
||||
if (this.deviceName) {
|
||||
this.renderer.setProperty(this.deviceName.nativeElement, 'value', this.state.deviceName);
|
||||
this.calculateHeaderTextWidth(this.deviceName.nativeElement.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ import { EditableTextComponent } from './components/editable-text/editable-text.
|
||||
import { Autofocus } from './directives/autofocus/autofocus.directive';
|
||||
import { UhkDeviceBootloaderNotActiveGuard } from './services/uhk-device-bootloader-not-active.guard';
|
||||
import { FileUploadComponent } from './components/file-upload';
|
||||
import { AutoGrowInputComponent } from './components/auto-grow-input';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -181,7 +182,8 @@ import { FileUploadComponent } from './components/file-upload';
|
||||
Autofocus,
|
||||
RestoreConfigurationComponent,
|
||||
RecoveryModeComponent,
|
||||
FileUploadComponent
|
||||
FileUploadComponent,
|
||||
AutoGrowInputComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
@import '~font-awesome/scss/font-awesome';
|
||||
@import './styles/tooltip';
|
||||
@import './styles/uhk-icons/uhk-icon';
|
||||
@import './styles/side-menu';
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
|
||||
22
packages/uhk-web/src/styles/_side-menu.scss
Normal file
22
packages/uhk-web/src/styles/_side-menu.scss
Normal file
@@ -0,0 +1,22 @@
|
||||
.side-menu-pane-title {
|
||||
margin-bottom: 1em;
|
||||
|
||||
&__name {
|
||||
border: none;
|
||||
border-bottom: 2px dotted #999;
|
||||
padding: 0;
|
||||
margin: 0 0.25rem;
|
||||
text-overflow: ellipsis;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px #ccc, 0 0 5px 0 #ccc;
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user