diff --git a/src/components/misc/flatpickr/Flatpickr.vue b/src/components/misc/flatpickr/Flatpickr.vue index 78f171d91..fded8fd65 100644 --- a/src/components/misc/flatpickr/Flatpickr.vue +++ b/src/components/misc/flatpickr/Flatpickr.vue @@ -1,10 +1,10 @@ @@ -20,39 +20,39 @@ type Options = flatpickr.Options.Options type DateOption = flatpickr.Options.DateOption function camelToKebab(string: string) { - return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() + return string.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() } function arrayify(obj: T) { - return obj instanceof Array + return obj instanceof Array ? obj : [obj] } function nullify(value: T) { - return (value && (value as unknown[]).length) + return (value && (value as unknown[]).length) ? value : null } // Events to emit, copied from flatpickr source const includedEvents = [ - 'onChange', - 'onClose', - 'onDestroy', - 'onMonthChange', - 'onOpen', - 'onYearChange', + 'onChange', + 'onClose', + 'onDestroy', + 'onMonthChange', + 'onOpen', + 'onYearChange', ] as HookKey[] // Let's not emit these events by default const excludedEvents = [ - 'onValueUpdate', - 'onDayCreate', - 'onParseConfig', - 'onReady', - 'onPreCalendarPosition', - 'onKeyDown', + 'onValueUpdate', + 'onDayCreate', + 'onParseConfig', + 'onReady', + 'onPreCalendarPosition', + 'onKeyDown', ] as HookKey[] // Keep a copy of all events for later use @@ -100,19 +100,19 @@ const attrs = useAttrs() const root = ref(null) const fp = ref(null) -const safeConfig = ref({ ...props.config }) +const safeConfig = ref({...props.config}) function prepareConfig() { // Don't mutate original object on parent component - const newConfig: Options = { ...props.config } + const newConfig: Options = {...props.config} props.events.forEach((hook) => { // Respect global callbacks registered via setDefault() method const globalCallbacks = flatpickr.defaultConfig[hook] || [] - + // Inject our own method along with user callback const localCallback: Hook = (...args) => emit(camelToKebab(hook), ...args) - + // Overwrite with merged array newConfig[hook] = arrayify(newConfig[hook] || []).concat( globalCallbacks, @@ -147,9 +147,9 @@ onMounted(() => { prepareConfig() /** - * Get the HTML node where flatpickr to be attached - * Bind on parent element if wrap is true - */ + * Get the HTML node where flatpickr to be attached + * Bind on parent element if wrap is true + */ const element = props.config.wrap ? root.value.parentNode : root.value @@ -179,7 +179,7 @@ watch(config, () => { fp.value.set(name, safeConfig.value[name]) } }) -}, {deep:true}) +}, {deep: true}) const fpInput = computed(() => { if (!fp.value) return @@ -198,8 +198,8 @@ watchEffect(() => fpInput.value?.addEventListener('blur', onBlur)) onBeforeUnmount(() => fpInput.value?.removeEventListener('blur', onBlur)) /** -* Watch for the disabled property and sets the value to the real input. -*/ + * Watch for the disabled property and sets the value to the real input. + */ watchEffect(() => { if (disabled.value) { fpInput.value?.setAttribute('disabled', '') diff --git a/src/views/user/settings/ApiTokens.vue b/src/views/user/settings/ApiTokens.vue index 4e35092c1..237341738 100644 --- a/src/views/user/settings/ApiTokens.vue +++ b/src/views/user/settings/ApiTokens.vue @@ -7,6 +7,10 @@ import BaseButton from '@/components/base/BaseButton.vue' import ApiTokenModel from '@/models/apiTokenModel' import Fancycheckbox from '@/components/input/fancycheckbox.vue' import {MILLISECONDS_A_DAY} from '@/constants/date' +import flatPickr from 'vue-flatpickr-component' +import 'flatpickr/dist/flatpickr.css' +import {useI18n} from 'vue-i18n' +import {useAuthStore} from '@/stores/auth' const service = new ApiTokenService() const tokens = ref([]) @@ -15,10 +19,27 @@ const showCreateForm = ref(false) const availableRoutes = ref(null) const newToken = ref(new ApiTokenModel()) const newTokenExpiry = ref(30) +const newTokenExpiryCustom = ref(new Date()) const newTokenPermissions = ref({}) const newTokenTitleValid = ref(true) const apiTokenTitle = ref() +const {t} = useI18n() +const authStore = useAuthStore() + +const now = new Date() +const flatPickerConfig = computed(() => ({ + altFormat: t('date.altFormatLong'), + altInput: true, + dateFormat: 'Y-m-d H:i', + enableTime: true, + time_24hr: true, + locale: { + firstDayOfWeek: authStore.settings.weekStart, + }, + minDate: now, +})) + onMounted(async () => { tokens.value = await service.getAll() availableRoutes.value = await service.getAvailableRoutes() @@ -44,11 +65,13 @@ async function createToken() { apiTokenTitle.value.focus() return } - + const expiry = Number(newTokenExpiry.value) if (!isNaN(expiry)) { // if it's a number, we assume it's the number of days in the future newToken.value.expiresAt = new Date((new Date()) + expiry * MILLISECONDS_A_DAY) + } else { + newToken.value.expiresAt = new Date(newTokenExpiryCustom.value) } newToken.value.permissions = {} @@ -65,6 +88,7 @@ async function createToken() { const token = await service.create(newToken.value) newToken.value = new ApiTokenModel() newTokenExpiry.value = 30 + newTokenExpiryCustom.value = new Date() resetPermissions() tokens.value.push(token) showCreateForm.value = false @@ -139,13 +163,21 @@ async function createToken() { -
- +
+
+ +
+