mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-22 23:28:44 +00:00
Compare commits
4 Commits
snapshot-f
...
snapshot-f
Author | SHA1 | Date | |
---|---|---|---|
5e3991d9ae | |||
f1826c81a9 | |||
230aaeef8c | |||
edab918763 |
@ -25,7 +25,7 @@ import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QT
|
|||||||
import {QJobComplete} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobComplete";
|
import {QJobComplete} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobComplete";
|
||||||
import {QJobError} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobError";
|
import {QJobError} from "@kingsrook/qqq-frontend-core/lib/model/processes/QJobError";
|
||||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||||
import {Alert, Button, Link} from "@mui/material";
|
import {Alert, Button} from "@mui/material";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Dialog from "@mui/material/Dialog";
|
import Dialog from "@mui/material/Dialog";
|
||||||
import DialogActions from "@mui/material/DialogActions";
|
import DialogActions from "@mui/material/DialogActions";
|
||||||
@ -40,14 +40,14 @@ import TextField from "@mui/material/TextField";
|
|||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import {TooltipProps} from "@mui/material/Tooltip/Tooltip";
|
import {TooltipProps} from "@mui/material/Tooltip/Tooltip";
|
||||||
import FormData from "form-data";
|
import FormData from "form-data";
|
||||||
import React, {useContext, useEffect, useRef, useState} from "react";
|
|
||||||
import {useLocation, useNavigate} from "react-router-dom";
|
|
||||||
import QContext from "QContext";
|
import QContext from "QContext";
|
||||||
import colors from "qqq/assets/theme/base/colors";
|
import colors from "qqq/assets/theme/base/colors";
|
||||||
import {QCancelButton, QDeleteButton, QSaveButton} from "qqq/components/buttons/DefaultButtons";
|
import {QCancelButton, QDeleteButton, QSaveButton} from "qqq/components/buttons/DefaultButtons";
|
||||||
import RecordQueryView from "qqq/models/query/RecordQueryView";
|
import RecordQueryView from "qqq/models/query/RecordQueryView";
|
||||||
import FilterUtils from "qqq/utils/qqq/FilterUtils";
|
import FilterUtils from "qqq/utils/qqq/FilterUtils";
|
||||||
import {SavedViewUtils} from "qqq/utils/qqq/SavedViewUtils";
|
import {SavedViewUtils} from "qqq/utils/qqq/SavedViewUtils";
|
||||||
|
import React, {useContext, useEffect, useRef, useState} from "react";
|
||||||
|
import {useLocation, useNavigate} from "react-router-dom";
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
@ -227,6 +227,12 @@ function SavedViews({qController, metaData, tableMetaData, currentSavedView, tab
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
const viewObject = JSON.parse(JSON.stringify(view));
|
const viewObject = JSON.parse(JSON.stringify(view));
|
||||||
viewObject.queryFilter = JSON.parse(JSON.stringify(FilterUtils.convertFilterPossibleValuesToIds(viewObject.queryFilter)));
|
viewObject.queryFilter = JSON.parse(JSON.stringify(FilterUtils.convertFilterPossibleValuesToIds(viewObject.queryFilter)));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// strip away incomplete filters too, just for cleaner saved view filters //
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
FilterUtils.stripAwayIncompleteCriteria(viewObject.queryFilter)
|
||||||
|
|
||||||
formData.append("viewJson", JSON.stringify(viewObject));
|
formData.append("viewJson", JSON.stringify(viewObject));
|
||||||
|
|
||||||
if (isSaveFilterAs || isRenameFilter || currentSavedView == null)
|
if (isSaveFilterAs || isRenameFilter || currentSavedView == null)
|
||||||
|
@ -410,7 +410,7 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
|
|||||||
let counter = 0;
|
let counter = 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flexWrap="wrap" fontSize="0.875rem">
|
<React.Fragment>
|
||||||
{thisQueryFilter.criteria?.map((criteria, i) =>
|
{thisQueryFilter.criteria?.map((criteria, i) =>
|
||||||
{
|
{
|
||||||
const {criteriaIsValid} = validateCriteria(criteria, null);
|
const {criteriaIsValid} = validateCriteria(criteria, null);
|
||||||
@ -446,7 +446,7 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}))}
|
}))}
|
||||||
</Box>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -821,7 +821,9 @@ const BasicAndAdvancedQueryControls = forwardRef((props: BasicAndAdvancedQueryCo
|
|||||||
pb={"0.125rem"}
|
pb={"0.125rem"}
|
||||||
boxShadow={"inset 0px 0px 4px 2px #EFEFED"}
|
boxShadow={"inset 0px 0px 4px 2px #EFEFED"}
|
||||||
>
|
>
|
||||||
{queryToAdvancedString(queryFilter)}
|
<Box display="flex" flexWrap="wrap" fontSize="0.875rem">
|
||||||
|
{queryToAdvancedString(queryFilter)}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -63,6 +63,8 @@ export default class RecordQueryView
|
|||||||
|
|
||||||
view.queryFilter = json.queryFilter as QQueryFilter;
|
view.queryFilter = json.queryFilter as QQueryFilter;
|
||||||
|
|
||||||
|
FilterUtils.stripAwayIncompleteCriteria(view.queryFilter)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// it's important that some criteria values exist as expression objects - so - do that. //
|
// it's important that some criteria values exist as expression objects - so - do that. //
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -447,9 +447,19 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
// recursively prep subfilters as well //
|
||||||
|
/////////////////////////////////////////
|
||||||
|
let subFilters = [] as QQueryFilter[];
|
||||||
|
for (let j = 0; j < sourceFilter?.subFilters?.length; j++)
|
||||||
|
{
|
||||||
|
subFilters.push(prepQueryFilterForBackend(sourceFilter.subFilters[j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
filterForBackend.subFilters = subFilters;
|
||||||
filterForBackend.skip = pageNumber * rowsPerPage;
|
filterForBackend.skip = pageNumber * rowsPerPage;
|
||||||
filterForBackend.limit = rowsPerPage;
|
filterForBackend.limit = rowsPerPage;
|
||||||
|
|
||||||
return filterForBackend;
|
return filterForBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -701,8 +711,27 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
|
|||||||
const doSetView = (view: RecordQueryView): void =>
|
const doSetView = (view: RecordQueryView): void =>
|
||||||
{
|
{
|
||||||
setView(view);
|
setView(view);
|
||||||
setViewAsJson(JSON.stringify(view));
|
const viewAsJSON = JSON.stringify(view);
|
||||||
localStorage.setItem(viewLocalStorageKey, JSON.stringify(view));
|
setViewAsJson(viewAsJSON);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// in case there's an incomplete criteria in the view (e.g., w/o a fieldName), //
|
||||||
|
// don't store that in local storage - we don't want that, it's messy, and it //
|
||||||
|
// has caused fails in the past. So, clone the view, and strip away such things. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const viewForLocalStorage: RecordQueryView = JSON.parse(viewAsJSON);
|
||||||
|
if (viewForLocalStorage?.queryFilter?.criteria?.length > 0)
|
||||||
|
{
|
||||||
|
FilterUtils.stripAwayIncompleteCriteria(viewForLocalStorage.queryFilter)
|
||||||
|
}
|
||||||
|
localStorage.setItem(viewLocalStorageKey, JSON.stringify(viewForLocalStorage));
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
console.log("Error storing view in local storage: " + e)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,8 +46,6 @@ import Menu from "@mui/material/Menu";
|
|||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import Modal from "@mui/material/Modal";
|
import Modal from "@mui/material/Modal";
|
||||||
import Tooltip from "@mui/material/Tooltip/Tooltip";
|
import Tooltip from "@mui/material/Tooltip/Tooltip";
|
||||||
import React, {useContext, useEffect, useState} from "react";
|
|
||||||
import {useLocation, useNavigate, useParams} from "react-router-dom";
|
|
||||||
import QContext from "QContext";
|
import QContext from "QContext";
|
||||||
import colors from "qqq/assets/theme/base/colors";
|
import colors from "qqq/assets/theme/base/colors";
|
||||||
import AuditBody from "qqq/components/audits/AuditBody";
|
import AuditBody from "qqq/components/audits/AuditBody";
|
||||||
@ -65,6 +63,8 @@ import Client from "qqq/utils/qqq/Client";
|
|||||||
import ProcessUtils from "qqq/utils/qqq/ProcessUtils";
|
import ProcessUtils from "qqq/utils/qqq/ProcessUtils";
|
||||||
import TableUtils from "qqq/utils/qqq/TableUtils";
|
import TableUtils from "qqq/utils/qqq/TableUtils";
|
||||||
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
import ValueUtils from "qqq/utils/qqq/ValueUtils";
|
||||||
|
import React, {useContext, useEffect, useState} from "react";
|
||||||
|
import {useLocation, useNavigate, useParams} from "react-router-dom";
|
||||||
|
|
||||||
const qController = Client.getInstance();
|
const qController = Client.getInstance();
|
||||||
|
|
||||||
@ -148,9 +148,9 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
///////////////////////
|
///////////////////////
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
if(tableMetaData == null)
|
if (tableMetaData == null)
|
||||||
{
|
{
|
||||||
(async() =>
|
(async () =>
|
||||||
{
|
{
|
||||||
const tableMetaData = await qController.loadTableMetaData(tableName);
|
const tableMetaData = await qController.loadTableMetaData(tableName);
|
||||||
setTableMetaData(tableMetaData);
|
setTableMetaData(tableMetaData);
|
||||||
@ -162,54 +162,54 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
const type = (e.target as any).type;
|
const type = (e.target as any).type;
|
||||||
const validType = (type !== "text" && type !== "textarea" && type !== "input" && type !== "search");
|
const validType = (type !== "text" && type !== "textarea" && type !== "input" && type !== "search");
|
||||||
|
|
||||||
if(validType && !dotMenuOpen && !keyboardHelpOpen && !showAudit && !showEditChildForm)
|
if (validType && !dotMenuOpen && !keyboardHelpOpen && !showAudit && !showEditChildForm)
|
||||||
{
|
{
|
||||||
if (! e.metaKey && e.key === "n" && table.capabilities.has(Capability.TABLE_INSERT) && table.insertPermission)
|
if (!e.metaKey && e.key === "n" && table.capabilities.has(Capability.TABLE_INSERT) && table.insertPermission)
|
||||||
{
|
{
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
gotoCreate();
|
gotoCreate();
|
||||||
}
|
}
|
||||||
else if (! e.metaKey && e.key === "e" && table.capabilities.has(Capability.TABLE_UPDATE) && table.editPermission)
|
else if (!e.metaKey && e.key === "e" && table.capabilities.has(Capability.TABLE_UPDATE) && table.editPermission)
|
||||||
{
|
{
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
navigate("edit");
|
navigate("edit");
|
||||||
}
|
}
|
||||||
else if (! e.metaKey && e.key === "c" && table.capabilities.has(Capability.TABLE_INSERT) && table.insertPermission)
|
else if (!e.metaKey && e.key === "c" && table.capabilities.has(Capability.TABLE_INSERT) && table.insertPermission)
|
||||||
{
|
{
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
navigate("copy");
|
navigate("copy");
|
||||||
}
|
}
|
||||||
else if (! e.metaKey && e.key === "d" && table.capabilities.has(Capability.TABLE_DELETE) && table.deletePermission)
|
else if (!e.metaKey && e.key === "d" && table.capabilities.has(Capability.TABLE_DELETE) && table.deletePermission)
|
||||||
{
|
{
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
handleClickDeleteButton();
|
handleClickDeleteButton();
|
||||||
}
|
}
|
||||||
else if (! e.metaKey && e.key === "a" && metaData && metaData.tables.has("audit"))
|
else if (!e.metaKey && e.key === "a" && metaData && metaData.tables.has("audit"))
|
||||||
{
|
{
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
navigate("#audit");
|
navigate("#audit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
document.addEventListener("keydown", down)
|
document.addEventListener("keydown", down);
|
||||||
return () =>
|
return () =>
|
||||||
{
|
{
|
||||||
document.removeEventListener("keydown", down)
|
document.removeEventListener("keydown", down);
|
||||||
}
|
};
|
||||||
}, [dotMenuOpen, keyboardHelpOpen, showEditChildForm, showAudit, metaData, location])
|
}, [dotMenuOpen, keyboardHelpOpen, showEditChildForm, showAudit, metaData, location]);
|
||||||
|
|
||||||
const gotoCreate = () =>
|
const gotoCreate = () =>
|
||||||
{
|
{
|
||||||
const path = `${pathParts.slice(0, -1).join("/")}/create`;
|
const path = `${pathParts.slice(0, -1).join("/")}/create`;
|
||||||
navigate(path);
|
navigate(path);
|
||||||
}
|
};
|
||||||
|
|
||||||
const gotoEdit = () =>
|
const gotoEdit = () =>
|
||||||
{
|
{
|
||||||
const path = `${pathParts.slice(0, -1).join("/")}/${record.values.get(table.primaryKeyField)}/edit`;
|
const path = `${pathParts.slice(0, -1).join("/")}/${record.values.get(table.primaryKeyField)}/edit`;
|
||||||
navigate(path);
|
navigate(path);
|
||||||
}
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// monitor location changes - if we've clicked a link from viewing one record to viewing another, //
|
// monitor location changes - if we've clicked a link from viewing one record to viewing another, //
|
||||||
@ -267,7 +267,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
// if our table is in the -4 index, and there's `createChild` in the -2 index, try to open a createChild form //
|
// if our table is in the -4 index, and there's `createChild` in the -2 index, try to open a createChild form //
|
||||||
// e.g., person/42/createChild/address (to create an address under person 42) //
|
// e.g., person/42/createChild/address (to create an address under person 42) //
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if(pathParts[pathParts.length - 4] === tableName && pathParts[pathParts.length - 2] == "createChild")
|
if (pathParts[pathParts.length - 4] === tableName && pathParts[pathParts.length - 2] == "createChild")
|
||||||
{
|
{
|
||||||
(async () =>
|
(async () =>
|
||||||
{
|
{
|
||||||
@ -298,7 +298,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hashParts[0] == "#audit")
|
if (hashParts[0] == "#audit")
|
||||||
{
|
{
|
||||||
setShowAudit(true);
|
setShowAudit(true);
|
||||||
return;
|
return;
|
||||||
@ -307,11 +307,11 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// look for anchor links - e.g., table section names. return w/ no-op if found. //
|
// look for anchor links - e.g., table section names. return w/ no-op if found. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
if(tableSections)
|
if (tableSections)
|
||||||
{
|
{
|
||||||
for (let i = 0; i < tableSections.length; i++)
|
for (let i = 0; i < tableSections.length; i++)
|
||||||
{
|
{
|
||||||
if("#" + tableSections[i].name === location.hash)
|
if ("#" + tableSections[i].name === location.hash)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -345,11 +345,11 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
section.fieldNames.forEach((fieldName) =>
|
section.fieldNames.forEach((fieldName) =>
|
||||||
{
|
{
|
||||||
const [field, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fieldName);
|
const [field, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fieldName);
|
||||||
if(tableForField && tableForField.name != tableMetaData.name)
|
if (tableForField && tableForField.name != tableMetaData.name)
|
||||||
{
|
{
|
||||||
visibleJoinTables.add(tableForField.name);
|
visibleJoinTables.add(tableForField.name);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (visibleJoinTables);
|
return (visibleJoinTables);
|
||||||
@ -361,15 +361,15 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
const getSectionHelp = (section: QTableSection) =>
|
const getSectionHelp = (section: QTableSection) =>
|
||||||
{
|
{
|
||||||
const helpRoles = ["VIEW_SCREEN", "READ_SCREENS", "ALL_SCREENS"]
|
const helpRoles = ["VIEW_SCREEN", "READ_SCREENS", "ALL_SCREENS"];
|
||||||
const formattedHelpContent = <HelpContent helpContents={section.helpContents} roles={helpRoles} helpContentKey={`table:${tableName};section:${section.name}`} />;
|
const formattedHelpContent = <HelpContent helpContents={section.helpContents} roles={helpRoles} helpContentKey={`table:${tableName};section:${section.name}`} />;
|
||||||
|
|
||||||
return formattedHelpContent && (
|
return formattedHelpContent && (
|
||||||
<Box px={"1.5rem"} fontSize={"0.875rem"} color={colors.blueGray.main}>
|
<Box px={"1.5rem"} fontSize={"0.875rem"} color={colors.blueGray.main}>
|
||||||
{formattedHelpContent}
|
{formattedHelpContent}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
if (!asyncLoadInited)
|
if (!asyncLoadInited)
|
||||||
@ -401,11 +401,11 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
// load processes that the routing needs to respect //
|
// load processes that the routing needs to respect //
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
const allTableProcesses = ProcessUtils.getProcessesForTable(metaData, tableName, true) // these include hidden ones (e.g., to find the bulks)
|
const allTableProcesses = ProcessUtils.getProcessesForTable(metaData, tableName, true); // these include hidden ones (e.g., to find the bulks)
|
||||||
const runRecordScriptProcess = metaData?.processes.get("runRecordScript");
|
const runRecordScriptProcess = metaData?.processes.get("runRecordScript");
|
||||||
if (runRecordScriptProcess)
|
if (runRecordScriptProcess)
|
||||||
{
|
{
|
||||||
allTableProcesses.unshift(runRecordScriptProcess)
|
allTableProcesses.unshift(runRecordScriptProcess);
|
||||||
}
|
}
|
||||||
setAllTableProcesses(allTableProcesses);
|
setAllTableProcesses(allTableProcesses);
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
|
|
||||||
let queryJoins: QueryJoin[] = null;
|
let queryJoins: QueryJoin[] = null;
|
||||||
const visibleJoinTables = getVisibleJoinTables(tableMetaData);
|
const visibleJoinTables = getVisibleJoinTables(tableMetaData);
|
||||||
if(visibleJoinTables.size > 0)
|
if (visibleJoinTables.size > 0)
|
||||||
{
|
{
|
||||||
queryJoins = TableUtils.getQueryJoins(tableMetaData, visibleJoinTables);
|
queryJoins = TableUtils.getQueryJoins(tableMetaData, visibleJoinTables);
|
||||||
}
|
}
|
||||||
@ -439,7 +439,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
{
|
{
|
||||||
HistoryUtils.ensurePathNotInHistory(location.pathname);
|
HistoryUtils.ensurePathNotInHistory(location.pathname);
|
||||||
}
|
}
|
||||||
catch(e)
|
catch (e)
|
||||||
{
|
{
|
||||||
console.error("Error pushing history: " + e);
|
console.error("Error pushing history: " + e);
|
||||||
}
|
}
|
||||||
@ -464,13 +464,13 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
|
|
||||||
setPageHeader(record.recordLabel);
|
setPageHeader(record.recordLabel);
|
||||||
|
|
||||||
if(!launchingProcess)
|
if (!launchingProcess)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HistoryUtils.push({label: `${tableMetaData?.label}: ${record.recordLabel}`, path: location.pathname, iconName: table.iconName});
|
HistoryUtils.push({label: `${tableMetaData?.label}: ${record.recordLabel}`, path: location.pathname, iconName: table.iconName});
|
||||||
}
|
}
|
||||||
catch(e)
|
catch (e)
|
||||||
{
|
{
|
||||||
console.error("Error pushing history: " + e);
|
console.error("Error pushing history: " + e);
|
||||||
}
|
}
|
||||||
@ -522,27 +522,30 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
section.fieldNames.map((fieldName: string) =>
|
section.fieldNames.map((fieldName: string) =>
|
||||||
{
|
{
|
||||||
let [field, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fieldName);
|
let [field, tableForField] = TableUtils.getFieldAndTable(tableMetaData, fieldName);
|
||||||
let label = field.label;
|
if (field != null)
|
||||||
|
{
|
||||||
|
let label = field.label;
|
||||||
|
|
||||||
const helpRoles = ["VIEW_SCREEN", "READ_SCREENS", "ALL_SCREENS"]
|
const helpRoles = ["VIEW_SCREEN", "READ_SCREENS", "ALL_SCREENS"];
|
||||||
const showHelp = helpHelpActive || hasHelpContent(field.helpContents, helpRoles);
|
const showHelp = helpHelpActive || hasHelpContent(field.helpContents, helpRoles);
|
||||||
const formattedHelpContent = <HelpContent helpContents={field.helpContents} roles={helpRoles} heading={label} helpContentKey={`table:${tableName};field:${fieldName}`} />;
|
const formattedHelpContent = <HelpContent helpContents={field.helpContents} roles={helpRoles} heading={label} helpContentKey={`table:${tableName};field:${fieldName}`} />;
|
||||||
|
|
||||||
const labelElement = <Typography variant="button" textTransform="none" fontWeight="bold" pr={1} color="rgb(52, 71, 103)" sx={{cursor: "default"}}>{label}:</Typography>
|
const labelElement = <Typography variant="button" textTransform="none" fontWeight="bold" pr={1} color="rgb(52, 71, 103)" sx={{cursor: "default"}}>{label}:</Typography>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box key={fieldName} flexDirection="row" pr={2}>
|
<Box key={fieldName} flexDirection="row" pr={2}>
|
||||||
<>
|
<>
|
||||||
{
|
{
|
||||||
showHelp && formattedHelpContent ? <Tooltip title={formattedHelpContent}>{labelElement}</Tooltip> : labelElement
|
showHelp && formattedHelpContent ? <Tooltip title={formattedHelpContent}>{labelElement}</Tooltip> : labelElement
|
||||||
}
|
}
|
||||||
<div style={{display: "inline-block", width: 0}}> </div>
|
<div style={{display: "inline-block", width: 0}}> </div>
|
||||||
<Typography variant="button" textTransform="none" fontWeight="regular" color="rgb(123, 128, 154)">
|
<Typography variant="button" textTransform="none" fontWeight="regular" color="rgb(123, 128, 154)">
|
||||||
{ValueUtils.getDisplayValue(field, record, "view", fieldName)}
|
{ValueUtils.getDisplayValue(field, record, "view", fieldName)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
</>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
@ -590,7 +593,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
setSectionFieldElements(sectionFieldElements);
|
setSectionFieldElements(sectionFieldElements);
|
||||||
setNonT1TableSections(nonT1TableSections);
|
setNonT1TableSections(nonT1TableSections);
|
||||||
|
|
||||||
if(location.state)
|
if (location.state)
|
||||||
{
|
{
|
||||||
let state: any = location.state;
|
let state: any = location.state;
|
||||||
if (state["createSuccess"] || state["updateSuccess"])
|
if (state["createSuccess"] || state["updateSuccess"])
|
||||||
@ -603,9 +606,9 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
setWarningMessage(state["warning"]);
|
setWarningMessage(state["warning"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete state["createSuccess"]
|
delete state["createSuccess"];
|
||||||
delete state["updateSuccess"]
|
delete state["updateSuccess"];
|
||||||
delete state["warning"]
|
delete state["warning"];
|
||||||
|
|
||||||
window.history.replaceState(state, "");
|
window.history.replaceState(state, "");
|
||||||
}
|
}
|
||||||
@ -640,7 +643,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
console.log("Caught:");
|
console.log("Caught:");
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
||||||
if(error.message.toLowerCase().startsWith("warning"))
|
if (error.message.toLowerCase().startsWith("warning"))
|
||||||
{
|
{
|
||||||
const path = pathParts.slice(0, -1).join("/");
|
const path = pathParts.slice(0, -1).join("/");
|
||||||
navigate(path, {state: {deleteSuccess: true, warning: error.message}});
|
navigate(path, {state: {deleteSuccess: true, warning: error.message}});
|
||||||
@ -767,7 +770,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// when closing a modal process, navigate up to the record being viewed //
|
// when closing a modal process, navigate up to the record being viewed //
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
if(location.hash)
|
if (location.hash)
|
||||||
{
|
{
|
||||||
navigate(location.pathname);
|
navigate(location.pathname);
|
||||||
}
|
}
|
||||||
@ -801,7 +804,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
// navigate back up to the record being viewed //
|
// navigate back up to the record being viewed //
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
if(location.hash)
|
if (location.hash)
|
||||||
{
|
{
|
||||||
navigate(location.pathname);
|
navigate(location.pathname);
|
||||||
}
|
}
|
||||||
@ -828,7 +831,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
|
|||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
// navigate back up to the record being viewed //
|
// navigate back up to the record being viewed //
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
if(location.hash)
|
if (location.hash)
|
||||||
{
|
{
|
||||||
navigate(location.pathname);
|
navigate(location.pathname);
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,14 @@ class FilterUtils
|
|||||||
|
|
||||||
criteria.values = values;
|
criteria.values = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// recursively clean values in any subfilters //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
for (let j = 0; j < queryFilter?.subFilters?.length; j++)
|
||||||
|
{
|
||||||
|
await FilterUtils.cleanupValuesInFilerFromQueryString(qController, tableMetaData, queryFilter.subFilters[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -581,6 +589,29 @@ class FilterUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** after go-live of redesigin in march 2024, we had bugs where we could get a
|
||||||
|
** filter with a criteria w/ a null field name (e.g., by having an incomplete
|
||||||
|
** criteria in the Advanced filter builder - and that would sometimes break
|
||||||
|
** the screen! So, strip those away when storing or loading filters, via
|
||||||
|
** this function.
|
||||||
|
*******************************************************************************/
|
||||||
|
public static stripAwayIncompleteCriteria(filter: QQueryFilter)
|
||||||
|
{
|
||||||
|
if (filter?.criteria?.length > 0)
|
||||||
|
{
|
||||||
|
for (let i = 0; i < filter.criteria.length; i++)
|
||||||
|
{
|
||||||
|
if (!filter.criteria[i].fieldName)
|
||||||
|
{
|
||||||
|
filter.criteria.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FilterUtils;
|
export default FilterUtils;
|
||||||
|
@ -110,7 +110,7 @@ class TableUtils
|
|||||||
return ([tableMetaData.fields.get(fieldName), tableMetaData]);
|
return ([tableMetaData.fields.get(fieldName), tableMetaData]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (null);
|
return [null, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ class TableUtils
|
|||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
console.log(`Error getting full field label for ${fieldName} in table ${tableMetaData?.name}: ${e}`);
|
console.log(`Error getting full field label for ${fieldName} in table ${tableMetaData?.name}: ${e}`);
|
||||||
return fieldName
|
return fieldName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user