Add Duplicate!

This commit is contained in:
2023-06-21 12:14:39 -05:00
parent 22caabb952
commit 45063ac416
3 changed files with 73 additions and 30 deletions

View File

@ -54,6 +54,7 @@ interface Props
closeModalHandler?: (event: object, reason: string) => void; closeModalHandler?: (event: object, reason: string) => void;
defaultValues: { [key: string]: string }; defaultValues: { [key: string]: string };
disabledFields: { [key: string]: boolean } | string[]; disabledFields: { [key: string]: boolean } | string[];
isDuplicate?: boolean;
} }
EntityForm.defaultProps = { EntityForm.defaultProps = {
@ -63,6 +64,7 @@ EntityForm.defaultProps = {
closeModalHandler: null, closeModalHandler: null,
defaultValues: {}, defaultValues: {},
disabledFields: {}, disabledFields: {},
isDuplicate: false
}; };
function EntityForm(props: Props): JSX.Element function EntityForm(props: Props): JSX.Element
@ -173,24 +175,30 @@ function EntityForm(props: Props): JSX.Element
fieldArray.push(fieldMetaData); 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 record: QRecord = null;
let defaultDisplayValues = new Map<string, string>(); let defaultDisplayValues = new Map<string, string>();
if (props.id !== null) if (props.id !== null)
{ {
record = await qController.get(tableName, props.id); record = await qController.get(tableName, props.id);
setRecord(record); setRecord(record);
setFormTitle(`Edit ${tableMetaData?.label}: ${record?.recordLabel}`);
const titleVerb = props.isDuplicate ? "Duplicate" : "Edit";
setFormTitle(`${titleVerb} ${tableMetaData?.label}: ${record?.recordLabel}`);
if (!props.isModal) if (!props.isModal)
{ {
setPageHeader(`Edit ${tableMetaData?.label}: ${record?.recordLabel}`); setPageHeader(`${titleVerb} ${tableMetaData?.label}: ${record?.recordLabel}`);
} }
tableMetaData.fields.forEach((fieldMetaData, key) => tableMetaData.fields.forEach((fieldMetaData, key) =>
{ {
if (props.isDuplicate && fieldMetaData.name == tableMetaData.primaryKeyField)
{
return;
}
initialValues[key] = record.values.get(key); initialValues[key] = record.values.get(key);
}); });
@ -215,15 +223,6 @@ function EntityForm(props: Props): JSX.Element
setPageHeader(`Creating New ${tableMetaData?.label}`); 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. // // if default values were supplied for a new record, then populate initialValues, for formik. //
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
@ -254,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 // // make sure all initialValues are properly formatted for the form //
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -316,11 +341,11 @@ function EntityForm(props: Props): JSX.Element
const fieldName = section.fieldNames[j]; const fieldName = section.fieldNames[j];
const field = tableMetaData.fields.get(fieldName); const field = tableMetaData.fields.get(fieldName);
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if id !== null - means we're on the edit screen -- show all fields on the edit screen. // // 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. // // || (or) we're on the insert screen in which case, only show editable fields. //
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (props.id !== null || field.isEditable) if ((props.id !== null && !props.isDuplicate) || field.isEditable)
{ {
sectionDynamicFormFields.push(dynamicFormFields[fieldName]); sectionDynamicFormFields.push(dynamicFormFields[fieldName]);
} }
@ -368,7 +393,12 @@ function EntityForm(props: Props): JSX.Element
// but if the user used the anchors on the page, this doesn't effectively cancel... // // 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 // // 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$/, "")}`; const path = `${location.pathname.replace(/\/edit$/, "")}`;
navigate(path, {replace: true}); navigate(path, {replace: true});
@ -428,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 await qController
.update(tableName, props.id, values) .update(tableName, props.id, values)
.then((record) => .then((record) =>
@ -473,7 +504,9 @@ function EntityForm(props: Props): JSX.Element
} }
else 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}}); navigate(path, {state: {createSuccess: true}});
} }
}) })
@ -481,8 +514,9 @@ function EntityForm(props: Props): JSX.Element
{ {
if(error.message.toLowerCase().startsWith("warning")) if(error.message.toLowerCase().startsWith("warning"))
{ {
const path = location.pathname.replace(/create$/, record.values.get(tableMetaData.primaryKeyField)); const path = props.isDuplicate ?
navigate(path); 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}}); navigate(path, {state: {createSuccess: true, warning: error.message}});
} }
else else

View File

@ -29,9 +29,15 @@ import BaseLayout from "qqq/layouts/BaseLayout";
interface Props interface Props
{ {
table?: QTableMetaData; table?: QTableMetaData;
isDuplicate?: boolean
} }
function EntityEdit({table}: Props): JSX.Element EntityEdit.defaultProps = {
table: null,
isDuplicate: false
};
function EntityEdit({table, isDuplicate}: Props): JSX.Element
{ {
const {id} = useParams(); const {id} = useParams();
@ -43,7 +49,7 @@ function EntityEdit({table}: Props): JSX.Element
<Box mb={3}> <Box mb={3}>
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={12}> <Grid item xs={12}>
<EntityForm table={table} id={id} /> <EntityForm table={table} id={id} isDuplicate={isDuplicate} />
</Grid> </Grid>
</Grid> </Grid>
</Box> </Box>
@ -54,8 +60,4 @@ function EntityEdit({table}: Props): JSX.Element
); );
} }
EntityEdit.defaultProps = {
table: null,
};
export default EntityEdit; export default EntityEdit;

View File

@ -534,6 +534,13 @@ function RecordView({table, launchProcess}: Props): JSX.Element
Create New Create New
</MenuItem> </MenuItem>
} }
{
table.capabilities.has(Capability.TABLE_INSERT) && table.insertPermission &&
<MenuItem onClick={() => navigate("duplicate")}>
<ListItemIcon><Icon>copy</Icon></ListItemIcon>
Create Duplicate
</MenuItem>
}
{ {
table.capabilities.has(Capability.TABLE_UPDATE) && table.editPermission && table.capabilities.has(Capability.TABLE_UPDATE) && table.editPermission &&
<MenuItem onClick={() => navigate("edit")}> <MenuItem onClick={() => navigate("edit")}>