Add default view setting #2306

Open
Elscrux wants to merge 4 commits from Elscrux/vikunja:feature/default-view-setting into main
5 changed files with 30 additions and 6 deletions

View File

@ -95,6 +95,7 @@
"weekStartMonday": "Monday",
"language": "Language",
"defaultProject": "Default Project",
"defaultView": "Default View",
"timezone": "Time Zone",
"overdueTasksRemindersTime": "Overdue tasks reminder email time",
"filterUsedOnOverview": "Saved filter used on the overview page"

View File

@ -4,12 +4,14 @@ import type {IProject} from './IProject'
import type {PrefixMode} from '@/modules/parseTaskText'
import type {BasicColorSchema} from '@vueuse/core'
import type {SupportedLocale} from '@/i18n'
import type {ProjectViewKind} from '@/modelTypes/IProjectView'
export interface IFrontendSettings {
playSoundWhenDone: boolean
quickAddMagicMode: PrefixMode
colorSchema: BasicColorSchema
filterIdUsedOnOverview: IProject['id'] | null
defaultView: ProjectViewKind
}
export interface IUserSettings extends IAbstract {

View File

@ -3,6 +3,7 @@ import AbstractModel from './abstractModel'
import type {IFrontendSettings, IUserSettings} from '@/modelTypes/IUserSettings'
import {getBrowserLanguage} from '@/i18n'
import {PrefixMode} from '@/modules/parseTaskText'
import {PROJECT_VIEW_KINDS} from '@/modelTypes/IProjectView'
export default class UserSettingsModel extends AbstractModel<IUserSettings> implements IUserSettings {
name = ''
@ -19,6 +20,7 @@ export default class UserSettingsModel extends AbstractModel<IUserSettings> impl
playSoundWhenDone: true,
quickAddMagicMode: PrefixMode.Default,
colorSchema: 'auto',
defaultView: PROJECT_VIEW_KINDS.LIST,
}
constructor(data: Partial<IUserSettings> = {}) {

View File

@ -8,6 +8,7 @@ import ProjectList from '@/components/project/views/ProjectList.vue'
import ProjectGantt from '@/components/project/views/ProjectGantt.vue'
import ProjectTable from '@/components/project/views/ProjectTable.vue'
import ProjectKanban from '@/components/project/views/ProjectKanban.vue'
import {useAuthStore} from '@/stores/auth'
const {
projectId,
@ -19,6 +20,7 @@ const {
const router = useRouter()
const projectStore = useProjectStore()
const authStore = useAuthStore()
const currentView = computed(() => {
const project = projectStore.projects[projectId]
@ -26,17 +28,17 @@ const currentView = computed(() => {
return project?.views.find(v => v.id === viewId)
})
function redirectToFirstViewIfNecessary() {
function redirectToDefaultViewIfNecessary() {
if (viewId === 0 || !projectStore.projects[projectId]?.views.find(v => v.id === viewId)) {
// Ideally, we would do that in the router redirect, but the projects (and therefore, the views)
// are not always loaded then.
const firstViewId = projectStore.projects[projectId]?.views[0].id
if (firstViewId) {
const defaultView = projectStore.projects[projectId]?.views.find(v => v.viewKind === authStore.settings.frontendSettings.defaultView)
if (defaultView) {
router.replace({
name: 'project.view',
params: {
projectId,
viewId: firstViewId,
viewId: defaultView.id,

This won't work. What if I rearrange the views or delete a view so that, for example, the kanban view is at the first position? Then this will crash.

Please loop over projectStore.projects[projectId]?.views until you find the first view of the kind that's saved in authStore.settings.frontendSettings.defaultView. If that's not available (use the .find function, then the result here is undefined), use the first view, in the same way as it was checked previously.

This won't work. What if I rearrange the views or delete a view so that, for example, the kanban view is at the first position? Then this will crash. Please loop over `projectStore.projects[projectId]?.views` until you find the first view of the kind that's saved in `authStore.settings.frontendSettings.defaultView`. If that's not available (use the `.find` function, then the result here is `undefined`), use the first view, in the same way as it was checked previously.

I'm not quite sure I did what you wanted, but it should search for them by view kind now.

I still couldn't test it as the views are always undefined even in the main branch for me and it always results in projectStore.projects[__props.projectId].views[something] is undefined when opening a project (opening tasks directly works).

I'm not quite sure I did what you wanted, but it should search for them by view kind now. I still couldn't test it as the views are always undefined even in the main branch for me and it always results in `projectStore.projects[__props.projectId].views[something] is undefined` when opening a project (opening tasks directly works).

I still couldn't test it as the views are always undefined even in the main branch for me

Did you test with an api built from the main branch as well?

> I still couldn't test it as the views are always undefined even in the main branch for me Did you test with an api built from the main branch as well?

Yes I did.

Yes I did.

Update: I actually just got it working - it is likely related to updating the backend that I used for testing.

Update: I actually just got it working - it is likely related to updating the backend that I used for testing.

So it all works fine?

So it all works fine?

Yeah I just tried it. Works just fine!
Now the only thing I'll be looking into adding is a default setting in the configs. (Although it looks like currently no frontend settings support default config options - would that make sense to add here?)

Yeah I just tried it. Works just fine! Now the only thing I'll be looking into adding is a default setting in the configs. (Although it looks like currently no frontend settings support default config options - would that make sense to add here?)

You mean a default setting in the config for new users? TBH I don't think that's needed because it is easily changeable for users.

You mean a default setting in the config for new users? TBH I don't think that's needed because it is easily changeable for users.

The reason why I'm bringing this up is that some of our members were very confused about the default list layout, and they didn't see the option to change the view to kanban which is what they're used to. A default setting would help with that.

The reason why I'm bringing this up is that some of our members were very confused about the default list layout, and they didn't see the option to change the view to kanban which is what they're used to. A default setting would help with that.

Okay, but doesn't educating the users about the different views and how they can set a default for them (with this PR) solve that problem?

Okay, but doesn't educating the users about the different views and how they can set a default for them (with this PR) solve that problem?

It does! I just wanted to have something for their convenience to set it to this by default.

It does! I just wanted to have something for their convenience to set it to this by default.
},
})
}
@ -45,13 +47,13 @@ function redirectToFirstViewIfNecessary() {
watch(
() => viewId,
redirectToFirstViewIfNecessary,
redirectToDefaultViewIfNecessary,
{immediate: true},
)
watch(
() => projectStore.projects[projectId],
redirectToFirstViewIfNecessary,
redirectToDefaultViewIfNecessary,
)
// using a watcher instead of beforeEnter because beforeEnter is not called when only the viewId changes

View File

@ -26,6 +26,22 @@
</label>
<ProjectSearch v-model="defaultProject" />
</div>
<div class="field">
<label class="label">
{{ $t('user.settings.general.defaultView') }}
</label>
<div class="select ml-2">
<select v-model="settings.frontendSettings.defaultView">
<option
v-for="view in PROJECT_VIEW_KINDS"
:key="view"
:value="view"
>
{{ $t(`project.${view}.title`) }}
</option>
</select>
</div>
</div>
<div
v-if="hasFilters"
class="field"
@ -221,6 +237,7 @@ import {useProjectStore} from '@/stores/projects'
import {useAuthStore} from '@/stores/auth'
import type {IUserSettings} from '@/modelTypes/IUserSettings'
import {isSavedFilter} from '@/services/savedFilter'
import {PROJECT_VIEW_KINDS} from '@/modelTypes/IProjectView'
const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.settings.general.title')} - ${t('user.settings.title')}`)