cosmos-explorer/src/SelfServe/PropertyDecorators.tsx
Srinath Narayanan 318842624f Resolved PR comments
Added tests
Moved onSubmt and initialize inside base class
Moved testExplorer to separate folder
made fields of SelfServe Class non static
2021-01-12 22:02:45 -08:00

108 lines
3.9 KiB
TypeScript

import { DropdownItem, Info, InputType, UiType } from "../Explorer/Controls/SmartUi/SmartUiComponent";
import { addPropertyToMap } from "./SelfServeUtils";
interface Decorator {
name: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
}
interface InputOptionsBase {
label: string;
}
export interface NumberInputOptions extends InputOptionsBase {
min: (() => Promise<number>) | number;
max: (() => Promise<number>) | number;
step: (() => Promise<number>) | number;
uiType: UiType;
}
export interface StringInputOptions extends InputOptionsBase {
placeholder?: (() => Promise<string>) | string;
}
export interface BooleanInputOptions extends InputOptionsBase {
trueLabel: (() => Promise<string>) | string;
falseLabel: (() => Promise<string>) | string;
}
export interface DropdownInputOptions extends InputOptionsBase {
choices: (() => Promise<DropdownItem[]>) | DropdownItem[];
}
type InputOptions = NumberInputOptions | StringInputOptions | BooleanInputOptions | DropdownInputOptions;
function isNumberInputOptions(inputOptions: InputOptions): inputOptions is NumberInputOptions {
return !!(inputOptions as NumberInputOptions).min;
}
function isBooleanInputOptions(inputOptions: InputOptions): inputOptions is BooleanInputOptions {
return !!(inputOptions as BooleanInputOptions).trueLabel;
}
function isDropdownInputOptions(inputOptions: InputOptions): inputOptions is DropdownInputOptions {
return !!(inputOptions as DropdownInputOptions).choices;
}
const addToMap = (...decorators: Decorator[]): PropertyDecorator => {
return (target, property) => {
let className = target.constructor.name;
const propertyName = property.toString();
if (className === "Function") {
className = (target as Function).name;
throw new Error(`Property '${propertyName}' in class '${className}'should be not be static.`);
}
const propertyType = (Reflect.getMetadata("design:type", target, property)?.name as string)?.toLowerCase();
addPropertyToMap(target, propertyName, className, "type", propertyType);
addPropertyToMap(target, propertyName, className, "dataFieldName", propertyName);
decorators.map((decorator: Decorator) =>
addPropertyToMap(target, propertyName, className, decorator.name, decorator.value)
);
};
};
export const OnChange = (
onChange: (currentState: Map<string, InputType>, newValue: InputType) => Map<string, InputType>
): PropertyDecorator => {
return addToMap({ name: "onChange", value: onChange });
};
export const PropertyInfo = (info: (() => Promise<Info>) | Info): PropertyDecorator => {
return addToMap({ name: "info", value: info });
};
export const Values = (inputOptions: InputOptions): PropertyDecorator => {
if (isNumberInputOptions(inputOptions)) {
const numberInputOptions = inputOptions as NumberInputOptions;
return addToMap(
{ name: "label", value: numberInputOptions.label },
{ name: "min", value: numberInputOptions.min },
{ name: "max", value: numberInputOptions.max },
{ name: "step", value: numberInputOptions.step },
{ name: "uiType", value: numberInputOptions.uiType }
);
} else if (isBooleanInputOptions(inputOptions)) {
const booleanInputOptions = inputOptions as BooleanInputOptions;
return addToMap(
{ name: "label", value: booleanInputOptions.label },
{ name: "trueLabel", value: booleanInputOptions.trueLabel },
{ name: "falseLabel", value: booleanInputOptions.falseLabel }
);
} else if (isDropdownInputOptions(inputOptions)) {
const dropdownInputOptions = inputOptions as DropdownInputOptions;
return addToMap(
{ name: "label", value: dropdownInputOptions.label },
{ name: "choices", value: dropdownInputOptions.choices }
);
} else {
const stringInputOptions = inputOptions as StringInputOptions;
return addToMap(
{ name: "label", value: stringInputOptions.label },
{ name: "placeholder", value: stringInputOptions.placeholder }
);
}
};