Skip to content

Commit

Permalink
Modals and DashAlert state (#737)
Browse files Browse the repository at this point in the history
* Notification bar state for UI

* Use layout value

* Legible UI contstants for modal layout

* Checking next props to update notibar state

* Checking for notification bar

* Use state to check for dispatch

* rerender less

* Refactor NotiBar to DashAlert

* Tweak dispatch name

* Yank dispatch props, ensure bool

* Yank dispatch from NewTeam component

* Restored dispatch on NewTeam container
  • Loading branch information
ackernaut authored and mattkrick committed Mar 5, 2017
1 parent 4798913 commit 0da996b
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import {css} from 'aphrodite-local-styles/no-important';
import ui from 'universal/styles/ui';
import {Link} from 'react-router';
import FontAwesome from 'react-fontawesome';
import NotificationBar from 'universal/components/NotificationBar/NotificationBar';
import {DashAlert} from 'universal/components/Dashboard';

const ActiveTrialNotificationBar = (props) => {
const ActiveTrialDashAlert = (props) => {
const {accountLink, styles} = props;
const iconStyle = {
fontSize: ui.iconSize
};
return (
<NotificationBar colorPalette="cool">
<DashAlert colorPalette="cool">
<div className={css(styles.inlineBlock, styles.message)}>
Add 30 days to your trial!
</div>
Expand All @@ -21,11 +21,11 @@ const ActiveTrialNotificationBar = (props) => {
<span className={css(styles.underline)}>Go to My Account</span> <FontAwesome name="arrow-right" style={iconStyle} />
</Link>
</div>
</NotificationBar>
</DashAlert>
);
};

ActiveTrialNotificationBar.propTypes = {
ActiveTrialDashAlert.propTypes = {
accountLink: PropTypes.string,
styles: PropTypes.object
};
Expand Down Expand Up @@ -62,4 +62,4 @@ const styleThunk = () => ({
}
});

export default withStyles(styleThunk)(ActiveTrialNotificationBar);
export default withStyles(styleThunk)(ActiveTrialDashAlert);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import withStyles from 'universal/styles/withStyles';
import {css} from 'aphrodite-local-styles/no-important';
import appTheme from 'universal/styles/theme/appTheme';

const NotificationBar = (props) => {
const DashAlert = (props) => {
const {children, styles} = props;
return (
<div className={css(styles.bar)}>
Expand All @@ -12,7 +12,7 @@ const NotificationBar = (props) => {
);
};

NotificationBar.propTypes = {
DashAlert.propTypes = {
children: PropTypes.any,
colorPalette: PropTypes.oneOf([
'cool',
Expand All @@ -36,4 +36,4 @@ const styleThunk = (customTheme, props) => ({
}
});

export default withStyles(styleThunk)(NotificationBar);
export default withStyles(styleThunk)(DashAlert);
12 changes: 6 additions & 6 deletions src/universal/components/Dashboard/DashLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React, {PropTypes} from 'react';
import withStyles from 'universal/styles/withStyles';
import {css} from 'aphrodite-local-styles/no-important';
import ui from 'universal/styles/ui';
import ActiveTrialNotificationBar from 'universal/components/ActiveTrialNotificationBar/ActiveTrialNotificationBar';
import ExpiredTrialNotificationBar from 'universal/components/ExpiredTrialNotificationBar/ExpiredTrialNotificationBar';
import MeetingNotificationBar from 'universal/components/MeetingNotificationBar/MeetingNotificationBar';
import ActiveTrialDashAlert from 'universal/components/ActiveTrialDashAlert/ActiveTrialDashAlert';
import ExpiredTrialDashAlert from 'universal/components/ExpiredTrialDashAlert/ExpiredTrialDashAlert';
import MeetingDashAlert from 'universal/components/MeetingDashAlert/MeetingDashAlert';
import {TRIAL_EXPIRES_SOON, TRIAL_EXPIRED} from 'universal/utils/constants';

const DashLayout = (props) => {
Expand All @@ -19,11 +19,11 @@ const DashLayout = (props) => {
return (
<div className={css(styles.root)}>
{/* Shows over any dashboard view when we prompt the trial extension (1 week after sign up?). */}
{barType === TRIAL_EXPIRES_SOON && <ActiveTrialNotificationBar accountLink={`/me/organizations/${orgId}`} />}
{barType === TRIAL_EXPIRES_SOON && <ActiveTrialDashAlert accountLink={`/me/organizations/${orgId}`} />}
{/* Shows over any account view when the trial has expired. */}
{barType === TRIAL_EXPIRED && <ExpiredTrialNotificationBar accountLink={`/me/organizations/${orgId}`} />}
{barType === TRIAL_EXPIRED && <ExpiredTrialDashAlert accountLink={`/me/organizations/${orgId}`} />}
{/* Shows over any dashboard view when there is a meeting. */}
{hasMeetingNotification && <MeetingNotificationBar activeMeetings={activeMeetings} />}
{hasMeetingNotification && <MeetingDashAlert activeMeetings={activeMeetings} />}
<div className={css(styles.main)}>
{children}
</div>
Expand Down
28 changes: 12 additions & 16 deletions src/universal/components/Dashboard/DashModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ const DashModal = (props) => {
isClosing,
onBackdropClick,
position,
modalContext,
modalLayout,
styles
} = props;
const backdropStyles = css(
styles.backdrop,
position && styles[position],
modalContext && styles[modalContext]
modalLayout && styles[modalLayout]
);
const modalStyles = css(
styles.modal,
Expand Down Expand Up @@ -47,17 +47,14 @@ DashModal.propTypes = {

// NOTE: Use 'fixed' to show over 'viewport'.
// Default styles use 'fixed' and 'viewport' values.
// Use 'absolute' to show over 'main'.
// Use 'absolute' to show over 'main' or 'mainHasDashAlert'.
// SEE: ui.modalLayout for options

position: PropTypes.oneOf([
'absolute',
'fixed'
]),
modalContext: PropTypes.oneOf([
'main',
'meetingInProgress',
'viewport'
]),
modalLayout: PropTypes.oneOf(ui.modalLayout),
styles: PropTypes.object
};

Expand Down Expand Up @@ -107,17 +104,17 @@ const styleThunk = (theme, props) => ({
animationName: animateOut
},

viewport: {
left: 0
},

main: {
[ui.modalLayoutMain]: {
left: ui.dashSidebarWidth
},

meetingInProgress: {
[ui.modalLayoutMainWithDashAlert]: {
left: ui.dashSidebarWidth,
top: ui.dashNotificationBarHeight
top: ui.dashAlertHeight
},

[ui.modalLayoutViewport]: {
left: 0
},

absolute: {
Expand All @@ -137,7 +134,6 @@ const styleThunk = (theme, props) => ({
modal: {
background: '#fff',
border: `.125rem solid ${appTheme.palette.mid30a}`,
// boxShadow: `0 0 0 .25rem ${appTheme.palette.mid30a}, ${ui.modalBoxShadow}`,
boxShadow: ui.modalBoxShadow,
borderRadius: ui.modalBorderRadius,
padding: '1.25rem',
Expand Down
1 change: 1 addition & 0 deletions src/universal/components/Dashboard/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export DashAlert from './DashAlert.js';
export DashContent from './DashContent.js';
export DashHeader from './DashHeader.js';
export DashHeaderInfo from './DashHeaderInfo.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import appTheme from 'universal/styles/theme/appTheme';
import ui from 'universal/styles/ui';
import {Link} from 'react-router';
import FontAwesome from 'react-fontawesome';
import NotificationBar from 'universal/components/NotificationBar/NotificationBar';
import {DashAlert} from 'universal/components/Dashboard';

const ExpiredTrialNotificationBar = (props) => {
const ExpiredTrialDashAlert = (props) => {
const {accountLink, styles} = props;
const iconStyle = {
fontSize: ui.iconSize
};
return (
<NotificationBar colorPalette="light">
<DashAlert colorPalette="light">
<div className={css(styles.inlineBlock, styles.message)}>
Your trial has expired!
</div>
Expand All @@ -22,11 +22,11 @@ const ExpiredTrialNotificationBar = (props) => {
<span className={css(styles.underline)}>Add Billing Information</span> <FontAwesome name="arrow-right" style={iconStyle} />
</Link>
</div>
</NotificationBar>
</DashAlert>
);
};

ExpiredTrialNotificationBar.propTypes = {
ExpiredTrialDashAlert.propTypes = {
accountLink: PropTypes.string,
styles: PropTypes.object
};
Expand Down Expand Up @@ -64,4 +64,4 @@ const styleThunk = () => ({
}
});

export default withStyles(styleThunk)(ExpiredTrialNotificationBar);
export default withStyles(styleThunk)(ExpiredTrialDashAlert);
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import withStyles from 'universal/styles/withStyles';
import {css} from 'aphrodite-local-styles/no-important';
import {Link} from 'react-router';
import plural from 'universal/utils/plural';
import NotificationBar from 'universal/components/NotificationBar/NotificationBar';
import {DashAlert} from 'universal/components/Dashboard';

const MeetingNotificationBar = (props) => {
const MeetingDashAlert = (props) => {
const {activeMeetings, styles} = props;
return (
<NotificationBar colorPalette="warm">
<DashAlert colorPalette="warm">
<div className={css(styles.inlineBlock, styles.message)}>
{`${plural(activeMeetings.length, 'Meeting')} in progress:`}
</div>
Expand All @@ -21,11 +21,11 @@ const MeetingNotificationBar = (props) => {
);
})}
</div>
</NotificationBar>
</DashAlert>
);
};

MeetingNotificationBar.propTypes = {
MeetingDashAlert.propTypes = {
activeMeetings: PropTypes.array,
styles: PropTypes.object
};
Expand Down Expand Up @@ -58,4 +58,4 @@ const styleThunk = () => ({
}
});

export default withStyles(styleThunk)(MeetingNotificationBar);
export default withStyles(styleThunk)(MeetingDashAlert);
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {cashay} from 'cashay';
import DashLayout from 'universal/components/Dashboard/DashLayout';
import {TEAM} from 'universal/subscriptions/constants';
import {TRIAL_EXPIRES_SOON, TRIAL_EXPIRED} from 'universal/utils/constants';
import {setDashAlertPresence} from 'universal/modules/dashboard/ducks/dashDuck';

const resolveActiveMeetings = (teams) => {
if (teams !== resolveActiveMeetings.teams) {
Expand Down Expand Up @@ -53,7 +54,8 @@ const mapStateToProps = (state) => {
activeMeetings: resolveActiveMeetings(teams),
tms: state.auth.obj.tms,
userId: state.auth.sub,
trialNotification
trialNotification,
hasDashAlert: state.dash.hasDashAlert
};
};

Expand All @@ -74,6 +76,10 @@ export default class DashLayoutContainer extends Component {
// userId: PropTypes.string
};

componentWillMount() {
this.maybeSetDashAlert(this.props);
}

componentDidMount() {
const {tms} = this.props;
subToAllTeams(tms);
Expand All @@ -84,12 +90,30 @@ export default class DashLayoutContainer extends Component {
if (this.props.tms !== nextProps.tms) {
subToAllTeams(nextProps.tms);
}
this.maybeSetDashAlert(nextProps);
}

maybeSetDashAlert(props) {
const {
activeMeetings,
trialNotification,
hasDashAlert,
dispatch
} = props;
const shouldHaveDashAlert = activeMeetings.length > 0 || trialNotification.type;
if (shouldHaveDashAlert !== hasDashAlert) {
dispatch(setDashAlertPresence(shouldHaveDashAlert));
}
}

render() {
const {activeMeetings, children, trialNotification} = this.props;
return (
<DashLayout activeMeetings={activeMeetings} children={children} trialNotification={trialNotification}/>
<DashLayout
activeMeetings={activeMeetings}
children={children}
trialNotification={trialNotification}
/>
);
}
}
28 changes: 28 additions & 0 deletions src/universal/modules/dashboard/ducks/dashDuck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const DASH_ALERT_PRESENCE = 'dash/DASH_ALERT_PRESENCE';

const initialState = {
hasDashAlert: false
};

export default function reducer(state = initialState, action = {}) {
switch (action.type) {
case DASH_ALERT_PRESENCE: {
return {
...state,
hasDashAlert: action.payload.hasDashAlert,
};
}
default:
return state;
}
}

export const setDashAlertPresence = (bool) => {
const hasDashAlert = Boolean(bool);
return {
type: DASH_ALERT_PRESENCE,
payload: {
hasDashAlert
}
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import IconLink from 'universal/components/IconLink/IconLink';
import Type from 'universal/components/Type/Type';
import {withRouter} from 'react-router';
import portal from 'react-portal-hoc';
import ui from 'universal/styles/ui';

const MeetingInProgressModal = (props) => {
const {closeAfter, isClosing, teamId, teamName, router} = props;
const {closeAfter, isClosing, modalLayout, teamId, teamName, router} = props;
const handleClick = () => {
router.push(`/meeting/${teamId}`);
};
return (
<DashModal position="absolute" modalContext="meetingInProgress" isClosing={isClosing} closeAfter={closeAfter}>
<DashModal position="absolute" modalLayout={modalLayout} isClosing={isClosing} closeAfter={closeAfter}>
<Type align="center" bold marginBottom="1.5rem" scale="s7" colorPalette="cool">
Oh, hi there!
</Type>
Expand All @@ -36,6 +37,7 @@ const MeetingInProgressModal = (props) => {
MeetingInProgressModal.propTypes = {
closeAfter: PropTypes.number,
isClosing: PropTypes.bool,
modalLayout: PropTypes.oneOf(ui.modalLayout),
router: PropTypes.object,
teamId: PropTypes.string,
teamName: PropTypes.string
Expand Down
Loading

0 comments on commit 0da996b

Please sign in to comment.