Add tableSection.isHidden; table.capabilities; adornmentType.CODE_EDITOR

This commit is contained in:
2022-11-01 16:29:27 -05:00
parent 860c79c405
commit 61394f4a52
10 changed files with 149 additions and 44 deletions

View File

@ -19,6 +19,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Capability} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Capability";
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
@ -73,6 +74,8 @@ function EntityForm({table, id}: Props): JSX.Element
const [tableSections, setTableSections] = useState(null as QTableSection[]);
const [, forceUpdate] = useReducer((x) => x + 1, 0);
const [noCapabilityError, setNoCapabilityError] = useState(null as string);
const {pageHeader, setPageHeader} = useContext(QContext);
const navigate = useNavigate();
@ -140,11 +143,21 @@ function EntityForm({table, id}: Props): JSX.Element
});
setFormValues(formValues);
if(!tableMetaData.capabilities.has(Capability.TABLE_UPDATE))
{
setNoCapabilityError("You may not edit records in this table");
}
}
else
{
setFormTitle(`Creating New ${tableMetaData?.label}`);
setPageHeader(`Creating New ${tableMetaData?.label}`);
if(!tableMetaData.capabilities.has(Capability.TABLE_INSERT))
{
setNoCapabilityError("You may not create records in this table");
}
}
setInitialValues(initialValues);
@ -168,6 +181,11 @@ function EntityForm({table, id}: Props): JSX.Element
const section = tableSections[i];
const sectionDynamicFormFields: any[] = [];
if(section.isHidden)
{
continue;
}
for (let j = 0; j < section.fieldNames.length; j++)
{
const fieldName = section.fieldNames[j];
@ -277,6 +295,19 @@ function EntityForm({table, id}: Props): JSX.Element
const formId = id != null ? `edit-${tableMetaData?.name}-form` : `create-${tableMetaData?.name}-form`;
if(noCapabilityError)
{
return <MDBox mb={3}>
<Grid container spacing={3}>
<Grid item xs={12}>
<MDBox mb={3}>
<Alert severity="error">{noCapabilityError}</Alert>
</MDBox>
</Grid>
</Grid>
</MDBox>;
}
return (
<MDBox mb={3}>
<Grid container spacing={3}>

View File

@ -71,7 +71,7 @@ interface QDeleteButtonProps
export function QDeleteButton({onClickHandler}: QDeleteButtonProps): JSX.Element
{
return (
<MDBox ml={3} mr={3} width={standardWidth}>
<MDBox ml={3} width={standardWidth}>
<MDButton variant="gradient" color="primary" size="small" onClick={onClickHandler} fullWidth startIcon={<Icon>delete</Icon>}>
Delete
</MDButton>
@ -82,7 +82,7 @@ export function QDeleteButton({onClickHandler}: QDeleteButtonProps): JSX.Element
export function QEditButton(): JSX.Element
{
return (
<MDBox width={standardWidth}>
<MDBox ml={3} width={standardWidth}>
<Link to="edit">
<MDButton variant="gradient" color="dark" size="small" fullWidth startIcon={<Icon>edit</Icon>}>
Edit

View File

@ -59,6 +59,11 @@ function QRecordSidebar({tableSections, widgetMetaDataList, light, stickyTop}: P
const sidebarEntries = [] as SidebarEntry[];
tableSections && tableSections.forEach((section, index) =>
{
if(section.isHidden)
{
return;
}
if (index === 1 && widgetMetaDataList)
{
widgetMetaDataList.forEach((widget) =>

View File

@ -20,6 +20,7 @@
*/
import {AdornmentType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/AdornmentType";
import {Capability} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Capability";
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
@ -584,9 +585,10 @@ function EntityList({table, launchProcess}: Props): JSX.Element
const row: any = {};
fields.forEach((field) =>
{
const value = QValueUtils.getDisplayValue(field, record);
const value = QValueUtils.getDisplayValue(field, record, "query");
if (typeof value !== "string")
{
console.log(`Need to render [${field.name}]`);
columnsToRender[field.name] = true;
}
row[field.name] = value;
@ -1146,18 +1148,27 @@ function EntityList({table, launchProcess}: Props): JSX.Element
onClose={closeActionsMenu}
keepMounted
>
<MenuItem onClick={bulkLoadClicked}>
<ListItemIcon><Icon>library_add</Icon></ListItemIcon>
Bulk Load
</MenuItem>
<MenuItem onClick={bulkEditClicked}>
<ListItemIcon><Icon>edit</Icon></ListItemIcon>
Bulk Edit
</MenuItem>
<MenuItem onClick={bulkDeleteClicked}>
<ListItemIcon><Icon>delete</Icon></ListItemIcon>
Bulk Delete
</MenuItem>
{
table.capabilities.has(Capability.TABLE_INSERT) &&
<MenuItem onClick={bulkLoadClicked}>
<ListItemIcon><Icon>library_add</Icon></ListItemIcon>
Bulk Load
</MenuItem>
}
{
table.capabilities.has(Capability.TABLE_UPDATE) &&
<MenuItem onClick={bulkEditClicked}>
<ListItemIcon><Icon>edit</Icon></ListItemIcon>
Bulk Edit
</MenuItem>
}
{
table.capabilities.has(Capability.TABLE_DELETE) &&
<MenuItem onClick={bulkDeleteClicked}>
<ListItemIcon><Icon>delete</Icon></ListItemIcon>
Bulk Delete
</MenuItem>
}
{tableProcesses.length > 0 && <Divider />}
{tableProcesses.map((process) => (
<MenuItem key={process.name} onClick={() => processClicked(process)}>
@ -1165,6 +1176,13 @@ function EntityList({table, launchProcess}: Props): JSX.Element
{process.label}
</MenuItem>
))}
{
tableProcesses.length == 0 && !table.capabilities.has(Capability.TABLE_INSERT) && !table.capabilities.has(Capability.TABLE_UPDATE) && !table.capabilities.has(Capability.TABLE_DELETE) &&
<MenuItem disabled>
<ListItemIcon><Icon>block</Icon></ListItemIcon>
<i>No actions available</i>
</MenuItem>
}
</Menu>
);
@ -1226,7 +1244,10 @@ function EntityList({table, launchProcess}: Props): JSX.Element
{renderActionsMenu}
</MDBox>
<QCreateNewButton />
{
table.capabilities.has(Capability.TABLE_INSERT) &&
<QCreateNewButton />
}
</MDBox>
<Card>
@ -1244,6 +1265,7 @@ function EntityList({table, launchProcess}: Props): JSX.Element
disableSelectionOnClick
autoHeight
rows={rows}
// getRowHeight={() => "auto"} // maybe nice? wraps values in cells...
columns={columnsModel}
rowBuffer={10}
rowCount={totalRecords === null ? 0 : totalRecords}

View File

@ -423,7 +423,7 @@ function EntityDeveloperView({table}: Props): JSX.Element
</Card>
{
associatedScripts.map((object) =>
associatedScripts && associatedScripts.map((object) =>
{
let fieldName = object.associatedScript?.fieldName;
let field = tableMetaData.fields.get(fieldName);

View File

@ -20,6 +20,7 @@
*/
import {QException} from "@kingsrook/qqq-frontend-core/lib/exceptions/QException";
import {Capability} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Capability";
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
@ -234,6 +235,11 @@ function EntityView({table, launchProcess}: Props): JSX.Element
for (let i = 0; i < tableSections.length; i++)
{
const section = tableSections[i];
if(section.isHidden)
{
continue;
}
sectionFieldElements.set(
section.name,
<MDBox key={section.name} display="flex" flexDirection="column" py={1} pr={2}>
@ -244,7 +250,7 @@ function EntityView({table, launchProcess}: Props): JSX.Element
{tableMetaData.fields.get(fieldName).label}:
</MDTypography>
<MDTypography variant="button" fontWeight="regular" color="text">
{QValueUtils.getDisplayValue(tableMetaData.fields.get(fieldName), record)}
{QValueUtils.getDisplayValue(tableMetaData.fields.get(fieldName), record, "view")}
</MDTypography>
</MDBox>
))
@ -313,27 +319,33 @@ function EntityView({table, launchProcess}: Props): JSX.Element
onClose={closeActionsMenu}
keepMounted
>
<MenuItem onClick={() => navigate("edit")}>
<ListItemIcon><Icon>edit</Icon></ListItemIcon>
Edit
</MenuItem>
<MenuItem onClick={() =>
{
setActionsMenu(null);
handleClickDeleteButton();
}}
>
<ListItemIcon><Icon>delete</Icon></ListItemIcon>
Delete
</MenuItem>
{tableProcesses.length > 0 && <Divider />}
table.capabilities.has(Capability.TABLE_UPDATE) &&
<MenuItem onClick={() => navigate("edit")}>
<ListItemIcon><Icon>edit</Icon></ListItemIcon>
Edit
</MenuItem>
}
{
table.capabilities.has(Capability.TABLE_DELETE) &&
<MenuItem onClick={() =>
{
setActionsMenu(null);
handleClickDeleteButton();
}}
>
<ListItemIcon><Icon>delete</Icon></ListItemIcon>
Delete
</MenuItem>
}
{tableProcesses.length > 0 && (table.capabilities.has(Capability.TABLE_UPDATE) || table.capabilities.has(Capability.TABLE_DELETE)) && <Divider />}
{tableProcesses.map((process) => (
<MenuItem key={process.name} onClick={() => processClicked(process)}>
<ListItemIcon><Icon>{process.iconName ?? "arrow_forward"}</Icon></ListItemIcon>
{process.label}
</MenuItem>
))}
<Divider />
{tableProcesses.length > 0 && <Divider />}
<MenuItem onClick={() => navigate("dev")}>
<ListItemIcon><Icon>data_object</Icon></ListItemIcon>
Developer Mode
@ -433,8 +445,12 @@ function EntityView({table, launchProcess}: Props): JSX.Element
)) : null}
<MDBox component="form" p={3}>
<Grid container justifyContent="flex-end" spacing={3}>
<QDeleteButton onClickHandler={handleClickDeleteButton} />
<QEditButton />
{
table.capabilities.has(Capability.TABLE_DELETE) && <QDeleteButton onClickHandler={handleClickDeleteButton} />
}
{
table.capabilities.has(Capability.TABLE_UPDATE) && <QEditButton />
}
</Grid>
</MDBox>

View File

@ -253,7 +253,7 @@ function QValidationReview({
{" "}
&nbsp;
{" "}
{QValueUtils.getDisplayValue(field, previewRecords[previewRecordIndex])}
{QValueUtils.getDisplayValue(field, previewRecords[previewRecordIndex], "view")}
</MDBox>
))
}

View File

@ -362,8 +362,11 @@ function ProcessRun({process, defaultProcessValues, isModal, recordIds, closeMod
{localTableSections.map((section: QTableSection, index: number) =>
{
const name = section.name
console.log(formData);
console.log(section.fieldNames);
if(section.isHidden)
{
return ;
}
const sectionFormFields = {};
for(let i = 0; i<section.fieldNames.length; i++)
@ -424,7 +427,7 @@ function ProcessRun({process, defaultProcessValues, isModal, recordIds, closeMod
: &nbsp;
</MDTypography>
<MDTypography variant="button" fontWeight="regular" color="text">
{QValueUtils.getValueForDisplay(field, processValues[field.name])}
{QValueUtils.getValueForDisplay(field, processValues[field.name], "view")}
</MDTypography>
</MDBox>
))}

View File

@ -25,8 +25,9 @@ import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QField
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
import "datejs";
import {Chip, Icon} from "@mui/material";
import {Chip, Icon, Typography} from "@mui/material";
import React, {Fragment} from "react";
import AceEditor from "react-ace";
import {Link} from "react-router-dom";
import QClient from "qqq/utils/QClient";
@ -66,19 +67,19 @@ class QValueUtils
** When you have a field, and a record - call this method to get a string or
** element back to display the field's value.
*******************************************************************************/
public static getDisplayValue(field: QFieldMetaData, record: QRecord): string | JSX.Element
public static getDisplayValue(field: QFieldMetaData, record: QRecord, usage: "view" | "query" = "view"): string | JSX.Element
{
const displayValue = record.displayValues ? record.displayValues.get(field.name) : undefined;
const rawValue = record.values ? record.values.get(field.name) : undefined;
return QValueUtils.getValueForDisplay(field, rawValue, displayValue);
return QValueUtils.getValueForDisplay(field, rawValue, displayValue, usage);
}
/*******************************************************************************
** When you have a field and a value (either just a raw value, or a raw and
** display value), call this method to get a string Element to display.
*******************************************************************************/
public static getValueForDisplay(field: QFieldMetaData, rawValue: any, displayValue: any = rawValue): string | JSX.Element
public static getValueForDisplay(field: QFieldMetaData, rawValue: any, displayValue: any = rawValue, usage: "view" | "query" = "view"): string | JSX.Element
{
if (field.hasAdornment(AdornmentType.LINK))
{
@ -141,6 +142,28 @@ class QValueUtils
return (<Chip label={displayValue} color={color} icon={iconElement} size="small" variant="outlined" sx={{fontWeight: 500}} />);
}
if (field.hasAdornment(AdornmentType.CODE_EDITOR))
{
if(usage === "view")
{
return (<AceEditor
mode="javascript"
theme="github"
name={field.name}
editorProps={{$blockScrolling: true}}
value={rawValue}
readOnly
width="100%"
showPrintMargin={false}
height="200px"
/>);
}
else
{
return rawValue;
}
}
return (QValueUtils.getUnadornedValueForDisplay(field, rawValue, displayValue));
}
@ -227,6 +250,11 @@ class QValueUtils
public static breakTextIntoLines(value: string): JSX.Element
{
if(!value)
{
return <Fragment />;
}
return (
<Fragment>
{value.split(/\n/).map((value: string, index: number) => (