diff --git a/lib/gui/app/components/drive-selector/drive-selector.tsx b/lib/gui/app/components/drive-selector/drive-selector.tsx
index 8bd3daef..7cb5196a 100644
--- a/lib/gui/app/components/drive-selector/drive-selector.tsx
+++ b/lib/gui/app/components/drive-selector/drive-selector.tsx
@@ -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 * as sourceDestination from 'etcher-sdk/build/source-destination/';
import * as React from 'react';
-import {
- Flex,
- ModalProps,
- Txt,
- Badge,
- Link,
- Table,
- TableColumn,
-} from 'rendition';
+import { Flex, ModalProps, Txt, Badge, Link, TableColumn } from 'rendition';
import styled from 'styled-components';
import {
@@ -43,7 +35,12 @@ import { getImage, isDriveSelected } from '../../models/selection-state';
import { store } from '../../models/store';
import { logEvent, logException } from '../../modules/analytics';
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 { SourceMetadata } from '../source-selector/source-selector';
@@ -75,74 +72,29 @@ function isDrivelistDrive(drive: Drive): drive is DrivelistDrive {
return typeof (drive as DrivelistDrive).size === 'number';
}
-const DrivesTable = styled(({ refFn, ...props }) => (
-
-
ref={refFn} {...props} />
-
+const DrivesTable = styled((props: GenericTableProps) => (
+ {...props} />
))`
- [data-display='table-head']
- > [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) {
- width: 38%;
- }
-
- &:nth-child(3) {
- width: 15%;
- }
-
- &:nth-child(4) {
- width: 15%;
- }
-
- &:nth-child(5) {
- 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-head'],
+ [data-display='table-body'] {
+ > [data-display='table-row'] > [data-display='table-cell'] {
+ &:nth-child(2) {
+ width: 38%;
}
- > [data-display='table-cell']:first-child {
- box-shadow: none;
+ &:nth-child(3) {
+ width: 15%;
+ }
+
+ &:nth-child(4) {
+ width: 15%;
+ }
+
+ &:nth-child(5) {
+ width: 32%;
}
}
}
-
- && [data-display='table-row'] > [data-display='table-cell'] {
- padding: 6px 8px;
- color: #2a506f;
- }
-
- input[type='checkbox'] + div {
- border-radius: ${({ multipleSelection }) =>
- multipleSelection ? '4px' : '50%'};
- }
`;
function badgeShadeFromStatus(status: string) {
@@ -453,95 +405,92 @@ export class DriveSelector extends React.Component<
}}
{...props}
>
-
- {!hasAvailableDrives() ? (
-
-
- {this.props.emptyListLabel}
-
- ) : (
-
- ) => {
- if (t !== null) {
- t.setRowSelection(selectedList);
- }
- }}
- multipleSelection={this.props.multipleSelection}
- columns={this.tableColumns}
- data={displayedDrives}
- disabledRows={disabledDrives}
- getRowClass={(row: Drive) =>
- isDrivelistDrive(row) && row.isSystem ? ['system'] : []
+ {!hasAvailableDrives() ? (
+
+
+ {this.props.emptyListLabel}
+
+ ) : (
+ <>
+ {
+ if (t !== null) {
+ t.setRowSelection(selectedList);
}
- rowKey="displayName"
- onCheck={(rows: Drive[]) => {
- const newSelection = rows.filter(isDrivelistDrive);
- if (this.props.multipleSelection) {
- this.setState({
- selectedList: newSelection,
- });
- return;
+ }}
+ multipleSelection={this.props.multipleSelection}
+ columns={this.tableColumns}
+ data={displayedDrives}
+ disabledRows={disabledDrives}
+ getRowClass={(row: Drive) =>
+ isDrivelistDrive(row) && row.isSystem ? ['system'] : []
+ }
+ rowKey="displayName"
+ onCheck={(rows: Drive[]) => {
+ const newSelection = rows.filter(isDrivelistDrive);
+ if (this.props.multipleSelection) {
+ this.setState({
+ selectedList: newSelection,
+ });
+ return;
+ }
+ this.setState({
+ selectedList: newSelection.slice(newSelection.length - 1),
+ });
+ }}
+ onRowClick={(row: Drive) => {
+ if (
+ !isDrivelistDrive(row) ||
+ this.driveShouldBeDisabled(row, image)
+ ) {
+ return;
+ }
+ if (this.props.multipleSelection) {
+ const newList = [...selectedList];
+ const selectedIndex = selectedList.findIndex(
+ (drive) => drive.device === row.device,
+ );
+ if (selectedIndex === -1) {
+ newList.push(row);
+ } else {
+ // Deselect if selected
+ newList.splice(selectedIndex, 1);
}
this.setState({
- selectedList: newSelection.slice(newSelection.length - 1),
+ selectedList: newList,
});
- }}
- onRowClick={(row: Drive) => {
- if (
- !isDrivelistDrive(row) ||
- this.driveShouldBeDisabled(row, image)
- ) {
- return;
- }
- if (this.props.multipleSelection) {
- const newList = [...selectedList];
- const selectedIndex = selectedList.findIndex(
- (drive) => drive.device === row.device,
- );
- if (selectedIndex === -1) {
- newList.push(row);
- } else {
- // Deselect if selected
- newList.splice(selectedIndex, 1);
- }
- this.setState({
- selectedList: newList,
- });
- return;
- }
- this.setState({
- selectedList: [row],
- });
- }}
- />
- {numberOfHiddenSystemDrives > 0 && (
- this.setState({ showSystemDrives: true })}
- >
-
-
- Show {numberOfHiddenSystemDrives} hidden
-
-
- )}
-
- )}
- {this.props.showWarnings && hasSystemDrives ? (
-
- Selecting your system drive is dangerous and will erase your
- drive!
-
- ) : null}
-
+ return;
+ }
+ this.setState({
+ selectedList: [row],
+ });
+ }}
+ />
+ {numberOfHiddenSystemDrives > 0 && (
+ this.setState({ showSystemDrives: true })}
+ >
+
+
+ Show {numberOfHiddenSystemDrives} hidden
+
+
+ )}
+ >
+ )}
+ {this.props.showWarnings && hasSystemDrives ? (
+
+ Selecting your system drive is dangerous and will erase your drive!
+
+ ) : null}
{missingDriversModal.drive !== undefined && (
{...props} />)`
&&& [data-display='table-head'],
@@ -99,7 +99,7 @@ const columns: Array> = [
field: 'message',
label: 'Error',
render: (message: string, { code }: FlashError) => {
- return message ? message : code;
+ return message ?? code;
},
},
];
@@ -152,7 +152,7 @@ export function FlashResults({
allFailed={allFailed}
color={allFailed || someFailed ? '#c6c8c9' : '#1ac135'}
/>
- {middleEllipsis(image, 16)}
+ {middleEllipsis(image, 24)}
Flash Complete!
diff --git a/lib/gui/app/styled-components.tsx b/lib/gui/app/styled-components.tsx
index 7ecd0487..2b5f8547 100644
--- a/lib/gui/app/styled-components.tsx
+++ b/lib/gui/app/styled-components.tsx
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+import * as _ from 'lodash';
import * as React from 'react';
import {
Alert as AlertBase,
@@ -23,27 +24,16 @@ import {
ButtonProps,
Modal as ModalBase,
Provider,
+ Table as BaseTable,
+ TableProps as BaseTableProps,
Txt,
- Theme as renditionTheme,
} from 'rendition';
import styled, { css } from 'styled-components';
import { colors, theme } from './theme';
-const defaultTheme = {
- ...renditionTheme,
- ...theme,
- layer: {
- extend: () => `
- > div:first-child {
- background-color: transparent;
- }
- `,
- },
-};
-
export const ThemedProvider = (props: any) => (
-
+
);
export const BaseButton = styled(Button)`
@@ -134,41 +124,27 @@ const modalFooterShadowCss = css`
background-attachment: local, local, scroll, scroll;
`;
-export const Modal = styled(({ style, ...props }) => {
+export const Modal = styled(({ style, children, ...props }) => {
return (
- `
- ${defaultTheme.layer.extend()}
-
- > div:last-child {
- top: 0;
- }
- `,
+
-
-
+
+ {...children}
+
+
);
})`
> div {
@@ -188,11 +164,8 @@ export const Modal = styled(({ style, ...props }) => {
> div:nth-child(2) {
height: 61%;
-
- > div:not(.system-drive-alert) {
- padding: 0 30px;
- ${modalFooterShadowCss}
- }
+ padding: 0 30px;
+ ${modalFooterShadowCss}
}
> div:last-child {
@@ -249,3 +222,82 @@ export const Alert = styled((props) => (
display: none;
}
`;
+
+export interface GenericTableProps extends BaseTableProps {
+ refFn: (t: BaseTable) => void;
+ multipleSelection: boolean;
+ showWarnings?: boolean;
+}
+
+const GenericTable: (
+ props: GenericTableProps,
+) => React.ReactElement> = ({
+ refFn,
+ ...props
+}: GenericTableProps) => (
+
+ ref={refFn} {...props} />
+
+);
+
+function StyledTable() {
+ return styled((props: GenericTableProps) => (
+ {...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 = (props: GenericTableProps) => {
+ const TypedStyledFunctional = StyledTable();
+ return ;
+};
diff --git a/lib/gui/app/theme.ts b/lib/gui/app/theme.ts
index 6c30e43e..d45b45c9 100644
--- a/lib/gui/app/theme.ts
+++ b/lib/gui/app/theme.ts
@@ -115,4 +115,11 @@ export const theme = _.merge({}, Theme, {
}
`,
},
+ layer: {
+ extend: () => `
+ > div:first-child {
+ background-color: transparent;
+ }
+ `,
+ },
});