feat: add display setting for dates (#1192)

This commit is contained in:
kolaente 2025-07-30 09:43:37 +02:00 committed by GitHub
parent 7363355fe0
commit b444cf8d43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 213 additions and 41 deletions

View File

@ -0,0 +1,57 @@
import {UserFactory} from '../../factories/user'
import {ProjectFactory} from '../../factories/project'
import {TaskFactory} from '../../factories/task'
import {login} from '../../support/authenticateUser'
import {DATE_DISPLAY} from '../../../src/constants/dateDisplay'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
dayjs.extend(relativeTime)
const createdDate = new Date(Date.UTC(2022, 6, 25, 12))
const now = new Date(Date.UTC(2022, 6, 30, 12))
const expectedFormats = {
[DATE_DISPLAY.RELATIVE]: dayjs(createdDate).from(now),
[DATE_DISPLAY.MM_DD_YYYY]: dayjs(createdDate).format('MM-DD-YYYY'),
[DATE_DISPLAY.DD_MM_YYYY]: dayjs(createdDate).format('DD-MM-YYYY'),
[DATE_DISPLAY.YYYY_MM_DD]: dayjs(createdDate).format('YYYY-MM-DD'),
[DATE_DISPLAY.MM_SLASH_DD_YYYY]: dayjs(createdDate).format('MM/DD/YYYY'),
[DATE_DISPLAY.DD_SLASH_MM_YYYY]: dayjs(createdDate).format('DD/MM/YYYY'),
[DATE_DISPLAY.YYYY_SLASH_MM_DD]: dayjs(createdDate).format('YYYY/MM/DD'),
[DATE_DISPLAY.DAY_MONTH_YEAR]: new Intl.DateTimeFormat('en', {
day: 'numeric',
month: 'long',
year: 'numeric',
}).format(createdDate),
[DATE_DISPLAY.WEEKDAY_DAY_MONTH_YEAR]: new Intl.DateTimeFormat('en', {
weekday: 'long',
day: 'numeric',
month: 'long',
year: 'numeric',
}).format(createdDate),
}
describe('Date display setting', () => {
Object.entries(expectedFormats).forEach(([format, expected]) => {
it(`shows ${format}`, () => {
const user = UserFactory.create(1, {
frontend_settings: JSON.stringify({dateDisplay: format}),
})[0]
const project = ProjectFactory.create(1, {owner_id: user.id})[0]
TaskFactory.truncate()
const task = TaskFactory.create(1, {
id: 1,
project_id: project.id,
created_by_id: user.id,
created: createdDate.toISOString(),
updated: createdDate.toISOString(),
})[0]
cy.clock(now, ['Date'])
login(user)
cy.visit(`/tasks/${task.id}`)
cy.get('.task-view .created time span').should('contain', expected)
})
})
})

View File

@ -1,5 +1,10 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
dayjs.extend(relativeTime)
import {TaskFactory} from '../../factories/task'
import {ProjectFactory} from '../../factories/project'
import {TaskCommentFactory} from '../../factories/task_comment'
@ -629,10 +634,9 @@ describe('Task', () => {
.click()
const today = new Date()
const day = today.toLocaleString('default', {day: 'numeric'})
const month = today.toLocaleString('default', {month: 'short'})
const year = today.toLocaleString('default', {year: 'numeric'})
const date = `${month} ${day}, ${year} 12:00 PM`
today.setHours(12)
today.setMinutes(0)
today.setSeconds(0)
cy.get('.task-view .columns.details .column')
.contains('Due Date')
.get('.date-input .datepicker-popup')
@ -640,7 +644,7 @@ describe('Task', () => {
cy.get('.task-view .columns.details .column')
.contains('Due Date')
.get('.date-input')
.should('contain.text', date)
.should('contain.text', dayjs(today).fromNow())
cy.get('.global-notification')
.should('contain', 'Success')
})
@ -658,6 +662,9 @@ describe('Task', () => {
})
const today = new Date(2025, 2, 5)
today.setHours(12)
today.setMinutes(0)
today.setSeconds(0)
cy.visit(`/tasks/${tasks[0].id}`)
@ -674,10 +681,6 @@ describe('Task', () => {
.contains('Confirm')
.click()
const day = today.toLocaleString('default', {day: 'numeric'})
const month = today.toLocaleString('default', {month: 'short'})
const year = today.toLocaleString('default', {year: 'numeric'})
const date = `${month} ${day}, ${year} 12:00 PM`
cy.get('.task-view .columns.details .column')
.contains('Due Date')
.get('.date-input .datepicker-popup')
@ -685,7 +688,7 @@ describe('Task', () => {
cy.get('.task-view .columns.details .column')
.contains('Due Date')
.get('.date-input')
.should('contain.text', date)
.should('contain.text', dayjs(today).fromNow())
cy.get('.global-notification')
.should('contain', 'Success')
})

View File

@ -5,7 +5,7 @@
:disabled="disabled || undefined"
@click.stop="toggleDatePopup"
>
{{ date === null ? chooseDateLabel : formatDateShort(date) }}
{{ date === null ? chooseDateLabel : formatDisplayDate(date) }}
</SimpleButton>
<CustomTransition name="fade">
@ -39,7 +39,7 @@ import CustomTransition from '@/components/misc/CustomTransition.vue'
import DatepickerInline from '@/components/input/DatepickerInline.vue'
import SimpleButton from '@/components/input/SimpleButton.vue'
import {formatDateShort} from '@/helpers/time/formatDate'
import {formatDisplayDate} from '@/helpers/time/formatDate'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
import {createDateFromString} from '@/helpers/time/createDateFromString'
import {useI18n} from 'vue-i18n'

View File

@ -59,7 +59,7 @@
v-tooltip="formatDateLong(n.created)"
class="created"
>
{{ formatDateSince(n.created) }}
{{ formatDisplayDate(n.created) }}
</span>
</div>
</div>
@ -95,7 +95,7 @@ import CustomTransition from '@/components/misc/CustomTransition.vue'
import User from '@/components/misc/User.vue'
import { NOTIFICATION_NAMES as names, type INotification} from '@/modelTypes/INotification'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
import {formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {formatDateLong, formatDisplayDate} from '@/helpers/time/formatDate'
import {getDisplayName} from '@/models/user'
import {useAuthStore} from '@/stores/auth'
import XButton from '@/components/input/Button.vue'

View File

@ -56,7 +56,7 @@
scope="global"
>
<span v-tooltip="formatDateLong(a.created)">
{{ formatDateSince(a.created) }}
{{ formatDisplayDate(a.created) }}
</span>
<User
:avatar-size="24"
@ -185,7 +185,7 @@ import type {IAttachment} from '@/modelTypes/IAttachment'
import type {ITask} from '@/modelTypes/ITask'
import {useAttachmentStore} from '@/stores/attachments'
import {formatDateSince, formatDateLong} from '@/helpers/time/formatDate'
import {formatDisplayDate, formatDateLong} from '@/helpers/time/formatDate'
import {uploadFiles, generateAttachmentUrl} from '@/helpers/attachments'
import {getHumanSize} from '@/helpers/getHumanSize'
import {useCopyToClipboard} from '@/composables/useCopyToClipboard'

View File

@ -53,13 +53,13 @@
v-tooltip="formatDateLong(c.created)"
class="has-text-grey"
>
{{ formatDateSince(c.created) }}
{{ formatDisplayDate(c.created) }}
</span>
<span
v-if="+new Date(c.created) !== +new Date(c.updated)"
v-tooltip="formatDateLong(c.updated)"
>
· {{ $t('task.comment.edited', {date: formatDateSince(c.updated)}) }}
· {{ $t('task.comment.edited', {date: formatDisplayDate(c.updated)}) }}
</span>
<a
v-tooltip="$t('task.comment.permalink')"
@ -221,7 +221,7 @@ import type {ITask} from '@/modelTypes/ITask'
import {uploadFile} from '@/helpers/attachments'
import {success} from '@/message'
import {formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {formatDateLong, formatDisplayDate} from '@/helpers/time/formatDate'
import {fetchAvatarBlobUrl, getDisplayName} from '@/models/user'
import type {IUser} from '@/modelTypes/IUser'
import {useConfigStore} from '@/stores/config'

View File

@ -8,7 +8,7 @@
keypath="task.detail.created"
scope="global"
>
<span>{{ formatDateSince(task.created) }}</span>
<span>{{ formatDisplayDate(task.created) }}</span>
{{ getDisplayName(task.createdBy) }}
</i18n-t>
</time>
@ -46,7 +46,7 @@
<script lang="ts" setup>
import {computed} from 'vue'
import type {ITask} from '@/modelTypes/ITask'
import {formatISO, formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {formatISO, formatDateLong, formatDisplayDate} from '@/helpers/time/formatDate'
import {getDisplayName} from '@/models/user'
const props = defineProps<{
@ -54,9 +54,9 @@ const props = defineProps<{
}>()
// Computed properties to show the actual date every time it gets updated
const updatedSince = computed(() => formatDateSince(props.task.updated))
const updatedSince = computed(() => formatDisplayDate(props.task.updated))
const updatedFormatted = computed(() => formatDateLong(props.task.updated))
const doneSince = computed(() => formatDateSince(props.task.doneAt))
const doneSince = computed(() => formatDisplayDate(props.task.doneAt))
const doneFormatted = computed(() => formatDateLong(props.task.doneAt))
</script>

View File

@ -1,13 +1,13 @@
<template>
<td v-tooltip="+date === 0 ? '' : formatDateLong(date)">
<time :datetime="date ? formatISO(date) : undefined">
{{ +date === 0 ? '-' : formatDateSince(date) }}
{{ +date === 0 ? '-' : formatDisplayDate(date) }}
</time>
</td>
</template>
<script setup lang="ts">
import {formatISO, formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {formatISO, formatDateLong, formatDisplayDate} from '@/helpers/time/formatDate'
withDefaults(defineProps<{
date?: Date

View File

@ -53,7 +53,7 @@
<Icon :icon="['far', 'calendar-alt']" />
</span>
<time :datetime="formatISO(task.dueDate)">
{{ formatDateSince(task.dueDate) }}
{{ formatDisplayDate(task.dueDate) }}
</time>
</span>
<h3>{{ task.title }}</h3>
@ -121,7 +121,7 @@ import type {IProject} from '@/modelTypes/IProject'
import {SUPPORTED_IMAGE_SUFFIX} from '@/models/attachment'
import AttachmentService, {PREVIEW_SIZE} from '@/services/attachment'
import {formatDateLong, formatDateSince, formatISO} from '@/helpers/time/formatDate'
import {formatDateLong, formatDisplayDate, formatISO} from '@/helpers/time/formatDate'
import {colorIsDark} from '@/helpers/color/colorIsDark'
import {useTaskStore} from '@/stores/tasks'
import AssigneeList from '@/components/tasks/partials/AssigneeList.vue'

View File

@ -3,7 +3,7 @@
<Popup @update:open="showFormSwitch = null">
<template #trigger="{toggle}">
<SimpleButton
v-tooltip="reminder.reminder && reminder.relativeTo !== null ? formatDateShort(reminder.reminder) : null"
v-tooltip="reminder.reminder && reminder.relativeTo !== null ? formatDisplayDate(reminder.reminder) : null"
@click.prevent.stop="toggle()"
>
{{ reminderText }}
@ -77,7 +77,7 @@ import {useI18n} from 'vue-i18n'
import {type PeriodUnit, secondsToPeriod} from '@/helpers/time/period'
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
import {formatDateShort} from '@/helpers/time/formatDate'
import {formatDisplayDate} from '@/helpers/time/formatDate'
import DatepickerInline from '@/components/input/DatepickerInline.vue'
import ReminderPeriod from '@/components/tasks/partials/ReminderPeriod.vue'
@ -132,7 +132,7 @@ const reminderText = computed(() => {
}
if (reminder.value.reminder !== null) {
return formatDateShort(reminder.value.reminder)
return formatDisplayDate(reminder.value.reminder)
}
return t('task.addReminder')

View File

@ -201,7 +201,7 @@ import Popup from '@/components/misc/Popup.vue'
import TaskService from '@/services/task'
import {formatDateSince, formatISO, formatDateLong} from '@/helpers/time/formatDate'
import {formatDisplayDate, formatISO, formatDateLong} from '@/helpers/time/formatDate'
import {success} from '@/message'
import {useProjectStore} from '@/stores/projects'
@ -286,7 +286,7 @@ function updateDueDate() {
return
}
dueDateFormatted.value = formatDateSince(task.value.dueDate)
dueDateFormatted.value = formatDisplayDate(task.value.dueDate)
}
const dueDateFormatted = ref('')

View File

@ -58,7 +58,7 @@
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
class="is-italic"
>
{{ $t('task.detail.due', {at: formatDateSince(task.dueDate)}) }}
{{ $t('task.detail.due', {at: formatDisplayDate(task.dueDate)}) }}
</time>
</span>
@ -108,7 +108,7 @@ import ChecklistSummary from '@/components/tasks/partials/ChecklistSummary.vue'
import ColorBubble from '@/components/misc/ColorBubble.vue'
import {formatDateSince, formatISO, formatDateLong} from '@/helpers/time/formatDate'
import {formatDisplayDate, formatISO, formatDateLong} from '@/helpers/time/formatDate'
import {useProjectStore} from '@/stores/projects'
import AssigneeList from '@/components/tasks/partials/AssigneeList.vue'

View File

@ -0,0 +1,9 @@
import {computed} from 'vue'
import {createSharedComposable} from '@vueuse/core'
import {useAuthStore} from '@/stores/auth'
export const useDateDisplay = createSharedComposable(() => {
const authStore = useAuthStore()
const store = computed(() => authStore.settings.frontendSettings.dateDisplay)
return {store}
})

View File

@ -0,0 +1,13 @@
export const DATE_DISPLAY = {
RELATIVE: 'relative',
MM_DD_YYYY: 'mm-dd-yyyy',
DD_MM_YYYY: 'dd-mm-yyyy',
YYYY_MM_DD: 'yyyy-mm-dd',
MM_SLASH_DD_YYYY: 'mm/dd/yyyy',
DD_SLASH_MM_YYYY: 'dd/mm/yyyy',
YYYY_SLASH_MM_DD: 'yyyy/mm/dd',
DAY_MONTH_YEAR: 'dayMonthYear',
WEEKDAY_DAY_MONTH_YEAR: 'weekdayDayMonthYear',
} as const
export type DateDisplay = typeof DATE_DISPLAY[keyof typeof DATE_DISPLAY]

View File

@ -4,6 +4,8 @@ import dayjs from 'dayjs'
import {i18n} from '@/i18n'
import {createSharedComposable} from '@vueuse/core'
import {computed, toValue, type MaybeRefOrGetter} from 'vue'
import {useDateDisplay} from '@/composables/useDateDisplay'
import {DATE_DISPLAY, type DateDisplay} from '@/constants/dateDisplay'
import {DAYJS_LOCALE_MAPPING} from '@/i18n/useDayjsLanguageSync.ts'
export function dateIsValid(date: Date | null) {
@ -67,3 +69,44 @@ export function useWeekDayFromDate() {
return computed(() => (date: Date) => dateTimeFormatter.value.format(date))
}
export function formatDisplayDate(date: Date | string | null) {
const {store} = useDateDisplay()
const current = store.value
return formatDisplayDateFormat(date, current)
}
export function formatDisplayDateFormat(date: Date | string | null, format: DateDisplay) {
if (typeof date === 'string') {
date = createDateFromString(date)
}
if (date === null || !dateIsValid(date)) {
return ''
}
switch (format) {
case DATE_DISPLAY.MM_DD_YYYY:
return formatDate(date, 'MM-DD-YYYY')
case DATE_DISPLAY.DD_MM_YYYY:
return formatDate(date, 'DD-MM-YYYY')
case DATE_DISPLAY.YYYY_MM_DD:
return formatDate(date, 'YYYY-MM-DD')
case DATE_DISPLAY.MM_SLASH_DD_YYYY:
return formatDate(date, 'MM/DD/YYYY')
case DATE_DISPLAY.DD_SLASH_MM_YYYY:
return formatDate(date, 'DD/MM/YYYY')
case DATE_DISPLAY.YYYY_SLASH_MM_DD:
return formatDate(date, 'YYYY/MM/DD')
case DATE_DISPLAY.DAY_MONTH_YEAR: {
return new Intl.DateTimeFormat(i18n.global.locale.value, {day: 'numeric', month: 'long', year: 'numeric'}).format(date)
}
case DATE_DISPLAY.WEEKDAY_DAY_MONTH_YEAR: {
return new Intl.DateTimeFormat(i18n.global.locale.value, {weekday: 'long', day: 'numeric', month: 'long', year: 'numeric'}).format(date)
}
case DATE_DISPLAY.RELATIVE:
default:
return formatDateSince(date)
}
}

View File

@ -103,6 +103,16 @@
"overdueTasksRemindersTime": "Overdue tasks reminder email time",
"filterUsedOnOverview": "Saved filter used on the overview page",
"minimumPriority": "Minimum visible task priority",
"dateDisplay": "Date display format",
"dateDisplayOptions": {
"relative": "Relative (e.g. 3 days ago)",
"mm-dd-yyyy": "MM-DD-YYYY",
"dd-mm-yyyy": "DD-MM-YYYY",
"yyyy-mm-dd": "YYYY-MM-DD",
"mm\/dd\/yyyy": "MM\/DD\/YYYY",
"dd\/mm\/yyyy": "DD\/MM\/YYYY",
"yyyy\/mm\/dd": "YYYY\/MM\/DD"
},
"externalUserNameChange": "Your name is managed by your login provider ({provider}). To change it, please update it there instead."
},
"totp": {

View File

@ -6,6 +6,7 @@ import type {BasicColorSchema} from '@vueuse/core'
import type {SupportedLocale} from '@/i18n'
import type {DefaultProjectViewKind} from '@/modelTypes/IProjectView'
import type {Priority} from '@/constants/priorities'
import type {DateDisplay} from '@/constants/dateDisplay'
export interface IFrontendSettings {
playSoundWhenDone: boolean
@ -15,6 +16,7 @@ export interface IFrontendSettings {
filterIdUsedOnOverview: IProject['id'] | null
defaultView?: DefaultProjectViewKind
minimumPriority: Priority
dateDisplay: DateDisplay
}
export interface IUserSettings extends IAbstract {

View File

@ -5,6 +5,7 @@ import {getBrowserLanguage} from '@/i18n'
import {PrefixMode} from '@/modules/parseTaskText'
import {DEFAULT_PROJECT_VIEW_SETTINGS} from '@/modelTypes/IProjectView'
import {PRIORITIES} from '@/constants/priorities'
import {DATE_DISPLAY} from '@/constants/dateDisplay'
export default class UserSettingsModel extends AbstractModel<IUserSettings> implements IUserSettings {
name = ''
@ -24,6 +25,7 @@ export default class UserSettingsModel extends AbstractModel<IUserSettings> impl
allowIconChanges: true,
defaultView: DEFAULT_PROJECT_VIEW_SETTINGS.FIRST,
minimumPriority: PRIORITIES.MEDIUM,
dateDisplay: DATE_DISPLAY.RELATIVE,
}
constructor(data: Partial<IUserSettings> = {}) {

View File

@ -22,6 +22,7 @@ import {useConfigStore} from '@/stores/config'
import UserSettingsModel from '@/models/userSettings'
import {MILLISECONDS_A_SECOND} from '@/constants/date'
import {PrefixMode} from '@/modules/parseTaskText'
import {DATE_DISPLAY} from '@/constants/dateDisplay'
import type {IProvider} from '@/types/IProvider'
function redirectToSpecifiedProvider() {
@ -131,6 +132,7 @@ export const useAuthStore = defineStore('auth', () => {
quickAddMagicMode: PrefixMode.Default,
colorSchema: 'auto',
allowIconChanges: true,
dateDisplay: DATE_DISPLAY.RELATIVE,
...newSettings.frontendSettings,
},
})

View File

@ -11,7 +11,7 @@
>
{{
$t('user.deletion.scheduled', {
date: formatDateShort(deletionScheduledAt),
date: formatDisplayDate(deletionScheduledAt),
dateSince: formatDateSince(deletionScheduledAt),
})
}}
@ -55,7 +55,7 @@ import ImportHint from '@/components/home/ImportHint.vue'
import {getHistory} from '@/modules/projectHistory'
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate'
import {formatDateSince, formatDisplayDate} from '@/helpers/time/formatDate'
import {useDaytimeSalutation} from '@/composables/useDaytimeSalutation'
import {useProjectStore} from '@/stores/projects'

View File

@ -2,7 +2,7 @@
import ApiTokenService from '@/services/apiToken'
import {computed, onMounted, ref} from 'vue'
import {useFlatpickrLanguage} from '@/helpers/useFlatpickrLanguage'
import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate'
import {formatDateSince, formatDisplayDate} from '@/helpers/time/formatDate'
import XButton from '@/components/input/Button.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import ApiTokenModel from '@/models/apiTokenModel'
@ -207,7 +207,7 @@ function toggleGroupPermissionsFromChild(group: string, checked: boolean) {
</template>
</td>
<td>
{{ formatDateShort(tk.expiresAt) }}
{{ formatDisplayDate(tk.expiresAt) }}
<p
v-if="tk.expiresAt < new Date()"
class="has-text-danger"
@ -215,7 +215,7 @@ function toggleGroupPermissionsFromChild(group: string, checked: boolean) {
{{ $t('user.settings.apiTokens.expired', {ago: formatDateSince(tk.expiresAt)}) }}
</p>
</td>
<td>{{ formatDateShort(tk.created) }}</td>
<td>{{ formatDisplayDate(tk.created) }}</td>
<td class="has-text-right">
<XButton
variant="secondary"

View File

@ -8,7 +8,7 @@
<p>
{{
$t('user.deletion.scheduled', {
date: formatDateShort(deletionScheduledAt),
date: formatDisplayDate(deletionScheduledAt),
dateSince: formatDateSince(deletionScheduledAt),
})
}}
@ -116,7 +116,7 @@ import {useI18n} from 'vue-i18n'
import AccountDeleteService from '@/services/accountDelete'
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate'
import {formatDateSince, formatDisplayDate} from '@/helpers/time/formatDate'
import {useTitle} from '@/composables/useTitle'
import {success} from '@/message'
import {useAuthStore} from '@/stores/auth'

View File

@ -228,6 +228,22 @@
</div>
</label>
</div>
<div class="field">
<label class="is-flex is-align-items-center">
<span>
{{ $t('user.settings.general.dateDisplay') }}
</span>
<div class="select ml-2">
<select v-model="settings.frontendSettings.dateDisplay">
<option
v-for="(label, value) in dateDisplaySettings"
:key="value"
:value="value"
>{{ label }}</option>
</select>
</div>
</label>
</div>
<div class="field">
<label class="is-flex is-align-items-center">
<span>
@ -269,6 +285,7 @@ import Multiselect from '@/components/input/Multiselect.vue'
import {SUPPORTED_LOCALES} from '@/i18n'
import {createRandomID} from '@/helpers/randomId'
import {AuthenticatedHTTPFactory} from '@/helpers/fetcher'
import {formatDisplayDateFormat} from '@/helpers/time/formatDate'
import {useTitle} from '@/composables/useTitle'
@ -278,6 +295,7 @@ import type {IUserSettings} from '@/modelTypes/IUserSettings'
import {isSavedFilter} from '@/services/savedFilter'
import {DEFAULT_PROJECT_VIEW_SETTINGS} from '@/modelTypes/IProjectView'
import {PRIORITIES} from '@/constants/priorities'
import {DATE_DISPLAY} from '@/constants/dateDisplay'
defineOptions({name: 'UserSettingsGeneral'})
@ -292,6 +310,18 @@ const colorSchemeSettings = computed(() => ({
dark: t('user.settings.appearance.colorScheme.dark'),
}))
const dateDisplaySettings = computed(() => ({
[DATE_DISPLAY.RELATIVE]: t('user.settings.general.dateDisplayOptions.relative'),
[DATE_DISPLAY.MM_DD_YYYY]: t('user.settings.general.dateDisplayOptions.mm-dd-yyyy'),
[DATE_DISPLAY.DD_MM_YYYY]: t('user.settings.general.dateDisplayOptions.dd-mm-yyyy'),
[DATE_DISPLAY.YYYY_MM_DD]: t('user.settings.general.dateDisplayOptions.yyyy-mm-dd'),
[DATE_DISPLAY.MM_SLASH_DD_YYYY]: t('user.settings.general.dateDisplayOptions.mm/dd/yyyy'),
[DATE_DISPLAY.DD_SLASH_MM_YYYY]: t('user.settings.general.dateDisplayOptions.dd/mm/yyyy'),
[DATE_DISPLAY.YYYY_SLASH_MM_DD]: t('user.settings.general.dateDisplayOptions.yyyy/mm/dd'),
[DATE_DISPLAY.DAY_MONTH_YEAR]: formatDisplayDateFormat(new Date(), DATE_DISPLAY.DAY_MONTH_YEAR),
[DATE_DISPLAY.WEEKDAY_DAY_MONTH_YEAR]: formatDisplayDateFormat(new Date(), DATE_DISPLAY.WEEKDAY_DAY_MONTH_YEAR),
}))
const authStore = useAuthStore()
const settings = ref<IUserSettings>({
@ -306,6 +336,7 @@ const settings = ref<IUserSettings>({
minimumPriority: authStore.settings.frontendSettings.minimumPriority ?? PRIORITIES.MEDIUM,
// Add fallback for old settings that don't have the logo change setting set
allowIconChanges: authStore.settings.frontendSettings.allowIconChanges ?? true,
dateDisplay: authStore.settings.frontendSettings.dateDisplay ?? DATE_DISPLAY.RELATIVE,
},
})