Client - add dropdown to select timezone in user preferences
This commit is contained in:
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div id="tz-dropdown">
|
||||
<input
|
||||
class="tz-dropdown-input"
|
||||
id="timezone"
|
||||
name="timezone"
|
||||
:value="timezone"
|
||||
:disabled="disabled"
|
||||
required
|
||||
@keydown.esc="onUpdateTimezone(input)"
|
||||
@keydown.enter="onEnter"
|
||||
@input="openDropdown"
|
||||
/>
|
||||
<ul class="tz-dropdown-list" v-if="isOpen" ref="tzList">
|
||||
<li
|
||||
v-for="(tz, index) in timeZones.filter((t) => matchTimezone(t))"
|
||||
:key="tz"
|
||||
class="tz-dropdown-item"
|
||||
:class="{ focus: index === focusItemIndex }"
|
||||
@click="onUpdateTimezone(tz)"
|
||||
@mouseover="onMouseOver(index)"
|
||||
:autofocus="index === focusItemIndex"
|
||||
>
|
||||
{{ tz }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Ref, defineComponent, ref, watch } from 'vue'
|
||||
|
||||
import { timeZones } from '@/utils/timezone'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TimezoneDropdown',
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
input: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ['updateTimezone'],
|
||||
setup(props, { emit }) {
|
||||
const timezone: Ref<string> = ref(props.input)
|
||||
const isOpen: Ref<boolean> = ref(false)
|
||||
const tzList: Ref<HTMLInputElement | null> = ref(null)
|
||||
const focusItemIndex: Ref<number> = ref(0)
|
||||
|
||||
function matchTimezone(t: string): RegExpMatchArray | null {
|
||||
return t.toLowerCase().match(timezone.value.toLowerCase())
|
||||
}
|
||||
function onMouseOver(index: number) {
|
||||
focusItemIndex.value = index
|
||||
}
|
||||
function onUpdateTimezone(value: string) {
|
||||
timezone.value = value
|
||||
isOpen.value = false
|
||||
emit('updateTimezone', value)
|
||||
}
|
||||
function onEnter(event: Event & { target: HTMLInputElement }) {
|
||||
event.preventDefault()
|
||||
if (tzList.value?.firstElementChild?.innerHTML) {
|
||||
onUpdateTimezone(tzList.value?.firstElementChild?.innerHTML)
|
||||
}
|
||||
}
|
||||
function openDropdown(event: Event & { target: HTMLInputElement }) {
|
||||
event.preventDefault()
|
||||
isOpen.value = true
|
||||
timezone.value = event.target.value.trim()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.input,
|
||||
(value) => {
|
||||
timezone.value = value
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
focusItemIndex,
|
||||
isOpen,
|
||||
timezone,
|
||||
timeZones,
|
||||
tzList,
|
||||
matchTimezone,
|
||||
onEnter,
|
||||
onMouseOver,
|
||||
onUpdateTimezone,
|
||||
openDropdown,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/scss/base.scss';
|
||||
|
||||
#tz-dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.tz-dropdown-list {
|
||||
background-color: var(--input-bg-color);
|
||||
border-radius: $border-radius;
|
||||
border: solid 1px var(--input-border-color);
|
||||
padding: $default-padding * 0.5 0;
|
||||
position: absolute;
|
||||
overflow-y: auto;
|
||||
top: 20px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-height: 200px;
|
||||
width: inherit;
|
||||
}
|
||||
.tz-dropdown-item {
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
font-weight: normal;
|
||||
padding: $default-padding * 0.5;
|
||||
|
||||
&.focus {
|
||||
background-color: var(--dropdown-hover-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -15,12 +15,12 @@
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="form-items" for="timezone">
|
||||
<label class="form-items">
|
||||
{{ $t('user.PROFILE.TIMEZONE') }}
|
||||
<input
|
||||
id="timezone"
|
||||
v-model="userForm.timezone"
|
||||
<TimezoneDropdown
|
||||
:input="userForm.timezone"
|
||||
:disabled="loading"
|
||||
@updateTimezone="updateTZ"
|
||||
/>
|
||||
</label>
|
||||
<label class="form-items">
|
||||
@ -61,6 +61,7 @@
|
||||
onMounted,
|
||||
} from 'vue'
|
||||
|
||||
import TimezoneDropdown from '@/components/User/ProfileEdition/TimezoneDropdown.vue'
|
||||
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
|
||||
import { IUserProfile, IUserPreferencesPayload } from '@/types/user'
|
||||
import { useStore } from '@/use/useStore'
|
||||
@ -68,6 +69,9 @@
|
||||
|
||||
export default defineComponent({
|
||||
name: 'UserPreferencesEdition',
|
||||
components: {
|
||||
TimezoneDropdown,
|
||||
},
|
||||
props: {
|
||||
user: {
|
||||
type: Object as PropType<IUserProfile>,
|
||||
@ -115,6 +119,9 @@
|
||||
userForm
|
||||
)
|
||||
}
|
||||
function updateTZ(value: string) {
|
||||
userForm.timezone = value
|
||||
}
|
||||
|
||||
return {
|
||||
availableLanguages,
|
||||
@ -123,6 +130,7 @@
|
||||
userForm,
|
||||
weekStart,
|
||||
updateProfile,
|
||||
updateTZ,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
Reference in New Issue
Block a user