feat: unify modal view
fix: List.vue
This commit is contained in:
@ -9,153 +9,128 @@
|
||||
v-shortcut="'g l'"
|
||||
:title="$t('keyboardShortcuts.list.switchToListView')"
|
||||
:class="{'is-active': $route.name === 'list.list'}"
|
||||
:to="{ name: 'list.list', params: { listId: listId } }">
|
||||
:to="{ name: 'list.list', params: { listId } }">
|
||||
{{ $t('list.list.title') }}
|
||||
</router-link>
|
||||
<router-link
|
||||
v-shortcut="'g g'"
|
||||
:title="$t('keyboardShortcuts.list.switchToGanttView')"
|
||||
:class="{'is-active': $route.name === 'list.gantt'}"
|
||||
:to="{ name: 'list.gantt', params: { listId: listId } }">
|
||||
:to="{ name: 'list.gantt', params: { listId } }">
|
||||
{{ $t('list.gantt.title') }}
|
||||
</router-link>
|
||||
<router-link
|
||||
v-shortcut="'g t'"
|
||||
:title="$t('keyboardShortcuts.list.switchToTableView')"
|
||||
:class="{'is-active': $route.name === 'list.table'}"
|
||||
:to="{ name: 'list.table', params: { listId: listId } }">
|
||||
:to="{ name: 'list.table', params: { listId } }">
|
||||
{{ $t('list.table.title') }}
|
||||
</router-link>
|
||||
<router-link
|
||||
v-shortcut="'g k'"
|
||||
:title="$t('keyboardShortcuts.list.switchToKanbanView')"
|
||||
:class="{'is-active': $route.name === 'list.kanban'}"
|
||||
:to="{ name: 'list.kanban', params: { listId: listId } }">
|
||||
:to="{ name: 'list.kanban', params: { listId } }">
|
||||
{{ $t('list.kanban.title') }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<message variant="warning" v-if="currentList.isArchived" class="mb-4">
|
||||
<Message variant="warning" v-if="currentList.isArchived" class="mb-4">
|
||||
{{ $t('list.archived') }}
|
||||
</message>
|
||||
</Message>
|
||||
</transition>
|
||||
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import {ref, shallowRef, computed, watchEffect} from 'vue'
|
||||
import {useRouter, useRoute} from 'vue-router'
|
||||
|
||||
import Message from '@/components/misc/message'
|
||||
import ListModel from '../../models/list'
|
||||
import ListService from '../../services/list'
|
||||
import {CURRENT_LIST} from '../../store/mutation-types'
|
||||
import {getListView} from '../../helpers/saveListView'
|
||||
import {saveListToHistory} from '../../modules/listHistory'
|
||||
|
||||
export default {
|
||||
components: {Message},
|
||||
data() {
|
||||
return {
|
||||
listService: new ListService(),
|
||||
listLoaded: 0,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// call again the method if the route changes
|
||||
'$route.path': {
|
||||
handler: 'loadList',
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
// Computed property to let "listId" always have a value
|
||||
listId() {
|
||||
return typeof this.$route.params.listId === 'undefined' ? 0 : this.$route.params.listId
|
||||
},
|
||||
background() {
|
||||
return this.$store.state.background
|
||||
},
|
||||
currentList() {
|
||||
return typeof this.$store.state.currentList === 'undefined' ? {
|
||||
id: 0,
|
||||
title: '',
|
||||
isArchived: false,
|
||||
} : this.$store.state.currentList
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
replaceListView() {
|
||||
const savedListView = getListView(this.$route.params.listId)
|
||||
this.$router.replace({name: savedListView, params: {id: this.$route.params.listId}})
|
||||
console.debug('Replaced list view with', savedListView)
|
||||
},
|
||||
import ListModel from '@/models/list'
|
||||
import ListService from '@/services/list'
|
||||
|
||||
async loadList() {
|
||||
if (this.$route.name.includes('.settings.')) {
|
||||
return
|
||||
}
|
||||
import {store} from '@/store'
|
||||
import {CURRENT_LIST} from '@/store/mutation-types'
|
||||
|
||||
const listData = {id: parseInt(this.$route.params.listId)}
|
||||
import {getListView} from '@/helpers/saveListView'
|
||||
import {getListTitle} from '@/helpers/getListTitle'
|
||||
import {saveListToHistory} from '@/modules/listHistory'
|
||||
import { useTitle } from '@/composables/useTitle'
|
||||
|
||||
saveListToHistory(listData)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
this.setTitle(this.currentList.id ? this.getListTitle(this.currentList) : '')
|
||||
const listService = shallowRef(new ListService())
|
||||
const loadedListId = ref(0)
|
||||
|
||||
// This invalidates the loaded list at the kanban board which lets it reload its content when
|
||||
// switched to it. This ensures updates done to tasks in the gantt or list views are consistently
|
||||
// shown in all views while preventing reloads when closing a task popup.
|
||||
// We don't do this for the table view because that does not change tasks.
|
||||
if (
|
||||
this.$route.name === 'list.list' ||
|
||||
this.$route.name === 'list.gantt'
|
||||
) {
|
||||
this.$store.commit('kanban/setListId', 0)
|
||||
}
|
||||
// beforeRouteEnter(to) {
|
||||
// Redirect the user to list view by default
|
||||
if (route.name !== 'list.index') {
|
||||
const savedListView = getListView(route.params.listId)
|
||||
console.debug('Replaced list view with', savedListView)
|
||||
router.replace({name: 'list.list', params: {id: route.params.listId}})
|
||||
}
|
||||
// },
|
||||
|
||||
// // When clicking again on a list in the menu, there would be no list view selected which means no list
|
||||
// // at all. Users will then have to click on the list view menu again which is quite confusing.
|
||||
// if (this.$route.name === 'list.index') {
|
||||
// return this.replaceListView()
|
||||
// }
|
||||
const currentList = computed(() => {
|
||||
return typeof store.state.currentList === 'undefined' ? {
|
||||
id: 0,
|
||||
title: '',
|
||||
isArchived: false,
|
||||
} : store.state.currentList
|
||||
})
|
||||
|
||||
// Don't load the list if we either already loaded it or aren't dealing with a list at all currently and
|
||||
// the currently loaded list has the right set.
|
||||
if (
|
||||
(
|
||||
this.$route.params.listId === this.listLoaded ||
|
||||
typeof this.$route.params.listId === 'undefined' ||
|
||||
this.$route.params.listId === this.currentList.id ||
|
||||
parseInt(this.$route.params.listId) === this.currentList.id
|
||||
)
|
||||
&& typeof this.currentList !== 'undefined' && this.currentList.maxRight !== null
|
||||
) {
|
||||
return
|
||||
}
|
||||
// Computed property to let "listId" always have a value
|
||||
const listId = computed(() => typeof route.params.listId === 'undefined' ? 0 : parseInt(route.params.listId))
|
||||
// call again the method if the listId changes
|
||||
watchEffect(() => loadList(listId.value))
|
||||
|
||||
// Redirect the user to list view by default
|
||||
if (
|
||||
this.$route.name !== 'list.list' &&
|
||||
this.$route.name !== 'list.gantt' &&
|
||||
this.$route.name !== 'list.table' &&
|
||||
this.$route.name !== 'list.kanban'
|
||||
) {
|
||||
return this.replaceListView()
|
||||
}
|
||||
useTitle(() => currentList.value.id ? getListTitle(currentList.value) : '')
|
||||
|
||||
console.debug(`Loading list, $route.name = ${this.$route.name}, $route.params =`, this.$route.params, `, listLoaded = ${this.listLoaded}, currentList = `, this.currentList)
|
||||
async function loadList(listId) {
|
||||
const listData = {id: listId}
|
||||
saveListToHistory(listData)
|
||||
|
||||
// We create an extra list object instead of creating it in this.list because that would trigger a ui update which would result in bad ux.
|
||||
const list = new ListModel(listData)
|
||||
try {
|
||||
const loadedList = await this.listService.get(list)
|
||||
await this.$store.dispatch(CURRENT_LIST, loadedList)
|
||||
this.setTitle(this.getListTitle(loadedList))
|
||||
} finally {
|
||||
this.listLoaded = this.$route.params.listId
|
||||
}
|
||||
},
|
||||
},
|
||||
// This invalidates the loaded list at the kanban board which lets it reload its content when
|
||||
// switched to it. This ensures updates done to tasks in the gantt or list views are consistently
|
||||
// shown in all views while preventing reloads when closing a task popup.
|
||||
// We don't do this for the table view because that does not change tasks.
|
||||
// FIXME: remove this
|
||||
if (
|
||||
route.name === 'list.list' ||
|
||||
route.name === 'list.gantt'
|
||||
) {
|
||||
store.commit('kanban/setListId', 0)
|
||||
}
|
||||
|
||||
// Don't load the list if we either already loaded it or aren't dealing with a list at all currently and
|
||||
// the currently loaded list has the right set.
|
||||
if (
|
||||
(
|
||||
listId.value === loadedListId.value ||
|
||||
typeof listId.value === 'undefined' ||
|
||||
listId.value === currentList.value.id
|
||||
)
|
||||
&& typeof currentList.value !== 'undefined' && currentList.value.maxRight !== null
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
console.debug(`Loading list, $route.name = ${route.name}, $route.params =`, route.params, `, loadedListId = ${loadedListId.value}, currentList = `, currentList.value)
|
||||
|
||||
// We create an extra list object instead of creating it in list.value because that would trigger a ui update which would result in bad ux.
|
||||
const list = new ListModel(listData)
|
||||
try {
|
||||
const loadedList = await listService.value.get(list)
|
||||
await store.dispatch(CURRENT_LIST, loadedList)
|
||||
} finally {
|
||||
loadedListId.value = listId
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -52,61 +52,43 @@
|
||||
:show-taskswithout-dates="showTaskswithoutDates"
|
||||
/>
|
||||
|
||||
<transition name="modal">
|
||||
<task-detail-view-modal v-if="showTaskDetail" />
|
||||
</transition>
|
||||
</card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GanttChart from '../../../components/tasks/gantt-component'
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import flatPickr from 'vue-flatpickr-component'
|
||||
import Fancycheckbox from '../../../components/input/fancycheckbox'
|
||||
|
||||
import { i18n } from '@/i18n'
|
||||
import { store } from '@/store'
|
||||
|
||||
import GanttChart from '@/components/tasks/gantt-component'
|
||||
import Fancycheckbox from '@/components/input/fancycheckbox'
|
||||
|
||||
import {saveListView} from '@/helpers/saveListView'
|
||||
|
||||
import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue'
|
||||
const route = useRoute()
|
||||
// Save the current list view to local storage
|
||||
// We use local storage and not vuex here to make it persistent across reloads.
|
||||
saveListView(route.params.listId, route.name)
|
||||
|
||||
export default {
|
||||
name: 'Gantt',
|
||||
components: {
|
||||
Fancycheckbox,
|
||||
flatPickr,
|
||||
GanttChart,
|
||||
TaskDetailViewModal,
|
||||
const showTaskswithoutDates = ref(false)
|
||||
const dayWidth = ref(35)
|
||||
const dateFrom = ref(new Date((new Date()).setDate((new Date()).getDate() - 15)))
|
||||
const dateTo = ref(new Date((new Date()).setDate((new Date()).getDate() + 30)))
|
||||
|
||||
|
||||
const flatPickerConfig = computed(() => ({
|
||||
altFormat: i18n.global.t('date.altFormatShort'),
|
||||
altInput: true,
|
||||
dateFormat: 'Y-m-d',
|
||||
enableTime: false,
|
||||
locale: {
|
||||
firstDayOfWeek: store.state.auth.settings.weekStart,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
showTaskDetail: useShowModal(),
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// Save the current list view to local storage
|
||||
// We use local storage and not vuex here to make it persistent across reloads.
|
||||
saveListView(this.$route.params.listId, this.$route.name)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showTaskswithoutDates: false,
|
||||
dayWidth: 35,
|
||||
dateFrom: new Date((new Date()).setDate((new Date()).getDate() - 15)),
|
||||
dateTo: new Date((new Date()).setDate((new Date()).getDate() + 30)),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
flatPickerConfig() {
|
||||
return {
|
||||
altFormat: this.$t('date.altFormatShort'),
|
||||
altInput: true,
|
||||
dateFormat: 'Y-m-d',
|
||||
enableTime: false,
|
||||
locale: {
|
||||
firstDayOfWeek: this.$store.state.auth.settings.weekStart,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}))
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -205,9 +205,8 @@
|
||||
</div>
|
||||
|
||||
<transition name="modal">
|
||||
<task-detail-view-modal v-if="showTaskDetail" />
|
||||
<modal
|
||||
v-else-if="showBucketDeleteModal"
|
||||
v-if="showBucketDeleteModal"
|
||||
@close="showBucketDeleteModal = false"
|
||||
@submit="deleteBucket()"
|
||||
>
|
||||
@ -236,7 +235,6 @@ import Dropdown from '@/components/misc/dropdown.vue'
|
||||
import {getCollapsedBucketState, saveCollapsedBucketState} from '@/helpers/saveCollapsedBucketState'
|
||||
import {calculateItemPosition} from '../../../helpers/calculateItemPosition'
|
||||
import KanbanCard from '@/components/tasks/partials/kanban-card'
|
||||
import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue'
|
||||
|
||||
const DRAG_OPTIONS = {
|
||||
// sortable options
|
||||
@ -256,7 +254,6 @@ export default {
|
||||
Dropdown,
|
||||
FilterPopup,
|
||||
draggable,
|
||||
TaskDetailViewModal,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -293,12 +290,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
setup() {
|
||||
return {
|
||||
showTaskDetail: useShowModal(),
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
// Save the current list view to local storage
|
||||
// We use local storage and not vuex here to make it persistent across reloads.
|
||||
|
@ -122,10 +122,6 @@
|
||||
:current-page="currentPage"
|
||||
/>
|
||||
</card>
|
||||
|
||||
<transition name="modal">
|
||||
<task-detail-view-modal v-if="showTaskDetail" />
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -133,13 +129,10 @@
|
||||
import { ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import TaskService from '../../../services/task'
|
||||
import TaskModel from '../../../models/task'
|
||||
|
||||
import EditTask from '../../../components/tasks/edit-task'
|
||||
import AddTask from '../../../components/tasks/add-task'
|
||||
import SingleTaskInList from '../../../components/tasks/partials/singleTaskInList'
|
||||
import { createTaskList } from '@/composables/taskList'
|
||||
import { useTaskList } from '@/composables/taskList'
|
||||
import {saveListView} from '@/helpers/saveListView'
|
||||
import Rights from '../../../models/constants/rights.json'
|
||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||
@ -147,7 +140,6 @@ import {HAS_TASKS} from '@/store/mutation-types'
|
||||
import Nothing from '@/components/misc/nothing.vue'
|
||||
import Pagination from '@/components/misc/pagination.vue'
|
||||
import {ALPHABETICAL_SORT} from '@/components/list/partials/filters.vue'
|
||||
import TaskDetailViewModal, { useShowModal } from '@/views/tasks/TaskDetailViewModal.vue'
|
||||
|
||||
import draggable from 'vuedraggable'
|
||||
import {calculateItemPosition} from '../../../helpers/calculateItemPosition'
|
||||
@ -174,7 +166,6 @@ export default {
|
||||
name: 'List',
|
||||
data() {
|
||||
return {
|
||||
taskService: new TaskService(),
|
||||
ctaVisible: false,
|
||||
showTaskSearch: false,
|
||||
|
||||
@ -193,11 +184,10 @@ export default {
|
||||
AddTask,
|
||||
draggable,
|
||||
Pagination,
|
||||
TaskDetailViewModal,
|
||||
},
|
||||
|
||||
setup() {
|
||||
const taskEditTask = ref(TaskModel)
|
||||
const taskEditTask = ref(null)
|
||||
const isTaskEdit = ref(false)
|
||||
|
||||
// This function initializes the tasks page and loads the first page of tasks
|
||||
@ -206,17 +196,18 @@ export default {
|
||||
isTaskEdit.value = false
|
||||
}
|
||||
|
||||
const taskList = createTaskList(beforeLoad)
|
||||
const taskList = useTaskList(beforeLoad)
|
||||
|
||||
// Save the current list view to local storage
|
||||
// We use local storage and not vuex here to make it persistent across reloads.
|
||||
const route = useRoute()
|
||||
saveListView(route.params.listId, route.name)
|
||||
|
||||
taskList.initTaskList()
|
||||
|
||||
return {
|
||||
taskEditTask,
|
||||
isTaskEdit,
|
||||
showTaskDetail: useShowModal(),
|
||||
...taskList,
|
||||
}
|
||||
},
|
||||
|
@ -68,19 +68,19 @@
|
||||
<tr>
|
||||
<th v-if="activeColumns.id">
|
||||
#
|
||||
<sort :order="sortBy.id" @click="sort('id')"/>
|
||||
<Sort :order="sortBy.id" @click="sort('id')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.done">
|
||||
{{ $t('task.attributes.done') }}
|
||||
<sort :order="sortBy.done" @click="sort('done')"/>
|
||||
<Sort :order="sortBy.done" @click="sort('done')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.title">
|
||||
{{ $t('task.attributes.title') }}
|
||||
<sort :order="sortBy.title" @click="sort('title')"/>
|
||||
<Sort :order="sortBy.title" @click="sort('title')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.priority">
|
||||
{{ $t('task.attributes.priority') }}
|
||||
<sort :order="sortBy.priority" @click="sort('priority')"/>
|
||||
<Sort :order="sortBy.priority" @click="sort('priority')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.labels">
|
||||
{{ $t('task.attributes.labels') }}
|
||||
@ -90,27 +90,27 @@
|
||||
</th>
|
||||
<th v-if="activeColumns.dueDate">
|
||||
{{ $t('task.attributes.dueDate') }}
|
||||
<sort :order="sortBy.due_date" @click="sort('due_date')"/>
|
||||
<Sort :order="sortBy.due_date" @click="sort('due_date')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.startDate">
|
||||
{{ $t('task.attributes.startDate') }}
|
||||
<sort :order="sortBy.start_date" @click="sort('start_date')"/>
|
||||
<Sort :order="sortBy.start_date" @click="sort('start_date')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.endDate">
|
||||
{{ $t('task.attributes.endDate') }}
|
||||
<sort :order="sortBy.end_date" @click="sort('end_date')"/>
|
||||
<Sort :order="sortBy.end_date" @click="sort('end_date')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.percentDone">
|
||||
{{ $t('task.attributes.percentDone') }}
|
||||
<sort :order="sortBy.percent_done" @click="sort('percent_done')"/>
|
||||
<Sort :order="sortBy.percent_done" @click="sort('percent_done')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.created">
|
||||
{{ $t('task.attributes.created') }}
|
||||
<sort :order="sortBy.created" @click="sort('created')"/>
|
||||
<Sort :order="sortBy.created" @click="sort('created')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.updated">
|
||||
{{ $t('task.attributes.updated') }}
|
||||
<sort :order="sortBy.updated" @click="sort('updated')"/>
|
||||
<Sort :order="sortBy.updated" @click="sort('updated')"/>
|
||||
</th>
|
||||
<th v-if="activeColumns.createdBy">
|
||||
{{ $t('task.attributes.createdBy') }}
|
||||
@ -173,22 +173,13 @@
|
||||
:current-page="currentPage"
|
||||
/>
|
||||
</card>
|
||||
|
||||
<!-- This router view is used to show the task popup while keeping the table view itself -->
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="modal">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, reactive, computed, toRaw } from 'vue'
|
||||
<script setup>
|
||||
import { ref, reactive, computed, toRaw } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
import { createTaskList } from '@/composables/taskList'
|
||||
import Done from '@/components/misc/Done.vue'
|
||||
import User from '@/components/misc/user'
|
||||
import PriorityLabel from '@/components/tasks/partials/priorityLabel'
|
||||
@ -196,11 +187,13 @@ import Labels from '@/components/tasks/partials/labels'
|
||||
import DateTableCell from '@/components/tasks/partials/date-table-cell'
|
||||
import Fancycheckbox from '@/components/input/fancycheckbox'
|
||||
import Sort from '@/components/tasks/partials/sort'
|
||||
import {saveListView} from '@/helpers/saveListView'
|
||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||
import Pagination from '@/components/misc/pagination.vue'
|
||||
import Popup from '@/components/misc/popup'
|
||||
|
||||
import { useTaskList } from '@/composables/taskList'
|
||||
import {saveListView} from '@/helpers/saveListView'
|
||||
|
||||
const ACTIVE_COLUMNS_DEFAULT = {
|
||||
id: true,
|
||||
done: true,
|
||||
@ -233,102 +226,86 @@ function useSavedView(activeColumns, sortBy) {
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Table',
|
||||
components: {
|
||||
Popup,
|
||||
Done,
|
||||
FilterPopup,
|
||||
Sort,
|
||||
Fancycheckbox,
|
||||
DateTableCell,
|
||||
Labels,
|
||||
PriorityLabel,
|
||||
User,
|
||||
Pagination,
|
||||
},
|
||||
setup() {
|
||||
const activeColumns = reactive({ ...ACTIVE_COLUMNS_DEFAULT })
|
||||
const sortBy = ref({ ...SORT_BY_DEFAULT })
|
||||
const activeColumns = reactive({ ...ACTIVE_COLUMNS_DEFAULT })
|
||||
const sortBy = ref({ ...SORT_BY_DEFAULT })
|
||||
|
||||
useSavedView(activeColumns, sortBy)
|
||||
useSavedView(activeColumns, sortBy)
|
||||
|
||||
function beforeLoad(params) {
|
||||
// This makes sure an id sort order is always sorted last.
|
||||
// When tasks would be sorted first by id and then by whatever else was specified, the id sort takes
|
||||
// precedence over everything else, making any other sort columns pretty useless.
|
||||
let hasIdFilter = false
|
||||
const sortKeys = Object.keys(sortBy.value)
|
||||
for (const s of sortKeys) {
|
||||
if (s === 'id') {
|
||||
sortKeys.splice(s, 1)
|
||||
hasIdFilter = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (hasIdFilter) {
|
||||
sortKeys.push('id')
|
||||
}
|
||||
params.value.sort_by = sortKeys
|
||||
params.value.order_by = sortKeys.map(s => sortBy.value[s])
|
||||
function beforeLoad(params) {
|
||||
// This makes sure an id sort order is always sorted last.
|
||||
// When tasks would be sorted first by id and then by whatever else was specified, the id sort takes
|
||||
// precedence over everything else, making any other sort columns pretty useless.
|
||||
let hasIdFilter = false
|
||||
const sortKeys = Object.keys(sortBy.value)
|
||||
for (const s of sortKeys) {
|
||||
if (s === 'id') {
|
||||
sortKeys.splice(s, 1)
|
||||
hasIdFilter = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (hasIdFilter) {
|
||||
sortKeys.push('id')
|
||||
}
|
||||
params.value.sort_by = sortKeys
|
||||
params.value.order_by = sortKeys.map(s => sortBy.value[s])
|
||||
}
|
||||
|
||||
const taskList = createTaskList(beforeLoad)
|
||||
const {
|
||||
tasks,
|
||||
loading,
|
||||
showTaskFilter,
|
||||
params,
|
||||
loadTasks,
|
||||
totalPages,
|
||||
currentPage,
|
||||
searchTerm,
|
||||
initTaskList,
|
||||
} = useTaskList(beforeLoad)
|
||||
|
||||
Object.assign(taskList.params.value, {
|
||||
filter_by: [],
|
||||
filter_value: [],
|
||||
filter_comparator: [],
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const taskDetailRoutes = computed(() => Object.fromEntries(
|
||||
taskList.tasks.value.map(({id}) => ([
|
||||
id,
|
||||
{
|
||||
name: 'task.detail',
|
||||
params: { id },
|
||||
state: { backgroundView: router.currentRoute.value.fullPath },
|
||||
},
|
||||
])),
|
||||
))
|
||||
|
||||
// Save the current list view to local storage
|
||||
// We use local storage and not vuex here to make it persistent across reloads.
|
||||
const route = useRoute()
|
||||
saveListView(route.params.listId, route.name)
|
||||
|
||||
function sort(property) {
|
||||
const order = sortBy.value[property]
|
||||
if (typeof order === 'undefined' || order === 'none') {
|
||||
sortBy.value[property] = 'desc'
|
||||
} else if (order === 'desc') {
|
||||
sortBy.value[property] = 'asc'
|
||||
} else {
|
||||
delete sortBy.value[property]
|
||||
}
|
||||
beforeLoad(taskList.currentPage.value, taskList.searchTerm.value)
|
||||
// Save the order to be able to retrieve them later
|
||||
localStorage.setItem('tableViewSortBy', JSON.stringify(sortBy.value))
|
||||
}
|
||||
|
||||
function saveTaskColumns() {
|
||||
localStorage.setItem('tableViewColumns', JSON.stringify(toRaw(activeColumns)))
|
||||
}
|
||||
|
||||
taskList.initTaskList()
|
||||
|
||||
return {
|
||||
...taskList,
|
||||
sortBy,
|
||||
activeColumns,
|
||||
sort,
|
||||
saveTaskColumns,
|
||||
taskDetailRoutes,
|
||||
}
|
||||
},
|
||||
Object.assign(params.value, {
|
||||
filter_by: [],
|
||||
filter_value: [],
|
||||
filter_comparator: [],
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const taskDetailRoutes = computed(() => Object.fromEntries(
|
||||
tasks.value.map(({id}) => ([
|
||||
id,
|
||||
{
|
||||
name: 'task.detail',
|
||||
params: { id },
|
||||
state: { backgroundView: router.currentRoute.value.fullPath },
|
||||
},
|
||||
])),
|
||||
))
|
||||
|
||||
// Save the current list view to local storage
|
||||
// We use local storage and not vuex here to make it persistent across reloads.
|
||||
const route = useRoute()
|
||||
saveListView(route.params.listId, route.name)
|
||||
|
||||
function sort(property) {
|
||||
const order = sortBy.value[property]
|
||||
if (typeof order === 'undefined' || order === 'none') {
|
||||
sortBy.value[property] = 'desc'
|
||||
} else if (order === 'desc') {
|
||||
sortBy.value[property] = 'asc'
|
||||
} else {
|
||||
delete sortBy.value[property]
|
||||
}
|
||||
beforeLoad(currentPage.value, searchTerm.value)
|
||||
// Save the order to be able to retrieve them later
|
||||
localStorage.setItem('tableViewSortBy', JSON.stringify(sortBy.value))
|
||||
}
|
||||
|
||||
function saveTaskColumns() {
|
||||
localStorage.setItem('tableViewColumns', JSON.stringify(toRaw(activeColumns)))
|
||||
}
|
||||
|
||||
initTaskList()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
Reference in New Issue
Block a user