mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-25 06:32:50 +00:00 
			
		
		
		
	adding location to ranges and more control on MyCalendarRanges
This commit is contained in:
		| @@ -1,11 +1,12 @@ | ||||
| import {EventInput} from '@fullcalendar/vue3'; | ||||
| import {DateTime, User, UserAssociatedInterface} from '../../../ChillMainBundle/Resources/public/types' ; | ||||
| import {DateTime, Location, User, UserAssociatedInterface} from '../../../ChillMainBundle/Resources/public/types' ; | ||||
|  | ||||
| export interface CalendarRange { | ||||
|   id: number; | ||||
|   endDate: DateTime; | ||||
|   startDate: DateTime; | ||||
|   user: User; | ||||
|   location: Location; | ||||
|   createdAt: DateTime; | ||||
|   createdBy: User; | ||||
|   updatedAt: DateTime; | ||||
| @@ -13,14 +14,16 @@ export interface CalendarRange { | ||||
| } | ||||
|  | ||||
| export interface CalendarRangeCreate { | ||||
|   user: UserAssociatedInterface, | ||||
|   startDate: DateTime, | ||||
|   endDate: DateTime | ||||
|   user: UserAssociatedInterface; | ||||
|   startDate: DateTime; | ||||
|   endDate: DateTime; | ||||
|   location: Location; | ||||
| } | ||||
|  | ||||
| export interface CalendarRangeEdit { | ||||
|   startDate?: DateTime, | ||||
|   endDate?: DateTime | ||||
|   location?: Location; | ||||
| } | ||||
|  | ||||
| export interface Calendar { | ||||
| @@ -38,6 +41,8 @@ export type EventInputCalendarRange = EventInput & { | ||||
|   id: string, | ||||
|   userId: number, | ||||
|   calendarRangeId: number, | ||||
|   locationId: number, | ||||
|   locationName: string, | ||||
|   start: string, | ||||
|   end: string, | ||||
|   is: "range" | ||||
|   | ||||
| @@ -3,22 +3,8 @@ import {datetimeToISO} from '../../../../../ChillMainBundle/Resources/public/chi | ||||
| import {User} from '../../../../../ChillMainBundle/Resources/public/types'; | ||||
| import {CalendarRange, CalendarRemote} from '../../types'; | ||||
|  | ||||
| export const whoami = (): Promise<User> => { | ||||
|   const url = `/api/1.0/main/whoami.json`; | ||||
|   return fetch(url) | ||||
|     .then(response => { | ||||
|       if (response.ok) { | ||||
|         return response.json(); | ||||
|       } | ||||
|       throw { | ||||
|         msg: 'Error while getting whoami.', | ||||
|         sta: response.status, | ||||
|         txt: response.statusText, | ||||
|         err: new Error(), | ||||
|         body: response.body | ||||
|       }; | ||||
|     }); | ||||
| }; | ||||
| // re-export whoami | ||||
| export {whoami} from "../../../../../ChillMainBundle/Resources/public/lib/api/user"; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|   | ||||
| @@ -73,6 +73,8 @@ export const calendarRangeToFullCalendarEvent = (entity: CalendarRange): EventIn | ||||
|     allDay: false, | ||||
|     userId: entity.user.id, | ||||
|     calendarRangeId: entity.id, | ||||
|     locationId: entity.location.id, | ||||
|     locationName: entity.location.name, | ||||
|     is: 'range', | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,10 @@ | ||||
| <template> | ||||
|   <p>Il y a {{ 'eventSources[0].length' }} plages</p> | ||||
|   <div class="row"> | ||||
|     <div class="col-sm"> | ||||
|       <label>Localisation</label> | ||||
|       <vue-multiselect v-model="pickedLocation" :options="locations" :label="'name'" :track-by="'id'"></vue-multiselect> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="display-options row justify-content-between"> | ||||
|     <div class="col-sm col-xs-12"> | ||||
|       <div class="input-group mb-3"> | ||||
| @@ -10,15 +15,45 @@ | ||||
|           <option value="00:15:00">15 minutes</option> | ||||
|           <option value="00:30:00">30 minutes</option> | ||||
|         </select> | ||||
|         <label class="input-group-text" for="slotMinTime">De</label> | ||||
|         <select v-model="slotMinTime" id="slotMinTime" class="form-select"> | ||||
|           <option value="00:00:00">0h</option> | ||||
|           <option value="01:00:00">1h</option> | ||||
|           <option value="02:00:00">2h</option> | ||||
|           <option value="03:00:00">3h</option> | ||||
|           <option value="04:00:00">4h</option> | ||||
|           <option value="05:00:00">5h</option> | ||||
|           <option value="06:00:00">6h</option> | ||||
|           <option value="07:00:00">7h</option> | ||||
|           <option value="08:00:00">8h</option> | ||||
|           <option value="09:00:00">9h</option> | ||||
|           <option value="10:00:00">10h</option> | ||||
|           <option value="11:00:00">11h</option> | ||||
|           <option value="12:00:00">12h</option> | ||||
|         </select> | ||||
|         <label class="input-group-text" for="slotMaxTime">À</label> | ||||
|         <select v-model="slotMaxTime" id="slotMaxTime" class="form-select"> | ||||
|           <option value="12:00:00">12h</option> | ||||
|           <option value="13:00:00">13h</option> | ||||
|           <option value="14:00:00">14h</option> | ||||
|           <option value="15:00:00">15h</option> | ||||
|           <option value="16:00:00">16h</option> | ||||
|           <option value="17:00:00">17h</option> | ||||
|           <option value="18:00:00">18h</option> | ||||
|           <option value="19:00:00">19h</option> | ||||
|           <option value="20:00:00">20h</option> | ||||
|           <option value="21:00:00">21h</option> | ||||
|           <option value="22:00:00">22h</option> | ||||
|           <option value="23:00:00">23h</option> | ||||
|           <option value="23:59:59">24h</option> | ||||
|         </select> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="col-sm col-xs-12"> | ||||
|       <div class="float-end"> | ||||
|         <div class="input-group mb-3"> | ||||
|           <div class="input-group-text"> | ||||
|             <input id="showHideWE" class="form-check-input mt-0" type="checkbox" v-model="showWeekends"> | ||||
|             <label for="showHideWE" class="form-check-label"> Masquer les week-ends</label> | ||||
|           </div> | ||||
|         <div class="form-check form-switch"> | ||||
|           <input id="showHideWE" class="form-check-input mt-0" type="checkbox" v-model="showWeekends"> | ||||
|           <label for="showHideWE" class="form-check-label">Week-ends</label> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
| @@ -27,7 +62,7 @@ | ||||
|     <template v-slot:eventContent='arg'> | ||||
|       <span :class="eventClasses(arg.event)"> | ||||
|           <b v-if="arg.event.extendedProps.is === 'remote'">{{ arg.event.title}}</b> | ||||
|           <b v-else-if="arg.event.extendedProps.is === 'range'">{{ arg.timeText }}</b> | ||||
|           <b v-else-if="arg.event.extendedProps.is === 'range'">{{ arg.timeText }} - {{ arg.event.extendedProps.locationName }}</b> | ||||
|           <b v-else >no 'is'</b> | ||||
|           <a v-if="arg.event.extendedProps.is === 'range'" class="fa fa-fw fa-times" | ||||
|              @click.prevent="onClickDelete(arg.event)"> | ||||
| @@ -71,11 +106,15 @@ import interactionPlugin, {DropArg, EventResizeDoneArg} from "@fullcalendar/inte | ||||
| import timeGridPlugin from "@fullcalendar/timegrid"; | ||||
| import {EventApi, DateSelectArg, EventDropArg} from "@fullcalendar/core"; | ||||
| import {ISOToDate, ISOToDatetime} from "../../../../../ChillMainBundle/Resources/public/chill/js/date"; | ||||
| import VueMultiselect from "vue-multiselect"; | ||||
| import {Location} from "../../../../../ChillMainBundle/Resources/public/types"; | ||||
|  | ||||
| const store = useStore(key); | ||||
|  | ||||
| const showWeekends = ref(true); | ||||
| const showWeekends = ref(false); | ||||
| const slotDuration = ref('00:15:00'); | ||||
| const slotMinTime = ref('08:00:00'); | ||||
| const slotMaxTime = ref('19:00:00'); | ||||
| const copyFrom = ref<string | null>(null); | ||||
| const copyTo = ref<string | null>(null); | ||||
|  | ||||
| @@ -96,8 +135,6 @@ const baseOptions = ref<CalendarOptions>({ | ||||
|   eventDrop: onEventDropOrResize, | ||||
|   selectMirror: false, | ||||
|   editable: true, | ||||
|   slotMinTime: "08:00:00", | ||||
|   slotMaxTime: "19:00:00", | ||||
|   headerToolbar: { | ||||
|     left: 'prev,next today', | ||||
|     center: 'title', | ||||
| @@ -109,6 +146,19 @@ const ranges = computed<EventInput[]>(() => { | ||||
|   return store.state.calendarRanges.ranges; | ||||
| }); | ||||
|  | ||||
| const locations = computed<Location[]>(() => { | ||||
|   return store.state.locations.locations; | ||||
| }); | ||||
|  | ||||
| const pickedLocation = computed<Location | null>({ | ||||
|   get(): Location | null { | ||||
|     return store.state.locations.locationPicked || store.state.locations.currentLocation; | ||||
|   }, | ||||
|   set(newLocation: Location | null): void { | ||||
|     store.commit('locations/setLocationPicked', newLocation, { root: true}); | ||||
|   } | ||||
| }) | ||||
|  | ||||
| /** | ||||
|  * return the show classes for the event | ||||
|  * @param arg | ||||
| @@ -143,6 +193,8 @@ const calendarOptions = computed((): CalendarOptions => { | ||||
|     weekends: showWeekends.value, | ||||
|     slotDuration: slotDuration.value, | ||||
|     events: ranges.value, | ||||
|     slotMinTime: slotMinTime.value, | ||||
|     slotMaxTime: slotMaxTime.value, | ||||
|   }; | ||||
| }); | ||||
|  | ||||
| @@ -154,7 +206,13 @@ function onDatesSet(event: DatesSetArg): void { | ||||
| } | ||||
|  | ||||
| function onDateSelect(event: DateSelectArg): void { | ||||
|   store.dispatch('calendarRanges/createRange', {start: event.start, end: event.end}); | ||||
|  | ||||
|   if (null === pickedLocation.value) { | ||||
|     window.alert("Indiquez une localisation avant de créer une période de disponibilité."); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   store.dispatch('calendarRanges/createRange', {start: event.start, end: event.end, location: pickedLocation.value}); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,30 +1,22 @@ | ||||
| import 'es6-promise/auto'; | ||||
| import {Store, createStore} from 'vuex'; | ||||
| import {InjectionKey} from "vue"; | ||||
| //import actions from './actions'; | ||||
| //import getters from './getters'; | ||||
| //import mutations from './mutations'; | ||||
| import me, {MeState} from './modules/me'; | ||||
| import fullCalendar, {FullCalendarState} from './modules/fullcalendar'; | ||||
| import calendarRanges, {CalendarRangesState} from './modules/calendarRanges'; | ||||
| import calendarRemotes, {CalendarRemotesState} from './modules/calendarRemotes'; | ||||
| import {whoami} from '../../Calendar/api'; | ||||
| import {whoami} from "../../../../../../ChillMainBundle/Resources/public/lib/api/user"; | ||||
| import {User} from '../../../../../../ChillMainBundle/Resources/public/types'; | ||||
| import locations, {LocationState} from "./modules/location"; | ||||
|  | ||||
| const debug = process.env.NODE_ENV !== 'production'; | ||||
|  | ||||
| export interface State { | ||||
|   /* | ||||
|   appointments: Calendar[], | ||||
|   appointmentsShown: boolean, | ||||
|   startDate: Date|null, | ||||
|   endDate: Date|null, | ||||
|    */ | ||||
|   //key: number, | ||||
|   calendarRanges: CalendarRangesState, | ||||
|   calendarRemotes: CalendarRemotesState, | ||||
|   fullCalendar: FullCalendarState, | ||||
|   me: MeState, | ||||
|   locations: LocationState | ||||
| } | ||||
|  | ||||
| export const key: InjectionKey<Store<State>> = Symbol(); | ||||
| @@ -33,38 +25,20 @@ const futureStore = function(): Promise<Store<State>> { | ||||
|   return whoami().then((user: User) => { | ||||
|     const store = createStore<State>({ | ||||
|       strict: debug, | ||||
|       /* | ||||
|       state: (): State => ({ | ||||
|         //key: 0, | ||||
|       }), | ||||
|  | ||||
|        */ | ||||
|       modules: { | ||||
|         me, | ||||
|         fullCalendar, | ||||
|         calendarRanges, | ||||
|         calendarRemotes, | ||||
|         locations, | ||||
|       }, | ||||
|       mutations: { | ||||
|         increaseKey(state: State) { | ||||
|           //state.key = state.key + 1; | ||||
|         } | ||||
|       } | ||||
|       /* | ||||
|       state: { | ||||
|         appointments: [], | ||||
|         appointmentsShown: true, | ||||
|         startDate: null, | ||||
|         endDate: null, | ||||
|       }, | ||||
|        */ | ||||
|       //getters, | ||||
|       //mutations, | ||||
|       //actions, | ||||
|       mutations: {} | ||||
|     }); | ||||
|  | ||||
|     store.commit('me/setWhoAmi', user, {root: true}) | ||||
|     //store.dispatch('calendarRanges/fetchRanges', null, {root: true}); | ||||
|     store.commit('me/setWhoAmi', user, {root: true}); | ||||
|     store.dispatch('locations/getLocations', null, {root: true}).then(_ => { | ||||
|       return store.dispatch('locations/getCurrentLocation', null, {root: true}); | ||||
|     }); | ||||
|  | ||||
|     return Promise.resolve(store); | ||||
|   }); | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import {State} from './../index'; | ||||
| import {ActionContext, Module} from 'vuex'; | ||||
| import {CalendarRange, CalendarRangeCreate, CalendarRangeEdit, isEventInputCalendarRange} from "../../../../types"; | ||||
| import {Location} from "../../../../../../../ChillMainBundle/Resources/public/types"; | ||||
| import {fetchCalendarRangeForUser} from '../../../Calendar/api'; | ||||
| import {calendarRangeToFullCalendarEvent} from '../../../Calendar/store/utils'; | ||||
| import {EventInput} from '@fullcalendar/vue3'; | ||||
| @@ -89,7 +90,7 @@ export default <Module<CalendarRangesState, State>>{ | ||||
|   },*/ | ||||
|     addRange(state: CalendarRangesState, payload: CalendarRange) { | ||||
|       const asEvent = calendarRangeToFullCalendarEvent(payload); | ||||
|       state.ranges.push(asEvent); | ||||
|       state.ranges.push({...asEvent, backgroundColor: 'white', borderColor: '#3788d8', textColor: 'black'}); | ||||
|       state.rangesIndex.add(asEvent.id); | ||||
|       state.key = state.key + 1; | ||||
|     }, | ||||
| @@ -122,17 +123,14 @@ export default <Module<CalendarRangesState, State>>{ | ||||
|   }, | ||||
|   actions: { | ||||
|     fetchRanges(ctx: Context, payload: { start: Date, end: Date }): Promise<null> { | ||||
|       console.log('fetchRanges', payload); | ||||
|       const start = payload.start; | ||||
|       const end = payload.end; | ||||
|  | ||||
|       if (ctx.rootGetters['me/getMe'] === null) { | ||||
|         console.log('me is not there'); | ||||
|         return Promise.resolve(ctx.getters.getRangeSource); | ||||
|       } | ||||
|  | ||||
|       if (ctx.getters.isRangeLoaded({start, end})) { | ||||
|         console.log('range already loaded'); | ||||
|         return Promise.resolve(ctx.getters.getRangeSource); | ||||
|       } | ||||
|  | ||||
| @@ -151,7 +149,7 @@ export default <Module<CalendarRangesState, State>>{ | ||||
|           return Promise.resolve(null); | ||||
|         }); | ||||
|     }, | ||||
|     createRange(ctx, {start, end}: { start: Date, end: Date }): Promise<null> { | ||||
|     createRange(ctx, {start, end, location}: { start: Date, end: Date, location: Location }): Promise<null> { | ||||
|       const url = `/api/1.0/calendar/calendar-range.json?`; | ||||
|  | ||||
|       if (ctx.rootState.me.me === null) { | ||||
| @@ -169,6 +167,10 @@ export default <Module<CalendarRangesState, State>>{ | ||||
|         endDate: { | ||||
|           datetime: datetimeToISO(end) | ||||
|         }, | ||||
|         location: { | ||||
|           id: location.id, | ||||
|           type: "location" | ||||
|         } | ||||
|       } as CalendarRangeCreate; | ||||
|  | ||||
|       return makeFetch<CalendarRangeCreate, CalendarRange>('POST', url, body) | ||||
| @@ -179,7 +181,7 @@ export default <Module<CalendarRangesState, State>>{ | ||||
|           return Promise.resolve(null); | ||||
|         }) | ||||
|         .catch((error) => { | ||||
|           console.log(error); | ||||
|           console.error(error); | ||||
|  | ||||
|           throw error; | ||||
|         }) | ||||
| @@ -208,7 +210,7 @@ export default <Module<CalendarRangesState, State>>{ | ||||
|           ctx.commit('updateRange', range); | ||||
|         }) | ||||
|         .catch((error) => { | ||||
|           console.log(error); | ||||
|           console.error(error); | ||||
|         }) | ||||
|     }, | ||||
|     copyFromDayToAnotherDay(ctx, {from, to}: {from: Date, to: Date}): Promise<null> { | ||||
|   | ||||
| @@ -0,0 +1,57 @@ | ||||
| import {Location} from "../../../../../../../ChillMainBundle/Resources/public/types"; | ||||
| import {State} from '../index'; | ||||
| import {Module} from 'vuex'; | ||||
| import {getLocations} from "../../../../../../../ChillMainBundle/Resources/public/lib/api/locations"; | ||||
| import {whereami} from "../../../../../../../ChillMainBundle/Resources/public/lib/api/user"; | ||||
|  | ||||
| export interface LocationState { | ||||
|   locations: Location[]; | ||||
|   locationPicked: Location | null; | ||||
|   currentLocation: Location | null; | ||||
| } | ||||
|  | ||||
| export default <Module<LocationState, State>>{ | ||||
|   namespaced: true, | ||||
|   state: (): LocationState => { | ||||
|     return { | ||||
|       locations: [], | ||||
|       locationPicked: null, | ||||
|       currentLocation: null, | ||||
|     } | ||||
|   }, | ||||
|   mutations: { | ||||
|     setLocations(state, locations): void { | ||||
|       state.locations = locations; | ||||
|     }, | ||||
|     setLocationPicked(state, location: Location | null): void { | ||||
|       if (null === location) { | ||||
|         state.locationPicked = null; | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       state.locationPicked = state.locations.find(l => l.id === location.id) || null; | ||||
|     }, | ||||
|     setCurrentLocation(state, location: Location | null): void { | ||||
|       if (null === location) { | ||||
|         state.currentLocation = null; | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       state.currentLocation = state.locations.find(l => l.id === location.id) || null; | ||||
|     } | ||||
|   }, | ||||
|   actions: { | ||||
|     getLocations(ctx): Promise<void> { | ||||
|       return getLocations().then(locations => { | ||||
|         ctx.commit('setLocations', locations); | ||||
|         return Promise.resolve(); | ||||
|       }); | ||||
|     }, | ||||
|     getCurrentLocation(ctx): Promise<void> { | ||||
|       return whereami().then(location => { | ||||
|         ctx.commit('setCurrentLocation', location); | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user