drf-react-by-schema
Version:
Components and Tools for building a React App having Django Rest Framework (DRF) as server
325 lines • 10.9 kB
TypeScript
import { JSX, ReactElement } from 'react';
import * as Yup from 'yup';
import { AutocompleteRenderOptionState } from '@mui/material/Autocomplete';
import { GridColDef, GridFilterModel, GridSortModel } from '@mui/x-data-grid';
import { DateView } from '@mui/x-date-pickers';
import { Control, FieldValues, UseFormGetValues, UseFormSetValue } from 'react-hook-form';
import { SxProps, Theme } from '@mui/material/styles';
import { OnEditModelType } from '../context/APIWrapperContext';
import { ServerEndPoint } from '../context/DRFReactBySchemaContext';
import { AlertColor } from '@mui/material/Alert';
import { MixedSchema } from 'yup/lib/mixed';
import { AnyObject, ObjectShape, OptionalObjectSchema, TypeOfShape } from 'yup/lib/object';
import { OptionalArraySchema } from 'yup/lib/array';
export type Id = string | number | null;
export type IdNotNull = string | number;
export type GenericValue = any;
export type Item = Record<string, GenericValue>;
export type AutocompleteItem = {
id: IdNotNull;
label: string;
};
export type OptionsACItem = AutocompleteItem | ChoiceItem;
export type FieldOptionsAC = OptionsACItem[];
export type OptionsAC = Record<string, FieldOptionsAC>;
export type OptionsACWithLoaders = Record<string, FieldOptionsAC | (() => Promise<FieldOptionsAC>)>;
export type PaginatedResult = {
count: number;
next: number;
previous: number;
sum_rows: null | Record<string, number>;
results: Item[];
};
export interface PaginationModel {
page: number;
pageSize: number;
filter?: GridFilterModel;
sort?: GridSortModel;
}
export type SchemaType = Record<string, Field>;
export type SchemaOptionsType = {
name: string;
description: string;
actions: {
POST: SchemaType;
};
renders: string[];
parses: string[];
verbose_name: string;
verbose_name_plural: string;
};
export type SchemaOptionsSingleActionType = Omit<SchemaOptionsType, 'actions'> & {
action: {
POST: SchemaType;
};
};
export type ModelOptionsType = Omit<SchemaOptionsType, 'actions' | 'renders' | 'parses'>;
export type ChoiceValue = IdNotNull;
export interface ChoiceItem {
value: ChoiceValue;
display_name: string;
}
type FieldChild = {
children?: SchemaType;
choices?: ChoiceItem[];
};
type FieldType = 'string' | 'email' | 'date' | 'datetime' | 'nested object' | 'field' | 'choice' | 'boolean' | 'decimal' | 'float' | 'file' | 'file upload' | 'image' | 'image upload' | 'number' | 'integer' | 'password' | 'array' | 'list';
export interface Field {
type: FieldType;
child?: FieldChild;
children?: SchemaType;
model_default?: GenericValue;
model_required?: boolean;
choices?: ChoiceItem[];
max_length?: number | string;
max_digits?: number;
decimal_places?: number;
label: string;
read_only?: boolean;
is_currency?: boolean;
prefix?: string;
suffix?: string;
creatable?: boolean;
related_editable?: boolean;
validators_regex?: Item[];
many?: boolean;
date_views?: DateView[];
required?: boolean;
ui_required?: boolean;
disabled?: boolean;
help_text?: string;
model_multiline?: boolean;
max_file_size?: number;
allowed_mime_types?: string[];
style?: Record<string, string>;
pattern_format?: string;
conditional_visible?: string[] | string[][];
}
export type GridEnrichedBySchemaColDef = GridColDef & {
isIndexField?: boolean;
creatable?: boolean;
disabled?: boolean;
orderable?: boolean;
patternFormat?: string;
uiRequired?: boolean;
};
export interface DataSchemaColumnsType {
data: Item[];
schema: SchemaType;
modelOptions: ModelOptionsType;
rowCount?: number;
sumRowsTotals?: null | Record<string, number>;
columns?: GridEnrichedBySchemaColDef[];
}
export interface ItemSchemaColumnsType {
data: Item;
schema: SchemaType;
modelOptions: ModelOptionsType;
columns?: GridEnrichedBySchemaColDef[];
}
export interface CommonFieldProps {
value?: GenericValue;
multiline?: boolean;
setValue?: UseFormSetValue<FieldValues>;
getValues?: UseFormGetValues<FieldValues>;
fieldKey?: string;
labelKey?: string;
index?: number;
optionsAC?: OptionsAC;
optionsModel?: string;
getOptionLabel?: (option: Item | string) => string;
renderOption?: (props: React.HTMLAttributes<HTMLLIElement>, option: Item, state: AutocompleteRenderOptionState) => React.ReactNode;
onEditModel?: (x: OnEditModelType) => void;
fieldsLayout?: FormFieldLayout[];
multiple?: boolean;
sx?: SxProps<Theme>;
options?: Item[];
isSemaphoric?: boolean;
label?: string;
onValueChange?: (x: GenericValue) => void;
decimalScale?: number;
type?: React.HTMLInputTypeAttribute;
autoComplete?: string;
minRows?: number;
optionIdKey?: string;
optionLabelKey?: string;
disabled?: boolean;
}
export interface FieldBySchemaProps extends Omit<CommonFieldProps, 'value'> {
name: string;
schema: SchemaType;
control: Control;
errors: Item;
autoFocus?: boolean;
}
export interface DetailFieldBySchemaProps {
fieldKey: string;
fieldSchema?: Field;
value: FormattedItemValue;
optionIdKey?: string;
optionLabelKey?: string;
sxField?: SxProps<Theme>;
sxLabel?: SxProps<Theme>;
sxValue?: SxProps<Theme>;
sxValueList?: SxProps<Theme>;
sxValueListItem?: SxProps<Theme>;
sxValueListItemText?: SxProps<Theme>;
}
type LinkProps = {
to: string | object;
href?: string;
state?: object;
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
} & React.AnchorHTMLAttributes<HTMLAnchorElement>;
export type LinkComponentType = React.ComponentType<LinkProps>;
export type AddParametersToEnd<TFunction extends (...args: any) => any, TParameters extends [...args: any]> = (...args: [...Parameters<TFunction>, ...TParameters]) => ReturnType<TFunction>;
export type ActionType = 'editInline' | 'remove' | 'edit' | 'view';
export interface CustomAction {
key: string;
icon: ReactElement;
label: string;
handleClick: (item: Item | undefined) => undefined;
}
export type BulkUpdateData = (newData: Item[]) => Promise<{
id: Id;
success: boolean;
}[]>;
export type BulkDeleteData = (ids: Id[]) => Promise<{
id: Id;
success: boolean;
}[]>;
export type OnSelectActionCustom = (selectedData: Item[], bulkUpdateData: BulkUpdateData) => void;
export type OnSelectActionTypes = OnSelectActionCustom | 'bulkDelete' | 'bulkCreate';
export type OnSelectActions = {
title: string;
action: OnSelectActionTypes;
};
export interface CustomFormField {
key: string;
CustomElement: (x: CommonFieldProps) => JSX.Element;
}
export interface FormFieldLayout {
title?: string;
rows?: (string | (string | CustomFormField)[] | CustomFormField)[];
customLabels?: Record<string, string>;
CustomElement?: React.ReactNode;
}
export interface ExtraSxCommonFieldProps {
sxSection?: SxProps<Theme>;
sxSectionTitle?: SxProps<Theme>;
sxRow?: SxProps<Theme>;
sxRowMultiple?: SxProps<Theme>;
sxField?: SxProps<Theme>;
sxLabel?: SxProps<Theme>;
sxValue?: SxProps<Theme>;
sxValueList?: SxProps<Theme>;
sxValueListItem?: SxProps<Theme>;
sxValueListItemText?: SxProps<Theme>;
}
export type DetailCommonFieldProps = CommonFieldProps & ExtraSxCommonFieldProps;
interface CustomDetailField {
key: string;
CustomElement: (x: DetailCommonFieldProps) => JSX.Element;
}
export type DetailFieldLayoutRows = (string | (string | CustomDetailField)[] | CustomDetailField)[];
export interface DetailFieldLayout extends ExtraSxCommonFieldProps {
title?: string;
rows?: DetailFieldLayoutRows;
CustomElement?: React.ReactNode;
isAccordion?: boolean;
isAccordionOpen?: boolean;
}
export interface DetailBySchemaProps extends ExtraSxCommonFieldProps {
values: Item;
schema: SchemaType;
columns: GridEnrichedBySchemaColDef[];
loading?: boolean;
editLink?: string;
editLabel?: string;
fieldsLayout?: DetailFieldLayout[];
hiddenFields?: string[];
fieldsProps?: Record<string, DetailCommonFieldProps>;
elevation?: number;
}
export type OnSuccessEvent = React.MouseEventHandler<HTMLButtonElement>;
export interface TargetApiParams {
path: string;
serverEndPoint: ServerEndPoint | null;
data: Item;
id: Id;
contentType?: 'application/json' | 'multipart/form-data';
}
export type TargetApiParamsLocal = Omit<TargetApiParams, 'serverEndPoint'>;
export type TargetApiPostParams = Omit<TargetApiParams, 'id'>;
export type TargetApiPostParamsLocal = Omit<TargetApiPostParams, 'serverEndPoint'>;
export interface SumRowsType {
rows: SumRowsItem[];
severity?: AlertColor;
}
interface SumRowsItem {
field: string;
prefix?: string;
suffix?: string;
isCount?: boolean;
}
export interface GetGenericModelListProps {
model: string;
serverEndPoint: ServerEndPoint | null;
id?: Id;
relatedModel?: string;
relatedModelId?: Id;
columnFields?: string[];
creatableFields?: string[];
disabledFields?: string[];
isInBatches?: boolean;
loadedSchema?: SchemaType | false;
loadedModelOptions?: ModelOptionsType | boolean;
page?: number;
filter?: GridFilterModel;
queryParams?: string[];
sort?: GridSortModel;
sumRows?: SumRowsType;
}
export type GetGenericModelListPropsLocal = Omit<GetGenericModelListProps, 'serverEndPoint'>;
export type GetGenericModelProps = {
model: string;
serverEndPoint: ServerEndPoint | null;
id?: Id;
relatedModel?: string;
relatedModelId?: string;
};
export type GetGenericModelPropsLocal = Omit<GetGenericModelProps, 'serverEndPoint'>;
export type FormattedItemValue = {
title: string;
valueStr: string;
value: GenericValue;
};
export type FormattedItem = Record<string, FormattedItemValue>;
export type formattedData = {
item: FormattedItem;
id: Id;
}[];
export interface MobileListRenderItemInfo {
item: FormattedItem;
index: number;
id: Id;
}
export type MobileListRenderItemType = (info: MobileListRenderItemInfo) => ReactElement | null;
export type GenericYupValidator = Yup.StringSchema | Yup.NumberSchema | OptionalObjectSchema<ObjectShape, AnyObject, TypeOfShape<ObjectShape>> | MixedSchema | Yup.DateSchema | Yup.BooleanSchema | OptionalArraySchema<Yup.AnySchema, AnyObject, GenericValue[] | undefined>;
export type ExtraValidators = Record<string, GenericYupValidator>;
export type ConditionalVisible = {
target: string;
source: string;
sourceValue: GenericValue;
};
export type { OnEditModelType };
export type UpdateDataBySchema = {
model: string;
modelObjectId: Id;
data: Item;
schema: SchemaType;
path?: string | null;
};
//# sourceMappingURL=index.d.ts.map