2018-09-08 23:33:23 +02:00
|
|
|
<template>
|
2020-05-31 21:17:10 +02:00
|
|
|
<div
|
2021-01-30 17:17:04 +01:00
|
|
|
:class="{ 'is-loading': listService.loading, 'is-archived': currentList.isArchived}"
|
2020-09-05 22:35:52 +02:00
|
|
|
class="loader-container"
|
2020-05-31 21:17:10 +02:00
|
|
|
>
|
2021-01-18 22:14:10 +01:00
|
|
|
<div class="switch-view-container">
|
|
|
|
<div class="switch-view">
|
|
|
|
<router-link
|
2021-11-13 21:28:29 +01:00
|
|
|
v-shortcut="'g l'"
|
|
|
|
:title="$t('keyboardShortcuts.list.switchToListView')"
|
2021-12-10 15:29:28 +01:00
|
|
|
:class="{'is-active': viewName === 'list'}"
|
2021-11-01 18:19:59 +01:00
|
|
|
:to="{ name: 'list.list', params: { listId } }">
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('list.list.title') }}
|
2021-01-18 22:14:10 +01:00
|
|
|
</router-link>
|
|
|
|
<router-link
|
2021-11-13 21:28:29 +01:00
|
|
|
v-shortcut="'g g'"
|
|
|
|
:title="$t('keyboardShortcuts.list.switchToGanttView')"
|
2021-12-10 15:29:28 +01:00
|
|
|
:class="{'is-active': viewName === 'gantt'}"
|
2021-11-01 18:19:59 +01:00
|
|
|
:to="{ name: 'list.gantt', params: { listId } }">
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('list.gantt.title') }}
|
2021-01-18 22:14:10 +01:00
|
|
|
</router-link>
|
|
|
|
<router-link
|
2021-11-13 21:28:29 +01:00
|
|
|
v-shortcut="'g t'"
|
|
|
|
:title="$t('keyboardShortcuts.list.switchToTableView')"
|
2021-12-10 15:29:28 +01:00
|
|
|
:class="{'is-active': viewName === 'table'}"
|
2021-11-01 18:19:59 +01:00
|
|
|
:to="{ name: 'list.table', params: { listId } }">
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('list.table.title') }}
|
2021-01-18 22:14:10 +01:00
|
|
|
</router-link>
|
|
|
|
<router-link
|
2021-11-13 21:28:29 +01:00
|
|
|
v-shortcut="'g k'"
|
|
|
|
:title="$t('keyboardShortcuts.list.switchToKanbanView')"
|
2021-12-10 15:29:28 +01:00
|
|
|
:class="{'is-active': viewName === 'kanban'}"
|
2021-11-01 18:19:59 +01:00
|
|
|
:to="{ name: 'list.kanban', params: { listId } }">
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('list.kanban.title') }}
|
2021-01-18 22:14:10 +01:00
|
|
|
</router-link>
|
|
|
|
</div>
|
2021-11-14 21:33:53 +01:00
|
|
|
<slot name="header" />
|
2020-05-31 21:17:10 +02:00
|
|
|
</div>
|
2021-01-30 17:17:04 +01:00
|
|
|
<transition name="fade">
|
2021-11-01 18:19:59 +01:00
|
|
|
<Message variant="warning" v-if="currentList.isArchived" class="mb-4">
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('list.archived') }}
|
2021-11-01 18:19:59 +01:00
|
|
|
</Message>
|
2021-01-30 17:17:04 +01:00
|
|
|
</transition>
|
2019-04-29 23:41:39 +02:00
|
|
|
|
2021-11-14 21:33:53 +01:00
|
|
|
<slot />
|
2018-09-08 23:33:23 +02:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2021-12-10 15:29:28 +01:00
|
|
|
<script setup lang="ts">
|
2021-11-01 18:19:59 +01:00
|
|
|
import {ref, shallowRef, computed, watchEffect} from 'vue'
|
2021-11-14 21:33:53 +01:00
|
|
|
import {useRoute} from 'vue-router'
|
2021-11-01 18:19:59 +01:00
|
|
|
|
2021-12-10 15:29:28 +01:00
|
|
|
import Message from '@/components/misc/message.vue'
|
2021-11-01 18:19:59 +01:00
|
|
|
|
|
|
|
import ListModel from '@/models/list'
|
|
|
|
import ListService from '@/services/list'
|
|
|
|
|
|
|
|
import {store} from '@/store'
|
|
|
|
import {CURRENT_LIST} from '@/store/mutation-types'
|
|
|
|
|
|
|
|
import {getListTitle} from '@/helpers/getListTitle'
|
|
|
|
import {saveListToHistory} from '@/modules/listHistory'
|
|
|
|
import { useTitle } from '@/composables/useTitle'
|
|
|
|
|
2021-12-10 15:29:28 +01:00
|
|
|
const props = defineProps({
|
|
|
|
listId: {
|
|
|
|
type: Number,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
viewName: {
|
|
|
|
type: String,
|
|
|
|
required: true,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-11-01 18:19:59 +01:00
|
|
|
const route = useRoute()
|
|
|
|
|
|
|
|
const listService = shallowRef(new ListService())
|
|
|
|
const loadedListId = ref(0)
|
|
|
|
|
|
|
|
const currentList = computed(() => {
|
|
|
|
return typeof store.state.currentList === 'undefined' ? {
|
|
|
|
id: 0,
|
|
|
|
title: '',
|
|
|
|
isArchived: false,
|
2022-01-30 16:47:23 +01:00
|
|
|
maxRight: null,
|
2021-11-01 18:19:59 +01:00
|
|
|
} : store.state.currentList
|
|
|
|
})
|
|
|
|
|
|
|
|
// call again the method if the listId changes
|
2021-12-10 15:29:28 +01:00
|
|
|
watchEffect(() => loadList(props.listId))
|
2021-11-01 18:19:59 +01:00
|
|
|
|
|
|
|
useTitle(() => currentList.value.id ? getListTitle(currentList.value) : '')
|
|
|
|
|
2021-12-10 15:29:28 +01:00
|
|
|
async function loadList(listIdToLoad: number) {
|
2021-11-17 18:04:53 +01:00
|
|
|
const listData = {id: listIdToLoad}
|
2021-11-01 18:19:59 +01:00
|
|
|
saveListToHistory(listData)
|
|
|
|
|
|
|
|
// 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 (
|
2021-12-10 15:29:28 +01:00
|
|
|
props.viewName === 'list.list' ||
|
|
|
|
props.viewName === 'list.gantt'
|
2021-11-01 18:19:59 +01:00
|
|
|
) {
|
|
|
|
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 (
|
|
|
|
(
|
2021-11-17 18:04:53 +01:00
|
|
|
listIdToLoad === loadedListId.value ||
|
|
|
|
typeof listIdToLoad === 'undefined' ||
|
|
|
|
listIdToLoad === currentList.value.id
|
2021-11-01 18:19:59 +01:00
|
|
|
)
|
|
|
|
&& typeof currentList.value !== 'undefined' && currentList.value.maxRight !== null
|
|
|
|
) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-10 15:29:28 +01:00
|
|
|
console.debug(`Loading list, props.viewName = ${props.viewName}, $route.params =`, route.params, `, loadedListId = ${loadedListId.value}, currentList = `, currentList.value)
|
2021-11-01 18:19:59 +01:00
|
|
|
|
|
|
|
// 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 {
|
2021-12-10 15:29:28 +01:00
|
|
|
loadedListId.value = props.listId
|
2021-11-01 18:19:59 +01:00
|
|
|
}
|
2020-09-05 22:35:52 +02:00
|
|
|
}
|
2021-07-09 10:22:20 +02:00
|
|
|
</script>
|
2021-10-18 14:21:02 +02:00
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2021-10-18 14:21:53 +02:00
|
|
|
.switch-view-container {
|
|
|
|
@media screen and (max-width: $tablet) {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.switch-view {
|
2021-11-22 22:12:54 +01:00
|
|
|
background: var(--white);
|
2021-10-18 14:21:53 +02:00
|
|
|
display: inline-flex;
|
|
|
|
border-radius: $radius;
|
|
|
|
font-size: .75rem;
|
2021-11-22 22:12:54 +01:00
|
|
|
box-shadow: var(--shadow-sm);
|
2021-10-18 14:21:53 +02:00
|
|
|
height: $switch-view-height;
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
padding: .5rem;
|
|
|
|
|
|
|
|
a {
|
|
|
|
padding: .25rem .5rem;
|
|
|
|
display: block;
|
|
|
|
border-radius: $radius;
|
|
|
|
|
|
|
|
transition: all 100ms;
|
|
|
|
|
|
|
|
&:not(:last-child) {
|
|
|
|
margin-right: .5rem;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.is-active,
|
2021-11-22 22:12:54 +01:00
|
|
|
&:hover {
|
|
|
|
color: var(--switch-view-color);
|
2021-10-18 14:21:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
&.is-active {
|
2021-11-22 22:12:54 +01:00
|
|
|
background: var(--primary);
|
2021-10-18 14:21:53 +02:00
|
|
|
font-weight: bold;
|
2021-11-22 22:12:54 +01:00
|
|
|
box-shadow: var(--shadow-xs);
|
2021-10-18 14:21:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
&:hover {
|
2021-11-22 22:12:54 +01:00
|
|
|
background: var(--primary);
|
2021-10-18 14:21:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-18 14:21:02 +02:00
|
|
|
.is-archived .notification.is-warning {
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
}
|
|
|
|
</style>
|