From a58c1eeab91524e2fcbffaa2e0b93a0a202a01b3 Mon Sep 17 00:00:00 2001
From: Alexis <35.alexis.pele@gmail.com>
Date: Sat, 8 Jun 2024 17:48:32 +0200
Subject: [PATCH 3/9] Added request cancel on create
This seems to not be always effective on really low connections, as the cancel request doesn't seem to be instantanneous.
---
assets/main.css | 53 ++++++++++++++----------
components/calendar/form/CreateEvent.vue | 22 ++++++++--
stores/EventStore.ts | 30 ++++++++++++--
3 files changed, 78 insertions(+), 27 deletions(-)
diff --git a/assets/main.css b/assets/main.css
index 71f25ec..219337f 100644
--- a/assets/main.css
+++ b/assets/main.css
@@ -5,64 +5,64 @@
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
-
+
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
-
+
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
-
+
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
-
+
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
-
+
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
-
+
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
-
+
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
-
+
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
-
+
--ring: 222.2 84% 4.9%;
-
+
--radius: 0.5rem;
}
-
+
:root.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
-
+
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
-
+
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
-
+
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
-
+
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
-
+
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
-
+
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
-
+
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
-
+
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
-
+
--ring: 212.7 26.8% 83.9%;
}
@@ -73,4 +73,15 @@
body {
@apply bg-background text-foreground;
}
-}
\ No newline at end of file
+}
+
+.fade-cancel-enter-active,
+.fade-cancel-leave-active {
+ transition: all .5s ease 1s;
+}
+
+.fade-cancel-enter-from,
+.fade-cancel-leave-to {
+ opacity: 0;
+ visibility: hidden;
+}
diff --git a/components/calendar/form/CreateEvent.vue b/components/calendar/form/CreateEvent.vue
index 32e5284..71c9483 100644
--- a/components/calendar/form/CreateEvent.vue
+++ b/components/calendar/form/CreateEvent.vue
@@ -4,7 +4,7 @@ import type { RPGDate } from '~/models/Date';
import { PhAlarm, PhCircleNotch, PhMapPinArea } from '@phosphor-icons/vue'
const { eventSkeleton } = storeToRefs(useCalendarEvents())
-const { resetSkeleton, submitSkeleton } = useCalendarEvents()
+const { resetSkeleton, submitSkeleton, cancelLatestRequest } = useCalendarEvents()
const popoverOpen = ref(false)
const isLoading = ref(false)
@@ -60,6 +60,14 @@ function handleClosing(e: Event) {
e.preventDefault()
}
}
+
+/**
+ * Click on the cancel button
+ */
+function handleCancel() {
+ cancelLatestRequest()
+ isLoading.value = false
+}
@@ -143,9 +151,17 @@ function handleClosing(e: Event) {
-
+
+
+
+ Annuler
+
+
+
-
+
+
+
Sauvegarder
diff --git a/stores/EventStore.ts b/stores/EventStore.ts
index 454bd24..47c9785 100644
--- a/stores/EventStore.ts
+++ b/stores/EventStore.ts
@@ -187,6 +187,8 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
* EVENT CREATION FUNCTIONS
*/
const lastActiveEvent = ref
()
+ let abortController: AbortController | null = null
+
/**
* Dummy event to hold creation data
*/
@@ -205,31 +207,52 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
* We assume it's been sanitized by the caller
*/
async function submitSkeleton() {
+ abortController = new AbortController()
+
try {
- const res = await $fetch('/api/calendars/events/create', { method: 'POST', body: { event : eventSkeleton.value, calendarId: calendarId.value }})
+ const res = await $fetch('/api/calendars/events/create', { method: 'POST', body: { event : eventSkeleton.value, calendarId: calendarId.value }, signal: abortController.signal })
+
baseEvents.value.push(res)
} catch (err) {
console.log(err)
+ } finally {
+ abortController = null
+ }
+ }
+
+ function cancelLatestRequest() {
+ if (abortController) {
+ abortController.abort()
}
}
async function updateEventFromSkeleton() {
+ abortController = new AbortController()
+
try {
- const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'PATCH', body: { event : eventSkeleton.value, calendarId: calendarId.value }})
+ const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'PATCH', body: { event : eventSkeleton.value, calendarId: calendarId.value }, signal: abortController.signal })
+
const eventIndex = baseEvents.value.findIndex(e => e.id === eventSkeleton.value.id)
baseEvents.value[eventIndex] = res
} catch (err) {
console.log(err)
+ } finally {
+ abortController = null
}
}
async function deleteEventFromSkeleton() {
+ abortController = new AbortController()
+
try {
- await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'DELETE' })
+ await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'DELETE', signal: abortController.signal })
+
const eventIndex = baseEvents.value.findIndex(e => e.id === eventSkeleton.value.id)
baseEvents.value.splice(eventIndex, 1)
} catch (err) {
console.log(err)
+ } finally {
+ abortController = null
}
}
@@ -239,6 +262,7 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
currentEvents,
getRelativeEventFromDate,
getRelativeEventFromEvent,
+ cancelLatestRequest,
eventSkeleton,
resetSkeleton,
submitSkeleton,
From a07afc8351d00bede5c04f05ac73de5fe9a66912 Mon Sep 17 00:00:00 2001
From: Alexis <35.alexis.pele@gmail.com>
Date: Sat, 8 Jun 2024 18:08:08 +0200
Subject: [PATCH 4/9] Prevented other popovers from opening when an operation
is underway
---
components/calendar/form/CreateEvent.vue | 11 ++++++--
components/calendar/state/monthly/DayTile.vue | 2 +-
stores/EventStore.ts | 26 ++++++++++++++-----
3 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/components/calendar/form/CreateEvent.vue b/components/calendar/form/CreateEvent.vue
index 71c9483..ac6cec8 100644
--- a/components/calendar/form/CreateEvent.vue
+++ b/components/calendar/form/CreateEvent.vue
@@ -3,7 +3,7 @@ import type { RPGDate } from '~/models/Date';
import { PhAlarm, PhCircleNotch, PhMapPinArea } from '@phosphor-icons/vue'
-const { eventSkeleton } = storeToRefs(useCalendarEvents())
+const { eventSkeleton, operationInProgress } = storeToRefs(useCalendarEvents())
const { resetSkeleton, submitSkeleton, cancelLatestRequest } = useCalendarEvents()
const popoverOpen = ref(false)
const isLoading = ref(false)
@@ -21,6 +21,14 @@ const props = defineProps<{
* Opens event creation's popover
*/
function openEventCreatePopover() {
+ console.log(operationInProgress.value)
+ if (operationInProgress.value) {
+ popoverOpen.value = false
+ return
+ }
+
+ console.log('open still what ?')
+
resetSkeleton()
popoverOpen.value = true
@@ -55,7 +63,6 @@ async function handleSubmit() {
* @param e The closing event (can be keydown or click)
*/
function handleClosing(e: Event) {
- console.log(e)
if (isLoading.value) {
e.preventDefault()
}
diff --git a/components/calendar/state/monthly/DayTile.vue b/components/calendar/state/monthly/DayTile.vue
index 0ae0b5d..bcd9b15 100644
--- a/components/calendar/state/monthly/DayTile.vue
+++ b/components/calendar/state/monthly/DayTile.vue
@@ -146,7 +146,7 @@ const eventsNotDisplayed: ComputedRef = computed(() => eventsFo
-
+
diff --git a/stores/EventStore.ts b/stores/EventStore.ts
index 47c9785..b3294e9 100644
--- a/stores/EventStore.ts
+++ b/stores/EventStore.ts
@@ -187,6 +187,10 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
* EVENT CREATION FUNCTIONS
*/
const lastActiveEvent = ref
()
+ const isCreatingEvent = ref(false)
+ const isUpdatingEvent = ref(false)
+ const isDeletingEvent = ref(false)
+ const operationInProgress = computed(() => isCreatingEvent.value || isUpdatingEvent.value || isDeletingEvent.value)
let abortController: AbortController | null = null
/**
@@ -208,6 +212,7 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
*/
async function submitSkeleton() {
abortController = new AbortController()
+ isCreatingEvent.value = true
try {
const res = await $fetch('/api/calendars/events/create', { method: 'POST', body: { event : eventSkeleton.value, calendarId: calendarId.value }, signal: abortController.signal })
@@ -217,17 +222,13 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
console.log(err)
} finally {
abortController = null
- }
- }
-
- function cancelLatestRequest() {
- if (abortController) {
- abortController.abort()
+ isCreatingEvent.value = false
}
}
async function updateEventFromSkeleton() {
abortController = new AbortController()
+ isUpdatingEvent.value = true
try {
const res = await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'PATCH', body: { event : eventSkeleton.value, calendarId: calendarId.value }, signal: abortController.signal })
@@ -238,11 +239,13 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
console.log(err)
} finally {
abortController = null
+ isUpdatingEvent.value = false
}
}
async function deleteEventFromSkeleton() {
abortController = new AbortController()
+ isDeletingEvent.value = true
try {
await $fetch(`/api/calendars/events/${eventSkeleton.value.id}`, { method: 'DELETE', signal: abortController.signal })
@@ -253,6 +256,13 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
console.log(err)
} finally {
abortController = null
+ isDeletingEvent.value = false
+ }
+ }
+
+ function cancelLatestRequest() {
+ if (abortController) {
+ abortController.abort()
}
}
@@ -263,6 +273,10 @@ export const useCalendarEvents = defineStore('calendar-events', () => {
getRelativeEventFromDate,
getRelativeEventFromEvent,
cancelLatestRequest,
+ isCreatingEvent,
+ isUpdatingEvent,
+ isDeletingEvent,
+ operationInProgress,
eventSkeleton,
resetSkeleton,
submitSkeleton,
From 721e26d8e4e45594e636ace473ae58ee9e60213a Mon Sep 17 00:00:00 2001
From: Alexis <35.alexis.pele@gmail.com>
Date: Sat, 8 Jun 2024 21:53:16 +0200
Subject: [PATCH 5/9] Added loading and cancelling to updating popover
---
assets/main.css | 14 ++++--
components/calendar/form/CreateEvent.vue | 11 +++--
components/calendar/form/UpdateEvent.vue | 62 +++++++++++++++++++-----
3 files changed, 67 insertions(+), 20 deletions(-)
diff --git a/assets/main.css b/assets/main.css
index 219337f..ad39aa5 100644
--- a/assets/main.css
+++ b/assets/main.css
@@ -75,13 +75,19 @@
}
}
-.fade-cancel-enter-active,
-.fade-cancel-leave-active {
+.fade-enter-active,
+.fade-leave-active {
+ transition: all .5s ease;
+}
+.fade-delay-enter-active,
+.fade-delay-leave-active {
transition: all .5s ease 1s;
}
-.fade-cancel-enter-from,
-.fade-cancel-leave-to {
+.fade-enter-from,
+.fade-leave-to,
+.fade-delay-enter-from,
+.fade-delay-leave-to {
opacity: 0;
visibility: hidden;
}
diff --git a/components/calendar/form/CreateEvent.vue b/components/calendar/form/CreateEvent.vue
index ac6cec8..524121f 100644
--- a/components/calendar/form/CreateEvent.vue
+++ b/components/calendar/form/CreateEvent.vue
@@ -21,14 +21,12 @@ const props = defineProps<{
* Opens event creation's popover
*/
function openEventCreatePopover() {
- console.log(operationInProgress.value)
+ // If another operation is in progress, whether it's another create popup or a modal, don't bother opening it
if (operationInProgress.value) {
popoverOpen.value = false
return
}
- console.log('open still what ?')
-
resetSkeleton()
popoverOpen.value = true
@@ -59,6 +57,7 @@ async function handleSubmit() {
}
/**
+ * Prevents the modal from closing if's still loading
*
* @param e The closing event (can be keydown or click)
*/
@@ -70,6 +69,8 @@ function handleClosing(e: Event) {
/**
* Click on the cancel button
+ *
+ * Must cancel the abortController in the store, and stop the loading
*/
function handleCancel() {
cancelLatestRequest()
@@ -159,14 +160,14 @@ function handleCancel() {