From e423f27b90dc00fcaa3d88b40822e6503c136570 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Fri, 5 Feb 2021 12:48:51 +0200 Subject: [PATCH 01/11] Add icon --- src/components/ListItem/index.js | 26 ++++++++++++++++---------- src/views/AcceptTasks/index.js | 2 ++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/components/ListItem/index.js b/src/components/ListItem/index.js index 9a4bf89..396d3b6 100644 --- a/src/components/ListItem/index.js +++ b/src/components/ListItem/index.js @@ -4,6 +4,7 @@ import { useHistory } from 'react-router-dom' import TaskIcon from 'assets/tasks/task.svg' import Actions from 'components/Actions' import FavouriteIcon from 'components/TaskActionsIcons' +import { MoreHorizontal } from 'react-feather' const StyledListItem = styled.div` position: relative; @@ -74,6 +75,7 @@ const ListItem = ({ onClick, userGuid, groupGuid, + showActionsIcon, }) => { const history = useHistory() @@ -91,16 +93,20 @@ const ListItem = ({ {showFavourite && } - {showActions && itemType && ( - - )} + {showActions && + itemType && + (showActionsIcon ? ( + + ) : ( + + ))} ) diff --git a/src/views/AcceptTasks/index.js b/src/views/AcceptTasks/index.js index 2399711..3688f0a 100644 --- a/src/views/AcceptTasks/index.js +++ b/src/views/AcceptTasks/index.js @@ -179,6 +179,8 @@ const AcceptTasks = () => { language="fi" icon={null} itemType={ITEM_TYPES.TASK} + showActions + showActionsIcon /> From 0ea1000986e8730f2f0164fe06133ef4c8f79d4a Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Fri, 5 Feb 2021 13:33:41 +0200 Subject: [PATCH 02/11] Show action when checkbox is checked --- src/views/AcceptTasks/index.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/views/AcceptTasks/index.js b/src/views/AcceptTasks/index.js index 3688f0a..b4312f6 100644 --- a/src/views/AcceptTasks/index.js +++ b/src/views/AcceptTasks/index.js @@ -105,6 +105,7 @@ const AcceptTasks = () => { const generalTranslations = useSelector(state => state.translations.yleiset) const [memberIdList, setMemberIdList] = React.useState(initialList) const [selectedGroup, setSelectedGroup] = React.useState() + const [isSelected, setSelected] = React.useState(false) if (!generalTranslations || !groupsData) return null function updateGroup(group) { @@ -116,6 +117,9 @@ const AcceptTasks = () => { } function handleChange(event) { + if (event.target.checked) { + setSelected(true) + } const editableList = memberIdList.slice(0) if (memberIdList.includes(event.target.value)) { const index = memberIdList.findIndex(id => id === event.target.value) @@ -127,6 +131,7 @@ const AcceptTasks = () => { } async function handleSubmit() { + setSelected(false) try { const data = { userIds: memberIdList, @@ -217,12 +222,14 @@ const AcceptTasks = () => { ) })} - - - - Lisää valituille - - + {isSelected ? ( + + + + Lisää valituille + + + ) : null} ) } From 8400df9941c18eb23fbf6d53b9db331ce54f8013 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Fri, 5 Feb 2021 16:28:41 +0200 Subject: [PATCH 03/11] Check if member has completed the task --- src/views/AcceptTasks/index.js | 52 +++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/src/views/AcceptTasks/index.js b/src/views/AcceptTasks/index.js index b4312f6..d70e1e3 100644 --- a/src/views/AcceptTasks/index.js +++ b/src/views/AcceptTasks/index.js @@ -8,7 +8,7 @@ import { AccordionItemButton, AccordionItemPanel, } from 'react-accessible-accordion' -import { X } from 'react-feather' +import { Check, X } from 'react-feather' import ListItem from 'components/ListItem' import { COMPLETION_STATUS, ITEM_TYPES } from 'consts' import { useSelector } from 'react-redux' @@ -105,9 +105,16 @@ const AcceptTasks = () => { const generalTranslations = useSelector(state => state.translations.yleiset) const [memberIdList, setMemberIdList] = React.useState(initialList) const [selectedGroup, setSelectedGroup] = React.useState() - const [isSelected, setSelected] = React.useState(false) if (!generalTranslations || !groupsData) return null + function isCompleted(memberTasks) { + const completedTasks = Object.keys(memberTasks).filter( + guid => memberTasks[guid] === COMPLETION_STATUS.COMPLETED + ) + const isCompleted = !!completedTasks.find(guid => guid === taskGuid) + + return isCompleted + } function updateGroup(group) { if (selectedGroup) { setSelectedGroup(null) @@ -117,9 +124,6 @@ const AcceptTasks = () => { } function handleChange(event) { - if (event.target.checked) { - setSelected(true) - } const editableList = memberIdList.slice(0) if (memberIdList.includes(event.target.value)) { const index = memberIdList.findIndex(id => id === event.target.value) @@ -131,7 +135,6 @@ const AcceptTasks = () => { } async function handleSubmit() { - setSelected(false) try { const data = { userIds: memberIdList, @@ -200,18 +203,29 @@ const AcceptTasks = () => { > {member.memberName} - + {isCompleted(member.memberTasks) ? ( + + ) : ( + + )} ) })} @@ -222,7 +236,7 @@ const AcceptTasks = () => { ) })} - {isSelected ? ( + {memberIdList.length > 0 ? ( From 03612bb458834ad87ddc0d6db2123c30586ef7e9 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Mon, 8 Feb 2021 13:01:30 +0200 Subject: [PATCH 04/11] Edit completion status --- src/views/AcceptTasks/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/AcceptTasks/index.js b/src/views/AcceptTasks/index.js index d70e1e3..50e1e68 100644 --- a/src/views/AcceptTasks/index.js +++ b/src/views/AcceptTasks/index.js @@ -140,20 +140,20 @@ const AcceptTasks = () => { userIds: memberIdList, } await acceptGroupMemeberTasks(data, taskGuid) - for (let id of memberIdList) { dispatch( updateGroupMemberTask({ task_guid: taskGuid, - user_guid: id, - completion_status: COMPLETION_STATUS.ACTIVE, - groupGuid: selectedGroup, + user_guid: Number(id), + completion_status: COMPLETION_STATUS.COMPLETED, + groupGuid: Number(selectedGroup), }) ) } } catch (e) { console.log(e) } + setMemberIdList(initialList) } return ( From 5db8d255ac362db4267f05c131bd93b534fff450 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Mon, 8 Feb 2021 17:34:26 +0200 Subject: [PATCH 05/11] Add group component and edit selection --- src/views/AcceptTasks/group.js | 250 +++++++++++++++++++++++++++++++++ src/views/AcceptTasks/index.js | 192 +------------------------ 2 files changed, 255 insertions(+), 187 deletions(-) create mode 100644 src/views/AcceptTasks/group.js diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js new file mode 100644 index 0000000..340777f --- /dev/null +++ b/src/views/AcceptTasks/group.js @@ -0,0 +1,250 @@ +import React from 'react' +import styled, { keyframes } from 'styled-components' +import { useParams } from 'react-router-dom' +import { + Accordion, + AccordionItem, + AccordionItemHeading, + AccordionItemButton, + AccordionItemPanel, +} from 'react-accessible-accordion' +import { Check } from 'react-feather' +import ListItem from 'components/ListItem' +import { COMPLETION_STATUS, ITEM_TYPES } from 'consts' +import { useSelector } from 'react-redux' +import { StyledAcceptIcon } from '../../components/TaskActionsIcons' +import { useDispatch } from 'react-redux' +import { updateGroupMemberTask } from '../../redux/actionCreators' +import { acceptGroupMemeberTasks } from '../../api' + +const StyledAcceptTasks = styled.div` + height: 100%; + background-color: ${({ theme }) => theme.color.background}; + pointer-events: all; + overflow: auto; +` + +const Subheading = styled.h3` + margin: 0; + font-size: 18px; + font-weight: normal; +` + +const Content = styled.div` + padding: 1rem; + + > ${Subheading} { + margin-bottom: 1rem; + } +` + +const AcceptTasksAction = styled.div` + position: fixed; + bottom: 0; + left: 0; + box-sizing: border-box; + width: 100%; + padding: 4rem; + z-index: 1; + animation: ${keyframes` + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + `} 200ms linear; +` + +const ActivityItem = styled.div` + display: flex; + align-items: center; + + > span { + padding: 1rem; + } + + :last-child { + justify-content: center; + + > span { + padding-top: 2rem; + } + } +` + +const StyledListItem = styled.div` + padding: 0 3.5rem 2rem 3.5rem; + text-decoration: none; +` + +const initialList = [] + +const getInitialCheckboxData = group => + group.members.map(member => ({ + selected: false, + name: member.memberName, + id: member.memberId, + tasks: member.memberTasks, + })) + +const Group = ({ group }) => { + const dispatch = useDispatch() + const { taskGuid } = useParams() + const groupsData = useSelector(state => state.user.userGroups) + const generalTranslations = useSelector(state => state.translations.yleiset) + const [memberIdList, setMemberIdList] = React.useState(initialList) + const [selectedGroup, setSelectedGroup] = React.useState() + const [checkboxData, setCheckboxData] = React.useState( + getInitialCheckboxData(group) + ) + if (!generalTranslations || !groupsData) return null + + const groupName = group.name + const ageGroup = group.ageGroup + const ageGroupId = group.id + const title = '' + groupName + ' / ' + ageGroup + + function isCompleted(memberTasks) { + const completedTasks = Object.keys(memberTasks).filter( + guid => memberTasks[guid] === COMPLETION_STATUS.COMPLETED + ) + const isCompleted = !!completedTasks.find(guid => guid === taskGuid) + + return isCompleted + } + function updateGroup(group) { + if (selectedGroup) { + setSelectedGroup(null) + } else { + setSelectedGroup(group) + } + } + + function handleChange(event) { + handleCheckboxSelection(Number(event.target.value), event.target.checked) + const editableList = memberIdList.slice(0) + if (memberIdList.includes(event.target.value)) { + const index = memberIdList.findIndex(id => id === event.target.value) + editableList.splice(index, 1) + } else { + editableList.push(event.target.value) + } + setMemberIdList(editableList) + } + + async function handleSubmit() { + try { + const data = { + userIds: memberIdList, + } + await acceptGroupMemeberTasks(data, taskGuid) + for (let id of memberIdList) { + dispatch( + updateGroupMemberTask({ + task_guid: taskGuid, + user_guid: Number(id), + completion_status: COMPLETION_STATUS.COMPLETED, + groupGuid: Number(selectedGroup), + }) + ) + } + } catch (e) { + console.log(e) + } + setMemberIdList(initialList) + } + + function handleCheckboxSelection(memberId, isChecked) { + const editableCheckboxData = checkboxData + editableCheckboxData.map(member => { + if (member.id === memberId && isChecked) { + member.selected = true + } + if (member.id === memberId && !isChecked) { + member.selected = false + } + }) + + setCheckboxData(editableCheckboxData) + } + + return ( + + + updateGroup(ageGroupId)} + key={ageGroupId} + > + + + + + + + + + {group.members.map(member => { + return ( + + + {isCompleted(member.memberTasks) ? ( + + ) : ( + + )} + + ) + })} + + + + + + {memberIdList.length > 0 ? ( + + + + Lisää valituille + + + ) : null} + + ) +} + +export default Group diff --git a/src/views/AcceptTasks/index.js b/src/views/AcceptTasks/index.js index 50e1e68..ef04e83 100644 --- a/src/views/AcceptTasks/index.js +++ b/src/views/AcceptTasks/index.js @@ -1,22 +1,10 @@ import React from 'react' -import styled, { keyframes } from 'styled-components' -import { useHistory, useParams } from 'react-router-dom' -import { - Accordion, - AccordionItem, - AccordionItemHeading, - AccordionItemButton, - AccordionItemPanel, -} from 'react-accessible-accordion' -import { Check, X } from 'react-feather' -import ListItem from 'components/ListItem' -import { COMPLETION_STATUS, ITEM_TYPES } from 'consts' +import styled from 'styled-components' +import { useHistory } from 'react-router-dom' +import { X } from 'react-feather' import { useSelector } from 'react-redux' import { determineLanguageFromUrl, getTermInLanguage } from 'helpers' -import { StyledAcceptIcon } from '../../components/TaskActionsIcons' -import { useDispatch } from 'react-redux' -import { updateGroupMemberTask } from '../../redux/actionCreators' -import { acceptGroupMemeberTasks } from '../../api' +import Group from './group' const StyledAcceptTasks = styled.div` height: 100%; @@ -53,109 +41,13 @@ const Content = styled.div` margin-bottom: 1rem; } ` - -const AcceptTasksAction = styled.div` - position: fixed; - bottom: 0; - left: 0; - box-sizing: border-box; - width: 100%; - padding: 4rem; - z-index: 1; - animation: ${keyframes` - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - `} 200ms linear; -` - -const ActivityItem = styled.div` - display: flex; - align-items: center; - - > span { - padding: 1rem; - } - - :last-child { - justify-content: center; - - > span { - padding-top: 2rem; - } - } -` - -const StyledListItem = styled.div` - padding: 0 3.5rem 2rem 3.5rem; - text-decoration: none; -` - -const initialList = [] - const AcceptTasks = () => { - const dispatch = useDispatch() - const { taskGuid } = useParams() const history = useHistory() const language = determineLanguageFromUrl(window.location) const groupsData = useSelector(state => state.user.userGroups) const generalTranslations = useSelector(state => state.translations.yleiset) - const [memberIdList, setMemberIdList] = React.useState(initialList) - const [selectedGroup, setSelectedGroup] = React.useState() if (!generalTranslations || !groupsData) return null - function isCompleted(memberTasks) { - const completedTasks = Object.keys(memberTasks).filter( - guid => memberTasks[guid] === COMPLETION_STATUS.COMPLETED - ) - const isCompleted = !!completedTasks.find(guid => guid === taskGuid) - - return isCompleted - } - function updateGroup(group) { - if (selectedGroup) { - setSelectedGroup(null) - } else { - setSelectedGroup(group) - } - } - - function handleChange(event) { - const editableList = memberIdList.slice(0) - if (memberIdList.includes(event.target.value)) { - const index = memberIdList.findIndex(id => id === event.target.value) - editableList.splice(index, 1) - } else { - editableList.push(event.target.value) - } - setMemberIdList(editableList) - } - - async function handleSubmit() { - try { - const data = { - userIds: memberIdList, - } - await acceptGroupMemeberTasks(data, taskGuid) - for (let id of memberIdList) { - dispatch( - updateGroupMemberTask({ - task_guid: taskGuid, - user_guid: Number(id), - completion_status: COMPLETION_STATUS.COMPLETED, - groupGuid: Number(selectedGroup), - }) - ) - } - } catch (e) { - console.log(e) - } - setMemberIdList(initialList) - } - return (
@@ -167,83 +59,9 @@ const AcceptTasks = () => { {getTermInLanguage(generalTranslations, 'own_groups', language)} {groupsData.map(group => { - const groupName = group.name - const ageGroup = group.ageGroup - const ageGroupId = group.id - const title = '' + groupName + ' / ' + ageGroup - return ( - updateGroup(ageGroupId)} - key={ageGroupId} - > - - - - - - - - - {group.members.map(member => { - return ( - - - {isCompleted(member.memberTasks) ? ( - - ) : ( - - )} - - ) - })} - - - - - ) + return })} - {memberIdList.length > 0 ? ( - - - - Lisää valituille - - - ) : null} ) } From 771250be8bbf003711d944f53e6524c3f7e85f7d Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Tue, 9 Feb 2021 17:24:47 +0200 Subject: [PATCH 06/11] Add select all --- src/views/AcceptTasks/group.js | 61 +++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js index 340777f..bda40fa 100644 --- a/src/views/AcceptTasks/group.js +++ b/src/views/AcceptTasks/group.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import styled, { keyframes } from 'styled-components' import { useParams } from 'react-router-dom' import { @@ -98,6 +98,8 @@ const Group = ({ group }) => { const [checkboxData, setCheckboxData] = React.useState( getInitialCheckboxData(group) ) + useEffect(() => setCheckboxData(getInitialCheckboxData(group)), [groupsData]) + if (!generalTranslations || !groupsData) return null const groupName = group.name @@ -122,14 +124,21 @@ const Group = ({ group }) => { } function handleChange(event) { - handleCheckboxSelection(Number(event.target.value), event.target.checked) - const editableList = memberIdList.slice(0) - if (memberIdList.includes(event.target.value)) { - const index = memberIdList.findIndex(id => id === event.target.value) - editableList.splice(index, 1) + if (event.target.name === 'checkAll') { + checkboxData.map(member => { + handleCheckboxSelection(Number(member.id), event.target.checked) + }) } else { - editableList.push(event.target.value) + handleCheckboxSelection(Number(event.target.value), event.target.checked) } + + const editableList = checkboxData.reduce((idList, data) => { + if (data.selected) { + idList.push(data.id.toString()) + } + return idList + }, []) + setMemberIdList(editableList) } @@ -165,7 +174,6 @@ const Group = ({ group }) => { member.selected = false } }) - setCheckboxData(editableCheckboxData) } @@ -194,16 +202,38 @@ const Group = ({ group }) => { - {group.members.map(member => { + + + + + {checkboxData.map(member => { return ( - + - {isCompleted(member.memberTasks) ? ( + {isCompleted(member.tasks) ? ( { /> ) : ( { height: '1.3rem', }} type="checkbox" - value={member.memberId} + value={member.id} onChange={handleChange} + checked={member.selected} /> )} From e83e26d865d44f8c8b99bf61cbf2e1c2985eccc2 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Wed, 24 Feb 2021 13:05:43 +0200 Subject: [PATCH 07/11] Add hr --- src/views/AcceptTasks/group.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js index bda40fa..7c23cf0 100644 --- a/src/views/AcceptTasks/group.js +++ b/src/views/AcceptTasks/group.js @@ -78,6 +78,10 @@ const StyledListItem = styled.div` text-decoration: none; ` +const HorizontalLine = styled.hr` + margin: 0 3.5rem 2.5rem 3.5rem; +` + const initialList = [] const getInitialCheckboxData = group => @@ -207,7 +211,6 @@ const Group = ({ group }) => { style={{ float: 'left', margin: 0 }} htmlFor={group.id} > - {' '} Valitse kaikki { onChange={handleChange} /> + {checkboxData.map(member => { return ( From 13d9fb17d9d11a8ecaf5a99137c5a174d66daf61 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Thu, 25 Feb 2021 10:02:16 +0200 Subject: [PATCH 08/11] Remove padding and add missing dependency to useEffect --- src/views/AcceptTasks/group.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js index 7c23cf0..93f1908 100644 --- a/src/views/AcceptTasks/group.js +++ b/src/views/AcceptTasks/group.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react' +import React, { useCallback, useEffect } from 'react' import styled, { keyframes } from 'styled-components' import { useParams } from 'react-router-dom' import { @@ -31,8 +31,6 @@ const Subheading = styled.h3` ` const Content = styled.div` - padding: 1rem; - > ${Subheading} { margin-bottom: 1rem; } @@ -102,7 +100,10 @@ const Group = ({ group }) => { const [checkboxData, setCheckboxData] = React.useState( getInitialCheckboxData(group) ) - useEffect(() => setCheckboxData(getInitialCheckboxData(group)), [groupsData]) + useEffect(() => setCheckboxData(getInitialCheckboxData(group)), [ + groupsData, + group, + ]) if (!generalTranslations || !groupsData) return null From b3be178cf85c32e3867e9cbf4028a77a8cd0f704 Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Thu, 25 Feb 2021 10:06:00 +0200 Subject: [PATCH 09/11] Remove unused import --- src/views/AcceptTasks/group.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js index 93f1908..78721ca 100644 --- a/src/views/AcceptTasks/group.js +++ b/src/views/AcceptTasks/group.js @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect } from 'react' +import React, { useEffect } from 'react' import styled, { keyframes } from 'styled-components' import { useParams } from 'react-router-dom' import { From 92f22e8b4124f4d150d8b41a9c337fa575d3935b Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Thu, 25 Feb 2021 10:23:34 +0200 Subject: [PATCH 10/11] Fix functions --- src/views/AcceptTasks/group.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js index 78721ca..984bcb5 100644 --- a/src/views/AcceptTasks/group.js +++ b/src/views/AcceptTasks/group.js @@ -131,7 +131,7 @@ const Group = ({ group }) => { function handleChange(event) { if (event.target.name === 'checkAll') { checkboxData.map(member => { - handleCheckboxSelection(Number(member.id), event.target.checked) + return handleCheckboxSelection(Number(member.id), event.target.checked) }) } else { handleCheckboxSelection(Number(event.target.value), event.target.checked) @@ -178,8 +178,8 @@ const Group = ({ group }) => { if (member.id === memberId && !isChecked) { member.selected = false } + return setCheckboxData(editableCheckboxData) }) - setCheckboxData(editableCheckboxData) } return ( From 0c69367d4504a3f137b9351f7ce3c4b73461403d Mon Sep 17 00:00:00 2001 From: Kaisa Korpela Date: Thu, 25 Feb 2021 10:54:19 +0200 Subject: [PATCH 11/11] Refactor checkbox styles --- src/views/AcceptTasks/group.js | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/views/AcceptTasks/group.js b/src/views/AcceptTasks/group.js index 984bcb5..9604311 100644 --- a/src/views/AcceptTasks/group.js +++ b/src/views/AcceptTasks/group.js @@ -182,6 +182,13 @@ const Group = ({ group }) => { }) } + const CHECK_STYLE = { + float: 'right', + margin: 0, + width: '1.3rem', + height: '1.3rem', + } + return ( @@ -218,12 +225,7 @@ const Group = ({ group }) => { id={group.id} value="checkAll" name="checkAll" - style={{ - float: 'right', - margin: 0, - width: '1.3rem', - height: '1.3rem', - }} + style={CHECK_STYLE} type="checkbox" onChange={handleChange} /> @@ -239,24 +241,11 @@ const Group = ({ group }) => { {member.name} {isCompleted(member.tasks) ? ( - + ) : (