add ASU compatibility
51
.eslintrc.js
|
|
@ -1,42 +1,31 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
parser: '@typescript-eslint/parser', // Specifies the ESLint parserx
|
||||||
'airbnb-typescript',
|
plugins: ['react-hooks', 'prettier'],
|
||||||
'airbnb/hooks',
|
settings: {
|
||||||
'plugin:@typescript-eslint/recommended',
|
react: {
|
||||||
'plugin:jest/recommended',
|
version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
|
||||||
'prettier',
|
|
||||||
'prettier/react',
|
|
||||||
'prettier/@typescript-eslint',
|
|
||||||
'plugin:prettier/recommended',
|
|
||||||
],
|
|
||||||
plugins: ['react', '@typescript-eslint', 'jest'],
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
es6: true,
|
|
||||||
jest: true,
|
|
||||||
},
|
|
||||||
globals: {
|
|
||||||
Atomics: 'readonly',
|
|
||||||
SharedArrayBuffer: 'readonly',
|
|
||||||
},
|
|
||||||
root: true,
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
parserOptions: {
|
|
||||||
ecmaFeatures: {
|
|
||||||
jsx: true,
|
|
||||||
},
|
},
|
||||||
ecmaVersion: 2018,
|
|
||||||
sourceType: 'module',
|
|
||||||
project: './tsconfig.json',
|
|
||||||
},
|
},
|
||||||
|
extends: [
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:prettier/recommended', // Make sure this is always the last configuration in the extends array.
|
||||||
|
'plugin:jest/recommended',
|
||||||
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'linebreak-style': 'off',
|
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
|
||||||
|
// Consider turning on eventually... lots of warnings though.
|
||||||
|
'max-len': ['error', 100],
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'react/react-in-jsx-scope': 'off',
|
||||||
|
// This rule is redundent when using arrow functions and we should only use arrow functions
|
||||||
'react/prop-types': 'off',
|
'react/prop-types': 'off',
|
||||||
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
|
|
||||||
'prettier/prettier': [
|
'prettier/prettier': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
endOfLine: 'auto',
|
trailingComma: 'all',
|
||||||
|
arrowParens: 'always',
|
||||||
|
printWidth: 100,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,14 @@
|
||||||
"i18next": "^17.0.4",
|
"i18next": "^17.0.4",
|
||||||
"i18next-browser-languagedetector": "^3.0.1",
|
"i18next-browser-languagedetector": "^3.0.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
|
"luxon": "^1.26.0",
|
||||||
"match-sorter": "^6.1.0",
|
"match-sorter": "^6.1.0",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.8.6",
|
"react-dom": "^16.8.6",
|
||||||
"react-i18next": "^10.11.2",
|
"react-i18next": "^10.11.2",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "4.0.1",
|
"react-scripts": "4.0.1",
|
||||||
|
"react-svg": "^12.1.0",
|
||||||
"react-use": "^15.3.8",
|
"react-use": "^15.3.8",
|
||||||
"web-vitals": "^1.0.1"
|
"web-vitals": "^1.0.1"
|
||||||
},
|
},
|
||||||
|
|
@ -50,6 +52,7 @@
|
||||||
"@testing-library/react": "^11.2.3",
|
"@testing-library/react": "^11.2.3",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/lodash": "^4.14.167",
|
"@types/lodash": "^4.14.167",
|
||||||
|
"@types/luxon": "^1.26.2",
|
||||||
"@types/react": "^17.0.0",
|
"@types/react": "^17.0.0",
|
||||||
"@types/react-dom": "^17.0.0",
|
"@types/react-dom": "^17.0.0",
|
||||||
"@types/react-router-dom": "^5.1.7",
|
"@types/react-router-dom": "^5.1.7",
|
||||||
|
|
@ -57,15 +60,10 @@
|
||||||
"@typescript-eslint/parser": "^4.12.0",
|
"@typescript-eslint/parser": "^4.12.0",
|
||||||
"axios-mock-adapter": "^1.19.0",
|
"axios-mock-adapter": "^1.19.0",
|
||||||
"eslint": "7.2.0",
|
"eslint": "7.2.0",
|
||||||
"eslint-config-airbnb": "18.2.1",
|
|
||||||
"eslint-config-airbnb-typescript": "^12.0.0",
|
|
||||||
"eslint-config-prettier": "^7.1.0",
|
"eslint-config-prettier": "^7.1.0",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
|
||||||
"eslint-plugin-jest": "^24.1.3",
|
"eslint-plugin-jest": "^24.1.3",
|
||||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-react": "^7.21.5",
|
|
||||||
"eslint-plugin-react-hooks": "4.0.0",
|
|
||||||
"husky": "^3.0.5",
|
"husky": "^3.0.5",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 54 KiB |
22
src/App.scss
|
|
@ -46,6 +46,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
.logo {
|
||||||
|
height: 40px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
& svg {
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title-desktop {
|
.title-desktop {
|
||||||
@media all and (max-width: 820px) {
|
@media all and (max-width: 820px) {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -74,7 +86,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 800px) {
|
||||||
|
.mobile {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media all and (max-width: 800px) {
|
@media all and (max-width: 800px) {
|
||||||
|
.desktop {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.report-problem-container {
|
.report-problem-container {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
|
||||||
41
src/App.tsx
|
|
@ -13,12 +13,47 @@ import Footer from './components/Footer';
|
||||||
const theme = createMuiTheme({
|
const theme = createMuiTheme({
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: '#3F51B5',
|
main: '#00B5E2',
|
||||||
|
contrastText: '#ffffff',
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: '#009688',
|
main: '#212322',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
typography: {
|
||||||
|
h1: {
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
h2: {
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
h3: {
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
h4: {
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
h5: {
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
h6: {
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
fontFamily: [
|
||||||
|
'Open Sans',
|
||||||
|
'-apple-system',
|
||||||
|
'BlinkMacSystemFont',
|
||||||
|
'Segoe UI',
|
||||||
|
'Roboto',
|
||||||
|
'Oxygen',
|
||||||
|
'Ubuntu',
|
||||||
|
'Cantarell',
|
||||||
|
'Fira Sans',
|
||||||
|
'Droid Sans',
|
||||||
|
'Helvetica Neue',
|
||||||
|
,
|
||||||
|
].join(','),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const App: FunctionComponent = () => {
|
const App: FunctionComponent = () => {
|
||||||
|
|
@ -30,7 +65,7 @@ const App: FunctionComponent = () => {
|
||||||
<Router>
|
<Router>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="" exact component={Home} />
|
<Route path="" exact component={Home} />
|
||||||
<Route default component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { fireEvent, render, RenderResult, waitFor } from '@testing-library/react';
|
import { fireEvent, render, RenderResult, waitFor } from '@testing-library/react';
|
||||||
|
|
||||||
import Header from './Header';
|
import Header from '.';
|
||||||
|
|
||||||
const mockChangeLanguage = jest.fn();
|
const mockChangeLanguage = jest.fn();
|
||||||
|
|
||||||
|
|
@ -11,9 +11,11 @@ import {
|
||||||
Typography,
|
Typography,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { ReactSVG } from 'react-svg';
|
||||||
|
|
||||||
import locales from '../locales';
|
import logo from '../../images/logo-white.svg';
|
||||||
import '../App.scss';
|
import locales from '../../locales';
|
||||||
|
import '../../App.scss';
|
||||||
|
|
||||||
const Header: FunctionComponent = () => {
|
const Header: FunctionComponent = () => {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
@ -32,8 +34,10 @@ const Header: FunctionComponent = () => {
|
||||||
return (
|
return (
|
||||||
<AppBar position="sticky" className="header">
|
<AppBar position="sticky" className="header">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Typography variant="h6">{t('tr-title')}</Typography>
|
<ReactSVG src={logo} className="logo" />
|
||||||
<span className="title-mobile">{t('tr-title')}</span>
|
<Typography variant="h5" component="div">
|
||||||
|
{t('tr-title')}
|
||||||
|
</Typography>
|
||||||
<div style={{ flexGrow: 1 }} />
|
<div style={{ flexGrow: 1 }} />
|
||||||
<Box position="relative">
|
<Box position="relative">
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -5,10 +5,10 @@ const config = {
|
||||||
show_help: true,
|
show_help: true,
|
||||||
|
|
||||||
// Path to overview.json file or URL to the ASU API
|
// Path to overview.json file or URL to the ASU API
|
||||||
versions: { '19.07.5': 'data/19.07.5', SNAPSHOT: 'data/SNAPSHOT' },
|
versions: { '19.07.7': 'data/19.07.7', SNAPSHOT: 'data/SNAPSHOT' },
|
||||||
|
|
||||||
// Pre-selected version (optional)
|
// Pre-selected version (optional)
|
||||||
default_version: '19.07.5',
|
default_version: '19.07.7',
|
||||||
|
|
||||||
// Image download URL (optional)
|
// Image download URL (optional)
|
||||||
image_url: 'https://downloads.openwrt.org/releases/{version}/targets/{target}',
|
image_url: 'https://downloads.openwrt.org/releases/{version}/targets/{target}',
|
||||||
|
|
@ -18,7 +18,7 @@ const config = {
|
||||||
|
|
||||||
// Build custom images (optional)
|
// Build custom images (optional)
|
||||||
// See https://github.com/aparcar/asu
|
// See https://github.com/aparcar/asu
|
||||||
// asu_url: 'https://chef.libremesh.org'
|
asu_url: 'https://chef.libremesh.org',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,16 @@ import React, { FunctionComponent, ReactNode, useCallback, useEffect, useState }
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
|
Chip,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
|
FormControl,
|
||||||
|
Grid,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
InputAdornment,
|
||||||
|
InputLabel,
|
||||||
Link,
|
Link,
|
||||||
|
makeStyles,
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
|
|
@ -12,15 +20,26 @@ import {
|
||||||
TableRow,
|
TableRow,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { Launch, CloudDownload } from '@material-ui/icons';
|
import { Launch, CloudDownload, Add } from '@material-ui/icons';
|
||||||
import Axios from 'axios';
|
import axios from 'axios';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
import { ProfilesEntity } from '../../../types/overview';
|
import { ProfilesEntity } from '../../../types/overview';
|
||||||
import { Profile, TitlesEntity } from '../../../types/profile';
|
import { Profile, TitlesEntity } from '../../../types/profile';
|
||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
import { getTitle } from '../utils/title';
|
import { getTitle } from '../utils/title';
|
||||||
|
import asu from '../../../utils/asu';
|
||||||
|
import { GetBuildResponse } from '../../../types/asu';
|
||||||
|
|
||||||
|
const useStyles = makeStyles(() => ({
|
||||||
|
chip: {
|
||||||
|
'&:focus': {
|
||||||
|
border: `2px solid #000`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
selectedVersion: string;
|
selectedVersion: string;
|
||||||
|
|
@ -30,7 +49,15 @@ type Props = {
|
||||||
const profilesData: { [key: string]: Profile } = {};
|
const profilesData: { [key: string]: Profile } = {};
|
||||||
|
|
||||||
const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedProfile }) => {
|
const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedProfile }) => {
|
||||||
const [profile, setProfileData] = useState<Profile>();
|
const classes = useStyles();
|
||||||
|
const [profile, setProfile] = useState<Profile>();
|
||||||
|
const [showAddPackages, setShowAddPackages] = useState(false);
|
||||||
|
const [customPackages, setCustomPackages] = useState<Set<string>>(new Set());
|
||||||
|
const [customPackagesInputValue, setCustomPackagesInputValue] = useState<string>('');
|
||||||
|
const [showPackageExistsError, setShowPackageExistsError] = useState(false);
|
||||||
|
const [buildStatus, setBuildStatus] = useState<React.ReactNode>();
|
||||||
|
const [buildResponse, setBuildResponse] = useState<GetBuildResponse>();
|
||||||
|
const [buildError, setBuildError] = useState<string>();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const getHelpKey = (type: string) => {
|
const getHelpKey = (type: string) => {
|
||||||
|
|
@ -56,12 +83,18 @@ const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedPro
|
||||||
return 'other-help';
|
return 'other-help';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const preExistingPackages = (_profile = profile) =>
|
||||||
|
Array.from(
|
||||||
|
new Set([...(_profile?.default_packages || []), ...(_profile?.device_packages || [])])
|
||||||
|
);
|
||||||
|
|
||||||
const getProfileData = useCallback(async () => {
|
const getProfileData = useCallback(async () => {
|
||||||
let profileData = profilesData[selectedProfile.id];
|
let profileData = profilesData[selectedProfile.id];
|
||||||
|
|
||||||
if (!profileData) {
|
if (!profileData) {
|
||||||
const response = await Axios.get<Profile>(
|
const response = await axios.get<Profile>(
|
||||||
`${process.env.PUBLIC_URL}/data/${selectedVersion}/${selectedProfile.target}/${selectedProfile.id}.json`
|
`${process.env.PUBLIC_URL}/data/${selectedVersion}` +
|
||||||
|
`/${selectedProfile.target}/${selectedProfile.id}.json`
|
||||||
);
|
);
|
||||||
profileData = response.data;
|
profileData = response.data;
|
||||||
profilesData[selectedProfile.id] = profileData;
|
profilesData[selectedProfile.id] = profileData;
|
||||||
|
|
@ -73,7 +106,10 @@ const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedPro
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
getProfileData().then((_profileData) => {
|
getProfileData().then((_profileData) => {
|
||||||
if (mounted && !isEqual(profile, _profileData)) setProfileData(_profileData);
|
if (mounted && !isEqual(profile, _profileData)) {
|
||||||
|
setProfile(_profileData);
|
||||||
|
setCustomPackages(new Set(preExistingPackages(_profileData)));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -81,14 +117,64 @@ const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedPro
|
||||||
};
|
};
|
||||||
}, [selectedVersion, selectedProfile, getProfileData, profile]);
|
}, [selectedVersion, selectedProfile, getProfileData, profile]);
|
||||||
|
|
||||||
|
const toggleAddPackages = () => {
|
||||||
|
if (!profile) return;
|
||||||
|
setShowAddPackages(!showAddPackages);
|
||||||
|
setCustomPackages(new Set(preExistingPackages()));
|
||||||
|
};
|
||||||
|
|
||||||
|
const appendAddPackageInput = (
|
||||||
|
e?: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>
|
||||||
|
) => {
|
||||||
|
if (((e && e.key === 'Enter') || !e) && customPackagesInputValue) {
|
||||||
|
setCustomPackages((prev) => {
|
||||||
|
setShowPackageExistsError(false);
|
||||||
|
if (
|
||||||
|
!profile?.device_packages?.includes(customPackagesInputValue) &&
|
||||||
|
!profile?.default_packages?.includes(customPackagesInputValue)
|
||||||
|
) {
|
||||||
|
return new Set(prev.add(customPackagesInputValue));
|
||||||
|
}
|
||||||
|
setShowPackageExistsError(true);
|
||||||
|
return prev;
|
||||||
|
});
|
||||||
|
setCustomPackagesInputValue('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onBuildStatusChange = (status: string) => {
|
||||||
|
setBuildStatus(status);
|
||||||
|
};
|
||||||
|
|
||||||
if (!profile) return <CircularProgress />;
|
if (!profile) return <CircularProgress />;
|
||||||
|
|
||||||
const buildAt = new Date(profile.build_at);
|
const buildCustomImage = async () => {
|
||||||
|
setBuildStatus('Please wait...');
|
||||||
|
try {
|
||||||
|
const response = await asu.build(
|
||||||
|
Array.from(customPackages.values()),
|
||||||
|
profile.id,
|
||||||
|
profile.version_number,
|
||||||
|
onBuildStatusChange
|
||||||
|
);
|
||||||
|
setBuildResponse(response);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
setBuildError(e.response.data.message);
|
||||||
|
}
|
||||||
|
setBuildStatus(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildAt = DateTime.fromFormat(profile.build_at, 'yyyy-MM-dd TT').toLocaleString(
|
||||||
|
DateTime.DATETIME_MED
|
||||||
|
);
|
||||||
|
const hasAbilityToBuildCustomPackages = Object.keys(config).includes('asu_url');
|
||||||
|
const canBuild = !isEqual(Array.from(customPackages.values()), preExistingPackages());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box paddingTop={3} paddingBottom={2}>
|
<Box paddingTop={3} paddingBottom={2}>
|
||||||
<Typography variant="h6" component="h1" align="left">
|
<Typography variant="h5" component="h3" align="left">
|
||||||
{t('tr-version-build')}
|
{t('tr-version-build')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -150,7 +236,7 @@ const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedPro
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
<Box paddingTop={3} paddingBottom={2}>
|
<Box paddingTop={3} paddingBottom={2}>
|
||||||
<Typography variant="h6" component="h1" align="left">
|
<Typography variant="h5" component="h3" align="left">
|
||||||
{t('tr-downloads')}
|
{t('tr-downloads')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -188,6 +274,182 @@ const ProfileDetails: FunctionComponent<Props> = ({ selectedVersion, selectedPro
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
<Box paddingTop={3} paddingBottom={2}>
|
||||||
|
<Typography variant="h5" component="h3" align="left">
|
||||||
|
{t('Packages')}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
{profile.default_packages && profile.default_packages.length > 0 && (
|
||||||
|
<Box mb={2}>
|
||||||
|
<Typography variant="h6" align="left">
|
||||||
|
{t('Default Packages')}
|
||||||
|
</Typography>
|
||||||
|
{profile.default_packages?.join(', ')}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{profile.device_packages && profile.device_packages.length > 0 && (
|
||||||
|
<Box mb={2}>
|
||||||
|
<Typography variant="h6" align="left">
|
||||||
|
{t('Device Packages')}
|
||||||
|
</Typography>
|
||||||
|
{profile.device_packages.join(', ')}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{hasAbilityToBuildCustomPackages && (
|
||||||
|
<Box>
|
||||||
|
{!showAddPackages && (
|
||||||
|
<Button variant="outlined" size="small" onClick={toggleAddPackages}>
|
||||||
|
customize packages
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{showAddPackages && (
|
||||||
|
<>
|
||||||
|
<Typography variant="h6" align="left">
|
||||||
|
{t('Customize Packages')}
|
||||||
|
<Box display="inline-block" ml={2}>
|
||||||
|
<Link href="https://openwrt.org/packages/table/start" target="_blank">
|
||||||
|
<Typography variant="caption">find packages index on this page</Typography>
|
||||||
|
</Link>
|
||||||
|
</Box>
|
||||||
|
</Typography>
|
||||||
|
<br />
|
||||||
|
{Array.from(customPackages.values()).map((p) => {
|
||||||
|
const isDefaultPackage = profile.default_packages?.includes(p);
|
||||||
|
return (
|
||||||
|
<Box key={p} pr={1} pb={1} display="inline-block">
|
||||||
|
<Chip
|
||||||
|
size="small"
|
||||||
|
label={p}
|
||||||
|
color={isDefaultPackage ? 'default' : 'primary'}
|
||||||
|
className={classes.chip}
|
||||||
|
onDelete={
|
||||||
|
isDefaultPackage
|
||||||
|
? undefined
|
||||||
|
: () =>
|
||||||
|
setCustomPackages((prev) => {
|
||||||
|
const newSet = new Set(Array.from(prev.values()));
|
||||||
|
newSet.delete(p);
|
||||||
|
return newSet;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<br />
|
||||||
|
<FormControl size="small">
|
||||||
|
<InputLabel style={{ fontSize: '0.9em' }}>Custom Package Name</InputLabel>
|
||||||
|
<Input
|
||||||
|
value={customPackagesInputValue}
|
||||||
|
onChange={(e) => e && setCustomPackagesInputValue(e.currentTarget.value)}
|
||||||
|
onKeyUp={appendAddPackageInput}
|
||||||
|
endAdornment={
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<IconButton size="small" onClick={() => appendAddPackageInput()}>
|
||||||
|
<Add />
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
{showPackageExistsError && (
|
||||||
|
<Box pt={2}>
|
||||||
|
<Typography color="error" variant="caption" component="div">
|
||||||
|
This profile already includes this package. Please try a diffrent one
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Box mt={3}>
|
||||||
|
{!buildStatus && (
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
disabled={!canBuild}
|
||||||
|
onClick={buildCustomImage}
|
||||||
|
>
|
||||||
|
build customized image
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{buildStatus && (
|
||||||
|
<>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
alignContent="center"
|
||||||
|
direction="row"
|
||||||
|
alignItems="center"
|
||||||
|
spacing={2}
|
||||||
|
>
|
||||||
|
{typeof buildStatus === 'string' && (
|
||||||
|
<Grid item>
|
||||||
|
<CircularProgress />
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
<Grid item>{buildStatus}</Grid>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{buildError && <Typography color="error">{buildError}</Typography>}
|
||||||
|
{buildResponse && (
|
||||||
|
<Box mt={3}>
|
||||||
|
<Typography variant="h5">Built Image:</Typography>
|
||||||
|
<Table>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Build At</TableCell>
|
||||||
|
<TableCell id="title">
|
||||||
|
{DateTime.fromFormat(
|
||||||
|
buildResponse.build_at.substr(0, 25),
|
||||||
|
'ccc, dd MMM yyyy TT',
|
||||||
|
{
|
||||||
|
zone: buildResponse.build_at.substr(26),
|
||||||
|
setZone: true,
|
||||||
|
}
|
||||||
|
).toLocaleString(DateTime.DATETIME_MED)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Download link</TableCell>
|
||||||
|
<TableCell>Help Text</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{buildResponse.images?.map((i) => {
|
||||||
|
const downloadURL = `${config.image_url
|
||||||
|
.replace('{target}', profile.target)
|
||||||
|
.replace('{version}', profile.version_number)}/${i.name}`;
|
||||||
|
return (
|
||||||
|
<TableRow key={downloadURL + i.type}>
|
||||||
|
<TableCell>
|
||||||
|
<Link href={downloadURL} target="_blank" data-testid="download_link">
|
||||||
|
<Button endIcon={<CloudDownload />} variant="contained" color="primary">
|
||||||
|
{i.type}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Box p={1}>
|
||||||
|
<Typography>{t(`tr-${getHelpKey(i.type)}`)}</Typography>
|
||||||
|
<Typography variant="caption">sha256sum: {i.sha256}</Typography>
|
||||||
|
</Box>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,8 @@ const ProfileSearch: FunctionComponent<Props> = ({ selectedVersion, onProfileCha
|
||||||
toggleWorking(true);
|
toggleWorking(true);
|
||||||
|
|
||||||
if (!overview) {
|
if (!overview) {
|
||||||
const response = await Axios.get<Overview>(
|
const overviewPath = `${process.env.PUBLIC_URL}/data/${selectedVersion}/overview.json`;
|
||||||
`${process.env.PUBLIC_URL}/data/${selectedVersion}/overview.json`
|
const response = await Axios.get<Overview>(overviewPath);
|
||||||
);
|
|
||||||
overview = response.data;
|
overview = response.data;
|
||||||
overviewData[selectedVersion] = overview;
|
overviewData[selectedVersion] = overview;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
394
src/images/logo-white.svg
Normal file
|
|
@ -0,0 +1,394 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="529.16669mm"
|
||||||
|
height="162.23152mm"
|
||||||
|
viewBox="0 0 529.16669 162.23152"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1356"
|
||||||
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||||
|
sodipodi:docname="logo_full_white.svg">
|
||||||
|
<defs
|
||||||
|
id="defs1350">
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath594">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path592" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath622">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path620" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath646">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path644" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath670">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path668" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath690">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path688" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath710">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path708" />
|
||||||
|
</clipPath>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath730">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 792 V 612 H 0 Z"
|
||||||
|
id="path728" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.18520099"
|
||||||
|
inkscape:cx="514.14383"
|
||||||
|
inkscape:cy="22.780654"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1533"
|
||||||
|
inkscape:window-height="991"
|
||||||
|
inkscape:window-x="26"
|
||||||
|
inkscape:window-y="23"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata1353">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-139.40571,-167.43852)">
|
||||||
|
<g
|
||||||
|
id="g588"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g590"
|
||||||
|
clip-path="url(#clipPath594)">
|
||||||
|
<g
|
||||||
|
id="g596"
|
||||||
|
transform="translate(476.7686,191.1094)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 0,-5.89 -4.604,-10.521 -10.493,-10.521 -5.889,0 -10.493,4.631 -10.493,10.521 0,5.916 4.604,10.627 10.493,10.627 C -4.604,10.627 0,5.916 0,0 m -3.667,0 c 0,4.095 -2.998,7.2 -6.826,7.2 -3.828,0 -6.826,-3.105 -6.826,-7.2 0,-4.095 2.998,-7.121 6.826,-7.121 3.828,0 6.826,3.025 6.826,7.121"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path598" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g600"
|
||||||
|
transform="translate(492.605,187.6562)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 0,-4.203 -3.158,-7.067 -6.559,-7.067 -1.82,0 -3.292,0.536 -4.416,1.445 v -8.539 h -3.534 V 6.692 h 3.535 V 5.621 C -9.85,6.558 -8.378,7.093 -6.558,7.093 -3.158,7.093 0,4.203 0,0 m -3.427,0 c 0,2.462 -1.606,4.015 -3.747,4.015 -1.9,0 -3.801,-1.553 -3.801,-4.015 0,-2.463 1.901,-3.987 3.801,-3.987 2.142,-0.002 3.747,1.524 3.747,3.987"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path602" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g604"
|
||||||
|
transform="translate(507.4006,186.7197)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 h -10.172 c 0.348,-1.928 1.713,-3.105 3.346,-3.105 1.044,0 2.355,0.133 3.319,1.766 l 3.159,-0.669 c -1.178,-2.784 -3.56,-4.122 -6.479,-4.122 -3.774,0 -6.852,2.864 -6.852,7.067 0,4.202 3.078,7.092 6.906,7.092 3.56,0 6.638,-2.758 6.772,-6.826 z m -10.065,2.489 h 6.453 c -0.455,1.714 -1.74,2.463 -3.159,2.463 -1.34,0 -2.866,-0.803 -3.294,-2.463"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path606" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g608"
|
||||||
|
transform="translate(521.8176,189.1284)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 v -8.138 h -3.533 v 7.388 c 0,1.874 -1.071,3.132 -2.704,3.132 -2.007,0 -3.319,-1.338 -3.319,-4.604 v -5.916 h -3.533 V 5.22 h 3.532 V 4.015 c 1.044,1.044 2.436,1.606 4.203,1.606 C -2.141,5.621 0,3.319 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path610" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g612"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,560.99821,305.04931)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -2.837 L -7.816,13.197 -12.822,0 h -2.81 l -6.666,20.344 h 3.8 l 4.471,-13.438 5.113,13.438 h 2.168 l 5.113,-13.438 4.47,13.438 h 3.827 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path614" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g616"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g618"
|
||||||
|
clip-path="url(#clipPath622)">
|
||||||
|
<g
|
||||||
|
id="g624"
|
||||||
|
transform="translate(558.9077,194.4282)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 -0.187,-3.399 h -0.777 c -3.265,0 -4.765,-2.008 -4.765,-5.729 v -4.31 H -9.262 V -0.08 h 3.533 v -2.329 c 0.991,1.553 2.543,2.516 4.792,2.516 0.348,0 0.616,0 0.937,-0.107"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path626" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g628"
|
||||||
|
transform="translate(566.4221,185.916)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 0,-1.312 0.616,-2.035 1.687,-2.035 0.615,0 1.525,0.269 2.223,0.643 l 1.017,-2.944 c -1.392,-0.75 -2.355,-0.991 -3.479,-0.991 -3.186,0 -4.979,1.821 -4.979,5.06 v 5.809 h -2.865 v 2.89 h 2.864 v 4.845 l 3.533,1.071 V 8.432 H 5.168 V 5.542 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path630" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g632"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,383.96624,329.4222)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -0.795 L -1.542,2.05 -2.293,0 h -0.791 l -1.219,3.781 h 1.015 l 0.632,-2.039 0.791,2.039 h 0.647 L -0.432,1.742 0.205,3.781 H 1.22 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path634" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g636"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,400.41254,326.72602)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 0.781 V -0.821 H -1.737 V 0 h 0.781 V 2.135 H -1.737 V 2.96 H 0.781 V 2.135 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path638" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g640"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g642"
|
||||||
|
clip-path="url(#clipPath646)">
|
||||||
|
<g
|
||||||
|
id="g648"
|
||||||
|
transform="translate(500.3777,173.5708)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 -0.697,0.821 H -1.442 V 0 h -0.956 v 3.781 h 1.762 C 0.359,3.781 0.961,3.194 0.961,2.319 0.961,1.756 0.707,1.303 0.269,1.05 L 1.199,0 Z m -0.672,1.642 c 0.398,0 0.726,0.269 0.726,0.677 0,0.398 -0.328,0.643 -0.726,0.643 h -0.77 V 1.644 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path650" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g652"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,439.08752,329.4222)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -2.886 V 3.781 H -0.03 V 2.96 h -1.9 V 2.313 h 1.87 V 1.493 H -1.93 V 0.821 h 1.931 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path654" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g656"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,456.59196,329.4222)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 h -2.791 v 3.781 h 0.955 V 0.821 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path658" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g660"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,474.36148,329.4222)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -2.886 V 3.781 H -0.03 V 2.96 H -1.931 V 2.313 H -0.06 V 1.493 H -1.931 V 0.821 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path662" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g664"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g666"
|
||||||
|
clip-path="url(#clipPath670)">
|
||||||
|
<g
|
||||||
|
id="g672"
|
||||||
|
transform="translate(522.7458,176.3374)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 -0.935,-0.189 c -0.08,0.383 -0.339,0.492 -0.563,0.492 -0.223,0 -0.408,-0.114 -0.408,-0.324 0,-0.148 0.08,-0.243 0.244,-0.293 l 0.737,-0.234 c 0.621,-0.203 0.96,-0.492 0.96,-1.084 0,-0.851 -0.746,-1.21 -1.488,-1.21 -0.821,0 -1.488,0.433 -1.582,1.155 l 0.98,0.199 c 0.079,-0.373 0.303,-0.533 0.632,-0.533 0.279,0 0.448,0.129 0.448,0.329 0,0.149 -0.08,0.254 -0.289,0.308 l -0.701,0.204 c -0.573,0.164 -0.961,0.458 -0.961,1.07 0,0.771 0.606,1.194 1.433,1.194 C -0.707,1.084 -0.125,0.707 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path674" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g676"
|
||||||
|
transform="translate(527.7451,176.3374)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 -0.936,-0.189 c -0.079,0.383 -0.338,0.492 -0.562,0.492 -0.223,0 -0.408,-0.114 -0.408,-0.324 0,-0.148 0.08,-0.243 0.244,-0.293 l 0.737,-0.234 c 0.621,-0.203 0.96,-0.492 0.96,-1.084 0,-0.851 -0.746,-1.21 -1.488,-1.21 -0.821,0 -1.488,0.433 -1.582,1.155 l 0.98,0.199 c 0.079,-0.373 0.303,-0.533 0.632,-0.533 0.279,0 0.448,0.129 0.448,0.329 0,0.149 -0.08,0.254 -0.289,0.308 l -0.702,0.205 c -0.572,0.164 -0.96,0.458 -0.96,1.07 0,0.771 0.606,1.194 1.433,1.194 C -0.707,1.084 -0.125,0.707 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path678" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g680"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,531.81272,321.82281)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H 1.776 V -0.821 H 0 V -2.313 H -0.956 V 1.468 H 1.906 V 0.647 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path682" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g684"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g686"
|
||||||
|
clip-path="url(#clipPath690)">
|
||||||
|
<g
|
||||||
|
id="g692"
|
||||||
|
transform="translate(541.5046,173.5708)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 -0.696,0.821 H -1.443 V 0 h -0.955 v 3.781 h 1.761 C 0.358,3.781 0.96,3.194 0.96,2.319 0.96,1.756 0.707,1.303 0.269,1.05 L 1.199,0 Z m -0.672,1.642 c 0.399,0 0.727,0.269 0.727,0.677 0,0.398 -0.328,0.643 -0.727,0.643 H -1.443 V 1.644 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path694" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g696"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,574.18343,329.4222)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -2.886 V 3.781 H -0.03 V 2.96 H -1.931 V 2.313 H -0.06 V 1.493 H -1.931 V 0.821 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path698" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g700"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,591.99727,329.4222)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -2.886 V 3.781 H -0.03 V 2.96 h -1.9 V 2.313 h 1.871 V 1.493 H -1.93 V 0.821 h 1.931 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path702" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g704"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g706"
|
||||||
|
clip-path="url(#clipPath710)">
|
||||||
|
<g
|
||||||
|
id="g712"
|
||||||
|
transform="translate(557.21,177.3521)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 C 1.204,0 2,-0.757 2,-1.891 2,-3.024 1.205,-3.781 0,-3.781 H -1.687 V 0 Z m -0.01,-2.96 c 0.652,0 1.05,0.428 1.05,1.069 0,0.642 -0.398,1.07 -1.05,1.07 H -0.73 V -2.96 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path714" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g716"
|
||||||
|
transform="translate(565.2275,175.4565)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 0,-1.104 -0.906,-1.96 -2.02,-1.96 -1.115,0 -2.025,0.856 -2.025,1.96 0,1.104 0.905,1.965 2.025,1.965 C -0.901,1.965 0,1.1 0,0 m -0.96,0 c 0,0.622 -0.468,1.104 -1.061,1.104 -0.592,0 -1.06,-0.482 -1.06,-1.104 0,-0.622 0.468,-1.104 1.06,-1.104 0.593,0 1.061,0.477 1.061,1.104 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path718" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g720"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,653.10448,329.4222)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 H -0.935 V 1.796 L -2.05,0.262 H -2.339 L -3.453,1.794 V -0.001 H -4.389 V 3.78 h 0.613 L -2.194,1.556 -0.612,3.78 H 0 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path722" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g724"
|
||||||
|
transform="matrix(3.2848066,0,0,-3.2848066,-1224.4529,899.56869)">
|
||||||
|
<g
|
||||||
|
id="g726"
|
||||||
|
clip-path="url(#clipPath730)">
|
||||||
|
<g
|
||||||
|
id="g732"
|
||||||
|
transform="translate(574.8005,200.6079)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 -0.985,1.069 H -1.391 V 0 h -0.453 v 2.53 h 0.945 c 0.531,0 0.852,-0.303 0.852,-0.729 C -0.039,1.51 -0.215,1.247 -0.486,1.142 L 0.566,0 Z m -0.899,1.478 c 0.266,0 0.403,0.14 0.403,0.323 0,0.182 -0.139,0.318 -0.403,0.318 H -1.391 V 1.477 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path734" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g736"
|
||||||
|
transform="translate(573.9438,199.3813)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c -1.301,0 -2.355,1.054 -2.355,2.354 -10e-4,1.301 1.053,2.355 2.354,2.355 1.3,0.001 2.355,-1.053 2.355,-2.354 v 0 C 2.353,1.055 1.3,0.002 0,0 m 0,4.375 c -1.116,0 -2.021,-0.904 -2.021,-2.02 0,-1.116 0.905,-2.021 2.021,-2.021 1.116,0 2.021,0.905 2.021,2.021 C 2.02,3.471 1.116,4.375 0,4.376 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path738" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g740"
|
||||||
|
transform="translate(434.1643,199.1333)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c -1.705,0 -3.087,-1.382 -3.087,-3.087 0,-1.705 1.382,-3.086 3.087,-3.086 1.705,0 3.087,1.381 3.087,3.086 C 3.084,-1.383 1.704,-0.002 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path742" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g744"
|
||||||
|
transform="translate(415.2021,215.0088)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 3.213,-3.213 c 4.032,4.032 9.606,6.52 15.749,6.52 6.143,0 11.718,-2.489 15.75,-6.52 L 37.925,0 C 33.074,4.851 26.365,7.875 18.962,7.875 11.56,7.875 4.851,4.851 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path746" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g748"
|
||||||
|
transform="translate(420.998,209.2129)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 3.213,-3.213 c 2.551,2.552 6.079,4.127 9.952,4.127 3.873,0 7.404,-1.575 9.955,-4.127 L 26.333,0 C 22.963,3.371 18.301,5.482 13.167,5.482 8.033,5.482 3.371,3.372 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path750" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g752"
|
||||||
|
transform="translate(426.7622,203.4482)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 3.213,-3.213 c 2.315,2.31 6.063,2.31 8.379,0 L 14.804,0 C 12.842,1.963 10.178,3.063 7.402,3.055 4.536,3.055 1.92,1.89 0,0"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path754" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g756"
|
||||||
|
transform="translate(445.5669,204.3306)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 1.701,-2.331 2.709,-5.197 2.709,-8.284 0,-7.78 -6.331,-14.112 -14.112,-14.112 -7.78,0 -14.111,6.332 -14.111,14.112 0,3.087 1.008,5.953 2.709,8.284 l -3.244,3.245 c -2.52,-3.182 -4.001,-7.182 -4.001,-11.529 0,-10.269 8.379,-18.647 18.647,-18.647 10.269,0 18.648,8.378 18.648,18.647 0,4.347 -1.512,8.347 -4.001,11.529 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path758" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -1,14 +1,14 @@
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap');
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||||
monospace;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
|
/* eslint-disable max-len */
|
||||||
/* exported translations */
|
/* exported translations */
|
||||||
|
|
||||||
const translations = {
|
const translations = {
|
||||||
ca: {
|
ca: {
|
||||||
'tr-load': 'Descarregueu el microprogramari OpenWrt per al vostre dispositiu',
|
'tr-load': 'Descarregueu el microprogramari OpenWrt per al vostre dispositiu',
|
||||||
'tr-title': 'Selector de microprogramari OpenWrt',
|
'tr-title': 'Selector de microprogramari',
|
||||||
'tr-message':
|
'tr-message':
|
||||||
'Introduïu el nom o el model del vostre dispositiu i seleccioneu la versió estable (per defecte) o la darrera imatge compilada ("snapshot")',
|
'Introduïu el nom o el model del vostre dispositiu i seleccioneu la versió estable (per defecte) o la darrera imatge compilada ("snapshot")',
|
||||||
'tr-version-build': 'Compilació',
|
'tr-version-build': 'Compilació',
|
||||||
|
|
@ -35,7 +36,7 @@ const translations = {
|
||||||
'tr-server-link': 'Files',
|
'tr-server-link': 'Files',
|
||||||
'tr-notfound': 'No model found!',
|
'tr-notfound': 'No model found!',
|
||||||
'tr-load': 'Download OpenWrt Firmware for your Device',
|
'tr-load': 'Download OpenWrt Firmware for your Device',
|
||||||
'tr-title': 'OpenWrt Firmware Selector',
|
'tr-title': 'Firmware Selector',
|
||||||
'tr-message':
|
'tr-message':
|
||||||
'Type the name or model of your device, then select the recommended build or some other.',
|
'Type the name or model of your device, then select the recommended build or some other.',
|
||||||
'tr-version-build': 'About this build',
|
'tr-version-build': 'About this build',
|
||||||
|
|
@ -65,7 +66,7 @@ const translations = {
|
||||||
es: {
|
es: {
|
||||||
'tr-notfound': '¡Modelo no encontrado!',
|
'tr-notfound': '¡Modelo no encontrado!',
|
||||||
'tr-load': 'Descargue el firmware OpenWrt para su dispositivo',
|
'tr-load': 'Descargue el firmware OpenWrt para su dispositivo',
|
||||||
'tr-title': 'Selector de firmware OpenWrt',
|
'tr-title': 'Selector de firmware',
|
||||||
'tr-message':
|
'tr-message':
|
||||||
'Escriba el nombre o modelo de su dispositivo, luego seleccione la versión recomendada o alguna otra.',
|
'Escriba el nombre o modelo de su dispositivo, luego seleccione la versión recomendada o alguna otra.',
|
||||||
'tr-version-build': 'Acerca de esta compilación',
|
'tr-version-build': 'Acerca de esta compilación',
|
||||||
|
|
@ -95,7 +96,7 @@ const translations = {
|
||||||
},
|
},
|
||||||
no: {
|
no: {
|
||||||
'tr-load': 'Last ned OpenWrt fastvare for din enhet!',
|
'tr-load': 'Last ned OpenWrt fastvare for din enhet!',
|
||||||
'tr-title': 'OpenWrt fastvare utvelger',
|
'tr-title': 'fastvare utvelger',
|
||||||
'tr-message': 'Bruk feltene nedenfor for å laste ned fastvare til enheten din!',
|
'tr-message': 'Bruk feltene nedenfor for å laste ned fastvare til enheten din!',
|
||||||
'tr-version-build': 'Sammensetning',
|
'tr-version-build': 'Sammensetning',
|
||||||
'tr-custom-build': 'Tilpasset sammensetning',
|
'tr-custom-build': 'Tilpasset sammensetning',
|
||||||
|
|
@ -126,7 +127,7 @@ const translations = {
|
||||||
'tr-server-link': 'Dateien',
|
'tr-server-link': 'Dateien',
|
||||||
'tr-notfound': 'Kein Model gefunden!',
|
'tr-notfound': 'Kein Model gefunden!',
|
||||||
'tr-load': 'Lade die OpenWrt Firmware für dein Gerät!',
|
'tr-load': 'Lade die OpenWrt Firmware für dein Gerät!',
|
||||||
'tr-title': 'OpenWrt Firmware Selector',
|
'tr-title': 'Firmware Selector',
|
||||||
'tr-message': 'Bitte benutze die Eingabe um die passende Firmware zu finden!',
|
'tr-message': 'Bitte benutze die Eingabe um die passende Firmware zu finden!',
|
||||||
'tr-version-build': 'Release Build',
|
'tr-version-build': 'Release Build',
|
||||||
'tr-custom-build': 'Custom Build',
|
'tr-custom-build': 'Custom Build',
|
||||||
|
|
@ -185,7 +186,7 @@ const translations = {
|
||||||
},
|
},
|
||||||
it: {
|
it: {
|
||||||
'tr-load': 'Scarica il firmware OpenWrt per il tuo dispositivo!',
|
'tr-load': 'Scarica il firmware OpenWrt per il tuo dispositivo!',
|
||||||
'tr-title': 'OpenWrt Firmware Selector',
|
'tr-title': 'Firmware Selector',
|
||||||
'tr-message': 'Usa la casella sottostante per scaricare il firmware per il tuo dispositivo!',
|
'tr-message': 'Usa la casella sottostante per scaricare il firmware per il tuo dispositivo!',
|
||||||
'tr-version-build': 'Build',
|
'tr-version-build': 'Build',
|
||||||
'tr-custom-build': 'Custom Build',
|
'tr-custom-build': 'Custom Build',
|
||||||
|
|
@ -216,7 +217,7 @@ const translations = {
|
||||||
'tr-server-link': 'Pliki',
|
'tr-server-link': 'Pliki',
|
||||||
'tr-notfound': 'Nie znaleziono modelu!',
|
'tr-notfound': 'Nie znaleziono modelu!',
|
||||||
'tr-load': 'Pobieranie oprogramowania OpenWrt',
|
'tr-load': 'Pobieranie oprogramowania OpenWrt',
|
||||||
'tr-title': 'OpenWrt Firmware Selector',
|
'tr-title': 'Firmware Selector',
|
||||||
'tr-message':
|
'tr-message':
|
||||||
'Wprowadź nazwę lub model swojego urządzenia, a następnie wybierz wersję zalecaną lub inną.',
|
'Wprowadź nazwę lub model swojego urządzenia, a następnie wybierz wersję zalecaną lub inną.',
|
||||||
'tr-version-build': 'Informacje o obrazie',
|
'tr-version-build': 'Informacje o obrazie',
|
||||||
|
|
@ -246,7 +247,7 @@ const translations = {
|
||||||
},
|
},
|
||||||
tr: {
|
tr: {
|
||||||
'tr-load': 'Cihazınız için OpenWrt yazılımını indirin!',
|
'tr-load': 'Cihazınız için OpenWrt yazılımını indirin!',
|
||||||
'tr-title': 'OpenWrt Yazılım Seçicisi',
|
'tr-title': 'Yazılım Seçicisi',
|
||||||
'tr-message':
|
'tr-message':
|
||||||
'Cihazınızın adını/modelini girin, ardından Stabil sürümü(varsayılan) veya nightly "snapshot" imajini seçin.',
|
'Cihazınızın adını/modelini girin, ardından Stabil sürümü(varsayılan) veya nightly "snapshot" imajini seçin.',
|
||||||
'tr-version-build': 'Sürüm',
|
'tr-version-build': 'Sürüm',
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB |
11
src/react-app-env.d.ts
vendored
|
|
@ -1 +1,12 @@
|
||||||
/// <reference types="react-scripts" />
|
/// <reference types="react-scripts" />
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace NodeJS {
|
||||||
|
interface ProcessEnv {
|
||||||
|
NODE_ENV: 'development' | 'production';
|
||||||
|
PUBLIC_URL: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
|
|
|
||||||
34
src/types/asu.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
export interface GetBuildResponse {
|
||||||
|
arch_packages: string;
|
||||||
|
bin_dir: string;
|
||||||
|
build_at: string;
|
||||||
|
default_packages?: string[];
|
||||||
|
device_packages?: string[];
|
||||||
|
enqueued_at: string;
|
||||||
|
id: string;
|
||||||
|
image_prefix: string;
|
||||||
|
images?: ImagesEntity[];
|
||||||
|
manifest: Record<string, string>;
|
||||||
|
metadata_version: number;
|
||||||
|
request_hash: string;
|
||||||
|
stderr: string;
|
||||||
|
stdout: string;
|
||||||
|
supported_devices?: string[];
|
||||||
|
target: string;
|
||||||
|
titles?: TitlesEntity[];
|
||||||
|
version_code: string;
|
||||||
|
version_number: string;
|
||||||
|
status?: 'queued' | 'started';
|
||||||
|
queue_position?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImagesEntity {
|
||||||
|
filesystem: string;
|
||||||
|
name: string;
|
||||||
|
sha256: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TitlesEntity {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
17
src/utils/api.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import config from '../config';
|
||||||
|
import { GetBuildResponse } from '../types/asu';
|
||||||
|
|
||||||
|
const asu = {
|
||||||
|
buildNew: (packages: string[], profile: string, version: string) =>
|
||||||
|
axios.post<GetBuildResponse>(`${config.asu_url}/api/build`, {
|
||||||
|
version,
|
||||||
|
profile,
|
||||||
|
packages,
|
||||||
|
diff_packages: true,
|
||||||
|
}),
|
||||||
|
checkBuild: (request_hash: string) =>
|
||||||
|
axios.get<GetBuildResponse>(`${config.asu_url}/api/build/${request_hash}`),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default { asu };
|
||||||
31
src/utils/asu.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import api from './api';
|
||||||
|
import { sleep } from './common';
|
||||||
|
|
||||||
|
const build = async (
|
||||||
|
packages: string[],
|
||||||
|
profile: string,
|
||||||
|
version: string,
|
||||||
|
buildStatusCallback: (status: string) => void
|
||||||
|
) => {
|
||||||
|
const buildResponse = await api.asu.buildNew(packages, profile, version);
|
||||||
|
if (buildResponse.status === 202) {
|
||||||
|
buildStatusCallback(`#${buildResponse} in queue`);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const checkBuildResponse = await api.asu.checkBuild(buildResponse.data.request_hash);
|
||||||
|
if (checkBuildResponse.status === 200) {
|
||||||
|
return checkBuildResponse.data;
|
||||||
|
} else if (checkBuildResponse.status === 202) {
|
||||||
|
if (checkBuildResponse.data.status === 'queued') {
|
||||||
|
buildStatusCallback(`#${buildResponse} in queue`);
|
||||||
|
} else if (checkBuildResponse.data.status === 'started') {
|
||||||
|
buildStatusCallback(`Building the image`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await sleep(5000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default { build };
|
||||||
3
src/utils/common.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function sleep(ms: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||