feat(MyTasks): allow filtering by task complete status

This commit is contained in:
Jordan Knott 2021-01-03 17:04:15 -06:00
parent a1c9251a1f
commit f051bebd48
8 changed files with 343 additions and 33 deletions

View File

@ -0,0 +1,151 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { Checkmark } from 'shared/icons';
import { TaskStatusFilter, TaskStatus, TaskSince } from 'shared/components/Lists';
import { MyTasksStatus } from 'shared/generated/graphql';
import { Popup } from 'shared/components/PopupMenu';
export const ActionsList = styled.ul`
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
`;
export const ActionExtraMenuContainer = styled.div`
visibility: hidden;
position: absolute;
left: 100%;
top: -4px;
padding-left: 2px;
width: 100%;
`;
export const ActionItem = styled.li`
position: relative;
padding-left: 4px;
padding-right: 4px;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
cursor: pointer;
display: flex;
align-items: center;
font-size: 14px;
&:hover {
background: ${props => props.theme.colors.primary};
}
&:hover ${ActionExtraMenuContainer} {
visibility: visible;
}
`;
export const ActionTitle = styled.span`
margin-left: 20px;
`;
export const ActionExtraMenu = styled.ul`
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
padding: 5px;
padding-top: 8px;
border-radius: 5px;
box-shadow: 0 5px 25px 0 rgba(0, 0, 0, 0.1);
color: #c2c6dc;
background: #262c49;
border: 1px solid rgba(0, 0, 0, 0.1);
border-color: #414561;
`;
export const ActionExtraMenuItem = styled.li`
position: relative;
padding-left: 4px;
padding-right: 4px;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
cursor: pointer;
display: flex;
align-items: center;
font-size: 14px;
&:hover {
background: rgb(${props => props.theme.colors.primary});
}
`;
const ActionExtraMenuSeparator = styled.li`
color: ${props => props.theme.colors.text.primary};
font-size: 12px;
padding-left: 4px;
padding-right: 4px;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
`;
const ActiveIcon = styled(Checkmark)`
position: absolute;
`;
type MyTasksStatusProps = {
status: MyTasksStatus;
onChangeStatus: (status: MyTasksStatus) => void;
};
const MyTasksStatusPopup: React.FC<MyTasksStatusProps> = ({ status: initialStatus, onChangeStatus }) => {
const [status, setStatus] = useState(initialStatus);
const handleStatusChange = (f: MyTasksStatus) => {
setStatus(f);
onChangeStatus(f);
};
return (
<Popup tab={0} title={null}>
<ActionsList>
<ActionItem onClick={() => handleStatusChange(MyTasksStatus.Incomplete)}>
{status === MyTasksStatus.Incomplete && <ActiveIcon width={12} height={12} />}
<ActionTitle>Incomplete Tasks</ActionTitle>
</ActionItem>
<ActionItem>
{status !== MyTasksStatus.Incomplete && status !== MyTasksStatus.All && <ActiveIcon width={12} height={12} />}
<ActionTitle>Compelete Tasks</ActionTitle>
<ActionExtraMenuContainer>
<ActionExtraMenu>
<ActionExtraMenuItem onClick={() => handleStatusChange(MyTasksStatus.CompleteAll)}>
{status === MyTasksStatus.CompleteAll && <ActiveIcon width={12} height={12} />}
<ActionTitle>All completed tasks</ActionTitle>
</ActionExtraMenuItem>
<ActionExtraMenuSeparator>Marked complete since</ActionExtraMenuSeparator>
<ActionExtraMenuItem onClick={() => handleStatusChange(MyTasksStatus.CompleteToday)}>
{status === MyTasksStatus.CompleteToday && <ActiveIcon width={12} height={12} />}
<ActionTitle>Today</ActionTitle>
</ActionExtraMenuItem>
<ActionExtraMenuItem onClick={() => handleStatusChange(MyTasksStatus.CompleteYesterday)}>
{status === MyTasksStatus.CompleteYesterday && <ActiveIcon width={12} height={12} />}
<ActionTitle>Yesterday</ActionTitle>
</ActionExtraMenuItem>
<ActionExtraMenuItem onClick={() => handleStatusChange(MyTasksStatus.CompleteOneWeek)}>
{status === MyTasksStatus.CompleteOneWeek && <ActiveIcon width={12} height={12} />}
<ActionTitle>1 week</ActionTitle>
</ActionExtraMenuItem>
<ActionExtraMenuItem onClick={() => handleStatusChange(MyTasksStatus.CompleteTwoWeek)}>
{status === MyTasksStatus.CompleteTwoWeek && <ActiveIcon width={12} height={12} />}
<ActionTitle>2 weeks</ActionTitle>
</ActionExtraMenuItem>
<ActionExtraMenuItem onClick={() => handleStatusChange(MyTasksStatus.CompleteThreeWeek)}>
{status === MyTasksStatus.CompleteThreeWeek && <ActiveIcon width={12} height={12} />}
<ActionTitle>3 weeks</ActionTitle>
</ActionExtraMenuItem>
</ActionExtraMenu>
</ActionExtraMenuContainer>
</ActionItem>
<ActionItem onClick={() => handleStatusChange(MyTasksStatus.All)}>
{status === MyTasksStatus.All && <ActiveIcon width={12} height={12} />}
<ActionTitle>All Tasks</ActionTitle>
</ActionItem>
</ActionsList>
</Popup>
);
};
export default MyTasksStatusPopup;

View File

@ -19,7 +19,7 @@ import { usePopup, Popup } from 'shared/components/PopupMenu';
import updateApolloCache from 'shared/utils/cache'; import updateApolloCache from 'shared/utils/cache';
import produce from 'immer'; import produce from 'immer';
import NOOP from 'shared/utils/noop'; import NOOP from 'shared/utils/noop';
import { Sort, Cogs, CaretDown, CheckCircle, CaretRight } from 'shared/icons'; import { Sort, Cogs, CaretDown, CheckCircle, CaretRight, CheckCircleOutline } from 'shared/icons';
import Select from 'react-select'; import Select from 'react-select';
import { editorColourStyles } from 'shared/components/Select'; import { editorColourStyles } from 'shared/components/Select';
import useOnOutsideClick from 'shared/hooks/onOutsideClick'; import useOnOutsideClick from 'shared/hooks/onOutsideClick';
@ -27,12 +27,36 @@ import DueDateManager from 'shared/components/DueDateManager';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import useStickyState from 'shared/hooks/useStickyState'; import useStickyState from 'shared/hooks/useStickyState';
import MyTasksSortPopup from './MyTasksSort'; import MyTasksSortPopup from './MyTasksSort';
import MyTasksStatusPopup from './MyTasksStatus';
import TaskEntry from './TaskEntry'; import TaskEntry from './TaskEntry';
type TaskRouteProps = { type TaskRouteProps = {
taskID: string; taskID: string;
}; };
function prettyStatus(status: MyTasksStatus) {
switch (status) {
case MyTasksStatus.All:
return 'All tasks';
case MyTasksStatus.Incomplete:
return 'Incomplete tasks';
case MyTasksStatus.CompleteAll:
return 'All completed tasks';
case MyTasksStatus.CompleteToday:
return 'Completed tasks: today';
case MyTasksStatus.CompleteYesterday:
return 'Completed tasks: yesterday';
case MyTasksStatus.CompleteOneWeek:
return 'Completed tasks: 1 week';
case MyTasksStatus.CompleteTwoWeek:
return 'Completed tasks: 2 weeks';
case MyTasksStatus.CompleteThreeWeek:
return 'Completed tasks: 3 weeks';
default:
return 'unknown tasks';
}
}
function prettySort(sort: MyTasksSort) { function prettySort(sort: MyTasksSort) {
if (sort === MyTasksSort.None) { if (sort === MyTasksSort.None) {
return 'Sort'; return 'Sort';
@ -492,7 +516,10 @@ const Projects = () => {
{ sort: MyTasksSort.None, status: MyTasksStatus.All }, { sort: MyTasksSort.None, status: MyTasksStatus.All },
'my_tasks_filter', 'my_tasks_filter',
); );
const { data } = useMyTasksQuery({ variables: { sort: filters.sort, status: filters.status } }); const { data } = useMyTasksQuery({
variables: { sort: filters.sort, status: filters.status },
fetchPolicy: 'cache-and-network',
});
const [dateEditor, setDateEditor] = useState<DateEditorState>({ open: false, pos: null, task: null }); const [dateEditor, setDateEditor] = useState<DateEditorState>({ open: false, pos: null, task: null });
const onEditDueDate = (task: Task, $target: React.RefObject<HTMLElement>) => { const onEditDueDate = (task: Task, $target: React.RefObject<HTMLElement>) => {
if ($target && $target.current && data) { if ($target && $target.current && data) {
@ -524,7 +551,7 @@ const Projects = () => {
}); });
} }
}; };
const { showPopup } = usePopup(); const { showPopup, hidePopup } = usePopup();
const [updateTaskDueDate] = useUpdateTaskDueDateMutation(); const [updateTaskDueDate] = useUpdateTaskDueDateMutation();
const $editorContents = useRef<HTMLDivElement>(null); const $editorContents = useRef<HTMLDivElement>(null);
const $dateContents = useRef<HTMLDivElement>(null); const $dateContents = useRef<HTMLDivElement>(null);
@ -653,9 +680,23 @@ const Projects = () => {
<ProjectBar> <ProjectBar>
<ProjectActions /> <ProjectActions />
<ProjectActions> <ProjectActions>
<ProjectAction disabled> <ProjectAction
<CheckCircle width={13} height={13} /> onClick={$target => {
<ProjectActionText>All Tasks</ProjectActionText> showPopup(
$target,
<MyTasksStatusPopup
status={filters.status}
onChangeStatus={status => {
setFilters(prev => ({ ...prev, status }));
hidePopup();
}}
/>,
{ width: 185 },
);
}}
>
<CheckCircleOutline width={13} height={13} />
<ProjectActionText>{prettyStatus(filters.status)}</ProjectActionText>
</ProjectAction> </ProjectAction>
<ProjectAction <ProjectAction
onClick={$target => { onClick={$target => {
@ -663,8 +704,12 @@ const Projects = () => {
$target, $target,
<MyTasksSortPopup <MyTasksSortPopup
sort={filters.sort} sort={filters.sort}
onChangeSort={sort => setFilters(prev => ({ ...prev, sort }))} onChangeSort={sort => {
setFilters(prev => ({ ...prev, sort }));
hidePopup();
}}
/>, />,
{ width: 185 },
); );
}} }}
> >

1
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/go-chi/chi v3.3.2+incompatible github.com/go-chi/chi v3.3.2+incompatible
github.com/golang-migrate/migrate/v4 v4.11.0 github.com/golang-migrate/migrate/v4 v4.11.0
github.com/google/uuid v1.1.1 github.com/google/uuid v1.1.1
github.com/jinzhu/now v1.1.1
github.com/jmoiron/sqlx v1.2.0 github.com/jmoiron/sqlx v1.2.0
github.com/lib/pq v1.3.0 github.com/lib/pq v1.3.0
github.com/lithammer/fuzzysearch v1.1.0 github.com/lithammer/fuzzysearch v1.1.0

2
go.sum
View File

@ -338,6 +338,8 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 h1:xqgexXAGQgY3HAjNPSaCqn5Aahbo5TKsmhp8VRfr1iQ= github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 h1:xqgexXAGQgY3HAjNPSaCqn5Aahbo5TKsmhp8VRfr1iQ=
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=

View File

@ -69,8 +69,8 @@ type Querier interface {
GetAllUserAccounts(ctx context.Context) ([]UserAccount, error) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
GetAllVisibleProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error) GetAllVisibleProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error)
GetAssignedMembersForTask(ctx context.Context, taskID uuid.UUID) ([]TaskAssigned, error) GetAssignedMembersForTask(ctx context.Context, taskID uuid.UUID) ([]TaskAssigned, error)
GetAssignedTasksDueDateForUserID(ctx context.Context, userID uuid.UUID) ([]Task, error) GetAssignedTasksDueDateForUserID(ctx context.Context, arg GetAssignedTasksDueDateForUserIDParams) ([]Task, error)
GetAssignedTasksProjectForUserID(ctx context.Context, userID uuid.UUID) ([]Task, error) GetAssignedTasksProjectForUserID(ctx context.Context, arg GetAssignedTasksProjectForUserIDParams) ([]Task, error)
GetCommentsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskComment, error) GetCommentsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskComment, error)
GetConfirmTokenByEmail(ctx context.Context, email string) (UserAccountConfirmToken, error) GetConfirmTokenByEmail(ctx context.Context, email string) (UserAccountConfirmToken, error)
GetConfirmTokenByID(ctx context.Context, confirmTokenID uuid.UUID) (UserAccountConfirmToken, error) GetConfirmTokenByID(ctx context.Context, confirmTokenID uuid.UUID) (UserAccountConfirmToken, error)
@ -99,7 +99,7 @@ type Querier interface {
GetProjectMembersForProjectID(ctx context.Context, projectID uuid.UUID) ([]ProjectMember, error) GetProjectMembersForProjectID(ctx context.Context, projectID uuid.UUID) ([]ProjectMember, error)
GetProjectRolesForUserID(ctx context.Context, userID uuid.UUID) ([]GetProjectRolesForUserIDRow, error) GetProjectRolesForUserID(ctx context.Context, userID uuid.UUID) ([]GetProjectRolesForUserIDRow, error)
GetProjectsForInvitedMember(ctx context.Context, email string) ([]uuid.UUID, error) GetProjectsForInvitedMember(ctx context.Context, email string) ([]uuid.UUID, error)
GetRecentlyAssignedTaskForUserID(ctx context.Context, userID uuid.UUID) ([]Task, error) GetRecentlyAssignedTaskForUserID(ctx context.Context, arg GetRecentlyAssignedTaskForUserIDParams) ([]Task, error)
GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error) GetRefreshTokenByID(ctx context.Context, tokenID uuid.UUID) (RefreshToken, error)
GetRoleForProjectMemberByUserID(ctx context.Context, arg GetRoleForProjectMemberByUserIDParams) (Role, error) GetRoleForProjectMemberByUserID(ctx context.Context, arg GetRoleForProjectMemberByUserIDParams) (Role, error)
GetRoleForTeamMember(ctx context.Context, arg GetRoleForTeamMemberParams) (Role, error) GetRoleForTeamMember(ctx context.Context, arg GetRoleForTeamMemberParams) (Role, error)

View File

@ -59,14 +59,25 @@ UPDATE task_comment SET message = $2, updated_at = $3 WHERE task_comment_id = $1
-- name: GetRecentlyAssignedTaskForUserID :many -- name: GetRecentlyAssignedTaskForUserID :many
SELECT task.* FROM task_assigned INNER JOIN SELECT task.* FROM task_assigned INNER JOIN
task ON task.task_id = task_assigned.task_id WHERE user_id = $1 ORDER BY task_assigned.assigned_date DESC; task ON task.task_id = task_assigned.task_id WHERE user_id = $1
AND $4::boolean = true OR (
$4::boolean = false AND complete = $2 AND (
$2 = false OR ($2 = true AND completed_at > $3)
)
)
ORDER BY task_assigned.assigned_date DESC;
-- name: GetAssignedTasksProjectForUserID :many -- name: GetAssignedTasksProjectForUserID :many
SELECT task.* FROM task_assigned SELECT task.* FROM task_assigned
INNER JOIN task ON task.task_id = task_assigned.task_id INNER JOIN task ON task.task_id = task_assigned.task_id
INNER JOIN task_group ON task_group.task_group_id = task.task_group_id INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
WHERE user_id = $1 WHERE user_id = $1
ORDER BY task_group.project_id DESC, task_assigned.assigned_date DESC; AND $4::boolean = true OR (
$4::boolean = false AND complete = $2 AND (
$2 = false OR ($2 = true AND completed_at > $3)
)
)
ORDER BY task_group.project_id DESC, task_assigned.assigned_date DESC;
-- name: GetProjectIdMappings :many -- name: GetProjectIdMappings :many
SELECT project_id, task_id FROM task SELECT project_id, task_id FROM task
@ -75,7 +86,12 @@ INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
-- name: GetAssignedTasksDueDateForUserID :many -- name: GetAssignedTasksDueDateForUserID :many
SELECT task.* FROM task_assigned SELECT task.* FROM task_assigned
INNER JOIN task ON task.task_id = task_assigned.task_id INNER JOIN task ON task.task_id = task_assigned.task_id
INNER JOIN task_group ON task_group.task_group_id = task.task_group_id INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
WHERE user_id = $1 WHERE user_id = $1
ORDER BY task.due_date DESC, task_group.project_id DESC; AND $4::boolean = true OR (
$4::boolean = false AND complete = $2 AND (
$2 = false OR ($2 = true AND completed_at > $3)
)
)
ORDER BY task.due_date DESC, task_group.project_id DESC;

View File

@ -200,14 +200,31 @@ func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) {
const getAssignedTasksDueDateForUserID = `-- name: GetAssignedTasksDueDateForUserID :many const getAssignedTasksDueDateForUserID = `-- name: GetAssignedTasksDueDateForUserID :many
SELECT task.task_id, task.task_group_id, task.created_at, task.name, task.position, task.description, task.due_date, task.complete, task.completed_at, task.has_time FROM task_assigned SELECT task.task_id, task.task_group_id, task.created_at, task.name, task.position, task.description, task.due_date, task.complete, task.completed_at, task.has_time FROM task_assigned
INNER JOIN task ON task.task_id = task_assigned.task_id INNER JOIN task ON task.task_id = task_assigned.task_id
INNER JOIN task_group ON task_group.task_group_id = task.task_group_id INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
WHERE user_id = $1 WHERE user_id = $1
ORDER BY task.due_date DESC, task_group.project_id DESC AND $4::boolean = true OR (
$4::boolean = false AND complete = $2 AND (
$2 = false OR ($2 = true AND completed_at > $3)
)
)
ORDER BY task.due_date DESC, task_group.project_id DESC
` `
func (q *Queries) GetAssignedTasksDueDateForUserID(ctx context.Context, userID uuid.UUID) ([]Task, error) { type GetAssignedTasksDueDateForUserIDParams struct {
rows, err := q.db.QueryContext(ctx, getAssignedTasksDueDateForUserID, userID) UserID uuid.UUID `json:"user_id"`
Complete bool `json:"complete"`
CompletedAt sql.NullTime `json:"completed_at"`
Column4 bool `json:"column_4"`
}
func (q *Queries) GetAssignedTasksDueDateForUserID(ctx context.Context, arg GetAssignedTasksDueDateForUserIDParams) ([]Task, error) {
rows, err := q.db.QueryContext(ctx, getAssignedTasksDueDateForUserID,
arg.UserID,
arg.Complete,
arg.CompletedAt,
arg.Column4,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -242,14 +259,31 @@ func (q *Queries) GetAssignedTasksDueDateForUserID(ctx context.Context, userID u
const getAssignedTasksProjectForUserID = `-- name: GetAssignedTasksProjectForUserID :many const getAssignedTasksProjectForUserID = `-- name: GetAssignedTasksProjectForUserID :many
SELECT task.task_id, task.task_group_id, task.created_at, task.name, task.position, task.description, task.due_date, task.complete, task.completed_at, task.has_time FROM task_assigned SELECT task.task_id, task.task_group_id, task.created_at, task.name, task.position, task.description, task.due_date, task.complete, task.completed_at, task.has_time FROM task_assigned
INNER JOIN task ON task.task_id = task_assigned.task_id INNER JOIN task ON task.task_id = task_assigned.task_id
INNER JOIN task_group ON task_group.task_group_id = task.task_group_id INNER JOIN task_group ON task_group.task_group_id = task.task_group_id
WHERE user_id = $1 WHERE user_id = $1
ORDER BY task_group.project_id DESC, task_assigned.assigned_date DESC AND $4::boolean = true OR (
$4::boolean = false AND complete = $2 AND (
$2 = false OR ($2 = true AND completed_at > $3)
)
)
ORDER BY task_group.project_id DESC, task_assigned.assigned_date DESC
` `
func (q *Queries) GetAssignedTasksProjectForUserID(ctx context.Context, userID uuid.UUID) ([]Task, error) { type GetAssignedTasksProjectForUserIDParams struct {
rows, err := q.db.QueryContext(ctx, getAssignedTasksProjectForUserID, userID) UserID uuid.UUID `json:"user_id"`
Complete bool `json:"complete"`
CompletedAt sql.NullTime `json:"completed_at"`
Column4 bool `json:"column_4"`
}
func (q *Queries) GetAssignedTasksProjectForUserID(ctx context.Context, arg GetAssignedTasksProjectForUserIDParams) ([]Task, error) {
rows, err := q.db.QueryContext(ctx, getAssignedTasksProjectForUserID,
arg.UserID,
arg.Complete,
arg.CompletedAt,
arg.Column4,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -366,11 +400,29 @@ func (q *Queries) GetProjectIdMappings(ctx context.Context, dollar_1 []uuid.UUID
const getRecentlyAssignedTaskForUserID = `-- name: GetRecentlyAssignedTaskForUserID :many const getRecentlyAssignedTaskForUserID = `-- name: GetRecentlyAssignedTaskForUserID :many
SELECT task.task_id, task.task_group_id, task.created_at, task.name, task.position, task.description, task.due_date, task.complete, task.completed_at, task.has_time FROM task_assigned INNER JOIN SELECT task.task_id, task.task_group_id, task.created_at, task.name, task.position, task.description, task.due_date, task.complete, task.completed_at, task.has_time FROM task_assigned INNER JOIN
task ON task.task_id = task_assigned.task_id WHERE user_id = $1 ORDER BY task_assigned.assigned_date DESC task ON task.task_id = task_assigned.task_id WHERE user_id = $1
AND $4::boolean = true OR (
$4::boolean = false AND complete = $2 AND (
$2 = false OR ($2 = true AND completed_at > $3)
)
)
ORDER BY task_assigned.assigned_date DESC
` `
func (q *Queries) GetRecentlyAssignedTaskForUserID(ctx context.Context, userID uuid.UUID) ([]Task, error) { type GetRecentlyAssignedTaskForUserIDParams struct {
rows, err := q.db.QueryContext(ctx, getRecentlyAssignedTaskForUserID, userID) UserID uuid.UUID `json:"user_id"`
Complete bool `json:"complete"`
CompletedAt sql.NullTime `json:"completed_at"`
Column4 bool `json:"column_4"`
}
func (q *Queries) GetRecentlyAssignedTaskForUserID(ctx context.Context, arg GetRecentlyAssignedTaskForUserIDParams) ([]Task, error) {
rows, err := q.db.QueryContext(ctx, getRecentlyAssignedTaskForUserID,
arg.UserID,
arg.Complete,
arg.CompletedAt,
arg.Column4,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jinzhu/now"
"github.com/jordanknott/taskcafe/internal/auth" "github.com/jordanknott/taskcafe/internal/auth"
"github.com/jordanknott/taskcafe/internal/db" "github.com/jordanknott/taskcafe/internal/db"
"github.com/jordanknott/taskcafe/internal/logger" "github.com/jordanknott/taskcafe/internal/logger"
@ -1411,18 +1412,60 @@ func (r *queryResolver) MyTasks(ctx context.Context, input MyTasks) (*MyTasksPay
projects := []ProjectTaskMapping{} projects := []ProjectTaskMapping{}
var tasks []db.Task var tasks []db.Task
var err error var err error
showAll := false
if input.Status == MyTasksStatusAll {
showAll = true
}
complete := false
completedAt := sql.NullTime{Valid: false, Time: time.Time{}}
switch input.Status {
case MyTasksStatusCompleteAll:
complete = true
completedAt = sql.NullTime{Valid: true, Time: time.Time{}}
case MyTasksStatusCompleteToday:
complete = true
completedAt = sql.NullTime{Valid: true, Time: now.BeginningOfDay()}
case MyTasksStatusCompleteYesterday:
complete = true
completedAt = sql.NullTime{Valid: true, Time: now.With(time.Now().AddDate(0, 0, -1)).BeginningOfDay()}
case MyTasksStatusCompleteOneWeek:
complete = true
completedAt = sql.NullTime{Valid: true, Time: now.With(time.Now().AddDate(0, 0, -7)).BeginningOfDay()}
case MyTasksStatusCompleteTwoWeek:
complete = true
completedAt = sql.NullTime{Valid: true, Time: now.With(time.Now().AddDate(0, 0, -14)).BeginningOfDay()}
case MyTasksStatusCompleteThreeWeek:
complete = true
completedAt = sql.NullTime{Valid: true, Time: now.With(time.Now().AddDate(0, 0, -21)).BeginningOfDay()}
}
if input.Sort == MyTasksSortNone { if input.Sort == MyTasksSortNone {
tasks, err = r.Repository.GetRecentlyAssignedTaskForUserID(ctx, userID) tasks, err = r.Repository.GetRecentlyAssignedTaskForUserID(ctx, db.GetRecentlyAssignedTaskForUserIDParams{
UserID: userID,
Complete: complete,
CompletedAt: completedAt,
Column4: showAll,
})
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
return &MyTasksPayload{}, err return &MyTasksPayload{}, err
} }
} else if input.Sort == MyTasksSortProject { } else if input.Sort == MyTasksSortProject {
tasks, err = r.Repository.GetAssignedTasksProjectForUserID(ctx, userID) tasks, err = r.Repository.GetAssignedTasksProjectForUserID(ctx, db.GetAssignedTasksProjectForUserIDParams{
UserID: userID,
Complete: complete,
CompletedAt: completedAt,
Column4: showAll,
})
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
return &MyTasksPayload{}, err return &MyTasksPayload{}, err
} }
} else if input.Sort == MyTasksSortDueDate { } else if input.Sort == MyTasksSortDueDate {
tasks, err = r.Repository.GetAssignedTasksDueDateForUserID(ctx, userID) tasks, err = r.Repository.GetAssignedTasksDueDateForUserID(ctx, db.GetAssignedTasksDueDateForUserIDParams{
UserID: userID,
Complete: complete,
CompletedAt: completedAt,
Column4: showAll,
})
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
return &MyTasksPayload{}, err return &MyTasksPayload{}, err
} }