Dot-menu css; add help menu; make 'a' always open audit on recordView

This commit is contained in:
2023-07-06 12:05:18 -05:00
parent 6b44742cb5
commit a42cabd903
3 changed files with 107 additions and 33 deletions

View File

@ -27,9 +27,17 @@ import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstan
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData"; import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import Grid from "@mui/material/Grid";
import Icon from "@mui/material/Icon"; import Icon from "@mui/material/Icon";
import Typography from "@mui/material/Typography";
import {makeStyles} from "@mui/styles";
import {Command} from "cmdk"; import {Command} from "cmdk";
import React, {useContext, useEffect, useRef} from "react"; import React, {useContext, useEffect, useRef, useState} from "react";
import {useNavigate} from "react-router-dom"; import {useNavigate} from "react-router-dom";
import QContext from "QContext"; import QContext from "QContext";
import HistoryUtils, {QHistoryEntry} from "qqq/utils/HistoryUtils"; import HistoryUtils, {QHistoryEntry} from "qqq/utils/HistoryUtils";
@ -39,6 +47,21 @@ interface Props
metaData?: QInstance; metaData?: QInstance;
} }
const useStyles = makeStyles((theme: any) => ({
item: {
whiteSpace: "nowrap"
},
keyboardKey: {
border: "1px solid gray",
borderRadius: "5px",
width: "28px",
display: "inline-block",
textAlign: "center",
marginRight: "5px",
fontWeight: "bold",
background: "#f0f0f0"
}
}));
const CommandMenu = ({metaData}: Props) => const CommandMenu = ({metaData}: Props) =>
{ {
@ -47,16 +70,27 @@ const CommandMenu = ({metaData}: Props) =>
const {accentColor, tableMetaData, dotMenuOpen, setDotMenuOpen, setTableMetaData, tableProcesses} = useContext(QContext); const {accentColor, tableMetaData, dotMenuOpen, setDotMenuOpen, setTableMetaData, tableProcesses} = useContext(QContext);
const [keyboardHelpOpen, setKeyboardHelpOpen] = useState(false)
const classes = useStyles();
function evalueKeyPress(e: KeyboardEvent) function evalueKeyPress(e: KeyboardEvent)
{ {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// if a dot pressed, not from a "text" element, then toggle command menu // // if a dot pressed, not from a "text" element, then toggle command menu //
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
const type = (e.target as any).type; const type = (e.target as any).type;
if (e.key === "." && type !== "text" && type !== "textarea" && type !== "input" && type !== "search") if (type !== "text" && type !== "textarea" && type !== "input" && type !== "search")
{ {
e.preventDefault(); if (e.key === "." && !keyboardHelpOpen)
setDotMenuOpen(!dotMenuOpen); {
e.preventDefault();
setDotMenuOpen(!dotMenuOpen);
}
else if (e.key === "?" && !dotMenuOpen)
{
e.preventDefault();
setKeyboardHelpOpen(true);
}
} }
} }
@ -83,7 +117,7 @@ const CommandMenu = ({metaData}: Props) =>
{ {
document.removeEventListener("keydown", down) document.removeEventListener("keydown", down)
} }
}, [tableMetaData, dotMenuOpen]) }, [tableMetaData, dotMenuOpen, keyboardHelpOpen])
useEffect(() => useEffect(() =>
{ {
@ -116,11 +150,11 @@ const CommandMenu = ({metaData}: Props) =>
{ {
if (nodes[i].type === QAppNodeType.APP && nodes[i].name === name) if (nodes[i].type === QAppNodeType.APP && nodes[i].name === name)
{ {
return (`${path} > ${nodes[i].label}`); return (`${path}${nodes[i].label}`);
} }
else if (nodes[i].type === QAppNodeType.APP) else if (nodes[i].type === QAppNodeType.APP)
{ {
const result = getFullAppLabel(nodes[i].children, name, depth + 1, `${path} ${nodes[i].label}`); const result = getFullAppLabel(nodes[i].children, name, depth + 1, `${path}${nodes[i].label} > `);
if (result !== null) if (result !== null)
{ {
return (result); return (result);
@ -272,24 +306,63 @@ const CommandMenu = ({metaData}: Props) =>
} }
const containerElement = useRef(null) const containerElement = useRef(null)
function closeKeyboardHelp()
{
setKeyboardHelpOpen(false);
}
return ( return (
<Box ref={containerElement} className="raycast" sx={{position: "relative", zIndex: 10_000}}> <React.Fragment>
<Command.Dialog open={dotMenuOpen} onOpenChange={setDotMenuOpen} container={containerElement.current} label="Test Global Command Menu"> <Box ref={containerElement} className="raycast" sx={{position: "relative", zIndex: 10_000}}>
<Box sx={{display: "flex"}}> {
<Command.Input placeholder="Search for Tables, Actions, or Recently Viewed Items..."/> dotMenuOpen && <Dialog open={dotMenuOpen}>
<Button onClick={() => setDotMenuOpen(false)}><Icon>close</Icon></Button> <Command.Dialog open={dotMenuOpen} onOpenChange={setDotMenuOpen} container={containerElement.current} label="Test Global Command Menu">
</Box> <Box sx={{display: "flex"}}>
<Command.Loading /> <Command.Input placeholder="Search for Tables, Actions, or Recently Viewed Items..."/>
<Command.Separator /> <Button onClick={() => setDotMenuOpen(false)}><Icon>close</Icon></Button>
<Command.List> </Box>
<Command.Empty>No results found.</Command.Empty> <Command.Loading />
<ActionsSection /> <Command.Separator />
<TablesSection /> <Command.List>
<AppsSection /> <Command.Empty>No results found.</Command.Empty>
<RecentlyViewedSection /> <ActionsSection />
</Command.List> <TablesSection />
</Command.Dialog> <AppsSection />
</Box> <RecentlyViewedSection />
</Command.List>
</Command.Dialog>
</Dialog>
}
</Box>
{
keyboardHelpOpen &&
<Dialog open={keyboardHelpOpen} onClose={closeKeyboardHelp}>
<DialogTitle id="alert-dialog-title">Keyboard Shortcuts</DialogTitle>
<DialogContent>
<Typography variant="h6">Global</Typography>
<Grid container columnSpacing={5} rowSpacing={1}>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>.</span>Open the Quick Navigation Menu</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>?</span>Open Keyboard Shortcuts Help</Grid>
</Grid>
<Typography variant="h6" pt={3}>Record View</Typography>
<Grid container columnSpacing={5} rowSpacing={1}>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>n</span>Create a New Record</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>c</span>Copy the current Record</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>e</span>Edit the current Record</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>d</span>Delete the current Record</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>a</span>Audit the current Record</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={closeKeyboardHelp}>Close</Button>
</DialogActions>
</Dialog>
}
</React.Fragment>
) )
} }
export default CommandMenu; export default CommandMenu;

View File

@ -190,7 +190,7 @@ function RecordView({table, launchProcess}: Props): JSX.Element
{ {
document.removeEventListener("keydown", down) document.removeEventListener("keydown", down)
} }
}, [dotMenuOpen, showEditChildForm, showAudit]) }, [dotMenuOpen, showEditChildForm, showAudit, metaData])
const gotoCreate = () => const gotoCreate = () =>
{ {

View File

@ -3,6 +3,10 @@
*/ */
.raycast { .raycast {
.MuiBox-root {
margin-bottom: 4px;
}
[cmdk-root] { [cmdk-root] {
max-width: 1000px; max-width: 1000px;
width: 650px; width: 650px;
@ -193,9 +197,10 @@
overflow: auto; overflow: auto;
overscroll-behavior: contain; overscroll-behavior: contain;
scroll-padding-block-end: 40px; scroll-padding-block-end: 40px;
scroll-padding-block-start: 80px;
transition: 100ms ease; transition: 100ms ease;
transition-property: height; transition-property: height;
padding-bottom: 40px; border-top: 1px solid var(--gray5)
} }
[cmdk-raycast-open-trigger], [cmdk-raycast-open-trigger],
@ -269,28 +274,24 @@
} }
[cmdk-separator] { [cmdk-separator] {
display: none;
height: 1px; height: 1px;
width: 100%; width: 100%;
background: var(--gray5); background: var(--gray5);
margin: 4px 0; margin: 4px 0;
} }
*:not([hidden]) + [cmdk-group] {
margin-top: 8px;
}
[cmdk-group-heading] { [cmdk-group-heading] {
user-select: none; user-select: none;
font-size: 14px; font-size: 14px;
color: var(--gray11); color: var(--gray11);
padding: 0 8px;
display: flex; display: flex;
align-items: center; align-items: center;
position: sticky; position: sticky;
top: 0px; top: 0px;
padding-bottom: 7px; padding: 7px 8px 7px;
border-bottom: var(--gray6) 1px solid; border-bottom: var(--gray6) 1px solid;
background: white; background: var(--gray1);
z-index: 1; z-index: 1;
} }