Better handle datetime
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
cc701f8994
commit
d93561742a
|
@ -19,11 +19,18 @@
|
||||||
expanded
|
expanded
|
||||||
:first-day-of-week="parseInt($t('firstDayOfWeek'), 10)"
|
:first-day-of-week="parseInt($t('firstDayOfWeek'), 10)"
|
||||||
:min-date="minDate"
|
:min-date="minDate"
|
||||||
v-model="date"
|
v-model="dateWithoutTime"
|
||||||
:placeholder="$t('Click to select')"
|
:placeholder="$t('Click to select')"
|
||||||
icon="calendar"
|
icon="calendar"
|
||||||
/>
|
/>
|
||||||
<b-input expanded type="time" required v-model="time" />
|
<b-timepicker
|
||||||
|
placeholder="Type or select a time..."
|
||||||
|
icon="clock"
|
||||||
|
v-model="dateWithTime"
|
||||||
|
expanded
|
||||||
|
size="is-small"
|
||||||
|
inline>
|
||||||
|
</b-timepicker>
|
||||||
</b-field>
|
</b-field>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -53,40 +60,26 @@ export default class DateTimePicker extends Vue {
|
||||||
*/
|
*/
|
||||||
@Prop({ required: false, type: Date, default: null }) minDate!: Date;
|
@Prop({ required: false, type: Date, default: null }) minDate!: Date;
|
||||||
|
|
||||||
date: Date = this.value;
|
dateWithoutTime: Date = this.value;
|
||||||
time: string = '00:00';
|
dateWithTime: Date = this.dateWithoutTime;
|
||||||
|
|
||||||
localeShortWeekDayNamesProxy = localeShortWeekDayNames();
|
localeShortWeekDayNamesProxy = localeShortWeekDayNames();
|
||||||
localeMonthNamesProxy = localeMonthNames();
|
localeMonthNamesProxy = localeMonthNames();
|
||||||
|
|
||||||
mounted() {
|
@Watch('value')
|
||||||
this.convertTime();
|
updateValue() {
|
||||||
|
this.dateWithoutTime = this.value;
|
||||||
|
this.dateWithTime = this.dateWithoutTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
convertTime() {
|
@Watch('dateWithoutTime')
|
||||||
let minutes = this.date.getHours() * 60 + this.date.getMinutes();
|
updateDateWithoutTimeWatcher() {
|
||||||
minutes = Math.ceil(minutes / this.step) * this.step;
|
|
||||||
|
|
||||||
this.time = [Math.floor(minutes / 60), minutes % 60].map((v) => { return v < 10 ? `0${v}` : v; }).join(':');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Watch('time')
|
|
||||||
updateTime(time: string) {
|
|
||||||
const [hours, minutes] = time.split(':', 2);
|
|
||||||
this.date.setHours(parseInt(hours, 10));
|
|
||||||
this.date.setMinutes(parseInt(minutes, 10));
|
|
||||||
this.updateDateTime();
|
this.updateDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('date')
|
@Watch('dateWithTime')
|
||||||
updateDate() {
|
updateDateWithTimeWatcher() {
|
||||||
this.updateTime(this.time);
|
this.updateDateTime();
|
||||||
}
|
|
||||||
|
|
||||||
@Watch('value')
|
|
||||||
updateValue() {
|
|
||||||
this.date = this.value;
|
|
||||||
this.convertTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDateTime() {
|
updateDateTime() {
|
||||||
|
@ -95,7 +88,17 @@ export default class DateTimePicker extends Vue {
|
||||||
*
|
*
|
||||||
* @type {Date}
|
* @type {Date}
|
||||||
*/
|
*/
|
||||||
this.$emit('input', this.date);
|
this.dateWithoutTime.setHours(this.dateWithTime.getHours());
|
||||||
|
this.dateWithoutTime.setMinutes(this.dateWithTime.getMinutes());
|
||||||
|
this.$emit('input', this.dateWithoutTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.timepicker {
|
||||||
|
/deep/ .dropdown-content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -18,14 +18,31 @@
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<span v-if="!endsOn">{{ beginsOn | formatDateTimeString }}</span>
|
<span v-if="!endsOn">{{ beginsOn | formatDateTimeString(showStartTime) }}</span>
|
||||||
<span v-else-if="isSameDay()">
|
<span v-else-if="isSameDay() && showStartTime && showEndTime">
|
||||||
{{ $t('On {date} from {startTime} to {endTime}', {date: formatDate(beginsOn), startTime: formatTime(beginsOn), endTime: formatTime(endsOn)}) }}
|
{{ $t('On {date} from {startTime} to {endTime}', {date: formatDate(beginsOn), startTime: formatTime(beginsOn), endTime: formatTime(endsOn)}) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="endsOn">
|
<span v-else-if="isSameDay() && !showStartTime && showEndTime">
|
||||||
|
{{ $t('On {date} ending at {endTime}', {date: formatDate(beginsOn), endTime: formatTime(endsOn)}) }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="isSameDay() && showStartTime && !showEndTime">
|
||||||
|
{{ $t('On {date} starting at {startTime}', {date: formatDate(beginsOn), startTime: formatTime(beginsOn)}) }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="isSameDay()">
|
||||||
|
{{ $t('On {date}', {date: formatDate(beginsOn)}) }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="endsOn && showStartTime && showEndTime">
|
||||||
{{ $t('From the {startDate} at {startTime} to the {endDate} at {endTime}',
|
{{ $t('From the {startDate} at {startTime} to the {endDate} at {endTime}',
|
||||||
{startDate: formatDate(beginsOn), startTime: formatTime(beginsOn), endDate: formatDate(endsOn), endTime: formatTime(endsOn)}) }}
|
{startDate: formatDate(beginsOn), startTime: formatTime(beginsOn), endDate: formatDate(endsOn), endTime: formatTime(endsOn)}) }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else-if="endsOn && showStartTime">
|
||||||
|
{{ $t('From the {startDate} at {startTime} to the {endDate}',
|
||||||
|
{startDate: formatDate(beginsOn), startTime: formatTime(beginsOn), endDate: formatDate(endsOn)}) }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="endsOn">
|
||||||
|
{{ $t('From the {startDate} to the {endDate}',
|
||||||
|
{startDate: formatDate(beginsOn), endDate: formatDate(endsOn)}) }}
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
|
@ -34,6 +51,8 @@ import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
export default class EventFullDate extends Vue {
|
export default class EventFullDate extends Vue {
|
||||||
@Prop({ required: true }) beginsOn!: string;
|
@Prop({ required: true }) beginsOn!: string;
|
||||||
@Prop({ required: false }) endsOn!: string;
|
@Prop({ required: false }) endsOn!: string;
|
||||||
|
@Prop({ required: false, default: true }) showStartTime!: boolean;
|
||||||
|
@Prop({ required: false, default: true }) showEndTime!: boolean;
|
||||||
|
|
||||||
formatDate(value) {
|
formatDate(value) {
|
||||||
if (!this.$options.filters) return;
|
if (!this.$options.filters) return;
|
||||||
|
|
|
@ -10,8 +10,13 @@ function formatTimeString(value: string): string {
|
||||||
return parseDateTime(value).toLocaleTimeString(undefined, { hour: 'numeric', minute: 'numeric' });
|
return parseDateTime(value).toLocaleTimeString(undefined, { hour: 'numeric', minute: 'numeric' });
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDateTimeString(value: string): string {
|
function formatDateTimeString(value: string, showTime: boolean = true): string {
|
||||||
return parseDateTime(value).toLocaleTimeString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' });
|
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' };
|
||||||
|
if (showTime) {
|
||||||
|
options.hour = 'numeric';
|
||||||
|
options.minute = 'numeric';
|
||||||
|
}
|
||||||
|
return parseDateTime(value).toLocaleTimeString(undefined, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ const optionsQuery = `
|
||||||
maximumAttendeeCapacity,
|
maximumAttendeeCapacity,
|
||||||
remainingAttendeeCapacity,
|
remainingAttendeeCapacity,
|
||||||
showRemainingAttendeeCapacity,
|
showRemainingAttendeeCapacity,
|
||||||
|
showStartTime,
|
||||||
|
showEndTime,
|
||||||
offers {
|
offers {
|
||||||
price,
|
price,
|
||||||
priceCurrency,
|
priceCurrency,
|
||||||
|
|
|
@ -59,6 +59,8 @@
|
||||||
"Create": "Create",
|
"Create": "Create",
|
||||||
"Creator": "Creator",
|
"Creator": "Creator",
|
||||||
"Current identity has been changed to {identityName} in order to manage this event.": "Current identity has been changed to {identityName} in order to manage this event.",
|
"Current identity has been changed to {identityName} in order to manage this event.": "Current identity has been changed to {identityName} in order to manage this event.",
|
||||||
|
"Date and time settings": "Date and time settings",
|
||||||
|
"Date parameters": "Date parameters",
|
||||||
"Delete event": "Delete event",
|
"Delete event": "Delete event",
|
||||||
"Delete this identity": "Delete this identity",
|
"Delete this identity": "Delete this identity",
|
||||||
"Delete your identity": "Delete your identity",
|
"Delete your identity": "Delete your identity",
|
||||||
|
@ -88,6 +90,7 @@
|
||||||
"Event edition": "Event edition",
|
"Event edition": "Event edition",
|
||||||
"Event list": "Event list",
|
"Event list": "Event list",
|
||||||
"Event not found.": "Event not found.",
|
"Event not found.": "Event not found.",
|
||||||
|
"Event page settings": "Event page settings",
|
||||||
"Event to be confirmed": "Event to be confirmed",
|
"Event to be confirmed": "Event to be confirmed",
|
||||||
"Event {eventTitle} deleted": "Event {eventTitle} deleted",
|
"Event {eventTitle} deleted": "Event {eventTitle} deleted",
|
||||||
"Event {eventTitle} reported": "Event {eventTitle} reported",
|
"Event {eventTitle} reported": "Event {eventTitle} reported",
|
||||||
|
@ -103,6 +106,8 @@
|
||||||
"Forgot your password ?": "Forgot your password ?",
|
"Forgot your password ?": "Forgot your password ?",
|
||||||
"From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?": "From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?",
|
"From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?": "From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?",
|
||||||
"From the {startDate} at {startTime} to the {endDate} at {endTime}": "From the {startDate} at {startTime} to the {endDate} at {endTime}",
|
"From the {startDate} at {startTime} to the {endDate} at {endTime}": "From the {startDate} at {startTime} to the {endDate} at {endTime}",
|
||||||
|
"From the {startDate} at {startTime} to the {endDate}": "From the {startDate} at {startTime} to the {endDate}",
|
||||||
|
"From the {startDate} to the {endDate}": "From the {startDate} to the {endDate}",
|
||||||
"Gather ⋅ Organize ⋅ Mobilize": "Gather ⋅ Organize ⋅ Mobilize",
|
"Gather ⋅ Organize ⋅ Mobilize": "Gather ⋅ Organize ⋅ Mobilize",
|
||||||
"General information": "General information",
|
"General information": "General information",
|
||||||
"Going as {name}": "Going as {name}",
|
"Going as {name}": "Going as {name}",
|
||||||
|
@ -150,14 +155,19 @@
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"New password": "New password",
|
"New password": "New password",
|
||||||
"No address defined": "No address defined",
|
"No address defined": "No address defined",
|
||||||
|
"No end date": "No end date",
|
||||||
"No events found": "No events found",
|
"No events found": "No events found",
|
||||||
"No group found": "No group found",
|
"No group found": "No group found",
|
||||||
"No groups found": "No groups found",
|
"No groups found": "No groups found",
|
||||||
"No participants yet": "No participants yet",
|
"No participants yet": "No participants yet",
|
||||||
"No results for \"{queryText}\"": "No results for \"{queryText}\"",
|
"No results for \"{queryText}\"": "No results for \"{queryText}\"",
|
||||||
"Number of places": "Number of places",
|
"Number of places": "Number of places",
|
||||||
|
"OK": "OK",
|
||||||
"Old password": "Old password",
|
"Old password": "Old password",
|
||||||
|
"On {date} ending at {endTime}": "On {date} ending at {endTime}",
|
||||||
"On {date} from {startTime} to {endTime}": "On {date} from {startTime} to {endTime}",
|
"On {date} from {startTime} to {endTime}": "On {date} from {startTime} to {endTime}",
|
||||||
|
"On {date} starting at {startTime}": "On {date} starting at {startTime}",
|
||||||
|
"On {date}": "On {date}",
|
||||||
"One person is going": "No one is going | One person is going | {approved} persons are going",
|
"One person is going": "No one is going | One person is going | {approved} persons are going",
|
||||||
"Only accessible through link and search (private)": "Only accessible through link and search (private)",
|
"Only accessible through link and search (private)": "Only accessible through link and search (private)",
|
||||||
"Opened reports": "Opened reports",
|
"Opened reports": "Opened reports",
|
||||||
|
@ -222,6 +232,8 @@
|
||||||
"Share this event": "Share this event",
|
"Share this event": "Share this event",
|
||||||
"Show map": "Show map",
|
"Show map": "Show map",
|
||||||
"Show remaining number of places": "Show remaining number of places",
|
"Show remaining number of places": "Show remaining number of places",
|
||||||
|
"Show the time when the event begins": "Show the time when the event begins",
|
||||||
|
"Show the time when the event ends": "Show the time when the event ends",
|
||||||
"Sign up": "Sign up",
|
"Sign up": "Sign up",
|
||||||
"Software to the people": "Software to the people",
|
"Software to the people": "Software to the people",
|
||||||
"Starts on…": "Starts on…",
|
"Starts on…": "Starts on…",
|
||||||
|
|
|
@ -59,6 +59,8 @@
|
||||||
"Create": "Créer",
|
"Create": "Créer",
|
||||||
"Creator": "Créateur",
|
"Creator": "Créateur",
|
||||||
"Current identity has been changed to {identityName} in order to manage this event.": "L'identité actuelle a été changée à {identityName} pour pouvoir gérer cet événement.",
|
"Current identity has been changed to {identityName} in order to manage this event.": "L'identité actuelle a été changée à {identityName} pour pouvoir gérer cet événement.",
|
||||||
|
"Date and time settings": "Paramètres de date et d'heure",
|
||||||
|
"Date parameters": "Paramètres de date",
|
||||||
"Delete event": "Supprimer un événement",
|
"Delete event": "Supprimer un événement",
|
||||||
"Delete this identity": "Supprimer cette identité",
|
"Delete this identity": "Supprimer cette identité",
|
||||||
"Delete your identity": "Supprimer votre identité",
|
"Delete your identity": "Supprimer votre identité",
|
||||||
|
@ -88,6 +90,7 @@
|
||||||
"Event edition": "Édition d'événement",
|
"Event edition": "Édition d'événement",
|
||||||
"Event list": "Liste d'événements",
|
"Event list": "Liste d'événements",
|
||||||
"Event not found.": "Événement non trouvé.",
|
"Event not found.": "Événement non trouvé.",
|
||||||
|
"Event page settings": "Paramètres de la page de l'événement",
|
||||||
"Event to be confirmed": "Événement à confirmer",
|
"Event to be confirmed": "Événement à confirmer",
|
||||||
"Event {eventTitle} deleted": "Événement {eventTitle} supprimé",
|
"Event {eventTitle} deleted": "Événement {eventTitle} supprimé",
|
||||||
"Event {eventTitle} reported": "Événement {eventTitle} signalé",
|
"Event {eventTitle} reported": "Événement {eventTitle} signalé",
|
||||||
|
@ -103,6 +106,8 @@
|
||||||
"Forgot your password ?": "Mot de passe oublié ?",
|
"Forgot your password ?": "Mot de passe oublié ?",
|
||||||
"From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?": "De l’anniversaire entre ami·e·s à une marche pour le climat, aujourd’hui, les bonnes raisons de se rassembler sont <b>captées par les géants du web</b>. Comment s’organiser, comment cliquer sur « je participe » sans <b>livrer des données intimes</b> à Facebook ou<b> s’enfermer</b> dans MeetUp ?",
|
"From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?": "De l’anniversaire entre ami·e·s à une marche pour le climat, aujourd’hui, les bonnes raisons de se rassembler sont <b>captées par les géants du web</b>. Comment s’organiser, comment cliquer sur « je participe » sans <b>livrer des données intimes</b> à Facebook ou<b> s’enfermer</b> dans MeetUp ?",
|
||||||
"From the {startDate} at {startTime} to the {endDate} at {endTime}": "Du {startDate} à {startTime} au {endDate} à {endTime}",
|
"From the {startDate} at {startTime} to the {endDate} at {endTime}": "Du {startDate} à {startTime} au {endDate} à {endTime}",
|
||||||
|
"From the {startDate} at {startTime} to the {endDate}": "Du {startDate} à {startTime} jusqu'au {endDate}",
|
||||||
|
"From the {startDate} to the {endDate}": "Du {startDate} au {endDate}",
|
||||||
"Gather ⋅ Organize ⋅ Mobilize": "Rassembler ⋅ Organiser ⋅ Mobiliser",
|
"Gather ⋅ Organize ⋅ Mobilize": "Rassembler ⋅ Organiser ⋅ Mobiliser",
|
||||||
"General information": "Information générales",
|
"General information": "Information générales",
|
||||||
"Going as {name}": "En tant que {name}",
|
"Going as {name}": "En tant que {name}",
|
||||||
|
@ -150,14 +155,19 @@
|
||||||
"Name": "Nom",
|
"Name": "Nom",
|
||||||
"New password": "Nouveau mot de passe",
|
"New password": "Nouveau mot de passe",
|
||||||
"No address defined": "Aucune adresse définie",
|
"No address defined": "Aucune adresse définie",
|
||||||
|
"No end date": "Pas de date de fin",
|
||||||
"No events found": "Aucun événement trouvé",
|
"No events found": "Aucun événement trouvé",
|
||||||
"No group found": "Aucun groupe trouvé",
|
"No group found": "Aucun groupe trouvé",
|
||||||
"No groups found": "Aucun groupe trouvé",
|
"No groups found": "Aucun groupe trouvé",
|
||||||
"No participants yet": "Aucun⋅e participant⋅e pour le moment",
|
"No participants yet": "Aucun⋅e participant⋅e pour le moment",
|
||||||
"No results for \"{queryText}\"": "Pas de résultats pour « {queryText} »",
|
"No results for \"{queryText}\"": "Pas de résultats pour « {queryText} »",
|
||||||
"Number of places": "Nombre de places",
|
"Number of places": "Nombre de places",
|
||||||
|
"OK": "OK",
|
||||||
"Old password": "Ancien mot de passe",
|
"Old password": "Ancien mot de passe",
|
||||||
|
"On {date} ending at {endTime}": "Le {date}, se terminant à {endTime}",
|
||||||
"On {date} from {startTime} to {endTime}": "Le {date} de {startTime} à {endTime}",
|
"On {date} from {startTime} to {endTime}": "Le {date} de {startTime} à {endTime}",
|
||||||
|
"On {date} starting at {startTime}": "Le {date} à partir de {startTime}",
|
||||||
|
"On {date}": "Le {date}",
|
||||||
"One person is going": "Personne n'y va | Une personne y va | {approved} personnes y vont",
|
"One person is going": "Personne n'y va | Une personne y va | {approved} personnes y vont",
|
||||||
"Only accessible through link and search (private)": "Uniquement accessibles par lien et la recherche (privé)",
|
"Only accessible through link and search (private)": "Uniquement accessibles par lien et la recherche (privé)",
|
||||||
"Opened reports": "Signalements ouverts",
|
"Opened reports": "Signalements ouverts",
|
||||||
|
@ -222,6 +232,8 @@
|
||||||
"Share this event": "Partager l'événement",
|
"Share this event": "Partager l'événement",
|
||||||
"Show map": "Afficher la carte",
|
"Show map": "Afficher la carte",
|
||||||
"Show remaining number of places": "Afficher le nombre de places restantes",
|
"Show remaining number of places": "Afficher le nombre de places restantes",
|
||||||
|
"Show the time when the event begins": "Afficher l'heure de début de l'événement",
|
||||||
|
"Show the time when the event ends": "Afficher l'heure de fin de l'événement",
|
||||||
"Sign up": "S'enregistrer",
|
"Sign up": "S'enregistrer",
|
||||||
"Software to the people": "Software to the people",
|
"Software to the people": "Software to the people",
|
||||||
"Starts on…": "Débute le…",
|
"Starts on…": "Débute le…",
|
||||||
|
|
|
@ -147,6 +147,8 @@ export interface IEventOptions {
|
||||||
program: string;
|
program: string;
|
||||||
commentModeration: CommentModeration;
|
commentModeration: CommentModeration;
|
||||||
showParticipationPrice: boolean;
|
showParticipationPrice: boolean;
|
||||||
|
showStartTime: boolean;
|
||||||
|
showEndTime: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EventOptions implements IEventOptions {
|
export class EventOptions implements IEventOptions {
|
||||||
|
@ -159,6 +161,8 @@ export class EventOptions implements IEventOptions {
|
||||||
program = '';
|
program = '';
|
||||||
commentModeration = CommentModeration.ALLOW_ALL;
|
commentModeration = CommentModeration.ALLOW_ALL;
|
||||||
showParticipationPrice = false;
|
showParticipationPrice = false;
|
||||||
|
showStartTime = true;
|
||||||
|
showEndTime = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EventModel implements IEvent {
|
export class EventModel implements IEvent {
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
|
|
||||||
<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…')" :step="15"/>
|
<date-time-picker v-model="event.beginsOn" :label="$t('Starts on…')" />
|
||||||
<date-time-picker :min-date="minDateForEndsOn" v-model="event.endsOn" :label="$t('Ends on…')" :step="15" />
|
<date-time-picker :min-date="minDateForEndsOn" v-model="event.endsOn" :label="$t('Ends on…')" />
|
||||||
|
<!-- <b-switch v-model="endsOnNull">{{ $t('No end date') }}</b-switch>-->
|
||||||
|
<b-button type="is-text" @click="dateSettingsIsOpen = true">{{ $t('Date parameters')}}</b-button>
|
||||||
|
|
||||||
<address-auto-complete v-model="event.physicalAddress" />
|
<address-auto-complete v-model="event.physicalAddress" />
|
||||||
|
|
||||||
|
@ -166,6 +168,31 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<b-modal :active.sync="dateSettingsIsOpen" has-modal-card trap-focus>
|
||||||
|
<form action="">
|
||||||
|
<div class="modal-card" style="width: auto">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">{{ $t('Date and time settings') }}</p>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<b-field :label="$t('Event page settings')">
|
||||||
|
<b-switch v-model="event.options.showStartTime">
|
||||||
|
{{ $t('Show the time when the event begins') }}
|
||||||
|
</b-switch>
|
||||||
|
</b-field>
|
||||||
|
<b-field>
|
||||||
|
<b-switch v-model="event.options.showEndTime">
|
||||||
|
{{ $t('Show the time when the event ends') }}
|
||||||
|
</b-switch>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot">
|
||||||
|
<button class="button" type="button" @click="dateSettingsIsOpen = false">{{ $t('OK') }}</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</b-modal>
|
||||||
<span ref="bottomObserver"></span>
|
<span ref="bottomObserver"></span>
|
||||||
<nav role="navigation" aria-label="main navigation" class="navbar" :class="{'is-fixed-bottom': showFixedNavbar }">
|
<nav role="navigation" aria-label="main navigation" class="navbar" :class="{'is-fixed-bottom': showFixedNavbar }">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -302,6 +329,8 @@ export default class EditEvent extends Vue {
|
||||||
CommentModeration = CommentModeration;
|
CommentModeration = CommentModeration;
|
||||||
showFixedNavbar: boolean = true;
|
showFixedNavbar: boolean = true;
|
||||||
observer!: IntersectionObserver;
|
observer!: IntersectionObserver;
|
||||||
|
dateSettingsIsOpen: boolean = false;
|
||||||
|
endsOnNull: boolean = false;
|
||||||
|
|
||||||
// categories: string[] = Object.keys(Category);
|
// categories: string[] = Object.keys(Category);
|
||||||
|
|
||||||
|
@ -505,6 +534,10 @@ export default class EditEvent extends Vue {
|
||||||
delete this.event.physicalAddress['__typename'];
|
delete this.event.physicalAddress['__typename'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.endsOnNull) {
|
||||||
|
res.endsOn = null;
|
||||||
|
}
|
||||||
|
|
||||||
const pictureObj = buildFileVariable(this.pictureFile, 'picture');
|
const pictureObj = buildFileVariable(this.pictureFile, 'picture');
|
||||||
res = Object.assign({}, res, pictureObj);
|
res = Object.assign({}, res, pictureObj);
|
||||||
|
|
||||||
|
@ -527,6 +560,9 @@ export default class EditEvent extends Vue {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (result.data.event.endsOn === null) {
|
||||||
|
this.endsOnNull = true;
|
||||||
|
}
|
||||||
return new EventModel(result.data.event);
|
return new EventModel(result.data.event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,17 +624,17 @@ export default class EditEvent extends Vue {
|
||||||
|
|
||||||
get beginsOn() { return this.event.beginsOn; }
|
get beginsOn() { return this.event.beginsOn; }
|
||||||
|
|
||||||
@Watch('beginsOn')
|
@Watch('beginsOn', { deep: true })
|
||||||
onBeginsOnChanged(beginsOn) {
|
onBeginsOnChanged(beginsOn) {
|
||||||
if (!this.event.endsOn) return;
|
if (!this.event.endsOn) return;
|
||||||
const dateBeginsOn = new Date(beginsOn);
|
const dateBeginsOn = new Date(beginsOn);
|
||||||
const dateEndsOn = new Date(this.event.endsOn);
|
const dateEndsOn = new Date(this.event.endsOn);
|
||||||
if (dateEndsOn < dateBeginsOn) {
|
if (dateEndsOn < dateBeginsOn) {
|
||||||
this.event.endsOn = dateBeginsOn;
|
this.event.endsOn = dateBeginsOn;
|
||||||
this.event.endsOn.setUTCHours(dateEndsOn.getUTCHours());
|
this.event.endsOn.setHours(dateEndsOn.getHours());
|
||||||
}
|
}
|
||||||
if (dateEndsOn === dateBeginsOn) {
|
if (dateEndsOn === dateBeginsOn) {
|
||||||
this.event.endsOn.setUTCHours(dateEndsOn.getUTCHours() + 1);
|
this.event.endsOn.setHours(dateEndsOn.getHours() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ import {ParticipantRole} from "@/types/event.model";
|
||||||
<div class="date-and-add-to-calendar">
|
<div class="date-and-add-to-calendar">
|
||||||
<div class="date-and-privacy" v-if="event.beginsOn">
|
<div class="date-and-privacy" v-if="event.beginsOn">
|
||||||
<b-icon icon="calendar-clock" />
|
<b-icon icon="calendar-clock" />
|
||||||
<event-full-date :beginsOn="event.beginsOn" :endsOn="event.endsOn" />
|
<event-full-date :beginsOn="event.beginsOn" :show-start-time="event.options.showStartTime" :show-end-time="event.options.showEndTime" :endsOn="event.endsOn" />
|
||||||
</div>
|
</div>
|
||||||
<a class="add-to-calendar" @click="downloadIcsEvent()" v-if="!event.draft">
|
<a class="add-to-calendar" @click="downloadIcsEvent()" v-if="!event.draft">
|
||||||
<b-icon icon="calendar-plus" />
|
<b-icon icon="calendar-plus" />
|
||||||
|
|
|
@ -22,7 +22,9 @@ defmodule Mobilizon.Events.EventOptions do
|
||||||
comment_moderation: CommentModeration.t(),
|
comment_moderation: CommentModeration.t(),
|
||||||
show_participation_price: boolean,
|
show_participation_price: boolean,
|
||||||
offers: [EventOffer.t()],
|
offers: [EventOffer.t()],
|
||||||
participation_condition: [EventParticipationCondition.t()]
|
participation_condition: [EventParticipationCondition.t()],
|
||||||
|
show_start_time: boolean,
|
||||||
|
show_end_time: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@attrs [
|
@attrs [
|
||||||
|
@ -32,7 +34,9 @@ defmodule Mobilizon.Events.EventOptions do
|
||||||
:attendees,
|
:attendees,
|
||||||
:program,
|
:program,
|
||||||
:comment_moderation,
|
:comment_moderation,
|
||||||
:show_participation_price
|
:show_participation_price,
|
||||||
|
:show_start_time,
|
||||||
|
:show_end_time
|
||||||
]
|
]
|
||||||
|
|
||||||
@primary_key false
|
@primary_key false
|
||||||
|
@ -45,6 +49,8 @@ defmodule Mobilizon.Events.EventOptions do
|
||||||
field(:program, :string)
|
field(:program, :string)
|
||||||
field(:comment_moderation, CommentModeration)
|
field(:comment_moderation, CommentModeration)
|
||||||
field(:show_participation_price, :boolean)
|
field(:show_participation_price, :boolean)
|
||||||
|
field(:show_start_time, :boolean)
|
||||||
|
field(:show_end_time, :boolean)
|
||||||
|
|
||||||
embeds_many(:offers, EventOffer)
|
embeds_many(:offers, EventOffer)
|
||||||
embeds_many(:participation_condition, EventParticipationCondition)
|
embeds_many(:participation_condition, EventParticipationCondition)
|
||||||
|
|
|
@ -181,6 +181,9 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||||
field(:show_participation_price, :boolean,
|
field(:show_participation_price, :boolean,
|
||||||
description: "Whether or not to show the participation price"
|
description: "Whether or not to show the participation price"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
field(:show_start_time, :boolean, description: "Show event start time")
|
||||||
|
field(:show_end_time, :boolean, description: "Show event end time")
|
||||||
end
|
end
|
||||||
|
|
||||||
input_object :event_options_input do
|
input_object :event_options_input do
|
||||||
|
@ -214,6 +217,9 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||||
field(:show_participation_price, :boolean,
|
field(:show_participation_price, :boolean,
|
||||||
description: "Whether or not to show the participation price"
|
description: "Whether or not to show the participation price"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
field(:show_start_time, :boolean, description: "Show event start time")
|
||||||
|
field(:show_end_time, :boolean, description: "Show event end time")
|
||||||
end
|
end
|
||||||
|
|
||||||
object :event_queries do
|
object :event_queries do
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= if MapSet.member?(@changes, :ends_on) do %>
|
<%= if MapSet.member?(@changes, :ends_on) && !is_nil(@event.ends_on) do %>
|
||||||
<tr>
|
<tr>
|
||||||
<td bgcolor="#ffffff" align="left">
|
<td bgcolor="#ffffff" align="left">
|
||||||
<%= gettext "Ending of event" %>
|
<%= gettext "Ending of event" %>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<%= gettext "New date and time for start of event: %{begins_on}", begins_on: datetime_to_string(@event.begins_on, @locale) %>
|
<%= gettext "New date and time for start of event: %{begins_on}", begins_on: datetime_to_string(@event.begins_on, @locale) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if MapSet.member?(@changes, :ends_on) do %>
|
<%= if MapSet.member?(@changes, :ends_on) && !is_nil(@event.ends_on) do %>
|
||||||
<%= gettext "New date and time for ending of event: %{ends_on}", ends_on: datetime_to_string(@event.ends_on, @locale) %>
|
<%= gettext "New date and time for ending of event: %{ends_on}", ends_on: datetime_to_string(@event.ends_on, @locale) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ defmodule Mobilizon.Service.ActivityPub.Converter.Event do
|
||||||
|> Enum.map(&Utils.camelize/1)
|
|> Enum.map(&Utils.camelize/1)
|
||||||
|
|
||||||
Enum.reduce(object, %{}, fn {key, value}, acc ->
|
Enum.reduce(object, %{}, fn {key, value}, acc ->
|
||||||
(value && key in keys && Map.put(acc, Utils.underscore(key), value)) ||
|
(!is_nil(value) && key in keys && Map.put(acc, Utils.underscore(key), value)) ||
|
||||||
acc
|
acc
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -346,7 +346,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||||
options = Events.EventOptions |> struct(metadata.options) |> Map.from_struct()
|
options = Events.EventOptions |> struct(metadata.options) |> Map.from_struct()
|
||||||
|
|
||||||
Enum.reduce(options, res, fn {key, value}, acc ->
|
Enum.reduce(options, res, fn {key, value}, acc ->
|
||||||
(value && Map.put(acc, camelize(key), value)) ||
|
(!is_nil(value) && Map.put(acc, camelize(key), value)) ||
|
||||||
acc
|
acc
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# source: http://localhost:4000/api
|
# source: http://localhost:4000/api
|
||||||
# timestamp: Mon Oct 14 2019 10:27:57 GMT+0200 (Central European Summer Time)
|
# timestamp: Mon Oct 14 2019 19:26:36 GMT+0200 (Central European Summer Time)
|
||||||
|
|
||||||
schema {
|
schema {
|
||||||
query: RootQueryType
|
query: RootQueryType
|
||||||
|
@ -400,11 +400,17 @@ type EventOptions {
|
||||||
"""The number of remaining seats for this event"""
|
"""The number of remaining seats for this event"""
|
||||||
remainingAttendeeCapacity: Int
|
remainingAttendeeCapacity: Int
|
||||||
|
|
||||||
|
"""Show event end time"""
|
||||||
|
showEndTime: Boolean
|
||||||
|
|
||||||
"""Whether or not to show the participation price"""
|
"""Whether or not to show the participation price"""
|
||||||
showParticipationPrice: Boolean
|
showParticipationPrice: Boolean
|
||||||
|
|
||||||
"""Whether or not to show the number of remaining seats for this event"""
|
"""Whether or not to show the number of remaining seats for this event"""
|
||||||
showRemainingAttendeeCapacity: Boolean
|
showRemainingAttendeeCapacity: Boolean
|
||||||
|
|
||||||
|
"""Show event start time"""
|
||||||
|
showStartTime: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
input EventOptionsInput {
|
input EventOptionsInput {
|
||||||
|
@ -429,11 +435,17 @@ input EventOptionsInput {
|
||||||
"""The number of remaining seats for this event"""
|
"""The number of remaining seats for this event"""
|
||||||
remainingAttendeeCapacity: Int
|
remainingAttendeeCapacity: Int
|
||||||
|
|
||||||
|
"""Show event end time"""
|
||||||
|
showEndTime: Boolean
|
||||||
|
|
||||||
"""Whether or not to show the participation price"""
|
"""Whether or not to show the participation price"""
|
||||||
showParticipationPrice: Boolean
|
showParticipationPrice: Boolean
|
||||||
|
|
||||||
"""Whether or not to show the number of remaining seats for this event"""
|
"""Whether or not to show the number of remaining seats for this event"""
|
||||||
showRemainingAttendeeCapacity: Boolean
|
showRemainingAttendeeCapacity: Boolean
|
||||||
|
|
||||||
|
"""Show event start time"""
|
||||||
|
showStartTime: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventParticipationCondition {
|
type EventParticipationCondition {
|
||||||
|
|
|
@ -229,7 +229,8 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do
|
||||||
category: "super_category",
|
category: "super_category",
|
||||||
options: {
|
options: {
|
||||||
maximumAttendeeCapacity: 30,
|
maximumAttendeeCapacity: 30,
|
||||||
showRemainingAttendeeCapacity: true
|
showRemainingAttendeeCapacity: true,
|
||||||
|
showEndTime: false
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
title,
|
title,
|
||||||
|
@ -246,7 +247,8 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do
|
||||||
category,
|
category,
|
||||||
options {
|
options {
|
||||||
maximumAttendeeCapacity,
|
maximumAttendeeCapacity,
|
||||||
showRemainingAttendeeCapacity
|
showRemainingAttendeeCapacity,
|
||||||
|
showEndTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,6 +275,7 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do
|
||||||
assert event["category"] == "super_category"
|
assert event["category"] == "super_category"
|
||||||
assert event["options"]["maximumAttendeeCapacity"] == 30
|
assert event["options"]["maximumAttendeeCapacity"] == 30
|
||||||
assert event["options"]["showRemainingAttendeeCapacity"] == true
|
assert event["options"]["showRemainingAttendeeCapacity"] == true
|
||||||
|
assert event["options"]["showEndTime"] == false
|
||||||
end
|
end
|
||||||
|
|
||||||
test "create_event/3 creates an event with tags", %{conn: conn, actor: actor, user: user} do
|
test "create_event/3 creates an event with tags", %{conn: conn, actor: actor, user: user} do
|
||||||
|
|
Loading…
Reference in a new issue