init
This commit is contained in:
commit
fcec12e5ba
78 files changed
+9569
No files matched your search
@@ -0,0 +1,126 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watchEffect } from 'vue'
|
||||
import { useIssueStore } from '@/stores/issue.js'
|
||||
import { useStatusStore } from '@/stores/status.ts'
|
||||
import ExpansionPanel from '@/components/ExpansionPanel.vue'
|
||||
import IssueContent from '@/components/IssueContent.vue'
|
||||
import type { Issue } from '@/api/issue.api.ts'
|
||||
import StatusMenu from '@/components/StatusMenu.vue'
|
||||
import AssigneeMenu from '@/components/AssigneeMenu.vue'
|
||||
import ReporterInfo from '@/components/ReporterInfo.vue'
|
||||
|
||||
interface Props {
|
||||
ckey: string
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
statusChanged: [issue: Issue]
|
||||
assigneeChanged: [issue: Issue]
|
||||
}>()
|
||||
|
||||
const issueStore = useIssueStore()
|
||||
const statusStore = useStatusStore()
|
||||
const issue = ref<Issue>()
|
||||
|
||||
const { ckey } = defineProps<Props>()
|
||||
|
||||
const statusName = computed(() => {
|
||||
return statusStore.statuses?.find((el) => el.alias === issue.value?.status)?.name ?? issue.value?.status
|
||||
})
|
||||
|
||||
const createdAtFormatted = computed(() => {
|
||||
if (!issue.value?.createdAt) return ''
|
||||
return new Intl.DateTimeFormat('ru-RU', { dateStyle: 'medium', timeStyle: 'short' }).format(
|
||||
new Date(issue.value.createdAt),
|
||||
)
|
||||
})
|
||||
|
||||
async function fetch() {
|
||||
const res = await issueStore.getByKey(ckey)
|
||||
if (!res) {
|
||||
return
|
||||
}
|
||||
|
||||
issue.value = res
|
||||
}
|
||||
|
||||
watchEffect(async () => fetch())
|
||||
|
||||
const onContentChanged = async (content: string) => {
|
||||
if (!issue.value) return
|
||||
const updated = await issueStore.update(issue.value.id, { content })
|
||||
if (updated) issue.value = updated
|
||||
}
|
||||
|
||||
const onStatusChanged = async (status: Issue['status']) => {
|
||||
if (!issue.value) return
|
||||
|
||||
const updated = await issueStore.update(issue.value.id, { status })
|
||||
if (updated) {
|
||||
issue.value = updated
|
||||
emit('statusChanged', updated)
|
||||
}
|
||||
}
|
||||
|
||||
const onAssigneeChanged = async (assignee: string) => {
|
||||
if (!issue.value) return
|
||||
|
||||
const updated = await issueStore.update(issue.value.id, { assignee })
|
||||
if (updated) {
|
||||
issue.value = updated
|
||||
emit('assigneeChanged', updated)
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
applyUpdate: (updated: Issue) => {
|
||||
if (issue.value && issue.value.id === updated.id) {
|
||||
issue.value = updated
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="issue" class="d-flex flex-column ga-4 pa-4">
|
||||
<div>{{ ckey }}</div>
|
||||
<div class="text-uppercase text-title-large">{{ issue.title }}</div>
|
||||
|
||||
<v-card elevation="0" border>
|
||||
<v-card-text class="u-grid">
|
||||
<div class="text-medium-emphasis">Status:</div>
|
||||
<status-menu :value="issue.status" @changed="onStatusChanged" />
|
||||
|
||||
<div class="text-medium-emphasis">Reporter:</div>
|
||||
<reporter-info :user="issue.reporter" />
|
||||
|
||||
<div class="text-medium-emphasis">Assignee:</div>
|
||||
<assignee-menu :value="issue.assignee" :compact="false" @changed="onAssigneeChanged" />
|
||||
|
||||
<div class="text-medium-emphasis">Created At:</div>
|
||||
<div>{{ createdAtFormatted }}</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<expansion-panel title="Details">
|
||||
<issue-content :value="issue.content" @changed="onContentChanged" />
|
||||
</expansion-panel>
|
||||
|
||||
<expansion-panel title="Activity">
|
||||
<v-btn-group divided border density="compact">
|
||||
<v-btn>comments</v-btn>
|
||||
<v-btn>history</v-btn>
|
||||
</v-btn-group>
|
||||
</expansion-panel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.u-grid {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
column-gap: 1rem;
|
||||
row-gap: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user