mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 21:30:45 +00:00
Merge branch 'integration/sprint-28' into feature/CTLE-214-dot-menu
This commit is contained in:
@ -118,12 +118,12 @@ function ChipTextField({...props})
|
||||
return (
|
||||
<div id="chip-text-field-container" style={{flexWrap: "wrap", display:"flex"}}>
|
||||
<TextField
|
||||
sx={{width: "100%"}}
|
||||
sx={{width: "99%"}}
|
||||
disabled={disabled}
|
||||
label={label}
|
||||
InputProps={{
|
||||
startAdornment:
|
||||
<div>
|
||||
<div style={{overflowY: "auto", overflowX: "hidden", margin: "-10px", width: "calc(100% + 20px)", padding: "10px", marginBottom: "-20px", height: "calc(100% + 10px)"}}>
|
||||
{
|
||||
chips.map((item, i) => (
|
||||
<Chip
|
||||
|
@ -38,6 +38,7 @@ interface Props
|
||||
tableName?: string;
|
||||
processName?: string;
|
||||
fieldName: string;
|
||||
overrideId?: string;
|
||||
fieldLabel: string;
|
||||
inForm: boolean;
|
||||
initialValue?: any;
|
||||
@ -70,29 +71,34 @@ DynamicSelect.defaultProps = {
|
||||
|
||||
const qController = Client.getInstance();
|
||||
|
||||
function DynamicSelect({tableName, processName, fieldName, fieldLabel, inForm, initialValue, initialDisplayValue, initialValues, onChange, isEditable, isMultiple, bulkEditMode, bulkEditSwitchChangeHandler, otherValues}: Props)
|
||||
function DynamicSelect({tableName, processName, fieldName, overrideId, fieldLabel, inForm, initialValue, initialDisplayValue, initialValues, onChange, isEditable, isMultiple, bulkEditMode, bulkEditSwitchChangeHandler, otherValues}: Props)
|
||||
{
|
||||
const [ open, setOpen ] = useState(false);
|
||||
const [ options, setOptions ] = useState<readonly QPossibleValue[]>([]);
|
||||
const [ searchTerm, setSearchTerm ] = useState(null);
|
||||
const [ firstRender, setFirstRender ] = useState(true);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [options, setOptions] = useState<readonly QPossibleValue[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState(null);
|
||||
const [firstRender, setFirstRender] = useState(true);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// default value - needs to be an array (from initialValues (array) prop) for multiple mode - //
|
||||
// else non-multiple, assume we took in an initialValue (id) and initialDisplayValue (label), //
|
||||
// and build a little object that looks like a possibleValue out of those //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const [defaultValue, _] = isMultiple ? useState(initialValues ?? undefined)
|
||||
let [defaultValue, _] = isMultiple ? useState(initialValues ?? undefined)
|
||||
: useState(initialValue && initialDisplayValue ? [{id: initialValue, label: initialDisplayValue}] : null);
|
||||
|
||||
if (isMultiple && defaultValue === null)
|
||||
{
|
||||
defaultValue = [];
|
||||
}
|
||||
|
||||
// const loading = open && options.length === 0;
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [ switchChecked, setSwitchChecked ] = useState(false);
|
||||
const [ isDisabled, setIsDisabled ] = useState(!isEditable || bulkEditMode);
|
||||
const [switchChecked, setSwitchChecked] = useState(false);
|
||||
const [isDisabled, setIsDisabled] = useState(!isEditable || bulkEditMode);
|
||||
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
|
||||
|
||||
let setFieldValueRef: (field: string, value: any, shouldValidate?: boolean) => void = null;
|
||||
if(inForm)
|
||||
if (inForm)
|
||||
{
|
||||
const {setFieldValue} = useFormikContext();
|
||||
setFieldValueRef = setFieldValue;
|
||||
@ -239,9 +245,11 @@ function DynamicSelect({tableName, processName, fieldName, fieldLabel, inForm, i
|
||||
bulkEditSwitchChangeHandler(fieldName, newSwitchValue);
|
||||
};
|
||||
|
||||
// console.log(`default value: ${JSON.stringify(defaultValue)}`);
|
||||
|
||||
const autocomplete = (
|
||||
<Autocomplete
|
||||
id={fieldName}
|
||||
id={overrideId ?? fieldName}
|
||||
sx={{background: isDisabled ? "#f0f2f5!important" : "initial"}}
|
||||
open={open}
|
||||
fullWidth
|
||||
@ -291,6 +299,8 @@ function DynamicSelect({tableName, processName, fieldName, fieldLabel, inForm, i
|
||||
disabled={isDisabled}
|
||||
multiple={isMultiple}
|
||||
disableCloseOnSelect={isMultiple}
|
||||
limitTags={5}
|
||||
slotProps={{popper: {className: "DynamicSelectPopper"}}}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
|
@ -54,6 +54,7 @@ interface Props
|
||||
closeModalHandler?: (event: object, reason: string) => void;
|
||||
defaultValues: { [key: string]: string };
|
||||
disabledFields: { [key: string]: boolean } | string[];
|
||||
isDuplicate?: boolean;
|
||||
}
|
||||
|
||||
EntityForm.defaultProps = {
|
||||
@ -63,6 +64,7 @@ EntityForm.defaultProps = {
|
||||
closeModalHandler: null,
|
||||
defaultValues: {},
|
||||
disabledFields: {},
|
||||
isDuplicate: false
|
||||
};
|
||||
|
||||
function EntityForm(props: Props): JSX.Element
|
||||
@ -133,6 +135,15 @@ function EntityForm(props: Props): JSX.Element
|
||||
for (let i = 0; i < formFields.length; i++)
|
||||
{
|
||||
formData.formFields[formFields[i].name] = formFields[i];
|
||||
|
||||
if (formFields[i].possibleValueProps)
|
||||
{
|
||||
formFields[i].possibleValueProps.otherValues = formFields[i].possibleValueProps.otherValues ?? new Map<string, any>();
|
||||
Object.keys(formFields).forEach((otherKey) =>
|
||||
{
|
||||
formFields[i].possibleValueProps.otherValues.set(otherKey, values[otherKey]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!Object.keys(formFields).length)
|
||||
@ -164,24 +175,30 @@ function EntityForm(props: Props): JSX.Element
|
||||
fieldArray.push(fieldMetaData);
|
||||
});
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// if doing an edit, fetch the record and pre-populate the form values from it //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if doing an edit or duplicate, fetch the record and pre-populate the form values from it //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
let record: QRecord = null;
|
||||
let defaultDisplayValues = new Map<string, string>();
|
||||
if (props.id !== null)
|
||||
{
|
||||
record = await qController.get(tableName, props.id);
|
||||
setRecord(record);
|
||||
setFormTitle(`Edit ${tableMetaData?.label}: ${record?.recordLabel}`);
|
||||
|
||||
const titleVerb = props.isDuplicate ? "Duplicate" : "Edit";
|
||||
setFormTitle(`${titleVerb} ${tableMetaData?.label}: ${record?.recordLabel}`);
|
||||
|
||||
if (!props.isModal)
|
||||
{
|
||||
setPageHeader(`Edit ${tableMetaData?.label}: ${record?.recordLabel}`);
|
||||
setPageHeader(`${titleVerb} ${tableMetaData?.label}: ${record?.recordLabel}`);
|
||||
}
|
||||
|
||||
tableMetaData.fields.forEach((fieldMetaData, key) =>
|
||||
{
|
||||
if (props.isDuplicate && fieldMetaData.name == tableMetaData.primaryKeyField)
|
||||
{
|
||||
return;
|
||||
}
|
||||
initialValues[key] = record.values.get(key);
|
||||
});
|
||||
|
||||
@ -206,15 +223,6 @@ function EntityForm(props: Props): JSX.Element
|
||||
setPageHeader(`Creating New ${tableMetaData?.label}`);
|
||||
}
|
||||
|
||||
if (!tableMetaData.capabilities.has(Capability.TABLE_INSERT))
|
||||
{
|
||||
setNotAllowedError("Records may not be created in this table");
|
||||
}
|
||||
else if (!tableMetaData.insertPermission)
|
||||
{
|
||||
setNotAllowedError(`You do not have permission to create ${tableMetaData.label} records`);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if default values were supplied for a new record, then populate initialValues, for formik. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -245,6 +253,32 @@ function EntityForm(props: Props): JSX.Element
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// check capabilities & permissions //
|
||||
//////////////////////////////////////
|
||||
if (props.isDuplicate || !props.id)
|
||||
{
|
||||
if (!tableMetaData.capabilities.has(Capability.TABLE_INSERT))
|
||||
{
|
||||
setNotAllowedError("Records may not be created in this table");
|
||||
}
|
||||
else if (!tableMetaData.insertPermission)
|
||||
{
|
||||
setNotAllowedError(`You do not have permission to create ${tableMetaData.label} records`);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tableMetaData.capabilities.has(Capability.TABLE_UPDATE))
|
||||
{
|
||||
setNotAllowedError("Records may not be edited in this table");
|
||||
}
|
||||
else if (!tableMetaData.editPermission)
|
||||
{
|
||||
setNotAllowedError(`You do not have permission to edit ${tableMetaData.label} records`);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// make sure all initialValues are properly formatted for the form //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -307,11 +341,11 @@ function EntityForm(props: Props): JSX.Element
|
||||
const fieldName = section.fieldNames[j];
|
||||
const field = tableMetaData.fields.get(fieldName);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if id !== null - means we're on the edit screen -- show all fields on the edit screen. //
|
||||
// || (or) we're on the insert screen in which case, only show editable fields. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (props.id !== null || field.isEditable)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if id !== null (and we're not duplicating) - means we're on the edit screen -- show all fields on the edit screen. //
|
||||
// || (or) we're on the insert screen in which case, only show editable fields. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if ((props.id !== null && !props.isDuplicate) || field.isEditable)
|
||||
{
|
||||
sectionDynamicFormFields.push(dynamicFormFields[fieldName]);
|
||||
}
|
||||
@ -359,7 +393,12 @@ function EntityForm(props: Props): JSX.Element
|
||||
// but if the user used the anchors on the page, this doesn't effectively cancel... //
|
||||
// what we have here pushed a new history entry (I think?), so could be better //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
if (props.id !== null)
|
||||
if (props.id !== null && props.isDuplicate)
|
||||
{
|
||||
const path = `${location.pathname.replace(/\/duplicate$/, "")}`;
|
||||
navigate(path, {replace: true});
|
||||
}
|
||||
else if (props.id !== null)
|
||||
{
|
||||
const path = `${location.pathname.replace(/\/edit$/, "")}`;
|
||||
navigate(path, {replace: true});
|
||||
@ -419,8 +458,9 @@ function EntityForm(props: Props): JSX.Element
|
||||
}
|
||||
}
|
||||
|
||||
if (props.id !== null)
|
||||
if (props.id !== null && !props.isDuplicate)
|
||||
{
|
||||
// todo - audit that it's a dupe
|
||||
await qController
|
||||
.update(tableName, props.id, values)
|
||||
.then((record) =>
|
||||
@ -464,7 +504,9 @@ function EntityForm(props: Props): JSX.Element
|
||||
}
|
||||
else
|
||||
{
|
||||
const path = location.pathname.replace(/create$/, record.values.get(tableMetaData.primaryKeyField));
|
||||
const path = props.isDuplicate ?
|
||||
location.pathname.replace(new RegExp(`/${props.id}/duplicate$`), "/" + record.values.get(tableMetaData.primaryKeyField))
|
||||
: location.pathname.replace(/create$/, record.values.get(tableMetaData.primaryKeyField));
|
||||
navigate(path, {state: {createSuccess: true}});
|
||||
}
|
||||
})
|
||||
@ -472,8 +514,9 @@ function EntityForm(props: Props): JSX.Element
|
||||
{
|
||||
if(error.message.toLowerCase().startsWith("warning"))
|
||||
{
|
||||
const path = location.pathname.replace(/create$/, record.values.get(tableMetaData.primaryKeyField));
|
||||
navigate(path);
|
||||
const path = props.isDuplicate ?
|
||||
location.pathname.replace(new RegExp(`/${props.id}/duplicate$`), "/" + record.values.get(tableMetaData.primaryKeyField))
|
||||
: location.pathname.replace(/create$/, record.values.get(tableMetaData.primaryKeyField));
|
||||
navigate(path, {state: {createSuccess: true, warning: error.message}});
|
||||
}
|
||||
else
|
||||
|
Reference in New Issue
Block a user