mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
Add tableSection.isHidden; table.capabilities; adornmentType.CODE_EDITOR
This commit is contained in:
@ -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}>
|
||||
|
@ -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
|
||||
|
@ -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) =>
|
||||
|
@ -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}
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
||||
|
@ -253,7 +253,7 @@ function QValidationReview({
|
||||
{" "}
|
||||
|
||||
{" "}
|
||||
{QValueUtils.getDisplayValue(field, previewRecords[previewRecordIndex])}
|
||||
{QValueUtils.getDisplayValue(field, previewRecords[previewRecordIndex], "view")}
|
||||
</MDBox>
|
||||
))
|
||||
}
|
||||
|
@ -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
|
||||
:
|
||||
</MDTypography>
|
||||
<MDTypography variant="button" fontWeight="regular" color="text">
|
||||
{QValueUtils.getValueForDisplay(field, processValues[field.name])}
|
||||
{QValueUtils.getValueForDisplay(field, processValues[field.name], "view")}
|
||||
</MDTypography>
|
||||
</MDBox>
|
||||
))}
|
||||
|
@ -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) => (
|
||||
|
Reference in New Issue
Block a user