From 762befa9236d030d69e60ab7e15e1c867c525e87 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 4 Feb 2018 21:25:11 +0330 Subject: [PATCH 1/2] Add StartupTabDialog component --- src/Settings/StartupTabDialog.js | 61 ++++++++++++++++++++++ src/Settings/__tests__/StartupTabDialog.js | 61 ++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/Settings/StartupTabDialog.js create mode 100644 src/Settings/__tests__/StartupTabDialog.js diff --git a/src/Settings/StartupTabDialog.js b/src/Settings/StartupTabDialog.js new file mode 100644 index 00000000..9829c377 --- /dev/null +++ b/src/Settings/StartupTabDialog.js @@ -0,0 +1,61 @@ +import React, { Component } from 'react'; +import Dialog from 'material-ui/Dialog'; +import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton'; +import FlatButton from 'material-ui/FlatButton'; +import { blue500, grey50 } from 'material-ui/styles/colors'; + +class StartupTabDialog extends Component { + handleRequestClose = (e, target) => { + setTimeout(() => { + this.props.onRequestClose(target); + }, 300); + } + render() { + const actions = [ + this.props.onRequestClose(this.props.startupTab)} + />, + ]; + const dialogContentStyle = { + maxWidth: 256, + }; + const radioButtonStyle = { + marginTop: 16, + }; + const dialogTitleStyle = { + backgroundColor: blue500, + color: grey50, + }; + return ( + this.props.onRequestClose(this.props.startupTab)} + > + + + + + + ); + } +} + +export default StartupTabDialog; diff --git a/src/Settings/__tests__/StartupTabDialog.js b/src/Settings/__tests__/StartupTabDialog.js new file mode 100644 index 00000000..57b70cc9 --- /dev/null +++ b/src/Settings/__tests__/StartupTabDialog.js @@ -0,0 +1,61 @@ +/* eslint-env mocha, jest */ + +import getActualComponentFactory from '../../lib/testUtils'; +import StartupTabDialog from '../StartupTabDialog'; + +const defaultProps = { + open: false, + startupTab: 'tasks', + onRequestClose() {}, +}; +const getActualDialog = getActualComponentFactory(StartupTabDialog, defaultProps); + +jest.useFakeTimers(); + +it('should render', () => { + getActualDialog(); +}); +it('should be a Dialog', () => { + const wrapper = getActualDialog(); + expect(wrapper.is('Dialog')).toBe(true); +}); +it('should have 2 RadioButton', () => { + const wrapper = getActualDialog(); + expect(wrapper.find('RadioButton').length).toBe(2); +}); +it('should set Dialog open based on props', () => { + const wrapper = getActualDialog({ open: true }); + expect(wrapper.find('Dialog').prop('open')).toBe(true); +}); +it('should set RadioButtonGroup defaultSelected based on props', () => { + const wrapper = getActualDialog({ startupTab: 'ideas' }); + expect(wrapper.find('RadioButtonGroup').prop('defaultSelected')).toBe('ideas'); +}); +it('should call onRequestClose inside Dialog onRequestClose', () => { + const wrapper = getActualDialog({ + startupTab: 'ideas', + onRequestClose(startupTab) { + expect(startupTab).toBe('ideas'); + }, + }); + wrapper.find('Dialog').props().onRequestClose(); +}); +it('should call onRequestClose inside FlatButton onClick', () => { + const wrapper = getActualDialog({ + startupTab: 'ideas', + onRequestClose(startupTab) { + expect(startupTab).toBe('ideas'); + }, + }); + wrapper.find('Dialog').prop('actions')[0].props.onClick(); +}); +it('should call onRequestClose inside RadioButtonGroup onChange', () => { + const wrapper = getActualDialog({ + startupTab: 'ideas', + onRequestClose(startupTab) { + expect(startupTab).toBe('ideas'); + }, + }); + wrapper.find('RadioButtonGroup').props().onChange(null, 'ideas'); + jest.runAllTimers(); +}); From 77d3d51751276e5d81b2f46ab8dd58da9cf4c664 Mon Sep 17 00:00:00 2001 From: mohammad Date: Sun, 4 Feb 2018 21:26:38 +0330 Subject: [PATCH 2/2] Implement startup tab selection --- main.js | 1 + src/App.js | 2 +- src/Settings/Settings.js | 24 ++++++++ src/Settings/SettingsContainer.js | 1 + src/Settings/__tests__/Settings.spec.js | 58 +++++++++++++------ ...pTabDialog.js => StartupTabDialog.spec.js} | 0 src/Settings/actionCreators.js | 12 +++- src/Sidebar/SidebarContainer.js | 1 + src/lib/database.js | 2 +- src/reducers/__tests__/appProperties.spec.js | 8 +++ src/reducers/appProperties.js | 5 ++ src/store.js | 1 + 12 files changed, 93 insertions(+), 22 deletions(-) rename src/Settings/__tests__/{StartupTabDialog.js => StartupTabDialog.spec.js} (100%) diff --git a/main.js b/main.js index c7f905b8..c6ca7a60 100644 --- a/main.js +++ b/main.js @@ -22,6 +22,7 @@ const createDatabase = () => { fullscreen: false, calendarSystem: 'en-US', firstDayOfWeek: 1, + startupTab: 'tasks', }, }); fs.writeFileSync('.config/db', prefill); diff --git a/src/App.js b/src/App.js index 64de2402..b1df8aed 100644 --- a/src/App.js +++ b/src/App.js @@ -122,7 +122,7 @@ class App extends Component { window={window} width={document.body.clientWidth} /> - + {this.state.toTasks && } diff --git a/src/Settings/Settings.js b/src/Settings/Settings.js index 855cf64f..9c43ba57 100644 --- a/src/Settings/Settings.js +++ b/src/Settings/Settings.js @@ -5,6 +5,7 @@ import Divider from 'material-ui/Divider'; import CalendarSystemDialog from './CalendarSystemDialog'; import FirstDayOfWeekDialog from './FirstDayOfWeekDialog'; +import StartupTabDialog from './StartupTabDialog'; import './Settings.css'; import { @@ -16,6 +17,7 @@ class Settings extends Component { state = { calendarSystemDialogOpen: false, firstDayOfWeekDialogOpen: false, + startupTabDialogOpen: false, }; handleCheckShowNotYet = (e, checked) => { @@ -34,6 +36,11 @@ class Settings extends Component { firstDayOfWeekDialogOpen: true, }); } + handleRequestStartupTabDialogOpen = () => { + this.setState({ + startupTabDialogOpen: true, + }); + } handleRequestCalendarSystemDialogClose = (calendarSystem) => { this.props.changeCalendarSystem(calendarSystem); this.setState({ @@ -46,6 +53,12 @@ class Settings extends Component { firstDayOfWeekDialogOpen: false, }); } + handleRequestStartupTabDialogClose = (startupTab) => { + this.props.changeStartupTab(startupTab); + this.setState({ + startupTabDialogOpen: false, + }); + } render() { const weekDays = { 0: 'Sunday', @@ -82,6 +95,12 @@ class Settings extends Component { onClick={this.handleRequestFirstDayOfWeekDialogOpen} /> + + + ); } diff --git a/src/Settings/SettingsContainer.js b/src/Settings/SettingsContainer.js index d110ac5d..7b137f99 100644 --- a/src/Settings/SettingsContainer.js +++ b/src/Settings/SettingsContainer.js @@ -9,6 +9,7 @@ const mapStateToProps = state => ({ showNotYetTasks: state.appProperties.showNotYetTasks, calendarSystem: state.appProperties.calendarSystem, firstDayOfWeek: state.appProperties.firstDayOfWeek, + startupTab: state.appProperties.startupTab, }); const mapDispatchToProps = dispatch => bindActionCreators(actionCreators, dispatch); diff --git a/src/Settings/__tests__/Settings.spec.js b/src/Settings/__tests__/Settings.spec.js index 64cf753f..c2d3a161 100644 --- a/src/Settings/__tests__/Settings.spec.js +++ b/src/Settings/__tests__/Settings.spec.js @@ -6,13 +6,15 @@ import Settings from '../Settings'; const defaultProps = { sidebarExpanded: true, calendarSystem: 'en-US', - fullscreen: false, firstDayOfWeek: 0, + startupTab: 'tasks', + fullscreen: false, showNotYetTasks: true, toggleNotYet() {}, toggleFullscreen() {}, changeCalendarSystem() {}, changeFirstDayOfWeek() {}, + changeStartupTab() {}, }; const getActualSettings = getActualComponentFactory(Settings, defaultProps); @@ -26,13 +28,13 @@ it('should be a div', () => { const wrapper = getActualSettings(); expect(wrapper.is('div.Settings')).toBe(true); }); -it('should have 4 ListItem', () => { +it('should have 5 ListItem', () => { const wrapper = getActualSettings(); - expect(wrapper.find('ListItem').length).toBe(4); + expect(wrapper.find('ListItem').length).toBe(5); }); -it('should have 4 Divider', () => { +it('should have 5 Divider', () => { const wrapper = getActualSettings(); - expect(wrapper.find('Divider').length).toBe(4); + expect(wrapper.find('Divider').length).toBe(5); }); it('should have 1 CalendarSystemDialog', () => { const wrapper = getActualSettings(); @@ -42,6 +44,10 @@ it('should have 1 FirstDayOfWeekDialog', () => { const wrapper = getActualSettings(); expect(wrapper.find('FirstDayOfWeekDialog').length).toBe(1); }); +it('should have 1 StartupTabDialog', () => { + const wrapper = getActualSettings(); + expect(wrapper.find('StartupTabDialog').length).toBe(1); +}); it('should set left margin style based on props', () => { const wrapper = getActualSettings({ @@ -55,23 +61,17 @@ it('should set ListItem secondaryText based on props', () => { }); expect(wrapper.find('ListItem').at(0).prop('secondaryText')).toBe('fa-IR'); }); -it('should set ListItem secondaryText based on props', () => { - const wrapper = getActualSettings({ - firstDayOfWeek: 6, - }); - expect(wrapper.find('ListItem').at(1).prop('secondaryText')).toBe('Saturday'); -}); it('should set fullscreen Checkbox defaultChecked based on props', () => { const wrapper = getActualSettings({ fullscreen: true, }); - expect(wrapper.find('ListItem').at(2).prop('leftCheckbox').props.defaultChecked).toBe(true); + expect(wrapper.find('ListItem').at(3).prop('leftCheckbox').props.defaultChecked).toBe(true); }); it('should set show not yet tasks Checkbox defaultChecked based on props', () => { const wrapper = getActualSettings({ showNotYetTasks: false, }); - expect(wrapper.find('ListItem').at(3).prop('leftCheckbox').props.defaultChecked).toBe(false); + expect(wrapper.find('ListItem').at(4).prop('leftCheckbox').props.defaultChecked).toBe(false); }); it('should set CalendarSystemDialog calendarSystem based on props', () => { const wrapper = getActualSettings({ @@ -85,22 +85,28 @@ it('should set FirstDayOfWeekDialog dialog firstDayOfWeek based on props', () => }); expect(wrapper.find('FirstDayOfWeekDialog').prop('firstDayOfWeek')).toBe(6); }); +it('should set StartupTabDialog dialog startupTab based on props', () => { + const wrapper = getActualSettings({ + startupTab: 'ideas', + }); + expect(wrapper.find('StartupTabDialog').prop('startupTab')).toBe('ideas'); +}); -it('should call toggleNotYet when handling show not yet check', () => { +it('should call toggleFullscreen when handling fullscreen check', () => { const wrapper = getActualSettings({ - toggleNotYet(checked) { + toggleFullscreen(checked) { expect(checked).toBe(true); }, }); wrapper.find('ListItem').at(3).prop('leftCheckbox').props.onCheck(null, true); }); -it('should call toggleFullscreen when handling fullscreen check', () => { +it('should call toggleNotYet when handling show not yet check', () => { const wrapper = getActualSettings({ - toggleFullscreen(checked) { + toggleNotYet(checked) { expect(checked).toBe(true); }, }); - wrapper.find('ListItem').at(2).prop('leftCheckbox').props.onCheck(null, true); + wrapper.find('ListItem').at(4).prop('leftCheckbox').props.onCheck(null, true); }); it('should call changeCalendarSystem when handling calendar system dialog close request', () => { const wrapper = getActualSettings({ @@ -110,7 +116,7 @@ it('should call changeCalendarSystem when handling calendar system dialog close }); wrapper.find('CalendarSystemDialog').props().onRequestClose('fa-IR'); }); -it('should call changeCalendarSystem when handling first day of week dialog close request', () => { +it('should call changeFirstDayOfWeek when handling first day of week dialog close request', () => { const wrapper = getActualSettings({ changeFirstDayOfWeek(firstDayOfWeek) { expect(firstDayOfWeek).toBe(6); @@ -118,6 +124,14 @@ it('should call changeCalendarSystem when handling first day of week dialog clos }); wrapper.find('FirstDayOfWeekDialog').props().onRequestClose(6); }); +it('should call changeStartupTab when handling startup tab dialog close request', () => { + const wrapper = getActualSettings({ + changeStartupTab(startupTab) { + expect(startupTab).toBe('ideas'); + }, + }); + wrapper.find('StartupTabDialog').props().onRequestClose('ideas'); +}); it('should set CalendarSystemDialog open based on state', () => { const wrapper = getActualSettings(); @@ -131,3 +145,9 @@ it('should set FirstDayOfWeekDialog open based on state', () => { wrapper.update(); expect(wrapper.find('FirstDayOfWeekDialog').prop('open')).toBe(true); }); +it('should set StartupTabDialog open based on state', () => { + const wrapper = getActualSettings(); + wrapper.find('ListItem').at(2).props().onClick(); + wrapper.update(); + expect(wrapper.find('StartupTabDialog').prop('open')).toBe(true); +}); diff --git a/src/Settings/__tests__/StartupTabDialog.js b/src/Settings/__tests__/StartupTabDialog.spec.js similarity index 100% rename from src/Settings/__tests__/StartupTabDialog.js rename to src/Settings/__tests__/StartupTabDialog.spec.js diff --git a/src/Settings/actionCreators.js b/src/Settings/actionCreators.js index 0a907c74..7820ba2e 100644 --- a/src/Settings/actionCreators.js +++ b/src/Settings/actionCreators.js @@ -14,5 +14,15 @@ const changeFirstDayOfWeek = firstDayOfWeek => ({ type: 'CHANGE_FIRST_DAY_OF_WEEK', firstDayOfWeek, }); +const changeStartupTab = startupTab => ({ + type: 'CHANGE_STARTUP_TAB', + startupTab, +}); -export { toggleNotYet, toggleFullscreen, changeCalendarSystem, changeFirstDayOfWeek }; +export { + toggleNotYet, + toggleFullscreen, + changeCalendarSystem, + changeFirstDayOfWeek, + changeStartupTab, +}; diff --git a/src/Sidebar/SidebarContainer.js b/src/Sidebar/SidebarContainer.js index 4fa535d4..7ddc5c48 100644 --- a/src/Sidebar/SidebarContainer.js +++ b/src/Sidebar/SidebarContainer.js @@ -6,6 +6,7 @@ import Sidebar from './Sidebar'; const mapStateToProps = state => ({ currentTab: state.appUI.currentTab, + startupTab: state.appProperties.startupTab, }); const mapDispatchToProps = dispatch => bindActionCreators({ changeTab }, dispatch); diff --git a/src/lib/database.js b/src/lib/database.js index 8816d819..ee3bdb34 100644 --- a/src/lib/database.js +++ b/src/lib/database.js @@ -30,7 +30,7 @@ const fetchDatabaseState = () => { appProperties: data.appProperties, appUI: { FABRaised: false, - currentTab: 'tasks', + currentTab: data.appProperties.startupTab, }, }; } diff --git a/src/reducers/__tests__/appProperties.spec.js b/src/reducers/__tests__/appProperties.spec.js index bc5274b3..b962348f 100644 --- a/src/reducers/__tests__/appProperties.spec.js +++ b/src/reducers/__tests__/appProperties.spec.js @@ -6,6 +6,7 @@ import { toggleFullscreen, changeCalendarSystem, changeFirstDayOfWeek, + changeStartupTab, } from '../../Settings/actionCreators'; const defaultState = { @@ -13,6 +14,7 @@ const defaultState = { fullscreen: false, calendarSystem: 'en-US', firstDayOfWeek: 1, + startupTab: 'tasks', }; const getExpectedState = (props = {}) => Object.assign({}, defaultState, props); @@ -46,3 +48,9 @@ it('should update firstDayOfWeek of state', () => { const actual = appPropertiesReducer(defaultState, action); expect(actual).toEqual(expected); }); +it('should update startupTab of state', () => { + const expected = getExpectedState({ startupTab: 'ideas' }); + const action = changeStartupTab('ideas'); + const actual = appPropertiesReducer(defaultState, action); + expect(actual).toEqual(expected); +}); diff --git a/src/reducers/appProperties.js b/src/reducers/appProperties.js index 1aae21e0..398bad3c 100644 --- a/src/reducers/appProperties.js +++ b/src/reducers/appProperties.js @@ -20,6 +20,11 @@ const appPropertiesReducer = (state = {}, action) => { ...state, firstDayOfWeek: action.firstDayOfWeek, }; + case 'CHANGE_STARTUP_TAB': + return { + ...state, + startupTab: action.startupTab, + }; default: return state; } diff --git a/src/store.js b/src/store.js index 0dc039e2..f02c4555 100644 --- a/src/store.js +++ b/src/store.js @@ -11,6 +11,7 @@ const initialStateFactory = () => ({ fullscreen: false, calendarSystem: 'en-US', firstDayOfWeek: 1, + startupTab: 'tasks', }, appUI: { FABRaised: false,