Merge branch 'dev_environment' of gitlab.com:brandx/bxt-app into dev_environment

This commit is contained in:
Carter 2025-04-24 12:00:08 -06:00
commit 860f730d88
22 changed files with 199 additions and 102 deletions

View file

@ -39,4 +39,8 @@ html, body, #root {
.MuiPopper-root { .MuiPopper-root {
z-index: 1501 !important; z-index: 1501 !important;
}
.MuiPopover-root {
z-index: 1501 !important;
} }

View file

@ -125,7 +125,7 @@ export default function Header() {
</Toolbar> </Toolbar>
</AppBar> </AppBar>
<SideNavigator open={navOpen} onOpen={() => {setNavOpen(true)}} onClose={() => {setNavOpen(false)}} /> <SideNavigator open={navOpen} onOpen={() => {setNavOpen(true)}} onClose={() => {setNavOpen(false)}} />
{isMobile && <BottomNavigator setNavOpen={() => {setNavOpen(true)}} sideIsOpen={navOpen} />} {isMobile && <BottomNavigator setNavOpen={isOpen => {setNavOpen(isOpen)}} sideIsOpen={navOpen} />}
</> </>
) )
} }

View file

@ -2255,7 +2255,7 @@ export default function BinSettings(props: Props) {
} }
return ( return (
<DialogActions> <DialogActions>
<Grid container justifyContent="space-between" direction="row"> <Grid container justifyContent="space-between" direction="row" width="100%">
<Grid size={{ xs: 5 }}> <Grid size={{ xs: 5 }}>
{mode === "add" ? ( {mode === "add" ? (
<Button <Button

View file

@ -153,7 +153,8 @@ const useStyles = makeStyles((theme: Theme) => {
sliderValLabel: { sliderValLabel: {
height: 30, height: 30,
width: 30, width: 30,
//top: -15, left: -5,
top: -20,
background: "transparent" background: "transparent"
}, },
}); });

View file

@ -45,9 +45,10 @@ const useStyles = makeStyles((theme: Theme) => ({
paddingBottom: 15, paddingBottom: 15,
zIndex: 101 zIndex: 101
}, },
appBar: { titleDisplay: {
position: "static", position: "static",
borderRadius: 30 borderRadius: 30,
backgroundColor: theme.palette.secondary.main
}, },
drawerPaper: { drawerPaper: {
overflowX: "hidden" overflowX: "hidden"
@ -91,7 +92,7 @@ export default function DisplayDrawer(props: Props) {
classes={{ paper: classes.drawerPaper }}> classes={{ paper: classes.drawerPaper }}>
<Box <Box
className={isMobile ? classes.drawerMobile : classes.drawerDesktop} className={isMobile ? classes.drawerMobile : classes.drawerDesktop}
style={{ width: isMobile ? "100%" : width, height: isMobile ? drawerHeight + "vh" : 0 }}> style={{ width: isMobile ? "100%" : width }}>
<Box className={classes.header} style={{ width: isMobile ? "100%" : width }}> <Box className={classes.header} style={{ width: isMobile ? "100%" : width }}>
<Box display="flex" justifyContent="space-between" alignItems="center"> <Box display="flex" justifyContent="space-between" alignItems="center">
<Box> <Box>
@ -118,10 +119,11 @@ export default function DisplayDrawer(props: Props) {
)} )}
</Box> </Box>
</Box> </Box>
<AppBar className={classes.appBar} color="secondary"> <Box className={classes.titleDisplay}>
<Grid <Grid
container container
direction="row" direction="row"
justifyContent="space-between"
alignItems="center" alignItems="center"
wrap="nowrap"> wrap="nowrap">
<Grid> <Grid>
@ -142,7 +144,7 @@ export default function DisplayDrawer(props: Props) {
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>
</AppBar> </Box>
</Box> </Box>
<Box>{drawerBody}</Box> <Box>{drawerBody}</Box>
</Box> </Box>

View file

@ -12,7 +12,7 @@ import {
useDeviceAPI, useDeviceAPI,
useInteractionsAPI, useInteractionsAPI,
useSnackbar, useSnackbar,
//useUsageAPI, useUsageAPI,
useUserAPI useUserAPI
} from "hooks"; } from "hooks";
import { cloneDeep } from "lodash"; import { cloneDeep } from "lodash";
@ -74,7 +74,7 @@ export default function Device(props: Props) {
const deviceAPI = useDeviceAPI(); const deviceAPI = useDeviceAPI();
const componentAPI = useComponentAPI(); const componentAPI = useComponentAPI();
const interactionsAPI = useInteractionsAPI(); const interactionsAPI = useInteractionsAPI();
//const usageAPI = useUsageAPI(); const usageAPI = useUsageAPI();
const userAPI = useUserAPI(); const userAPI = useUserAPI();
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const [device, setDevice] = useState<DeviceModel>(DeviceModel.create()); const [device, setDevice] = useState<DeviceModel>(DeviceModel.create());
@ -147,25 +147,25 @@ export default function Device(props: Props) {
error(err); error(err);
}) })
.finally(() => setIsLoading(false)); .finally(() => setIsLoading(false));
// usageAPI usageAPI
// .getUsage(deviceID, moment().subtract(1, "days")) .getUsage(deviceID, moment().subtract(1, "days"))
// .then((res: any) => { .then((res: any) => {
// let usage = res.data; let usage = res.data;
// if (usage) { if (usage) {
// let rCellularStatus = "active"; let rCellularStatus = "active";
// let rCellularUsage = 0; let rCellularUsage = 0;
// let sessions: any[] = []; let sessions: any[] = [];
// if (usage.sessions) { if (usage.sessions) {
// sessions = usage.sessions.filter((session: any) => { sessions = usage.sessions.filter((session: any) => {
// return moment(session.begin).isAfter(moment().subtract(1, "days")); return moment(session.begin).isAfter(moment().subtract(1, "days"));
// }); });
// } }
// sessions.forEach((session: any) => (rCellularUsage += Number(or(session.bytes, 0)))); sessions.forEach((session: any) => (rCellularUsage += Number(or(session.bytes, 0))));
// setCellularStatus(rCellularStatus); setCellularStatus(rCellularStatus);
// setCellularUsage(rCellularUsage); setCellularUsage(rCellularUsage);
// } }
// }) })
// .catch(err => {}); .catch(err => {});
}, [componentAPI, props.device, deviceID, error, interactionsAPI, /*usageAPI*/, userAPI, user, as]); }, [componentAPI, props.device, deviceID, error, interactionsAPI, /*usageAPI*/, userAPI, user, as]);
useEffect(() => { useEffect(() => {

View file

@ -210,13 +210,14 @@ export default function DeviceWizard(props: Props) {
}; };
const setupCard = () => { const setupCard = () => {
const deviceIcon = GetDeviceProductIcon(device)
return ( return (
<Card className={classes.card} raised> <Card className={classes.card} raised>
<CardHeader <CardHeader
avatar={ avatar={
<Avatar <Avatar
variant="square" variant="square"
src={GetDeviceProductIcon(device.settings)} src={deviceIcon}
className={classes.avatarIcon} className={classes.avatarIcon}
alt={"devIcon"} alt={"devIcon"}
/> />

View file

@ -53,29 +53,6 @@ const useStyles = makeStyles((theme: Theme) => {
position: "relative", position: "relative",
width: "auto", width: "auto",
marginRight: theme.spacing(1) marginRight: theme.spacing(1)
},
sliderRoot: {},
sliderThumb: {
left: 23
},
mobileSliderThumb: {
left: 28
},
sliderTrack: {
height: "100%",
},
sliderRail: {
height: "100%",
},
sliderValLabel: {
// left: -20,
height: 30,
width: 30,
top: -15,
background: "transparent"
},
sliderLabel: {
background: "gold"
} }
}); });
}); });
@ -279,13 +256,6 @@ export default function GrainBagVisualizer(props: Props) {
<Slider <Slider
orientation="vertical" orientation="vertical"
value={fillLevel} value={fillLevel}
classes={{
root: classes.sliderRoot,
rail: classes.sliderRail,
track: classes.sliderTrack,
thumb: isMobile ? classes.mobileSliderThumb : classes.sliderThumb,
valueLabel: classes.sliderValLabel,
}}
style={{height: "100%", color: sliderColour }} style={{height: "100%", color: sliderColour }}
min={0} min={0}
max={100} max={100}

View file

@ -20,7 +20,7 @@ export {
// useSecurity, // useSecurity,
useSnackbar, useSnackbar,
// useTagAPI, // useTagAPI,
// useUsageAPI, useUsageAPI,
useUserAPI useUserAPI
} from "providers"; } from "providers";
export * from "./useDebounce"; export * from "./useDebounce";

View file

@ -584,6 +584,7 @@ export default function MapBase(props: Props) {
{tools()} {tools()}
{mapStyleDialog()} {mapStyleDialog()}
<Map <Map
style={{width: "100%", height: "100%"}}
ref={mapRef} ref={mapRef}
maxZoom={18} maxZoom={18}
initialViewState={startingView} initialViewState={startingView}

View file

@ -230,12 +230,12 @@ export default function FieldDrawer(props: Props) {
{field.fieldName()} Details {field.fieldName()} Details
</Typography> </Typography>
</Box> </Box>
<Grid container direction="column" alignItems="center"> <Grid container direction="column" alignItems="center" width="100%">
<Grid container direction="row" className={classes.dark}> <Grid container direction="row" justifyContent="space-between" width="100%" className={classes.dark}>
<Grid>Approximate Area:</Grid> <Grid>Approximate Area:</Grid>
<Grid>{field.acres()}ac</Grid> <Grid>{field.acres()}ac</Grid>
</Grid> </Grid>
<Grid container direction="row" className={classes.light}> <Grid container direction="row" justifyContent="space-between" width="100%" className={classes.light}>
<Grid>Grain:</Grid> <Grid>Grain:</Grid>
<Grid> <Grid>
{field.grain() === pond.Grain.GRAIN_CUSTOM {field.grain() === pond.Grain.GRAIN_CUSTOM
@ -243,11 +243,11 @@ export default function FieldDrawer(props: Props) {
: GrainDescriber(field.crop()).name} : GrainDescriber(field.crop()).name}
</Grid> </Grid>
</Grid> </Grid>
<Grid container direction="row" className={classes.dark}> <Grid container direction="row" justifyContent="space-between" width="100%" className={classes.dark}>
<Grid>Grain Variant:</Grid> <Grid>Grain Variant:</Grid>
<Grid>{field.settings.grainSubtype}</Grid> <Grid>{field.settings.grainSubtype}</Grid>
</Grid> </Grid>
<Grid container direction="row" className={classes.light}> <Grid container direction="row" justifyContent="space-between" width="100%" className={classes.light}>
<Grid>Land Location:</Grid> <Grid>Land Location:</Grid>
<Grid>{field.landLoc()}</Grid> <Grid>{field.landLoc()}</Grid>
</Grid> </Grid>

View file

@ -6,7 +6,7 @@ export default function AviationMap() {
const location = useLocation(); const location = useLocation();
return ( return (
<PageContainer> <PageContainer padding={-1}>
{location.state !== undefined && {location.state !== undefined &&
location.state !== null && location.state !== null &&
location.state.long !== undefined && location.state.long !== undefined &&

View file

@ -43,7 +43,6 @@ import BindaptIcon from "products/Bindapt/BindaptIcon";
import Close from "@mui/icons-material/Close"; import Close from "@mui/icons-material/Close";
import Chat from "chat/Chat"; import Chat from "chat/Chat";
import TasksIcon from "products/Construction/TasksIcon"; import TasksIcon from "products/Construction/TasksIcon";
// import TaskViewer from "tasks/TaskViewer";
import FieldsIcon from "products/AgIcons/FieldsIcon"; import FieldsIcon from "products/AgIcons/FieldsIcon";
import BinComponentTypes from "bin/BinComponentTypes"; import BinComponentTypes from "bin/BinComponentTypes";
import { Plenum } from "models/Plenum"; import { Plenum } from "models/Plenum";
@ -66,6 +65,7 @@ import BinConditioningCard from "bin/BinConditioningCard";
import { makeStyles, styled } from "@mui/styles"; import { makeStyles, styled } from "@mui/styles";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { Controller } from "models/Controller"; import { Controller } from "models/Controller";
import TaskViewer from "tasks/TaskViewer";
interface TabPanelProps { interface TabPanelProps {
children?: React.ReactNode; children?: React.ReactNode;
@ -547,10 +547,11 @@ export default function Bin(props: Props) {
}; };
const tasks = () => { const tasks = () => {
console.log(showTasks())
if (showTasks()) { if (showTasks()) {
return ( return (
<React.Fragment> <React.Fragment>
{/* <TaskViewer drawerView objectKey={binID} loadKeys={[binID]} /> */} <TaskViewer drawerView objectKey={binID} loadKeys={[binID]} />
</React.Fragment> </React.Fragment>
); );
} }
@ -1144,11 +1145,11 @@ export default function Bin(props: Props) {
anchor="right" anchor="right"
classes={{ paper: classes.drawerPaper }} classes={{ paper: classes.drawerPaper }}
onClose={() => setTaskDrawer(false)}> onClose={() => setTaskDrawer(false)}>
<Box paddingTop={10}> <Box>
<IconButton style={{ width: 50 }} onClick={() => setTaskDrawer(false)}> <IconButton style={{ width: 50 }} onClick={() => setTaskDrawer(false)}>
<Close /> <Close />
</IconButton> </IconButton>
{/* <TaskViewer drawerView objectKey={binID} loadKeys={[binID]} /> */} <TaskViewer drawerView objectKey={binID} loadKeys={[binID]} />
</Box> </Box>
</Drawer> </Drawer>
)} )}

View file

@ -6,7 +6,7 @@ export default function ConstructionSiteMap() {
const location = useLocation(); const location = useLocation();
return ( return (
<PageContainer> <PageContainer padding={-1}>
{location.state !== undefined && {location.state !== undefined &&
location.state !== null && location.state !== null &&
location.state.long !== undefined && location.state.long !== undefined &&

View file

@ -20,6 +20,7 @@ import { sameComponentID, sortComponents } from "pbHelpers/Component";
import { isController } from "pbHelpers/ComponentType"; import { isController } from "pbHelpers/ComponentType";
import { or } from "utils"; import { or } from "utils";
import ComponentDiagnostics from "component/ComponentDiagnostics"; import ComponentDiagnostics from "component/ComponentDiagnostics";
import DeviceWizard from "device/DeviceWizard";
export default function DevicePage() { export default function DevicePage() {
const deviceAPI = useDeviceAPI() const deviceAPI = useDeviceAPI()
@ -358,16 +359,16 @@ export default function DevicePage() {
</li> </li>
<Divider component="li" /> <Divider component="li" />
<ListItem> <ListItem>
<Grid container direction="row" spacing={2}> <Grid container direction="row" spacing={2} width={"100%"}>
{isMobile ? ( {isMobile ? (
<> <>
<Grid size={{ xs: 12 }}> <Grid size={{ xs: 12 }}>
{/* <DeviceWizard <DeviceWizard
device={device} device={device}
//permissions={permissions} //permissions={permissions}
components={Array.from(components.values())} components={Array.from(components.values())}
refreshCallback={load} refreshCallback={loadDevice}
/> */} />
</Grid> </Grid>
{diagnosticComponents.map(comp => ( {diagnosticComponents.map(comp => (
<Grid size={{ xs: 12 }} key={comp.key()}> <Grid size={{ xs: 12 }} key={comp.key()}>
@ -382,12 +383,12 @@ export default function DevicePage() {
) : ( ) : (
<> <>
<Grid size={{ xs: 6, sm: 6, lg: 4, xl: 3 }} > <Grid size={{ xs: 6, sm: 6, lg: 4, xl: 3 }} >
{/* <DeviceWizard <DeviceWizard
device={device} device={device}
//permissions={permissions} //permissions={permissions}
components={Array.from(components.values())} components={Array.from(components.values())}
refreshCallback={load} refreshCallback={loadDevice}
/> */} />
</Grid> </Grid>
<Grid size={{ xs: 6, sm: 6, lg: 8, xl: 9 }} > <Grid size={{ xs: 6, sm: 6, lg: 8, xl: 9 }} >
<Grid container direction="row" spacing={2}> <Grid container direction="row" spacing={2}>

View file

@ -5,7 +5,7 @@ import { useLocation } from "react-router";
export default function FieldMap() { export default function FieldMap() {
const location = useLocation(); const location = useLocation();
return ( return (
<PageContainer> <PageContainer padding={-1}>
{location.state !== undefined && {location.state !== undefined &&
location.state !== null && location.state !== null &&
location.state.long !== undefined && location.state.long !== undefined &&

View file

@ -87,7 +87,7 @@ export default function Gate(props: Props) {
//const match = useRouteMatch<MatchParams>(); //const match = useRouteMatch<MatchParams>();
//const gateID = props.gateID ?? match.params.gateID; //const gateID = props.gateID ?? match.params.gateID;
const { gateKey } = props const { gateKey } = props
const gateID = gateKey ?? useParams<{ gateID: string }>()?.gateID ?? ""; const gateID = gateKey ?? useParams<{ gateKey: string }>()?.gateKey ?? "";
const classes = useStyles(); const classes = useStyles();
const gateAPI = useGateAPI(); const gateAPI = useGateAPI();
const userAPI = useUserAPI(); const userAPI = useUserAPI();
@ -115,13 +115,17 @@ export default function Gate(props: Props) {
}; };
useEffect(() => { useEffect(() => {
console.log(gateID)
let key = gateID; let key = gateID;
let kind = "gate"; let kind = "gate";
if (as) { if (as) {
key = as; key = as;
kind = "team"; kind = "team";
} }
console.log(key)
console.log(kind)
userAPI.getUser(user.id(), { key: key, kind: kind } as Scope).then(resp => { userAPI.getUser(user.id(), { key: key, kind: kind } as Scope).then(resp => {
console.log(resp)
setPermissions(resp.permissions); setPermissions(resp.permissions);
}); });
}, [as, gateID, userAPI, user]); }, [as, gateID, userAPI, user]);

View file

@ -30,7 +30,7 @@ export {
useTeamAPI, useTeamAPI,
useImagekitAPI, useImagekitAPI,
useTaskAPI, //TODO: update api with resolve, reject useTaskAPI, //TODO: update api with resolve, reject
// useUsageAPI, useUsageAPI,//TODO: update api with resolve, reject
useUserAPI, useUserAPI,
// useStripeAPI, // useStripeAPI,
useDataDogProxyAPI, useDataDogProxyAPI,

View file

@ -32,6 +32,7 @@ import PreferenceProvider, {usePreferenceAPI} from "./preferenceAPI";
import TaskProvider, { useTaskAPI } from "./taskAPI"; import TaskProvider, { useTaskAPI } from "./taskAPI";
import DataDogProvider, { useDataDogProxyAPI } from "./datadogProxyAPI"; import DataDogProvider, { useDataDogProxyAPI } from "./datadogProxyAPI";
import ContractProvider, { useContractAPI } from "./contractAPI"; import ContractProvider, { useContractAPI } from "./contractAPI";
import UsageProvider, { useUsageAPI } from "./usageAPI";
// import NoteProvider from "providers/noteAPI"; // import NoteProvider from "providers/noteAPI";
export const pondURL = (partial: string, demo: boolean = false): string => { export const pondURL = (partial: string, demo: boolean = false): string => {
@ -80,7 +81,9 @@ export default function PondProvider(props: PropsWithChildren<any>) {
<TaskProvider> <TaskProvider>
<DataDogProvider> <DataDogProvider>
<ContractProvider> <ContractProvider>
{children} <UsageProvider>
{children}
</UsageProvider>
</ContractProvider> </ContractProvider>
</DataDogProvider> </DataDogProvider>
</TaskProvider> </TaskProvider>
@ -147,5 +150,6 @@ export {
usePreferenceAPI, usePreferenceAPI,
useTaskAPI, useTaskAPI,
useDataDogProxyAPI, useDataDogProxyAPI,
useContractAPI useContractAPI,
useUsageAPI
}; };

View file

@ -0,0 +1,99 @@
import { useHTTP } from "hooks";
import moment from "moment";
import { useGlobalState } from "providers";
import { createContext, PropsWithChildren, useContext } from "react";
import { pondURL } from "./pond";
export interface IUsageAPIContext {
getUsage: (
deviceID: number | string,
startDate?: any,
demo?: boolean,
keys?: string[],
types?: string[]
) => Promise<any>;
getUsages: (deviceIDs: number[], startDate?: any) => Promise<any>;
listUsages: (startDate?: any) => Promise<any>;
}
export const UsageAPIContext = createContext<IUsageAPIContext>({} as IUsageAPIContext);
function usageQuery(deviceIDs?: number[], startDate?: any): string {
let query = "";
let symbol: "?" | "&" = "?";
if (deviceIDs && deviceIDs.length > 0) {
query = query.concat(symbol + "ids=" + deviceIDs.join(","));
symbol = "&";
}
if (startDate) {
let start = moment(startDate).toISOString();
query = query.concat(symbol + "start=" + start);
symbol = "&";
}
return query;
}
interface Props {}
export default function UsageProvider(props: PropsWithChildren<Props>) {
const { children } = props;
const { get } = useHTTP();
const [{ as }] = useGlobalState();
const getUsage = (
deviceID: number | string,
startDate?: any,
demo: boolean = false,
keys?: string[],
types?: string[]
) => {
if (as && !(types && types.length > 0 && types[0] === "team"))
return get(
pondURL(
"/devices/" +
deviceID +
"/usage" +
usageQuery(undefined, startDate) +
"&as=" +
as +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : ""),
demo
)
);
return get(
pondURL(
"/devices/" +
deviceID +
"/usage" +
usageQuery(undefined, startDate) +
(keys ? "&keys=" + keys.toString() : "") +
(types ? "&types=" + types.toString() : ""),
demo
)
);
};
const getUsages = (deviceIDs: number[], startDate?: any) => {
if (as) return get(pondURL("/usage/devices" + usageQuery(deviceIDs, startDate) + "&as=" + as));
return get(pondURL("/usage/devices" + usageQuery(deviceIDs, startDate)));
};
const listUsages = (startDate?: any) => {
if (as) return get(pondURL("/usage" + usageQuery(undefined, startDate) + "&as=" + as));
return get(pondURL("/usage" + usageQuery(undefined, startDate)));
};
return (
<UsageAPIContext.Provider
value={{
getUsage,
getUsages,
listUsages
}}>
{children}
</UsageAPIContext.Provider>
);
}
export const useUsageAPI = () => useContext(UsageAPIContext);

View file

@ -19,6 +19,7 @@ import { useSnackbar, useUserAPI } from "hooks";
import { useEffect } from "react"; import { useEffect } from "react";
import { Task, teamScope, User } from "models"; import { Task, teamScope, User } from "models";
import ColourPicker from "common/ColourPicker"; import ColourPicker from "common/ColourPicker";
import ResponsiveDialog from "common/ResponsiveDialog";
interface Props { interface Props {
open: boolean; open: boolean;
@ -159,7 +160,7 @@ export default function TaskSettings(props: Props) {
}; };
return ( return (
<Dialog open={props.open} onClose={closeDialog}> <ResponsiveDialog open={props.open} onClose={closeDialog}>
<DialogTitle id="form-dialog-title">New Task</DialogTitle> <DialogTitle id="form-dialog-title">New Task</DialogTitle>
<DialogContent> <DialogContent>
<TextField <TextField
@ -346,6 +347,6 @@ export default function TaskSettings(props: Props) {
</Button> </Button>
)} )}
</DialogActions> </DialogActions>
</Dialog> </ResponsiveDialog>
); );
} }

View file

@ -40,6 +40,7 @@ import { blue, red } from "@mui/material/colors";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
import { Share, RemoveCircle as RemoveUserIcon } from "@mui/icons-material"; import { Share, RemoveCircle as RemoveUserIcon } from "@mui/icons-material";
import CancelSubmit from "common/CancelSubmit";
const useStyles = makeStyles((theme: Theme) => { const useStyles = makeStyles((theme: Theme) => {
const avatarBG = theme.palette.secondary["700" as keyof PaletteColor]; const avatarBG = theme.palette.secondary["700" as keyof PaletteColor];
@ -547,22 +548,29 @@ export default function ObjectTeams(props: Props) {
const actions = () => { const actions = () => {
return ( return (
<Grid container direction="row" justifyContent="space-between"> <CancelSubmit
<Grid size={{ xs: 4 }}></Grid> onCancel={close}
<Grid size={{ xs: 8 }} container justifyContent="flex-end"> onSubmit={submit}
{!cardMode && ( submitText={cardMode ? "Update" : "Submit"}
<Button onClick={close} color="primary"> />
Cancel )
</Button> // return (
)} // <Grid container direction="row" justifyContent="space-between">
{canManageUsers && ( // <Grid size={{ xs: 4 }}></Grid>
<Button onClick={submit} color="primary" disabled={objectUsersUnchanged()}> // <Grid size={{ xs: 8 }} container justifyContent="flex-end">
{cardMode ? "Update" : "Submit"} // {!cardMode && (
</Button> // <Button onClick={close} color="primary">
)} // Cancel
</Grid> // </Button>
</Grid> // )}
); // {canManageUsers && (
// <Button onClick={submit} color="primary" disabled={objectUsersUnchanged()}>
// {cardMode ? "Update" : "Submit"}
// </Button>
// )}
// </Grid>
// </Grid>
// );
}; };
const dialogs = () => { const dialogs = () => {