feat: change url structure to use short ids instead of full uuids
This commit is contained in:
		| @@ -70,11 +70,10 @@ const Routes: React.FC = () => { | |||||||
|       <Route exact path="/confirm" component={Confirm} /> |       <Route exact path="/confirm" component={Confirm} /> | ||||||
|       <Switch> |       <Switch> | ||||||
|         <MainContent> |         <MainContent> | ||||||
|           <Route path="/projects/:projectID" component={Project} /> |           <Route path="/p/:projectID" component={Project} /> | ||||||
|  |  | ||||||
|           <UserRequiredRoute> |           <UserRequiredRoute> | ||||||
|             <Route exact path="/" component={Dashboard} /> |             <Route exact path="/" component={Projects} /> | ||||||
|             <Route exact path="/projects" component={Projects} /> |  | ||||||
|             <Route path="/teams/:teamID" component={Teams} /> |             <Route path="/teams/:teamID" component={Teams} /> | ||||||
|             <Route path="/profile" component={Profile} /> |             <Route path="/profile" component={Profile} /> | ||||||
|             <Route path="/admin" component={Admin} /> |             <Route path="/admin" component={Admin} /> | ||||||
|   | |||||||
| @@ -429,6 +429,7 @@ const ProjectBoard: React.FC<ProjectBoardProps> = ({ projectID, onCardLabelClick | |||||||
|             createTask: { |             createTask: { | ||||||
|               __typename: 'Task', |               __typename: 'Task', | ||||||
|               id: `${Math.round(Math.random() * -1000000)}`, |               id: `${Math.round(Math.random() * -1000000)}`, | ||||||
|  |               shortId: '', | ||||||
|               name, |               name, | ||||||
|               watched: false, |               watched: false, | ||||||
|               complete: false, |               complete: false, | ||||||
| @@ -605,7 +606,7 @@ const ProjectBoard: React.FC<ProjectBoardProps> = ({ projectID, onCardLabelClick | |||||||
|         <SimpleLists |         <SimpleLists | ||||||
|           isPublic={user === null} |           isPublic={user === null} | ||||||
|           onTaskClick={(task) => { |           onTaskClick={(task) => { | ||||||
|             history.push(`${match.url}/c/${task.id}`); |             history.push(`${match.url}/c/${task.shortId}`); | ||||||
|           }} |           }} | ||||||
|           onCardLabelClick={onCardLabelClick ?? NOOP} |           onCardLabelClick={onCardLabelClick ?? NOOP} | ||||||
|           cardLabelVariant={cardLabelVariant ?? 'large'} |           cardLabelVariant={cardLabelVariant ?? 'large'} | ||||||
|   | |||||||
| @@ -87,7 +87,7 @@ const Project = () => { | |||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           }), |           }), | ||||||
|         { projectID }, |         { projectID: data ? data.findProject.id : '' }, | ||||||
|       ), |       ), | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -100,7 +100,7 @@ const Project = () => { | |||||||
|           produce(cache, (draftCache) => { |           produce(cache, (draftCache) => { | ||||||
|             draftCache.findProject.name = newName.data?.updateProjectName.name ?? ''; |             draftCache.findProject.name = newName.data?.updateProjectName.name ?? ''; | ||||||
|           }), |           }), | ||||||
|         { projectID }, |         { projectID: data ? data.findProject.id : '' }, | ||||||
|       ); |       ); | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| @@ -123,7 +123,7 @@ const Project = () => { | |||||||
|               ]; |               ]; | ||||||
|             } |             } | ||||||
|           }), |           }), | ||||||
|         { projectID }, |         { projectID: data ? data.findProject.id : '' }, | ||||||
|       ); |       ); | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| @@ -138,7 +138,7 @@ const Project = () => { | |||||||
|               (m) => m.email !== response.data?.deleteInvitedProjectMember.invitedMember.email ?? '', |               (m) => m.email !== response.data?.deleteInvitedProjectMember.invitedMember.email ?? '', | ||||||
|             ); |             ); | ||||||
|           }), |           }), | ||||||
|         { projectID }, |         { projectID: data ? data.findProject.id : '' }, | ||||||
|       ); |       ); | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| @@ -153,7 +153,7 @@ const Project = () => { | |||||||
|               (m) => m.id !== response.data?.deleteProjectMember.member.id, |               (m) => m.id !== response.data?.deleteProjectMember.member.id, | ||||||
|             ); |             ); | ||||||
|           }), |           }), | ||||||
|         { projectID }, |         { projectID: data ? data.findProject.id : '' }, | ||||||
|       ); |       ); | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| @@ -171,29 +171,29 @@ const Project = () => { | |||||||
|       <> |       <> | ||||||
|         <GlobalTopNavbar |         <GlobalTopNavbar | ||||||
|           onChangeRole={(userID, roleCode) => { |           onChangeRole={(userID, roleCode) => { | ||||||
|             updateProjectMemberRole({ variables: { userID, roleCode, projectID } }); |             updateProjectMemberRole({ variables: { userID, roleCode, projectID: data ? data.findProject.id : '' } }); | ||||||
|           }} |           }} | ||||||
|           onChangeProjectOwner={() => { |           onChangeProjectOwner={() => { | ||||||
|             hidePopup(); |             hidePopup(); | ||||||
|           }} |           }} | ||||||
|           onRemoveFromBoard={(userID) => { |           onRemoveFromBoard={(userID) => { | ||||||
|             deleteProjectMember({ variables: { userID, projectID } }); |             deleteProjectMember({ variables: { userID, projectID: data ? data.findProject.id : '' } }); | ||||||
|             hidePopup(); |             hidePopup(); | ||||||
|           }} |           }} | ||||||
|           onRemoveInvitedFromBoard={(email) => { |           onRemoveInvitedFromBoard={(email) => { | ||||||
|             deleteInvitedProjectMember({ variables: { projectID, email } }); |             deleteInvitedProjectMember({ variables: { projectID: data ? data.findProject.id : '', email } }); | ||||||
|             hidePopup(); |             hidePopup(); | ||||||
|           }} |           }} | ||||||
|           onSaveProjectName={(projectName) => { |           onSaveProjectName={(projectName) => { | ||||||
|             updateProjectName({ variables: { projectID, name: projectName } }); |             updateProjectName({ variables: { projectID: data ? data.findProject.id : '', name: projectName } }); | ||||||
|           }} |           }} | ||||||
|           onInviteUser={($target) => { |           onInviteUser={($target) => { | ||||||
|             showPopup( |             showPopup( | ||||||
|               $target, |               $target, | ||||||
|               <UserManagementPopup |               <UserManagementPopup | ||||||
|                 projectID={projectID} |                 projectID={data ? data.findProject.id : ''} | ||||||
|                 onInviteProjectMembers={(members) => { |                 onInviteProjectMembers={(members) => { | ||||||
|                   inviteProjectMembers({ variables: { projectID, members } }); |                   inviteProjectMembers({ variables: { projectID: data ? data.findProject.id : '', members } }); | ||||||
|                   hidePopup(); |                   hidePopup(); | ||||||
|                 }} |                 }} | ||||||
|                 users={data.users} |                 users={data.users} | ||||||
|   | |||||||
| @@ -307,7 +307,7 @@ const Projects = () => { | |||||||
|               <ProjectList> |               <ProjectList> | ||||||
|                 {personalProjects.map((project, idx) => ( |                 {personalProjects.map((project, idx) => ( | ||||||
|                   <ProjectListItem key={project.id}> |                   <ProjectListItem key={project.id}> | ||||||
|                     <ProjectTile color={colors[idx % 5]} to={`/projects/${project.id}`}> |                     <ProjectTile color={colors[idx % 5]} to={`/p/${project.shortId}`}> | ||||||
|                       <ProjectTileFade /> |                       <ProjectTileFade /> | ||||||
|                       <ProjectTileDetails> |                       <ProjectTileDetails> | ||||||
|                         <ProjectTileName>{project.name}</ProjectTileName> |                         <ProjectTileName>{project.name}</ProjectTileName> | ||||||
| @@ -351,7 +351,7 @@ const Projects = () => { | |||||||
|                   <ProjectList> |                   <ProjectList> | ||||||
|                     {team.projects.map((project, idx) => ( |                     {team.projects.map((project, idx) => ( | ||||||
|                       <ProjectListItem key={project.id}> |                       <ProjectListItem key={project.id}> | ||||||
|                         <ProjectTile color={colors[idx % 5]} to={`/projects/${project.id}`}> |                         <ProjectTile color={colors[idx % 5]} to={`/p/${project.shortId}`}> | ||||||
|                           <ProjectTileFade /> |                           <ProjectTileFade /> | ||||||
|                           <ProjectTileDetails> |                           <ProjectTileDetails> | ||||||
|                             <ProjectTileName>{project.name}</ProjectTileName> |                             <ProjectTileName>{project.name}</ProjectTileName> | ||||||
|   | |||||||
| @@ -331,7 +331,7 @@ const Notification: React.FC<NotificationProps> = ({ causedBy, createdAt, data, | |||||||
|       prefix.push(<UserCircle width={14} height={16} />); |       prefix.push(<UserCircle width={14} height={16} />); | ||||||
|       prefix.push(<NotificationPrefix>Assigned </NotificationPrefix>); |       prefix.push(<NotificationPrefix>Assigned </NotificationPrefix>); | ||||||
|       prefix.push(<span>you to the task "{dataMap.get('TaskName')}"</span>); |       prefix.push(<span>you to the task "{dataMap.get('TaskName')}"</span>); | ||||||
|       link = `/projects/${dataMap.get('ProjectID')}/board/c/${dataMap.get('TaskID')}`; |       link = `/p/${dataMap.get('ProjectID')}/board/c/${dataMap.get('TaskID')}`; | ||||||
|       break; |       break; | ||||||
|     default: |     default: | ||||||
|       throw new Error('unknown action type'); |       throw new Error('unknown action type'); | ||||||
|   | |||||||
| @@ -278,11 +278,13 @@ export type DuplicateTaskGroupPayload = { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| export type FindProject = { | export type FindProject = { | ||||||
|   projectID: Scalars['UUID']; |   projectID?: Maybe<Scalars['UUID']>; | ||||||
|  |   projectShortID?: Maybe<Scalars['String']>; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export type FindTask = { | export type FindTask = { | ||||||
|   taskID: Scalars['UUID']; |   taskID?: Maybe<Scalars['UUID']>; | ||||||
|  |   taskShortID?: Maybe<Scalars['String']>; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export type FindTeam = { | export type FindTeam = { | ||||||
| @@ -908,6 +910,7 @@ export type ProfileIcon = { | |||||||
| export type Project = { | export type Project = { | ||||||
|   __typename?: 'Project'; |   __typename?: 'Project'; | ||||||
|   id: Scalars['ID']; |   id: Scalars['ID']; | ||||||
|  |   shortId: Scalars['String']; | ||||||
|   createdAt: Scalars['Time']; |   createdAt: Scalars['Time']; | ||||||
|   name: Scalars['String']; |   name: Scalars['String']; | ||||||
|   team?: Maybe<Team>; |   team?: Maybe<Team>; | ||||||
| @@ -1068,6 +1071,7 @@ export type Subscription = { | |||||||
| export type Task = { | export type Task = { | ||||||
|   __typename?: 'Task'; |   __typename?: 'Task'; | ||||||
|   id: Scalars['ID']; |   id: Scalars['ID']; | ||||||
|  |   shortId: Scalars['String']; | ||||||
|   taskGroup: TaskGroup; |   taskGroup: TaskGroup; | ||||||
|   createdAt: Scalars['Time']; |   createdAt: Scalars['Time']; | ||||||
|   name: Scalars['String']; |   name: Scalars['String']; | ||||||
| @@ -1419,7 +1423,7 @@ export type CreateProjectMutation = ( | |||||||
|   { __typename?: 'Mutation' } |   { __typename?: 'Mutation' } | ||||||
|   & { createProject: ( |   & { createProject: ( | ||||||
|     { __typename?: 'Project' } |     { __typename?: 'Project' } | ||||||
|     & Pick<Project, 'id' | 'name'> |     & Pick<Project, 'id' | 'shortId' | 'name'> | ||||||
|     & { team?: Maybe<( |     & { team?: Maybe<( | ||||||
|       { __typename?: 'Team' } |       { __typename?: 'Team' } | ||||||
|       & Pick<Team, 'id' | 'name'> |       & Pick<Team, 'id' | 'name'> | ||||||
| @@ -1509,7 +1513,7 @@ export type DeleteTaskGroupMutation = ( | |||||||
| ); | ); | ||||||
|  |  | ||||||
| export type FindProjectQueryVariables = Exact<{ | export type FindProjectQueryVariables = Exact<{ | ||||||
|   projectID: Scalars['UUID']; |   projectID: Scalars['String']; | ||||||
| }>; | }>; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1517,7 +1521,7 @@ export type FindProjectQuery = ( | |||||||
|   { __typename?: 'Query' } |   { __typename?: 'Query' } | ||||||
|   & { findProject: ( |   & { findProject: ( | ||||||
|     { __typename?: 'Project' } |     { __typename?: 'Project' } | ||||||
|     & Pick<Project, 'name' | 'publicOn'> |     & Pick<Project, 'id' | 'name' | 'publicOn'> | ||||||
|     & { team?: Maybe<( |     & { team?: Maybe<( | ||||||
|       { __typename?: 'Team' } |       { __typename?: 'Team' } | ||||||
|       & Pick<Team, 'id'> |       & Pick<Team, 'id'> | ||||||
| @@ -1584,7 +1588,7 @@ export type FindProjectQuery = ( | |||||||
| ); | ); | ||||||
|  |  | ||||||
| export type FindTaskQueryVariables = Exact<{ | export type FindTaskQueryVariables = Exact<{ | ||||||
|   taskID: Scalars['UUID']; |   taskID: Scalars['String']; | ||||||
| }>; | }>; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1592,7 +1596,7 @@ export type FindTaskQuery = ( | |||||||
|   { __typename?: 'Query' } |   { __typename?: 'Query' } | ||||||
|   & { findTask: ( |   & { findTask: ( | ||||||
|     { __typename?: 'Task' } |     { __typename?: 'Task' } | ||||||
|     & Pick<Task, 'id' | 'name' | 'watched' | 'description' | 'dueDate' | 'position' | 'complete' | 'hasTime'> |     & Pick<Task, 'id' | 'shortId' | 'name' | 'watched' | 'description' | 'dueDate' | 'position' | 'complete' | 'hasTime'> | ||||||
|     & { taskGroup: ( |     & { taskGroup: ( | ||||||
|       { __typename?: 'TaskGroup' } |       { __typename?: 'TaskGroup' } | ||||||
|       & Pick<TaskGroup, 'id' | 'name'> |       & Pick<TaskGroup, 'id' | 'name'> | ||||||
| @@ -1668,7 +1672,7 @@ export type FindTaskQuery = ( | |||||||
|  |  | ||||||
| export type TaskFieldsFragment = ( | export type TaskFieldsFragment = ( | ||||||
|   { __typename?: 'Task' } |   { __typename?: 'Task' } | ||||||
|   & Pick<Task, 'id' | 'name' | 'description' | 'dueDate' | 'hasTime' | 'complete' | 'watched' | 'completedAt' | 'position'> |   & Pick<Task, 'id' | 'shortId' | 'name' | 'description' | 'dueDate' | 'hasTime' | 'complete' | 'watched' | 'completedAt' | 'position'> | ||||||
|   & { badges: ( |   & { badges: ( | ||||||
|     { __typename?: 'TaskBadges' } |     { __typename?: 'TaskBadges' } | ||||||
|     & { checklist?: Maybe<( |     & { checklist?: Maybe<( | ||||||
| @@ -1715,7 +1719,7 @@ export type GetProjectsQuery = ( | |||||||
|     & Pick<Team, 'id' | 'name' | 'createdAt'> |     & Pick<Team, 'id' | 'name' | 'createdAt'> | ||||||
|   )>, projects: Array<( |   )>, projects: Array<( | ||||||
|     { __typename?: 'Project' } |     { __typename?: 'Project' } | ||||||
|     & Pick<Project, 'id' | 'name'> |     & Pick<Project, 'id' | 'shortId' | 'name'> | ||||||
|     & { team?: Maybe<( |     & { team?: Maybe<( | ||||||
|       { __typename?: 'Team' } |       { __typename?: 'Team' } | ||||||
|       & Pick<Team, 'id' | 'name'> |       & Pick<Team, 'id' | 'name'> | ||||||
| @@ -1785,7 +1789,7 @@ export type MyTasksQuery = ( | |||||||
|     { __typename?: 'MyTasksPayload' } |     { __typename?: 'MyTasksPayload' } | ||||||
|     & { tasks: Array<( |     & { tasks: Array<( | ||||||
|       { __typename?: 'Task' } |       { __typename?: 'Task' } | ||||||
|       & Pick<Task, 'id' | 'name' | 'dueDate' | 'hasTime' | 'complete' | 'completedAt'> |       & Pick<Task, 'id' | 'shortId' | 'name' | 'dueDate' | 'hasTime' | 'complete' | 'completedAt'> | ||||||
|       & { taskGroup: ( |       & { taskGroup: ( | ||||||
|         { __typename?: 'TaskGroup' } |         { __typename?: 'TaskGroup' } | ||||||
|         & Pick<TaskGroup, 'id' | 'name'> |         & Pick<TaskGroup, 'id' | 'name'> | ||||||
| @@ -2859,6 +2863,7 @@ export type UsersQuery = ( | |||||||
| export const TaskFieldsFragmentDoc = gql` | export const TaskFieldsFragmentDoc = gql` | ||||||
|     fragment TaskFields on Task { |     fragment TaskFields on Task { | ||||||
|   id |   id | ||||||
|  |   shortId | ||||||
|   name |   name | ||||||
|   description |   description | ||||||
|   dueDate |   dueDate | ||||||
| @@ -2988,6 +2993,7 @@ export const CreateProjectDocument = gql` | |||||||
|     mutation createProject($teamID: UUID, $name: String!) { |     mutation createProject($teamID: UUID, $name: String!) { | ||||||
|   createProject(input: {teamID: $teamID, name: $name}) { |   createProject(input: {teamID: $teamID, name: $name}) { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     team { |     team { | ||||||
|       id |       id | ||||||
| @@ -3215,8 +3221,9 @@ export type DeleteTaskGroupMutationHookResult = ReturnType<typeof useDeleteTaskG | |||||||
| export type DeleteTaskGroupMutationResult = Apollo.MutationResult<DeleteTaskGroupMutation>; | export type DeleteTaskGroupMutationResult = Apollo.MutationResult<DeleteTaskGroupMutation>; | ||||||
| export type DeleteTaskGroupMutationOptions = Apollo.BaseMutationOptions<DeleteTaskGroupMutation, DeleteTaskGroupMutationVariables>; | export type DeleteTaskGroupMutationOptions = Apollo.BaseMutationOptions<DeleteTaskGroupMutation, DeleteTaskGroupMutationVariables>; | ||||||
| export const FindProjectDocument = gql` | export const FindProjectDocument = gql` | ||||||
|     query findProject($projectID: UUID!) { |     query findProject($projectID: String!) { | ||||||
|   findProject(input: {projectID: $projectID}) { |   findProject(input: {projectShortID: $projectID}) { | ||||||
|  |     id | ||||||
|     name |     name | ||||||
|     publicOn |     publicOn | ||||||
|     team { |     team { | ||||||
| @@ -3332,9 +3339,10 @@ export type FindProjectQueryHookResult = ReturnType<typeof useFindProjectQuery>; | |||||||
| export type FindProjectLazyQueryHookResult = ReturnType<typeof useFindProjectLazyQuery>; | export type FindProjectLazyQueryHookResult = ReturnType<typeof useFindProjectLazyQuery>; | ||||||
| export type FindProjectQueryResult = Apollo.QueryResult<FindProjectQuery, FindProjectQueryVariables>; | export type FindProjectQueryResult = Apollo.QueryResult<FindProjectQuery, FindProjectQueryVariables>; | ||||||
| export const FindTaskDocument = gql` | export const FindTaskDocument = gql` | ||||||
|     query findTask($taskID: UUID!) { |     query findTask($taskID: String!) { | ||||||
|   findTask(input: {taskID: $taskID}) { |   findTask(input: {taskShortID: $taskID}) { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     watched |     watched | ||||||
|     description |     description | ||||||
| @@ -3477,6 +3485,7 @@ export const GetProjectsDocument = gql` | |||||||
|   } |   } | ||||||
|   projects { |   projects { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     team { |     team { | ||||||
|       id |       id | ||||||
| @@ -3625,6 +3634,7 @@ export const MyTasksDocument = gql` | |||||||
|   myTasks(input: {status: $status, sort: $sort}) { |   myTasks(input: {status: $status, sort: $sort}) { | ||||||
|     tasks { |     tasks { | ||||||
|       id |       id | ||||||
|  |       shortId | ||||||
|       taskGroup { |       taskGroup { | ||||||
|         id |         id | ||||||
|         name |         name | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| mutation createProject($teamID: UUID, $name: String!) { | mutation createProject($teamID: UUID, $name: String!) { | ||||||
|   createProject(input: {teamID: $teamID, name: $name}) { |   createProject(input: {teamID: $teamID, name: $name}) { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     team { |     team { | ||||||
|       id |       id | ||||||
|   | |||||||
| @@ -2,8 +2,9 @@ import gql from 'graphql-tag'; | |||||||
| import TASK_FRAGMENT from './fragments/task'; | import TASK_FRAGMENT from './fragments/task'; | ||||||
|  |  | ||||||
| const FIND_PROJECT_QUERY = gql` | const FIND_PROJECT_QUERY = gql` | ||||||
| query findProject($projectID: UUID!) { | query findProject($projectID: String!) { | ||||||
|   findProject(input: { projectID: $projectID }) { |   findProject(input: { projectShortID: $projectID }) { | ||||||
|  |     id | ||||||
|     name |     name | ||||||
|     publicOn |     publicOn | ||||||
|     team { |     team { | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| query findTask($taskID: UUID!) { | query findTask($taskID: String!) { | ||||||
|   findTask(input: {taskID: $taskID}) { |   findTask(input: {taskShortID: $taskID}) { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     watched |     watched | ||||||
|     description |     description | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import gql from 'graphql-tag'; | |||||||
| const TASK_FRAGMENT = gql` | const TASK_FRAGMENT = gql` | ||||||
|   fragment TaskFields on Task { |   fragment TaskFields on Task { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     description |     description | ||||||
|     dueDate |     dueDate | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ query getProjects { | |||||||
|   } |   } | ||||||
|   projects { |   projects { | ||||||
|     id |     id | ||||||
|  |     shortId | ||||||
|     name |     name | ||||||
|     team { |     team { | ||||||
|       id |       id | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ query myTasks($status: MyTasksStatus!, $sort: MyTasksSort!) { | |||||||
|   myTasks(input: { status: $status, sort: $sort }) { |   myTasks(input: { status: $status, sort: $sort }) { | ||||||
|     tasks { |     tasks { | ||||||
|       id |       id | ||||||
|  |       shortId | ||||||
|       taskGroup { |       taskGroup { | ||||||
|         id |         id | ||||||
|         name |         name | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								frontend/src/types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								frontend/src/types.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -103,6 +103,7 @@ type TaskComment = { | |||||||
|  |  | ||||||
| type Task = { | type Task = { | ||||||
|   id: string; |   id: string; | ||||||
|  |   shortId: string; | ||||||
|   taskGroup: InnerTaskGroup; |   taskGroup: InnerTaskGroup; | ||||||
|   name: string; |   name: string; | ||||||
|   watched?: boolean; |   watched?: boolean; | ||||||
|   | |||||||
| @@ -86,6 +86,7 @@ type Project struct { | |||||||
| 	CreatedAt time.Time    `json:"created_at"` | 	CreatedAt time.Time    `json:"created_at"` | ||||||
| 	Name      string       `json:"name"` | 	Name      string       `json:"name"` | ||||||
| 	PublicOn  sql.NullTime `json:"public_on"` | 	PublicOn  sql.NullTime `json:"public_on"` | ||||||
|  | 	ShortID   string       `json:"short_id"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type ProjectLabel struct { | type ProjectLabel struct { | ||||||
| @@ -132,6 +133,7 @@ type Task struct { | |||||||
| 	Complete    bool           `json:"complete"` | 	Complete    bool           `json:"complete"` | ||||||
| 	CompletedAt sql.NullTime   `json:"completed_at"` | 	CompletedAt sql.NullTime   `json:"completed_at"` | ||||||
| 	HasTime     bool           `json:"has_time"` | 	HasTime     bool           `json:"has_time"` | ||||||
|  | 	ShortID     string         `json:"short_id"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type TaskActivity struct { | type TaskActivity struct { | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| const createPersonalProject = `-- name: CreatePersonalProject :one | const createPersonalProject = `-- name: CreatePersonalProject :one | ||||||
| INSERT INTO project(team_id, created_at, name) VALUES (null, $1, $2) RETURNING project_id, team_id, created_at, name, public_on | INSERT INTO project(team_id, created_at, name) VALUES (null, $1, $2) RETURNING project_id, team_id, created_at, name, public_on, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type CreatePersonalProjectParams struct { | type CreatePersonalProjectParams struct { | ||||||
| @@ -29,6 +29,7 @@ func (q *Queries) CreatePersonalProject(ctx context.Context, arg CreatePersonalP | |||||||
| 		&i.CreatedAt, | 		&i.CreatedAt, | ||||||
| 		&i.Name, | 		&i.Name, | ||||||
| 		&i.PublicOn, | 		&i.PublicOn, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
| @@ -80,7 +81,7 @@ func (q *Queries) CreateProjectMember(ctx context.Context, arg CreateProjectMemb | |||||||
| } | } | ||||||
|  |  | ||||||
| const createTeamProject = `-- name: CreateTeamProject :one | const createTeamProject = `-- name: CreateTeamProject :one | ||||||
| INSERT INTO project(team_id, created_at, name) VALUES ($1, $2, $3) RETURNING project_id, team_id, created_at, name, public_on | INSERT INTO project(team_id, created_at, name) VALUES ($1, $2, $3) RETURNING project_id, team_id, created_at, name, public_on, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type CreateTeamProjectParams struct { | type CreateTeamProjectParams struct { | ||||||
| @@ -98,6 +99,7 @@ func (q *Queries) CreateTeamProject(ctx context.Context, arg CreateTeamProjectPa | |||||||
| 		&i.CreatedAt, | 		&i.CreatedAt, | ||||||
| 		&i.Name, | 		&i.Name, | ||||||
| 		&i.PublicOn, | 		&i.PublicOn, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
| @@ -135,7 +137,7 @@ func (q *Queries) DeleteProjectMember(ctx context.Context, arg DeleteProjectMemb | |||||||
| } | } | ||||||
|  |  | ||||||
| const getAllProjectsForTeam = `-- name: GetAllProjectsForTeam :many | const getAllProjectsForTeam = `-- name: GetAllProjectsForTeam :many | ||||||
| SELECT project_id, team_id, created_at, name, public_on FROM project WHERE team_id = $1 | SELECT project_id, team_id, created_at, name, public_on, short_id FROM project WHERE team_id = $1 | ||||||
| ` | ` | ||||||
|  |  | ||||||
| func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) { | func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ([]Project, error) { | ||||||
| @@ -153,6 +155,7 @@ func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ( | |||||||
| 			&i.CreatedAt, | 			&i.CreatedAt, | ||||||
| 			&i.Name, | 			&i.Name, | ||||||
| 			&i.PublicOn, | 			&i.PublicOn, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -168,7 +171,7 @@ func (q *Queries) GetAllProjectsForTeam(ctx context.Context, teamID uuid.UUID) ( | |||||||
| } | } | ||||||
|  |  | ||||||
| const getAllTeamProjects = `-- name: GetAllTeamProjects :many | const getAllTeamProjects = `-- name: GetAllTeamProjects :many | ||||||
| SELECT project_id, team_id, created_at, name, public_on FROM project WHERE team_id IS NOT null | SELECT project_id, team_id, created_at, name, public_on, short_id FROM project WHERE team_id IS NOT null | ||||||
| ` | ` | ||||||
|  |  | ||||||
| func (q *Queries) GetAllTeamProjects(ctx context.Context) ([]Project, error) { | func (q *Queries) GetAllTeamProjects(ctx context.Context) ([]Project, error) { | ||||||
| @@ -186,6 +189,7 @@ func (q *Queries) GetAllTeamProjects(ctx context.Context) ([]Project, error) { | |||||||
| 			&i.CreatedAt, | 			&i.CreatedAt, | ||||||
| 			&i.Name, | 			&i.Name, | ||||||
| 			&i.PublicOn, | 			&i.PublicOn, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -201,7 +205,7 @@ func (q *Queries) GetAllTeamProjects(ctx context.Context) ([]Project, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| const getAllVisibleProjectsForUserID = `-- name: GetAllVisibleProjectsForUserID :many | const getAllVisibleProjectsForUserID = `-- name: GetAllVisibleProjectsForUserID :many | ||||||
| SELECT project.project_id, project.team_id, project.created_at, project.name, project.public_on FROM project LEFT JOIN | SELECT project.project_id, project.team_id, project.created_at, project.name, project.public_on, project.short_id FROM project LEFT JOIN | ||||||
|  project_member ON project_member.project_id = project.project_id WHERE project_member.user_id = $1 |  project_member ON project_member.project_id = project.project_id WHERE project_member.user_id = $1 | ||||||
| ` | ` | ||||||
|  |  | ||||||
| @@ -220,6 +224,7 @@ func (q *Queries) GetAllVisibleProjectsForUserID(ctx context.Context, userID uui | |||||||
| 			&i.CreatedAt, | 			&i.CreatedAt, | ||||||
| 			&i.Name, | 			&i.Name, | ||||||
| 			&i.PublicOn, | 			&i.PublicOn, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -298,7 +303,7 @@ func (q *Queries) GetMemberProjectIDsForUserID(ctx context.Context, userID uuid. | |||||||
| } | } | ||||||
|  |  | ||||||
| const getPersonalProjectsForUserID = `-- name: GetPersonalProjectsForUserID :many | const getPersonalProjectsForUserID = `-- name: GetPersonalProjectsForUserID :many | ||||||
| SELECT project.project_id, project.team_id, project.created_at, project.name, project.public_on FROM project | SELECT project.project_id, project.team_id, project.created_at, project.name, project.public_on, project.short_id FROM project | ||||||
|   LEFT JOIN personal_project ON personal_project.project_id = project.project_id |   LEFT JOIN personal_project ON personal_project.project_id = project.project_id | ||||||
|   WHERE personal_project.user_id = $1 |   WHERE personal_project.user_id = $1 | ||||||
| ` | ` | ||||||
| @@ -318,6 +323,7 @@ func (q *Queries) GetPersonalProjectsForUserID(ctx context.Context, userID uuid. | |||||||
| 			&i.CreatedAt, | 			&i.CreatedAt, | ||||||
| 			&i.Name, | 			&i.Name, | ||||||
| 			&i.PublicOn, | 			&i.PublicOn, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -333,7 +339,7 @@ func (q *Queries) GetPersonalProjectsForUserID(ctx context.Context, userID uuid. | |||||||
| } | } | ||||||
|  |  | ||||||
| const getProjectByID = `-- name: GetProjectByID :one | const getProjectByID = `-- name: GetProjectByID :one | ||||||
| SELECT project_id, team_id, created_at, name, public_on FROM project WHERE project_id = $1 | SELECT project_id, team_id, created_at, name, public_on, short_id FROM project WHERE project_id = $1 | ||||||
| ` | ` | ||||||
|  |  | ||||||
| func (q *Queries) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) { | func (q *Queries) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) { | ||||||
| @@ -345,10 +351,22 @@ func (q *Queries) GetProjectByID(ctx context.Context, projectID uuid.UUID) (Proj | |||||||
| 		&i.CreatedAt, | 		&i.CreatedAt, | ||||||
| 		&i.Name, | 		&i.Name, | ||||||
| 		&i.PublicOn, | 		&i.PublicOn, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const getProjectIDByShortID = `-- name: GetProjectIDByShortID :one | ||||||
|  | SELECT project_id FROM project WHERE short_id = $1 | ||||||
|  | ` | ||||||
|  |  | ||||||
|  | func (q *Queries) GetProjectIDByShortID(ctx context.Context, shortID string) (uuid.UUID, error) { | ||||||
|  | 	row := q.db.QueryRowContext(ctx, getProjectIDByShortID, shortID) | ||||||
|  | 	var project_id uuid.UUID | ||||||
|  | 	err := row.Scan(&project_id) | ||||||
|  | 	return project_id, err | ||||||
|  | } | ||||||
|  |  | ||||||
| const getProjectMemberInvitedIDByEmail = `-- name: GetProjectMemberInvitedIDByEmail :one | const getProjectMemberInvitedIDByEmail = `-- name: GetProjectMemberInvitedIDByEmail :one | ||||||
| SELECT email, invited_on, project_member_invited_id FROM user_account_invited AS uai | SELECT email, invited_on, project_member_invited_id FROM user_account_invited AS uai | ||||||
|  inner join project_member_invited AS pmi |  inner join project_member_invited AS pmi | ||||||
| @@ -489,7 +507,7 @@ func (q *Queries) GetUserRolesForProject(ctx context.Context, arg GetUserRolesFo | |||||||
| } | } | ||||||
|  |  | ||||||
| const setPublicOn = `-- name: SetPublicOn :one | const setPublicOn = `-- name: SetPublicOn :one | ||||||
| UPDATE project SET public_on = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, public_on | UPDATE project SET public_on = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, public_on, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type SetPublicOnParams struct { | type SetPublicOnParams struct { | ||||||
| @@ -506,6 +524,7 @@ func (q *Queries) SetPublicOn(ctx context.Context, arg SetPublicOnParams) (Proje | |||||||
| 		&i.CreatedAt, | 		&i.CreatedAt, | ||||||
| 		&i.Name, | 		&i.Name, | ||||||
| 		&i.PublicOn, | 		&i.PublicOn, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
| @@ -535,7 +554,7 @@ func (q *Queries) UpdateProjectMemberRole(ctx context.Context, arg UpdateProject | |||||||
| } | } | ||||||
|  |  | ||||||
| const updateProjectNameByID = `-- name: UpdateProjectNameByID :one | const updateProjectNameByID = `-- name: UpdateProjectNameByID :one | ||||||
| UPDATE project SET name = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, public_on | UPDATE project SET name = $2 WHERE project_id = $1 RETURNING project_id, team_id, created_at, name, public_on, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type UpdateProjectNameByIDParams struct { | type UpdateProjectNameByIDParams struct { | ||||||
| @@ -552,6 +571,7 @@ func (q *Queries) UpdateProjectNameByID(ctx context.Context, arg UpdateProjectNa | |||||||
| 		&i.CreatedAt, | 		&i.CreatedAt, | ||||||
| 		&i.Name, | 		&i.Name, | ||||||
| 		&i.PublicOn, | 		&i.PublicOn, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|   | |||||||
| @@ -94,6 +94,7 @@ type Querier interface { | |||||||
| 	GetNotifiedByID(ctx context.Context, notifiedID uuid.UUID) (GetNotifiedByIDRow, error) | 	GetNotifiedByID(ctx context.Context, notifiedID uuid.UUID) (GetNotifiedByIDRow, error) | ||||||
| 	GetPersonalProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error) | 	GetPersonalProjectsForUserID(ctx context.Context, userID uuid.UUID) ([]Project, error) | ||||||
| 	GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) | 	GetProjectByID(ctx context.Context, projectID uuid.UUID) (Project, error) | ||||||
|  | 	GetProjectIDByShortID(ctx context.Context, shortID string) (uuid.UUID, error) | ||||||
| 	GetProjectIDForTask(ctx context.Context, taskID uuid.UUID) (uuid.UUID, error) | 	GetProjectIDForTask(ctx context.Context, taskID uuid.UUID) (uuid.UUID, error) | ||||||
| 	GetProjectIDForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) (uuid.UUID, error) | 	GetProjectIDForTaskChecklist(ctx context.Context, taskChecklistID uuid.UUID) (uuid.UUID, error) | ||||||
| 	GetProjectIDForTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) (uuid.UUID, error) | 	GetProjectIDForTaskChecklistItem(ctx context.Context, taskChecklistItemID uuid.UUID) (uuid.UUID, error) | ||||||
| @@ -119,6 +120,7 @@ type Querier interface { | |||||||
| 	GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error) | 	GetTaskChecklistsForTask(ctx context.Context, taskID uuid.UUID) ([]TaskChecklist, error) | ||||||
| 	GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error) | 	GetTaskGroupByID(ctx context.Context, taskGroupID uuid.UUID) (TaskGroup, error) | ||||||
| 	GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error) | 	GetTaskGroupsForProject(ctx context.Context, projectID uuid.UUID) ([]TaskGroup, error) | ||||||
|  | 	GetTaskIDByShortID(ctx context.Context, shortID string) (uuid.UUID, error) | ||||||
| 	GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error) | 	GetTaskLabelByID(ctx context.Context, taskLabelID uuid.UUID) (TaskLabel, error) | ||||||
| 	GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error) | 	GetTaskLabelForTaskByProjectLabelID(ctx context.Context, arg GetTaskLabelForTaskByProjectLabelIDParams) (TaskLabel, error) | ||||||
| 	GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error) | 	GetTaskLabelsForTaskID(ctx context.Context, taskID uuid.UUID) ([]TaskLabel, error) | ||||||
|   | |||||||
| @@ -1,6 +1,9 @@ | |||||||
| -- name: GetAllTeamProjects :many | -- name: GetAllTeamProjects :many | ||||||
| SELECT * FROM project WHERE team_id IS NOT null; | SELECT * FROM project WHERE team_id IS NOT null; | ||||||
|  |  | ||||||
|  | -- name: GetProjectIDByShortID :one | ||||||
|  | SELECT project_id FROM project WHERE short_id = $1; | ||||||
|  |  | ||||||
| -- name: GetAllProjectsForTeam :many | -- name: GetAllProjectsForTeam :many | ||||||
| SELECT * FROM project WHERE team_id = $1; | SELECT * FROM project WHERE team_id = $1; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,9 @@ SELECT * FROM task_watcher WHERE user_id = $1 AND task_id = $2; | |||||||
| -- name: CreateTaskWatcher :one | -- name: CreateTaskWatcher :one | ||||||
| INSERT INTO task_watcher (user_id, task_id, watched_at) VALUES ($1, $2, $3) RETURNING *; | INSERT INTO task_watcher (user_id, task_id, watched_at) VALUES ($1, $2, $3) RETURNING *; | ||||||
|  |  | ||||||
|  | -- name: GetTaskIDByShortID :one | ||||||
|  | SELECT task_id FROM task WHERE short_id = $1; | ||||||
|  |  | ||||||
| -- name: DeleteTaskWatcher :exec | -- name: DeleteTaskWatcher :exec | ||||||
| DELETE FROM task_watcher WHERE user_id = $1 AND task_id = $2; | DELETE FROM task_watcher WHERE user_id = $1 AND task_id = $2; | ||||||
|  |  | ||||||
| @@ -54,7 +57,7 @@ SELECT project_id FROM task | |||||||
|   WHERE task_id = $1; |   WHERE task_id = $1; | ||||||
|  |  | ||||||
| -- name: GetProjectInfoForTask :one | -- name: GetProjectInfoForTask :one | ||||||
| SELECT project.project_id, project.name FROM task | SELECT project.short_id AS project_short_id, project.name, task.short_id AS task_short_id FROM task | ||||||
|   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 | ||||||
|   INNER JOIN project ON task_group.project_id = project.project_id |   INNER JOIN project ON task_group.project_id = project.project_id | ||||||
|   WHERE task_id = $1; |   WHERE task_id = $1; | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ import ( | |||||||
|  |  | ||||||
| const createTask = `-- name: CreateTask :one | const createTask = `-- name: CreateTask :one | ||||||
| INSERT INTO task (task_group_id, created_at, name, position) | INSERT INTO task (task_group_id, created_at, name, position) | ||||||
|   VALUES($1, $2, $3, $4) RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time |   VALUES($1, $2, $3, $4) RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type CreateTaskParams struct { | type CreateTaskParams struct { | ||||||
| @@ -43,13 +43,14 @@ func (q *Queries) CreateTask(ctx context.Context, arg CreateTaskParams) (Task, e | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
| const createTaskAll = `-- name: CreateTaskAll :one | const createTaskAll = `-- name: CreateTaskAll :one | ||||||
| INSERT INTO task (task_group_id, created_at, name, position, description, complete, due_date) | INSERT INTO task (task_group_id, created_at, name, position, description, complete, due_date) | ||||||
|   VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time |   VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type CreateTaskAllParams struct { | type CreateTaskAllParams struct { | ||||||
| @@ -84,6 +85,7 @@ func (q *Queries) CreateTaskAll(ctx context.Context, arg CreateTaskAllParams) (T | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
| @@ -197,7 +199,7 @@ func (q *Queries) DeleteTasksByTaskGroupID(ctx context.Context, taskGroupID uuid | |||||||
| } | } | ||||||
|  |  | ||||||
| const getAllTasks = `-- name: GetAllTasks :many | const getAllTasks = `-- name: GetAllTasks :many | ||||||
| SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time FROM task | SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id FROM task | ||||||
| ` | ` | ||||||
|  |  | ||||||
| func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) { | func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) { | ||||||
| @@ -220,6 +222,7 @@ func (q *Queries) GetAllTasks(ctx context.Context) ([]Task, error) { | |||||||
| 			&i.Complete, | 			&i.Complete, | ||||||
| 			&i.CompletedAt, | 			&i.CompletedAt, | ||||||
| 			&i.HasTime, | 			&i.HasTime, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -235,7 +238,7 @@ 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, task.short_id 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 | ||||||
| @@ -279,6 +282,7 @@ func (q *Queries) GetAssignedTasksDueDateForUserID(ctx context.Context, arg GetA | |||||||
| 			&i.Complete, | 			&i.Complete, | ||||||
| 			&i.CompletedAt, | 			&i.CompletedAt, | ||||||
| 			&i.HasTime, | 			&i.HasTime, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -294,7 +298,7 @@ func (q *Queries) GetAssignedTasksDueDateForUserID(ctx context.Context, arg GetA | |||||||
| } | } | ||||||
|  |  | ||||||
| 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, task.short_id 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 | ||||||
| @@ -338,6 +342,7 @@ func (q *Queries) GetAssignedTasksProjectForUserID(ctx context.Context, arg GetA | |||||||
| 			&i.Complete, | 			&i.Complete, | ||||||
| 			&i.CompletedAt, | 			&i.CompletedAt, | ||||||
| 			&i.HasTime, | 			&i.HasTime, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -446,26 +451,27 @@ func (q *Queries) GetProjectIdMappings(ctx context.Context, dollar_1 []uuid.UUID | |||||||
| } | } | ||||||
|  |  | ||||||
| const getProjectInfoForTask = `-- name: GetProjectInfoForTask :one | const getProjectInfoForTask = `-- name: GetProjectInfoForTask :one | ||||||
| SELECT project.project_id, project.name FROM task | SELECT project.short_id AS project_short_id, project.name, task.short_id AS task_short_id FROM task | ||||||
|   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 | ||||||
|   INNER JOIN project ON task_group.project_id = project.project_id |   INNER JOIN project ON task_group.project_id = project.project_id | ||||||
|   WHERE task_id = $1 |   WHERE task_id = $1 | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type GetProjectInfoForTaskRow struct { | type GetProjectInfoForTaskRow struct { | ||||||
| 	ProjectID uuid.UUID `json:"project_id"` | 	ProjectShortID string `json:"project_short_id"` | ||||||
| 	Name      string    `json:"name"` | 	Name           string `json:"name"` | ||||||
|  | 	TaskShortID    string `json:"task_short_id"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (q *Queries) GetProjectInfoForTask(ctx context.Context, taskID uuid.UUID) (GetProjectInfoForTaskRow, error) { | func (q *Queries) GetProjectInfoForTask(ctx context.Context, taskID uuid.UUID) (GetProjectInfoForTaskRow, error) { | ||||||
| 	row := q.db.QueryRowContext(ctx, getProjectInfoForTask, taskID) | 	row := q.db.QueryRowContext(ctx, getProjectInfoForTask, taskID) | ||||||
| 	var i GetProjectInfoForTaskRow | 	var i GetProjectInfoForTaskRow | ||||||
| 	err := row.Scan(&i.ProjectID, &i.Name) | 	err := row.Scan(&i.ProjectShortID, &i.Name, &i.TaskShortID) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
| 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, task.short_id FROM task_assigned INNER JOIN | ||||||
|   task ON task.task_id = task_assigned.task_id WHERE user_id = $1 |   task ON task.task_id = task_assigned.task_id WHERE user_id = $1 | ||||||
|   AND $4::boolean = true OR ( |   AND $4::boolean = true OR ( | ||||||
|     $4::boolean = false AND complete = $2 AND ( |     $4::boolean = false AND complete = $2 AND ( | ||||||
| @@ -507,6 +513,7 @@ func (q *Queries) GetRecentlyAssignedTaskForUserID(ctx context.Context, arg GetR | |||||||
| 			&i.Complete, | 			&i.Complete, | ||||||
| 			&i.CompletedAt, | 			&i.CompletedAt, | ||||||
| 			&i.HasTime, | 			&i.HasTime, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -522,7 +529,7 @@ func (q *Queries) GetRecentlyAssignedTaskForUserID(ctx context.Context, arg GetR | |||||||
| } | } | ||||||
|  |  | ||||||
| const getTaskByID = `-- name: GetTaskByID :one | const getTaskByID = `-- name: GetTaskByID :one | ||||||
| SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time FROM task WHERE task_id = $1 | SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id FROM task WHERE task_id = $1 | ||||||
| ` | ` | ||||||
|  |  | ||||||
| func (q *Queries) GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error) { | func (q *Queries) GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, error) { | ||||||
| @@ -539,10 +546,22 @@ func (q *Queries) GetTaskByID(ctx context.Context, taskID uuid.UUID) (Task, erro | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | const getTaskIDByShortID = `-- name: GetTaskIDByShortID :one | ||||||
|  | SELECT task_id FROM task WHERE short_id = $1 | ||||||
|  | ` | ||||||
|  |  | ||||||
|  | func (q *Queries) GetTaskIDByShortID(ctx context.Context, shortID string) (uuid.UUID, error) { | ||||||
|  | 	row := q.db.QueryRowContext(ctx, getTaskIDByShortID, shortID) | ||||||
|  | 	var task_id uuid.UUID | ||||||
|  | 	err := row.Scan(&task_id) | ||||||
|  | 	return task_id, err | ||||||
|  | } | ||||||
|  |  | ||||||
| const getTaskWatcher = `-- name: GetTaskWatcher :one | const getTaskWatcher = `-- name: GetTaskWatcher :one | ||||||
| SELECT task_watcher_id, task_id, user_id, watched_at FROM task_watcher WHERE user_id = $1 AND task_id = $2 | SELECT task_watcher_id, task_id, user_id, watched_at FROM task_watcher WHERE user_id = $1 AND task_id = $2 | ||||||
| ` | ` | ||||||
| @@ -565,7 +584,7 @@ func (q *Queries) GetTaskWatcher(ctx context.Context, arg GetTaskWatcherParams) | |||||||
| } | } | ||||||
|  |  | ||||||
| const getTasksForTaskGroupID = `-- name: GetTasksForTaskGroupID :many | const getTasksForTaskGroupID = `-- name: GetTasksForTaskGroupID :many | ||||||
| SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time FROM task WHERE task_group_id = $1 | SELECT task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id FROM task WHERE task_group_id = $1 | ||||||
| ` | ` | ||||||
|  |  | ||||||
| func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error) { | func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.UUID) ([]Task, error) { | ||||||
| @@ -588,6 +607,7 @@ func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.U | |||||||
| 			&i.Complete, | 			&i.Complete, | ||||||
| 			&i.CompletedAt, | 			&i.CompletedAt, | ||||||
| 			&i.HasTime, | 			&i.HasTime, | ||||||
|  | 			&i.ShortID, | ||||||
| 		); err != nil { | 		); err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| @@ -603,7 +623,7 @@ func (q *Queries) GetTasksForTaskGroupID(ctx context.Context, taskGroupID uuid.U | |||||||
| } | } | ||||||
|  |  | ||||||
| const setTaskComplete = `-- name: SetTaskComplete :one | const setTaskComplete = `-- name: SetTaskComplete :one | ||||||
| UPDATE task SET complete = $2, completed_at = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time | UPDATE task SET complete = $2, completed_at = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type SetTaskCompleteParams struct { | type SetTaskCompleteParams struct { | ||||||
| @@ -626,6 +646,7 @@ func (q *Queries) SetTaskComplete(ctx context.Context, arg SetTaskCompleteParams | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
| @@ -656,7 +677,7 @@ func (q *Queries) UpdateTaskComment(ctx context.Context, arg UpdateTaskCommentPa | |||||||
| } | } | ||||||
|  |  | ||||||
| const updateTaskDescription = `-- name: UpdateTaskDescription :one | const updateTaskDescription = `-- name: UpdateTaskDescription :one | ||||||
| UPDATE task SET description = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time | UPDATE task SET description = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type UpdateTaskDescriptionParams struct { | type UpdateTaskDescriptionParams struct { | ||||||
| @@ -678,12 +699,13 @@ func (q *Queries) UpdateTaskDescription(ctx context.Context, arg UpdateTaskDescr | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
| const updateTaskDueDate = `-- name: UpdateTaskDueDate :one | const updateTaskDueDate = `-- name: UpdateTaskDueDate :one | ||||||
| UPDATE task SET due_date = $2, has_time = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time | UPDATE task SET due_date = $2, has_time = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type UpdateTaskDueDateParams struct { | type UpdateTaskDueDateParams struct { | ||||||
| @@ -706,12 +728,13 @@ func (q *Queries) UpdateTaskDueDate(ctx context.Context, arg UpdateTaskDueDatePa | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
| const updateTaskLocation = `-- name: UpdateTaskLocation :one | const updateTaskLocation = `-- name: UpdateTaskLocation :one | ||||||
| UPDATE task SET task_group_id = $2, position = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time | UPDATE task SET task_group_id = $2, position = $3 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type UpdateTaskLocationParams struct { | type UpdateTaskLocationParams struct { | ||||||
| @@ -734,12 +757,13 @@ func (q *Queries) UpdateTaskLocation(ctx context.Context, arg UpdateTaskLocation | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
| const updateTaskName = `-- name: UpdateTaskName :one | const updateTaskName = `-- name: UpdateTaskName :one | ||||||
| UPDATE task SET name = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time | UPDATE task SET name = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type UpdateTaskNameParams struct { | type UpdateTaskNameParams struct { | ||||||
| @@ -761,12 +785,13 @@ func (q *Queries) UpdateTaskName(ctx context.Context, arg UpdateTaskNameParams) | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|  |  | ||||||
| const updateTaskPosition = `-- name: UpdateTaskPosition :one | const updateTaskPosition = `-- name: UpdateTaskPosition :one | ||||||
| UPDATE task SET position = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time | UPDATE task SET position = $2 WHERE task_id = $1 RETURNING task_id, task_group_id, created_at, name, position, description, due_date, complete, completed_at, has_time, short_id | ||||||
| ` | ` | ||||||
|  |  | ||||||
| type UpdateTaskPositionParams struct { | type UpdateTaskPositionParams struct { | ||||||
| @@ -788,6 +813,7 @@ func (q *Queries) UpdateTaskPosition(ctx context.Context, arg UpdateTaskPosition | |||||||
| 		&i.Complete, | 		&i.Complete, | ||||||
| 		&i.CompletedAt, | 		&i.CompletedAt, | ||||||
| 		&i.HasTime, | 		&i.HasTime, | ||||||
|  | 		&i.ShortID, | ||||||
| 	) | 	) | ||||||
| 	return i, err | 	return i, err | ||||||
| } | } | ||||||
|   | |||||||
| @@ -359,6 +359,7 @@ type ComplexityRoot struct { | |||||||
| 		Name           func(childComplexity int) int | 		Name           func(childComplexity int) int | ||||||
| 		Permission     func(childComplexity int) int | 		Permission     func(childComplexity int) int | ||||||
| 		PublicOn       func(childComplexity int) int | 		PublicOn       func(childComplexity int) int | ||||||
|  | 		ShortID        func(childComplexity int) int | ||||||
| 		TaskGroups     func(childComplexity int) int | 		TaskGroups     func(childComplexity int) int | ||||||
| 		Team           func(childComplexity int) int | 		Team           func(childComplexity int) int | ||||||
| 	} | 	} | ||||||
| @@ -436,6 +437,7 @@ type ComplexityRoot struct { | |||||||
| 		Labels      func(childComplexity int) int | 		Labels      func(childComplexity int) int | ||||||
| 		Name        func(childComplexity int) int | 		Name        func(childComplexity int) int | ||||||
| 		Position    func(childComplexity int) int | 		Position    func(childComplexity int) int | ||||||
|  | 		ShortID     func(childComplexity int) int | ||||||
| 		TaskGroup   func(childComplexity int) int | 		TaskGroup   func(childComplexity int) int | ||||||
| 		Watched     func(childComplexity int) int | 		Watched     func(childComplexity int) int | ||||||
| 	} | 	} | ||||||
| @@ -680,11 +682,9 @@ type QueryResolver interface { | |||||||
| 	Users(ctx context.Context) ([]db.UserAccount, error) | 	Users(ctx context.Context) ([]db.UserAccount, error) | ||||||
| 	InvitedUsers(ctx context.Context) ([]InvitedUserAccount, error) | 	InvitedUsers(ctx context.Context) ([]InvitedUserAccount, error) | ||||||
| 	FindUser(ctx context.Context, input FindUser) (*db.UserAccount, error) | 	FindUser(ctx context.Context, input FindUser) (*db.UserAccount, error) | ||||||
| 	FindProject(ctx context.Context, input FindProject) (*db.Project, error) |  | ||||||
| 	FindTask(ctx context.Context, input FindTask) (*db.Task, error) |  | ||||||
| 	Projects(ctx context.Context, input *ProjectsFilter) ([]db.Project, error) | 	Projects(ctx context.Context, input *ProjectsFilter) ([]db.Project, error) | ||||||
| 	FindTeam(ctx context.Context, input FindTeam) (*db.Team, error) |  | ||||||
| 	Teams(ctx context.Context) ([]db.Team, error) | 	Teams(ctx context.Context) ([]db.Team, error) | ||||||
|  | 	FindTeam(ctx context.Context, input FindTeam) (*db.Team, error) | ||||||
| 	MyTasks(ctx context.Context, input MyTasks) (*MyTasksPayload, error) | 	MyTasks(ctx context.Context, input MyTasks) (*MyTasksPayload, error) | ||||||
| 	LabelColors(ctx context.Context) ([]db.LabelColor, error) | 	LabelColors(ctx context.Context) ([]db.LabelColor, error) | ||||||
| 	TaskGroups(ctx context.Context) ([]db.TaskGroup, error) | 	TaskGroups(ctx context.Context) ([]db.TaskGroup, error) | ||||||
| @@ -692,6 +692,8 @@ type QueryResolver interface { | |||||||
| 	Notifications(ctx context.Context) ([]Notified, error) | 	Notifications(ctx context.Context) ([]Notified, error) | ||||||
| 	Notified(ctx context.Context, input NotifiedInput) (*NotifiedResult, error) | 	Notified(ctx context.Context, input NotifiedInput) (*NotifiedResult, error) | ||||||
| 	HasUnreadNotifications(ctx context.Context) (*HasUnreadNotificationsResult, error) | 	HasUnreadNotifications(ctx context.Context) (*HasUnreadNotificationsResult, error) | ||||||
|  | 	FindProject(ctx context.Context, input FindProject) (*db.Project, error) | ||||||
|  | 	FindTask(ctx context.Context, input FindTask) (*db.Task, error) | ||||||
| 	SearchMembers(ctx context.Context, input MemberSearchFilter) ([]MemberSearchResult, error) | 	SearchMembers(ctx context.Context, input MemberSearchFilter) ([]MemberSearchResult, error) | ||||||
| } | } | ||||||
| type SubscriptionResolver interface { | type SubscriptionResolver interface { | ||||||
| @@ -699,6 +701,7 @@ type SubscriptionResolver interface { | |||||||
| } | } | ||||||
| type TaskResolver interface { | type TaskResolver interface { | ||||||
| 	ID(ctx context.Context, obj *db.Task) (uuid.UUID, error) | 	ID(ctx context.Context, obj *db.Task) (uuid.UUID, error) | ||||||
|  |  | ||||||
| 	TaskGroup(ctx context.Context, obj *db.Task) (*db.TaskGroup, error) | 	TaskGroup(ctx context.Context, obj *db.Task) (*db.TaskGroup, error) | ||||||
|  |  | ||||||
| 	Description(ctx context.Context, obj *db.Task) (*string, error) | 	Description(ctx context.Context, obj *db.Task) (*string, error) | ||||||
| @@ -2264,6 +2267,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in | |||||||
|  |  | ||||||
| 		return e.complexity.Project.PublicOn(childComplexity), true | 		return e.complexity.Project.PublicOn(childComplexity), true | ||||||
|  |  | ||||||
|  | 	case "Project.shortId": | ||||||
|  | 		if e.complexity.Project.ShortID == nil { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return e.complexity.Project.ShortID(childComplexity), true | ||||||
|  |  | ||||||
| 	case "Project.taskGroups": | 	case "Project.taskGroups": | ||||||
| 		if e.complexity.Project.TaskGroups == nil { | 		if e.complexity.Project.TaskGroups == nil { | ||||||
| 			break | 			break | ||||||
| @@ -2654,6 +2664,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in | |||||||
|  |  | ||||||
| 		return e.complexity.Task.Position(childComplexity), true | 		return e.complexity.Task.Position(childComplexity), true | ||||||
|  |  | ||||||
|  | 	case "Task.shortId": | ||||||
|  | 		if e.complexity.Task.ShortID == nil { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return e.complexity.Task.ShortID(childComplexity), true | ||||||
|  |  | ||||||
| 	case "Task.taskGroup": | 	case "Task.taskGroup": | ||||||
| 		if e.complexity.Task.TaskGroup == nil { | 		if e.complexity.Task.TaskGroup == nil { | ||||||
| 			break | 			break | ||||||
| @@ -3364,6 +3381,7 @@ type Notified { | |||||||
|  |  | ||||||
| type Project { | type Project { | ||||||
|   id: ID! |   id: ID! | ||||||
|  |   shortId: String! | ||||||
|   createdAt: Time! |   createdAt: Time! | ||||||
|   name: String! |   name: String! | ||||||
|   team: Team |   team: Team | ||||||
| @@ -3503,6 +3521,15 @@ type UpdateProjectMemberRolePayload { | |||||||
|   member: Member! |   member: Member! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | extend type Query { | ||||||
|  |   findProject(input: FindProject!): Project! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FindProject { | ||||||
|  |   projectID: UUID | ||||||
|  |   projectShortID: String | ||||||
|  | } | ||||||
|  |  | ||||||
| extend type Mutation { | extend type Mutation { | ||||||
|   createProject(input: NewProject!): Project! @hasRole(roles: [ADMIN], level: TEAM, type: TEAM) |   createProject(input: NewProject!): Project! @hasRole(roles: [ADMIN], level: TEAM, type: TEAM) | ||||||
|   deleteProject(input: DeleteProject!): |   deleteProject(input: DeleteProject!): | ||||||
| @@ -3618,12 +3645,9 @@ type Query { | |||||||
|   users: [UserAccount!]! |   users: [UserAccount!]! | ||||||
|   invitedUsers: [InvitedUserAccount!]! |   invitedUsers: [InvitedUserAccount!]! | ||||||
|   findUser(input: FindUser!): UserAccount! |   findUser(input: FindUser!): UserAccount! | ||||||
|   findProject(input: FindProject!): |  | ||||||
|     Project! |  | ||||||
|   findTask(input: FindTask!): Task! |  | ||||||
|   projects(input: ProjectsFilter): [Project!]! |   projects(input: ProjectsFilter): [Project!]! | ||||||
|   findTeam(input: FindTeam!): Team! |  | ||||||
|   teams: [Team!]! |   teams: [Team!]! | ||||||
|  |   findTeam(input: FindTeam!): Team! | ||||||
|   myTasks(input: MyTasks!): MyTasksPayload! |   myTasks(input: MyTasks!): MyTasksPayload! | ||||||
|   labelColors: [LabelColor!]! |   labelColors: [LabelColor!]! | ||||||
|   taskGroups: [TaskGroup!]! |   taskGroups: [TaskGroup!]! | ||||||
| @@ -3691,13 +3715,6 @@ input FindUser { | |||||||
|   userID: UUID! |   userID: UUID! | ||||||
| } | } | ||||||
|  |  | ||||||
| input FindProject { |  | ||||||
|   projectID: UUID! |  | ||||||
| } |  | ||||||
|  |  | ||||||
| input FindTask { |  | ||||||
|   taskID: UUID! |  | ||||||
| } |  | ||||||
|  |  | ||||||
| input FindTeam { | input FindTeam { | ||||||
|   teamID: UUID! |   teamID: UUID! | ||||||
| @@ -3727,6 +3744,7 @@ type TaskBadges { | |||||||
|  |  | ||||||
| type Task { | type Task { | ||||||
|   id: ID! |   id: ID! | ||||||
|  |   shortId: String! | ||||||
|   taskGroup: TaskGroup! |   taskGroup: TaskGroup! | ||||||
|   createdAt: Time! |   createdAt: Time! | ||||||
|   name: String! |   name: String! | ||||||
| @@ -4042,6 +4060,16 @@ type ToggleTaskLabelPayload { | |||||||
|   task: Task! |   task: Task! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | extend type Query { | ||||||
|  |   findTask(input: FindTask!): Task! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FindTask { | ||||||
|  |   taskID: UUID | ||||||
|  |   taskShortID: String | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| extend type Mutation { | extend type Mutation { | ||||||
|   createTask(input: NewTask!): |   createTask(input: NewTask!): | ||||||
|     Task! @hasRole(roles: [ADMIN, MEMBER], level: PROJECT, type: TASK_GROUP) |     Task! @hasRole(roles: [ADMIN, MEMBER], level: PROJECT, type: TASK_GROUP) | ||||||
| @@ -13300,6 +13328,41 @@ func (ec *executionContext) _Project_id(ctx context.Context, field graphql.Colle | |||||||
| 	return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res) | 	return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (ec *executionContext) _Project_shortId(ctx context.Context, field graphql.CollectedField, obj *db.Project) (ret graphql.Marshaler) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 			ret = graphql.Null | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	fc := &graphql.FieldContext{ | ||||||
|  | 		Object:     "Project", | ||||||
|  | 		Field:      field, | ||||||
|  | 		Args:       nil, | ||||||
|  | 		IsMethod:   false, | ||||||
|  | 		IsResolver: false, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx = graphql.WithFieldContext(ctx, fc) | ||||||
|  | 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { | ||||||
|  | 		ctx = rctx // use context from middleware stack in children | ||||||
|  | 		return obj.ShortID, nil | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	if resTmp == nil { | ||||||
|  | 		if !graphql.HasFieldError(ctx, fc) { | ||||||
|  | 			ec.Errorf(ctx, "must not be null") | ||||||
|  | 		} | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	res := resTmp.(string) | ||||||
|  | 	fc.Result = res | ||||||
|  | 	return ec.marshalNString2string(ctx, field.Selections, res) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (ec *executionContext) _Project_createdAt(ctx context.Context, field graphql.CollectedField, obj *db.Project) (ret graphql.Marshaler) { | func (ec *executionContext) _Project_createdAt(ctx context.Context, field graphql.CollectedField, obj *db.Project) (ret graphql.Marshaler) { | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if r := recover(); r != nil { | 		if r := recover(); r != nil { | ||||||
| @@ -14138,90 +14201,6 @@ func (ec *executionContext) _Query_findUser(ctx context.Context, field graphql.C | |||||||
| 	return ec.marshalNUserAccount2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐUserAccount(ctx, field.Selections, res) | 	return ec.marshalNUserAccount2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐUserAccount(ctx, field.Selections, res) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_findProject(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { |  | ||||||
| 	defer func() { |  | ||||||
| 		if r := recover(); r != nil { |  | ||||||
| 			ec.Error(ctx, ec.Recover(ctx, r)) |  | ||||||
| 			ret = graphql.Null |  | ||||||
| 		} |  | ||||||
| 	}() |  | ||||||
| 	fc := &graphql.FieldContext{ |  | ||||||
| 		Object:     "Query", |  | ||||||
| 		Field:      field, |  | ||||||
| 		Args:       nil, |  | ||||||
| 		IsMethod:   true, |  | ||||||
| 		IsResolver: true, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx = graphql.WithFieldContext(ctx, fc) |  | ||||||
| 	rawArgs := field.ArgumentMap(ec.Variables) |  | ||||||
| 	args, err := ec.field_Query_findProject_args(ctx, rawArgs) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ec.Error(ctx, err) |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	fc.Args = args |  | ||||||
| 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { |  | ||||||
| 		ctx = rctx // use context from middleware stack in children |  | ||||||
| 		return ec.resolvers.Query().FindProject(rctx, args["input"].(FindProject)) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ec.Error(ctx, err) |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	if resTmp == nil { |  | ||||||
| 		if !graphql.HasFieldError(ctx, fc) { |  | ||||||
| 			ec.Errorf(ctx, "must not be null") |  | ||||||
| 		} |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	res := resTmp.(*db.Project) |  | ||||||
| 	fc.Result = res |  | ||||||
| 	return ec.marshalNProject2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProject(ctx, field.Selections, res) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_findTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { |  | ||||||
| 	defer func() { |  | ||||||
| 		if r := recover(); r != nil { |  | ||||||
| 			ec.Error(ctx, ec.Recover(ctx, r)) |  | ||||||
| 			ret = graphql.Null |  | ||||||
| 		} |  | ||||||
| 	}() |  | ||||||
| 	fc := &graphql.FieldContext{ |  | ||||||
| 		Object:     "Query", |  | ||||||
| 		Field:      field, |  | ||||||
| 		Args:       nil, |  | ||||||
| 		IsMethod:   true, |  | ||||||
| 		IsResolver: true, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx = graphql.WithFieldContext(ctx, fc) |  | ||||||
| 	rawArgs := field.ArgumentMap(ec.Variables) |  | ||||||
| 	args, err := ec.field_Query_findTask_args(ctx, rawArgs) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ec.Error(ctx, err) |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	fc.Args = args |  | ||||||
| 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { |  | ||||||
| 		ctx = rctx // use context from middleware stack in children |  | ||||||
| 		return ec.resolvers.Query().FindTask(rctx, args["input"].(FindTask)) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ec.Error(ctx, err) |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	if resTmp == nil { |  | ||||||
| 		if !graphql.HasFieldError(ctx, fc) { |  | ||||||
| 			ec.Errorf(ctx, "must not be null") |  | ||||||
| 		} |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	res := resTmp.(*db.Task) |  | ||||||
| 	fc.Result = res |  | ||||||
| 	return ec.marshalNTask2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTask(ctx, field.Selections, res) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_projects(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | func (ec *executionContext) _Query_projects(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if r := recover(); r != nil { | 		if r := recover(); r != nil { | ||||||
| @@ -14264,6 +14243,41 @@ func (ec *executionContext) _Query_projects(ctx context.Context, field graphql.C | |||||||
| 	return ec.marshalNProject2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProjectᚄ(ctx, field.Selections, res) | 	return ec.marshalNProject2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProjectᚄ(ctx, field.Selections, res) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (ec *executionContext) _Query_teams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 			ret = graphql.Null | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	fc := &graphql.FieldContext{ | ||||||
|  | 		Object:     "Query", | ||||||
|  | 		Field:      field, | ||||||
|  | 		Args:       nil, | ||||||
|  | 		IsMethod:   true, | ||||||
|  | 		IsResolver: true, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx = graphql.WithFieldContext(ctx, fc) | ||||||
|  | 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { | ||||||
|  | 		ctx = rctx // use context from middleware stack in children | ||||||
|  | 		return ec.resolvers.Query().Teams(rctx) | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	if resTmp == nil { | ||||||
|  | 		if !graphql.HasFieldError(ctx, fc) { | ||||||
|  | 			ec.Errorf(ctx, "must not be null") | ||||||
|  | 		} | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	res := resTmp.([]db.Team) | ||||||
|  | 	fc.Result = res | ||||||
|  | 	return ec.marshalNTeam2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTeamᚄ(ctx, field.Selections, res) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_findTeam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | func (ec *executionContext) _Query_findTeam(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if r := recover(); r != nil { | 		if r := recover(); r != nil { | ||||||
| @@ -14306,41 +14320,6 @@ func (ec *executionContext) _Query_findTeam(ctx context.Context, field graphql.C | |||||||
| 	return ec.marshalNTeam2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTeam(ctx, field.Selections, res) | 	return ec.marshalNTeam2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTeam(ctx, field.Selections, res) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_teams(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { |  | ||||||
| 	defer func() { |  | ||||||
| 		if r := recover(); r != nil { |  | ||||||
| 			ec.Error(ctx, ec.Recover(ctx, r)) |  | ||||||
| 			ret = graphql.Null |  | ||||||
| 		} |  | ||||||
| 	}() |  | ||||||
| 	fc := &graphql.FieldContext{ |  | ||||||
| 		Object:     "Query", |  | ||||||
| 		Field:      field, |  | ||||||
| 		Args:       nil, |  | ||||||
| 		IsMethod:   true, |  | ||||||
| 		IsResolver: true, |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx = graphql.WithFieldContext(ctx, fc) |  | ||||||
| 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { |  | ||||||
| 		ctx = rctx // use context from middleware stack in children |  | ||||||
| 		return ec.resolvers.Query().Teams(rctx) |  | ||||||
| 	}) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ec.Error(ctx, err) |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	if resTmp == nil { |  | ||||||
| 		if !graphql.HasFieldError(ctx, fc) { |  | ||||||
| 			ec.Errorf(ctx, "must not be null") |  | ||||||
| 		} |  | ||||||
| 		return graphql.Null |  | ||||||
| 	} |  | ||||||
| 	res := resTmp.([]db.Team) |  | ||||||
| 	fc.Result = res |  | ||||||
| 	return ec.marshalNTeam2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTeamᚄ(ctx, field.Selections, res) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_myTasks(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | func (ec *executionContext) _Query_myTasks(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if r := recover(); r != nil { | 		if r := recover(); r != nil { | ||||||
| @@ -14597,6 +14576,90 @@ func (ec *executionContext) _Query_hasUnreadNotifications(ctx context.Context, f | |||||||
| 	return ec.marshalNHasUnreadNotificationsResult2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐHasUnreadNotificationsResult(ctx, field.Selections, res) | 	return ec.marshalNHasUnreadNotificationsResult2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐHasUnreadNotificationsResult(ctx, field.Selections, res) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (ec *executionContext) _Query_findProject(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 			ret = graphql.Null | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	fc := &graphql.FieldContext{ | ||||||
|  | 		Object:     "Query", | ||||||
|  | 		Field:      field, | ||||||
|  | 		Args:       nil, | ||||||
|  | 		IsMethod:   true, | ||||||
|  | 		IsResolver: true, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx = graphql.WithFieldContext(ctx, fc) | ||||||
|  | 	rawArgs := field.ArgumentMap(ec.Variables) | ||||||
|  | 	args, err := ec.field_Query_findProject_args(ctx, rawArgs) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	fc.Args = args | ||||||
|  | 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { | ||||||
|  | 		ctx = rctx // use context from middleware stack in children | ||||||
|  | 		return ec.resolvers.Query().FindProject(rctx, args["input"].(FindProject)) | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	if resTmp == nil { | ||||||
|  | 		if !graphql.HasFieldError(ctx, fc) { | ||||||
|  | 			ec.Errorf(ctx, "must not be null") | ||||||
|  | 		} | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	res := resTmp.(*db.Project) | ||||||
|  | 	fc.Result = res | ||||||
|  | 	return ec.marshalNProject2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProject(ctx, field.Selections, res) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (ec *executionContext) _Query_findTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 			ret = graphql.Null | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	fc := &graphql.FieldContext{ | ||||||
|  | 		Object:     "Query", | ||||||
|  | 		Field:      field, | ||||||
|  | 		Args:       nil, | ||||||
|  | 		IsMethod:   true, | ||||||
|  | 		IsResolver: true, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx = graphql.WithFieldContext(ctx, fc) | ||||||
|  | 	rawArgs := field.ArgumentMap(ec.Variables) | ||||||
|  | 	args, err := ec.field_Query_findTask_args(ctx, rawArgs) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	fc.Args = args | ||||||
|  | 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { | ||||||
|  | 		ctx = rctx // use context from middleware stack in children | ||||||
|  | 		return ec.resolvers.Query().FindTask(rctx, args["input"].(FindTask)) | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	if resTmp == nil { | ||||||
|  | 		if !graphql.HasFieldError(ctx, fc) { | ||||||
|  | 			ec.Errorf(ctx, "must not be null") | ||||||
|  | 		} | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	res := resTmp.(*db.Task) | ||||||
|  | 	fc.Result = res | ||||||
|  | 	return ec.marshalNTask2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTask(ctx, field.Selections, res) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (ec *executionContext) _Query_searchMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | func (ec *executionContext) _Query_searchMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if r := recover(); r != nil { | 		if r := recover(); r != nil { | ||||||
| @@ -14930,6 +14993,41 @@ func (ec *executionContext) _Task_id(ctx context.Context, field graphql.Collecte | |||||||
| 	return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res) | 	return ec.marshalNID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (ec *executionContext) _Task_shortId(ctx context.Context, field graphql.CollectedField, obj *db.Task) (ret graphql.Marshaler) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 			ret = graphql.Null | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	fc := &graphql.FieldContext{ | ||||||
|  | 		Object:     "Task", | ||||||
|  | 		Field:      field, | ||||||
|  | 		Args:       nil, | ||||||
|  | 		IsMethod:   false, | ||||||
|  | 		IsResolver: false, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx = graphql.WithFieldContext(ctx, fc) | ||||||
|  | 	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { | ||||||
|  | 		ctx = rctx // use context from middleware stack in children | ||||||
|  | 		return obj.ShortID, nil | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ec.Error(ctx, err) | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	if resTmp == nil { | ||||||
|  | 		if !graphql.HasFieldError(ctx, fc) { | ||||||
|  | 			ec.Errorf(ctx, "must not be null") | ||||||
|  | 		} | ||||||
|  | 		return graphql.Null | ||||||
|  | 	} | ||||||
|  | 	res := resTmp.(string) | ||||||
|  | 	fc.Result = res | ||||||
|  | 	return ec.marshalNString2string(ctx, field.Selections, res) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (ec *executionContext) _Task_taskGroup(ctx context.Context, field graphql.CollectedField, obj *db.Task) (ret graphql.Marshaler) { | func (ec *executionContext) _Task_taskGroup(ctx context.Context, field graphql.CollectedField, obj *db.Task) (ret graphql.Marshaler) { | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if r := recover(); r != nil { | 		if r := recover(); r != nil { | ||||||
| @@ -19707,7 +19805,15 @@ func (ec *executionContext) unmarshalInputFindProject(ctx context.Context, obj i | |||||||
| 			var err error | 			var err error | ||||||
|  |  | ||||||
| 			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) | 			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) | ||||||
| 			it.ProjectID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) | 			it.ProjectID, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return it, err | ||||||
|  | 			} | ||||||
|  | 		case "projectShortID": | ||||||
|  | 			var err error | ||||||
|  |  | ||||||
|  | 			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectShortID")) | ||||||
|  | 			it.ProjectShortID, err = ec.unmarshalOString2ᚖstring(ctx, v) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return it, err | 				return it, err | ||||||
| 			} | 			} | ||||||
| @@ -19727,7 +19833,15 @@ func (ec *executionContext) unmarshalInputFindTask(ctx context.Context, obj inte | |||||||
| 			var err error | 			var err error | ||||||
|  |  | ||||||
| 			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("taskID")) | 			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("taskID")) | ||||||
| 			it.TaskID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) | 			it.TaskID, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return it, err | ||||||
|  | 			} | ||||||
|  | 		case "taskShortID": | ||||||
|  | 			var err error | ||||||
|  |  | ||||||
|  | 			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("taskShortID")) | ||||||
|  | 			it.TaskShortID, err = ec.unmarshalOString2ᚖstring(ctx, v) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return it, err | 				return it, err | ||||||
| 			} | 			} | ||||||
| @@ -22875,6 +22989,11 @@ func (ec *executionContext) _Project(ctx context.Context, sel ast.SelectionSet, | |||||||
| 				} | 				} | ||||||
| 				return res | 				return res | ||||||
| 			}) | 			}) | ||||||
|  | 		case "shortId": | ||||||
|  | 			out.Values[i] = ec._Project_shortId(ctx, field, obj) | ||||||
|  | 			if out.Values[i] == graphql.Null { | ||||||
|  | 				atomic.AddUint32(&invalids, 1) | ||||||
|  | 			} | ||||||
| 		case "createdAt": | 		case "createdAt": | ||||||
| 			out.Values[i] = ec._Project_createdAt(ctx, field, obj) | 			out.Values[i] = ec._Project_createdAt(ctx, field, obj) | ||||||
| 			if out.Values[i] == graphql.Null { | 			if out.Values[i] == graphql.Null { | ||||||
| @@ -23226,34 +23345,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr | |||||||
| 				} | 				} | ||||||
| 				return res | 				return res | ||||||
| 			}) | 			}) | ||||||
| 		case "findProject": |  | ||||||
| 			field := field |  | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { |  | ||||||
| 				defer func() { |  | ||||||
| 					if r := recover(); r != nil { |  | ||||||
| 						ec.Error(ctx, ec.Recover(ctx, r)) |  | ||||||
| 					} |  | ||||||
| 				}() |  | ||||||
| 				res = ec._Query_findProject(ctx, field) |  | ||||||
| 				if res == graphql.Null { |  | ||||||
| 					atomic.AddUint32(&invalids, 1) |  | ||||||
| 				} |  | ||||||
| 				return res |  | ||||||
| 			}) |  | ||||||
| 		case "findTask": |  | ||||||
| 			field := field |  | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { |  | ||||||
| 				defer func() { |  | ||||||
| 					if r := recover(); r != nil { |  | ||||||
| 						ec.Error(ctx, ec.Recover(ctx, r)) |  | ||||||
| 					} |  | ||||||
| 				}() |  | ||||||
| 				res = ec._Query_findTask(ctx, field) |  | ||||||
| 				if res == graphql.Null { |  | ||||||
| 					atomic.AddUint32(&invalids, 1) |  | ||||||
| 				} |  | ||||||
| 				return res |  | ||||||
| 			}) |  | ||||||
| 		case "projects": | 		case "projects": | ||||||
| 			field := field | 			field := field | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
| @@ -23268,20 +23359,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr | |||||||
| 				} | 				} | ||||||
| 				return res | 				return res | ||||||
| 			}) | 			}) | ||||||
| 		case "findTeam": |  | ||||||
| 			field := field |  | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { |  | ||||||
| 				defer func() { |  | ||||||
| 					if r := recover(); r != nil { |  | ||||||
| 						ec.Error(ctx, ec.Recover(ctx, r)) |  | ||||||
| 					} |  | ||||||
| 				}() |  | ||||||
| 				res = ec._Query_findTeam(ctx, field) |  | ||||||
| 				if res == graphql.Null { |  | ||||||
| 					atomic.AddUint32(&invalids, 1) |  | ||||||
| 				} |  | ||||||
| 				return res |  | ||||||
| 			}) |  | ||||||
| 		case "teams": | 		case "teams": | ||||||
| 			field := field | 			field := field | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
| @@ -23296,6 +23373,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr | |||||||
| 				} | 				} | ||||||
| 				return res | 				return res | ||||||
| 			}) | 			}) | ||||||
|  | 		case "findTeam": | ||||||
|  | 			field := field | ||||||
|  | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
|  | 				defer func() { | ||||||
|  | 					if r := recover(); r != nil { | ||||||
|  | 						ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 					} | ||||||
|  | 				}() | ||||||
|  | 				res = ec._Query_findTeam(ctx, field) | ||||||
|  | 				if res == graphql.Null { | ||||||
|  | 					atomic.AddUint32(&invalids, 1) | ||||||
|  | 				} | ||||||
|  | 				return res | ||||||
|  | 			}) | ||||||
| 		case "myTasks": | 		case "myTasks": | ||||||
| 			field := field | 			field := field | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
| @@ -23391,6 +23482,34 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr | |||||||
| 				} | 				} | ||||||
| 				return res | 				return res | ||||||
| 			}) | 			}) | ||||||
|  | 		case "findProject": | ||||||
|  | 			field := field | ||||||
|  | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
|  | 				defer func() { | ||||||
|  | 					if r := recover(); r != nil { | ||||||
|  | 						ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 					} | ||||||
|  | 				}() | ||||||
|  | 				res = ec._Query_findProject(ctx, field) | ||||||
|  | 				if res == graphql.Null { | ||||||
|  | 					atomic.AddUint32(&invalids, 1) | ||||||
|  | 				} | ||||||
|  | 				return res | ||||||
|  | 			}) | ||||||
|  | 		case "findTask": | ||||||
|  | 			field := field | ||||||
|  | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
|  | 				defer func() { | ||||||
|  | 					if r := recover(); r != nil { | ||||||
|  | 						ec.Error(ctx, ec.Recover(ctx, r)) | ||||||
|  | 					} | ||||||
|  | 				}() | ||||||
|  | 				res = ec._Query_findTask(ctx, field) | ||||||
|  | 				if res == graphql.Null { | ||||||
|  | 					atomic.AddUint32(&invalids, 1) | ||||||
|  | 				} | ||||||
|  | 				return res | ||||||
|  | 			}) | ||||||
| 		case "searchMembers": | 		case "searchMembers": | ||||||
| 			field := field | 			field := field | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
| @@ -23529,6 +23648,11 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj | |||||||
| 				} | 				} | ||||||
| 				return res | 				return res | ||||||
| 			}) | 			}) | ||||||
|  | 		case "shortId": | ||||||
|  | 			out.Values[i] = ec._Task_shortId(ctx, field, obj) | ||||||
|  | 			if out.Values[i] == graphql.Null { | ||||||
|  | 				atomic.AddUint32(&invalids, 1) | ||||||
|  | 			} | ||||||
| 		case "taskGroup": | 		case "taskGroup": | ||||||
| 			field := field | 			field := field | ||||||
| 			out.Concurrently(i, func() (res graphql.Marshaler) { | 			out.Concurrently(i, func() (res graphql.Marshaler) { | ||||||
|   | |||||||
| @@ -215,11 +215,13 @@ type DuplicateTaskGroupPayload struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type FindProject struct { | type FindProject struct { | ||||||
| 	ProjectID uuid.UUID `json:"projectID"` | 	ProjectID      *uuid.UUID `json:"projectID"` | ||||||
|  | 	ProjectShortID *string    `json:"projectShortID"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type FindTask struct { | type FindTask struct { | ||||||
| 	TaskID uuid.UUID `json:"taskID"` | 	TaskID      *uuid.UUID `json:"taskID"` | ||||||
|  | 	TaskShortID *string    `json:"taskShortID"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type FindTeam struct { | type FindTeam struct { | ||||||
|   | |||||||
| @@ -392,6 +392,39 @@ func (r *projectLabelResolver) Name(ctx context.Context, obj *db.ProjectLabel) ( | |||||||
| 	return name, nil | 	return name, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *queryResolver) FindProject(ctx context.Context, input FindProject) (*db.Project, error) { | ||||||
|  | 	_, isLoggedIn := GetUser(ctx) | ||||||
|  | 	var projectID uuid.UUID | ||||||
|  | 	var err error | ||||||
|  | 	if input.ProjectID != nil { | ||||||
|  | 		projectID = *input.ProjectID | ||||||
|  | 	} else if input.ProjectShortID != nil { | ||||||
|  | 		projectID, err = r.Repository.GetProjectIDByShortID(ctx, *input.ProjectShortID) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.WithError(err).Error("error while getting project id by short id") | ||||||
|  | 			return &db.Project{}, err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return &db.Project{}, errors.New("FindProject requires either ProjectID or ProjectShortID to be set") | ||||||
|  | 	} | ||||||
|  | 	if !isLoggedIn { | ||||||
|  | 		isPublic, _ := IsProjectPublic(ctx, r.Repository, projectID) | ||||||
|  | 		if !isPublic { | ||||||
|  | 			return &db.Project{}, NotAuthorized() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	project, err := r.Repository.GetProjectByID(ctx, projectID) | ||||||
|  | 	if err == sql.ErrNoRows { | ||||||
|  | 		return &db.Project{}, &gqlerror.Error{ | ||||||
|  | 			Message: "Project not found", | ||||||
|  | 			Extensions: map[string]interface{}{ | ||||||
|  | 				"code": "NOT_FOUND", | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return &project, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // LabelColor returns LabelColorResolver implementation. | // LabelColor returns LabelColorResolver implementation. | ||||||
| func (r *Resolver) LabelColor() LabelColorResolver { return &labelColorResolver{r} } | func (r *Resolver) LabelColor() LabelColorResolver { return &labelColorResolver{r} } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -61,31 +61,6 @@ func (r *queryResolver) FindUser(ctx context.Context, input FindUser) (*db.UserA | |||||||
| 	return &account, err | 	return &account, err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (r *queryResolver) FindProject(ctx context.Context, input FindProject) (*db.Project, error) { |  | ||||||
| 	_, isLoggedIn := GetUser(ctx) |  | ||||||
| 	if !isLoggedIn { |  | ||||||
| 		isPublic, _ := IsProjectPublic(ctx, r.Repository, input.ProjectID) |  | ||||||
| 		if !isPublic { |  | ||||||
| 			return &db.Project{}, NotAuthorized() |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	project, err := r.Repository.GetProjectByID(ctx, input.ProjectID) |  | ||||||
| 	if err == sql.ErrNoRows { |  | ||||||
| 		return &db.Project{}, &gqlerror.Error{ |  | ||||||
| 			Message: "Project not found", |  | ||||||
| 			Extensions: map[string]interface{}{ |  | ||||||
| 				"code": "NOT_FOUND", |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return &project, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*db.Task, error) { |  | ||||||
| 	task, err := r.Repository.GetTaskByID(ctx, input.TaskID) |  | ||||||
| 	return &task, err |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]db.Project, error) { | func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]db.Project, error) { | ||||||
| 	userID, ok := GetUser(ctx) | 	userID, ok := GetUser(ctx) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| @@ -137,14 +112,6 @@ func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([] | |||||||
| 	return allProjects, nil | 	return allProjects, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (r *queryResolver) FindTeam(ctx context.Context, input FindTeam) (*db.Team, error) { |  | ||||||
| 	team, err := r.Repository.GetTeamByID(ctx, input.TeamID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return &db.Team{}, err |  | ||||||
| 	} |  | ||||||
| 	return &team, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *queryResolver) Teams(ctx context.Context) ([]db.Team, error) { | func (r *queryResolver) Teams(ctx context.Context) ([]db.Team, error) { | ||||||
| 	userID, ok := GetUser(ctx) | 	userID, ok := GetUser(ctx) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| @@ -190,6 +157,14 @@ func (r *queryResolver) Teams(ctx context.Context) ([]db.Team, error) { | |||||||
| 	return foundTeams, nil | 	return foundTeams, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *queryResolver) FindTeam(ctx context.Context, input FindTeam) (*db.Team, error) { | ||||||
|  | 	team, err := r.Repository.GetTeamByID(ctx, input.TeamID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return &db.Team{}, err | ||||||
|  | 	} | ||||||
|  | 	return &team, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (r *queryResolver) MyTasks(ctx context.Context, input MyTasks) (*MyTasksPayload, error) { | func (r *queryResolver) MyTasks(ctx context.Context, input MyTasks) (*MyTasksPayload, error) { | ||||||
| 	userID, _ := GetUserID(ctx) | 	userID, _ := GetUserID(ctx) | ||||||
| 	projects := []ProjectTaskMapping{} | 	projects := []ProjectTaskMapping{} | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ type ProjectPermission { | |||||||
|  |  | ||||||
| type Project { | type Project { | ||||||
|   id: ID! |   id: ID! | ||||||
|  |   shortId: String! | ||||||
|   createdAt: Time! |   createdAt: Time! | ||||||
|   name: String! |   name: String! | ||||||
|   team: Team |   team: Team | ||||||
| @@ -145,6 +146,15 @@ type UpdateProjectMemberRolePayload { | |||||||
|   member: Member! |   member: Member! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | extend type Query { | ||||||
|  |   findProject(input: FindProject!): Project! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FindProject { | ||||||
|  |   projectID: UUID | ||||||
|  |   projectShortID: String | ||||||
|  | } | ||||||
|  |  | ||||||
| extend type Mutation { | extend type Mutation { | ||||||
|   createProject(input: NewProject!): Project! @hasRole(roles: [ADMIN], level: TEAM, type: TEAM) |   createProject(input: NewProject!): Project! @hasRole(roles: [ADMIN], level: TEAM, type: TEAM) | ||||||
|   deleteProject(input: DeleteProject!): |   deleteProject(input: DeleteProject!): | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ type ProjectPermission { | |||||||
|  |  | ||||||
| type Project { | type Project { | ||||||
|   id: ID! |   id: ID! | ||||||
|  |   shortId: String! | ||||||
|   createdAt: Time! |   createdAt: Time! | ||||||
|   name: String! |   name: String! | ||||||
|   team: Team |   team: Team | ||||||
|   | |||||||
| @@ -1,3 +1,12 @@ | |||||||
|  | extend type Query { | ||||||
|  |   findProject(input: FindProject!): Project! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FindProject { | ||||||
|  |   projectID: UUID | ||||||
|  |   projectShortID: String | ||||||
|  | } | ||||||
|  |  | ||||||
| extend type Mutation { | extend type Mutation { | ||||||
|   createProject(input: NewProject!): Project! @hasRole(roles: [ADMIN], level: TEAM, type: TEAM) |   createProject(input: NewProject!): Project! @hasRole(roles: [ADMIN], level: TEAM, type: TEAM) | ||||||
|   deleteProject(input: DeleteProject!): |   deleteProject(input: DeleteProject!): | ||||||
|   | |||||||
| @@ -75,12 +75,9 @@ type Query { | |||||||
|   users: [UserAccount!]! |   users: [UserAccount!]! | ||||||
|   invitedUsers: [InvitedUserAccount!]! |   invitedUsers: [InvitedUserAccount!]! | ||||||
|   findUser(input: FindUser!): UserAccount! |   findUser(input: FindUser!): UserAccount! | ||||||
|   findProject(input: FindProject!): |  | ||||||
|     Project! |  | ||||||
|   findTask(input: FindTask!): Task! |  | ||||||
|   projects(input: ProjectsFilter): [Project!]! |   projects(input: ProjectsFilter): [Project!]! | ||||||
|   findTeam(input: FindTeam!): Team! |  | ||||||
|   teams: [Team!]! |   teams: [Team!]! | ||||||
|  |   findTeam(input: FindTeam!): Team! | ||||||
|   myTasks(input: MyTasks!): MyTasksPayload! |   myTasks(input: MyTasks!): MyTasksPayload! | ||||||
|   labelColors: [LabelColor!]! |   labelColors: [LabelColor!]! | ||||||
|   taskGroups: [TaskGroup!]! |   taskGroups: [TaskGroup!]! | ||||||
| @@ -148,13 +145,6 @@ input FindUser { | |||||||
|   userID: UUID! |   userID: UUID! | ||||||
| } | } | ||||||
|  |  | ||||||
| input FindProject { |  | ||||||
|   projectID: UUID! |  | ||||||
| } |  | ||||||
|  |  | ||||||
| input FindTask { |  | ||||||
|   taskID: UUID! |  | ||||||
| } |  | ||||||
|  |  | ||||||
| input FindTeam { | input FindTeam { | ||||||
|   teamID: UUID! |   teamID: UUID! | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ type TaskBadges { | |||||||
|  |  | ||||||
| type Task { | type Task { | ||||||
|   id: ID! |   id: ID! | ||||||
|  |   shortId: String! | ||||||
|   taskGroup: TaskGroup! |   taskGroup: TaskGroup! | ||||||
|   createdAt: Time! |   createdAt: Time! | ||||||
|   name: String! |   name: String! | ||||||
| @@ -337,6 +338,16 @@ type ToggleTaskLabelPayload { | |||||||
|   task: Task! |   task: Task! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | extend type Query { | ||||||
|  |   findTask(input: FindTask!): Task! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FindTask { | ||||||
|  |   taskID: UUID | ||||||
|  |   taskShortID: String | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| extend type Mutation { | extend type Mutation { | ||||||
|   createTask(input: NewTask!): |   createTask(input: NewTask!): | ||||||
|     Task! @hasRole(roles: [ADMIN, MEMBER], level: PROJECT, type: TASK_GROUP) |     Task! @hasRole(roles: [ADMIN, MEMBER], level: PROJECT, type: TASK_GROUP) | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ type TaskBadges { | |||||||
|  |  | ||||||
| type Task { | type Task { | ||||||
|   id: ID! |   id: ID! | ||||||
|  |   shortId: String! | ||||||
|   taskGroup: TaskGroup! |   taskGroup: TaskGroup! | ||||||
|   createdAt: Time! |   createdAt: Time! | ||||||
|   name: String! |   name: String! | ||||||
|   | |||||||
| @@ -1,3 +1,13 @@ | |||||||
|  | extend type Query { | ||||||
|  |   findTask(input: FindTask!): Task! | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input FindTask { | ||||||
|  |   taskID: UUID | ||||||
|  |   taskShortID: String | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| extend type Mutation { | extend type Mutation { | ||||||
|   createTask(input: NewTask!): |   createTask(input: NewTask!): | ||||||
|     Task! @hasRole(roles: [ADMIN, MEMBER], level: PROJECT, type: TASK_GROUP) |     Task! @hasRole(roles: [ADMIN, MEMBER], level: PROJECT, type: TASK_GROUP) | ||||||
|   | |||||||
| @@ -635,9 +635,9 @@ func (r *mutationResolver) AssignTask(ctx context.Context, input *AssignTaskInpu | |||||||
| 			Data: map[string]string{ | 			Data: map[string]string{ | ||||||
| 				"CausedByUsername": causedBy.Username, | 				"CausedByUsername": causedBy.Username, | ||||||
| 				"CausedByFullName": causedBy.FullName, | 				"CausedByFullName": causedBy.FullName, | ||||||
| 				"TaskID":           assignedTask.TaskID.String(), | 				"TaskID":           project.TaskShortID, | ||||||
| 				"TaskName":         task.Name, | 				"TaskName":         task.Name, | ||||||
| 				"ProjectID":        project.ProjectID.String(), | 				"ProjectID":        project.ProjectShortID, | ||||||
| 				"ProjectName":      project.Name, | 				"ProjectName":      project.Name, | ||||||
| 			}, | 			}, | ||||||
| 		}) | 		}) | ||||||
| @@ -670,6 +670,23 @@ func (r *mutationResolver) UnassignTask(ctx context.Context, input *UnassignTask | |||||||
| 	return &task, nil | 	return &task, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*db.Task, error) { | ||||||
|  | 	var taskID uuid.UUID | ||||||
|  | 	var err error | ||||||
|  | 	if input.TaskID != nil { | ||||||
|  | 		taskID = *input.TaskID | ||||||
|  | 	} else if input.TaskShortID != nil { | ||||||
|  | 		taskID, err = r.Repository.GetTaskIDByShortID(ctx, *input.TaskShortID) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return &db.Task{}, err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return &db.Task{}, errors.New("FindTask requires either TaskID or TaskShortID to be set") | ||||||
|  | 	} | ||||||
|  | 	task, err := r.Repository.GetTaskByID(ctx, taskID) | ||||||
|  | 	return &task, err | ||||||
|  | } | ||||||
|  |  | ||||||
| func (r *taskResolver) ID(ctx context.Context, obj *db.Task) (uuid.UUID, error) { | func (r *taskResolver) ID(ctx context.Context, obj *db.Task) (uuid.UUID, error) { | ||||||
| 	return obj.TaskID, nil | 	return obj.TaskID, nil | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								migrations/0069_add-short_id-to-tasks-and-projects.up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								migrations/0069_add-short_id-to-tasks-and-projects.up.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | CREATE OR REPLACE FUNCTION unique_short_id() | ||||||
|  | RETURNS TRIGGER AS $$ | ||||||
|  |  | ||||||
|  |  -- Declare the variables we'll be using. | ||||||
|  | DECLARE | ||||||
|  |   key TEXT; | ||||||
|  |   qry TEXT; | ||||||
|  |   found TEXT; | ||||||
|  | BEGIN | ||||||
|  |  | ||||||
|  |   -- generate the first part of a query as a string with safely | ||||||
|  |   -- escaped table name, using || to concat the parts | ||||||
|  |   qry := 'SELECT short_id FROM ' || quote_ident(TG_TABLE_NAME) || ' WHERE short_id='; | ||||||
|  |  | ||||||
|  |   -- This loop will probably only run once per call until we've generated | ||||||
|  |   -- millions of ids. | ||||||
|  |   LOOP | ||||||
|  |  | ||||||
|  |     -- Generate our string bytes and re-encode as a base64 string. | ||||||
|  |     key := encode(gen_random_bytes(6), 'base64'); | ||||||
|  |  | ||||||
|  |     -- Base64 encoding contains 2 URL unsafe characters by default. | ||||||
|  |     -- The URL-safe version has these replacements. | ||||||
|  |     key := replace(key, '/', '_'); -- url safe replacement | ||||||
|  |     key := replace(key, '+', '-'); -- url safe replacement | ||||||
|  |  | ||||||
|  |     -- Concat the generated key (safely quoted) with the generated query | ||||||
|  |     -- and run it. | ||||||
|  |     -- SELECT id FROM "test" WHERE id='blahblah' INTO found | ||||||
|  |     -- Now "found" will be the duplicated id or NULL. | ||||||
|  |     EXECUTE qry || quote_literal(key) INTO found; | ||||||
|  |  | ||||||
|  |     -- Check to see if found is NULL. | ||||||
|  |     -- If we checked to see if found = NULL it would always be FALSE | ||||||
|  |     -- because (NULL = NULL) is always FALSE. | ||||||
|  |     IF found IS NULL THEN | ||||||
|  |  | ||||||
|  |       -- If we didn't find a collision then leave the LOOP. | ||||||
|  |       EXIT; | ||||||
|  |     END IF; | ||||||
|  |  | ||||||
|  |     -- We haven't EXITed yet, so return to the top of the LOOP | ||||||
|  |     -- and try again. | ||||||
|  |   END LOOP; | ||||||
|  |  | ||||||
|  |   -- NEW and OLD are available in TRIGGER PROCEDURES. | ||||||
|  |   -- NEW is the mutated row that will actually be INSERTed. | ||||||
|  |   -- We're replacing id, regardless of what it was before | ||||||
|  |   -- with our key variable. | ||||||
|  |   NEW.short_id = key; | ||||||
|  |  | ||||||
|  |   -- The RECORD returned here is what will actually be INSERTed, | ||||||
|  |   -- or what the next trigger will get if there is one. | ||||||
|  |   RETURN NEW; | ||||||
|  | END; | ||||||
|  | $$ language 'plpgsql'; | ||||||
|  |  | ||||||
|  | ALTER TABLE project ADD COLUMN short_id text UNIQUE; | ||||||
|  | UPDATE project SET short_id = encode(gen_random_bytes(6), 'base64'); | ||||||
|  | ALTER TABLE project ALTER COLUMN short_id SET NOT NULL; | ||||||
|  | ALTER TABLE project ADD CONSTRAINT project_short_id_unique UNIQUE (short_id); | ||||||
|  | CREATE TRIGGER trigger_project_short_id BEFORE INSERT ON project FOR EACH ROW EXECUTE PROCEDURE unique_short_id(); | ||||||
|  |  | ||||||
|  | ALTER TABLE task ADD COLUMN short_id text UNIQUE; | ||||||
|  | UPDATE task SET short_id = encode(gen_random_bytes(6), 'base64'); | ||||||
|  | ALTER TABLE task ALTER COLUMN short_id SET NOT NULL; | ||||||
|  | ALTER TABLE task ADD CONSTRAINT task_short_id_unique UNIQUE (short_id); | ||||||
|  | CREATE TRIGGER trigger_task_short_id BEFORE INSERT ON task FOR EACH ROW EXECUTE PROCEDURE unique_short_id(); | ||||||
		Reference in New Issue
	
	Block a user