SPRINT-20: updates to saved filters based on ui feedback

This commit is contained in:
Tim Chamberlain
2023-02-01 21:54:13 -06:00
parent d29fb32978
commit afa5092808
4 changed files with 88 additions and 40 deletions

View File

@ -50,7 +50,7 @@
"clean": "rm -rf node_modules package-lock.json", "clean": "rm -rf node_modules package-lock.json",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"geff-ham": "rm -rf node_modules/ && rm -rf package-lock.json && rm -rf lib/ && npm install", "geff-ham": "rm -rf node_modules/ && rm -rf package-lock.json && rm -rf lib/ && npm install",
"install-legacy-peer-deps": "npm install --legacy-peer-deps", "npm-install": "npm install",
"prepublishOnly": "tsc -p ./ --outDir lib/", "prepublishOnly": "tsc -p ./ --outDir lib/",
"start": "BROWSER=none react-scripts start", "start": "BROWSER=none react-scripts start",
"test": "react-scripts test", "test": "react-scripts test",

View File

@ -111,6 +111,7 @@ export function QActionsMenuButton({isOpen, onClickHandler}: QActionsMenuButtonP
variant={isOpen ? "contained" : "outlined"} variant={isOpen ? "contained" : "outlined"}
color="dark" color="dark"
onClick={onClickHandler} onClick={onClickHandler}
startIcon={<Icon>games</Icon>}
fullWidth fullWidth
> >
actions&nbsp; actions&nbsp;
@ -129,6 +130,7 @@ export function QSavedFiltersMenuButton({isOpen, onClickHandler}: QActionsMenuBu
color="dark" color="dark"
onClick={onClickHandler} onClick={onClickHandler}
fullWidth fullWidth
startIcon={<Icon>filter_alt</Icon>}
> >
saved&nbsp;filters&nbsp; saved&nbsp;filters&nbsp;
<Icon>keyboard_arrow_down</Icon> <Icon>keyboard_arrow_down</Icon>

View File

@ -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 {KeyboardArrowDown} from "@mui/icons-material"; import {FiberManualRecord, KeyboardArrowDown} from "@mui/icons-material";
import {Alert, ClickAwayListener, Grow, MenuList, Paper, Popper} from "@mui/material"; import {Alert, ClickAwayListener, Grow, MenuList, Paper, Popper} from "@mui/material";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
@ -34,9 +34,13 @@ import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions"; import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent"; import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle"; import DialogTitle from "@mui/material/DialogTitle";
import Divider from "@mui/material/Divider";
import Icon from "@mui/material/Icon";
import ListItemIcon from "@mui/material/ListItemIcon";
import Menu from "@mui/material/Menu"; import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem"; import MenuItem from "@mui/material/MenuItem";
import TextField from "@mui/material/TextField"; import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import {GridFilterModel, GridSortItem} from "@mui/x-data-grid-pro"; import {GridFilterModel, GridSortItem} from "@mui/x-data-grid-pro";
import FormData from "form-data"; import FormData from "form-data";
@ -76,12 +80,12 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
const location = useLocation(); const location = useLocation();
const [saveOptionsOpen, setSaveOptionsOpen] = useState(false); const [saveOptionsOpen, setSaveOptionsOpen] = useState(false);
const SAVE_OPTION = "Save Filter..."; const SAVE_OPTION = "Save...";
const SAVE_AS_OPTION = "Create A New Filter From This Filter..."; const DUPLICATE_OPTION = "Duplicate...";
const RENAME_OPTION = "Rename This Filter..."; const RENAME_OPTION = "Rename...";
const CLEAR_OPTION = "Clear This Filter"; const DELETE_OPTION = "Delete...";
const DELETE_OPTION = "Delete This Filter..."; const CLEAR_OPTION = "Clear Current Filter";
const dropdownOptions = [SAVE_AS_OPTION, RENAME_OPTION, CLEAR_OPTION, DELETE_OPTION]; const dropdownOptions = [DUPLICATE_OPTION, RENAME_OPTION, DELETE_OPTION, CLEAR_OPTION];
const openSavedFiltersMenu = (event: any) => setSavedFiltersMenu(event.currentTarget); const openSavedFiltersMenu = (event: any) => setSavedFiltersMenu(event.currentTarget);
const closeSavedFiltersMenu = () => setSavedFiltersMenu(null); const closeSavedFiltersMenu = () => setSavedFiltersMenu(null);
@ -146,7 +150,6 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
setSaveOptionsOpen(false); setSaveOptionsOpen(false);
setPopupAlertContent(null); setPopupAlertContent(null);
closeSavedFiltersMenu(); closeSavedFiltersMenu();
setSavedFilterNameInputValue(null);
setSaveFilterPopupOpen(true); setSaveFilterPopupOpen(true);
setIsSaveFilterAs(false); setIsSaveFilterAs(false);
setIsRenameFilter(false); setIsRenameFilter(false);
@ -156,7 +159,7 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
{ {
case SAVE_OPTION: case SAVE_OPTION:
break; break;
case SAVE_AS_OPTION: case DUPLICATE_OPTION:
setIsSaveFilterAs(true); setIsSaveFilterAs(true);
break; break;
case CLEAR_OPTION: case CLEAR_OPTION:
@ -165,6 +168,10 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
navigate(metaData.getTablePathByName(tableMetaData.name)); navigate(metaData.getTablePathByName(tableMetaData.name));
break; break;
case RENAME_OPTION: case RENAME_OPTION:
if(currentSavedFilter != null)
{
setSavedFilterNameInputValue(currentSavedFilter.values.get("label"));
}
setIsRenameFilter(true); setIsRenameFilter(true);
break; break;
case DELETE_OPTION: case DELETE_OPTION:
@ -322,9 +329,12 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
return (savedFilters); return (savedFilters);
} }
const hasStorePermission = metaData?.processes.has("storeSavedFilter");
const hasDeletePermission = metaData?.processes.has("deleteSavedFilter");
const hasQueryPermission = metaData?.processes.has("querySavedFilter");
const renderSavedFiltersMenu = tableMetaData && ( const renderSavedFiltersMenu = tableMetaData && (
<Menu <Menu
sx={{width: "500px"}}
anchorEl={savedFiltersMenu} anchorEl={savedFiltersMenu}
anchorOrigin={{ anchorOrigin={{
vertical: "bottom", vertical: "bottom",
@ -338,10 +348,47 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
onClose={closeSavedFiltersMenu} onClose={closeSavedFiltersMenu}
keepMounted keepMounted
> >
<MenuItem sx={{width: "300px"}}><b>Filter Actions</b></MenuItem>
{
hasStorePermission &&
<MenuItem onClick={() => handleDropdownOptionClick(SAVE_OPTION)}>
<ListItemIcon><Icon>save</Icon></ListItemIcon>
Save...
</MenuItem>
}
{
hasStorePermission &&
<MenuItem disabled={currentSavedFilter === null} onClick={() => handleDropdownOptionClick(RENAME_OPTION)}>
<ListItemIcon><Icon>edit</Icon></ListItemIcon>
Rename...
</MenuItem>
}
{
hasStorePermission &&
<MenuItem disabled={currentSavedFilter === null} onClick={() => handleDropdownOptionClick(DUPLICATE_OPTION)}>
<ListItemIcon><Icon>content_copy</Icon></ListItemIcon>
Duplicate...
</MenuItem>
}
{
hasDeletePermission &&
<MenuItem disabled={currentSavedFilter === null} onClick={() => handleDropdownOptionClick(DELETE_OPTION)}>
<ListItemIcon><Icon>delete</Icon></ListItemIcon>
Delete...
</MenuItem>
}
{
<MenuItem disabled={currentSavedFilter === null} onClick={() => handleDropdownOptionClick(CLEAR_OPTION)}>
<ListItemIcon><Icon>clear</Icon></ListItemIcon>
Clear Current Filter
</MenuItem>
}
<Divider/>
<MenuItem><b>Your Filters</b></MenuItem>
{ {
savedFilters && savedFilters.length > 0 ? ( savedFilters && savedFilters.length > 0 ? (
savedFilters.map((record: QRecord, index: number) => savedFilters.map((record: QRecord, index: number) =>
<MenuItem key={`savedFiler-${index}`} onClick={() => handleSavedFilterRecordOnClick(record)}> <MenuItem sx={{paddingLeft: "50px"}} key={`savedFiler-${index}`} onClick={() => handleSavedFilterRecordOnClick(record)}>
{record.values.get("label")} {record.values.get("label")}
</MenuItem> </MenuItem>
) )
@ -354,38 +401,27 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
</Menu> </Menu>
); );
const hasStorePermission = metaData?.processes.has("storeSavedFilter");
const hasDeletePermission = metaData?.processes.has("deleteSavedFilter");
const hasQueryPermission = metaData?.processes.has("querySavedFilter");
return ( return (
hasQueryPermission && tableMetaData ? ( hasQueryPermission && tableMetaData ? (
<Box display="flex" flexGrow={1}> <Box display="flex" flexGrow={1}>
<QSavedFiltersMenuButton isOpen={savedFiltersMenu} onClickHandler={openSavedFiltersMenu} /> <QSavedFiltersMenuButton isOpen={savedFiltersMenu} onClickHandler={openSavedFiltersMenu} />
{renderSavedFiltersMenu} {renderSavedFiltersMenu}
<Box display="flex" justifyContent="flex-end" flexDirection="column"> <Box display="flex" justifyContent="center" flexDirection="column">
<Box pl={2} pr={2} sx={{display: "flex", alignItems: "center"}}> <Box pl={2} pr={2} sx={{display: "flex", alignItems: "center"}}>
{ {
savedFiltersHaveLoaded && ( savedFiltersHaveLoaded && currentSavedFilter && (
currentSavedFilter ? ( <Typography mr={2} variant="h6">Current Filter:&nbsp;
<Typography mr={2} variant="h6">Current Filter:&nbsp; <span style={{fontWeight: "initial"}}>
<span style={{fontWeight: "initial"}}> {currentSavedFilter.values.get("label")}
{currentSavedFilter.values.get("label")} {
{ filterIsModified && (
filterIsModified && ( <Tooltip sx={{cursor: "pointer"}} title={"The current has been modified, click \"Save...\" to save the changes."}>
<i>&nbsp;*</i> <FiberManualRecord sx={{color: "orange", paddingLeft: "2px", paddingTop: "4px"}} />
</Tooltip>
) )
} }
</span> </span>
</Typography> </Typography>
) : (
<Typography mr={2} variant="h6">&nbsp;
<span style={{fontWeight: "initial"}}>&nbsp;</span>
</Typography>
)
) )
} }
</Box> </Box>
@ -407,7 +443,7 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
<Popper <Popper
sx={{ sx={{
zIndex: 10, zIndex: 10,
marginLeft: "175px !important" marginLeft: "100px !important"
}} }}
open={saveOptionsOpen} open={saveOptionsOpen}
anchorEl={anchorRef.current} anchorEl={anchorRef.current}
@ -428,7 +464,7 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
<ClickAwayListener onClickAway={handleSaveOptionsMenuClose}> <ClickAwayListener onClickAway={handleSaveOptionsMenuClose}>
<MenuList id="split-button-menu" autoFocusItem> <MenuList id="split-button-menu" autoFocusItem>
{dropdownOptions.map((option, index) => ( {dropdownOptions.map((option, index) => (
(option === CLEAR_OPTION || ((option !== DELETE_OPTION || hasDeletePermission) && (option !== SAVE_AS_OPTION || hasStorePermission))) && ( (option === CLEAR_OPTION || ((option !== DELETE_OPTION || hasDeletePermission) && (option !== DUPLICATE_OPTION || hasStorePermission))) && (
<MenuItem <MenuItem
key={option} key={option}
onClick={() => handleDropdownOptionClick(option)} onClick={() => handleDropdownOptionClick(option)}
@ -488,8 +524,13 @@ function SavedFilters({qController, metaData, tableMetaData, currentSavedFilter,
placeholder="Filter Name" placeholder="Filter Name"
label="Filter Name" label="Filter Name"
inputProps={{width: "100%", maxLength: 100}} inputProps={{width: "100%", maxLength: 100}}
value={savedFilterNameInputValue}
sx={{width: "100%"}} sx={{width: "100%"}}
onChange={handleSaveFilterInputChange} onChange={handleSaveFilterInputChange}
onFocus={event =>
{
event.target.select();
}}
/> />
</Box> </Box>
):( ):(

View File

@ -223,6 +223,11 @@ input[type="search"]::-webkit-search-results-decoration { display: none; }
overflow: scroll; overflow: scroll;
} }
.MuiChip-root
{
padding-top: 1px !important;
}
#outlined-multiline-static #outlined-multiline-static
{ {
padding-left: 10px; padding-left: 10px;