mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-22 10:46:31 +00:00
Refactor UI without bootstrap & flexboxgrid
Change-type: patch Changelog-entry: Refactor UI without bootstrap & flexboxgrid Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
This commit is contained in:
parent
00f193541d
commit
3ca50a1e2d
@ -45,19 +45,13 @@ export class FeaturedProject extends React.Component<
|
|||||||
|
|
||||||
public async componentDidMount() {
|
public async componentDidMount() {
|
||||||
try {
|
try {
|
||||||
let endpoint =
|
const url = new URL(
|
||||||
(await settings.get('featuredProjectEndpoint')) ||
|
(await settings.get('featuredProjectEndpoint')) ||
|
||||||
'https://assets.balena.io/etcher-featured/index.html';
|
'https://assets.balena.io/etcher-featured/index.html',
|
||||||
const efpParams = {
|
);
|
||||||
borderRight: false,
|
url.searchParams.append('borderRight', 'false');
|
||||||
darkBackground: true,
|
url.searchParams.append('darkBackground', 'true');
|
||||||
};
|
this.setState({ endpoint: url.toString() });
|
||||||
let params = '?';
|
|
||||||
for (const [param, value] of Object.entries(efpParams)) {
|
|
||||||
params += `${param}=${value}&`;
|
|
||||||
}
|
|
||||||
endpoint += params;
|
|
||||||
this.setState({ endpoint });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
analytics.logException(error);
|
analytics.logException(error);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Flex } from 'rendition';
|
||||||
import { v4 as uuidV4 } from 'uuid';
|
import { v4 as uuidV4 } from 'uuid';
|
||||||
|
|
||||||
import * as flashState from '../../models/flash-state';
|
import * as flashState from '../../models/flash-state';
|
||||||
@ -56,50 +57,45 @@ function formattedErrors() {
|
|||||||
function FinishPage({ goToMain }: { goToMain: () => void }) {
|
function FinishPage({ goToMain }: { goToMain: () => void }) {
|
||||||
const results = flashState.getFlashResults().results || {};
|
const results = flashState.getFlashResults().results || {};
|
||||||
return (
|
return (
|
||||||
<div className="page-finish row around-xs">
|
<Flex flexDirection="column" width="100%" color="#fff">
|
||||||
<div className="col-xs">
|
<Flex height="160px" alignItems="center" justifyContent="center">
|
||||||
<div className="box center">
|
<FlashResults results={results} errors={formattedErrors()} />
|
||||||
<FlashResults results={results} errors={formattedErrors()} />
|
|
||||||
|
|
||||||
<FlashAnother
|
<FlashAnother
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
restart(goToMain);
|
restart(goToMain);
|
||||||
}}
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex
|
||||||
|
flexDirection="column"
|
||||||
|
height="320px"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Flex fontSize="28px" mt="40px">
|
||||||
|
Thanks for using
|
||||||
|
<EtcherSvg
|
||||||
|
width="165px"
|
||||||
|
style={{ margin: '0 10px', cursor: 'pointer' }}
|
||||||
|
onClick={() =>
|
||||||
|
openExternal('https://balena.io/etcher?ref=etcher_offline_banner')
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Flex>
|
||||||
|
<Flex mb="10px">
|
||||||
<div className="box center">
|
made with
|
||||||
<div className="fallback-banner">
|
<LoveSvg height="20px" style={{ margin: '0 10px' }} />
|
||||||
<div className="caption-big">
|
by
|
||||||
Thanks for using
|
<BalenaSvg
|
||||||
<span
|
height="20px"
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ margin: '0 10px', cursor: 'pointer' }}
|
||||||
onClick={() =>
|
onClick={() => openExternal('https://balena.io?ref=etcher_success')}
|
||||||
openExternal(
|
/>
|
||||||
'https://balena.io/etcher?ref=etcher_offline_banner',
|
</Flex>
|
||||||
)
|
</Flex>
|
||||||
}
|
</Flex>
|
||||||
>
|
|
||||||
<EtcherSvg width="165px" style={{ margin: '0 10px' }} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="caption-small fallback-footer">
|
|
||||||
made with
|
|
||||||
<LoveSvg height="20px" style={{ margin: '0 10px' }} />
|
|
||||||
by
|
|
||||||
<span
|
|
||||||
style={{ cursor: 'pointer' }}
|
|
||||||
onClick={() =>
|
|
||||||
openExternal('https://balena.io?ref=etcher_success')
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<BalenaSvg height="20px" style={{ margin: '0 10px' }} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,24 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import { BaseButton } from '../../styled-components';
|
import { BaseButton } from '../../styled-components';
|
||||||
|
|
||||||
const FlashAnotherButton = styled(BaseButton)`
|
|
||||||
position: absolute;
|
|
||||||
right: 152px;
|
|
||||||
top: 60px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export interface FlashAnotherProps {
|
export interface FlashAnotherProps {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FlashAnother = (props: FlashAnotherProps) => {
|
export const FlashAnother = (props: FlashAnotherProps) => {
|
||||||
return (
|
return (
|
||||||
<FlashAnotherButton primary onClick={props.onClick}>
|
<BaseButton primary onClick={props.onClick}>
|
||||||
Flash Another
|
Flash Another
|
||||||
</FlashAnotherButton>
|
</BaseButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import { faCheckCircle, faCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faCheckCircle, faCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import * as _ from 'lodash';
|
||||||
import outdent from 'outdent';
|
import outdent from 'outdent';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Txt, Flex } from 'rendition';
|
import { Txt, Flex } from 'rendition';
|
||||||
@ -39,17 +40,21 @@ export function FlashResults({
|
|||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
const allDevicesFailed = results.devices.successful === 0;
|
const allDevicesFailed = results.devices.successful === 0;
|
||||||
const effectiveSpeed = bytesToMegabytes(
|
const effectiveSpeed = _.round(
|
||||||
results.sourceMetadata.size /
|
bytesToMegabytes(
|
||||||
(results.bytesWritten / results.averageFlashingSpeed),
|
results.sourceMetadata.size /
|
||||||
).toFixed(1);
|
(results.bytesWritten / results.averageFlashingSpeed),
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
|
mr="80px"
|
||||||
|
height="90px"
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'relative',
|
||||||
left: '153px',
|
top: '25px',
|
||||||
top: '66px',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center">
|
||||||
@ -66,12 +71,10 @@ export function FlashResults({
|
|||||||
Flash Complete!
|
Flash Complete!
|
||||||
</Txt>
|
</Txt>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex flexDirection="column" mr="0" mb="0" ml="40px">
|
<Flex flexDirection="column" mr="0" mb="0" ml="40px" color="#7e8085">
|
||||||
{Object.keys(results.devices).map((type: 'failed' | 'successful') => {
|
{Object.entries(results.devices).map(([type, quantity]) => {
|
||||||
const quantity = results.devices[type];
|
|
||||||
return quantity ? (
|
return quantity ? (
|
||||||
<Flex
|
<Flex
|
||||||
color="#fff"
|
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
tooltip={type === 'failed' ? errors : undefined}
|
tooltip={type === 'failed' ? errors : undefined}
|
||||||
>
|
>
|
||||||
@ -86,7 +89,6 @@ export function FlashResults({
|
|||||||
})}
|
})}
|
||||||
{!allDevicesFailed && (
|
{!allDevicesFailed && (
|
||||||
<Txt
|
<Txt
|
||||||
color="#787c7f"
|
|
||||||
fontSize="10px"
|
fontSize="10px"
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
|
@ -52,10 +52,10 @@ export class ReducedFlashingInfos extends React.Component<
|
|||||||
height="21px"
|
height="21px"
|
||||||
contents={this.props.imageLogo}
|
contents={this.props.imageLogo}
|
||||||
fallback={ImageSvg}
|
fallback={ImageSvg}
|
||||||
style={{ marginRight: 9 }}
|
style={{ marginRight: '9px' }}
|
||||||
/>
|
/>
|
||||||
<Txt
|
<Txt
|
||||||
style={{ marginRight: 9 }}
|
style={{ marginRight: '9px' }}
|
||||||
tooltip={{ text: this.props.imageName, placement: 'right' }}
|
tooltip={{ text: this.props.imageName, placement: 'right' }}
|
||||||
>
|
>
|
||||||
{middleEllipsis(this.props.imageName, 16)}
|
{middleEllipsis(this.props.imageName, 16)}
|
||||||
@ -64,7 +64,7 @@ export class ReducedFlashingInfos extends React.Component<
|
|||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex>
|
<Flex>
|
||||||
<DriveSvg width="21px" height="21px" style={{ marginRight: 9 }} />
|
<DriveSvg width="21px" height="21px" style={{ marginRight: '9px' }} />
|
||||||
<Txt tooltip={{ text: this.props.driveLabel, placement: 'right' }}>
|
<Txt tooltip={{ text: this.props.driveLabel, placement: 'right' }}>
|
||||||
{middleEllipsis(this.props.driveTitle, 16)}
|
{middleEllipsis(this.props.driveTitle, 16)}
|
||||||
</Txt>
|
</Txt>
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 balena.io
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.page-finish {
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-finish .title,
|
|
||||||
.page-finish .title h3 {
|
|
||||||
color: $palette-theme-dark-foreground;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-finish .center {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-finish .box > div > button {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-finish webview {
|
|
||||||
width: 800px;
|
|
||||||
height: 300px;
|
|
||||||
position: absolute;
|
|
||||||
top: 80px;
|
|
||||||
left: 0;
|
|
||||||
z-index: 9001;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-finish .fallback-banner {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
color: white;
|
|
||||||
height: 320px;
|
|
||||||
width: 100vw;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
> * {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caption {
|
|
||||||
display: flex;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caption-big {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: bold;
|
|
||||||
position: absolute;
|
|
||||||
top: 75px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caption-small {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fallback-footer {
|
|
||||||
font-size: 12px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
max-height: 21px;
|
|
||||||
margin-bottom: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-footer {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
.footer-right {
|
|
||||||
color: #7e8085;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-right: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -161,17 +161,21 @@ export class MainPage extends React.Component<
|
|||||||
!this.state.isFlashing || !this.state.isWebviewShowing;
|
!this.state.isFlashing || !this.state.isWebviewShowing;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header
|
<Flex
|
||||||
id="app-header"
|
id="app-header"
|
||||||
|
justifyContent="center"
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
height: '50px',
|
||||||
padding: '13px 14px',
|
padding: '13px 14px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span
|
<EtcherSvg
|
||||||
|
width="123px"
|
||||||
|
height="22px"
|
||||||
style={{
|
style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
}}
|
}}
|
||||||
@ -179,11 +183,9 @@ export class MainPage extends React.Component<
|
|||||||
openExternal('https://www.balena.io/etcher?ref=etcher_footer')
|
openExternal('https://www.balena.io/etcher?ref=etcher_footer')
|
||||||
}
|
}
|
||||||
tabIndex={100}
|
tabIndex={100}
|
||||||
>
|
/>
|
||||||
<EtcherSvg width="123px" height="22px" />
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
<Flex
|
||||||
style={{
|
style={{
|
||||||
float: 'right',
|
float: 'right',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -208,8 +210,8 @@ export class MainPage extends React.Component<
|
|||||||
tabIndex={6}
|
tabIndex={6}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</span>
|
</Flex>
|
||||||
</header>
|
</Flex>
|
||||||
{this.state.hideSettings ? null : (
|
{this.state.hideSettings ? null : (
|
||||||
<SettingsModal
|
<SettingsModal
|
||||||
toggleModal={(value: boolean) => {
|
toggleModal={(value: boolean) => {
|
||||||
@ -320,15 +322,23 @@ export class MainPage extends React.Component<
|
|||||||
|
|
||||||
private renderSuccess() {
|
private renderSuccess() {
|
||||||
return (
|
return (
|
||||||
<div className="section-loader isFinish">
|
<Flex flexDirection="column" alignItems="center" height="100%">
|
||||||
<FinishPage
|
<FinishPage
|
||||||
goToMain={() => {
|
goToMain={() => {
|
||||||
flashState.resetState();
|
flashState.resetState();
|
||||||
this.setState({ current: 'main' });
|
this.setState({ current: 'main' });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SafeWebview src="https://www.balena.io/etcher/success-banner/" />
|
<SafeWebview
|
||||||
</div>
|
src="https://www.balena.io/etcher/success-banner/"
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '320px',
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 balena.io
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.disabled {
|
|
||||||
opacity: $disabled-opacity;
|
|
||||||
}
|
|
@ -14,17 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$icon-font-path: "../../../../node_modules/bootstrap-sass/assets/fonts/bootstrap/";
|
|
||||||
$font-size-base: 16px;
|
|
||||||
$cursor-disabled: initial;
|
|
||||||
$link-hover-decoration: none;
|
|
||||||
$btn-min-width: 170px;
|
|
||||||
$link-color: #ddd;
|
|
||||||
$disabled-opacity: 0.2;
|
$disabled-opacity: 0.2;
|
||||||
|
|
||||||
@import "./modules/theme";
|
@import "./modules/theme";
|
||||||
@import "../pages/main/styles/main";
|
|
||||||
@import "../pages/finish/styles/finish";
|
|
||||||
@import "./desktop";
|
@import "./desktop";
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@ -46,9 +38,11 @@ $disabled-opacity: 0.2;
|
|||||||
// Prevent white flash when running application
|
// Prevent white flash when running application
|
||||||
html {
|
html {
|
||||||
background-color: $palette-theme-dark-background;
|
background-color: $palette-theme-dark-background;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
margin: 0;
|
||||||
background-color: $palette-theme-dark-background;
|
background-color: $palette-theme-dark-background;
|
||||||
letter-spacing: 0.1px;
|
letter-spacing: 0.1px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -104,3 +98,7 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
opacity: $disabled-opacity;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user