added the firmware page
This commit is contained in:
parent
428e45f148
commit
31fae79fd5
10 changed files with 1909 additions and 1552 deletions
125
src/firmware/UpdateFirmwareChannel.tsx
Normal file
125
src/firmware/UpdateFirmwareChannel.tsx
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
MenuItem,
|
||||
TextField
|
||||
} from "@mui/material";
|
||||
import { useFirmwareAPI, usePrevious, useSnackbar } from "hooks";
|
||||
import { Firmware } from "models";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Props {
|
||||
firmware: Firmware;
|
||||
isOpen: boolean;
|
||||
closeCallback: Function;
|
||||
refreshCallback: Function;
|
||||
}
|
||||
|
||||
export default function UpdateFirmwareChannel(props: Props) {
|
||||
const firmwareAPI = useFirmwareAPI();
|
||||
const { isOpen, closeCallback, refreshCallback } = props;
|
||||
const prevFirmware = usePrevious(props.firmware);
|
||||
const { success, error } = useSnackbar();
|
||||
const [firmware, setFirmware] = useState<Firmware>(Firmware.create());
|
||||
|
||||
useEffect(() => {
|
||||
if (prevFirmware !== props.firmware) {
|
||||
setFirmware(Firmware.clone(props.firmware));
|
||||
}
|
||||
}, [firmware, prevFirmware, props.firmware]);
|
||||
|
||||
const closeDialog = () => {
|
||||
closeCallback();
|
||||
};
|
||||
|
||||
const changeChannel = (event: any) => {
|
||||
let updatedFirmware = firmware;
|
||||
updatedFirmware.settings.channel = event.target.value;
|
||||
setFirmware(updatedFirmware);
|
||||
};
|
||||
|
||||
const update = () => {
|
||||
firmwareAPI
|
||||
.updateChannel(
|
||||
firmware.settings.platform,
|
||||
firmware.settings.version,
|
||||
firmware.settings.channel
|
||||
)
|
||||
.then((response: any) => {
|
||||
success("Firmware channel updated");
|
||||
closeDialog();
|
||||
refreshCallback();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
error(err);
|
||||
});
|
||||
};
|
||||
|
||||
if (firmware === null || firmware === undefined) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<Dialog fullWidth open={isOpen} onClose={closeDialog} aria-labelledby="form-dialog-title">
|
||||
<DialogTitle id="form-dialog-title">Upload Firmware</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
disabled
|
||||
id="platform"
|
||||
name="platform"
|
||||
select
|
||||
label="Platform"
|
||||
margin="normal"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={firmware.settings.platform}>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_PHOTON}>Photon (Wifi)</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_ELECTRON}>
|
||||
Electron (Cellular)
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
<TextField
|
||||
disabled
|
||||
id="version"
|
||||
name="version"
|
||||
autoFocus
|
||||
label="Version"
|
||||
margin="normal"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={firmware.settings.version}
|
||||
/>
|
||||
<TextField
|
||||
id="channel"
|
||||
name="channel"
|
||||
select
|
||||
required
|
||||
label="Channel"
|
||||
margin="normal"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={firmware.settings.channel}
|
||||
onChange={changeChannel}>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_RECOVERY}>Recovery</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_DEVELOPMENT}>Development</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_ALPHA}>Alpha</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_BETA}>Beta</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_STABLE}>Stable</MenuItem>
|
||||
</TextField>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={closeDialog} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={update} color="primary">
|
||||
Update
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
304
src/firmware/UploadFirmware.tsx
Normal file
304
src/firmware/UploadFirmware.tsx
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
FormControlLabel,
|
||||
IconButton,
|
||||
InputBase,
|
||||
MenuItem,
|
||||
Paper,
|
||||
Switch,
|
||||
TextField,
|
||||
Theme
|
||||
} from "@mui/material";
|
||||
import { createStyles } from "@mui/styles";
|
||||
import withStyles, { WithStyles } from "@mui/styles/withStyles";
|
||||
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { FirmwareAPIContext } from "providers/pond/firmwareAPI";
|
||||
import React from "react";
|
||||
import semver from "semver";
|
||||
import { or } from "utils/types";
|
||||
|
||||
const styles = (theme: Theme) => {
|
||||
return createStyles({
|
||||
root: {
|
||||
padding: "2px 4px",
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
},
|
||||
input: {
|
||||
marginLeft: 8,
|
||||
flex: 1
|
||||
},
|
||||
iconButton: {
|
||||
padding: 10
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
interface Props extends WithStyles<typeof styles> {
|
||||
isOpen: boolean;
|
||||
closeDialogCallback: () => void;
|
||||
refreshCallback: () => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
dirty: boolean;
|
||||
version: string;
|
||||
platform: pond.DevicePlatform;
|
||||
channel: pond.UpgradeChannel;
|
||||
file?: Blob;
|
||||
breaksStorage: boolean;
|
||||
}
|
||||
|
||||
class UploadFirmware extends React.Component<Props, State> {
|
||||
static contextType = FirmwareAPIContext;
|
||||
declare context: React.ContextType<typeof FirmwareAPIContext>;
|
||||
selector: any;
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dirty: false,
|
||||
version: "",
|
||||
platform: pond.DevicePlatform.DEVICE_PLATFORM_PHOTON,
|
||||
channel: pond.UpgradeChannel.UPGRADE_CHANNEL_DEVELOPMENT,
|
||||
breaksStorage: false
|
||||
};
|
||||
}
|
||||
|
||||
isValid() {
|
||||
const { version, platform, channel, file } = this.state;
|
||||
var isPlatformValid = [
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_PHOTON,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_ELECTRON,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_S3,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_GREEN,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE
|
||||
].includes(platform);
|
||||
var isChannelValid = [
|
||||
pond.UpgradeChannel.UPGRADE_CHANNEL_ALPHA,
|
||||
pond.UpgradeChannel.UPGRADE_CHANNEL_BETA,
|
||||
pond.UpgradeChannel.UPGRADE_CHANNEL_STABLE,
|
||||
pond.UpgradeChannel.UPGRADE_CHANNEL_DEVELOPMENT
|
||||
].includes(channel);
|
||||
|
||||
var isVersionValid = semver.valid(version) !== null;
|
||||
var isFileValid = file !== undefined;
|
||||
return isPlatformValid && isChannelValid && isVersionValid && isFileValid;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.selector = document.createElement("input");
|
||||
this.selector.setAttribute("type", "file");
|
||||
var self = this;
|
||||
this.selector.addEventListener("change", function() {
|
||||
if (self.selector.files && self.selector.files.length > 0) {
|
||||
self.selectFile(self.selector.files[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closeDialog = () => {
|
||||
this.props.closeDialogCallback();
|
||||
};
|
||||
|
||||
openFileSelector = () => {
|
||||
this.selector.click();
|
||||
};
|
||||
|
||||
prefill = (filename: string) => {
|
||||
filename = filename.toLowerCase();
|
||||
var state: State = {} as State;
|
||||
if (filename.includes("photon") || filename.includes("wifi")) {
|
||||
state.platform = pond.DevicePlatform.DEVICE_PLATFORM_PHOTON;
|
||||
}
|
||||
if (filename.includes("electron") || filename.includes("cell")) {
|
||||
state.platform = pond.DevicePlatform.DEVICE_PLATFORM_ELECTRON;
|
||||
}
|
||||
if (filename.includes("alpha")) {
|
||||
state.channel = pond.UpgradeChannel.UPGRADE_CHANNEL_ALPHA;
|
||||
}
|
||||
if (filename.includes("beta")) {
|
||||
state.channel = pond.UpgradeChannel.UPGRADE_CHANNEL_BETA;
|
||||
}
|
||||
if (filename.includes("stable")) {
|
||||
state.channel = pond.UpgradeChannel.UPGRADE_CHANNEL_STABLE;
|
||||
}
|
||||
if (filename.includes("dev")) {
|
||||
state.channel = pond.UpgradeChannel.UPGRADE_CHANNEL_DEVELOPMENT;
|
||||
}
|
||||
var version = filename.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)*/g);
|
||||
if (version && version.length > 0) {
|
||||
state.version = version[0];
|
||||
}
|
||||
if (filename.includes("break")) {
|
||||
state.breaksStorage = true;
|
||||
}
|
||||
this.setState(state);
|
||||
};
|
||||
|
||||
selectFile = (file: any) => {
|
||||
const { dirty } = this.state;
|
||||
if (!dirty) {
|
||||
this.prefill(file.name);
|
||||
}
|
||||
this.setState({ file: file });
|
||||
};
|
||||
|
||||
uploadFirmware = () => {
|
||||
const { refreshCallback } = this.props;
|
||||
const { version, channel, platform, file, breaksStorage } = this.state;
|
||||
const firmwareAPI = this.context;
|
||||
if (file) {
|
||||
firmwareAPI
|
||||
.uploadFirmware(version, channel, platform, file, breaksStorage)
|
||||
.then(() => {
|
||||
this.closeDialog();
|
||||
refreshCallback();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.error(err ? err.message : "Error occurred while uploading firmware");
|
||||
});
|
||||
} else {
|
||||
console.error("Cannot upload firmware, file not found");
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { classes, isOpen } = this.props;
|
||||
const { version, channel, platform, file } = this.state;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
fullWidth
|
||||
open={isOpen}
|
||||
onClose={this.closeDialog}
|
||||
aria-labelledby="form-dialog-title">
|
||||
<DialogTitle id="form-dialog-title">Upload Firmware</DialogTitle>
|
||||
<DialogContent>
|
||||
<Paper className={classes.root} elevation={0}>
|
||||
<IconButton
|
||||
onClick={this.openFileSelector}
|
||||
className={classes.iconButton}
|
||||
aria-label="Select">
|
||||
<CloudUploadIcon />
|
||||
</IconButton>
|
||||
<InputBase
|
||||
disabled
|
||||
className={classes.input}
|
||||
placeholder="Select a binary"
|
||||
value={or(file as any, { name: "" }).name}
|
||||
/>
|
||||
</Paper>
|
||||
<TextField
|
||||
id="platform"
|
||||
name="platform"
|
||||
select
|
||||
required
|
||||
label="Platform"
|
||||
margin="normal"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={platform}
|
||||
onChange={event =>
|
||||
this.setState({
|
||||
platform: parseInt(event.target.value) as pond.DevicePlatform,
|
||||
dirty: true
|
||||
})
|
||||
}>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_PHOTON}>Photon (Wifi)</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_ELECTRON}>
|
||||
Electron (Cellular)
|
||||
</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR}>V2 Cellular</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_S3}>V2 Wifi S3</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK}>
|
||||
V2 Cellular Black
|
||||
</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_GREEN}>
|
||||
V2 Cellular Green
|
||||
</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE}>
|
||||
V2 Cellular Blue
|
||||
</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE}>
|
||||
V2 Wifi Blue
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
<TextField
|
||||
id="channel"
|
||||
name="channel"
|
||||
select
|
||||
required
|
||||
label="Channel"
|
||||
margin="normal"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={channel}
|
||||
onChange={event => {
|
||||
this.setState({
|
||||
channel: parseInt(event.target.value) as pond.UpgradeChannel,
|
||||
dirty: true
|
||||
});
|
||||
}}>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_RECOVERY}>Recovery</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_DEVELOPMENT}>Development</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_ALPHA}>Alpha</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_BETA}>Beta</MenuItem>
|
||||
<MenuItem value={pond.UpgradeChannel.UPGRADE_CHANNEL_STABLE}>Stable</MenuItem>
|
||||
</TextField>
|
||||
<TextField
|
||||
id="version"
|
||||
name="version"
|
||||
autoFocus
|
||||
required
|
||||
label="Version"
|
||||
margin="normal"
|
||||
type="text"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={version}
|
||||
onChange={event => {
|
||||
this.setState({
|
||||
version: event.target.value,
|
||||
dirty: true
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
name="breaksStorage"
|
||||
checked={this.state.breaksStorage}
|
||||
onChange={event => {
|
||||
this.setState({
|
||||
breaksStorage: event.target.checked,
|
||||
dirty: true
|
||||
});
|
||||
}}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="Breaks Storage"
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.closeDialog} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={this.uploadFirmware} color="primary" disabled={!this.isValid()}>
|
||||
Upload
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(UploadFirmware);
|
||||
Loading…
Add table
Add a link
Reference in a new issue