drf-react-by-schema
Version:
Components and Tools for building a React App having Django Rest Framework (DRF) as server
266 lines (265 loc) • 15.3 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const react_hook_form_1 = require("react-hook-form");
const TextField_1 = __importDefault(require("@mui/material/TextField"));
const Autocomplete_1 = __importStar(require("@mui/material/Autocomplete"));
const Edit_1 = __importDefault(require("@mui/icons-material/Edit"));
const IconButton_1 = __importDefault(require("@mui/material/IconButton"));
const Chip_1 = __importDefault(require("@mui/material/Chip"));
const utils_1 = require("../../../utils");
const DialogActions_1 = __importDefault(require("../../DialogActions"));
const APIWrapperContext_1 = require("../../../context/APIWrapperContext");
const filter = (0, Autocomplete_1.createFilterOptions)();
const EditableAutocompleteFieldBySchema = react_1.default.forwardRef((_a, _) => {
var { control, schema, errors, setValue, getValues, fieldKey, labelKey = 'nome', index, name = 'name', optionsAC, optionsModel, getOptionLabel, renderOption, onEditModel, sx = { mr: 2 }, onValueChange, multiple = false, disabled, fieldsLayout, autoFocus } = _a, other = __rest(_a, ["control", "schema", "errors", "setValue", "getValues", "fieldKey", "labelKey", "index", "name", "optionsAC", "optionsModel", "getOptionLabel", "renderOption", "onEditModel", "sx", "onValueChange", "multiple", "disabled", "fieldsLayout", "autoFocus"]);
const { setDialog } = (0, APIWrapperContext_1.useAPIWrapper)();
const [options, setOptions] = (0, react_1.useState)(null);
const model = name;
const label = schema[model].label;
if (!optionsModel) {
optionsModel = model;
}
if (fieldKey && index && index >= 0) {
name = `${fieldKey}.${index}.${name}`;
}
(0, react_1.useEffect)(() => {
if (optionsAC && optionsModel && optionsAC[optionsModel]) {
setOptions(optionsAC[optionsModel]);
}
}, [optionsAC, optionsModel]);
(0, react_1.useEffect)(() => {
if (!getValues || !setValue || !options) {
return;
}
const valuesInitial = getValues(model);
if (!valuesInitial) {
return;
}
if (multiple) {
const harmonizedValues = [];
for (const valueInitial of valuesInitial) {
const harmonizedValue = options.find((option) => option.id === valueInitial.id);
if (harmonizedValue) {
harmonizedValues.push(harmonizedValue);
}
}
setValue(model, harmonizedValues);
return;
}
const harmonizedValues = options.find((option) => option.id === valuesInitial.id);
setValue(model, harmonizedValues);
}, [options, setValue, getValues, model, multiple]);
const { error, helperText } = fieldKey && index && index >= 0
? (0, utils_1.errorProps)({
fieldKey,
index,
fieldKeyProp: name,
errors,
})
: {
error: errors && Boolean(errors[name]),
helperText: errors && errors[name] ? errors[name].message : schema[name].help_text || '',
};
if (options === null) {
return react_1.default.createElement(react_1.default.Fragment, null);
}
if (!disabled && !schema[model].disabled && onEditModel && optionsModel) {
return (react_1.default.createElement(react_hook_form_1.Controller, { control: control, name: name, render: ({ field }) => (react_1.default.createElement(Autocomplete_1.default, Object.assign({ key: name }, field, { id: name, options: options, disabled: schema[model].disabled === true, autoHighlight: true, isOptionEqualToValue: (option, value) => option.id === value.id, fullWidth: true, multiple: multiple, sx: sx, onChange: (e, value) => {
let valueAr = value;
if (!multiple) {
valueAr = [value];
}
const newValueAr = [];
if (valueAr) {
for (let newValue of valueAr) {
if (typeof newValue === 'string') {
const tmpId = (0, utils_1.getTmpId)();
newValue = {
id: tmpId,
label: newValue,
[labelKey]: newValue,
};
}
if (newValue && newValue.inputValue) {
const tmpId = (0, utils_1.getTmpId)();
if (onEditModel) {
// Open modal to save new item:
onEditModel({
fieldKey,
index,
model: optionsModel,
id: tmpId,
labelKey,
setValue,
getValues,
fieldsLayout,
initialValuesPartial: {
[labelKey]: newValue.inputValue,
},
});
}
// Define new Item as an "optimistic response"
newValue = {
id: tmpId,
label: newValue.inputValue,
[labelKey]: newValue.inputValue,
};
}
newValueAr.push(newValue);
}
}
field.onChange(multiple ? newValueAr : newValueAr[0]);
if (onValueChange) {
onValueChange(e);
}
}, renderInput: (params) => (react_1.default.createElement(TextField_1.default, Object.assign({}, params, { label: label, required: schema[model].required, margin: "normal", error: error, autoFocus: autoFocus, helperText: helperText, InputProps: Object.assign(Object.assign({}, params.InputProps), { endAdornment: (react_1.default.createElement(react_1.default.Fragment, null,
!multiple && field.value && (react_1.default.createElement(IconButton_1.default, { size: "small", onClick: () => {
if ((0, utils_1.isTmpId)(field.value.id)) {
setDialog({
open: true,
loading: false,
title: 'Item sendo criado',
Body: 'Este item está sendo criado agora por você. Para editar suas propriedades, salve antes, e depois você poderá editar!',
Actions: (react_1.default.createElement(DialogActions_1.default, { setDialog: setDialog, btnCancel: "Entendi" })),
});
return;
}
if (optionsModel) {
onEditModel({
fieldKey,
index,
model: optionsModel,
id: field.value.id,
labelKey,
setValue,
getValues,
fieldsLayout,
});
}
} },
react_1.default.createElement(Edit_1.default, null))),
params.InputProps.endAdornment)) }) }, other))), freeSolo: true, filterOptions: (filteredOptions, params) => {
if (filteredOptions.length === 0) {
return [];
}
let filtered = filter(filteredOptions, params);
const { inputValue } = params;
const inputValueSlug = (0, utils_1.slugify)(inputValue);
const inputValueLength = inputValueSlug.length;
// Suggest the creation of a new value
const isExisting = filteredOptions.find((option) => inputValueSlug === (0, utils_1.slugify)(option.label));
if (inputValue !== '' && !isExisting) {
filtered.push({
inputValue,
label: `Criar "${inputValue}"`,
});
}
// Show first the exact match:
if (isExisting) {
filtered = [
isExisting,
...filtered.filter((option) => isExisting.id !== option.id),
];
}
// Show first the options that start with inputValue:
const startsWith = filtered.filter((option) => inputValueSlug === (0, utils_1.slugify)(option.label).substring(0, inputValueLength));
if (startsWith.length > 0) {
const startsWithIds = startsWith.map((option) => option.id);
filtered = [
...startsWith,
...filtered.filter((option) => !startsWithIds.includes(option.id)),
];
}
return filtered;
}, handleHomeEndKeys: true, getOptionLabel: getOptionLabel
? getOptionLabel
: (option) => {
// Value selected with enter, right from the input
if (typeof option === 'string') {
return option;
}
// Criar "xxx" option created dynamically
if (option.inputValue) {
return option.inputValue;
}
// Regular option
return option.label;
}, renderOption: renderOption ? renderOption : (props, option) => react_1.default.createElement("li", Object.assign({}, props), option.label), renderTags: multiple
? (tagValue, getTagProps) => {
return tagValue.map((option, index) => (
// eslint-disable-next-line react/jsx-key
react_1.default.createElement(Chip_1.default, Object.assign({}, getTagProps({ index }), { label: option.label, icon: (0, utils_1.isTmpId)(option.id) ? (react_1.default.createElement(react_1.default.Fragment, null)) : (react_1.default.createElement(IconButton_1.default, { size: "small", onClick: () => {
if (optionsModel) {
onEditModel({
fieldKey,
index,
model: optionsModel,
id: option.id,
labelKey,
setValue,
getValues,
fieldsLayout,
});
}
} },
react_1.default.createElement(Edit_1.default, null))) }))));
}
: undefined }))) }));
}
return (react_1.default.createElement(react_hook_form_1.Controller, { control: control, name: name, render: ({ field }) => (react_1.default.createElement(Autocomplete_1.default, Object.assign({ key: name }, field, { id: name, options: options, disabled: schema[model].disabled === true || disabled === true, autoHighlight: true, isOptionEqualToValue: (option, value) => option.id === value.id, fullWidth: true, multiple: multiple, sx: sx, onChange: (e, value) => {
field.onChange(value);
if (onValueChange) {
onValueChange(e);
}
}, renderInput: (params) => (react_1.default.createElement(TextField_1.default, Object.assign({}, params, { label: label, required: schema[model].required, margin: "normal", error: error, autoFocus: autoFocus, helperText: helperText }, other))), getOptionLabel: getOptionLabel, renderOption: renderOption }))) }));
});
EditableAutocompleteFieldBySchema.displayName = 'EditableAutocompleteFieldBySchema';
exports.default = EditableAutocompleteFieldBySchema;