feat(labels): show priority labels based on minimum priority setting (#3075)

I think showing the priority of a task regardless of its value can be useful, the option for the user to choose the minimum priority for visualization is exposed in the settings. The default value is `priority.HIGH`, that corresponds to the current behavior.

Co-authored-by: konrad <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/3075
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Leonardo Cossutta <leonardo.cossutta@gmail.com>
Co-committed-by: Leonardo Cossutta <leonardo.cossutta@gmail.com>
This commit is contained in:
Leonardo Cossutta 2025-03-19 12:56:19 +00:00 committed by konrad
parent 516c764202
commit 357dbc1c69
6 changed files with 59 additions and 8 deletions

View File

@ -28,6 +28,7 @@ import {
faDownload,
faEllipsisH,
faEllipsisV,
faExclamation,
faExclamationCircle,
faEye,
faEyeSlash,
@ -193,6 +194,7 @@ library.add(faFont)
library.add(faRulerHorizontal)
library.add(faUnderline)
library.add(faFaceLaugh)
library.add(faExclamation)
// overwriting the wrong types
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes

View File

@ -1,17 +1,22 @@
<template>
<span
v-if="!done && (showAll || priority >= priorities.HIGH)"
v-if="!done && (showAll || priority >= minimumPriority)"
:class="{
'not-so-high': priority === priorities.HIGH,
'negligible': priority <= priorities.LOW,
'not-so-high': priority > priorities.LOW && priority < priorities.HIGH,
'high-priority': priority >= priorities.HIGH
}"
class="priority-label"
>
<span
v-if="priority >= priorities.HIGH"
class="icon"
>
<Icon icon="exclamation-circle" />
<span class="icon">
<Icon
v-if="priority >= priorities.HIGH"
icon="exclamation-circle"
/>
<Icon
v-else
icon="exclamation"
/>
</span>
<span>
<template v-if="priority === priorities.UNSET">{{ $t('task.priority.unset') }}</template>
@ -25,7 +30,9 @@
</template>
<script setup lang="ts">
import {computed} from 'vue'
import {PRIORITIES as priorities} from '@/constants/priorities'
import {useAuthStore} from '@/stores/auth'
withDefaults(defineProps<{
priority: number,
@ -36,6 +43,12 @@ withDefaults(defineProps<{
showAll: false,
done: false,
})
const authStore = useAuthStore()
const minimumPriority = computed(() => {
return authStore.settings.frontendSettings.minimumPriority
})
</script>
<style lang="scss" scoped>
@ -48,6 +61,10 @@ withDefaults(defineProps<{
color: var(--warning);
}
.negligible {
color: var(--info);
}
.icon {
vertical-align: top;
width: auto !important;

View File

@ -100,6 +100,7 @@
"timezone": "Time zone",
"overdueTasksRemindersTime": "Overdue tasks reminder email time",
"filterUsedOnOverview": "Saved filter used on the overview page",
"minimumPriority": "Minimum visible task priority",
"externalUserNameChange": "Your name is managed by your login provider ({provider}). To change it, please update it there instead."
},
"totp": {

View File

@ -5,6 +5,7 @@ import type {PrefixMode} from '@/modules/parseTaskText'
import type {BasicColorSchema} from '@vueuse/core'
import type {SupportedLocale} from '@/i18n'
import type {DefaultProjectViewKind} from '@/modelTypes/IProjectView'
import type {Priority} from '@/constants/priorities'
export interface IFrontendSettings {
playSoundWhenDone: boolean
@ -12,6 +13,7 @@ export interface IFrontendSettings {
colorSchema: BasicColorSchema
filterIdUsedOnOverview: IProject['id'] | null
defaultView?: DefaultProjectViewKind
minimumPriority: Priority
}
export interface IUserSettings extends IAbstract {
@ -20,7 +22,7 @@ export interface IUserSettings extends IAbstract {
discoverableByName: boolean
discoverableByEmail: boolean
overdueTasksRemindersEnabled: boolean
overdueTasksRemindersTime: string | Date
overdueTasksRemindersTime: undefined | string | Date
defaultProjectId: undefined | IProject['id']
weekStart: 0 | 1 | 2 | 3 | 4 | 5 | 6
timezone: string

View File

@ -4,6 +4,7 @@ import type {IFrontendSettings, IUserSettings} from '@/modelTypes/IUserSettings'
import {getBrowserLanguage} from '@/i18n'
import {PrefixMode} from '@/modules/parseTaskText'
import {DEFAULT_PROJECT_VIEW_SETTINGS} from '@/modelTypes/IProjectView'
import {PRIORITIES} from '@/constants/priorities'
export default class UserSettingsModel extends AbstractModel<IUserSettings> implements IUserSettings {
name = ''
@ -21,6 +22,7 @@ export default class UserSettingsModel extends AbstractModel<IUserSettings> impl
quickAddMagicMode: PrefixMode.Default,
colorSchema: 'auto',
defaultView: DEFAULT_PROJECT_VIEW_SETTINGS.FIRST,
minimumPriority: PRIORITIES.HIGH,
}
constructor(data: Partial<IUserSettings> = {}) {

View File

@ -51,6 +51,30 @@
</select>
</div>
</div>
<div class="field">
<label class="label">
{{ $t('user.settings.general.minimumPriority') }}
</label>
<div class="select">
<select v-model="settings.frontendSettings.minimumPriority">
<option :value="PRIORITIES.LOW">
{{ $t('task.priority.low') }}
</option>
<option :value="PRIORITIES.MEDIUM">
{{ $t('task.priority.medium') }}
</option>
<option :value="PRIORITIES.HIGH">
{{ $t('task.priority.high') }}
</option>
<option :value="PRIORITIES.URGENT">
{{ $t('task.priority.urgent') }}
</option>
<option :value="PRIORITIES.DO_NOW">
{{ $t('task.priority.doNow') }}
</option>
</select>
</div>
</div>
<div
v-if="hasFilters"
class="field"
@ -247,6 +271,7 @@ import {useAuthStore} from '@/stores/auth'
import type {IUserSettings} from '@/modelTypes/IUserSettings'
import {isSavedFilter} from '@/services/savedFilter'
import {DEFAULT_PROJECT_VIEW_SETTINGS} from '@/modelTypes/IProjectView'
import {PRIORITIES} from '@/constants/priorities'
const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.settings.general.title')} - ${t('user.settings.title')}`)
@ -288,6 +313,8 @@ const settings = ref<IUserSettings>({
...authStore.settings.frontendSettings,
// Add fallback for old settings that don't have the default view set
defaultView: authStore.settings.frontendSettings.defaultView ?? DEFAULT_PROJECT_VIEW_SETTINGS.FIRST,
// Add fallback for old settings that don't have the minimum priority set
minimumPriority: authStore.settings.frontendSettings.minimumPriority ?? PRIORITIES.HIGH,
},
})
const id = ref(createRandomID())