Merge pull request #520 from Fisker-Inc/CEC-5982

CEC-5982 - Allow selecting all VINs in a fleet for bulk Flashpack upd…
This commit is contained in:
Paul Adamsen
2024-04-19 15:18:03 -04:00
committed by GitHub
6 changed files with 137 additions and 16 deletions

View File

@@ -6,6 +6,8 @@ import vehiclesAPI from "../../../services/vehiclesAPI";
export default forwardRef(({ export default forwardRef(({
ids, ids,
idCSV, idCSV,
fleet,
selectAll,
}, ref) => { }, ref) => {
const { setMessage } = useStatusContext(); const { setMessage } = useStatusContext();
const { token: { idToken: { jwtToken: token } } } = useUserContext(); const { token: { idToken: { jwtToken: token } } } = useUserContext();
@@ -13,10 +15,12 @@ export default forwardRef(({
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
async submit() { async submit() {
return vehiclesAPI return vehiclesAPI
.flashpackVersionBulkUpdate(ids, token) .flashpackVersionBulkUpdate(selectAll, fleet, ids, token)
.then((data) => { .then((data) => {
if (data.error) { if (data.error) {
setMessage(`${data.error}: ${data.message}`); setMessage(`${data.error}: ${data.message}`);
} else if (selectAll) {
setMessage(`Updating flashpack number all VINs in ${fleet}`);
} else if (ids.length === 1) { } else if (ids.length === 1) {
setMessage(`Updating flashpack number for ${ids[0]}`); setMessage(`Updating flashpack number for ${ids[0]}`);
} else { } else {
@@ -26,11 +30,21 @@ export default forwardRef(({
}, },
})); }));
if (selectAll) {
return ( return (
<div> <div>
<p>
You are updating flashpack numbers for all VINs in the following fleet: {fleet}.
</p>
</div>
)
} else {
return (
< div >
<p> <p>
You are updating flashpack numbers for the following VINs: {idCSV}. You are updating flashpack numbers for the following VINs: {idCSV}.
</p> </p>
</div> </div>
); )
}
}); });

View File

@@ -21,6 +21,7 @@ export default function BulkActions({
ids = [], ids = [],
actions = [], actions = [],
fleet = undefined, fleet = undefined,
selectAll = false,
callback = (active, ids, context) => { }, // context is raised from the action itself callback = (active, ids, context) => { }, // context is raised from the action itself
}) { }) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -92,6 +93,7 @@ export default function BulkActions({
ids, ids,
idCSV: (ids && ids.length > 0) ? truncateCSV(ids, 10) : "N/A", idCSV: (ids && ids.length > 0) ? truncateCSV(ids, 10) : "N/A",
fleet, fleet,
selectAll,
ref: activeRef ref: activeRef
}; };
@@ -112,7 +114,7 @@ export default function BulkActions({
setEmbedded(action?.embedded); setEmbedded(action?.embedded);
}, [active, filteredActions]); }, [active, filteredActions]);
if (!ids || ids.length === 0) return <></>; if (!selectAll && (!ids || ids.length === 0)) return <></>;
return ( return (
<> <>

View File

@@ -38,12 +38,53 @@ exports[`FleetVehiclesTable Render 1`] = `
</svg> </svg>
</a> </a>
</div> </div>
<div
class="MuiGrid-root makeStyles-textJustifyAlign-0 MuiGrid-item MuiGrid-grid-md-2"
>
<label
class="MuiFormControlLabel-root"
>
<span
aria-disabled="false"
class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-0 MuiCheckbox-root MuiCheckbox-colorSecondary MuiIconButton-colorSecondary"
>
<span
class="MuiIconButton-label"
>
<input
class="PrivateSwitchBase-input-0"
data-indeterminate="false"
type="checkbox"
value=""
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
<span
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
>
Select All Vehicles
</span>
</label>
</div>
<div <div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-md-4" class="MuiGrid-root MuiGrid-item MuiGrid-grid-md-4"
/> />
<div <div
align="right" align="right"
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-7" class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-5"
> >
<div <div
class="MuiFormControl-root makeStyles-margin-0 makeStyles-fullWidth-0" class="MuiFormControl-root makeStyles-margin-0 makeStyles-fullWidth-0"

View File

@@ -1,5 +1,6 @@
import { import {
Checkbox, Checkbox,
FormControlLabel,
Grid, Grid,
LinearProgress, LinearProgress,
Table, Table,
@@ -70,6 +71,7 @@ const MainForm = ({ name }) => {
const [order, setOrder] = useState("desc"); const [order, setOrder] = useState("desc");
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [selected, setSelected] = useState([]); const [selected, setSelected] = useState([]);
const [selectAllSelected, setSelectAllSelected] = useState(false);
const componentMounted = useRef(true); const componentMounted = useRef(true);
const classes = useStyles(); const classes = useStyles();
const { setMessage } = useStatusContext(); const { setMessage } = useStatusContext();
@@ -174,15 +176,28 @@ const MainForm = ({ name }) => {
<AddCircleIcon fontSize="large" /> <AddCircleIcon fontSize="large" />
</Link> </Link>
</Grid> </Grid>
<Grid item md={2} className={classes.textJustifyAlign}>
<FormControlLabel control={
<Checkbox
checked={selectAllSelected}
onChange={() => setSelectAllSelected(selectAllSelected => !selectAllSelected)}
/>
} label="Select All Vehicles" />
</Grid>
<Grid item md={4}> <Grid item md={4}>
<BulkActions <BulkActions
actions={["updateFleetVehicles", "addTags", "sms", "updateConfig", "remoteCommand", "diagnostic", "updateFlashpackNumbers"]} actions={
selectAllSelected ?
["updateFlashpackNumbers"] :
["updateFleetVehicles", "addTags", "sms", "updateConfig", "remoteCommand", "diagnostic", "updateFlashpackNumbers"]
}
ids={selected} ids={selected}
fleet={name} fleet={name}
selectAll={selectAllSelected}
callback={bulkActionCallback} callback={bulkActionCallback}
/> />
</Grid> </Grid>
<Grid item md={7} align="right" className={classes.textCenterAlign}> <Grid item md={5} align="right" className={classes.textCenterAlign}>
<SearchField classes={classes} onSearch={handleSearch} /> <SearchField classes={classes} onSearch={handleSearch} />
</Grid> </Grid>
</Grid> </Grid>

View File

@@ -37,12 +37,53 @@ exports[`VehiclesTab Render 1`] = `
</svg> </svg>
</a> </a>
</div> </div>
<div
class="MuiGrid-root makeStyles-textJustifyAlign-0 MuiGrid-item MuiGrid-grid-md-2"
>
<label
class="MuiFormControlLabel-root"
>
<span
aria-disabled="false"
class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-0 MuiCheckbox-root MuiCheckbox-colorSecondary MuiIconButton-colorSecondary"
>
<span
class="MuiIconButton-label"
>
<input
class="PrivateSwitchBase-input-0"
data-indeterminate="false"
type="checkbox"
value=""
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
<span
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
>
Select All Vehicles
</span>
</label>
</div>
<div <div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-md-4" class="MuiGrid-root MuiGrid-item MuiGrid-grid-md-4"
/> />
<div <div
align="right" align="right"
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-7" class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-5"
> >
<div <div
class="MuiFormControl-root makeStyles-margin-0 makeStyles-fullWidth-0" class="MuiFormControl-root makeStyles-margin-0 makeStyles-fullWidth-0"

View File

@@ -341,8 +341,16 @@ const vehiclesAPI = {
.catch(errorHandler) .catch(errorHandler)
}, },
flashpackVersionBulkUpdate: async (vins, token) => { flashpackVersionBulkUpdate: async (selectAll, fleet, vins, token) => {
return fetch(`${API_ENDPOINT}/flashpack_version_bulk_update`, { var url = `${API_ENDPOINT}/flashpack_version_bulk_update`
const queryParams = {
fleet,
};
if (selectAll) {
url = addQueryParams(url, queryParams);
}
return fetch(url, {
method: "PUT", method: "PUT",
headers: Object.assign( headers: Object.assign(
{ "Content-Type": "application/json" }, { "Content-Type": "application/json" },