put the jd and cnh pages in, still need to test that the re-directs still function as expected with the new platform

This commit is contained in:
csawatzky 2025-04-23 13:25:45 -06:00
parent eb7efada69
commit 424b75afb8
13 changed files with 1393 additions and 64 deletions

View file

@ -0,0 +1,203 @@
import {
Avatar,
Box,
Button,
DialogActions,
DialogContent,
DialogTitle,
Grid,
MenuItem,
TextField
} from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog";
import { teamScope, User } from "models";
import { pond } from "protobuf-ts/pond";
import { useSnackbar, useUserAPI, useCNHiProxyAPI } from "providers";
import { useEffect, useState } from "react";
import { useLocation } from "react-router";
import TeamSearch from "teams/TeamSearch";
export default function CNHiAccess() {
const [openDialog, setOpenDialog] = useState(false);
const [teamKey, setTeamKey] = useState("");
const [teamUsers, setTeamUsers] = useState<User[]>([]);
const [primaryUser, setPrimaryUser] = useState("");
const [cnhiUsername, setCNHiUserName] = useState("");
const [cnhiCode, setCNHiCode] = useState<string | null>("");
//const [activeStep, setActiveStep] = useState<number>(0);
const userAPI = useUserAPI();
const cnhiAPI = useCNHiProxyAPI();
//const [dataOps, setDataOps] = useState<pond.DataOption[]>([]);
const { openSnack } = useSnackbar();
const search = useLocation().search;
const searchParams = new URLSearchParams(search);
//const [{ as }] = useGlobalState();
const client_id = import.meta.env.VITE_CNHI_CLIENT_ID;
const auth_url = import.meta.env.VITE_CNHI_AUTHORIZE_URL;
const redirect_url = import.meta.env.VITE_CNHI_REDIRECT_URI;
const scopes = import.meta.env.VITE_CNHI_SCOPES;
const connection = import.meta.env.VITE_CNHI_CONNECTION;
const audience = import.meta.env.VITE_CNHI_AUDIENCE;
const submitNewOrganization = () => {
if (cnhiCode) {
cnhiAPI
.addAccount(teamKey, primaryUser, cnhiCode, cnhiUsername)
.then(resp => {
//the code was used so remove it from local storage
if (localStorage.getItem("code")) {
localStorage.removeItem("code");
}
openSnack("Added New Case New Holland Account Link");
})
.catch(err => {
openSnack("Failed to Add New Case New Holland Account Link");
});
setOpenDialog(false);
}
};
useEffect(() => {
if (teamKey !== "") {
userAPI.listObjectUsers(teamScope(teamKey)).then(resp => {
setTeamUsers(resp.data.users.map((u: pond.User) => User.any(u)));
});
}
}, [teamKey, userAPI]);
useEffect(() => {
let code = localStorage.getItem("code");
if (code) {
setCNHiCode(code);
setOpenDialog(true);
}
}, [searchParams, cnhiCode]);
const validate = () => {
let invalid = false;
if (cnhiUsername === "" || teamKey === "" || primaryUser === "" || cnhiCode === "") {
invalid = true;
}
return invalid;
};
const general = () => {
return (
<Box>
<TextField
margin="dense"
label="Case New Holland Email"
fullWidth
variant="outlined"
value={cnhiUsername}
onChange={e => setCNHiUserName(e.target.value)}
/>
<TeamSearch label="Team" setTeamCallback={setTeamKey} />
<TextField
disabled={teamKey === ""}
margin="dense"
label="Primary User"
select
fullWidth
variant="outlined"
value={primaryUser}
onChange={e => setPrimaryUser(e.target.value)}>
{teamUsers.map(u => (
<MenuItem key={u.id()} value={u.id()}>
<Grid container direction="row" alignItems="center">
<Grid item>
<Avatar
alt={u.name()}
src={
u.settings.avatar && u.settings.avatar !== "" ? u.settings.avatar : undefined
}
/>
</Grid>
<Grid item>
<Box marginLeft={2}>{u.name()}</Box>
</Grid>
</Grid>
</MenuItem>
))}
</TextField>
<TextField
margin="dense"
label="code"
disabled
fullWidth
variant="outlined"
value={cnhiCode}
onChange={e => setCNHiCode(e.target.value)}
/>
</Box>
);
};
const newOrgDialog = () => {
return (
<ResponsiveDialog
open={openDialog}
onClose={() => {
setOpenDialog(false);
}}>
<DialogTitle>Enter New Integration Link</DialogTitle>
<DialogContent>{general()}</DialogContent>
<DialogActions>
<Button
onClick={() => {
setOpenDialog(false);
}}>
Close
</Button>
<Button
disabled={validate()}
onClick={submitNewOrganization}
variant="contained"
color="primary">
Submit
</Button>
</DialogActions>
</ResponsiveDialog>
);
};
return (
<Box style={{ padding: 10 }}>
<Button
variant="contained"
color="primary"
onClick={e => {
e.preventDefault();
window.open(
`${auth_url}?client_id=${client_id}&response_type=code&scope=${scopes}&redirect_uri=${redirect_url}&audience=${audience}&connection=${connection}`,
"_blank"
);
}}>
Link Case New Holland Account
</Button>
{newOrgDialog()}
{/* Admin testing buttons */}
{/*
<Button
onClick={() => {
setOpenDialog(true);
}}>
2. Choose team and user
</Button>
<Button
onClick={() => {
cnhiAPI
.listFields(100, 0, as)
.then(resp => {
console.log(resp);
})
.catch(err => {
console.log("errors found");
});
}}>
Field List test
</Button> */}
</Box>
);
}

View file

@ -0,0 +1,215 @@
import {
Avatar,
Box,
Button,
DialogActions,
DialogContent,
DialogTitle,
Grid2 as Grid,
MenuItem,
TextField
} from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog";
import { teamScope, User } from "models";
import { pond } from "protobuf-ts/pond";
import { useSnackbar, useUserAPI, useJohnDeereProxyAPI } from "providers";
import { useEffect, useState } from "react";
import { useLocation } from "react-router";
import TeamSearch from "teams/TeamSearch";
//const steps = [{label: "General"},{label: "Data Options"}]
export default function JDAccess() {
const [openDialog, setOpenDialog] = useState(false);
const [teamKey, setTeamKey] = useState("");
const [teamUsers, setTeamUsers] = useState<User[]>([]);
const [primaryUser, setPrimaryUser] = useState("");
const [jdUserName, setJDUserName] = useState("");
const [jdCode, setJDCode] = useState<string | null>("");
//const [activeStep, setActiveStep] = useState<number>(0);
const userAPI = useUserAPI();
const johnDeereAPI = useJohnDeereProxyAPI();
//const [dataOps, setDataOps] = useState<pond.DataOption[]>([]);
const { openSnack } = useSnackbar();
const search = useLocation().search;
const searchParams = new URLSearchParams(search);
//const [{ as }] = useGlobalState();
//const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN;
const client_id = import.meta.env.VITE_JD_CLIENT_ID;
const auth_url = import.meta.env.VITE_JD_AUTHORIZE_URL;
const redirect_url = import.meta.env.VITE_JD_REDIRECT_URI;
const scopes = import.meta.env.VITE_JD_SCOPES;
const state = import.meta.env.VITE_JD_STATE;
const submitNewOrganization = () => {
//api call to add the new organization
if (jdCode) {
johnDeereAPI
.addAccount(teamKey, primaryUser, jdCode, jdUserName)
.then(resp => {
//the code was used so remove it from local storage
if (sessionStorage.getItem("code")) {
sessionStorage.removeItem("code");
}
openSnack("Added New John Deere Account Link");
window.open(
`https://connections.deere.com/connections/${client_id}/select-organizations`
);
})
.catch(err => {
openSnack("Failed to Add New John Deere Account Link");
});
setOpenDialog(false);
}
};
useEffect(() => {
if (teamKey !== "") {
userAPI.listObjectUsers(teamScope(teamKey)).then(resp => {
setTeamUsers(resp.data.users.map((u: pond.User) => User.any(u)));
});
}
}, [teamKey, userAPI]);
useEffect(() => {
let code = sessionStorage.getItem("code");
if (code) {
setJDCode(code);
setOpenDialog(true);
}
}, [searchParams, jdCode]);
const validate = () => {
let invalid = false;
if (jdUserName === "" || teamKey === "" || primaryUser === "" || jdCode === "") {
invalid = true;
}
return invalid;
};
const general = () => {
return (
<Box>
<TextField
margin="dense"
label="John Deere Username"
fullWidth
variant="outlined"
value={jdUserName}
onChange={e => setJDUserName(e.target.value)}
/>
<TeamSearch label="Team" setTeamCallback={setTeamKey} />
<TextField
disabled={teamKey === ""}
margin="dense"
label="Primary User"
select
fullWidth
variant="outlined"
value={primaryUser}
onChange={e => setPrimaryUser(e.target.value)}>
{teamUsers.map(u => (
<MenuItem key={u.id()} value={u.id()}>
<Grid container direction="row" alignItems="center">
<Grid>
<Avatar
alt={u.name()}
src={
u.settings.avatar && u.settings.avatar !== "" ? u.settings.avatar : undefined
}
/>
</Grid>
<Grid>
<Box marginLeft={2}>{u.name()}</Box>
</Grid>
</Grid>
</MenuItem>
))}
</TextField>
<TextField
margin="dense"
label="code"
disabled
fullWidth
variant="outlined"
value={jdCode}
onChange={e => setJDCode(e.target.value)}
/>
</Box>
);
};
const newOrgDialog = () => {
return (
<ResponsiveDialog
open={openDialog}
onClose={() => {
setOpenDialog(false);
}}>
<DialogTitle>Enter New Integration Link</DialogTitle>
<DialogContent>{general()}</DialogContent>
<DialogActions>
<Button
onClick={() => {
setOpenDialog(false);
}}>
Close
</Button>
<Button
disabled={validate()}
onClick={submitNewOrganization}
variant="contained"
color="primary">
Submit
</Button>
</DialogActions>
</ResponsiveDialog>
);
};
return (
<Box style={{ padding: 10 }}>
<Button
variant="contained"
color="primary"
// onClick={e => {
// e.preventDefault();
// (window.location.href =
// // TODO: Remember to change the redirect uri to the correct address before putting this up on staging/prod
// `${auth_url}?response_type=code&scope=${scopes}&client_id=${client_id}&redirect_uri=${redirect_url}&state=${state}`),
// "_blank"
// }
onClick={e => {
e.preventDefault();
window.open(
`${auth_url}?response_type=code&scope=${scopes}&client_id=${client_id}&redirect_uri=${redirect_url}&state=${state}`,
"_blank"
);
}}>
Link John Deere Account
</Button>
{newOrgDialog()}
{/* admin buttons for testing */}
{/* <Button
onClick={() => {
johnDeereAPI
.listFields(100, 0, as)
.then(resp => {
console.log(resp);
})
.catch(err => {
console.log("errors found");
});
}}>
Field List test
</Button>
<Button
onClick={() => {
setOpenDialog(true);
}}>
2. Choose team and user
</Button>*/}
</Box>
);
}