mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
add feature add and delete range
This commit is contained in:
parent
75b2f6419e
commit
3ea630748a
@ -1,5 +1,5 @@
|
||||
import {EventInput} from '@fullcalendar/vue3';
|
||||
import {DateTime, User} from 'ChillMainAssets/types';
|
||||
import {DateTime, User, UserAssociatedInterface} from 'ChillMainAssets/types';
|
||||
|
||||
export interface CalendarRange {
|
||||
id: number;
|
||||
@ -12,6 +12,12 @@ export interface CalendarRange {
|
||||
updatedBy: User;
|
||||
}
|
||||
|
||||
export interface CalendarRangeEdit {
|
||||
user: UserAssociatedInterface,
|
||||
startDate: DateTime,
|
||||
endDate: DateTime
|
||||
}
|
||||
|
||||
export interface Calendar {
|
||||
id: number;
|
||||
}
|
||||
@ -23,4 +29,11 @@ export interface CalendarRemote {
|
||||
title: string
|
||||
}
|
||||
|
||||
export type EventInputCalendarRange = EventInput & {
|
||||
id: string,
|
||||
userId: number,
|
||||
calendarRangeId: number,
|
||||
is: "range"
|
||||
};
|
||||
|
||||
export {};
|
||||
|
@ -2,6 +2,7 @@ import {COLORS} from '../const';
|
||||
import {ISOToDatetime} from 'ChillMainAssets/chill/js/date';
|
||||
import {DateTime, User} from 'ChillMainAssets/types';
|
||||
import {CalendarRange, CalendarRemote} from 'ChillCalendarAssets/types';
|
||||
import type {EventInputCalendarRange} from 'ChillCalendarAssets/types';
|
||||
import {EventInput} from '@fullcalendar/vue3';
|
||||
|
||||
export interface UserData {
|
||||
@ -63,7 +64,7 @@ export const createUserData = (user: User, colorIndex: number): UserData => {
|
||||
}
|
||||
|
||||
// TODO move this function to a more global namespace, as it is in use in MyCalendarRange app
|
||||
export const calendarRangeToFullCalendarEvent = (entity: CalendarRange): EventInput & {id: string} => {
|
||||
export const calendarRangeToFullCalendarEvent = (entity: CalendarRange): EventInputCalendarRange => {
|
||||
return {
|
||||
id: `range_${entity.id}`,
|
||||
title: "(" + entity.user.text + ")",
|
||||
|
@ -48,7 +48,7 @@ import frLocale from '@fullcalendar/core/locales/fr';
|
||||
import FullCalendar from '@fullcalendar/vue3';
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||
import {EventApi} from "@fullcalendar/core";
|
||||
import {EventApi, DateSelectArg} from "@fullcalendar/core";
|
||||
|
||||
const store = useStore(key);
|
||||
|
||||
@ -64,7 +64,10 @@ const baseOptions = ref<CalendarOptions>({
|
||||
initialView: 'timeGridWeek',
|
||||
initialDate: new Date(),
|
||||
selectable: true,
|
||||
// when the dates are changes in the fullcalendar view OR when new events are added
|
||||
datesSet: onDatesSet,
|
||||
// when a date is selected
|
||||
select: onDateSelect,
|
||||
selectMirror: false,
|
||||
editable: true,
|
||||
slotMinTime: "08:00:00",
|
||||
@ -121,15 +124,25 @@ const calendarOptions = computed((): CalendarOptions => {
|
||||
/**
|
||||
* launched when the calendar range date change
|
||||
*/
|
||||
function onDatesSet(event: DatesSetArg) {
|
||||
function onDatesSet(event: DatesSetArg): void {
|
||||
store.dispatch('fullCalendar/setCurrentDatesView', {start: event.start, end: event.end});
|
||||
}
|
||||
|
||||
function onDateSelect(event: DateSelectArg): void {
|
||||
store.dispatch('calendarRanges/createRange', {start: event.start, end: event.end});
|
||||
}
|
||||
|
||||
/**
|
||||
* When a calendar range is deleted
|
||||
*/
|
||||
function onClickDelete(event: EventApi) {
|
||||
function onClickDelete(event: EventApi): void {
|
||||
console.log('onClickDelete', event);
|
||||
|
||||
if (event.extendedProps.is !== 'range') {
|
||||
return;
|
||||
}
|
||||
|
||||
store.dispatch('calendarRanges/deleteRange', event.extendedProps.calendarRangeId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,6 +24,7 @@ export interface State {
|
||||
calendarRanges: CalendarRangesState,
|
||||
calendarRemotes: CalendarRemotesState,
|
||||
fullCalendar: FullCalendarState,
|
||||
me: MeState,
|
||||
}
|
||||
|
||||
export const key: InjectionKey<Store<State>> = Symbol();
|
||||
|
@ -1,12 +1,16 @@
|
||||
import {State} from './../index';
|
||||
import {ActionContext, Module} from 'vuex';
|
||||
import {CalendarRange/*, CalendarRangeEvent*/} from 'ChillCalendarAssets/types';
|
||||
import {CalendarRange, CalendarRangeEdit} from "ChillCalendarAssets/types";
|
||||
import {fetchCalendarRangeForUser} from 'ChillCalendarAssets/vuejs/Calendar/api';
|
||||
import {calendarRangeToFullCalendarEvent/*, CalendarRangeEvent*/} from 'ChillCalendarAssets/vuejs/Calendar/store/utils';
|
||||
import {EventInput, EventSource} from '@fullcalendar/vue3';
|
||||
import {calendarRangeToFullCalendarEvent} from 'ChillCalendarAssets/vuejs/Calendar/store/utils';
|
||||
import {UserAssociatedInterface} from "../../../../../../../ChillMainBundle/Resources/public/types";
|
||||
import {EventInput} from '@fullcalendar/vue3';
|
||||
import {makeFetch} from "../../../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
|
||||
import {datetimeToISO} from "../../../../../../../ChillMainBundle/Resources/public/chill/js/date";
|
||||
import type {EventInputCalendarRange} from "ChillCalendarAssets/types";
|
||||
|
||||
export interface CalendarRangesState {
|
||||
ranges: EventInput[],
|
||||
ranges: (EventInput | EventInputCalendarRange) [],
|
||||
rangesLoaded: { start: number, end: number }[],
|
||||
rangesIndex: Set<string>,
|
||||
key: number
|
||||
@ -35,12 +39,12 @@ export default <Module<CalendarRangesState, State>> {
|
||||
},
|
||||
mutations: {
|
||||
addRanges(state: CalendarRangesState, ranges: CalendarRange[]) {
|
||||
console.log('addRanges', ranges);
|
||||
|
||||
const toAdd = ranges
|
||||
.map(cr => calendarRangeToFullCalendarEvent(cr))
|
||||
.map(cr => ({...cr, backgroundColor: 'white', borderColor:'#3788d8',
|
||||
textColor: 'black'}))
|
||||
.map(cr => ({
|
||||
...cr, backgroundColor: 'white', borderColor: '#3788d8',
|
||||
textColor: 'black'
|
||||
}))
|
||||
.filter(r => !state.rangesIndex.has(r.id));
|
||||
|
||||
toAdd.forEach((r) => {
|
||||
@ -72,17 +76,20 @@ export default <Module<CalendarRangesState, State>> {
|
||||
state.rangesIndex.add(asEvent.id);
|
||||
state.key = state.key + 1;
|
||||
},
|
||||
removeRange(state: CalendarRangesState, payload: EventInput) {
|
||||
/*
|
||||
state.ranges = state.ranges.filter(
|
||||
(r) => r.id !== payload.id
|
||||
);
|
||||
if (typeof payload.id === "string") {
|
||||
state.rangesIndex.delete(payload.id);
|
||||
}
|
||||
state.key = state.key + 1;
|
||||
removeRange(state: CalendarRangesState, calendarRangeId: number) {
|
||||
const found = state.ranges.find(r => r.calendarRangeId === calendarRangeId && r.is === "range");
|
||||
|
||||
*/
|
||||
if (found !== undefined) {
|
||||
state.ranges = state.ranges.filter(
|
||||
(r) => !(r.calendarRangeId === calendarRangeId && r.is === "range")
|
||||
);
|
||||
|
||||
if (typeof found.id === "string") { // should always be true
|
||||
state.rangesIndex.delete(found.id);
|
||||
}
|
||||
|
||||
state.key = state.key + 1;
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
@ -115,6 +122,48 @@ export default <Module<CalendarRangesState, State>> {
|
||||
ctx.commit('addRanges', ranges);
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
},
|
||||
createRange(ctx, {start, end}: { start: Date, end: Date }): Promise<null> {
|
||||
const url = `/api/1.0/calendar/calendar-range.json?`;
|
||||
|
||||
if (ctx.rootState.me.me === null) {
|
||||
throw new Error('user is currently null');
|
||||
}
|
||||
|
||||
const body = {
|
||||
user: {
|
||||
id: ctx.rootState.me.me.id,
|
||||
type: "user"
|
||||
},
|
||||
startDate: {
|
||||
datetime: datetimeToISO(start),
|
||||
},
|
||||
endDate: {
|
||||
datetime: datetimeToISO(end)
|
||||
},
|
||||
} as CalendarRangeEdit;
|
||||
|
||||
return makeFetch<CalendarRangeEdit, CalendarRange>('POST', url, body)
|
||||
.then((newRange) => {
|
||||
|
||||
ctx.commit('addRange', newRange);
|
||||
|
||||
return Promise.resolve(null);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
|
||||
throw error;
|
||||
})
|
||||
},
|
||||
deleteRange({commit}, calendarRangeId: number) {
|
||||
const url = `/api/1.0/calendar/calendar-range/${calendarRangeId}.json`;
|
||||
|
||||
makeFetch<undefined, never>('DELETE', url)
|
||||
.then((_) => {
|
||||
commit('removeRange', calendarRangeId);
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
@ -51,13 +51,15 @@ export interface NotFoundExceptionInterface extends TransportExceptionInterface
|
||||
export interface ServerExceptionInterface extends TransportExceptionInterface {
|
||||
name: 'ServerException';
|
||||
message: string;
|
||||
code: number;
|
||||
body: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generic api method that can be adapted to any fetch request
|
||||
*/
|
||||
export const makeFetch = <T, Q>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DELETE', url: string, body?: body | T | null, options?: FetchParams): Promise<Q> => {
|
||||
export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DELETE', url: string, body?: body | Input | null, options?: FetchParams): Promise<Output> => {
|
||||
let opts = {
|
||||
method: method,
|
||||
headers: {
|
||||
@ -128,15 +130,31 @@ function _fetchAction<T>(page: number, uri: string, params?: FetchParams): Promi
|
||||
},
|
||||
}).then((response) => {
|
||||
if (response.ok) { return response.json(); }
|
||||
|
||||
if (response.status === 404) {
|
||||
throw NotFoundException(response);
|
||||
}
|
||||
|
||||
console.error(response);
|
||||
throw ServerException();
|
||||
if (response.status === 422) {
|
||||
return response.json().then(response => {
|
||||
throw ValidationException(response)
|
||||
});
|
||||
}
|
||||
|
||||
if (response.status === 403) {
|
||||
throw AccessException(response);
|
||||
}
|
||||
|
||||
if (response.status >= 500) {
|
||||
return response.text().then(body => {
|
||||
throw ServerException(response.status, body);
|
||||
});
|
||||
}
|
||||
|
||||
throw new Error("other network error");
|
||||
}).catch((reason: any) => {
|
||||
console.error(reason);
|
||||
throw ServerException();
|
||||
throw new Error(reason);
|
||||
});
|
||||
};
|
||||
|
||||
@ -192,9 +210,11 @@ const NotFoundException = (response: Response): NotFoundExceptionInterface => {
|
||||
return error;
|
||||
}
|
||||
|
||||
const ServerException = (): ServerExceptionInterface => {
|
||||
const ServerException = (code: number, body: string): ServerExceptionInterface => {
|
||||
const error = {} as ServerExceptionInterface;
|
||||
error.name = 'ServerException';
|
||||
error.code = code;
|
||||
error.body = body;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -34,3 +34,8 @@ export interface User {
|
||||
user_job: Job;
|
||||
// todo: mainCenter; mainJob; etc..
|
||||
}
|
||||
|
||||
export interface UserAssociatedInterface {
|
||||
type: "user";
|
||||
id: number;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user