]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/dimless-binary.directive.ts
add stop-gap to fix compat with CPUs not supporting SSE 4.1
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / directives / dimless-binary.directive.ts
1 import {
2 Directive,
3 ElementRef,
4 EventEmitter,
5 HostListener,
6 Input,
7 OnInit,
8 Output
9 } from '@angular/core';
10 import { NgControl } from '@angular/forms';
11
12 import _ from 'lodash';
13
14 import { DimlessBinaryPipe } from '../pipes/dimless-binary.pipe';
15 import { FormatterService } from '../services/formatter.service';
16
17 @Directive({
18 selector: '[cdDimlessBinary]'
19 })
20 export class DimlessBinaryDirective implements OnInit {
21 @Output()
22 ngModelChange: EventEmitter<any> = new EventEmitter();
23
24 /**
25 * Minimum size in bytes.
26 * If user enter a value lower than <minBytes>,
27 * the model will automatically be update to <minBytes>.
28 *
29 * If <roundPower> is used, this value should be a power of <roundPower>.
30 *
31 * Example:
32 * Given minBytes=4096 (4KiB), if user type 1KiB, then model will be updated to 4KiB
33 */
34 @Input()
35 minBytes: number;
36
37 /**
38 * Maximum size in bytes.
39 * If user enter a value greater than <maxBytes>,
40 * the model will automatically be update to <maxBytes>.
41 *
42 * If <roundPower> is used, this value should be a power of <roundPower>.
43 *
44 * Example:
45 * Given maxBytes=3145728 (3MiB), if user type 4MiB, then model will be updated to 3MiB
46 */
47 @Input()
48 maxBytes: number;
49
50 /**
51 * Value will be rounded up the nearest power of <roundPower>
52 *
53 * Example:
54 * Given roundPower=2, if user type 7KiB, then model will be updated to 8KiB
55 * Given roundPower=2, if user type 5KiB, then model will be updated to 4KiB
56 */
57 @Input()
58 roundPower: number;
59
60 /**
61 * Default unit that should be used when user do not type a unit.
62 * By default, "MiB" will be used.
63 *
64 * Example:
65 * Given defaultUnit=null, if user type 7, then model will be updated to 7MiB
66 * Given defaultUnit=k, if user type 7, then model will be updated to 7KiB
67 */
68 @Input()
69 defaultUnit: string;
70
71 private el: HTMLInputElement;
72
73 constructor(
74 private elementRef: ElementRef,
75 private control: NgControl,
76 private dimlessBinaryPipe: DimlessBinaryPipe,
77 private formatter: FormatterService
78 ) {
79 this.el = this.elementRef.nativeElement;
80 }
81
82 ngOnInit() {
83 this.setValue(this.el.value);
84 }
85
86 setValue(value: string) {
87 if (/^[\d.]+$/.test(value)) {
88 value += this.defaultUnit || 'm';
89 }
90 const size = this.formatter.toBytes(value);
91 const roundedSize = this.round(size);
92 this.el.value = this.dimlessBinaryPipe.transform(roundedSize);
93 if (size !== null) {
94 this.ngModelChange.emit(this.el.value);
95 this.control.control.setValue(this.el.value);
96 } else {
97 this.ngModelChange.emit(null);
98 this.control.control.setValue(null);
99 }
100 }
101
102 round(size: number) {
103 if (size !== null && size !== 0) {
104 if (!_.isUndefined(this.minBytes) && size < this.minBytes) {
105 return this.minBytes;
106 }
107 if (!_.isUndefined(this.maxBytes) && size > this.maxBytes) {
108 return this.maxBytes;
109 }
110 if (!_.isUndefined(this.roundPower)) {
111 const power = Math.round(Math.log(size) / Math.log(this.roundPower));
112 return Math.pow(this.roundPower, power);
113 }
114 }
115 return size;
116 }
117
118 @HostListener('blur', ['$event.target.value'])
119 onBlur(value: string) {
120 this.setValue(value);
121 }
122 }