Compare commits
1 Commits
master
...
feat/updat
Author | SHA1 | Date | |
---|---|---|---|
|
4a8d4a6ec3 |
@ -323,6 +323,7 @@ const ProjectBoard: React.FC<ProjectBoardProps> = ({ projectID, onCardLabelClick
|
|||||||
const [updateTaskGroupName] = useUpdateTaskGroupNameMutation({});
|
const [updateTaskGroupName] = useUpdateTaskGroupNameMutation({});
|
||||||
const { loading, data } = useFindProjectQuery({
|
const { loading, data } = useFindProjectQuery({
|
||||||
variables: { projectID },
|
variables: { projectID },
|
||||||
|
pollInterval: 5000,
|
||||||
});
|
});
|
||||||
const [deleteTaskGroupTasks] = useDeleteTaskGroupTasksMutation({
|
const [deleteTaskGroupTasks] = useDeleteTaskGroupTasksMutation({
|
||||||
update: (client, resp) =>
|
update: (client, resp) =>
|
||||||
|
@ -3,7 +3,7 @@ import Modal from 'shared/components/Modal';
|
|||||||
import TaskDetails from 'shared/components/TaskDetails';
|
import TaskDetails from 'shared/components/TaskDetails';
|
||||||
import { Popup, usePopup } from 'shared/components/PopupMenu';
|
import { Popup, usePopup } from 'shared/components/PopupMenu';
|
||||||
import MemberManager from 'shared/components/MemberManager';
|
import MemberManager from 'shared/components/MemberManager';
|
||||||
import { useRouteMatch, useHistory } from 'react-router';
|
import { useRouteMatch, useHistory, Redirect } from 'react-router';
|
||||||
import {
|
import {
|
||||||
useDeleteTaskChecklistMutation,
|
useDeleteTaskChecklistMutation,
|
||||||
useUpdateTaskChecklistNameMutation,
|
useUpdateTaskChecklistNameMutation,
|
||||||
@ -32,6 +32,7 @@ import Input from 'shared/components/Input';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import updateApolloCache from 'shared/utils/cache';
|
import updateApolloCache from 'shared/utils/cache';
|
||||||
import NOOP from 'shared/utils/noop';
|
import NOOP from 'shared/utils/noop';
|
||||||
|
import hasNotFoundError from 'shared/utils/error';
|
||||||
|
|
||||||
const calculateChecklistBadge = (checklists: Array<TaskChecklist>) => {
|
const calculateChecklistBadge = (checklists: Array<TaskChecklist>) => {
|
||||||
const total = checklists.reduce((prev: any, next: any) => {
|
const total = checklists.reduce((prev: any, next: any) => {
|
||||||
@ -269,8 +270,8 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { loading, data, refetch } = useFindTaskQuery({ variables: { taskID } });
|
const { loading, data, refetch, error } = useFindTaskQuery({ variables: { taskID }, pollInterval: 5000 });
|
||||||
const [setTaskComplete] = useSetTaskCompleteMutation();
|
const [setTaskComplete, { error: setTaskCompleteError }] = useSetTaskCompleteMutation();
|
||||||
const [updateTaskDueDate] = useUpdateTaskDueDateMutation({
|
const [updateTaskDueDate] = useUpdateTaskDueDateMutation({
|
||||||
onCompleted: () => {
|
onCompleted: () => {
|
||||||
refetch();
|
refetch();
|
||||||
@ -289,9 +290,13 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
refreshCache();
|
refreshCache();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (loading) {
|
if (hasNotFoundError(error, setTaskCompleteError)) {
|
||||||
return null;
|
return <Redirect to={projectURL} />;
|
||||||
}
|
}
|
||||||
|
if (setTaskCompleteError && setTaskCompleteError)
|
||||||
|
if (loading) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -346,7 +351,11 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
onTaskNameChange={onTaskNameChange}
|
onTaskNameChange={onTaskNameChange}
|
||||||
onTaskDescriptionChange={onTaskDescriptionChange}
|
onTaskDescriptionChange={onTaskDescriptionChange}
|
||||||
onToggleTaskComplete={task => {
|
onToggleTaskComplete={task => {
|
||||||
setTaskComplete({ variables: { taskID: task.id, complete: !task.complete } });
|
setTaskComplete({ variables: { taskID: task.id, complete: !task.complete } }).catch(r => {
|
||||||
|
if (hasNotFoundError(r)) {
|
||||||
|
history.push(projectURL);
|
||||||
|
}
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
onDeleteTask={onDeleteTask}
|
onDeleteTask={onDeleteTask}
|
||||||
onChangeItemName={(itemID, itemName) => {
|
onChangeItemName={(itemID, itemName) => {
|
||||||
|
@ -234,7 +234,7 @@ type ShowNewProject = {
|
|||||||
|
|
||||||
const Projects = () => {
|
const Projects = () => {
|
||||||
const { showPopup, hidePopup } = usePopup();
|
const { showPopup, hidePopup } = usePopup();
|
||||||
const { loading, data } = useGetProjectsQuery({ fetchPolicy: 'network-only' });
|
const { loading, data } = useGetProjectsQuery({ fetchPolicy: 'network-only', pollInterval: 5000 });
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = 'Taskcafé';
|
document.title = 'Taskcafé';
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -154,7 +154,7 @@ type TeamProjectsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const TeamProjects: React.FC<TeamProjectsProps> = ({ teamID }) => {
|
const TeamProjects: React.FC<TeamProjectsProps> = ({ teamID }) => {
|
||||||
const { loading, data } = useGetTeamQuery({ variables: { teamID } });
|
const { loading, data } = useGetTeamQuery({ variables: { teamID }, pollInterval: 5000 });
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <span>loading</span>;
|
return <span>loading</span>;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,8 @@ export enum ObjectType {
|
|||||||
Org = 'ORG',
|
Org = 'ORG',
|
||||||
Team = 'TEAM',
|
Team = 'TEAM',
|
||||||
Project = 'PROJECT',
|
Project = 'PROJECT',
|
||||||
Task = 'TASK'
|
Task = 'TASK',
|
||||||
|
TaskGroup = 'TASK_GROUP'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Query = {
|
export type Query = {
|
||||||
@ -722,7 +723,7 @@ export type UpdateProjectMemberRolePayload = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type NewTask = {
|
export type NewTask = {
|
||||||
taskGroupID: Scalars['String'];
|
taskGroupID: Scalars['UUID'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
position: Scalars['Float'];
|
position: Scalars['Float'];
|
||||||
};
|
};
|
||||||
@ -1472,7 +1473,7 @@ export type UpdateProjectMemberRoleMutation = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type CreateTaskMutationVariables = {
|
export type CreateTaskMutationVariables = {
|
||||||
taskGroupID: Scalars['String'];
|
taskGroupID: Scalars['UUID'];
|
||||||
name: Scalars['String'];
|
name: Scalars['String'];
|
||||||
position: Scalars['Float'];
|
position: Scalars['Float'];
|
||||||
};
|
};
|
||||||
@ -3044,7 +3045,7 @@ export type UpdateProjectMemberRoleMutationHookResult = ReturnType<typeof useUpd
|
|||||||
export type UpdateProjectMemberRoleMutationResult = ApolloReactCommon.MutationResult<UpdateProjectMemberRoleMutation>;
|
export type UpdateProjectMemberRoleMutationResult = ApolloReactCommon.MutationResult<UpdateProjectMemberRoleMutation>;
|
||||||
export type UpdateProjectMemberRoleMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateProjectMemberRoleMutation, UpdateProjectMemberRoleMutationVariables>;
|
export type UpdateProjectMemberRoleMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateProjectMemberRoleMutation, UpdateProjectMemberRoleMutationVariables>;
|
||||||
export const CreateTaskDocument = gql`
|
export const CreateTaskDocument = gql`
|
||||||
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
mutation createTask($taskGroupID: UUID!, $name: String!, $position: Float!) {
|
||||||
createTask(input: {taskGroupID: $taskGroupID, name: $name, position: $position}) {
|
createTask(input: {taskGroupID: $taskGroupID, name: $name, position: $position}) {
|
||||||
...TaskFields
|
...TaskFields
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import gql from 'graphql-tag';
|
|||||||
import TASK_FRAGMENT from '../fragments/task';
|
import TASK_FRAGMENT from '../fragments/task';
|
||||||
|
|
||||||
const CREATE_TASK_MUTATION = gql`
|
const CREATE_TASK_MUTATION = gql`
|
||||||
mutation createTask($taskGroupID: String!, $name: String!, $position: Float!) {
|
mutation createTask($taskGroupID: UUID!, $name: String!, $position: Float!) {
|
||||||
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
createTask(input: { taskGroupID: $taskGroupID, name: $name, position: $position }) {
|
||||||
...TaskFields
|
...TaskFields
|
||||||
}
|
}
|
||||||
|
13
frontend/src/shared/utils/error.ts
Normal file
13
frontend/src/shared/utils/error.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { ApolloError } from '@apollo/client';
|
||||||
|
|
||||||
|
export default function hasNotFoundError(...errors: Array<ApolloError | undefined>) {
|
||||||
|
for (const error of errors) {
|
||||||
|
if (error && error.graphQLErrors.length !== 0) {
|
||||||
|
const notFound = error.graphQLErrors.find(e => e.extensions && e.extensions.code === '404');
|
||||||
|
if (notFound) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@ -2648,6 +2648,7 @@ enum ObjectType {
|
|||||||
TEAM
|
TEAM
|
||||||
PROJECT
|
PROJECT
|
||||||
TASK
|
TASK
|
||||||
|
TASK_GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
directive @hasRole(roles: [RoleLevel!]!, level: ActionLevel!, type: ObjectType!) on FIELD_DEFINITION
|
directive @hasRole(roles: [RoleLevel!]!, level: ActionLevel!, type: ObjectType!) on FIELD_DEFINITION
|
||||||
@ -2851,20 +2852,20 @@ type UpdateProjectMemberRolePayload {
|
|||||||
|
|
||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
createTask(input: NewTask!):
|
createTask(input: NewTask!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK_GROUP)
|
||||||
deleteTask(input: DeleteTaskInput!):
|
deleteTask(input: DeleteTaskInput!):
|
||||||
DeleteTaskPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
DeleteTaskPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
|
|
||||||
updateTaskDescription(input: UpdateTaskDescriptionInput!):
|
updateTaskDescription(input: UpdateTaskDescriptionInput!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskLocation(input: NewTaskLocation!):
|
updateTaskLocation(input: NewTaskLocation!):
|
||||||
UpdateTaskLocationPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
UpdateTaskLocationPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskName(input: UpdateTaskName!):
|
updateTaskName(input: UpdateTaskName!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
setTaskComplete(input: SetTaskComplete!):
|
setTaskComplete(input: SetTaskComplete!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskDueDate(input: UpdateTaskDueDate!):
|
updateTaskDueDate(input: UpdateTaskDueDate!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
|
|
||||||
assignTask(input: AssignTaskInput):
|
assignTask(input: AssignTaskInput):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
@ -2873,7 +2874,7 @@ extend type Mutation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input NewTask {
|
input NewTask {
|
||||||
taskGroupID: String!
|
taskGroupID: UUID!
|
||||||
name: String!
|
name: String!
|
||||||
position: Float!
|
position: Float!
|
||||||
}
|
}
|
||||||
@ -6533,7 +6534,7 @@ func (ec *executionContext) _Mutation_createTask(ctx context.Context, field grap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK_GROUP")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6606,7 +6607,7 @@ func (ec *executionContext) _Mutation_deleteTask(ctx context.Context, field grap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6679,7 +6680,7 @@ func (ec *executionContext) _Mutation_updateTaskDescription(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6752,7 +6753,7 @@ func (ec *executionContext) _Mutation_updateTaskLocation(ctx context.Context, fi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6825,7 +6826,7 @@ func (ec *executionContext) _Mutation_updateTaskName(ctx context.Context, field
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6898,7 +6899,7 @@ func (ec *executionContext) _Mutation_setTaskComplete(ctx context.Context, field
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6971,7 +6972,7 @@ func (ec *executionContext) _Mutation_updateTaskDueDate(ctx context.Context, fie
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "PROJECT")
|
typeArg, err := ec.unmarshalNObjectType2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐObjectType(ctx, "TASK")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -15194,7 +15195,7 @@ func (ec *executionContext) unmarshalInputNewTask(ctx context.Context, obj inter
|
|||||||
switch k {
|
switch k {
|
||||||
case "taskGroupID":
|
case "taskGroupID":
|
||||||
var err error
|
var err error
|
||||||
it.TaskGroupID, err = ec.unmarshalNString2string(ctx, v)
|
it.TaskGroupID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/jordanknott/taskcafe/internal/db"
|
"github.com/jordanknott/taskcafe/internal/db"
|
||||||
"github.com/jordanknott/taskcafe/internal/utils"
|
"github.com/jordanknott/taskcafe/internal/utils"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewHandler returns a new graphql endpoint handler.
|
// NewHandler returns a new graphql endpoint handler.
|
||||||
@ -51,6 +52,8 @@ func NewHandler(repo db.Repository) http.Handler {
|
|||||||
fieldName = "TeamID"
|
fieldName = "TeamID"
|
||||||
case ObjectTypeTask:
|
case ObjectTypeTask:
|
||||||
fieldName = "TaskID"
|
fieldName = "TaskID"
|
||||||
|
case ObjectTypeTaskGroup:
|
||||||
|
fieldName = "TaskGroupID"
|
||||||
default:
|
default:
|
||||||
fieldName = "ProjectID"
|
fieldName = "ProjectID"
|
||||||
}
|
}
|
||||||
@ -68,6 +71,13 @@ func NewHandler(repo db.Repository) http.Handler {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else if typeArg == ObjectTypeTaskGroup {
|
||||||
|
log.WithFields(log.Fields{"subjectID": subjectID}).Info("fetching project ID using task group ID")
|
||||||
|
taskGroup, err := repo.GetTaskGroupByID(ctx, subjectID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
subjectID = taskGroup.ProjectID
|
||||||
}
|
}
|
||||||
roles, err := GetProjectRoles(ctx, repo, subjectID)
|
roles, err := GetProjectRoles(ctx, repo, subjectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -186,3 +196,13 @@ func GetActionType(actionType int32) ActionType {
|
|||||||
panic("Not a valid entity type!")
|
panic("Not a valid entity type!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotFoundError creates a 404 gqlerror
|
||||||
|
func NotFoundError(message string) error {
|
||||||
|
return &gqlerror.Error{
|
||||||
|
Message: message,
|
||||||
|
Extensions: map[string]interface{}{
|
||||||
|
"code": "404",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -229,9 +229,9 @@ type NewRefreshToken struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NewTask struct {
|
type NewTask struct {
|
||||||
TaskGroupID string `json:"taskGroupID"`
|
TaskGroupID uuid.UUID `json:"taskGroupID"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Position float64 `json:"position"`
|
Position float64 `json:"position"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewTaskGroup struct {
|
type NewTaskGroup struct {
|
||||||
@ -648,10 +648,11 @@ func (e EntityType) MarshalGQL(w io.Writer) {
|
|||||||
type ObjectType string
|
type ObjectType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ObjectTypeOrg ObjectType = "ORG"
|
ObjectTypeOrg ObjectType = "ORG"
|
||||||
ObjectTypeTeam ObjectType = "TEAM"
|
ObjectTypeTeam ObjectType = "TEAM"
|
||||||
ObjectTypeProject ObjectType = "PROJECT"
|
ObjectTypeProject ObjectType = "PROJECT"
|
||||||
ObjectTypeTask ObjectType = "TASK"
|
ObjectTypeTask ObjectType = "TASK"
|
||||||
|
ObjectTypeTaskGroup ObjectType = "TASK_GROUP"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AllObjectType = []ObjectType{
|
var AllObjectType = []ObjectType{
|
||||||
@ -659,11 +660,12 @@ var AllObjectType = []ObjectType{
|
|||||||
ObjectTypeTeam,
|
ObjectTypeTeam,
|
||||||
ObjectTypeProject,
|
ObjectTypeProject,
|
||||||
ObjectTypeTask,
|
ObjectTypeTask,
|
||||||
|
ObjectTypeTaskGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ObjectType) IsValid() bool {
|
func (e ObjectType) IsValid() bool {
|
||||||
switch e {
|
switch e {
|
||||||
case ObjectTypeOrg, ObjectTypeTeam, ObjectTypeProject, ObjectTypeTask:
|
case ObjectTypeOrg, ObjectTypeTeam, ObjectTypeProject, ObjectTypeTask, ObjectTypeTaskGroup:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -174,6 +174,7 @@ enum ObjectType {
|
|||||||
TEAM
|
TEAM
|
||||||
PROJECT
|
PROJECT
|
||||||
TASK
|
TASK
|
||||||
|
TASK_GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
directive @hasRole(roles: [RoleLevel!]!, level: ActionLevel!, type: ObjectType!) on FIELD_DEFINITION
|
directive @hasRole(roles: [RoleLevel!]!, level: ActionLevel!, type: ObjectType!) on FIELD_DEFINITION
|
||||||
@ -377,20 +378,20 @@ type UpdateProjectMemberRolePayload {
|
|||||||
|
|
||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
createTask(input: NewTask!):
|
createTask(input: NewTask!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK_GROUP)
|
||||||
deleteTask(input: DeleteTaskInput!):
|
deleteTask(input: DeleteTaskInput!):
|
||||||
DeleteTaskPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
DeleteTaskPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
|
|
||||||
updateTaskDescription(input: UpdateTaskDescriptionInput!):
|
updateTaskDescription(input: UpdateTaskDescriptionInput!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskLocation(input: NewTaskLocation!):
|
updateTaskLocation(input: NewTaskLocation!):
|
||||||
UpdateTaskLocationPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
UpdateTaskLocationPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskName(input: UpdateTaskName!):
|
updateTaskName(input: UpdateTaskName!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
setTaskComplete(input: SetTaskComplete!):
|
setTaskComplete(input: SetTaskComplete!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskDueDate(input: UpdateTaskDueDate!):
|
updateTaskDueDate(input: UpdateTaskDueDate!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
|
|
||||||
assignTask(input: AssignTaskInput):
|
assignTask(input: AssignTaskInput):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
@ -399,7 +400,7 @@ extend type Mutation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input NewTask {
|
input NewTask {
|
||||||
taskGroupID: String!
|
taskGroupID: UUID!
|
||||||
name: String!
|
name: String!
|
||||||
position: Float!
|
position: Float!
|
||||||
}
|
}
|
||||||
|
@ -179,14 +179,9 @@ func (r *mutationResolver) UpdateProjectMemberRole(ctx context.Context, input Up
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*db.Task, error) {
|
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*db.Task, error) {
|
||||||
taskGroupID, err := uuid.Parse(input.TaskGroupID)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("issue while parsing task group ID")
|
|
||||||
return &db.Task{}, err
|
|
||||||
}
|
|
||||||
createdAt := time.Now().UTC()
|
createdAt := time.Now().UTC()
|
||||||
log.WithFields(log.Fields{"positon": input.Position, "taskGroupID": taskGroupID}).Info("creating task")
|
log.WithFields(log.Fields{"positon": input.Position, "taskGroupID": input.TaskGroupID}).Info("creating task")
|
||||||
task, err := r.Repository.CreateTask(ctx, db.CreateTaskParams{taskGroupID, createdAt, input.Name, input.Position})
|
task, err := r.Repository.CreateTask(ctx, db.CreateTaskParams{input.TaskGroupID, createdAt, input.Name, input.Position})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("issue while creating task")
|
log.WithError(err).Error("issue while creating task")
|
||||||
return &db.Task{}, err
|
return &db.Task{}, err
|
||||||
@ -238,6 +233,9 @@ func (r *mutationResolver) SetTaskComplete(ctx context.Context, input SetTaskCom
|
|||||||
completedAt := time.Now().UTC()
|
completedAt := time.Now().UTC()
|
||||||
task, err := r.Repository.SetTaskComplete(ctx, db.SetTaskCompleteParams{TaskID: input.TaskID, Complete: input.Complete, CompletedAt: sql.NullTime{Time: completedAt, Valid: true}})
|
task, err := r.Repository.SetTaskComplete(ctx, db.SetTaskCompleteParams{TaskID: input.TaskID, Complete: input.Complete, CompletedAt: sql.NullTime{Time: completedAt, Valid: true}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return &db.Task{}, NotFoundError("task does not exist")
|
||||||
|
}
|
||||||
return &db.Task{}, err
|
return &db.Task{}, err
|
||||||
}
|
}
|
||||||
return &task, nil
|
return &task, nil
|
||||||
@ -1033,6 +1031,14 @@ func (r *queryResolver) FindProject(ctx context.Context, input FindProject) (*db
|
|||||||
|
|
||||||
func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*db.Task, error) {
|
func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*db.Task, error) {
|
||||||
task, err := r.Repository.GetTaskByID(ctx, input.TaskID)
|
task, err := r.Repository.GetTaskByID(ctx, input.TaskID)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return &db.Task{}, &gqlerror.Error{
|
||||||
|
Message: "Task does not exist",
|
||||||
|
Extensions: map[string]interface{}{
|
||||||
|
"code": "404",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
return &task, err
|
return &task, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1240,6 +1246,9 @@ func (r *taskResolver) Assigned(ctx context.Context, obj *db.Task) ([]Member, er
|
|||||||
taskMemberLinks, err := r.Repository.GetAssignedMembersForTask(ctx, obj.TaskID)
|
taskMemberLinks, err := r.Repository.GetAssignedMembersForTask(ctx, obj.TaskID)
|
||||||
taskMembers := []Member{}
|
taskMembers := []Member{}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return taskMembers, nil
|
||||||
|
}
|
||||||
return taskMembers, err
|
return taskMembers, err
|
||||||
}
|
}
|
||||||
for _, taskMemberLink := range taskMemberLinks {
|
for _, taskMemberLink := range taskMemberLinks {
|
||||||
@ -1274,11 +1283,19 @@ func (r *taskResolver) Assigned(ctx context.Context, obj *db.Task) ([]Member, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *taskResolver) Labels(ctx context.Context, obj *db.Task) ([]db.TaskLabel, error) {
|
func (r *taskResolver) Labels(ctx context.Context, obj *db.Task) ([]db.TaskLabel, error) {
|
||||||
return r.Repository.GetTaskLabelsForTaskID(ctx, obj.TaskID)
|
labels, err := r.Repository.GetTaskLabelsForTaskID(ctx, obj.TaskID)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return []db.TaskLabel{}, err
|
||||||
|
}
|
||||||
|
return labels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *taskResolver) Checklists(ctx context.Context, obj *db.Task) ([]db.TaskChecklist, error) {
|
func (r *taskResolver) Checklists(ctx context.Context, obj *db.Task) ([]db.TaskChecklist, error) {
|
||||||
return r.Repository.GetTaskChecklistsForTask(ctx, obj.TaskID)
|
checklists, err := r.Repository.GetTaskChecklistsForTask(ctx, obj.TaskID)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return []db.TaskChecklist{}, err
|
||||||
|
}
|
||||||
|
return checklists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *taskResolver) Badges(ctx context.Context, obj *db.Task) (*TaskBadges, error) {
|
func (r *taskResolver) Badges(ctx context.Context, obj *db.Task) (*TaskBadges, error) {
|
||||||
|
@ -14,6 +14,7 @@ enum ObjectType {
|
|||||||
TEAM
|
TEAM
|
||||||
PROJECT
|
PROJECT
|
||||||
TASK
|
TASK
|
||||||
|
TASK_GROUP
|
||||||
}
|
}
|
||||||
|
|
||||||
directive @hasRole(roles: [RoleLevel!]!, level: ActionLevel!, type: ObjectType!) on FIELD_DEFINITION
|
directive @hasRole(roles: [RoleLevel!]!, level: ActionLevel!, type: ObjectType!) on FIELD_DEFINITION
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
createTask(input: NewTask!):
|
createTask(input: NewTask!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK_GROUP)
|
||||||
deleteTask(input: DeleteTaskInput!):
|
deleteTask(input: DeleteTaskInput!):
|
||||||
DeleteTaskPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
DeleteTaskPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
|
|
||||||
updateTaskDescription(input: UpdateTaskDescriptionInput!):
|
updateTaskDescription(input: UpdateTaskDescriptionInput!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskLocation(input: NewTaskLocation!):
|
updateTaskLocation(input: NewTaskLocation!):
|
||||||
UpdateTaskLocationPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
UpdateTaskLocationPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskName(input: UpdateTaskName!):
|
updateTaskName(input: UpdateTaskName!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
setTaskComplete(input: SetTaskComplete!):
|
setTaskComplete(input: SetTaskComplete!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
updateTaskDueDate(input: UpdateTaskDueDate!):
|
updateTaskDueDate(input: UpdateTaskDueDate!):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
|
|
||||||
assignTask(input: AssignTaskInput):
|
assignTask(input: AssignTaskInput):
|
||||||
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
Task! @hasRole(roles: [ADMIN], level: PROJECT, type: TASK)
|
||||||
@ -22,7 +22,7 @@ extend type Mutation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input NewTask {
|
input NewTask {
|
||||||
taskGroupID: String!
|
taskGroupID: UUID!
|
||||||
name: String!
|
name: String!
|
||||||
position: Float!
|
position: Float!
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user