mirror of
https://git.netzspielplatz.de/docker-multiarch/openwrt-firmware-selector.git
synced 2025-11-08 23:39:37 +00:00
adds more display information and advanced section
Basic device information is added to be displayed along with the download buttons. Additionally, a warning432 message will be displayed if the size of the image is less than 4000k. New interface for customized image building with a custom selection of packages. Signed-off-by: Sudhanshu Gautam <me@sudhanshug.com>
This commit is contained in:
parent
16a6f7eb0b
commit
7cab0bfeb5
2 changed files with 188 additions and 68 deletions
|
|
@ -1,10 +1,30 @@
|
|||
import React from "react";
|
||||
import { Container, Paper, Typography, InputAdornment, FormControl, TextField, List, ListItem, ListItemText, CircularProgress, Button } from "@material-ui/core";
|
||||
import {
|
||||
Container,
|
||||
Paper,
|
||||
Typography,
|
||||
InputAdornment,
|
||||
FormControl,
|
||||
TextField,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
CircularProgress,
|
||||
Button,
|
||||
Grid,
|
||||
ClickAwayListener,
|
||||
ExpansionPanel,
|
||||
ExpansionPanelSummary,
|
||||
ExpansionPanelDetails,
|
||||
Checkbox,
|
||||
FormGroup,
|
||||
FormControlLabel } from "@material-ui/core";
|
||||
import { fade, makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
import CloudDownloadIcon from '@material-ui/icons/CloudDownload';
|
||||
import WarningIcon from '@material-ui/icons/Warning';
|
||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||
import './home.scss';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import FuzzySet from 'fuzzyset.js';
|
||||
|
|
@ -57,7 +77,7 @@ class Home extends React.Component {
|
|||
deviceNamesID = {};
|
||||
state = {
|
||||
showDeviceData: false,
|
||||
device: null,
|
||||
device: {},
|
||||
deviceLoaded: false,
|
||||
devices: [],
|
||||
devicesLoaded: false,
|
||||
|
|
@ -66,17 +86,20 @@ class Home extends React.Component {
|
|||
selectedSearchIndex: 0,
|
||||
query: '',
|
||||
downloading: false,
|
||||
packages: {},
|
||||
};
|
||||
fuzzySet;
|
||||
packages = ["opkg","ip6tables","odhcp6c","base-files","mtd","fstools","kmod-leds-gpio","busybox","wpad-mini","kmod-gpio-button-hotplug","kmod-mt76","logd","swconfig","dnsmasq","dropbear","ppp","netifd","ppp-mod-pppoe","uci","libc","uclient-fetch","kmod-ipt-offload","libgcc","odhcpd-ipv6only","iptables","firewall","luci"];
|
||||
|
||||
getDevicesData = () => fetch('https://chef.libremesh.org/download/json/devices.json').then(res => res.json());
|
||||
getDeviceData = (device_id) => fetch('https://chef.libremesh.org/download/json/' + device_id + '.json').then(res => res.json());
|
||||
|
||||
componentDidMount() {
|
||||
this.getDevicesData().then(data => {
|
||||
Object.keys(data['devices']).forEach((device_name) => {
|
||||
Object.keys(data['devices']).forEach((device_id) => {
|
||||
var device_name = data['devices'][device_id];
|
||||
this.deviceNames.push(device_name);
|
||||
this.deviceNamesID[device_name] = data['devices'][device_name];
|
||||
this.deviceNamesID[device_name] = device_id;
|
||||
});
|
||||
this.fuzzySet = FuzzySet(this.deviceNames);
|
||||
this.setState({
|
||||
|
|
@ -84,17 +107,25 @@ class Home extends React.Component {
|
|||
devicesLoaded: true,
|
||||
});
|
||||
});
|
||||
var packages = {};
|
||||
this.packages.forEach((package_name) => {
|
||||
packages[package_name] = true;
|
||||
});
|
||||
this.setState({
|
||||
packages,
|
||||
});
|
||||
}
|
||||
|
||||
selectDevice = (device_name) => {
|
||||
if (device_name != null) {
|
||||
var device_id = this.deviceNamesID[device_name];
|
||||
this.setState({
|
||||
showDeviceData: true,
|
||||
showSearch: false,
|
||||
query: device_name,
|
||||
deviceLoaded: false,
|
||||
});
|
||||
this.getDeviceData(this.state.devices[device_name]).then(data => {
|
||||
this.getDeviceData(device_id).then(data => {
|
||||
this.setState({
|
||||
device: data,
|
||||
deviceLoaded: true,
|
||||
|
|
@ -119,28 +150,22 @@ class Home extends React.Component {
|
|||
}
|
||||
this.setState({
|
||||
searchResults,
|
||||
showSearch: true,
|
||||
showSearch: query.length > 0,
|
||||
});
|
||||
}
|
||||
|
||||
isDescendant = (parent, child) => {
|
||||
var node = child.parentNode;
|
||||
if (child === parent) {
|
||||
return true;
|
||||
}
|
||||
while (node !== null) {
|
||||
if (node === parent) {
|
||||
return true;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return false;
|
||||
hideSearchResults = () => {
|
||||
console.log("bahar")
|
||||
this.setState({
|
||||
showSearch: false
|
||||
});
|
||||
}
|
||||
|
||||
toggleSearchIfIntended = (event) => {
|
||||
var showSearch = this.isDescendant(document.getElementsByClassName('search-container')[0], event.target) && this.state.query !== '';
|
||||
packageSettingChange = (event, package_name) => {
|
||||
var packages = this.state.packages;
|
||||
packages[package_name] = event.target.checked;
|
||||
this.setState({
|
||||
showSearch
|
||||
packages,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -156,6 +181,23 @@ class Home extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const warning432 = this.state.showDeviceData && parseInt((this.state.device['image_size'] || '').slice(0, -1)) <= 4000 && (
|
||||
<Paper className="warning-432" elevation={0}>
|
||||
<Grid
|
||||
container
|
||||
direction="row"
|
||||
justify="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Grid item>
|
||||
<WarningIcon className="icon" />
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
Devices with ≤4MB flash and/or ≤32MB ram will work but they will be very limited (usually they can't install or run additional packages) because they have low RAM and flash space. Consider this when choosing a device to buy, or when deciding to flash OpenWrt on your device because it is listed as supported.
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
);
|
||||
const notLoaded = (
|
||||
<CircularProgress />
|
||||
);
|
||||
|
|
@ -168,54 +210,57 @@ class Home extends React.Component {
|
|||
{this.props.t('Please use the input below to download firmware for your device!')}
|
||||
</Typography>
|
||||
<br />
|
||||
<div className="search-container">
|
||||
<FormControl fullWidth>
|
||||
<SearchTextField
|
||||
id="outlined-adornment-search-devices"
|
||||
labeltext={this.props.t('Search your device')}
|
||||
value={this.state.query}
|
||||
onChange={this.search}
|
||||
onClick={this.search}
|
||||
/>
|
||||
</FormControl>
|
||||
</div>
|
||||
{
|
||||
this.state.showSearch && (
|
||||
<Paper elevation={4} className="search-results">
|
||||
<List>
|
||||
{
|
||||
this.state.searchResults.map((res, index) => {
|
||||
return (
|
||||
<ListItem
|
||||
key={res}
|
||||
button
|
||||
onClick={() => this.selectDevice(res)}
|
||||
>
|
||||
<ListItemText primary={
|
||||
<div>
|
||||
{res}
|
||||
</div>
|
||||
} />
|
||||
</ListItem>
|
||||
);
|
||||
})
|
||||
}
|
||||
</List>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
{
|
||||
(this.state.searchResults.length === 0 && this.state.showSearch) && (
|
||||
<Paper elevation={4} className="search-results">
|
||||
<ListItem>
|
||||
<ListItemText primary={this.props.t('No results')}></ListItemText>
|
||||
</ListItem>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
<ClickAwayListener onClickAway={this.hideSearchResults}>
|
||||
<div className="search-container">
|
||||
<FormControl fullWidth>
|
||||
<SearchTextField
|
||||
id="outlined-adornment-search-devices"
|
||||
labeltext={this.props.t('Search your device')}
|
||||
value={this.state.query}
|
||||
onChange={this.search}
|
||||
onClick={this.search}
|
||||
/>
|
||||
</FormControl>
|
||||
{
|
||||
this.state.showSearch && (
|
||||
<Paper elevation={4} className="search-results">
|
||||
<List>
|
||||
{
|
||||
this.state.searchResults.map((res, index) => {
|
||||
return (
|
||||
<ListItem
|
||||
key={res}
|
||||
button
|
||||
onClick={() => this.selectDevice(res)}
|
||||
>
|
||||
<ListItemText primary={
|
||||
<div>
|
||||
{res}
|
||||
</div>
|
||||
} />
|
||||
</ListItem>
|
||||
);
|
||||
})
|
||||
}
|
||||
</List>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
{
|
||||
(this.state.searchResults.length === 0 && this.state.showSearch) && (
|
||||
<Paper elevation={4} className="search-results">
|
||||
<ListItem>
|
||||
<ListItemText primary={this.props.t('No results')}></ListItemText>
|
||||
</ListItem>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</ClickAwayListener>
|
||||
{
|
||||
this.state.showDeviceData && !this.state.deviceLoaded && (
|
||||
<>
|
||||
<br />
|
||||
{ notLoaded }
|
||||
</>
|
||||
)
|
||||
|
|
@ -223,7 +268,52 @@ class Home extends React.Component {
|
|||
{
|
||||
this.state.showDeviceData && this.state.deviceLoaded && (
|
||||
<>
|
||||
{ warning432 }
|
||||
<br />
|
||||
<Grid container className="device-info">
|
||||
<Grid item xs>
|
||||
<b>Name: </b> {this.state.device['title']}
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<b>Target: </b> {this.state.device['target']}
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<b>Subtarget: </b> {this.state.device['subtarget']}
|
||||
</Grid>
|
||||
<Grid item xs>
|
||||
<b>Image Size: </b> {this.state.device['image_size']}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ExpansionPanel elevation={0} className="advanced-settings">
|
||||
<ExpansionPanelSummary
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
aria-controls="panel1a-content"
|
||||
id="panel1a-header"
|
||||
>
|
||||
<Typography>Customize Packages (<WarningIcon className="icon" /> for advanced users)</Typography>
|
||||
</ExpansionPanelSummary>
|
||||
<ExpansionPanelDetails className="options">
|
||||
<FormGroup row>
|
||||
{
|
||||
this.packages.map((package_name, i) => {
|
||||
return (
|
||||
<FormControlLabel
|
||||
key={i}
|
||||
control={
|
||||
<Checkbox
|
||||
onChange={(event) => this.packageSettingChange(event, package_name)}
|
||||
value={this.state.packages[package_name]}
|
||||
checked={this.state.packages[package_name]}
|
||||
/>
|
||||
}
|
||||
label={package_name}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</FormGroup>
|
||||
</ExpansionPanelDetails>
|
||||
</ExpansionPanel>
|
||||
{
|
||||
this.state.device.images.map((image, i) => {
|
||||
return (
|
||||
|
|
@ -253,7 +343,7 @@ class Home extends React.Component {
|
|||
</>
|
||||
);
|
||||
return (
|
||||
<Container className="home-container" onClick={this.toggleSearchIfIntended}>
|
||||
<Container className="home-container">
|
||||
<Paper className="home-container-paper">
|
||||
{ this.state.devicesLoaded ? onLoad : notLoaded }
|
||||
</Paper>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,20 @@
|
|||
.home-container-paper {
|
||||
padding: 30px;
|
||||
text-align: left;
|
||||
.warning-432 {
|
||||
background-color: #f0f0f0;
|
||||
padding: 10px;
|
||||
margin-top: 20px;
|
||||
border: 1px solid #e3e3e3;
|
||||
color: #666;
|
||||
.icon {
|
||||
margin: 0 20px 0 10px;
|
||||
color: #F9A825
|
||||
}
|
||||
}
|
||||
.device-info {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.search-label {
|
||||
background-color: #fff;
|
||||
padding: 0 10px;
|
||||
|
|
@ -23,6 +37,22 @@
|
|||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.advanced-settings {
|
||||
border: 1px solid #999;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 6px;
|
||||
margin-top: 20px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20px;
|
||||
.icon {
|
||||
font-size: 1em;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.options {
|
||||
padding-top: 30px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue