Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement create issue button #7

Merged
merged 1 commit into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions src/components/dialog/issue/NewIssueDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<script setup lang="ts">

import { useNewIssueDialog } from '@/components/dialog/issue/new-issue-dialog-controller'
import { type CreateIssueInput, IssueStateType } from '@/gql/graphql'
import { computed, ref } from 'vue'
import { useProjectService } from '@/service/project-service'
import { useIssueService } from '@/service/issue-service'

const { newIssueDialogVisible, closeNewIssueDialog } = useNewIssueDialog()

const { project } = useProjectService()
const { createIssue, loading } = useIssueService()

const backlogStateName = computed<string>(() => project.value?.projectSettings.imsSettings.issueStates
.filter((state) => state.type === IssueStateType.Backlog)[0].name ?? '')
const sprintBacklogStateName = computed<string>(() => project.value?.projectSettings.imsSettings.issueStates
.filter((state) => state.type === IssueStateType.SprintBacklog)[0].name ?? '')
const currentSprint = computed(() => project.value?.currentSprintNumber)

const issueTypes = computed(() => project.value?.projectSettings.imsSettings.issueTypes
.map(type => ({ name: type.name })) ?? [])
const issueTypeItems = computed(() => issueTypes.value?.map(type => type.name) ?? [])

const issueTitle = ref<string>('')
const issueDescription = ref<string>('')
const issueType = ref<string>( '')
const inSprintOrBacklog = ref<'sprint' | 'backlog'>('backlog')

const issueInput = computed<CreateIssueInput>(() => ({
title: issueTitle.value,
description: issueDescription.value,
stateName: inSprintOrBacklog.value === 'sprint' ? sprintBacklogStateName.value : backlogStateName.value,
sprintNumber: inSprintOrBacklog.value === 'sprint' ? currentSprint.value : null,
typeName: issueType.value
}))

function confirmCreateIssue() {
createIssue(issueInput.value)
.then(() => closeNewIssueDialog())
.then(() => {
issueTitle.value = ''
issueDescription.value = ''
issueType.value = ''
inSprintOrBacklog.value = 'backlog'
})
}

const valid = ref(false)

</script>

<template>
<v-dialog :model-value="newIssueDialogVisible" width="700">
<v-card>
<v-card-title>Create New Issue</v-card-title>
<v-card-text>

<v-form v-model="valid">
<v-text-field
v-model="issueTitle"
label="Title"
required
:rules="[(v: string) => !!v || 'Title is required']"
/>
<v-textarea v-model="issueDescription" label="Description" />

<v-select
v-model="issueType" :items="issueTypeItems"
label="Issue Type"
required
:rules="[(v: string) => !!v || 'Issue Type is required']"
/>

<v-radio-group v-model="inSprintOrBacklog">
<v-radio label="Create in Backlog" value="backlog"></v-radio>
<v-radio label="Create for current Sprint" value="sprint"></v-radio>
</v-radio-group>

</v-form>

</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn @click="closeNewIssueDialog">Cancel</v-btn>
<v-btn color="primary" @click="confirmCreateIssue" :loading="loading" :disabled="!valid">
Create
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<style scoped>

</style>
20 changes: 20 additions & 0 deletions src/components/dialog/issue/new-issue-dialog-controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ref } from 'vue'


const newIssueDialogVisible = ref(false)

function openNewIssueDialog () {
newIssueDialogVisible.value = true
}

function closeNewIssueDialog () {
newIssueDialogVisible.value = false
}

export function useNewIssueDialog () {
return {
newIssueDialogVisible,
openNewIssueDialog,
closeNewIssueDialog,
}
}
9 changes: 7 additions & 2 deletions src/gql/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const documents = {
"\n query BoardQuery($projectId: UUID!) {\n project(id: $projectId) {\n projectBoard {\n ... ProjectBoard\n }\n }\n }\n ": types.BoardQueryDocument,
"\n mutation ChangeStateMutation($projectId: UUID!, $issueId: ID!, $stateName: String!) {\n mutateProject(id: $projectId) {\n mutateIssue(id: $issueId) {\n changeIssueState(stateName: $stateName) {\n ...IssueBase\n }\n }\n }\n }\n ": types.ChangeStateMutationDocument,
"\n mutation FinishIssueMutation($projectId: UUID!, $issueId: ID!, $doneStateName: String!, $dodConfirmStates: [DefinitionOfDoneConfirmState!]!) {\n mutateProject(id: $projectId) {\n mutateIssue(id: $issueId) {\n finishIssue(doneStateName: $doneStateName, dodConfirmStates: $dodConfirmStates) {\n ...IssueBase\n }\n }\n }\n }\n ": types.FinishIssueMutationDocument,
"\n mutation CreateIssueMutation($projectId: UUID!, $input: CreateIssueInput!) {\n mutateProject(id: $projectId) {\n createIssue(input: $input) {\n ...IssueBase\n }\n }\n }\n ": types.CreateIssueMutationDocument,
"\n mutation AssignIssueMutation($projectId: UUID!, $issueId: ID!, $assigneeId: UUID!) {\n mutateProject(id: $projectId) {\n mutateIssue(id: $issueId) {\n assignIssue(assigneeId: $assigneeId) {\n ...IssueBase\n }\n }\n }\n }\n ": types.AssignIssueMutationDocument,
"\n query IssueQuery($projectId: UUID!, $issueId: UUID!) {\n project(id: $projectId) {\n issue(id: $issueId) {\n ...IssueWithEvents\n }\n }\n }\n ": types.IssueQueryDocument,
"\n fragment IssueBase on Issue {\n id\n title\n issueUrl\n description\n storyPoints\n effortEstimation\n priority\n sprintNumber\n type {\n iconPath\n name\n }\n assignees {\n user {\n id\n avatar\n username\n }\n }\n }": types.IssueBaseFragmentDoc,
Expand All @@ -52,7 +53,7 @@ const documents = {
"\n mutation FinishMeeting($projectId: UUID!) {\n mutateProject(id: $projectId) {\n mutatePlanningMeeting {\n finishMeeting {\n ...DefaultSprint\n }\n }\n }\n }": types.FinishMeetingDocument,
"\n subscription PlanningMeeting($projectId: UUID!) {\n planningMeeting(projectId: $projectId) {\n ...DefaultPlanningMeeting\n }\n }": types.PlanningMeetingDocument,
"\n fragment DefaultPlanningMeeting on PlanningMeeting {\n ...DefaultMeeting\n currentPage\n animalVoting {\n finished\n votableAnimals\n votingResult\n animalVotingStates {\n votedFor\n totalVotes\n userVotes {\n user {\n id\n username\n }\n }\n }\n }\n nameVoting {\n finished\n votableNames\n votingResult\n nameVotingStates {\n votedFor\n totalVotes\n userVotes {\n user {\n id\n username\n }\n }\n }\n }\n issueEstimation {\n finished\n countdownSeconds\n estimationStats {\n max\n min\n median\n mode\n }\n finalResult\n issueId # remark: in subscription context, requesting issues is not allowed, so we only get the id\n votes {\n totalVotes\n votedFor\n userVotes {\n user {\n id\n username\n }\n }\n }\n }\n sprintGoalVoting {\n finished\n nonSprintIssueIds\n sprintIssueIds\n }\n }": types.DefaultPlanningMeetingFragmentDoc,
"\n fragment ProjectMain on Project {\n id\n name\n description\n\n projectSettings {\n imsSettings {\n imsName\n imsIcon {\n path\n }\n imsProjectUrl\n }\n codeRepositorySettings {\n repositories {\n name\n url\n icon {\n mdiIcon\n }\n }\n }\n definitionOfDone {\n text\n required\n implies {\n text\n required\n implies {\n text\n required\n }\n }\n }\n }\n }\n ": types.ProjectMainFragmentDoc,
"\n fragment ProjectMain on Project {\n id\n name\n description\n currentSprintNumber\n\n projectSettings {\n imsSettings {\n imsName\n imsIcon {\n path\n }\n imsProjectUrl\n issueStates {\n name\n type\n }\n issueTypes {\n name\n }\n }\n codeRepositorySettings {\n repositories {\n name\n url\n icon {\n mdiIcon\n }\n }\n }\n definitionOfDone {\n text\n required\n implies {\n text\n required\n implies {\n text\n required\n }\n }\n }\n }\n }\n ": types.ProjectMainFragmentDoc,
"\n fragment ProjectBase on Project {\n id\n name\n description\n\n currentUser {\n roles {\n projectPrivileges\n }\n }\n }\n ": types.ProjectBaseFragmentDoc,
"\n query ProjectMainQuery($projectId: UUID!) {\n project(id: $projectId) {\n ... ProjectMain\n }\n }\n ": types.ProjectMainQueryDocument,
"\n query AllProjectsQuery {\n projects {\n ... ProjectBase\n }\n }\n ": types.AllProjectsQueryDocument,
Expand Down Expand Up @@ -141,6 +142,10 @@ export function graphql(source: "\n mutation ChangeStateMutation($project
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation FinishIssueMutation($projectId: UUID!, $issueId: ID!, $doneStateName: String!, $dodConfirmStates: [DefinitionOfDoneConfirmState!]!) {\n mutateProject(id: $projectId) {\n mutateIssue(id: $issueId) {\n finishIssue(doneStateName: $doneStateName, dodConfirmStates: $dodConfirmStates) {\n ...IssueBase\n }\n }\n }\n }\n "): (typeof documents)["\n mutation FinishIssueMutation($projectId: UUID!, $issueId: ID!, $doneStateName: String!, $dodConfirmStates: [DefinitionOfDoneConfirmState!]!) {\n mutateProject(id: $projectId) {\n mutateIssue(id: $issueId) {\n finishIssue(doneStateName: $doneStateName, dodConfirmStates: $dodConfirmStates) {\n ...IssueBase\n }\n }\n }\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation CreateIssueMutation($projectId: UUID!, $input: CreateIssueInput!) {\n mutateProject(id: $projectId) {\n createIssue(input: $input) {\n ...IssueBase\n }\n }\n }\n "): (typeof documents)["\n mutation CreateIssueMutation($projectId: UUID!, $input: CreateIssueInput!) {\n mutateProject(id: $projectId) {\n createIssue(input: $input) {\n ...IssueBase\n }\n }\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down Expand Up @@ -248,7 +253,7 @@ export function graphql(source: "\n fragment DefaultPlanningMeeting on Planni
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment ProjectMain on Project {\n id\n name\n description\n\n projectSettings {\n imsSettings {\n imsName\n imsIcon {\n path\n }\n imsProjectUrl\n }\n codeRepositorySettings {\n repositories {\n name\n url\n icon {\n mdiIcon\n }\n }\n }\n definitionOfDone {\n text\n required\n implies {\n text\n required\n implies {\n text\n required\n }\n }\n }\n }\n }\n "): (typeof documents)["\n fragment ProjectMain on Project {\n id\n name\n description\n\n projectSettings {\n imsSettings {\n imsName\n imsIcon {\n path\n }\n imsProjectUrl\n }\n codeRepositorySettings {\n repositories {\n name\n url\n icon {\n mdiIcon\n }\n }\n }\n definitionOfDone {\n text\n required\n implies {\n text\n required\n implies {\n text\n required\n }\n }\n }\n }\n }\n "];
export function graphql(source: "\n fragment ProjectMain on Project {\n id\n name\n description\n currentSprintNumber\n\n projectSettings {\n imsSettings {\n imsName\n imsIcon {\n path\n }\n imsProjectUrl\n issueStates {\n name\n type\n }\n issueTypes {\n name\n }\n }\n codeRepositorySettings {\n repositories {\n name\n url\n icon {\n mdiIcon\n }\n }\n }\n definitionOfDone {\n text\n required\n implies {\n text\n required\n implies {\n text\n required\n }\n }\n }\n }\n }\n "): (typeof documents)["\n fragment ProjectMain on Project {\n id\n name\n description\n currentSprintNumber\n\n projectSettings {\n imsSettings {\n imsName\n imsIcon {\n path\n }\n imsProjectUrl\n issueStates {\n name\n type\n }\n issueTypes {\n name\n }\n }\n codeRepositorySettings {\n repositories {\n name\n url\n icon {\n mdiIcon\n }\n }\n }\n definitionOfDone {\n text\n required\n implies {\n text\n required\n implies {\n text\n required\n }\n }\n }\n }\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
Loading