mirror of
https://git.netzspielplatz.de/docker-multiarch/openwrt-firmware-selector.git
synced 2025-11-08 18:59:27 +00:00
Introduce interface to list packages in built image
A dropdown interface that lists all the installed packages for the built images. Fixes #7 Signed-off-by: Sudhanshu Gautam <me@sudhanshug.com>
This commit is contained in:
parent
acdb7741e8
commit
3f46d13ccf
3 changed files with 127 additions and 63 deletions
|
|
@ -37,7 +37,8 @@
|
||||||
padding: 15px 10%;
|
padding: 15px 10%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-radius: 0
|
border-radius: 0;
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.report-link {
|
.report-link {
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,14 @@ import {
|
||||||
Tabs,
|
Tabs,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
|
ExpansionPanel,
|
||||||
|
ExpansionPanelSummary,
|
||||||
|
ExpansionPanelDetails
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import CloudDownloadIcon from '@material-ui/icons/CloudDownload';
|
import CloudDownloadIcon from '@material-ui/icons/CloudDownload';
|
||||||
import WarningIcon from '@material-ui/icons/Warning';
|
import WarningIcon from '@material-ui/icons/Warning';
|
||||||
import BuildIcon from '@material-ui/icons/Build';
|
import BuildIcon from '@material-ui/icons/Build';
|
||||||
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||||
import './home.scss';
|
import './home.scss';
|
||||||
import {withTranslation} from 'react-i18next';
|
import {withTranslation} from 'react-i18next';
|
||||||
import FuzzySet from 'fuzzyset.js';
|
import FuzzySet from 'fuzzyset.js';
|
||||||
|
|
@ -74,6 +78,7 @@ class Home extends React.Component {
|
||||||
packages: this.packages,
|
packages: this.packages,
|
||||||
configChanged: true,
|
configChanged: true,
|
||||||
packageName: '',
|
packageName: '',
|
||||||
|
builtDeviceManifest: [],
|
||||||
builtImages: [],
|
builtImages: [],
|
||||||
isBuilding: false,
|
isBuilding: false,
|
||||||
queuePosition: -1,
|
queuePosition: -1,
|
||||||
|
|
@ -280,6 +285,12 @@ class Home extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
displayBuiltImageData = async (buildStatusResponse) => {
|
displayBuiltImageData = async (buildStatusResponse) => {
|
||||||
|
const manifestResponse = await this.dataService.getDeviceManifest(
|
||||||
|
buildStatusResponse.data.image_folder + '/' + buildStatusResponse.data.image_prefix + '.manifest'
|
||||||
|
);
|
||||||
|
|
||||||
|
const builtDeviceManifest = manifestResponse.data.split('\n');
|
||||||
|
|
||||||
let builtImages = [];
|
let builtImages = [];
|
||||||
buildStatusResponse.data.images.forEach((image) => {
|
buildStatusResponse.data.images.forEach((image) => {
|
||||||
builtImages.push({
|
builtImages.push({
|
||||||
|
|
@ -290,6 +301,7 @@ class Home extends React.Component {
|
||||||
});
|
});
|
||||||
if (this.state.isBuilding) {
|
if (this.state.isBuilding) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
builtDeviceManifest,
|
||||||
builtImages,
|
builtImages,
|
||||||
configChanged: false,
|
configChanged: false,
|
||||||
isBuilding: false,
|
isBuilding: false,
|
||||||
|
|
@ -298,42 +310,63 @@ class Home extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
buildImageCheck = async (request_hash) => {
|
buildImageCheck = async (request_hash) => {
|
||||||
return new Promise(async (resolve, reject) => {
|
try {
|
||||||
try {
|
if (!this.state.isBuilding) {
|
||||||
if (!this.state.isBuilding) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const buildStatusResponse = await this.dataService.buildStatusCheck(request_hash);
|
|
||||||
if (buildStatusResponse.status === 202) {
|
|
||||||
if (buildStatusResponse.headers['X-Build-Queue-Position'] !== undefined) {
|
|
||||||
this.setState({
|
|
||||||
queuePosition: buildStatusResponse.headers['X-Build-Queue-Position'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await sleep(buildStatusCheckInterval);
|
|
||||||
await this.buildImageCheck(request_hash);
|
|
||||||
resolve();
|
|
||||||
} else if (buildStatusResponse.status === 200) {
|
|
||||||
await this.displayBuiltImageData(buildStatusResponse);
|
|
||||||
resolve();
|
|
||||||
} else if (buildStatusResponse.status === 409) {
|
|
||||||
this.setState({
|
|
||||||
openErrorDialog: true,
|
|
||||||
errorDialogMessage: (
|
|
||||||
<>
|
|
||||||
{buildStatusResponse.data.error} <br />
|
|
||||||
<a href={buildStatusResponse.data.error}>Build logs</a>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
});
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
throw buildStatusResponse.data;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
}
|
}
|
||||||
});
|
const buildStatusResponse = await this.dataService.buildStatusCheck(request_hash);
|
||||||
|
if (buildStatusResponse.status === 202) {
|
||||||
|
if (buildStatusResponse.headers['X-Build-Queue-Position'] !== undefined) {
|
||||||
|
this.setState({
|
||||||
|
queuePosition: buildStatusResponse.headers['X-Build-Queue-Position'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await sleep(buildStatusCheckInterval);
|
||||||
|
await this.buildImageCheck(request_hash);
|
||||||
|
} else if (buildStatusResponse.status === 200) {
|
||||||
|
await this.displayBuiltImageData(buildStatusResponse);
|
||||||
|
} else if (buildStatusResponse.status === 409) {
|
||||||
|
this.setState({
|
||||||
|
openErrorDialog: true,
|
||||||
|
errorDialogMessage: (
|
||||||
|
<>
|
||||||
|
{buildStatusResponse.data.error} <br />
|
||||||
|
<a href={buildStatusResponse.data.error}>Build logs</a>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw buildStatusResponse.data;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e.response.status === 409) {
|
||||||
|
this.setState({
|
||||||
|
isBuilding: false,
|
||||||
|
openErrorDialog: true,
|
||||||
|
errorDialogMessage: (
|
||||||
|
<>
|
||||||
|
{e.response.data.error} <br />
|
||||||
|
<a href={asu + e.response.data.log} target="_blank" rel="noopener noreferrer">Build logs</a>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else if (e.response.status === 422) {
|
||||||
|
this.setState({
|
||||||
|
isBuilding: false,
|
||||||
|
openErrorDialog: true,
|
||||||
|
errorDialogMessage: (
|
||||||
|
<>
|
||||||
|
{e.response.data.error}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
isBuilding: false,
|
||||||
|
showUnexpectedErrorBar: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
buildImage = async () => {
|
buildImage = async () => {
|
||||||
|
|
@ -348,7 +381,6 @@ class Home extends React.Component {
|
||||||
builtImages: [],
|
builtImages: [],
|
||||||
});
|
});
|
||||||
let buildResponse = await this.dataService.buildImage(board, packages, target, version);
|
let buildResponse = await this.dataService.buildImage(board, packages, target, version);
|
||||||
console.log(buildResponse);
|
|
||||||
if (buildResponse.status === 202 && buildResponse.data['request_hash'] !== undefined) {
|
if (buildResponse.status === 202 && buildResponse.data['request_hash'] !== undefined) {
|
||||||
const request_hash = buildResponse.data['request_hash'];
|
const request_hash = buildResponse.data['request_hash'];
|
||||||
await sleep(buildStatusCheckInterval);
|
await sleep(buildStatusCheckInterval);
|
||||||
|
|
@ -576,13 +608,13 @@ class Home extends React.Component {
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
this.state.packages.map((package_name, i) =>
|
this.state.packages.map((package_name, i) =>
|
||||||
<Chip className="package"
|
<Chip className="package"
|
||||||
key={package_name + i}
|
key={package_name + i}
|
||||||
size="small"
|
size="small"
|
||||||
onDelete={() => this.deletePackage(
|
onDelete={() => this.deletePackage(
|
||||||
i)}
|
i)}
|
||||||
label={package_name}
|
label={package_name}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
|
@ -638,29 +670,46 @@ class Home extends React.Component {
|
||||||
{this.props.t('Model')}: <b> {this.state.selection.device['title']} </b> <br />
|
{this.props.t('Model')}: <b> {this.state.selection.device['title']} </b> <br />
|
||||||
{this.props.t('Target')}: {this.state.selection.device['target']} <br />
|
{this.props.t('Target')}: {this.state.selection.device['target']} <br />
|
||||||
{this.props.t('Version')}: {this.state.data[this.state.selection.version].name} ({this.state.data[this.state.selection.version].revision})
|
{this.props.t('Version')}: {this.state.data[this.state.selection.version].name} ({this.state.data[this.state.selection.version].revision})
|
||||||
|
<ExpansionPanel className="installed-packages" elevation={0}>
|
||||||
|
<ExpansionPanelSummary
|
||||||
|
expandIcon={<ExpandMoreIcon />}
|
||||||
|
id="packages-manifest"
|
||||||
|
>
|
||||||
|
<Typography className="installed-packages-title">Installed Packages ({this.state.builtDeviceManifest.length})</Typography>
|
||||||
|
</ExpansionPanelSummary>
|
||||||
|
<ExpansionPanelDetails>
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
this.state.builtDeviceManifest.map(
|
||||||
|
(package_name) => <div key={package_name}>
|
||||||
|
{package_name}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</ExpansionPanelDetails>
|
||||||
|
</ExpansionPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs>
|
<Grid item xs>
|
||||||
<b>{this.props.t('Downloads')}: </b>
|
<b>{this.props.t('Downloads')}: </b>
|
||||||
{
|
{
|
||||||
this.state.builtImages.map((image) => (
|
this.state.builtImages.map((image) =>
|
||||||
<>
|
<div key={image.url}>
|
||||||
<br />
|
<Button
|
||||||
<Button
|
className="download-button"
|
||||||
key={image.url}
|
href={image.url}
|
||||||
className="download-button"
|
color="primary"
|
||||||
href={image.url}
|
variant="contained"
|
||||||
color="primary"
|
onClick={() => this.downloadingImageIndicatorShow()}
|
||||||
variant="contained"
|
>
|
||||||
onClick={() => this.downloadingImageIndicatorShow()}
|
<CloudDownloadIcon
|
||||||
>
|
className="download-icon"/>
|
||||||
<CloudDownloadIcon
|
{image.type}
|
||||||
className="download-icon"/>
|
</Button>
|
||||||
{image.type}
|
</div>
|
||||||
</Button>
|
)
|
||||||
</>
|
}
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
this.state.downloading && (
|
this.state.downloading && (
|
||||||
<CircularProgress size={20}/>
|
<CircularProgress size={20}/>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,19 @@ $bg-color: #f0f0f0;
|
||||||
|
|
||||||
.device-info {
|
.device-info {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
.installed-packages {
|
||||||
|
width: 80%;
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
border-radius: 7px;
|
||||||
|
margin-top: 16px !important;
|
||||||
|
}
|
||||||
|
.installed-packages::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.installed-packages-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-select {
|
.version-select {
|
||||||
|
|
@ -76,6 +89,7 @@ $bg-color: #f0f0f0;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.download-button {
|
.download-button {
|
||||||
margin-top: 17px;
|
margin-top: 17px;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue