From be0a42d1a221f59d8696912fe8eaf4c4735926c1 Mon Sep 17 00:00:00 2001 From: Federico Madoery Date: Tue, 8 Jan 2019 17:43:36 -0300 Subject: [PATCH 1/2] [WIP] Issue #22 Code Cleanup Alphabetical ordering of imports and actions (in redux) Implementation of BlockList to manage and render the Set Blocks, to improve the readability of Schedule Page by reducing your code length Enable Submit now is managed through redux UI Polish Fix alignment for Setblocks scheduled within the same day and make sure the setblock dots (on both the sidebar and the main page are perfect squares instead of rectangles - Was Fixed some commits ago in PR "Close Issue #9" Fix alignment on the empty state UI "This user hasn't committed..." - Was Fixed some commits ago in PR "Close Issue #9" --- config/paths.js | 4 +- web/components/BlockList.jsx | 87 ++++++++++++++++++++++++++++++--- web/components/CommitBlock.jsx | 2 +- web/components/DayBlock.jsx | 5 +- web/components/NavigationBar.js | 2 +- web/components/SchedulePage.jsx | 76 +++++++--------------------- web/components/SetBlock.jsx | 6 +-- web/components/SideBar.jsx | 2 +- web/components/TeamMember.jsx | 5 +- web/reducers/environment.js | 60 ++++++++++++++--------- 10 files changed, 151 insertions(+), 98 deletions(-) diff --git a/config/paths.js b/config/paths.js index 9c7c793..146fd0c 100644 --- a/config/paths.js +++ b/config/paths.js @@ -1,5 +1,5 @@ -var path = require('path') -var fs = require('fs') +const path = require('path') +const fs = require('fs') const projectDirectory = fs.realpathSync(process.cwd()) const resolve = relativePath => path.resolve(projectDirectory, relativePath) diff --git a/web/components/BlockList.jsx b/web/components/BlockList.jsx index 4bcc434..b47ea26 100644 --- a/web/components/BlockList.jsx +++ b/web/components/BlockList.jsx @@ -1,12 +1,87 @@ import React from 'react'; +import { connect } from 'react-redux'; +import moment from 'moment'; +import { cloneDeep } from 'lodash'; + +import SetBlock from './SetBlock'; +import Text from './Text'; +import { DEFAULT_SETBLOCKS } from '../constants'; + +import { + setEnableSubmit, updateUnsavedSetblocks, +} from '../reducers/environment'; + +class BlockList extends React.Component { + + completeWithEmptySetBlocks(setBlocks) { + const defaultSetBlocks = cloneDeep(DEFAULT_SETBLOCKS); + let replacedBlocks = 0; + setBlocks = _.orderBy(setBlocks, ['blockTime'], ['asc']); // Use Lodash to sort array by 'name' + setBlocks = _.uniqBy(setBlocks, 'blockTime'); // Use Lodash to delete repeated blockTimes + if (setBlocks && setBlocks.length > 0) { // To avoid iterate if the array is empty, return default + defaultSetBlocks.forEach((setBlock, index, theArray) => { + if (setBlocks && replacedBlocks < setBlocks.length && setBlock.blockTime === setBlocks[replacedBlocks].blockTime) { + theArray[index] = setBlocks[replacedBlocks]; + replacedBlocks++; + } + }); + } + return defaultSetBlocks + } + + updateUnsavedSetBlock(selectedDay, index, editedSetBlock ) { + const { unsavedSetBlocks } = this.props + let dayEdited = unsavedSetBlocks[selectedDay]; + dayEdited[index] = editedSetBlock; // index 0 = SetBlock with blockTime 1 + this.props.updateUnsavedSetblocks({ + ...unsavedSetBlocks, + [selectedDay]: dayEdited + }) + this.props.setEnableSubmit(true) + } -export default class BlockList extends React.Component { render() { - return ( -
-
BlockList
-
- ); + const { + editModeSchedule, currentWeeklySetblocks, unsavedSetBlocks, selectedDay + } = this.props; + const selectedDayFormatted = moment(selectedDay).format('YYYY-MM-DD') + let setBlocksByDate = _.groupBy(currentWeeklySetblocks, 'date'); + let setBlocks = setBlocksByDate[selectedDayFormatted]; + + if (editModeSchedule && unsavedSetBlocks ) { + // As it is your schedule, you can see the empty blocks, to complete then, that's why it is completed with the missing ones + return this.completeWithEmptySetBlocks(setBlocks).map((setBlock, index) => { + return ( + this.updateUnsavedSetBlock(selectedDayFormatted, index, editedSetBlock )} + /> + ) + }) + } else if (!editModeSchedule && setBlocks) { + return setBlocks.map((setBlock, index) => { + return + }) + } else { + return ( + This user hasn't committed any Setblocks for this day + ) + } } } +const mapStateToProps = ({ environment }) => { + return { + ...environment + }; +}; + +const mapDispatchToProps = (dispatch) => { + return { + setEnableSubmit: (enableSubmit) => dispatch(setEnableSubmit(enableSubmit)), + updateUnsavedSetblocks: (unsavedSetBlocks) => dispatch(updateUnsavedSetblocks(unsavedSetBlocks)) + }; +}; +export default connect(mapStateToProps, mapDispatchToProps)(BlockList); \ No newline at end of file diff --git a/web/components/CommitBlock.jsx b/web/components/CommitBlock.jsx index 4221a71..fb95f90 100644 --- a/web/components/CommitBlock.jsx +++ b/web/components/CommitBlock.jsx @@ -3,9 +3,9 @@ import moment from 'moment'; import { connect } from 'react-redux'; import { Check } from 'styled-icons/feather/Check.cjs' -import Text from './Text'; import Card from './Card'; import Flex from './Flex'; +import Text from './Text'; import { createSetBlock, setEditModeSchedule, updateSetBlock } from '../reducers/environment'; diff --git a/web/components/DayBlock.jsx b/web/components/DayBlock.jsx index 5b9203a..5db3f7b 100644 --- a/web/components/DayBlock.jsx +++ b/web/components/DayBlock.jsx @@ -1,10 +1,11 @@ +import React from 'react'; import { connect } from 'react-redux'; import moment from 'moment'; -import React from 'react'; + +import Card from './Card'; import Flex from './Flex'; import Text from './Text'; -import Card from './Card'; class DayBlock extends React.Component { diff --git a/web/components/NavigationBar.js b/web/components/NavigationBar.js index 39722ba..fdc2e53 100644 --- a/web/components/NavigationBar.js +++ b/web/components/NavigationBar.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -var _ = require('lodash'); +import _ from 'lodash' import NavLinkItem from './NavLinkItem'; diff --git a/web/components/SchedulePage.jsx b/web/components/SchedulePage.jsx index a4410f4..b5f4439 100644 --- a/web/components/SchedulePage.jsx +++ b/web/components/SchedulePage.jsx @@ -3,18 +3,20 @@ import moment from 'moment'; import { connect } from 'react-redux'; import { cloneDeep } from 'lodash'; +import BlockList from './BlockList'; +import CommitBlock from './CommitBlock'; +import Flex from './Flex'; +import LoadingDots from './Loading'; import ScheduleHeader from './ScheduleHeader'; import SideBar from './SideBar'; -import Flex from './Flex'; -import SetBlock from './SetBlock'; import Text from './Text'; -import LoadingDots from './Loading'; -import CommitBlock from './CommitBlock'; -import { DEFAULT_SETBLOCKS } from '../constants/index'; + +import { DEFAULT_SETBLOCKS } from '../constants'; import { fetchCurrentTeamMemberById, setEditModeSchedule, + setEnableSubmit, setSelectedDay, updateUnsavedSetblocks } from '../reducers/environment'; @@ -23,7 +25,6 @@ import { class SchedulePage extends React.Component { state = { daysOfWeek: [], - enableSubmit: false, } componentDidMount() { @@ -72,7 +73,7 @@ class SchedulePage extends React.Component { } if ((editModeSchedule && currentTeamMember !== nextProps.currentTeamMember) || selectedDay !== nextProps.selectedDay) { this.makeSetBlocksForEdit(nextProps.currentWeeklySetblocks); - this.setState({ enableSubmit: false }) + this.props.setEnableSubmit(false) } } @@ -89,61 +90,21 @@ class SchedulePage extends React.Component { let replacedBlocks = 0; setBlocks = _.orderBy(setBlocks, ['blockTime'], ['asc']); // Use Lodash to sort array by 'name' setBlocks = _.uniqBy(setBlocks, 'blockTime'); // Use Lodash to delete repeated blockTimes - defaultSetBlocks.forEach((setBlock, index, theArray) => { - if (setBlocks && replacedBlocks < setBlocks.length && setBlock.blockTime === setBlocks[replacedBlocks].blockTime) { - theArray[index] = setBlocks[replacedBlocks]; - replacedBlocks++; - } - }); - return defaultSetBlocks - } - - updateUnsavedSetBlock(selectedDay, index, editedSetBlock ) { - const { unsavedSetBlocks } = this.props - let dayEdited = unsavedSetBlocks[selectedDay]; - dayEdited[index] = editedSetBlock; // index 0 = SetBlock with blockTime 1 - this.props.updateUnsavedSetblocks({ - ...unsavedSetBlocks, - [selectedDay]: dayEdited - }) - this.setState({ enableSubmit: true }) - } - - renderSetBlocks = (selectedDay) => { - const { editModeSchedule, currentWeeklySetblocks, unsavedSetBlocks } = this.props; - selectedDay = moment(selectedDay).format('YYYY-MM-DD') - const setBlocksByDate = _.groupBy(currentWeeklySetblocks, 'date') - let setBlocks = setBlocksByDate[selectedDay]; - - if (editModeSchedule && unsavedSetBlocks) { - // If the match.params don't have a teamMemberId are u seeing your schedule - // As it is your schedule, you can see the empty blocks, to complete then, that's why it is completed with the missing ones - return this.completeWithEmptySetBlocks(setBlocks).map((setBlock, index) => { - return ( - this.updateUnsavedSetBlock(selectedDay, index, editedSetBlock )} - /> - ) - }) - } else if (!editModeSchedule && setBlocks) { - return setBlocks.map((setBlock, index) => { - return - }) - } else { - return ( - This user hasn't committed any Setblocks for this day - ) + if (setBlocks && setBlocks.length > 0) { // To avoid iterate if the array is empty, return default + defaultSetBlocks.forEach((setBlock, index, theArray) => { + if (setBlocks && replacedBlocks < setBlocks.length && setBlock.blockTime === setBlocks[replacedBlocks].blockTime) { + theArray[index] = setBlocks[replacedBlocks]; + replacedBlocks++; + } + }); } + return defaultSetBlocks } renderIfItReady() { const { - match, currentTeamMember, fetchingData, selectedDay, editModeSchedule + match, currentTeamMember, fetchingData, editModeSchedule, enableSubmit } = this.props - const { enableSubmit } = this.state if (fetchingData) { return ( // If you are waiting for the API to respond, render a loading @@ -164,7 +125,7 @@ class SchedulePage extends React.Component { {match.params.teamMemberId ? currentTeamMember.name : 'Your'} {' Schedule\'s Page'} - {this.renderSetBlocks(selectedDay)} + {editModeSchedule && ()} ) @@ -215,6 +176,7 @@ const mapDispatchToProps = (dispatch) => { fetchCurrentTeamMemberById: (params) => dispatch(fetchCurrentTeamMemberById(params)), setSelectedDay: (selectedDay) => dispatch(setSelectedDay(selectedDay)), setEditModeSchedule: (editMode) => dispatch(setEditModeSchedule(editMode)), + setEnableSubmit: (enableSubmit) => dispatch(setEnableSubmit(enableSubmit)), updateUnsavedSetblocks: (unsavedSetBlocks) => dispatch(updateUnsavedSetblocks(unsavedSetBlocks)) }; }; diff --git a/web/components/SetBlock.jsx b/web/components/SetBlock.jsx index 65c9ba4..80f6c8a 100644 --- a/web/components/SetBlock.jsx +++ b/web/components/SetBlock.jsx @@ -2,12 +2,12 @@ import React from 'react'; import { connect } from 'react-redux'; import { Edit3 } from 'styled-icons/feather/Edit3.cjs' -import Flex from './Flex'; -import Text from './Text'; +import Box from './Box'; import Card from './Card'; +import Flex from './Flex'; import Modal from './Modal'; -import Box from './Box'; import Input from './Input'; +import Text from './Text'; class SetBlock extends React.Component { diff --git a/web/components/SideBar.jsx b/web/components/SideBar.jsx index ec13389..3c696b8 100644 --- a/web/components/SideBar.jsx +++ b/web/components/SideBar.jsx @@ -2,8 +2,8 @@ import React from 'react'; import { withRouter } from 'react-router-dom'; import { connect } from 'react-redux'; -import Flex from './Flex'; import DayBlock from './DayBlock'; +import Flex from './Flex'; import { setEditModeSchedule, setSelectedDay } from '../reducers/environment'; diff --git a/web/components/TeamMember.jsx b/web/components/TeamMember.jsx index 49d8b9d..c59ff4e 100644 --- a/web/components/TeamMember.jsx +++ b/web/components/TeamMember.jsx @@ -1,9 +1,10 @@ import React from 'react'; -import Flex from './Flex'; -import Text from './Text'; import Card from './Card'; +import Flex from './Flex'; import Image from './Image'; +import Text from './Text'; + export default class TeamMember extends React.Component { render() { diff --git a/web/reducers/environment.js b/web/reducers/environment.js index 0ad9373..ddfc078 100644 --- a/web/reducers/environment.js +++ b/web/reducers/environment.js @@ -1,59 +1,71 @@ -import moment from 'moment'; - import api from 'scripts/api' +import moment from 'moment'; // Index of Action Types -const RECEIVE_TEAM_MEMBERS = 'RECEIVE_TEAM_MEMBERS' +const CREATE_SET_BLOCK = 'CREATE_SET_BLOCK' +const EDIT_MODE_SCHEDULE = 'EDIT_MODE_SCHEDULE' +const ENABLE_SUBMIT = 'ENABLE_SUBMIT' +const FETCHING_DATA = 'FETCHING_DATA' const RECEIVE_TEAM_MEMBER = 'RECEIVE_TEAM_MEMBER' +const RECEIVE_TEAM_MEMBERS = 'RECEIVE_TEAM_MEMBERS' const SET_SELECTED_DAY = 'SET_SELECTED_DAY' -const FETCHING_DATA = 'FETCHING_DATA' -const EDIT_MODE_SCHEDULE = 'EDIT_MODE_SCHEDULE' const UPDATE_BLOCK_FRACTION = 'UPDATE_BLOCK_FRACTION' -const CREATE_SET_BLOCK = 'CREATE_SET_BLOCK' const UPDATE_SET_BLOCK = 'UPDATE_SET_BLOCK' const UPDATE_UNSAVED_SET_BLOCKS = 'UPDATE_UNSAVED_SET_BLOCKS' // Reducer const initialState = { - teamMembers: [], currentTeamMember: { id: '', name: '' }, currentWeeklySetblocks: [], - selectedDay: moment.now(), - fetchingData: false, editModeSchedule: false, + enableSubmit: false, + fetchingData: false, + teamMembers: [], + selectedDay: moment.now(), unsavedSetBlocks: [], } export default function reducer(state = initialState, action) { switch (action.type) { - case RECEIVE_TEAM_MEMBERS: + case CREATE_SET_BLOCK: return { ...state, - teamMembers: action.members + + currentWeeklySetblocks: action.teamMember.weeklySetblocks } - case RECEIVE_TEAM_MEMBER: + case EDIT_MODE_SCHEDULE: return { ...state, - currentTeamMember: { id: action.member.id, name: action.member.name }, - currentWeeklySetblocks: action.member.weeklySetblocks + editModeSchedule: action.editModeSchedule } - case SET_SELECTED_DAY: + case ENABLE_SUBMIT: return { ...state, - selectedDay: action.selectedDay + enableSubmit: action.enableSubmit } case FETCHING_DATA: return { ...state, fetchingData: action.fetchingData } - case EDIT_MODE_SCHEDULE: + case RECEIVE_TEAM_MEMBER: return { ...state, - editModeSchedule: action.editModeSchedule + currentTeamMember: { id: action.member.id, name: action.member.name }, + currentWeeklySetblocks: action.member.weeklySetblocks + } + case RECEIVE_TEAM_MEMBERS: + return { + ...state, + teamMembers: action.members + } + case SET_SELECTED_DAY: + return { + ...state, + selectedDay: action.selectedDay } case UPDATE_BLOCK_FRACTION: return { @@ -62,11 +74,6 @@ export default function reducer(state = initialState, action) { (setBlock) => setBlock.id === action.blockId ? { ...setBlock, blockFraction: action.blockFraction } : setBlock ) } - case CREATE_SET_BLOCK: - return { - ...state, - currentWeeklySetblocks: action.teamMember.weeklySetblocks - } case UPDATE_SET_BLOCK: return { ...state, @@ -239,6 +246,13 @@ export function setEditModeSchedule(editModeSchedule) { } } +export function setEnableSubmit(enableSubmit) { + return { + type: ENABLE_SUBMIT, + enableSubmit + } +} + export function updateBlockFraction(blockId, blockFraction) { return { type: UPDATE_BLOCK_FRACTION, From 28cfb60b375c285d80aa91db7e6abaa7a402d2b2 Mon Sep 17 00:00:00 2001 From: Federico Madoery Date: Wed, 9 Jan 2019 13:51:26 -0300 Subject: [PATCH 2/2] [WIP] Issue #22 UI Polish Remove "Set Team" component from Team Page and add a simple "Team" header On the TeamPage, make sure the color bubbles are vertically center-aligned On the TeamPage, make sure the team member names are vertically left-aligned On the TeamPage, remove the filter/sliders icon on the right On the SchedulePage, change "Hours Counter: X" text to "X work hours scheduled" On the SideBar, the small setblocks should be vertically left/center-aligned --- web/components/CommitBlock.jsx | 2 +- web/components/DayBlock.jsx | 6 +++--- web/components/SetBlock.jsx | 4 ++-- web/components/TeamLogo.jsx | 24 ------------------------ web/components/TeamMember.jsx | 11 +++-------- web/components/TeamPage.js | 6 ++++-- 6 files changed, 13 insertions(+), 40 deletions(-) delete mode 100644 web/components/TeamLogo.jsx diff --git a/web/components/CommitBlock.jsx b/web/components/CommitBlock.jsx index fb95f90..0cf0e48 100644 --- a/web/components/CommitBlock.jsx +++ b/web/components/CommitBlock.jsx @@ -82,7 +82,7 @@ class CommitBlock extends React.Component { size='10px' ml='-10rem' > - {' Hours Counter: ' + this.countHours()} + {this.countHours() + ' work hours scheduled'} diff --git a/web/components/DayBlock.jsx b/web/components/DayBlock.jsx index 5db3f7b..32c4aa2 100644 --- a/web/components/DayBlock.jsx +++ b/web/components/DayBlock.jsx @@ -18,7 +18,7 @@ class DayBlock extends React.Component { onClick(day)} > - + { // If you are waiting for the API to respond, it does not render !fetchingData && this.renderTinySetBlocks(currentWeeklySetblocks, day) } - + {day.getDate()} diff --git a/web/components/SetBlock.jsx b/web/components/SetBlock.jsx index 80f6c8a..6ddc0d3 100644 --- a/web/components/SetBlock.jsx +++ b/web/components/SetBlock.jsx @@ -283,8 +283,8 @@ class SetBlock extends React.Component { diff --git a/web/components/TeamLogo.jsx b/web/components/TeamLogo.jsx deleted file mode 100644 index de68630..0000000 --- a/web/components/TeamLogo.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; - -import Image from './Image'; -import Flex from './Flex'; - -export default class TeamLogo extends React.Component { - render() { - return ( - - - - - ); - } -} diff --git a/web/components/TeamMember.jsx b/web/components/TeamMember.jsx index c59ff4e..d38313f 100644 --- a/web/components/TeamMember.jsx +++ b/web/components/TeamMember.jsx @@ -23,10 +23,9 @@ export default class TeamMember extends React.Component { > {name} - - diff --git a/web/components/TeamPage.js b/web/components/TeamPage.js index c0ea101..51f6e7b 100644 --- a/web/components/TeamPage.js +++ b/web/components/TeamPage.js @@ -1,9 +1,9 @@ import React from 'react'; import TeamList from './TeamList'; -import TeamLogo from './TeamLogo'; import Header from './Header'; import Flex from './Flex'; +import Text from './Text'; export default class TeamPage extends React.Component { @@ -24,7 +24,9 @@ export default class TeamPage extends React.Component { >
- + + {'Team'} +