refactor to use store for storing events

This commit is contained in:
Julien Fastré 2022-05-17 16:57:31 +02:00
parent 9ceb66e2da
commit f68c69d443
11 changed files with 373 additions and 147 deletions

View File

@ -1,16 +1,5 @@
<template> <template>
<concerned-groups></concerned-groups> <concerned-groups></concerned-groups>
<location></location>
<teleport to="#calendarControls">
<calendar-user-selector
v-bind:users="users"
v-bind:calendarEvents="calendarEvents"
v-bind:updateEventsSource="updateEventsSource"
v-bind:showMyCalendar="showMyCalendar"
v-bind:toggleMyCalendar="toggleMyCalendar"
v-bind:toggleWeekends="toggleWeekends" >
</calendar-user-selector>
</teleport>
<teleport to="#fullCalendar"> <teleport to="#fullCalendar">
<FullCalendar ref="fullCalendar" :options="calendarOptions"> <FullCalendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent='arg'> <template v-slot:eventContent='arg'>
@ -19,9 +8,11 @@
</template> </template>
</FullCalendar> </FullCalendar>
</teleport> </teleport>
<location></location>
</template> </template>
<script> <script>
//import {mapGetters} from 'vuex';
import ConcernedGroups from 'ChillActivityAssets/vuejs/Activity/components/ConcernedGroups.vue'; import ConcernedGroups from 'ChillActivityAssets/vuejs/Activity/components/ConcernedGroups.vue';
import Location from 'ChillActivityAssets/vuejs/Activity/components/Location.vue'; import Location from 'ChillActivityAssets/vuejs/Activity/components/Location.vue';
import CalendarUserSelector from '../_components/CalendarUserSelector/CalendarUserSelector.vue'; import CalendarUserSelector from '../_components/CalendarUserSelector/CalendarUserSelector.vue';
@ -44,6 +35,7 @@ export default {
data() { data() {
return { return {
errorMsg: [], errorMsg: [],
/*
users: { users: {
loaded: [], loaded: [],
selected: [], selected: [],
@ -62,18 +54,26 @@ export default {
id: window.mainUser, id: window.mainUser,
color: '#bbbbbb' color: '#bbbbbb'
} }
}, },*/
selectedEvent: null, selectedEvent: null,
previousSelectedEvent: null, previousSelectedEvent: null,
previousSelectedEventColor: null, previousSelectedEventColor: null,
showMyCalendar: false, showMyCalendar: false,
calendarOptions: { }
},
computed: {
events() {
return this.$store.getters.getEventSources;
},
calendarOptions() {
return {
locale: frLocale, locale: frLocale,
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ], plugins: [dayGridPlugin, interactionPlugin, timeGridPlugin],
initialView: 'timeGridWeek', initialView: 'timeGridWeek',
initialDate: window.startDate !== undefined ? window.startDate : new Date(), initialDate: this.$store.getters.initialDate,
eventSource: [], eventSources: this.events,
selectable: true, selectable: true,
datesSet: this.onDatesSet,
select: this.onDateSelect, select: this.onDateSelect,
eventChange: this.onEventChange, eventChange: this.onEventChange,
eventClick: this.onEventClick, eventClick: this.onEventClick,
@ -86,21 +86,22 @@ export default {
left: 'prev,next today', left: 'prev,next today',
center: 'title', center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth,listWeek,listDay' right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth,listWeek,listDay'
}
};
}, },
}
}
}, },
methods: { methods: {
init() { init() {
this.updateEventsSource(); //this.updateEventsSource();
}, },
toggleMyCalendar(value) { toggleMyCalendar(value) {
this.showMyCalendar = value; this.showMyCalendar = value;
}, },
toggleWeekends: function() { toggleWeekends: function () {
this.calendarOptions.weekends = !this.calendarOptions.weekends; this.calendarOptions.weekends = !this.calendarOptions.weekends;
}, },
updateEventsSource() { updateEventsSource() {
/*
this.calendarOptions.eventSources = []; this.calendarOptions.eventSources = [];
this.calendarOptions.eventSources.push(...this.calendarEvents.selected); this.calendarOptions.eventSources.push(...this.calendarEvents.selected);
if (window.startDate !== undefined) { if (window.startDate !== undefined) {
@ -109,14 +110,22 @@ export default {
if (this.showMyCalendar) { if (this.showMyCalendar) {
this.calendarOptions.eventSources.push(this.calendarEvents.user); this.calendarOptions.eventSources.push(this.calendarEvents.user);
} }
console.log('eventSources', this.calendarOptions.eventSoruces);
*/
},
onDatesSet(event) {
console.log('onDatesSet', event);
this.$store.dispatch('setCurrentDatesView', {start: event.start, end: event.end});
}, },
unSelectPreviousEvent(event) { unSelectPreviousEvent(event) {
if (event) { if (event) {
if (typeof event.setProp === 'function') { if (typeof event.setProp === 'function') {
event.setProp('backgroundColor', this.previousSelectedEventColor); event.setProp('backgroundColor', this.previousSelectedEventColor);
event.setProp('borderColor', this.previousSelectedEventColor); event.setProp('borderColor', this.previousSelectedEventColor);
event.setProp('textColor','#444444'); event.setProp('textColor', '#444444');
event.setProp('title',''); event.setProp('title', '');
} }
} }
}, },
@ -136,20 +145,20 @@ export default {
this.previousSelectedEventColor = payload.event.extendedProps.sourceColor; this.previousSelectedEventColor = payload.event.extendedProps.sourceColor;
this.selectedEvent = payload.event; this.selectedEvent = payload.event;
this.unSelectPreviousEvent(this.previousSelectedEvent); this.unSelectPreviousEvent(this.previousSelectedEvent);
payload.event.setProp('backgroundColor','#3788d8'); payload.event.setProp('backgroundColor', '#3788d8');
payload.event.setProp('borderColor','#3788d8'); payload.event.setProp('borderColor', '#3788d8');
payload.event.setProp('title', 'Choisir cette plage'); payload.event.setProp('title', 'Choisir cette plage');
payload.event.setProp('textColor','#ffffff'); payload.event.setProp('textColor', '#ffffff');
}, },
onEventMouseEnter(payload) { onEventMouseEnter(payload) {
payload.event.setProp('borderColor','#444444'); payload.event.setProp('borderColor', '#444444');
}, },
onEventMouseLeave(payload) { onEventMouseLeave(payload) {
payload.event.setProp('borderColor','#ffffff'); payload.event.setProp('borderColor', '#ffffff');
} }
}, },
mounted() { mounted() {
this.init(); //this.init();
} }
} }
</script> </script>

View File

@ -0,0 +1,39 @@
import {fetchResults} from 'ChillMainAssets/lib/api/apiMethods';
import {datetimeToISO} from 'ChillMainAssets/chill/js/date';
const whoami = () => {
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
};
});
};
/**
*
* @param user
* @param Date start
* @param Date end
* @return Promise
*/
const fetchCalendarRangeForUser = (user, start, end) => {
const uri = `/api/1.0/calendar/calendar-range-available/${user.id}.json`;
const dateFrom = datetimeToISO(start);
const dateTo = datetimeToISO(end);
return fetchResults(uri, {dateFrom, dateTo});
}
export {
whoami,
fetchCalendarRangeForUser,
};

View File

@ -0,0 +1,8 @@
const USER_CALENDAR_SHOW_RANGES = 'ranges';
const USER_CALENDAR_SHOW_EVENTS = 'events';
export {
USER_CALENDAR_SHOW_RANGES,
USER_CALENDAR_SHOW_EVENTS,
};

View File

@ -4,8 +4,38 @@ import {
removeIdFromValue, removeIdFromValue,
mapEntity mapEntity
} from './utils'; } from './utils';
import {fetchCalendarRangeForUser} from './../api';
export default { export default {
setCurrentDatesView({ commit, dispatch }, {start, end}) {
commit('setCurrentDatesView', {start, end});
return dispatch('fetchCalendarEvents');
},
fetchCalendarEvents({ state, getters, dispatch }) {
if (state.currentView.start === null && state.currentView.end === null) {
return Promise.resolve();
}
let promises = [];
if (null !== getters.getMainUser) {
promises.push(
dispatch('fetchCalendarRangeForUser',
{user: getters.getMainUser, start: state.currentView.start, end: state.currentView.end})
);
}
return Promise.all(promises);
},
fetchCalendarRangeForUser({ commit, getters }, { user, start, end }) {
if (!getters.isCalendarRangeLoadedForUser({user, start, end})) {
return fetchCalendarRangeForUser(user, start, end).then((ranges) => {
commit('addCalendarRangesForUser', {user, ranges, start, end});
return Promise.resolve();
});
}
},
addPersonsInvolved({ commit }, payload) { addPersonsInvolved({ commit }, payload) {
console.log('### action addPersonsInvolved', payload.result.type); console.log('### action addPersonsInvolved', payload.result.type);
switch (payload.result.type) { switch (payload.result.type) {

View File

@ -1,6 +1,72 @@
import {USER_CALENDAR_SHOW_RANGES, USER_CALENDAR_SHOW_EVENTS} from './../const';
import {calendarRangeToFullCalendarEvent} from './utils';
export default { export default {
getMainUser(state) {
return state.activity.mainUser || null;
},
getEventDate(state) {
if (null === state.activity.start) {
return new Date();
}
throw 'transform date to object ?';
},
getEventSources(state) {
console.log('getEventSources');
let sources = [];
for (const [userId, kinds] of state.currentView.users.entries()) {
console.log('loop', userId, kinds);
if (!state.usersData.has(userId)) {
console.log('try to get events on a user which not exists', userId);
continue;
}
console.log('addingUser', userId);
const userData = state.usersData.get(userId);
console.log('userData', userData);
if (kinds.includes(USER_CALENDAR_SHOW_RANGES) && userData.calendarRanges.length > 0) {
console.log('adding ranges for user', userId);
const s = {
//'id': `ranges_${userId}`,
'events': userData.calendarRanges,
};
console.log('range source', s);
sources.push(s);
} else {
console.log('not adding ranges for user', userId);
}
}
console.log('eventSources', sources);
return sources;
},
getUserData: (state) => (user) => {
return state.usersData.get(user.id);
},
hasUserData: (state) => (user) => {
return state.usersData.has(user.id);
},
isCalendarRangeLoadedForUser: (state, getters) => ({user, start, end}) => {
if (!getters.hasUserData(user)) {
return false;
}
for (let interval of getters.getUserData(user).calendarRangesLoaded) {
if (start >= interval.start && end <= interval.end) {
return true;
}
}
return false;
},
suggestedEntities(state, getters) { suggestedEntities(state, getters) {
if (typeof(state.activity.accompanyingPeriod) === 'undefined') { if (typeof (state.activity.accompanyingPeriod) === 'undefined') {
return []; return [];
} }
const allEntities = [ const allEntities = [

View File

@ -6,6 +6,8 @@ import getters from './getters';
import actions from './actions'; import actions from './actions';
import mutations from './mutations'; import mutations from './mutations';
import { mapEntity } from './utils'; import { mapEntity } from './utils';
import { whoami } from '../api';
import { USER_CALENDAR_SHOW_RANGES }from './../const';
import { import {
getLocations, getLocationTypeByDefaultFor, getLocations, getLocationTypeByDefaultFor,
@ -14,18 +16,34 @@ import {
const debug = process.env.NODE_ENV !== 'production'; const debug = process.env.NODE_ENV !== 'production';
const store = createStore({ const store = createStore({
strict: debug, strict: debug,
state: { state: {
activity: mapEntity(window.entity), // activity is the calendar entity actually activity: mapEntity(window.entity), // activity is the calendar entity actually
currentEvent: null, currentEvent: null,
availableLocations: [], availableLocations: [],
mainUser: null me: null,
initialDate: null,
currentView: {
start: null,
end: null,
users: new Map(),
},
usersData: new Map(),
}, },
getters, getters,
mutations, mutations,
actions, actions,
}); });
console.log('calendar event', store.state.activity);
whoami().then(me => {
store.commit('setWhoAmiI', me);
});
if (null !== store.getters.getMainUser) {
store.commit('showUserOnCalendar', {what: [USER_CALENDAR_SHOW_RANGES], user: store.getters.getMainUser});
}
export default store; export default store;

View File

@ -1,4 +1,18 @@
import {createUserData, calendarRangeToFullCalendarEvent} from './utils';
export default { export default {
setWhoAmiI(state, me) {
state.me = me;
},
setCurrentDatesView(state, {start, end}) {
state.currentView.start = start;
state.currentView.end = end;
},
showUserOnCalendar(state, {user, what}) {
console.log('showUserOnCalendar', {user: user.id, what});
state.currentView.users.set(user.id, what);
},
// ConcernedGroups // ConcernedGroups
addPersonsInvolved(state, payload) { addPersonsInvolved(state, payload) {
//console.log('### mutation addPersonsInvolved', payload.result.type); //console.log('### mutation addPersonsInvolved', payload.result.type);
@ -12,7 +26,8 @@ export default {
case 'user': case 'user':
state.activity.users.push(payload.result); state.activity.users.push(payload.result);
break; break;
}; }
;
}, },
removePersonInvolved(state, payload) { removePersonInvolved(state, payload) {
//console.log('### mutation removePersonInvolved', payload.type); //console.log('### mutation removePersonInvolved', payload.type);
@ -26,13 +41,29 @@ export default {
case 'user': case 'user':
state.activity.users = state.activity.users.filter(user => user !== payload); state.activity.users = state.activity.users.filter(user => user !== payload);
break; break;
}; }
;
}, },
// Calendar addCalendarRangesForUser(state, {user, ranges, start, end}) {
setEvents(state, payload) { let userData;
if (state.usersData.has(user.id)) {
userData = state.usersData.get(user.id);
} else {
userData = createUserData(user);
state.usersData.set(user.id, userData);
}
const eventRanges = ranges.map(r => calendarRangeToFullCalendarEvent(r));
userData.calendarRanges = userData.calendarRanges.concat(eventRanges);
userData.calendarRangesLoaded.push({start, end});
},
/*
// Calendar
setEvents(state, payload) {
console.log(payload) console.log(payload)
state.currentEvent = {start: payload.start, end: payload.end} state.currentEvent = {start: payload.start, end: payload.end}
}, },*/
// Location // Location
updateLocation(state, value) { updateLocation(state, value) {
console.log('### mutation: updateLocation', value); console.log('### mutation: updateLocation', value);

View File

@ -20,8 +20,29 @@ const mapEntity = (entity) => {
return entity; return entity;
}; };
const createUserData = (user) => {
return {
user: user,
calendarRanges: [],
calendarRangesLoaded: [],
}
}
const calendarRangeToFullCalendarEvent = (entity) => {
return {
//id: `range_${entity.id}`,
title: "Disponible",
start: entity.startDate.datetime8601,
end: entity.endDate.datetime8601,
allDay: false,
//userId: entity.user.id,
};
}
export { export {
addIdToValue, addIdToValue,
calendarRangeToFullCalendarEvent,
removeIdFromValue, removeIdFromValue,
mapEntity mapEntity,
createUserData,
}; };

View File

@ -4,6 +4,7 @@
* @returns {Promise} a promise containing all Calendar ranges objects * @returns {Promise} a promise containing all Calendar ranges objects
*/ */
const fetchCalendarRanges = () => { const fetchCalendarRanges = () => {
return Promise.resolve([]);
const url = `/api/1.0/calendar/calendar-range-available.json`; const url = `/api/1.0/calendar/calendar-range-available.json`;
return fetch(url) return fetch(url)
.then(response => { .then(response => {
@ -13,6 +14,7 @@ const fetchCalendarRanges = () => {
}; };
const fetchCalendarRangesByUser = (userId) => { const fetchCalendarRangesByUser = (userId) => {
return Promise.resolve([]);
const url = `/api/1.0/calendar/calendar-range-available.json?user=${userId}`; const url = `/api/1.0/calendar/calendar-range-available.json?user=${userId}`;
return fetch(url) return fetch(url)
.then(response => { .then(response => {
@ -27,6 +29,7 @@ const fetchCalendarRangesByUser = (userId) => {
* @returns {Promise} a promise containing all Calendar objects * @returns {Promise} a promise containing all Calendar objects
*/ */
const fetchCalendar = (mainUserId) => { const fetchCalendar = (mainUserId) => {
return Promise.resolve([]);
const url = `/api/1.0/calendar/calendar.json?main_user=${mainUserId}&item_per_page=1000`; const url = `/api/1.0/calendar/calendar.json?main_user=${mainUserId}&item_per_page=1000`;
return fetch(url) return fetch(url)
.then(response => { .then(response => {

View File

@ -24,8 +24,6 @@ function loadDynamicPicker(element) {
null : [ JSON.parse(input.value) ] null : [ JSON.parse(input.value) ]
) )
; ;
console.log('picked at startup', picked);
console.log('input', input);
if (!isMultiple) { if (!isMultiple) {
if (input.value === '[]'){ if (input.value === '[]'){

View File

@ -146,6 +146,9 @@ export default {
} }
}, },
titleCreate() { titleCreate() {
if (typeof this.allowedTypes === 'undefined') {
return 'onthefly.create.title.default';
}
return this.allowedTypes.every(t => t === 'person') return this.allowedTypes.every(t => t === 'person')
? 'onthefly.create.title.person' ? 'onthefly.create.title.person'
: this.allowedTypes.every(t => t === 'thirdparty') : this.allowedTypes.every(t => t === 'thirdparty')