Use drive-selector's table for flash errors table

Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
This commit is contained in:
Lorenzo Alberto Maria Ambrosi 2020-09-18 09:43:12 +02:00
parent e74dc9eb60
commit 31409c61ca
4 changed files with 219 additions and 211 deletions

View File

@ -18,15 +18,7 @@ import ExclamationTriangleSvg from '@fortawesome/fontawesome-free/svgs/solid/exc
import ChevronDownSvg from '@fortawesome/fontawesome-free/svgs/solid/chevron-down.svg'; import ChevronDownSvg from '@fortawesome/fontawesome-free/svgs/solid/chevron-down.svg';
import * as sourceDestination from 'etcher-sdk/build/source-destination/'; import * as sourceDestination from 'etcher-sdk/build/source-destination/';
import * as React from 'react'; import * as React from 'react';
import { import { Flex, ModalProps, Txt, Badge, Link, TableColumn } from 'rendition';
Flex,
ModalProps,
Txt,
Badge,
Link,
Table,
TableColumn,
} from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import { import {
@ -43,7 +35,12 @@ import { getImage, isDriveSelected } from '../../models/selection-state';
import { store } from '../../models/store'; import { store } from '../../models/store';
import { logEvent, logException } from '../../modules/analytics'; import { logEvent, logException } from '../../modules/analytics';
import { open as openExternal } from '../../os/open-external/services/open-external'; import { open as openExternal } from '../../os/open-external/services/open-external';
import { Alert, Modal, ScrollableFlex } from '../../styled-components'; import {
Alert,
GenericTableProps,
Modal,
Table,
} from '../../styled-components';
import DriveSVGIcon from '../../../assets/tgt.svg'; import DriveSVGIcon from '../../../assets/tgt.svg';
import { SourceMetadata } from '../source-selector/source-selector'; import { SourceMetadata } from '../source-selector/source-selector';
@ -75,27 +72,12 @@ function isDrivelistDrive(drive: Drive): drive is DrivelistDrive {
return typeof (drive as DrivelistDrive).size === 'number'; return typeof (drive as DrivelistDrive).size === 'number';
} }
const DrivesTable = styled(({ refFn, ...props }) => ( const DrivesTable = styled((props: GenericTableProps<Drive>) => (
<div> <Table<Drive> {...props} />
<Table<Drive> ref={refFn} {...props} />
</div>
))` ))`
[data-display='table-head'] [data-display='table-head'],
> [data-display='table-row'] [data-display='table-body'] {
> [data-display='table-cell'] { > [data-display='table-row'] > [data-display='table-cell'] {
position: sticky;
top: 0;
background-color: ${(props) => props.theme.colors.quartenary.light};
input[type='checkbox'] + div {
display: ${({ multipleSelection }) =>
multipleSelection ? 'flex' : 'none'};
}
&:first-child {
padding-left: 15px;
}
&:nth-child(2) { &:nth-child(2) {
width: 38%; width: 38%;
} }
@ -112,36 +94,6 @@ const DrivesTable = styled(({ refFn, ...props }) => (
width: 32%; width: 32%;
} }
} }
[data-display='table-body'] > [data-display='table-row'] {
> [data-display='table-cell']:first-child {
padding-left: 15px;
}
> [data-display='table-cell']:last-child {
padding-right: 0;
}
&[data-highlight='true'] {
&.system {
background-color: ${(props) =>
props.showWarnings ? '#fff5e6' : '#e8f5fc'};
}
> [data-display='table-cell']:first-child {
box-shadow: none;
}
}
}
&& [data-display='table-row'] > [data-display='table-cell'] {
padding: 6px 8px;
color: #2a506f;
}
input[type='checkbox'] + div {
border-radius: ${({ multipleSelection }) =>
multipleSelection ? '4px' : '50%'};
} }
`; `;
@ -453,7 +405,6 @@ export class DriveSelector extends React.Component<
}} }}
{...props} {...props}
> >
<Flex width="100%" height="90%">
{!hasAvailableDrives() ? ( {!hasAvailableDrives() ? (
<Flex <Flex
flexDirection="column" flexDirection="column"
@ -465,9 +416,9 @@ export class DriveSelector extends React.Component<
<b>{this.props.emptyListLabel}</b> <b>{this.props.emptyListLabel}</b>
</Flex> </Flex>
) : ( ) : (
<ScrollableFlex flexDirection="column" width="100%"> <>
<DrivesTable <DrivesTable
refFn={(t: Table<Drive>) => { refFn={(t) => {
if (t !== null) { if (t !== null) {
t.setRowSelection(selectedList); t.setRowSelection(selectedList);
} }
@ -533,15 +484,13 @@ export class DriveSelector extends React.Component<
</Flex> </Flex>
</Link> </Link>
)} )}
</ScrollableFlex> </>
)} )}
{this.props.showWarnings && hasSystemDrives ? ( {this.props.showWarnings && hasSystemDrives ? (
<Alert className="system-drive-alert" style={{ width: '67%' }}> <Alert className="system-drive-alert" style={{ width: '67%' }}>
Selecting your system drive is dangerous and will erase your Selecting your system drive is dangerous and will erase your drive!
drive!
</Alert> </Alert>
) : null} ) : null}
</Flex>
{missingDriversModal.drive !== undefined && ( {missingDriversModal.drive !== undefined && (
<Modal <Modal

View File

@ -20,7 +20,7 @@ import TimesCircleSvg from '@fortawesome/fontawesome-free/svgs/solid/times-circl
import * as _ from 'lodash'; import * as _ from 'lodash';
import outdent from 'outdent'; import outdent from 'outdent';
import * as React from 'react'; import * as React from 'react';
import { Flex, FlexProps, Link, Table, TableColumn, Txt } from 'rendition'; import { Flex, FlexProps, Link, TableColumn, Txt } from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import { progress } from '../../../../shared/messages'; import { progress } from '../../../../shared/messages';
@ -31,7 +31,7 @@ import { getDrives } from '../../models/available-drives';
import { resetState } from '../../models/flash-state'; import { resetState } from '../../models/flash-state';
import * as selection from '../../models/selection-state'; import * as selection from '../../models/selection-state';
import { middleEllipsis } from '../../utils/middle-ellipsis'; import { middleEllipsis } from '../../utils/middle-ellipsis';
import { Modal } from '../../styled-components'; import { Modal, Table } from '../../styled-components';
const ErrorsTable = styled((props) => <Table<FlashError> {...props} />)` const ErrorsTable = styled((props) => <Table<FlashError> {...props} />)`
&&& [data-display='table-head'], &&& [data-display='table-head'],
@ -99,7 +99,7 @@ const columns: Array<TableColumn<FlashError>> = [
field: 'message', field: 'message',
label: 'Error', label: 'Error',
render: (message: string, { code }: FlashError) => { render: (message: string, { code }: FlashError) => {
return message ? message : code; return message ?? code;
}, },
}, },
]; ];
@ -152,7 +152,7 @@ export function FlashResults({
allFailed={allFailed} allFailed={allFailed}
color={allFailed || someFailed ? '#c6c8c9' : '#1ac135'} color={allFailed || someFailed ? '#c6c8c9' : '#1ac135'}
/> />
<Txt>{middleEllipsis(image, 16)}</Txt> <Txt>{middleEllipsis(image, 24)}</Txt>
</Flex> </Flex>
<Txt fontSize={24} color="#fff" mb="17px"> <Txt fontSize={24} color="#fff" mb="17px">
Flash Complete! Flash Complete!

View File

@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import { import {
Alert as AlertBase, Alert as AlertBase,
@ -23,27 +24,16 @@ import {
ButtonProps, ButtonProps,
Modal as ModalBase, Modal as ModalBase,
Provider, Provider,
Table as BaseTable,
TableProps as BaseTableProps,
Txt, Txt,
Theme as renditionTheme,
} from 'rendition'; } from 'rendition';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import { colors, theme } from './theme'; import { colors, theme } from './theme';
const defaultTheme = {
...renditionTheme,
...theme,
layer: {
extend: () => `
> div:first-child {
background-color: transparent;
}
`,
},
};
export const ThemedProvider = (props: any) => ( export const ThemedProvider = (props: any) => (
<Provider theme={defaultTheme} {...props}></Provider> <Provider theme={theme} {...props}></Provider>
); );
export const BaseButton = styled(Button)` export const BaseButton = styled(Button)`
@ -134,25 +124,8 @@ const modalFooterShadowCss = css`
background-attachment: local, local, scroll, scroll; background-attachment: local, local, scroll, scroll;
`; `;
export const Modal = styled(({ style, ...props }) => { export const Modal = styled(({ style, children, ...props }) => {
return ( return (
<Provider
theme={{
...defaultTheme,
header: {
height: '50px',
},
layer: {
extend: () => `
${defaultTheme.layer.extend()}
> div:last-child {
top: 0;
}
`,
},
}}
>
<ModalBase <ModalBase
position="top" position="top"
width="97vw" width="97vw"
@ -167,8 +140,11 @@ export const Modal = styled(({ style, ...props }) => {
...style, ...style,
}} }}
{...props} {...props}
/> >
</Provider> <ScrollableFlex flexDirection="column" width="100%" height="90%">
{...children}
</ScrollableFlex>
</ModalBase>
); );
})` })`
> div { > div {
@ -188,12 +164,9 @@ export const Modal = styled(({ style, ...props }) => {
> div:nth-child(2) { > div:nth-child(2) {
height: 61%; height: 61%;
> div:not(.system-drive-alert) {
padding: 0 30px; padding: 0 30px;
${modalFooterShadowCss} ${modalFooterShadowCss}
} }
}
> div:last-child { > div:last-child {
margin: 0; margin: 0;
@ -249,3 +222,82 @@ export const Alert = styled((props) => (
display: none; display: none;
} }
`; `;
export interface GenericTableProps<T> extends BaseTableProps<T> {
refFn: (t: BaseTable<T>) => void;
multipleSelection: boolean;
showWarnings?: boolean;
}
const GenericTable: <T>(
props: GenericTableProps<T>,
) => React.ReactElement<GenericTableProps<T>> = <T extends {}>({
refFn,
...props
}: GenericTableProps<T>) => (
<div>
<BaseTable<T> ref={refFn} {...props} />
</div>
);
function StyledTable<T>() {
return styled((props: GenericTableProps<T>) => (
<GenericTable<T> {...props} />
))`
[data-display='table-head']
> [data-display='table-row']
> [data-display='table-cell'] {
position: sticky;
background-color: #f8f9fd;
top: 0;
z-index: 1;
input[type='checkbox'] + div {
display: ${(props) => (props.multipleSelection ? 'flex' : 'none')};
}
}
[data-display='table-head'] > [data-display='table-row'],
[data-display='table-body'] > [data-display='table-row'] {
> [data-display='table-cell']:first-child {
padding-left: 15px;
width: 6%;
}
> [data-display='table-cell']:last-child {
padding-right: 0;
}
}
[data-display='table-body'] > [data-display='table-row'] {
&:nth-of-type(2n) {
background: transparent;
}
&[data-highlight='true'] {
&.system {
background-color: ${(props) =>
props.showWarnings ? '#fff5e6' : '#e8f5fc'};
}
> [data-display='table-cell']:first-child {
box-shadow: none;
}
}
}
&& [data-display='table-row'] > [data-display='table-cell'] {
padding: 6px 8px;
color: #2a506f;
}
input[type='checkbox'] + div {
border-radius: ${(props) => (props.multipleSelection ? '4px' : '50%')};
}
`;
}
export const Table = <T extends {}>(props: GenericTableProps<T>) => {
const TypedStyledFunctional = StyledTable<T>();
return <TypedStyledFunctional {...props} />;
};

View File

@ -115,4 +115,11 @@ export const theme = _.merge({}, Theme, {
} }
`, `,
}, },
layer: {
extend: () => `
> div:first-child {
background-color: transparent;
}
`,
},
}); });