Decouple RelinkDialog from NetworkStatusDialog

This commit is contained in:
Josh Perez 2020-04-16 15:20:52 -04:00 committed by GitHub
parent 0970c73310
commit 4dc7631851
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 123 additions and 37 deletions

View file

@ -37,6 +37,7 @@ export interface PropsType {
renderMainHeader: () => JSX.Element; renderMainHeader: () => JSX.Element;
renderMessageSearchResult: (id: string) => JSX.Element; renderMessageSearchResult: (id: string) => JSX.Element;
renderNetworkStatus: () => JSX.Element; renderNetworkStatus: () => JSX.Element;
renderRelinkDialog: () => JSX.Element;
renderUpdateDialog: () => JSX.Element; renderUpdateDialog: () => JSX.Element;
} }
@ -394,6 +395,7 @@ export class LeftPane extends React.Component<PropsType> {
renderExpiredBuildDialog, renderExpiredBuildDialog,
renderMainHeader, renderMainHeader,
renderNetworkStatus, renderNetworkStatus,
renderRelinkDialog,
renderUpdateDialog, renderUpdateDialog,
showArchived, showArchived,
} = this.props; } = this.props;
@ -408,6 +410,7 @@ export class LeftPane extends React.Component<PropsType> {
{renderExpiredBuildDialog()} {renderExpiredBuildDialog()}
{renderNetworkStatus()} {renderNetworkStatus()}
{renderUpdateDialog()} {renderUpdateDialog()}
{renderRelinkDialog()}
{this.renderList()} {this.renderList()}
</div> </div>
)} )}

View file

@ -16,9 +16,7 @@ const defaultProps = {
hasNetworkDialog: true, hasNetworkDialog: true,
i18n, i18n,
isOnline: true, isOnline: true,
isRegistrationDone: true,
socketStatus: 0, socketStatus: 0,
relinkDevice: action('relink-device'),
manualReconnect: action('manual-reconnect'), manualReconnect: action('manual-reconnect'),
withinConnectingGracePeriod: false, withinConnectingGracePeriod: false,
}; };
@ -42,19 +40,6 @@ const permutations = [
socketStatus: 3, socketStatus: 3,
}, },
}, },
{
title: 'Unlinked (online)',
props: {
isRegistrationDone: false,
},
},
{
title: 'Unlinked (offline)',
props: {
isOnline: false,
isRegistrationDone: false,
},
},
{ {
title: 'Offline', title: 'Offline',
props: { props: {
@ -67,7 +52,6 @@ storiesOf('Components/NetworkStatus', module)
.add('Knobs Playground', () => { .add('Knobs Playground', () => {
const hasNetworkDialog = boolean('hasNetworkDialog', true); const hasNetworkDialog = boolean('hasNetworkDialog', true);
const isOnline = boolean('isOnline', true); const isOnline = boolean('isOnline', true);
const isRegistrationDone = boolean('isRegistrationDone', true);
const socketStatus = select( const socketStatus = select(
'socketStatus', 'socketStatus',
{ {
@ -84,7 +68,6 @@ storiesOf('Components/NetworkStatus', module)
{...defaultProps} {...defaultProps}
hasNetworkDialog={hasNetworkDialog} hasNetworkDialog={hasNetworkDialog}
isOnline={isOnline} isOnline={isOnline}
isRegistrationDone={isRegistrationDone}
socketStatus={socketStatus} socketStatus={socketStatus}
/> />
); );

View file

@ -8,8 +8,6 @@ const FIVE_SECONDS = 5 * 1000;
export interface PropsType extends NetworkStateType { export interface PropsType extends NetworkStateType {
hasNetworkDialog: boolean; hasNetworkDialog: boolean;
i18n: LocalizerType; i18n: LocalizerType;
isRegistrationDone: boolean;
relinkDevice: () => void;
manualReconnect: () => void; manualReconnect: () => void;
} }
@ -39,9 +37,7 @@ export const NetworkStatus = ({
hasNetworkDialog, hasNetworkDialog,
i18n, i18n,
isOnline, isOnline,
isRegistrationDone,
socketStatus, socketStatus,
relinkDevice,
manualReconnect, manualReconnect,
}: PropsType): JSX.Element | null => { }: PropsType): JSX.Element | null => {
if (!hasNetworkDialog) { if (!hasNetworkDialog) {
@ -76,17 +72,7 @@ export const NetworkStatus = ({
</div> </div>
); );
if (!isRegistrationDone) { if (isConnecting) {
return renderDialog({
renderActionableButton: (): JSX.Element => (
<div className="module-left-pane-dialog__actions">
<button onClick={relinkDevice}>{i18n('relink')}</button>
</div>
),
subtext: i18n('unlinkedWarning'),
title: i18n('unlinked'),
});
} else if (isConnecting) {
return renderDialog({ return renderDialog({
subtext: i18n('connectingHangOn'), subtext: i18n('connectingHangOn'),
title: i18n('connecting'), title: i18n('connecting'),

View file

@ -0,0 +1,58 @@
import * as React from 'react';
import { RelinkDialog } from './RelinkDialog';
// @ts-ignore
import { setup as setupI18n } from '../../js/modules/i18n';
// @ts-ignore
import enMessages from '../../_locales/en/messages.json';
import { storiesOf } from '@storybook/react';
import { boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
const i18n = setupI18n('en', enMessages);
const defaultProps = {
hasNetworkDialog: false,
i18n,
isRegistrationDone: true,
relinkDevice: action('relink-device'),
};
const permutations = [
{
title: 'Unlinked (online)',
props: {
isRegistrationDone: false,
},
},
{
title: 'Unlinked (offline)',
props: {
hasNetworkDialog: true,
isRegistrationDone: false,
},
},
];
storiesOf('Components/RelinkDialog', module)
.add('Knobs Playground', () => {
const hasNetworkDialog = boolean('hasNetworkDialog', false);
const isRegistrationDone = boolean('isRegistrationDone', false);
return (
<RelinkDialog
{...defaultProps}
hasNetworkDialog={hasNetworkDialog}
isRegistrationDone={isRegistrationDone}
/>
);
})
.add('Iterations', () => {
return permutations.map(({ props, title }) => (
<>
<h3>{title}</h3>
<RelinkDialog {...defaultProps} {...props} />
</>
));
});

View file

@ -0,0 +1,33 @@
import React from 'react';
import { LocalizerType } from '../types/Util';
export interface PropsType {
hasNetworkDialog: boolean;
i18n: LocalizerType;
isRegistrationDone: boolean;
relinkDevice: () => void;
}
export const RelinkDialog = ({
hasNetworkDialog,
i18n,
isRegistrationDone,
relinkDevice,
}: PropsType): JSX.Element | null => {
if (hasNetworkDialog || isRegistrationDone) {
return null;
}
return (
<div className="module-left-pane-dialog module-left-pane-dialog--warning">
<div className="module-left-pane-dialog__message">
<h3>{i18n('unlinked')}</h3>
<span>{i18n('unlinkedWarning')}</span>
</div>
<div className="module-left-pane-dialog__actions">
<button onClick={relinkDevice}>{i18n('relink')}</button>
</div>
</div>
);
};

View file

@ -16,6 +16,7 @@ import { SmartExpiredBuildDialog } from './ExpiredBuildDialog';
import { SmartMainHeader } from './MainHeader'; import { SmartMainHeader } from './MainHeader';
import { SmartMessageSearchResult } from './MessageSearchResult'; import { SmartMessageSearchResult } from './MessageSearchResult';
import { SmartNetworkStatus } from './NetworkStatus'; import { SmartNetworkStatus } from './NetworkStatus';
import { SmartRelinkDialog } from './RelinkDialog';
import { SmartUpdateDialog } from './UpdateDialog'; import { SmartUpdateDialog } from './UpdateDialog';
// Workaround: A react component's required properties are filtering up through connect() // Workaround: A react component's required properties are filtering up through connect()
@ -25,6 +26,7 @@ const FilteredSmartMessageSearchResult = SmartMessageSearchResult as any;
const FilteredSmartNetworkStatus = SmartNetworkStatus as any; const FilteredSmartNetworkStatus = SmartNetworkStatus as any;
const FilteredSmartUpdateDialog = SmartUpdateDialog as any; const FilteredSmartUpdateDialog = SmartUpdateDialog as any;
const FilteredSmartExpiredBuildDialog = SmartExpiredBuildDialog as any; const FilteredSmartExpiredBuildDialog = SmartExpiredBuildDialog as any;
const FilteredSmartRelinkDialog = SmartRelinkDialog as any;
function renderExpiredBuildDialog(): JSX.Element { function renderExpiredBuildDialog(): JSX.Element {
return <FilteredSmartExpiredBuildDialog />; return <FilteredSmartExpiredBuildDialog />;
@ -35,12 +37,15 @@ function renderMainHeader(): JSX.Element {
function renderMessageSearchResult(id: string): JSX.Element { function renderMessageSearchResult(id: string): JSX.Element {
return <FilteredSmartMessageSearchResult id={id} />; return <FilteredSmartMessageSearchResult id={id} />;
} }
function renderUpdateDialog(): JSX.Element {
return <FilteredSmartUpdateDialog />;
}
function renderNetworkStatus(): JSX.Element { function renderNetworkStatus(): JSX.Element {
return <FilteredSmartNetworkStatus />; return <FilteredSmartNetworkStatus />;
} }
function renderRelinkDialog(): JSX.Element {
return <FilteredSmartRelinkDialog />;
}
function renderUpdateDialog(): JSX.Element {
return <FilteredSmartUpdateDialog />;
}
const mapStateToProps = (state: StateType) => { const mapStateToProps = (state: StateType) => {
const showSearch = isSearching(state); const showSearch = isSearching(state);
@ -59,6 +64,7 @@ const mapStateToProps = (state: StateType) => {
renderMainHeader, renderMainHeader,
renderMessageSearchResult, renderMessageSearchResult,
renderNetworkStatus, renderNetworkStatus,
renderRelinkDialog,
renderUpdateDialog, renderUpdateDialog,
}; };
}; };

View file

@ -4,14 +4,12 @@ import { NetworkStatus } from '../../components/NetworkStatus';
import { StateType } from '../reducer'; import { StateType } from '../reducer';
import { getIntl } from '../selectors/user'; import { getIntl } from '../selectors/user';
import { hasNetworkDialog } from '../selectors/network'; import { hasNetworkDialog } from '../selectors/network';
import { isDone } from '../../util/registration';
const mapStateToProps = (state: StateType) => { const mapStateToProps = (state: StateType) => {
return { return {
...state.network, ...state.network,
hasNetworkDialog: hasNetworkDialog(state), hasNetworkDialog: hasNetworkDialog(state),
i18n: getIntl(state), i18n: getIntl(state),
isRegistrationDone: isDone(),
}; };
}; };

View file

@ -0,0 +1,19 @@
import { connect } from 'react-redux';
import { mapDispatchToProps } from '../actions';
import { RelinkDialog } from '../../components/RelinkDialog';
import { StateType } from '../reducer';
import { getIntl } from '../selectors/user';
import { hasNetworkDialog } from '../selectors/network';
import { isDone } from '../../util/registration';
const mapStateToProps = (state: StateType) => {
return {
hasNetworkDialog: hasNetworkDialog(state),
i18n: getIntl(state),
isRegistrationDone: isDone(),
};
};
const smart = connect(mapStateToProps, mapDispatchToProps);
export const SmartRelinkDialog = smart(RelinkDialog);