Skip to content

Commit

Permalink
feat: add action cell in tasks and add info on top of task list
Browse files Browse the repository at this point in the history
feat: add action cell in tasks and add info on top of task list
  • Loading branch information
caro3801 committed Nov 15, 2024
1 parent 7dbfed5 commit d5979ed
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 86 deletions.
5 changes: 5 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ declare module 'vue' {
BDropdown: typeof import('bootstrap-vue-next')['BDropdown']
BDropdownDivider: typeof import('bootstrap-vue-next')['BDropdownDivider']
BDropdownItem: typeof import('bootstrap-vue-next')['BDropdownItem']
BDropdownItemButton: typeof import('bootstrap-vue-next')['BDropdownItemButton']
BForm: typeof import('bootstrap-vue-next')['BForm']
BFormCheckbox: typeof import('bootstrap-vue-next')['BFormCheckbox']
BFormCheckboxGroup: typeof import('bootstrap-vue-next')['BFormCheckboxGroup']
BFormFile: typeof import('bootstrap-vue-next')['BFormFile']
BFormGroup: typeof import('bootstrap-vue-next')['BFormGroup']
BFormInput: typeof import('bootstrap-vue-next')['BFormInput']
BFormInvalidFeedback: typeof import('bootstrap-vue-next')['BFormInvalidFeedback']
Expand Down Expand Up @@ -119,6 +121,7 @@ declare module 'vue' {
DisplayDatetimeRange: typeof import('./src/components/Display/DisplayDatetimeRange.vue')['default']
DisplayDatetimeShort: typeof import('./src/components/Display/DisplayDatetimeShort.vue')['default']
DisplayExtractionLevel: typeof import('./src/components/Display/DisplayExtractionLevel.vue')['default']
DisplayHighlights: typeof import('./src/components/Display/DisplayHighlights.vue')['default']
DisplayLanguage: typeof import('./src/components/Display/DisplayLanguage.vue')['default']
DisplayNumber: typeof import('./src/components/Display/DisplayNumber.vue')['default']
DisplayNumberHuman: typeof import('./src/components/Display/DisplayNumberHuman.vue')['default']
Expand Down Expand Up @@ -168,6 +171,7 @@ declare module 'vue' {
DocumentEntriesTable: typeof import('./src/components/Document/DocumentEntries/DocumentEntriesTable.vue')['default']
DocumentEntriesTableBody: typeof import('./src/components/Document/DocumentEntries/DocumentEntriesTableBody.vue')['default']
DocumentEntriesTableHead: typeof import('./src/components/Document/DocumentEntries/DocumentEntriesTableHead.vue')['default']
DocumentFloating: typeof import('./src/components/Document/DocumentFloating.vue')['default']
DocumentGlobalSearchTerms: typeof import('./src/components/Document/DocumentGlobalSearchTerms/DocumentGlobalSearchTerms.vue')['default']
DocumentGlobalSearchTermsEntry: typeof import('./src/components/Document/DocumentGlobalSearchTerms/DocumentGlobalSearchTermsEntry.vue')['default']
DocumentInModal: typeof import('./src/components/DocumentInModal.vue')['default']
Expand Down Expand Up @@ -475,6 +479,7 @@ declare module 'vue' {
}
export interface ComponentCustomProperties {
vBModal: typeof import('bootstrap-vue-next')['vBModal']
vBToggle: typeof import('bootstrap-vue-next')['vBToggle']
vBTooltip: typeof import('bootstrap-vue-next')['vBTooltip']
}
}
2 changes: 2 additions & 0 deletions src/components/AppSidebar/AppSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ const noAnalysis = computed(() => {
icon="files"
:to="{ name: 'task.documents.list' }"
:action-to="{ name: 'task.documents.new' }"
:action-title="t('task.documents.new.title')"
>
{{ t('appSidebar.documents') }}
</app-sidebar-section-entry>
Expand All @@ -155,6 +156,7 @@ const noAnalysis = computed(() => {
icon="users-three"
:to="{ name: 'task.entities.list' }"
:action-to="{ name: 'task.entities.new' }"
:action-title="t('task.entities.new.title')"
>
{{ t('appSidebar.entities') }}
</app-sidebar-section-entry>
Expand Down
34 changes: 13 additions & 21 deletions src/components/Task/TaskList.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<page-table>
<page-table v-model:sort="sort" v-model:order="order">
<template #thead>
<page-table-th
v-for="field in columns"
Expand All @@ -10,29 +10,16 @@
:name="field.name"
/>
</template>
<page-table-tr v-if="tasks.length === 0"
><td :colspan="columns.length" class="text-center"><slot name="empty">No results found</slot></td>
</page-table-tr>
<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" />
<slot name="cell(action)" v-bind="{ item }"></slot>
</page-table-td-actions>
</page-table-tr>
</page-table>
Expand Down Expand Up @@ -75,9 +62,6 @@
{{ 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>
Expand All @@ -87,6 +71,12 @@ import { sortBy } from 'lodash'
import { computed } from 'vue'
import { useStore } from 'vuex'
import { getHumanTaskName } from '@/enums/taskNames'
import DisplayDatetimeLong from '@/components/Display/DisplayDatetimeLong'
import DisplayProgress from '@/components/Display/DisplayProgress'
import DisplayStatus from '@/components/Display/DisplayStatus'
import PageTable from '@/components/PageTable/PageTable'
defineOptions({ name: 'TaskList' })
defineProps({
/**
Expand All @@ -107,6 +97,8 @@ defineProps({
}
})
const store = useStore()
const sort = defineModel('sort', { type: String, default: null })
const order = defineModel('order', { type: String, default: 'desc' })
const sortedTasks = computed(() => {
// Move running tasks on top
const states = ['RUNNING']
Expand Down
35 changes: 21 additions & 14 deletions src/enums/taskNames.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import { startCase } from 'lodash'

const BATCH_SEARCH = 'BatchSearchRunner'
const BATCH_DOWNLOAD = 'BatchDownloadRunner'
const SCAN = 'ScanTask'
const INDEX = 'IndexTask'
const EXTRACT_NLP = 'ExtractNlpTask'
export const TASK_NAMES = Object.freeze({
const ENQUEUE_FROM_INDEX = 'EnqueueFromIndexTask'
export const TASK_NAME = Object.freeze({
BATCH_SEARCH,
BATCH_DOWNLOAD,
SCAN,
INDEX,
EXTRACT_NLP
EXTRACT_NLP,
ENQUEUE_FROM_INDEX
})
export const HUMAN_TASK_NAME = Object.freeze({
[BATCH_SEARCH]: 'Batch search',
[BATCH_DOWNLOAD]: 'Batch download',
[SCAN]: 'Scan',
[INDEX]: 'Index',
[EXTRACT_NLP]: 'Extract entities',
[ENQUEUE_FROM_INDEX]: 'Enqueue from index'
})
export const taskNameValidator = (v) => TASK_NAMES.includes(v)
export const TASK_NAME_LIST = Object.values(TASK_NAME)

export const taskNameValidator = (v) => TASK_NAME_LIST.includes(v)

export function getTaskName(longName) {
const taskName = longName.split('.').pop()
if (taskNameValidator(taskName)) {
return taskName
}
throw new Error(`Wrong task name ${longName}`)
return longName.split('.').pop()
}

export function getLongTaskName(shortName) {
if (taskNameValidator(shortName)) {
return `org.icij.datashare.tasks.${shortName}`
}
throw new Error(`Wrong task name ${shortName}`)
export function getHumanTaskName(longName) {
const taskName = getTaskName(longName)
return taskNameValidator(taskName) ? HUMAN_TASK_NAME[taskName] : startCase(taskName)
}
17 changes: 10 additions & 7 deletions src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -900,9 +900,10 @@
"entities": {
"title": "Entities",
"list": {
"title":"All tasks",
"info":"Entity recognitions are tasks that you run in order to recognize and to list the entities in your documents.",
"searchPlaceholder": "Search task",
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>"
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>",
"noResults": "No search results. Try adjusting the query or filters."
},
"new": {
"title":"Find entities"
Expand Down Expand Up @@ -940,9 +941,10 @@
"documents": {
"title": "Documents",
"list": {
"title":"All tasks",
"info": "Document additions are tasks that you run to ask Datashare to add new documents.", ",searchPlaceholder": "Search task",
"searchPlaceholder": "Search task",
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>"
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>",
"noResults": "No search results. Try adjusting the query or filters."
},
"new": {
"title":"Add documents"
Expand All @@ -969,17 +971,18 @@
"batch-download": {
"title": "Batch downloads",
"list": {
"title":"All tasks",
"info": "Batch downloads are password-protected zip files containing all the documents from one of your specific search.",
"searchPlaceholder": "Search task",
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>"
}
},
"batch-search": {
"title": "Batch searches",
"list": {
"title":"All tasks",
"info": "Batch searches allow to get the results of each query of a list, but all at once.",
"searchPlaceholder": "Search task",
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>"
"empty": "You have not yet started any tasks. <a href=\"{howToLink}\" target=\"_blank\">Read more.</a>",
"noResults": "No search results. Try adjusting the query or filters."
},
"new": {
"title":"Run a new batch search"
Expand Down
11 changes: 5 additions & 6 deletions src/views/Task/BatchDownload/TaskBatchDownloadList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import TaskList from '@/components/Task/TaskList'
import DisplayStatus from '@/components/Display/DisplayStatus'
import DisplayDatetimeFromNow from '@/components/Display/DisplayDatetimeFromNow'
import DisplayProgress from '@/components/Display/DisplayProgress'
import { useTaskProperties } from '@/views/Task/task-properties'
const settingName = 'task'
const { propertiesModelValueOptions } = useTaskProperties(settingName)
</script>
<template>
<task
v-slot="{ tasks, columns }"
:task-filter="['org.icij.datashare.tasks.BatchDownloadRunner']"
page-name="batch-download"
>
<task-list :tasks="tasks" :columns="columns" :stoppable="true">
<task v-slot="{ tasks }" :task-filter="['org.icij.datashare.tasks.BatchDownloadRunner']" page-name="batch-download">
<task-list :tasks="tasks" :columns="propertiesModelValueOptions" :stoppable="true">
<template #cell(state)="{ item }"><display-status :value="item.state" /></template>
<template #cell(createdAt)="{ item }"><display-datetime-from-now :value="item.createdAt" /></template>
<template #cell(progress)="{ item }"><display-progress :value="item.progress" /></template>
Expand Down
7 changes: 5 additions & 2 deletions src/views/Task/BatchSearch/TaskBatchSearchList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import TaskList from '@/components/Task/TaskList'
import DisplayStatus from '@/components/Display/DisplayStatus'
import DisplayDatetimeFromNow from '@/components/Display/DisplayDatetimeFromNow'
import DisplayProgress from '@/components/Display/DisplayProgress'
import { useTaskProperties } from '@/views/Task/task-properties'
const settingName = 'task'
const { propertiesModelValueOptions } = useTaskProperties(settingName)
</script>
<template>
<task
v-slot="{ tasks, columns }"
v-slot="{ tasks }"
:task-filter="['org.icij.datashare.tasks.BatchSearchRunner']"
page-name="batch-search"
show-add
>
<task-list :tasks="tasks" :columns="columns" :stoppable="true">
<task-list :tasks="tasks" :columns="propertiesModelValueOptions" :stoppable="true">
<template #cell(state)="{ item }"><display-status :value="item.state" /></template>
<template #cell(createdAt)="{ item }"><display-datetime-from-now :value="item.createdAt" /></template>
<template #cell(progress)="{ item }"><display-progress :value="item.progress" /></template>
Expand Down
33 changes: 30 additions & 3 deletions src/views/Task/Documents/TaskDocumentsList.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
<script setup>
import { useStore } from 'vuex'
import Task from '@/views/Task/Task'
import TaskList from '@/components/Task/TaskList'
import DisplayStatus from '@/components/Display/DisplayStatus'
import DisplayDatetimeFromNow from '@/components/Display/DisplayDatetimeFromNow'
import DisplayProgress from '@/components/Display/DisplayProgress'
import { useTaskProperties } from '@/views/Task/task-properties'
import { getHumanTaskName } from '@/enums/taskNames'
import ButtonIcon from '@/components/Button/ButtonIcon'
const settingName = 'task'
const { propertiesModelValueOptions } = useTaskProperties(settingName)
const store = useStore()
async function stopTask(name) {
await store.dispatch('indexing/stopTask', name)
await store.dispatch('indexing/getTasks')
}
</script>
<template>
<task
v-slot="{ tasks, columns }"
v-slot="{ tasks, sortBy }"
:task-filter="['org.icij.datashare.tasks.EnqueueFromIndexTask', 'org.icij.datashare.tasks.ScanTask']"
page-name="documents"
show-add
>
<task-list :tasks="tasks" :columns="columns" :stoppable="true">
<task-list
v-model:sort="sortBy.modelValue[0]"
v-model:order="sortBy.modelValue[1]"
:tasks="tasks"
:columns="propertiesModelValueOptions"
>
<template #cell(state)="{ item }"><display-status :value="item.state" /></template>
<template #cell(createdAt)="{ item }"><display-datetime-from-now :value="item.createdAt" /></template>
<template #cell(progress)="{ item }"><display-progress :value="item.progress" /></template>
<template #cell(name)="{ item }">{{ item.name }}</template>
<template #cell(name)="{ item }">{{ getHumanTaskName(item.name) }}</template>
<template #cell(action)="{ item }">
<button-icon
variant="outline-secondary"
square
hide-label
size="sm"
icon-left="trash"
class="border-0"
@click="stopTask(item.id)"
/></template>
</task-list>
</task>
</template>
15 changes: 7 additions & 8 deletions src/views/Task/Entities/TaskEntitiesList.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
<script setup>
import { getHumanTaskName } from '@/enums/taskNames'
import Task from '@/views/Task/Task'
import TaskList from '@/components/Task/TaskList'
import DisplayStatus from '@/components/Display/DisplayStatus'
import DisplayProgress from '@/components/Display/DisplayProgress'
import DisplayDatetimeLong from '@/components/Display/DisplayDatetimeLong'
import { useTaskProperties } from '@/views/Task/task-properties'
const settingName = 'task'
const { propertiesModelValueOptions } = useTaskProperties(settingName)
</script>
<template>
<task
v-slot="{ tasks, columns }"
:task-filter="['org.icij.datashare.tasks.ExtractNlpTask']"
page-name="entities"
show-add
>
<task-list :tasks="tasks" :columns="columns" :stoppable="true">
<task v-slot="{ tasks }" :task-filter="['org.icij.datashare.tasks.ExtractNlpTask']" page-name="entities" show-add>
<task-list :tasks="tasks" :columns="propertiesModelValueOptions" :stoppable="true">
<template #cell(state)="{ item }"><display-status :value="item.state" /></template>
<template #cell(createdAt)="{ item }"><display-datetime-long :value="item.createdAt" /></template>
<template #cell(progress)="{ item }"><display-progress :value="item.progress" /></template>
<template #cell(name)="{ item }">{{ item.name }}</template>
<template #cell(name)="{ item }">{{ getHumanTaskName(item.name) }}</template>
</task-list>
</task>
</template>
17 changes: 5 additions & 12 deletions src/views/Task/Task.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script setup>
import { computed, toRef } from 'vue'
import { toRef } from 'vue'
import { useTaskHeader } from './task-header'
import { useTaskPolling } from './task-polling'
import PageHeader from '@/components/PageHeader/PageHeader'
import TaskActions from '@/components/Task/TaskActions'
import { useTaskProperties } from '@/views/Task/task-properties'
import DismissableAlert from '@/components/Dismissable/DismissableAlert'
const props = defineProps({
taskFilter: {
type: Array,
Expand All @@ -29,17 +29,11 @@ const {
stopPendingTasks,
deleteDoneTasks
} = useTaskPolling(taskNames)
const { toAddRoute, searchQuery, page, perPage, searchPlaceholder, displayedTasks, totalRows } = useTaskHeader(
const { toAddRoute, searchQuery, page, perPage, searchPlaceholder, displayedTasks, totalRows, sortBy } = useTaskHeader(
props.pageName,
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 @@ -64,8 +58,7 @@ const shownProperties = computed(() => {
</template>
</page-header>
<page-container fluid>
<slot :tasks="displayedTasks" :columns="shownProperties">
<task-list :tasks="displayedTasks" :columns="shownProperties" :stoppable="true" />
</slot>
<dismissable-alert variant="info">{{ $t(`task.${pageName}.list.info`) }}</dismissable-alert>
<slot :tasks="displayedTasks" :sort-by="sortBy"> </slot>
</page-container>
</template>
Loading

0 comments on commit d5979ed

Please sign in to comment.