added branding as metadata, fixed problem where query string filter wasn't seeding properly,

This commit is contained in:
Tim Chamberlain
2022-09-06 18:15:48 -05:00
parent e376f4ae72
commit 5a5fa1f148
13 changed files with 180 additions and 187 deletions

View File

@ -35,32 +35,35 @@ import SidenavItem from "qqq/components/Sidenav/SidenavItem";
import SidenavList from "qqq/components/Sidenav/SidenavList";
import SidenavRoot from "qqq/components/Sidenav/SidenavRoot";
interface Props {
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark";
brand?: string;
brandName?: string;
routes: {
[key: string]:
| ReactNode
| string
| {
interface Props
{
color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "dark";
icon?: string;
logo?: string;
companyName?: string;
routes: {
[key: string]:
| ReactNode
| string
| {
[key: string]:
| ReactNode
| string
| {
[key: string]: ReactNode | string;
}[];
[key: string]:
| ReactNode
| string
| {
[key: string]:
| ReactNode
| string
| {
[key: string]: ReactNode | string;
}[];
}[];
}[];
}[];
}[];
[key: string]: any;
}[];
[key: string]: any;
}
function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
function Sidenav({color, icon, logo, companyName, routes, ...rest}: Props): JSX.Element
{
const [openCollapse, setOpenCollapse] = useState<boolean | string>(false);
const [openNestedCollapse, setOpenNestedCollapse] = useState<boolean | string>(false);
@ -75,17 +78,17 @@ function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
const [, forceUpdate] = useReducer((x) => x + 1, 0);
let textColor:
| "primary"
| "secondary"
| "info"
| "success"
| "warning"
| "error"
| "dark"
| "white"
| "inherit"
| "text"
| "light" = "white";
| "primary"
| "secondary"
| "info"
| "success"
| "warning"
| "error"
| "dark"
| "white"
| "inherit"
| "text"
| "light" = "white";
if (transparentSidenav || (whiteSidenav && !darkMode))
{
@ -115,8 +118,8 @@ function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
}
/**
The event listener that's calling the handleMiniSidenav function when resizing the window.
*/
The event listener that's calling the handleMiniSidenav function when resizing the window.
*/
window.addEventListener("resize", handleMiniSidenav);
window.onload = () =>
{
@ -283,7 +286,7 @@ function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
key={key}
light={
(!darkMode && !whiteSidenav && !transparentSidenav) ||
(darkMode && !transparentSidenav && whiteSidenav)
(darkMode && !transparentSidenav && whiteSidenav)
}
/>
);
@ -314,10 +317,11 @@ function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
</MDTypography>
</MDBox>
<MDBox component={NavLink} to="/" display="flex" alignItems="center">
{brand && <MDBox component="img" src={brand} alt="Brand" width="100%" />}
{brandName && <MDBox width={!brandName && "100%"} sx={(theme: any) => sidenavLogoLabel(theme, {miniSidenav})}>
{!miniSidenav && logo && <MDBox component="img" src={logo} alt="Logo" width="100%" />}
{miniSidenav && icon && <MDBox component="img" src={icon} alt="Icon" width="160%" />}
{!miniSidenav && companyName && <MDBox width={!companyName && "100%"} sx={(theme: any) => sidenavLogoLabel(theme, {miniSidenav})}>
<MDTypography component="h6" variant="button" fontWeight="medium" color={textColor}>
{brandName}
{companyName}
</MDTypography>
</MDBox>
}
@ -326,7 +330,7 @@ function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
<Divider
light={
(!darkMode && !whiteSidenav && !transparentSidenav) ||
(darkMode && !transparentSidenav && whiteSidenav)
(darkMode && !transparentSidenav && whiteSidenav)
}
/>
<List>{renderRoutes}</List>
@ -338,8 +342,9 @@ function Sidenav({color, brand, brandName, routes, ...rest}: Props): JSX.Element
// Declaring default props for Sidenav
Sidenav.defaultProps = {
color: "info",
brand: "",
brandName: "",
icon: "",
logo: "",
companyName: "",
};
export default Sidenav;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -59,43 +59,46 @@ interface Props
** Get the default filter to use on the page - either from query string, or
** local storage, or a default (empty).
*******************************************************************************/
function getDefaultFilter(searchParams: URLSearchParams, filterLocalStorageKey: string): GridFilterModel
function getDefaultFilter(tableMetaData: QTableMetaData, searchParams: URLSearchParams, filterLocalStorageKey: string): GridFilterModel
{
if (searchParams.has("filter"))
if (tableMetaData.fields !== undefined)
{
try
if (searchParams.has("filter"))
{
const qQueryFilter = JSON.parse(searchParams.get("filter")) as QQueryFilter;
console.log(`Got a filter from the query string: ${JSON.stringify(qQueryFilter)}`);
//////////////////////////////////////////////////////////////////
// translate from a qqq-style filter to one that the grid wants //
//////////////////////////////////////////////////////////////////
const defaultFilter = {items: []} as GridFilterModel;
let id = 1;
qQueryFilter.criteria.forEach((criteria) =>
try
{
defaultFilter.items.push({
columnField: criteria.fieldName,
operatorValue: QFilterUtils.qqqCriteriaOperatorToGrid(criteria.operator),
value: QFilterUtils.qqqCriteriaValuesToGrid(criteria.operator, criteria.values),
id: id++, // not sure what this id is!!
});
});
const qQueryFilter = JSON.parse(searchParams.get("filter")) as QQueryFilter;
//////////////////////////////////////////////////////////////////
// translate from a qqq-style filter to one that the grid wants //
//////////////////////////////////////////////////////////////////
const defaultFilter = {items: []} as GridFilterModel;
let id = 1;
qQueryFilter.criteria.forEach((criteria) =>
{
const fieldType = tableMetaData.fields.get(criteria.fieldName).type;
defaultFilter.items.push({
columnField: criteria.fieldName,
operatorValue: QFilterUtils.qqqCriteriaOperatorToGrid(criteria.operator, fieldType),
value: QFilterUtils.qqqCriteriaValuesToGrid(criteria.operator, criteria.values),
id: id++, // not sure what this id is!!
});
});
return (defaultFilter);
}
catch (e)
{
console.warn("Error parsing filter from query string", e);
}
}
if (localStorage.getItem(filterLocalStorageKey))
{
const defaultFilter = JSON.parse(localStorage.getItem(filterLocalStorageKey));
console.log(`Got default from LS: ${JSON.stringify(defaultFilter)}`);
return (defaultFilter);
}
catch (e)
{
console.warn("Error parsing filter from query string", e);
}
}
if (localStorage.getItem(filterLocalStorageKey))
{
const defaultFilter = JSON.parse(localStorage.getItem(filterLocalStorageKey));
console.log(`Got default from LS: ${JSON.stringify(defaultFilter)}`);
return (defaultFilter);
}
return ({items: []});
@ -116,7 +119,6 @@ function EntityList({table}: Props): JSX.Element
const filterLocalStorageKey = `${FILTER_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
let defaultSort = [] as GridSortItem[];
let defaultVisibility = {};
const _defaultFilter = getDefaultFilter(searchParams, filterLocalStorageKey);
if (localStorage.getItem(sortLocalStorageKey))
{
@ -127,7 +129,7 @@ function EntityList({table}: Props): JSX.Element
defaultVisibility = JSON.parse(localStorage.getItem(columnVisibilityLocalStorageKey));
}
const [filterModel, setFilterModel] = useState(_defaultFilter);
const [filterModel, setFilterModel] = useState({items: []} as GridFilterModel);
const [columnSortModel, setColumnSortModel] = useState(defaultSort);
const [columnVisibilityModel, setColumnVisibilityModel] = useState(defaultVisibility);
@ -137,11 +139,11 @@ function EntityList({table}: Props): JSX.Element
// when that happens put the default back - it needs to be in state //
// const [defaultFilter1] = useState(defaultFilter); //
///////////////////////////////////////////////////////////////////////////////////////////////
const [defaultFilter] = useState(_defaultFilter);
const [filterChangeHasOccurred, setFilterChangeHasOccurred] = useState(false);
const [defaultFilter] = useState({items: []} as GridFilterModel);
const [tableState, setTableState] = useState("");
const [tableMetaData, setTableMetaData] = useState(null as QTableMetaData);
const [defaultFilterLoaded, setDefaultFilterLoaded] = useState(false);
const [, setFiltersMenu] = useState(null);
const [actionsMenu, setActionsMenu] = useState(null);
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
@ -194,6 +196,19 @@ function EntityList({table}: Props): JSX.Element
(async () =>
{
const tableMetaData = await qController.loadTableMetaData(tableName);
////////////////////////////////////////////////////////////////////////////////////////////////
// we need the table meta data to look up the default filter (if it comes from query string), //
// because we need to know field types to translate qqq filter to material filter //
// because we need to know field types to translate qqq filter to material filter //
// return here ane wait for the next 'turn' to allow doing the actual query //
////////////////////////////////////////////////////////////////////////////////////////////////
if (!defaultFilterLoaded)
{
setDefaultFilterLoaded(true);
setFilterModel(getDefaultFilter(tableMetaData, searchParams, filterLocalStorageKey));
return;
}
setTableMetaData(tableMetaData);
if (columnSortModel.length === 0)
{
@ -416,21 +431,13 @@ function EntityList({table}: Props): JSX.Element
const handleFilterChange = (filterModel: GridFilterModel) =>
{
if (!filterChangeHasOccurred)
setFilterModel(filterModel);
if (filterLocalStorageKey)
{
setFilterModel(defaultFilter);
setFilterChangeHasOccurred(true);
}
else
{
setFilterModel(filterModel);
if (filterLocalStorageKey)
{
localStorage.setItem(
filterLocalStorageKey,
JSON.stringify(filterModel),
);
}
localStorage.setItem(
filterLocalStorageKey,
JSON.stringify(filterModel),
);
}
};

View File

@ -64,7 +64,7 @@ class QFilterUtils
return QCriteriaOperator.IS_BLANK;
case "isNotEmpty":
return QCriteriaOperator.IS_NOT_BLANK;
case "isAny":
case "isAnyOf":
return QCriteriaOperator.IN;
case "isNone": // todo - verify - not seen in UI
return QCriteriaOperator.NOT_IN;
@ -118,7 +118,7 @@ class QFilterUtils
return ("isNot");
}
case QCriteriaOperator.IN:
return ("isAny");
return ("isAnyOf");
case QCriteriaOperator.NOT_IN:
return ("isNone"); // todo verify - not seen in UI
case QCriteriaOperator.STARTS_WITH: