diff options
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts')
-rw-r--r-- | src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts new file mode 100644 index 000000000..a90e2b8f8 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary-per-second.directive.ts @@ -0,0 +1,132 @@ +import { + Directive, + ElementRef, + EventEmitter, + HostListener, + Input, + OnInit, + Output +} from '@angular/core'; +import { NgControl } from '@angular/forms'; + +import _ from 'lodash'; + +import { DimlessBinaryPerSecondPipe } from '../pipes/dimless-binary-per-second.pipe'; +import { FormatterService } from '../services/formatter.service'; + +@Directive({ + selector: '[cdDimlessBinaryPerSecond]' +}) +export class DimlessBinaryPerSecondDirective implements OnInit { + @Output() + ngModelChange: EventEmitter<any> = new EventEmitter(); + + /** + * Event emitter for letting this directive know that the data has (asynchronously) been loaded + * and the value needs to be adapted by this directive. + */ + @Input() + ngDataReady: EventEmitter<any>; + + /** + * Minimum size in bytes. + * If user enter a value lower than <minBytes>, + * the model will automatically be update to <minBytes>. + * + * If <roundPower> is used, this value should be a power of <roundPower>. + * + * Example: + * Given minBytes=4096 (4KiB), if user type 1KiB, then model will be updated to 4KiB + */ + @Input() + minBytes: number; + + /** + * Maximum size in bytes. + * If user enter a value greater than <maxBytes>, + * the model will automatically be update to <maxBytes>. + * + * If <roundPower> is used, this value should be a power of <roundPower>. + * + * Example: + * Given maxBytes=3145728 (3MiB), if user type 4MiB, then model will be updated to 3MiB + */ + @Input() + maxBytes: number; + + /** + * Value will be rounded up the nearest power of <roundPower> + * + * Example: + * Given roundPower=2, if user type 7KiB, then model will be updated to 8KiB + * Given roundPower=2, if user type 5KiB, then model will be updated to 4KiB + */ + @Input() + roundPower: number; + + /** + * Default unit that should be used when user do not type a unit. + * By default, "MiB" will be used. + * + * Example: + * Given defaultUnit=null, if user type 7, then model will be updated to 7MiB + * Given defaultUnit=k, if user type 7, then model will be updated to 7KiB + */ + @Input() + defaultUnit: string; + + private el: HTMLInputElement; + + constructor( + private elementRef: ElementRef, + private control: NgControl, + private dimlessBinaryPerSecondPipe: DimlessBinaryPerSecondPipe, + private formatter: FormatterService + ) { + this.el = this.elementRef.nativeElement; + } + + ngOnInit() { + this.setValue(this.el.value); + if (this.ngDataReady) { + this.ngDataReady.subscribe(() => this.setValue(this.el.value)); + } + } + + setValue(value: string) { + if (/^[\d.]+$/.test(value)) { + value += this.defaultUnit || 'm'; + } + const size = this.formatter.toBytes(value, 0); + const roundedSize = this.round(size); + this.el.value = this.dimlessBinaryPerSecondPipe.transform(roundedSize); + if (size !== null) { + this.ngModelChange.emit(this.el.value); + this.control.control.setValue(this.el.value); + } else { + this.ngModelChange.emit(null); + this.control.control.setValue(null); + } + } + + round(size: number) { + if (size !== null && size !== 0) { + if (!_.isUndefined(this.minBytes) && size < this.minBytes) { + return this.minBytes; + } + if (!_.isUndefined(this.maxBytes) && size > this.maxBytes) { + return this.maxBytes; + } + if (!_.isUndefined(this.roundPower)) { + const power = Math.round(Math.log(size) / Math.log(this.roundPower)); + return Math.pow(this.roundPower, power); + } + } + return size; + } + + @HostListener('blur', ['$event.target.value']) + onBlur(value: string) { + this.setValue(value); + } +} |