filter
This commit is contained in:
1 parent
baf0fa186e
commit
6f651eeaeb
5 files changed
+68
-5
No files matched your search
+1
-1
@@ -25,7 +25,7 @@ const { data } = useEventSource<string[], IssueSseEvent>(
|
|||||||
console.log('Failed to connect EventSource after 3 retries')
|
console.log('Failed to connect EventSource after 3 retries')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
autoConnect: true,
|
autoConnect: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,19 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import AssigneeFilter from '@/components/AssigneeFilter.vue'
|
import AssigneeFilter from '@/components/AssigneeFilter.vue'
|
||||||
import TextFilter from '@/components/TextFilter.vue'
|
import TextFilter from '@/components/TextFilter.vue'
|
||||||
|
import StatusFilter from '@/components/StatusFilter.vue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
text?: string | null
|
text?: string | null
|
||||||
assigneeId?: string | null
|
assigneeId?: string | null
|
||||||
|
status?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), { text: null, assigneeId: null })
|
const props = withDefaults(defineProps<Props>(), { text: null, assigneeId: null })
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:text': [value: string | null]
|
'update:text': [value: string | null]
|
||||||
'update:assigneeId': [value: string | null]
|
'update:assigneeId': [value: string | null]
|
||||||
|
'update:status': [value: string | null]
|
||||||
'update:clear': []
|
'update:clear': []
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
@@ -20,11 +23,16 @@ const selectedAssignees = computed(() => (props.assigneeId ? [props.assigneeId]
|
|||||||
function onAssigneeChanged(value: string[]) {
|
function onAssigneeChanged(value: string[]) {
|
||||||
emit('update:assigneeId', value.at(-1) ?? null)
|
emit('update:assigneeId', value.at(-1) ?? null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onStatusChanged(alias: string) {
|
||||||
|
emit('update:status', alias)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="filter-grid ga-4 align-center">
|
<div class="filter-grid ga-4 align-center">
|
||||||
<text-filter :model-value="text" @update:model-value="emit('update:text', $event)" />
|
<text-filter :model-value="text" @update:model-value="emit('update:text', $event)" />
|
||||||
|
<status-filter :status="status" @changed="onStatusChanged" />
|
||||||
<assignee-filter :selected="selectedAssignees" @changed="onAssigneeChanged" />
|
<assignee-filter :selected="selectedAssignees" @changed="onAssigneeChanged" />
|
||||||
<v-btn prepend-icon="mdi-close" variant="tonal" @click="emit('update:clear')">Clear Filters</v-btn>
|
<v-btn prepend-icon="mdi-close" variant="tonal" @click="emit('update:clear')">Clear Filters</v-btn>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,6 +41,6 @@ function onAssigneeChanged(value: string[]) {
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.filter-grid {
|
.filter-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto auto;
|
grid-template-columns: 1fr auto auto auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useStatusStore } from '@/stores/status.ts'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
status?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const { status } = defineProps<Props>()
|
||||||
|
const emit = defineEmits<{ changed: [value: string] }>()
|
||||||
|
const statusStore = useStatusStore()
|
||||||
|
const selected = ref(status)
|
||||||
|
const onUpdate = (val: unknown) => emit('changed', val as string)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-btn-toggle
|
||||||
|
v-model="selected"
|
||||||
|
class="border-opacity-25"
|
||||||
|
border
|
||||||
|
divided
|
||||||
|
size="default"
|
||||||
|
density="compact"
|
||||||
|
variant="text"
|
||||||
|
@update:model-value="onUpdate"
|
||||||
|
>
|
||||||
|
<v-btn
|
||||||
|
slim
|
||||||
|
v-for="status in statusStore.statuses"
|
||||||
|
:color="status.color"
|
||||||
|
:value="status.alias"
|
||||||
|
:key="status.alias"
|
||||||
|
rounded="0"
|
||||||
|
>
|
||||||
|
<div class="text-default">{{ status.name }}</div>
|
||||||
|
</v-btn>
|
||||||
|
</v-btn-toggle>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
@@ -129,7 +129,7 @@ function openProject(project: Project) {
|
|||||||
|
|
||||||
<v-row density="compact">
|
<v-row density="compact">
|
||||||
<v-col cols="12" md="8">
|
<v-col cols="12" md="8">
|
||||||
<v-card>
|
<v-card border>
|
||||||
<v-card-title class="d-flex align-center justify-space-between">
|
<v-card-title class="d-flex align-center justify-space-between">
|
||||||
<span>Мои задачи</span>
|
<span>Мои задачи</span>
|
||||||
<v-btn size="small" variant="text" to="/issues">Все задачи</v-btn>
|
<v-btn size="small" variant="text" to="/issues">Все задачи</v-btn>
|
||||||
@@ -177,7 +177,7 @@ function openProject(project: Project) {
|
|||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-card>
|
<v-card border>
|
||||||
<v-card-title class="d-flex align-center justify-space-between">
|
<v-card-title class="d-flex align-center justify-space-between">
|
||||||
<span>Проекты</span>
|
<span>Проекты</span>
|
||||||
<v-btn size="small" variant="text" to="/settings/projects">Все проекты</v-btn>
|
<v-btn size="small" variant="text" to="/settings/projects">Все проекты</v-btn>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const serverItems = ref<Issue[]>([])
|
|||||||
|
|
||||||
const text = ref<string | null>(null)
|
const text = ref<string | null>(null)
|
||||||
const assigneeId = ref<string | null>(null)
|
const assigneeId = ref<string | null>(null)
|
||||||
|
const status = ref<string | null>(null)
|
||||||
const selected = ref<[string] | []>([])
|
const selected = ref<[string] | []>([])
|
||||||
const batch = ref<number[]>([])
|
const batch = ref<number[]>([])
|
||||||
const deleting = ref(false)
|
const deleting = ref(false)
|
||||||
@@ -36,6 +37,7 @@ async function fetch() {
|
|||||||
page: page.value,
|
page: page.value,
|
||||||
limit: itemsPerPage.value,
|
limit: itemsPerPage.value,
|
||||||
text: text.value,
|
text: text.value,
|
||||||
|
status: status.value,
|
||||||
assigneeId: assigneeId.value,
|
assigneeId: assigneeId.value,
|
||||||
projectId: currentProjectId.value,
|
projectId: currentProjectId.value,
|
||||||
})
|
})
|
||||||
@@ -55,6 +57,7 @@ function syncQuery() {
|
|||||||
|
|
||||||
if (text.value) query.text = text.value
|
if (text.value) query.text = text.value
|
||||||
if (assigneeId.value) query.assignee = assigneeId.value
|
if (assigneeId.value) query.assignee = assigneeId.value
|
||||||
|
if (status.value) query.status = status.value
|
||||||
if (selected.value.length) query.selected_issue = selected.value[0]
|
if (selected.value.length) query.selected_issue = selected.value[0]
|
||||||
|
|
||||||
router.replace({ query })
|
router.replace({ query })
|
||||||
@@ -66,6 +69,7 @@ watch(
|
|||||||
page.value = query.page ? Number(query.page) : 1
|
page.value = query.page ? Number(query.page) : 1
|
||||||
text.value = query.text ? String(query.text) : null
|
text.value = query.text ? String(query.text) : null
|
||||||
assigneeId.value = query.assignee ? String(query.assignee) : null
|
assigneeId.value = query.assignee ? String(query.assignee) : null
|
||||||
|
status.value = query.status ? String(query.status) : null
|
||||||
selected.value = query.selected_issue ? [String(query.selected_issue)] : []
|
selected.value = query.selected_issue ? [String(query.selected_issue)] : []
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
@@ -102,6 +106,12 @@ async function onAssigneeChanged(value: string | null) {
|
|||||||
await load()
|
await load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onStatusChanged(value: string | null) {
|
||||||
|
status.value = value
|
||||||
|
page.value = 1
|
||||||
|
await load()
|
||||||
|
}
|
||||||
|
|
||||||
async function onClear() {
|
async function onClear() {
|
||||||
text.value = null
|
text.value = null
|
||||||
assigneeId.value = null
|
assigneeId.value = null
|
||||||
@@ -175,8 +185,10 @@ async function onDeleteBatch() {
|
|||||||
class="mb-2"
|
class="mb-2"
|
||||||
:text="text"
|
:text="text"
|
||||||
:assignee-id="assigneeId"
|
:assignee-id="assigneeId"
|
||||||
|
:status="status"
|
||||||
@update:text="onTextChanged"
|
@update:text="onTextChanged"
|
||||||
@update:assignee-id="onAssigneeChanged"
|
@update:assignee-id="onAssigneeChanged"
|
||||||
|
@update:status="onStatusChanged"
|
||||||
@update:clear="onClear"
|
@update:clear="onClear"
|
||||||
/>
|
/>
|
||||||
<v-list class="pa-0" density="compact" v-model:selected="selected" mandatory>
|
<v-list class="pa-0" density="compact" v-model:selected="selected" mandatory>
|
||||||
@@ -198,7 +210,10 @@ async function onDeleteBatch() {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #append>
|
<template #append>
|
||||||
<issue-stats />
|
<div class="d-flex ga-4 align-center">
|
||||||
|
<issue-stats />
|
||||||
|
<v-btn density="compact" icon="mdi-dots-horizontal"></v-btn>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user