cleanup Lens repo with tighter linting

Signed-off-by: Sebastian Malton <smalton@mirantis.com>
This commit is contained in:
Sebastian Malton committed 2020-07-09 17:00:23 -04:00
1 parent e468105143
commit b1ff34879a
470 files changed
+8447 -7443

No files matched your search

@@ -9,14 +9,14 @@ describe("k8s CPU units conversion", () => {
"100m", // 0.1
"930000n", // 0.00093
"3028u", // 0.003028
]
const cpuCores = units.map(unit => cpuUnitsToNumber(unit))
];
const cpuCores = units.map(unit => cpuUnitsToNumber(unit));
const expected = [
0.5,
0.1,
0.00093,
0.003028
]
expect(cpuCores).toEqual(expected)
];
expect(cpuCores).toEqual(expected);
});
});
@@ -11,8 +11,8 @@ describe("Kubernetes units conversion", () => {
4596968000, // 4.2Gi
4596968000000, // 4.1Ti
1.2384898975269E+15 // 1.1Pi
]
const units = bytes.map(byte => bytesToUnits(byte))
];
const units = bytes.map(byte => bytesToUnits(byte));
const expected = [
"128B",
"2.0Ki",
@@ -20,22 +20,22 @@ describe("Kubernetes units conversion", () => {
"4.3Gi",
"4.2Ti",
"1.1Pi"
]
expect(units).toEqual(expected)
];
expect(units).toEqual(expected);
});
test("Convert bytes to units with decimal precision", () => {
const bytes = [
2107152, // 2.010Mi
4596968000, // 4.281Gi
]
const units = bytes.map(byte => bytesToUnits(byte, 3))
];
const units = bytes.map(byte => bytesToUnits(byte, 3));
const expected = [
"2.010Mi",
"4.281Gi"
]
expect(units).toEqual(expected)
})
];
expect(units).toEqual(expected);
});
test("Convert 0 to bytes", () => {
expect(bytesToUnits(0)).toEqual("N/A");
@@ -49,7 +49,7 @@ describe("Kubernetes units conversion", () => {
"7.99Gi", // 8579197173
"2Ti", // 2199023255552
"1Pi", // 1125899906842624
]
];
const expected = [
128,
22528,
@@ -57,9 +57,9 @@ describe("Kubernetes units conversion", () => {
8579197173,
2199023255552,
1125899906842624
]
const bytes = units.map(unitsToBytes)
expect(bytes).toEqual(expected)
];
const bytes = units.map(unitsToBytes);
expect(bytes).toEqual(expected);
});
test("Convert shorten units to bytes", () => {
@@ -70,7 +70,7 @@ describe("Kubernetes units conversion", () => {
"7.99G", // 8579197173
"2T", // 2199023255552
"1P", // 1125899906842624
]
];
const expected = [
128,
22528,
@@ -78,9 +78,9 @@ describe("Kubernetes units conversion", () => {
8579197173,
2199023255552,
1125899906842624
]
const bytes = units.map(unitsToBytes)
expect(bytes).toEqual(expected)
];
const bytes = units.map(unitsToBytes);
expect(bytes).toEqual(expected);
});
test("Convert strange unit to bytes", () => {
+2 -2
View File
@@ -9,11 +9,11 @@
* @returns the left and right sub-arrays which when conjoined with `element`
* is the same as `array`, and `true`
*/
export function split<T>(array: Array<T>, element: T): [Array<T>, Array<T>, boolean] {
export function split<T>(array: T[], element: T): [T[], T[], boolean] {
const index = array.indexOf(element);
if (index < 0) {
return [array, [], false];
}
return [array.slice(0, index), array.slice(index+1, array.length), true]
return [array.slice(0, index), array.slice(index+1, array.length), true];
}
+36 -27
View File
@@ -2,32 +2,9 @@
// Can be applied to class or single method as @autobind()
type Constructor<T = {}> = new (...args: any[]) => T;
export function autobind() {
return function (target: Constructor | object, prop?: string, descriptor?: PropertyDescriptor) {
if (target instanceof Function) return bindClass(target);
else return bindMethod(target, prop, descriptor);
}
}
function bindClass<T extends Constructor>(constructor: T) {
const proto = constructor.prototype;
const descriptors = Object.getOwnPropertyDescriptors(proto);
const skipMethod = (methodName: string) => {
return methodName === "constructor"
|| typeof descriptors[methodName].value !== "function";
};
Object.keys(descriptors).forEach(prop => {
if (skipMethod(prop)) return;
const boundDescriptor = bindMethod(proto, prop, descriptors[prop]);
Object.defineProperty(proto, prop, boundDescriptor);
})
}
function bindMethod(target: object, prop?: string, descriptor?: PropertyDescriptor) {
function bindMethod(target: object, prop?: string, descriptor?: PropertyDescriptor): any {
if (!descriptor || typeof descriptor.value !== "function") {
throw new Error(`@autobind() must be used on class or method only`)
throw new Error(`@autobind() must be used on class or method only`);
}
const { value: func, enumerable, configurable } = descriptor;
const boundFunc = new WeakMap<object, Function>();
@@ -36,9 +13,41 @@ function bindMethod(target: object, prop?: string, descriptor?: PropertyDescript
enumerable,
configurable,
get() {
if (this === target) return func; // direct access from prototype
if (!boundFunc.has(this)) boundFunc.set(this, func.bind(this));
if (this === target) {
return func;
} // direct access from prototype
if (!boundFunc.has(this)) {
boundFunc.set(this, func.bind(this));
}
return boundFunc.get(this);
}
});
}
function bindClass<T extends Constructor>(constructor: T): void {
const proto = constructor.prototype;
const descriptors = Object.getOwnPropertyDescriptors(proto);
const skipMethod = (methodName: string): boolean => {
return methodName === "constructor"
|| typeof descriptors[methodName].value !== "function";
};
Object.keys(descriptors).forEach(prop => {
if (skipMethod(prop)) {
return;
}
const boundDescriptor = bindMethod(proto, prop, descriptors[prop]);
Object.defineProperty(proto, prop, boundDescriptor);
});
}
export function autobind(): (target: Constructor | object, prop?: string, descriptor?: PropertyDescriptor) => void | any {
return function (target: Constructor | object, prop?: string, descriptor?: PropertyDescriptor): void | any {
if (target instanceof Function) {
return bindClass(target);
} else {
return bindMethod(target, prop, descriptor);
}
};
}
+2 -2
View File
@@ -3,10 +3,10 @@ import * as Base64 from "crypto-js/enc-base64";
import * as Utf8 from "crypto-js/enc-utf8";
export const base64 = {
decode(data: string) {
decode(data: string): string {
return Base64.parse(data).toString(Utf8);
},
encode(data: string) {
encode(data: string): string {
return Utf8.parse(data).toString(Base64);
}
};
+2 -4
View File
@@ -4,15 +4,13 @@ import { camelCase, isPlainObject } from "lodash";
export function toCamelCase(data: any): any {
if (Array.isArray(data)) {
return data.map(toCamelCase);
}
else if (isPlainObject(data)) {
} else if (isPlainObject(data)) {
return Object.keys(data).reduce<any>((result, key) => {
const value = data[key];
result[camelCase(key)] = typeof value === "object" ? toCamelCase(value) : value;
return result;
}, {});
}
else {
} else {
return data;
}
}
+4 -4
View File
@@ -12,7 +12,7 @@ interface WrappingFunction {
<T>(result: T): T;
}
export function cancelableFetch(reqInfo: RequestInfo, reqInit: RequestInit = {}) {
export function cancelableFetch(reqInfo: RequestInfo, reqInit: RequestInit = {}): CancelablePromise<Response> {
const abortController = new AbortController();
const signal = abortController.signal;
const cancel = abortController.abort.bind(abortController);
@@ -20,14 +20,14 @@ export function cancelableFetch(reqInfo: RequestInfo, reqInit: RequestInit = {})
const wrapResult: WrappingFunction = function (result: any) {
if (result instanceof Promise) {
const promise: CancelablePromise<any> = result as any;
promise.then = function (onfulfilled, onrejected) {
promise.then = function (onfulfilled, onrejected): any {
const data = Object.getPrototypeOf(this).then.call(this, onfulfilled, onrejected);
return wrapResult(data);
}
};
promise.cancel = cancel;
}
return result;
}
};
const req = fetch(reqInfo, { ...reqInit, signal });
return wrapResult(req);
+13 -7
View File
@@ -1,10 +1,16 @@
// Helper to convert CPU K8S units to numbers
export function cpuUnitsToNumber(cpu: string) {
const cpuNum = parseInt(cpu)
const billion = 1000000 * 1000
if (cpu.includes("m")) return cpuNum / 1000
if (cpu.includes("u")) return cpuNum / 1000000
if (cpu.includes("n")) return cpuNum / billion
return parseFloat(cpu)
export function cpuUnitsToNumber(cpu: string): number {
const cpuNum = parseInt(cpu);
const billion = 1000000 * 1000;
if (cpu.includes("m")) {
return cpuNum / 1000;
}
if (cpu.includes("u")) {
return cpuNum / 1000000;
}
if (cpu.includes("n")) {
return cpuNum / billion;
}
return parseFloat(cpu);
}
+12 -12
View File
@@ -1,28 +1,28 @@
// Helper to convert memory from units Ki, Mi, Gi, Ti, Pi to bytes and vise versa
const base = 1024
const suffixes = ['K', 'M', 'G', 'T', 'P', 'E'] // Equivalents: Ki, Mi, Gi, Ti, Pi, Ei
const base = 1024;
const suffixes = ['K', 'M', 'G', 'T', 'P', 'E']; // Equivalents: Ki, Mi, Gi, Ti, Pi, Ei
export function unitsToBytes(value: string) {
export function unitsToBytes(value: string): number {
if (!suffixes.some(suffix => value.includes(suffix))) {
return parseFloat(value)
return parseFloat(value);
}
const index = suffixes.findIndex(suffix =>
suffix == value.replace(/[0-9]|i|\./g, '')
)
);
return parseInt(
(parseFloat(value) * Math.pow(base, index + 1)).toFixed(1)
)
);
}
export function bytesToUnits(bytes: number, precision = 1) {
const sizes = ["B", ...suffixes]
const index = Math.floor(Math.log(bytes) / Math.log(base))
export function bytesToUnits(bytes: number, precision = 1): string {
const sizes = ["B", ...suffixes];
const index = Math.floor(Math.log(bytes) / Math.log(base));
if (!bytes) {
return "N/A"
return "N/A";
}
if (index === 0) {
return `${bytes}${sizes[index]}`
return `${bytes}${sizes[index]}`;
}
return `${(bytes / (1024 ** index)).toFixed(precision)}${sizes[index]}i`
return `${(bytes / (1024 ** index)).toFixed(precision)}${sizes[index]}i`;
}
+10 -9
View File
@@ -1,21 +1,22 @@
// Helper for selecting element's text content and copy in clipboard
function isSelectable(elem: HTMLElement): elem is HTMLInputElement {
return !!(elem as HTMLInputElement).select;
}
export function copyToClipboard(elem: HTMLElement, resetSelection = true): boolean {
let clearSelection: () => void;
if (isSelectable(elem)) {
elem.select();
clearSelection = () => elem.setSelectionRange(0, 0)
}
else {
clearSelection = (): void => elem.setSelectionRange(0, 0);
} else {
const selection = window.getSelection();
selection.selectAllChildren(elem);
clearSelection = () => selection.removeAllRanges();
clearSelection = (): void => selection.removeAllRanges();
}
const copyResult = document.execCommand("copy");
if (resetSelection) clearSelection();
if (resetSelection) {
clearSelection();
}
return copyResult;
}
function isSelectable(elem: HTMLElement): elem is HTMLInputElement {
return !!(elem as HTMLInputElement).select;
}
+13 -15
View File
@@ -1,23 +1,19 @@
// Helper to work with browser's local/session storage api
export interface IStorageHelperOptions {
export interface StorageHelperOptions {
addKeyPrefix?: boolean;
useSession?: boolean; // use `sessionStorage` instead of `localStorage`
}
export function createStorage<T>(key: string, defaultValue?: T, options?: IStorageHelperOptions) {
return new StorageHelper(key, defaultValue, options);
}
export class StorageHelper<T> {
static keyPrefix = "lens_";
static defaultOptions: IStorageHelperOptions = {
static defaultOptions: StorageHelperOptions = {
addKeyPrefix: true,
useSession: false,
}
constructor(protected key: string, protected defaultValue?: T, protected options?: IStorageHelperOptions) {
constructor(protected key: string, protected defaultValue?: T, protected options?: StorageHelperOptions) {
this.options = Object.assign({}, StorageHelper.defaultOptions, options);
if (this.options.addKeyPrefix) {
@@ -25,8 +21,10 @@ export class StorageHelper<T> {
}
}
protected get storage() {
if (this.options.useSession) return window.sessionStorage;
protected get storage(): Storage {
if (this.options.useSession) {
return window.sessionStorage;
}
return window.localStorage;
}
@@ -36,32 +34,32 @@ export class StorageHelper<T> {
try {
return JSON.parse(strValue);
} catch (e) {
console.error(`Parsing json failed for pair: ${this.key}=${strValue}`)
console.error(`Parsing json failed for pair: ${this.key}=${strValue}`);
}
}
return this.defaultValue;
}
set(value: T) {
set(value: T): StorageHelper<T> {
this.storage.setItem(this.key, JSON.stringify(value));
return this;
}
merge(value: Partial<T>) {
merge(value: Partial<T>): StorageHelper<T> {
const currentValue = this.get();
return this.set(Object.assign(currentValue, value));
}
clear() {
clear(): StorageHelper<T> {
this.storage.removeItem(this.key);
return this;
}
getDefaultValue() {
getDefaultValue(): T {
return this.defaultValue;
}
restoreDefaultValue() {
restoreDefaultValue(): StorageHelper<T> {
return this.set(this.defaultValue);
}
}
+7 -8
View File
@@ -1,22 +1,21 @@
// Helper for combining css classes inside components
export type IClassName = string | string[] | IClassNameMap;
export type IClassNameMap = {
export type ClassName = string | string[] | ClassNameMap;
export interface ClassNameMap {
[className: string]: boolean | any;
};
}
export function cssNames(...args: IClassName[]): string {
const map: IClassNameMap = {};
export function cssNames(...args: ClassName[]): string {
const map: ClassNameMap = {};
args.forEach(className => {
if (typeof className === "string" || Array.isArray(className)) {
[].concat(className).forEach(name => map[name] = true);
}
else {
} else {
Object.assign(map, className);
}
});
return Object.entries(map)
.filter(([className, isActive]) => !!isActive)
.filter(([_className, isActive]) => !!isActive)
.map(([className]) => className.trim())
.join(' ');
}
+19 -7
View File
@@ -1,17 +1,29 @@
// Helper for getting/setting css-variables
export function cssVar(elem: HTMLElement) {
export interface CSSVar {
toString(): string;
valueOf(): number;
}
export interface CSSVarWrapper {
get(name: string): CSSVar;
set(name: string, value: number | string): void;
}
export function cssVar(elem: HTMLElement): CSSVarWrapper {
return {
get(name: string) {
get(name: string): CSSVar {
const value = window.getComputedStyle(elem).getPropertyValue(name).trim();
return {
toString: () => value,
valueOf: () => parseFloat(value)
toString: (): string => value,
valueOf: (): number => parseFloat(value)
};
},
set(name: string, value: number | string) {
if (typeof value === "number") value = value + "px";
set(name: string, value: number | string): void {
if (typeof value === "number") {
value = value + "px";
}
elem.style.setProperty(name, value);
}
}
};
}
+2 -2
View File
@@ -1,8 +1,8 @@
// Debouncing promise evaluation
export const debouncePromise = function (promisedFunc: Function, timeout = 0) {
export const debouncePromise = function (promisedFunc: Function, timeout = 0): (...params: any[]) => Promise<any> {
let timer: number;
return (...params: any[]) => new Promise((resolve, reject) => {
return (...params: any[]): Promise<any> => new Promise((resolve, _reject) => {
clearTimeout(timer);
timer = window.setTimeout(() => resolve(promisedFunc.apply(this, params)), timeout);
});
+2 -2
View File
@@ -1,4 +1,4 @@
export function downloadFile(filename: string, contents: any, type: string) {
export function downloadFile(filename: string, contents: any, type: string): void {
const data = new Blob([contents], { type: type });
const url = URL.createObjectURL(data);
const link = document.createElement("a");
@@ -8,5 +8,5 @@ export function downloadFile(filename: string, contents: any, type: string) {
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url)
URL.revokeObjectURL(url);
}
+12 -9
View File
@@ -10,31 +10,34 @@ type Callback<D extends [...any[]]> = (...data: D) => void | boolean;
export class EventEmitter<D extends [...any[]]> {
protected listeners = new Map<Callback<D>, Options>();
addListener(callback: Callback<D>, options: Options = {}) {
addListener(callback: Callback<D>, options: Options = {}): void {
if (options.prepend) {
const listeners = [...this.listeners];
listeners.unshift([callback, options]);
this.listeners = new Map(listeners);
}
else {
} else {
this.listeners.set(callback, options);
}
}
removeListener(callback: Callback<D>) {
removeListener(callback: Callback<D>): void {
this.listeners.delete(callback);
}
removeAllListeners() {
removeAllListeners(): void {
this.listeners.clear();
}
emit(...data: D) {
emit(...data: D): void {
[...this.listeners].every(([callback, options]) => {
if (options.once) this.removeListener(callback);
if (options.once) {
this.removeListener(callback);
}
const result = callback(...data);
if (result === false) return; // break cycle
if (result === false) {
return;
} // break cycle
return true;
})
});
}
}
+4 -2
View File
@@ -2,7 +2,7 @@
import moment from "moment";
export function formatDuration(timeValue: number, compact: boolean) {
export function formatDuration(timeValue: number, compact: boolean): string {
let result = "";
const duration = moment.duration(timeValue);
const suffixes = ["d", "h", "m"];
@@ -12,7 +12,9 @@ export function formatDuration(timeValue: number, compact: boolean) {
duration.minutes(),
];
durationValues.forEach((value, index) => {
if (value) result += value + suffixes[index] + " ";
if (value) {
result += value + suffixes[index] + " ";
}
});
if (compact) {
result = result.split(" ")[0];
+17 -17
View File
@@ -1,21 +1,21 @@
// Common usage utils & helpers
export const noop = () => {};
export const noop = (): void => {};
export const isElectron = !!navigator.userAgent.match(/Electron/);
export * from './autobind'
export * from './cssVar'
export * from './cssNames'
export * from './eventEmitter'
export * from './downloadFile'
export * from './prevDefault'
export * from './createStorage'
export * from './interval'
export * from './debouncePromise'
export * from './copyToClipboard'
export * from './formatDuration'
export * from './camelCase'
export * from './base64'
export * from './isReactNode'
export * from './convertMemory'
export * from './convertCpu'
export * from './autobind';
export * from './cssVar';
export * from './cssNames';
export * from './eventEmitter';
export * from './downloadFile';
export * from './prevDefault';
export * from './createStorage';
export * from './interval';
export * from './debouncePromise';
export * from './copyToClipboard';
export * from './formatDuration';
export * from './camelCase';
export * from './base64';
export * from './isReactNode';
export * from './convertMemory';
export * from './convertCpu';
+43 -26
View File
@@ -2,31 +2,48 @@
type IntervalCallback = (count: number) => void;
export function interval(timeSec = 1, callback: IntervalCallback, autoRun = false) {
let count = 0;
let timer = -1;
let isRunning = false;
const intervalManager = {
start: function (runImmediately = false) {
if (isRunning) return;
const tick = () => callback(++count);
isRunning = true;
timer = window.setInterval(tick, 1000 * timeSec);
if (runImmediately) tick();
},
stop: function () {
count = 0;
isRunning = false;
clearInterval(timer);
},
restart: function (runImmediately = false) {
this.stop();
this.start(runImmediately);
},
get isRunning() {
return isRunning;
export class IntervalManager {
private count: number;
private timer: number;
private isCurRunning: boolean;
private timeSec: number;
private callback: IntervalCallback;
constructor(timeSec = 1, callback: IntervalCallback, autoRun = false) {
this.timeSec = timeSec;
this.callback = callback;
if (autoRun) {
this.start();
}
}
if (autoRun) intervalManager.start();
return intervalManager;
}
start(runImmediately?: boolean): void {
if (this.isRunning) {
return;
}
const tick = (): void => this.callback(++this.count);
this.isCurRunning = true;
this.timer = window.setInterval(tick, 1000 * this.timeSec);
if (runImmediately) {
tick();
}
}
stop(): void {
this.count = 0;
this.isCurRunning = false;
clearInterval(this.timer);
}
restart(runImmediately = false): void {
this.stop();
this.start(runImmediately);
}
get isRunning(): boolean {
return this.isCurRunning;
}
}
+2 -2
View File
@@ -1,9 +1,9 @@
// Type guard for checking valid react node to use in render
import React, { ReactNode } from "react"
import React, { ReactNode } from "react";
export function isReactNode(node: ReactNode): node is ReactNode {
return React.isValidElement(node)
|| Array.isArray(node) && node.every(isReactNode)
|| node == null
|| typeof node !== "object"
|| typeof node !== "object";
}
+4 -4
View File
@@ -12,14 +12,14 @@ import * as React from "react";
// <Icon onClick={prevDefault(() => console.log('stay on the page and open dialog'))}/>
// </a>
export function prevDefault<E extends React.SyntheticEvent | Event>(callback: (evt: E) => any) {
return function (evt: E) {
export function prevDefault<E extends React.SyntheticEvent | Event>(callback: (evt: E) => any): (evt: E) => any {
return function (evt: E): any {
evt.preventDefault();
evt.stopPropagation();
return callback(evt);
}
};
}
export function stopPropagation(evt: Event | React.SyntheticEvent) {
export function stopPropagation(evt: Event | React.SyntheticEvent): void {
evt.stopPropagation();
}