Skip to content

Commit

Permalink
Fix: responsive views (#496)
Browse files Browse the repository at this point in the history
* add app sections to make app.tsx more readable

* treat screens with width less than 992px as mobile screens
At point 992 is where the screen breaks
  • Loading branch information
thewahome committed May 5, 2020
1 parent 53a0a94 commit ed0bcc8
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 143 deletions.
173 changes: 35 additions & 138 deletions src/app/views/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {
IconButton, IStackTokens, ITheme, Label, MessageBar,
MessageBarType, Stack, styled
IStackTokens, ITheme, styled
} from 'office-ui-fabric-react';
import React, { Component } from 'react';
import { FormattedMessage, InjectedIntl, injectIntl } from 'react-intl';
import { InjectedIntl, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import { loadGETheme } from '../../themes';
import { ThemeContext } from '../../themes/theme-context';
import { LoginType, Mode } from '../../types/enums';
import { Mode } from '../../types/enums';
import { IInitMessage, IQuery, IThemeChangedMessage } from '../../types/query-runner';
import { ISharedQueryParams } from '../../types/share-query';
import { ISidebarProps } from '../../types/sidebar';
Expand All @@ -22,11 +21,14 @@ import { toggleSidebar } from '../services/actions/toggle-sidebar-action-creator
import { getLoginType, logIn } from '../services/graph-client/msal-service';
import { parseSampleUrl } from '../utils/sample-url-generation';
import { substituteTokens } from '../utils/token-helpers';
import { appTitleDisplayOnFullScreen, appTitleDisplayOnMobileScreen } from './app-sections/AppTitle';
import { headerMessaging } from './app-sections/HeaderMessaging';
import { statusMessages } from './app-sections/StatusMessages';
import { termsOfUseMessage } from './app-sections/TermsOfUseMessage';
import { appStyles } from './App.styles';
import { Authentication } from './authentication';
import { classNames } from './classnames';
import { createShareLink } from './common/share';
import { Banner } from './opt-in-out-banner';
import { QueryResponse } from './query-response';
import { QueryRunner } from './query-runner';
import { parse } from './query-runner/util/iframe-message-parser';
Expand Down Expand Up @@ -65,7 +67,7 @@ interface IAppState {

class App extends Component<IAppProps, IAppState> {

private mediaQueryList = window.matchMedia('(max-width: 767px)');
private mediaQueryList = window.matchMedia('(max-width: 992px)');

constructor(props: IAppProps) {
super(props);
Expand Down Expand Up @@ -308,7 +310,6 @@ class App extends Component<IAppProps, IAppState> {
</div>;
}


private closeDialog = (): void => {
this.setState({ hideDialog: true });
};
Expand Down Expand Up @@ -349,159 +350,55 @@ class App extends Component<IAppProps, IAppState> {
layout = `col-xs-12 col-sm-12 col-lg-11 col-md-11 ${classes.layoutExtra}`;
}

if (mobileScreen) {
sidebarWidth = layout = 'col-xs-12 col-sm-12';
}




return (
// @ts-ignore
<ThemeContext.Provider value={this.props.appTheme}>
<main className={`container-fluid ${classes.app}`}>
<div className='row'>
{graphExplorerMode === Mode.Complete && (
<div className={sidebarWidth}>
{mobileScreen && <Stack horizontal={true} disableShrink={true} tokens={stackTokens}>
<>
<IconButton
iconProps={{ iconName: 'GlobalNavButton' }}
className={classes.sidebarToggle}
title='Remove sidebar'
ariaLabel='Remove sidebar'
onClick={this.toggleSidebar}
/>
<div style={{ padding: 10 }}>
<Label className={classes.graphExplorerLabel}>
Graph Explorer
</Label>
<Banner optOut={this.optOut} />
</div>
<span style={{
position: 'absolute',
marginLeft: '70%',
marginTop: '2.5%'
}}>

<Authentication />
</span>
</>
</Stack>
}
{mobileScreen && appTitleDisplayOnMobileScreen(
stackTokens,
classes,
this.toggleSidebar,
this.optOut)}

{!mobileScreen && appTitleDisplayOnFullScreen(
classes,
minimised,
classes,
this.toggleSidebar,
)}

<hr className={classes.separator} />
{!mobileScreen &&
<div style={{ display: 'flex' }}>
<IconButton
iconProps={{ iconName: 'GlobalNavButton' }}
className={classes.sidebarToggle}
title='Minimise sidebar'
ariaLabel='Minimise sidebar'
onClick={this.toggleSidebar}
/>
<div className={classes.graphExplorerLabelContainer}>

{!minimised &&
<>
<Label className={classes.graphExplorerLabel}>
Graph Explorer
</Label>
<span className={classes.previewButton} >
<Banner optOut={this.optOut} />
</span>
</>
}

</div>
</div>
<>
{this.displayAuthenticationSection(minimised)}
<hr className={classes.separator} />
</>
}


<hr className={classes.separator} />
{!mobileScreen && <>
{this.displayAuthenticationSection(minimised)}
<hr className={classes.separator} /></>}

{showSidebar && <>
<Sidebar sampleHeaderText={sampleHeaderText} historyHeaderText={historyHeaderText} />
</>}
</div>
)}
<div className={layout}>
{graphExplorerMode === Mode.TryIt && (
<div style={{ marginBottom: 8 }}>
{loginType === LoginType.Popup && <>
<MessageBar
messageBarType={MessageBarType.info}
isMultiline={true}
>
<p>
<FormattedMessage id='To try the full features' />,
<a className={classes.links}
tabIndex={0}
href={query} target='_blank'>
<FormattedMessage id='full Graph Explorer' />.
</a>
</p>
<p>
<FormattedMessage id='running the query' />.
</p>
</MessageBar>

<Authentication />
</>}
{loginType === LoginType.Redirect && <MessageBar
messageBarType={MessageBarType.warning}
isMultiline={true}
>
<p>
<FormattedMessage id='To try operations other than GET' />,

<a className={classes.links}
tabIndex={0}
href={query} target='_blank'>
<FormattedMessage id='sign in' />.
</a>
</p>
</MessageBar>}
</div>
)}
{graphExplorerMode.TryIt && headerMessaging(loginType, classes, query)}

{displayContent && <>
<div style={{ marginBottom: 8 }}>
<QueryRunner onSelectVerb={this.handleSelectVerb} />
</div>
{queryState && (
<MessageBar
messageBarType={queryState.messageType}
isMultiline={false}
onDismiss={actions.clearQueryStatus}
>
{`${queryState.statusText} - ${queryState.status} `}
{queryState.duration && <>
{`- ${queryState.duration}`}<FormattedMessage id='milliseconds' />
</>}

{queryState.status === 403 && <>.
<FormattedMessage id='consent to scopes' />
<span style={{ fontWeight: 600 }}>
<FormattedMessage id='modify permissions' />
</span>
<FormattedMessage id='tab' />
</>}

</MessageBar>
)}
{termsOfUse && (
<MessageBar
messageBarType={MessageBarType.info}
isMultiline={false}
onDismiss={actions.clearTermsOfUse}
>
<FormattedMessage id='use the Microsoft Graph API' /><a className={classes.links}
href={'https://docs.microsoft.com/' + language +
'/legal/microsoft-apis/terms-of-use?context=graph/context'}
target='_blank'>
<FormattedMessage id='Terms of use' /></a>.
<FormattedMessage id='View the' /><a className={classes.links}
href={'https://privacy.microsoft.com/' + language + '/privacystatement'}
target='_blank'>
<FormattedMessage id='Microsoft Privacy Statement' /></a>
</MessageBar>
)}
{statusMessages(queryState, actions)}
{termsOfUseMessage(termsOfUse, actions, classes, language)}
{
// @ts-ignore
<QueryResponse verb={this.state.selectedVerb} />
Expand Down
64 changes: 64 additions & 0 deletions src/app/views/app-sections/AppTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { IconButton, IStackTokens, Label, Stack } from 'office-ui-fabric-react';
import React from 'react';
import { Authentication } from '../authentication';
import { Banner } from '../opt-in-out-banner';

export function appTitleDisplayOnFullScreen(
classes: any,
minimised: any,
toggleSidebar: Function,
optOut: Function
): React.ReactNode {

return <div style={{ display: 'flex', width: '100%' }}>
<IconButton
iconProps={{ iconName: 'GlobalNavButton' }}
className={classes.sidebarToggle}
title='Minimise sidebar'
ariaLabel='Minimise sidebar'
onClick={() => toggleSidebar()} />
<div className={classes.graphExplorerLabelContainer}>
{!minimised &&
<>
<Label className={classes.graphExplorerLabel}>
Graph Explorer
</Label>
<span className={classes.previewButton}>
<Banner optOut={() => optOut()} />
</span>
</>}
</div>
</div>;
}

export function appTitleDisplayOnMobileScreen(
stackTokens: IStackTokens,
classes: any,
toggleSidebar: Function,
optOut: Function
): React.ReactNode {
return <Stack horizontal={true} disableShrink={true} tokens={stackTokens}>
<>
<IconButton
iconProps={{ iconName: 'GlobalNavButton' }}
className={classes.sidebarToggle}
title='Remove sidebar'
ariaLabel='Remove sidebar'
onClick={() => toggleSidebar()}
/>
<div style={{ padding: 10 }}>
<Label className={classes.graphExplorerLabel}>
Graph Explorer
</Label>
<Banner optOut={() => optOut()} />
</div>
<span style={{
position: 'absolute',
marginLeft: '70%',
marginTop: '2.5%'
}}>
<Authentication />
</span>
</>
</Stack>;
}
34 changes: 34 additions & 0 deletions src/app/views/app-sections/HeaderMessaging.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { MessageBar, MessageBarType } from 'office-ui-fabric-react';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { LoginType } from '../../../types/enums';
import { Authentication } from '../authentication';
export function headerMessaging(loginType: LoginType, classes: any, query: string): React.ReactNode {
return (
<div style={{ marginBottom: 8 }}>
{loginType === LoginType.Popup && <>
<MessageBar messageBarType={MessageBarType.info} isMultiline={true}>
<p>
<FormattedMessage id='To try the full features' />,
<a className={classes.links} tabIndex={0} href={query} target='_blank'>
<FormattedMessage id='full Graph Explorer' />.
</a>
</p>
<p>
<FormattedMessage id='running the query' />.
</p>
</MessageBar>

<Authentication />
</>}
{loginType === LoginType.Redirect && <MessageBar messageBarType={MessageBarType.warning} isMultiline={true}>
<p>
<FormattedMessage id='To try operations other than GET' />,

<a className={classes.links} tabIndex={0} href={query} target='_blank'>
<FormattedMessage id='sign in' />.
</a>
</p>
</MessageBar>}
</div>);
}
22 changes: 22 additions & 0 deletions src/app/views/app-sections/StatusMessages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { MessageBar } from 'office-ui-fabric-react';
import React from 'react';
import { FormattedMessage } from 'react-intl';
export function statusMessages(queryState: any, actions: any) {
return queryState && (
<MessageBar messageBarType={queryState.messageType}
isMultiline={false} onDismiss={actions.clearQueryStatus}>
{`${queryState.statusText} - ${queryState.status} `}
{queryState.duration && <>
{`- ${queryState.duration}`}<FormattedMessage id='milliseconds' />
</>}

{queryState.status === 403 && <>.
<FormattedMessage id='consent to scopes' />
<span style={{ fontWeight: 600 }}>
<FormattedMessage id='modify permissions' />
</span>
<FormattedMessage id='tab' />
</>}

</MessageBar>);
}
17 changes: 17 additions & 0 deletions src/app/views/app-sections/TermsOfUseMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MessageBar, MessageBarType } from 'office-ui-fabric-react';
import React from 'react';
import { FormattedMessage } from 'react-intl';
export function termsOfUseMessage(termsOfUse: any, actions: any, classes: any, language: string) {
return termsOfUse && (
<MessageBar messageBarType={MessageBarType.info}
isMultiline={false} onDismiss={actions.clearTermsOfUse}>
<FormattedMessage id='use the Microsoft Graph API' />
<a className={classes.links} href={'https://docs.microsoft.com/' + language +
'/legal/microsoft-apis/terms-of-use?context=graph/context'} target='_blank'>
<FormattedMessage id='Terms of use' /></a>.
<FormattedMessage id='View the' />
<a className={classes.links} href={'https://privacy.microsoft.com/' + language + '/privacystatement'}
target='_blank'>
<FormattedMessage id='Microsoft Privacy Statement' /></a>
</MessageBar>);
}
Loading

0 comments on commit ed0bcc8

Please sign in to comment.