Feat/55 v2 (#225)

* chore: upgrade relevant libraries
* feat(skip): add skip styling to paginated items
* chore: upgrade relevant libraries
* Fix: issue with text colour (#214)
* fix: adjust text colour from context
* fix: issue with wrong proptype
* fix issue with vite migration (#217)
* hotfix: 1.8.2 issues vite migration
* fix: file import options
* feat(55): styling
* refactor: remove onhover option for entry block
* refactor: relocate logging provider
* refactor: convert to typescript
* feat(55): add event editor
* refactor: extract event actions
* fix: bad import
* feat(55): redesign components
* fix: issues with not awaiting async
* refactor: replace socket with subscription
* refactor: remove unused
* style: small tweaks
* refactor: extract event actions
* refactor: cleanup debug
* refactor: chakra imports
* fix: optimistic mutations
* refactor: handle promise rejections
* refactor: validation
* fix: rq optimistic mutations
* feat: add playback feedback to block
* refactor: no optimistic adding of events
* refactor: simplify cursor state
* styles: cleanup editor style
* refactor: cleanup duration update
* fix: revert package upgrade (issues with vitest)
* fix: prevent cyclic imports
* refactor: extract data fetcher
* refactor: typescript migration
* chore: update tests
This commit is contained in:
Carlos Valente
2022-10-19 21:30:25 +02:00
committed by GitHub
parent 13be6ea2bc
commit 0fea4064c3
157 changed files with 4072 additions and 3033 deletions
+288
View File
@@ -0,0 +1,288 @@
import { useCallback, useContext } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { EVENTS_TABLE, EVENTS_TABLE_KEY } from '../api/apiConstants';
import {
requestApplyDelay,
requestDelete,
requestDeleteAll,
requestPostEvent,
requestPutEvent,
requestReorderEvent,
} from '../api/eventsApi';
import { LoggingContext } from '../context/LoggingContext';
/**
* @description Set of utilities for events
*/
export const useEventAction = () => {
const queryClient = useQueryClient();
const { emitError } = useContext(LoggingContext);
/**
* @description Calls mutation to add new event
* @private
*/
const _addEventMutation = useMutation(requestPostEvent, {
// Mutation finished, failed or successful
// Fetch anyway, just to be sure
onSettled: () => {
queryClient.invalidateQueries(EVENTS_TABLE);
},
});
/**
* @description Adds new event to list
* @param {object} event - Event to be added
* @param {object} [options] - Event options
*/
const addEvent = useCallback(
async (event, options) => {
const newEvent = { ...event };
// ************* CHECK OPTIONS
// there is an option to pass an index of an array to use as start time
if (typeof options?.startIsLastEnd !== 'undefined') {
const events = queryClient.getQueryData(EVENTS_TABLE);
const previousEvent = events.find((event) => event.id === options.startIsLastEnd);
newEvent.timeStart = previousEvent.timeEnd || 0;
}
// hard coding duration value to be as expected for now
// this until timeOptions gets implemented
if (newEvent.type === 'event') {
newEvent.duration = Math.max(0, newEvent.timeEnd - newEvent.timeStart) || 0;
}
try {
await _addEventMutation.mutateAsync(newEvent);
} catch (error) {
emitError(`Error fetching data: ${error.message}`);
}
},
[_addEventMutation, emitError],
);
/**
* @description Calls mutation to update existing event
* @private
*/
const _updateEventMutation = useMutation(requestPutEvent, {
// we optimistically update here
onMutate: async (newEvent) => {
// cancel ongoing queries
await queryClient.cancelQueries([EVENTS_TABLE_KEY, newEvent.id]);
// Snapshot the previous value
const previousEvent = queryClient.getQueryData([EVENTS_TABLE_KEY, newEvent.id]);
// optimistically update object
queryClient.setQueryData([EVENTS_TABLE_KEY, newEvent.id], newEvent);
// Return a context with the previous and new events
return { previousEvent, newEvent };
},
// Mutation fails, rollback undoes optimist update
onError: (error, newEvent, context) => {
queryClient.setQueryData([EVENTS_TABLE_KEY, context.newEvent.id], context.previousEvent);
},
// Mutation finished, failed or successful
// Fetch anyway, just to be sure
onSettled: async (newEvent) => {
await queryClient.invalidateQueries([EVENTS_TABLE_KEY, newEvent.id]);
},
});
/**
* @description Updates existing event
* @param {object} event - Event to be added
*/
const updateEvent = useCallback(
async (event) => {
try {
await _updateEventMutation.mutateAsync(event);
} catch (error) {
emitError(`Error updating event: ${error.message}`);
}
},
[_updateEventMutation, emitError]
);
/**
* @description Calls mutation to delete an event
* @private
*/
const _deleteEventMutation = useMutation(requestDelete, {
// we optimistically update here
onMutate: async (eventId) => {
// cancel ongoing queries
await queryClient.cancelQueries([EVENTS_TABLE_KEY, eventId]);
// Snapshot the previous value
const previousEvents = queryClient.getQueryData(EVENTS_TABLE);
const filtered = [...previousEvents].filter((e) => e.id !== eventId);
// optimistically update object
queryClient.setQueryData(EVENTS_TABLE, filtered);
// Return a context with the previous and new events
return { previousEvents };
},
// Mutation fails, rollback undoes optimist update
onError: (error, eventId, context) => {
queryClient.setQueryData(EVENTS_TABLE, context.previousEvents);
},
// Mutation finished, failed or successful
// Fetch anyway, just to be sure
onSettled: () => {
queryClient.invalidateQueries(EVENTS_TABLE);
},
});
/**
* @description Deletes an event form the list
* @param {object} eventId - Event to be deleted
*/
const deleteEvent = useCallback(
async (eventId) => {
try {
await _deleteEventMutation.mutateAsync(eventId);
} catch (error) {
emitError(`Error deleting event: ${error.message}`);
}
},
[_deleteEventMutation, emitError],
);
/**
* @description Calls mutation to delete all events
* @private
*/
const _deleteAllEventsMutation = useMutation(requestDeleteAll, {
// we optimistically update here
onMutate: async () => {
// cancel ongoing queries
await queryClient.cancelQueries(EVENTS_TABLE, { exact: true });
// Snapshot the previous value
const previousEvents = queryClient.getQueryData(EVENTS_TABLE);
const clear = [];
// optimistically update object
queryClient.setQueryData(EVENTS_TABLE, clear);
// Return a context with the previous and new events
return { previousEvents };
},
// Mutation fails, rollback undos optimist update
onError: (error, eventId, context) => {
queryClient.setQueryData(EVENTS_TABLE, context.previousEvents);
},
// Mutation finished, failed or successful
// Fetch anyway, just to be sure
onSettled: () => {
queryClient.invalidateQueries(EVENTS_TABLE);
},
});
/**
* @description Deletes all events from list
*/
const deleteAllEvents = useCallback(async () => {
try {
await _deleteAllEventsMutation.mutateAsync();
} catch (error) {
emitError(`Error deleting events: ${error.message}`);
}
}, [_deleteAllEventsMutation, emitError]);
/**
* @description Calls mutation to apply a delay
* @private
*/
const _applyDelayMutation = useMutation(requestApplyDelay, {
// Mutation finished, failed or successful
onSettled: () => {
queryClient.invalidateQueries(EVENTS_TABLE);
},
});
/**
* @description Applies a given delay
* @param {object} delayEventId - Id of delay to be applied
*/
const applyDelay = useCallback(
async (delayEventId) => {
try {
await _applyDelayMutation.mutateAsync(delayEventId);
} catch (error) {
emitError(`Error applying delay: ${error.message}`);
}
},
[_applyDelayMutation, emitError],
);
/**
* @description Calls mutation to reorder an event
* @private
*/
const _reorderEventMutation = useMutation(requestReorderEvent, {
// we optimistically update here
onMutate: async (data) => {
// cancel ongoing queries
await queryClient.cancelQueries(EVENTS_TABLE, { exact: true });
// Snapshot the previous value
const previousEvents = queryClient.getQueryData(EVENTS_TABLE);
const e = [...previousEvents];
const [reorderedItem] = e.splice(data.from, 1);
e.splice(data.to, 0, reorderedItem);
// optimistically update object
queryClient.setQueryData(EVENTS_TABLE, e);
// Return a context with the previous and new events
return { previousEvents };
},
// Mutation fails, rollback undoes optimist update
onError: (error, eventId, context) => {
queryClient.setQueryData(EVENTS_TABLE, context.previousEvents);
},
// Mutation finished, failed or successful
// Fetch anyway, just to be sure
onSettled: () => {
queryClient.invalidateQueries(EVENTS_TABLE);
},
});
/**
* @description Reorders a given event
* @param {string} eventID - ID of event to reorder
* @param {number} from - Current index
* @param {number} to - New Index
*/
const reorderEvent = useCallback(
async (eventId, from, to) => {
try {
const reorderObject = {
index: eventId,
from: from,
to: to,
};
await _reorderEventMutation.mutateAsync(reorderObject);
} catch (error) {
emitError(`Error re-ordering event: ${error.message}`);
}
},
[_reorderEventMutation, emitError],
);
return { addEvent, updateEvent, deleteEvent, deleteAllEvents, applyDelay, reorderEvent };
};