Skip to content

Commit

Permalink
feat: table column is customizable through settings
Browse files Browse the repository at this point in the history
  • Loading branch information
caro3801 committed Nov 14, 2024
1 parent d6d62a6 commit d144688
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 122 deletions.
236 changes: 127 additions & 109 deletions src/components/Task/TaskList.vue
Original file line number Diff line number Diff line change
@@ -1,119 +1,137 @@
<template>
<div class="task-list">
<b-table
:fields="showTasksFields"
:items="sortedTasks"
responsive
striped
show-empty
thead-tr-class="text-nowrap"
tbody-tr-class="tasks-list__tasks__item"
class="card tasks-list__tasks"
>
<template #empty>
<slot name="empty">
<p class="text-center m-0" v-html="$t('tasksList.empty')"></p>
</slot>
</template>
<template #cell(state)="{ item }">
<slot name="status" v-bind="{ item }">
<ellipse-status :status="item.state" :progress="item.progress * 100" horizontal />
</slot>
</template>
<template #cell(name)="{ item }">
<div class="tasks-list__tasks__item__name m-0 fw-bold">
<slot v-bind="{ item }">
{{ item.name }}
</slot>
</div>
<div class="d-flex align-items-center">
<b-badge variant="tertiary" class="tasks-list__tasks__item__id my-1">
{{ item.id }}
</b-badge>
<template v-if="item.state === 'RUNNING' && stoppable">
<span class="px-1"> – </span>
<b-button
variant="link"
size="sm"
class="tasks-list__tasks__item__stop text-danger p-0"
@click="stopTask(item.id)"
>
{{ $t('tasksList.stop') }}
</b-button>
</template>
</div>
<div v-if="isBatchDownloadEncrypted(item)" class="font-italic tasks-list__tasks__item__encrypted">
{{ $t('tasksList.encrypted') }}
</div>
<div v-if="hasZipSize(item)" class="tasks-list__tasks__item__size m-0 fw-bold">
{{ humanSize(item.result.size, false, $tm('human.size')) }}
</div>
</template>
<template #table-colgroup="{ fields }">
<col v-for="{ key } in taskFields" :key="key" :style="{ width: key === 'state' ? '140px' : 'auto' }" />
</template>
</b-table>
</div>
<page-table>
<template #thead>
<page-table-th
v-for="field in columns"
:key="field.name"
:label="field.text"
sortable
emphasis
:name="field.name"
/>
</template>
<page-table-tr v-for="(item, index) in tasks" :key="index">
<td v-for="(column, i) in columns" :key="i">
<slot :name="`cell(${column.value})`" v-bind="{ item, column }">{{ item[column.value] }}</slot>
</td>

<page-table-td-actions>
<button-icon
variant="outline-secondary"
square
hide-label
size="sm"
icon-left="magnifying-glass"
class="border-0 me-1"
/>
<button-icon
variant="outline-secondary"
square
hide-label
size="sm"
icon-left="arrow-clockwise"
class="border-0 me-1"
/>
<button-icon variant="outline-secondary" square hide-label size="sm" icon-left="trash" class="border-0 me-1" />
</page-table-td-actions>
</page-table-tr>
</page-table>
<!-- <template #empty>
<slot name="empty">
<p class="text-center m-0" v-html="$t('tasksList.empty')"></p>
</slot>
</template>
<template #cell(state)="{ item }">
<slot name="status" v-bind="{ item }">
<ellipse-status :status="item.state" :progress="item.progress * 100" horizontal />
</slot>
</template>
<template #cell(name)="{ item }">
<div class="tasks-list__tasks__item__name m-0 fw-bold">
<slot v-bind="{ item }">
{{ item.name }}
</slot>
</div>
<div class="d-flex align-items-center">
<b-badge variant="tertiary" class="tasks-list__tasks__item__id my-1">
{{ item.id }}
</b-badge>
<template v-if="item.state === 'RUNNING' && stoppable">
<span class="px-1"> – </span>
<b-button
variant="link"
size="sm"
class="tasks-list__tasks__item__stop text-danger p-0"
@click="stopTask(item.id)"
>
{{ $t('tasksList.stop') }}
</b-button>
</template>
</div>
<div v-if="isBatchDownloadEncrypted(item)" class="font-italic tasks-list__tasks__item__encrypted">
{{ $t('tasksList.encrypted') }}
</div>
<div v-if="hasZipSize(item)" class="tasks-list__tasks__item__size m-0 fw-bold">
{{ humanSize(item.result.size, false, $tm('human.size')) }}
</div>
</template>
<template #table-colgroup="{ fields }">
<col v-for="{ key } in taskFields" :key="key" :style="{ width: key === 'state' ? '140px' : 'auto' }" />
</template>
</b-table>
</div>-->
</template>

<script>
<script setup>
import { sortBy } from 'lodash'
import { computed } from 'vue'
import { useStore } from 'vuex'
import EllipseStatus from '@/components/EllipseStatus'
import humanSize from '@/utils/humanSize'
export default {
name: 'TasksList',
components: {
EllipseStatus
defineOptions({ name: 'TaskList' })
defineProps({
/**
* Object of tasks passed from the parent
*/
tasks: {
type: Array
},
props: {
/**
* Object of tasks passed from the parent
*/
tasks: {
type: Array
},
taskFields: {
type: Array
},
/**
* Display a button to stop the task
*/
stoppable: {
type: Boolean
}
columns: {
type: Array,
default: () => []
},
computed: {
sortedTasks() {
// Move running tasks on top
const states = ['RUNNING']
return sortBy(this.tasks, ({ state }) => -states.indexOf(state))
},
showTasksFields() {
return this.tasks.length ? ['state', 'name'] : this.taskFields
}
},
methods: {
isBatchDownloadEncrypted(item) {
return item.name.includes('BatchDownload') && item.args.batchDownload.encrypted
},
hasZipSize(item) {
return item.name.includes('BatchDownload') && item.state !== 'ERROR' && item.result?.size !== undefined
},
async stopPendingTasks() {
await this.$store.dispatch('indexing/stopPendingTasks')
await this.$store.dispatch('indexing/getTasks')
},
async stopTask(name) {
await this.$store.dispatch('indexing/stopTask', name)
await this.$store.dispatch('indexing/getTasks')
},
async deleteDoneTasks() {
await this.$store.dispatch('indexing/deleteDoneTasks')
await this.$store.dispatch('indexing/getTasks')
},
humanSize
/**
* Display a button to stop the task
*/
stoppable: {
type: Boolean
}
})
const store = useStore()
const sortedTasks = computed(() => {
// Move running tasks on top
const states = ['RUNNING']
return sortBy(this.tasks, ({ state }) => -states.indexOf(state))
})
const showTasksFields = computed(() => {
return this.tasks.length ? this.taskFields : []
})
function isBatchDownloadEncrypted(item) {
return item.name.includes('BatchDownload') && item.args.batchDownload.encrypted
}
function hasZipSize(item) {
return item.name.includes('BatchDownload') && item.state !== 'ERROR' && item.result?.size !== undefined
}
async function stopPendingTasks() {
await store.dispatch('indexing/stopPendingTasks')
await store.dispatch('indexing/getTasks')
}
async function stopTask(name) {
await store.dispatch('indexing/stopTask', name)
await store.dispatch('indexing/getTasks')
}
async function deleteDoneTasks() {
await store.dispatch('indexing/deleteDoneTasks')
await store.dispatch('indexing/getTasks')
}
</script>
2 changes: 1 addition & 1 deletion src/composables/task-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'
export function useTaskSettings() {
const { t } = useI18n()

const propertiesOrder = ['id', 'name', 'createdAt', 'progress', 'result', 'state']
const propertiesOrder = ['state', 'name', 'id', 'progress', 'createdAt']

const propertiesLabel = computed(() => {
return {
Expand Down
30 changes: 23 additions & 7 deletions src/views/Task/Task.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { toRef, watch } from 'vue'
import { computed, toRef } from 'vue'
import { useTaskHeader } from './task-header'
import { useTaskPolling } from './task-polling'
Expand All @@ -15,17 +15,31 @@ const props = defineProps({
pageName: {
type: String,
required: true
},
showAdd: {
type: Boolean,
default: false
}
})
const taskNames = toRef(props, 'taskFilter')
const { tasks, hasPendingTasks, hasDoneTasks, stopPendingTasks, deleteDoneTasks } = useTaskPolling(taskNames)
const { fields } = useTaskProperties(props.pageName)
const {
tasks: pollingTasks,
hasPendingTasks,
hasDoneTasks,
stopPendingTasks,
deleteDoneTasks
} = useTaskPolling(taskNames)
const { toAddRoute, searchQuery, page, perPage, searchPlaceholder, displayedTasks, totalRows } = useTaskHeader(
props.pageName,
true,
tasks
props.showAdd,
pollingTasks
)
const settingName = 'task'
const { properties } = useTaskProperties(settingName)
const shownProperties = computed(() => {
return properties.value.options.filter((p) => properties.value.modelValue.includes(p.value))
})
</script>

<template>
Expand All @@ -50,6 +64,8 @@ const { toAddRoute, searchQuery, page, perPage, searchPlaceholder, displayedTask
</template>
</page-header>
<page-container fluid>
<task-list :tasks="displayedTasks" :task-fields="fields" :stoppable="true" />
<slot :tasks="displayedTasks" :columns="shownProperties">
<task-list :tasks="displayedTasks" :columns="shownProperties" :stoppable="true" />
</slot>
</page-container>
</template>
8 changes: 7 additions & 1 deletion src/views/Task/TasksListSettings.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
<script setup>
import { noop } from 'lodash'
import { watch } from 'vue'
import PageSettings from '@/components/PageSettings/PageSettings'
import PageSettingsSection from '@/components/PageSettings/PageSettingsSection'
import { useTaskProperties } from '@/views/Task/task-properties'
const settingName = 'task'
const { perPage, sortBy, properties } = useTaskProperties(settingName)
watch(
() => properties.value.modelValue,
(val) => {
console.log('watch1', val)
}
)
defineProps({
hide: {
type: Function,
Expand Down
4 changes: 0 additions & 4 deletions src/views/Task/task-properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,8 @@ export function useTaskProperties(pageName) {
})
})
})
const fields = computed(() => {
return [{ key: 'state' }]
})

return {
fields,
sortBy,
properties,
perPage
Expand Down

0 comments on commit d144688

Please sign in to comment.