From dc4504e09130ed4fe468205f2064b52fc5f8065f Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Fri, 11 Oct 2019 18:41:29 +0200
Subject: [PATCH] Limit minimum endsOn datetime selector to current beginsOn,
 set correct date of first week and translate labels on datepicker

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/src/components/Event/DateTimePicker.vue | 21 ++++++++++++++++++++-
 js/src/i18n/en_US.json                     |  1 +
 js/src/i18n/fr_FR.json                     |  1 +
 js/src/utils/datetime.ts                   | 21 +++++++++++++++++++++
 js/src/views/Event/Edit.vue                | 11 ++++++++++-
 5 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 js/src/utils/datetime.ts

diff --git a/js/src/components/Event/DateTimePicker.vue b/js/src/components/Event/DateTimePicker.vue
index 20fefbe63..8fd28b1af 100644
--- a/js/src/components/Event/DateTimePicker.vue
+++ b/js/src/components/Event/DateTimePicker.vue
@@ -13,12 +13,23 @@
 </docs>
 <template>
     <b-field grouped horizontal :label="label">
-        <b-datepicker expanded v-model="date" :placeholder="$t('Click to select')" icon="calendar"></b-datepicker>
+        <b-datepicker
+                :day-names="localeShortWeekDayNamesProxy"
+                :month-names="localeMonthNamesProxy"
+                expanded
+                :first-day-of-week="parseInt($t('firstDayOfWeek'), 10)"
+                :min-date="minDate"
+                v-model="date"
+                :placeholder="$t('Click to select')"
+                icon="calendar"
+        />
         <b-input expanded type="time" required v-model="time" />
     </b-field>
 </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 {
   /**
@@ -37,9 +48,17 @@ export default class DateTimePicker extends Vue {
    */
   @Prop({ required: false, type: Number, default: 1 }) step!: number;
 
+    /**
+     * Earliest date available for selection
+     */
+  @Prop({ required: false, type: Date, default: null }) minDate!: Date;
+
   date: Date = this.value;
   time: string = '00:00';
 
+  localeShortWeekDayNamesProxy = localeShortWeekDayNames();
+  localeMonthNamesProxy = localeMonthNames();
+
   mounted() {
     this.convertTime();
   }
diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json
index 654f4114a..4ba78e570 100644
--- a/js/src/i18n/en_US.json
+++ b/js/src/i18n/en_US.json
@@ -265,6 +265,7 @@
 	"Your local administrator resumed it's policy:": "Your local administrator resumed it's policy:",
 	"a decentralised federation protocol": "a decentralised federation protocol",
 	"e.g. 10 Rue Jangot": "e.g. 10 Rue Jangot",
+	"firstDayOfWeek": "0",
 	"iCal Feed": "iCal Feed",
 	"interconnect with others like it": "interconnect with others like it",
 	"its source code is public": "its source code is public",
diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json
index eaeb4b52d..855144503 100644
--- a/js/src/i18n/fr_FR.json
+++ b/js/src/i18n/fr_FR.json
@@ -303,6 +303,7 @@
     "Your local administrator resumed it's policy:": "Votre administrateur local a résumé sa politique ainsi :",
     "a decentralised federation protocol": "un protocole de fédération décentralisée",
     "e.g. 10 Rue Jangot": "par exemple : 10 Rue Jangot",
+    "firstDayOfWeek": "1",
     "iCal Feed": "Flux iCal",
     "interconnect with others like it": "s’interconnecter simplement avec d’autres",
     "its source code is public": "son code source est public",
diff --git a/js/src/utils/datetime.ts b/js/src/utils/datetime.ts
new file mode 100644
index 000000000..d34727422
--- /dev/null
+++ b/js/src/utils/datetime.ts
@@ -0,0 +1,21 @@
+function localeMonthNames(): string[] {
+  const monthNames: string[] = [];
+  for (let i = 0; i < 12; i += 1) {
+    const d = new Date(2019, i, 1);
+    const month = d.toLocaleString('default', { month: 'long' });
+    monthNames.push(month);
+  }
+  return monthNames;
+}
+
+function localeShortWeekDayNames(): string[] {
+  const weekDayNames: string[] = [];
+  for (let i = 13; i < 20; i += 1) {
+    const d = new Date(2019, 9, i);
+    const weekDay = d.toLocaleString('default', { weekday: 'short' });
+    weekDayNames.push(weekDay);
+  }
+  return weekDayNames;
+}
+
+export { localeMonthNames, localeShortWeekDayNames };
diff --git a/js/src/views/Event/Edit.vue b/js/src/views/Event/Edit.vue
index d5996d4f3..40dbc7647 100644
--- a/js/src/views/Event/Edit.vue
+++ b/js/src/views/Event/Edit.vue
@@ -22,7 +22,7 @@
           <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.endsOn" :label="$t('Ends on…')" :step="15" />
+          <date-time-picker :min-date="minDateForEndsOn" v-model="event.endsOn" :label="$t('Ends on…')" :step="15" />
 
           <address-auto-complete v-model="event.physicalAddress" />
 
@@ -569,6 +569,15 @@ export default class EditEvent extends Vue {
       this.event.endsOn.setUTCHours(dateEndsOn.getUTCHours() + 1);
     }
   }
+
+  /**
+   * In event endsOn datepicker, we lock starting with the day before the beginsOn date
+   */
+  get minDateForEndsOn(): Date {
+    const minDate = new Date(this.event.beginsOn);
+    minDate.setDate(minDate.getDate() - 1);
+    return minDate;
+  }
 }
 </script>