Use direct datetime picker from Buefy
Closes #494 Closes #459 Closes #207 Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
118aabf544
commit
736020392b
@ -1,147 +0,0 @@
|
|||||||
<docs>
|
|
||||||
### Datetime Picker
|
|
||||||
|
|
||||||
> We're wrapping the Buefy datepicker & an input
|
|
||||||
|
|
||||||
### Defaults
|
|
||||||
- step: 10
|
|
||||||
|
|
||||||
### Example
|
|
||||||
```vue
|
|
||||||
<DateTimePicker :value="new Date()" />
|
|
||||||
```
|
|
||||||
</docs>
|
|
||||||
<template>
|
|
||||||
<div class="field is-horizontal">
|
|
||||||
<div class="field-label is-normal">
|
|
||||||
<label class="label">{{ label }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="field-body">
|
|
||||||
<div class="field is-narrow is-grouped calendar-picker">
|
|
||||||
<b-datepicker
|
|
||||||
:day-names="localeShortWeekDayNamesProxy"
|
|
||||||
:month-names="localeMonthNamesProxy"
|
|
||||||
:first-day-of-week="parseInt($t('firstDayOfWeek'), 10)"
|
|
||||||
:min-date="minDatetime"
|
|
||||||
:max-date="maxDatetime"
|
|
||||||
v-model="dateWithTime"
|
|
||||||
:placeholder="$t('Click to select')"
|
|
||||||
:years-range="[-2, 10]"
|
|
||||||
icon="calendar"
|
|
||||||
class="is-narrow"
|
|
||||||
/>
|
|
||||||
<b-timepicker
|
|
||||||
placeholder="Type or select a time..."
|
|
||||||
icon="clock"
|
|
||||||
v-model="dateWithTime"
|
|
||||||
:min-time="minTime"
|
|
||||||
:max-time="maxTime"
|
|
||||||
size="is-small"
|
|
||||||
inline
|
|
||||||
>
|
|
||||||
</b-timepicker>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts">
|
|
||||||
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
|
|
||||||
import { localeMonthNames, localeShortWeekDayNames } from "@/utils/datetime";
|
|
||||||
|
|
||||||
@Component
|
|
||||||
export default class DateTimePicker extends Vue {
|
|
||||||
/**
|
|
||||||
* @model
|
|
||||||
* The DateTime value
|
|
||||||
*/
|
|
||||||
@Prop({ required: true, type: Date, default: () => new Date() }) value!: Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* What's shown besides the picker
|
|
||||||
*/
|
|
||||||
@Prop({ required: false, type: String, default: "Datetime" }) label!: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The step for the time input
|
|
||||||
*/
|
|
||||||
@Prop({ required: false, type: Number, default: 1 }) step!: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Earliest date available for selection
|
|
||||||
*/
|
|
||||||
@Prop({ required: false, type: Date, default: null }) minDatetime!: Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Latest date available for selection
|
|
||||||
*/
|
|
||||||
@Prop({ required: false, type: Date, default: null }) maxDatetime!: Date;
|
|
||||||
|
|
||||||
dateWithTime: Date = this.value;
|
|
||||||
|
|
||||||
localeShortWeekDayNamesProxy = localeShortWeekDayNames();
|
|
||||||
|
|
||||||
localeMonthNamesProxy = localeMonthNames();
|
|
||||||
|
|
||||||
@Watch("value")
|
|
||||||
updateValue(): void {
|
|
||||||
this.dateWithTime = this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Watch("dateWithTime")
|
|
||||||
updateDateWithTimeWatcher(): void {
|
|
||||||
this.updateDateTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDateTime(): void {
|
|
||||||
/**
|
|
||||||
* Returns the updated date
|
|
||||||
*
|
|
||||||
* @type {Date}
|
|
||||||
*/
|
|
||||||
this.$emit("input", this.dateWithTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
get minTime(): Date | null {
|
|
||||||
if (
|
|
||||||
this.minDatetime &&
|
|
||||||
this.datesAreOnSameDay(this.dateWithTime, this.minDatetime)
|
|
||||||
) {
|
|
||||||
return this.minDatetime;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get maxTime(): Date | null {
|
|
||||||
if (
|
|
||||||
this.maxDatetime &&
|
|
||||||
this.datesAreOnSameDay(this.dateWithTime, this.maxDatetime)
|
|
||||||
) {
|
|
||||||
return this.maxDatetime;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
|
||||||
private datesAreOnSameDay(first: Date, second: Date): boolean {
|
|
||||||
return (
|
|
||||||
first.getFullYear() === second.getFullYear() &&
|
|
||||||
first.getMonth() === second.getMonth() &&
|
|
||||||
first.getDate() === second.getDate()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.timepicker {
|
|
||||||
::v-deep .dropdown-content {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-picker {
|
|
||||||
::v-deep .dropdown-menu {
|
|
||||||
z-index: 200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -31,12 +31,31 @@
|
|||||||
|
|
||||||
<tag-input v-model="event.tags" :data="tags" path="title" />
|
<tag-input v-model="event.tags" :data="tags" path="title" />
|
||||||
|
|
||||||
<date-time-picker v-model="event.beginsOn" :label="$t('Starts on…')" />
|
<b-field horizontal :label="$t('Starts on…')" class="begins-on-field">
|
||||||
<date-time-picker
|
<b-datetimepicker
|
||||||
:min-datetime="event.beginsOn"
|
:placeholder="$t('Type or select a date…')"
|
||||||
|
icon="calendar-today"
|
||||||
|
:locale="$i18n.locale"
|
||||||
|
v-model="event.beginsOn"
|
||||||
|
horizontal-time-picker
|
||||||
|
editable
|
||||||
|
>
|
||||||
|
</b-datetimepicker>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field horizontal :label="$t('Ends on…')">
|
||||||
|
<b-datetimepicker
|
||||||
|
:placeholder="$t('Type or select a date…')"
|
||||||
|
icon="calendar-today"
|
||||||
|
:locale="$i18n.locale"
|
||||||
v-model="event.endsOn"
|
v-model="event.endsOn"
|
||||||
:label="$t('Ends on…')"
|
horizontal-time-picker
|
||||||
/>
|
:min-datetime="event.beginsOn"
|
||||||
|
editable
|
||||||
|
>
|
||||||
|
</b-datetimepicker>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
<!-- <b-switch v-model="endsOnNull">{{ $t('No end date') }}</b-switch>-->
|
<!-- <b-switch v-model="endsOnNull">{{ $t('No end date') }}</b-switch>-->
|
||||||
<b-button type="is-text" @click="dateSettingsIsOpen = true">
|
<b-button type="is-text" @click="dateSettingsIsOpen = true">
|
||||||
{{ $t("Date parameters") }}
|
{{ $t("Date parameters") }}
|
||||||
@ -367,6 +386,10 @@ section {
|
|||||||
padding: 2rem 1.5rem;
|
padding: 2rem 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.begins-on-field {
|
||||||
|
margin-top: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
nav.navbar {
|
nav.navbar {
|
||||||
min-height: 2rem !important;
|
min-height: 2rem !important;
|
||||||
background: lighten($secondary, 10%);
|
background: lighten($secondary, 10%);
|
||||||
@ -394,7 +417,6 @@ import { Component, Prop, Vue, Watch } from "vue-property-decorator";
|
|||||||
import { RefetchQueryDescription } from "apollo-client/core/watchQueryOptions";
|
import { RefetchQueryDescription } from "apollo-client/core/watchQueryOptions";
|
||||||
import PictureUpload from "@/components/PictureUpload.vue";
|
import PictureUpload from "@/components/PictureUpload.vue";
|
||||||
import EditorComponent from "@/components/Editor.vue";
|
import EditorComponent from "@/components/Editor.vue";
|
||||||
import DateTimePicker from "@/components/Event/DateTimePicker.vue";
|
|
||||||
import TagInput from "@/components/Event/TagInput.vue";
|
import TagInput from "@/components/Event/TagInput.vue";
|
||||||
import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue";
|
import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue";
|
||||||
import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
|
import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
|
||||||
@ -443,7 +465,6 @@ const DEFAULT_LIMIT_NUMBER_OF_PLACES = 10;
|
|||||||
IdentityPickerWrapper,
|
IdentityPickerWrapper,
|
||||||
FullAddressAutoComplete,
|
FullAddressAutoComplete,
|
||||||
TagInput,
|
TagInput,
|
||||||
DateTimePicker,
|
|
||||||
PictureUpload,
|
PictureUpload,
|
||||||
Editor: EditorComponent,
|
Editor: EditorComponent,
|
||||||
},
|
},
|
||||||
@ -532,14 +553,16 @@ export default class EditEvent extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeEvent() {
|
private initializeEvent() {
|
||||||
// TODO : Check me
|
const roundUpTo15Minutes = (time: Date) => {
|
||||||
// const roundUpTo = (roundTo) => (x: number) => new Date(Math.ceil(x / roundTo) * roundTo);
|
time.setMilliseconds(Math.round(time.getMilliseconds() / 1000) * 1000);
|
||||||
// const roundUpTo15Minutes = roundUpTo(1000 * 60 * 15);
|
time.setSeconds(Math.round(time.getSeconds() / 60) * 60);
|
||||||
|
time.setMinutes(Math.round(time.getMinutes() / 15) * 15);
|
||||||
|
return time;
|
||||||
|
};
|
||||||
|
|
||||||
|
const now = roundUpTo15Minutes(new Date());
|
||||||
|
const end = new Date(now.valueOf());
|
||||||
|
|
||||||
// const now = roundUpTo15Minutes(new Date());
|
|
||||||
// const end = roundUpTo15Minutes(new Date());
|
|
||||||
const now = new Date();
|
|
||||||
const end = new Date();
|
|
||||||
end.setUTCHours(now.getUTCHours() + 3);
|
end.setUTCHours(now.getUTCHours() + 3);
|
||||||
|
|
||||||
this.event.beginsOn = now;
|
this.event.beginsOn = now;
|
||||||
|
Loading…
Reference in New Issue
Block a user