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

View File

@ -6,6 +6,8 @@ import getters from './getters';
import actions from './actions';
import mutations from './mutations';
import { mapEntity } from './utils';
import { whoami } from '../api';
import { USER_CALENDAR_SHOW_RANGES }from './../const';
import {
getLocations, getLocationTypeByDefaultFor,
@ -14,18 +16,34 @@ import {
const debug = process.env.NODE_ENV !== 'production';
const store = createStore({
strict: debug,
state: {
activity: mapEntity(window.entity), // activity is the calendar entity actually
currentEvent: null,
availableLocations: [],
mainUser: null
me: null,
initialDate: null,
currentView: {
start: null,
end: null,
users: new Map(),
},
usersData: new Map(),
},
getters,
mutations,
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;

View File

@ -1,4 +1,18 @@
import {createUserData, calendarRangeToFullCalendarEvent} from './utils';
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
addPersonsInvolved(state, payload) {
//console.log('### mutation addPersonsInvolved', payload.result.type);
@ -12,7 +26,8 @@ export default {
case 'user':
state.activity.users.push(payload.result);
break;
};
}
;
},
removePersonInvolved(state, payload) {
//console.log('### mutation removePersonInvolved', payload.type);
@ -26,13 +41,29 @@ export default {
case 'user':
state.activity.users = state.activity.users.filter(user => user !== payload);
break;
};
}
;
},
// Calendar
setEvents(state, payload) {
addCalendarRangesForUser(state, {user, ranges, start, end}) {
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)
state.currentEvent = {start: payload.start, end: payload.end}
},
},*/
// Location
updateLocation(state, value) {
console.log('### mutation: updateLocation', value);

View File

@ -20,8 +20,29 @@ const mapEntity = (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 {
addIdToValue,
calendarRangeToFullCalendarEvent,
removeIdFromValue,
mapEntity
mapEntity,
createUserData,
};

View File

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

View File

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

View File

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