From f68c69d4430163253b6c3aafe51b82a7ec85ab3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 17 May 2022 16:57:31 +0200 Subject: [PATCH] refactor to use store for storing events --- .../Resources/public/vuejs/Calendar/App.vue | 87 +++++---- .../Resources/public/vuejs/Calendar/api.js | 39 ++++ .../Resources/public/vuejs/Calendar/const.js | 8 + .../public/vuejs/Calendar/store/actions.js | 30 +++ .../public/vuejs/Calendar/store/getters.js | 172 ++++++++++++------ .../public/vuejs/Calendar/store/index.js | 22 ++- .../public/vuejs/Calendar/store/mutations.js | 107 +++++++---- .../public/vuejs/Calendar/store/utils.js | 47 +++-- .../Resources/public/vuejs/_api/api.js | 3 + .../public/module/pick-entity/index.js | 2 - .../vuejs/OnTheFly/components/OnTheFly.vue | 3 + 11 files changed, 373 insertions(+), 147 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/api.js create mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/const.js diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index 2741f8b8f..bc95e3cc8 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -1,16 +1,5 @@ diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/api.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/api.js new file mode 100644 index 000000000..94dcffd58 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/api.js @@ -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, +}; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/const.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/const.js new file mode 100644 index 000000000..c5d78a023 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/const.js @@ -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, +}; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/actions.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/actions.js index 87debf9de..0127a7885 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/actions.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/actions.js @@ -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) { diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/getters.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/getters.js index c7f0e878d..bef563f10 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/getters.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/getters.js @@ -1,56 +1,122 @@ -export default { - suggestedEntities(state, getters) { - if (typeof(state.activity.accompanyingPeriod) === 'undefined') { - return []; - } - const allEntities = [ - getters.suggestedPersons, - getters.suggestedRequestor, - getters.suggestedUser, - getters.suggestedResources - ]; - const uniqueIds = [...new Set(allEntities.map(i => `${i.type}-${i.id}`))]; - return Array.from(uniqueIds, id => allEntities.filter(r => `${r.type}-${r.id}` === id)[0]); - }, - suggestedPersons(state) { - const existingPersonIds = state.activity.persons.map(p => p.id); - return state.activity.accompanyingPeriod.participations - .filter(p => p.endDate === null) - .map(p => p.person) - .filter(p => !existingPersonIds.includes(p.id)) - }, - suggestedRequestor(state) { - if (state.activity.accompanyingPeriod.requestor === null) { - return []; - } +import {USER_CALENDAR_SHOW_RANGES, USER_CALENDAR_SHOW_EVENTS} from './../const'; +import {calendarRangeToFullCalendarEvent} from './utils'; - const existingPersonIds = state.activity.persons.map(p => p.id); - const existingThirdPartyIds = state.activity.thirdParties.map(p => p.id); - return [state.activity.accompanyingPeriod.requestor] - .filter(r => - (r.type === 'person' && !existingPersonIds.includes(r.id)) || - (r.type === 'thirdparty' && !existingThirdPartyIds.includes(r.id)) - ); - }, - suggestedUser(state) { - if (null === state.activity.users) { - return []; - } - const existingUserIds = state.activity.users.map(p => p.id); - return [state.activity.accompanyingPeriod.user] - .filter( - u => u !== null && !existingUserIds.includes(u.id) - ); - }, - suggestedResources(state) { - const resources = state.activity.accompanyingPeriod.resources; - const existingPersonIds = state.activity.persons.map(p => p.id); - const existingThirdPartyIds = state.activity.thirdParties.map(p => p.id); - return state.activity.accompanyingPeriod.resources - .map(r => r.resource) - .filter(r => - (r.type === 'person' && !existingPersonIds.includes(r.id)) || - (r.type === 'thirdparty' && !existingThirdPartyIds.includes(r.id)) - ); +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') { + return []; + } + const allEntities = [ + getters.suggestedPersons, + getters.suggestedRequestor, + getters.suggestedUser, + getters.suggestedResources + ]; + const uniqueIds = [...new Set(allEntities.map(i => `${i.type}-${i.id}`))]; + return Array.from(uniqueIds, id => allEntities.filter(r => `${r.type}-${r.id}` === id)[0]); + }, + suggestedPersons(state) { + const existingPersonIds = state.activity.persons.map(p => p.id); + return state.activity.accompanyingPeriod.participations + .filter(p => p.endDate === null) + .map(p => p.person) + .filter(p => !existingPersonIds.includes(p.id)) + }, + suggestedRequestor(state) { + if (state.activity.accompanyingPeriod.requestor === null) { + return []; + } + + const existingPersonIds = state.activity.persons.map(p => p.id); + const existingThirdPartyIds = state.activity.thirdParties.map(p => p.id); + return [state.activity.accompanyingPeriod.requestor] + .filter(r => + (r.type === 'person' && !existingPersonIds.includes(r.id)) || + (r.type === 'thirdparty' && !existingThirdPartyIds.includes(r.id)) + ); + }, + suggestedUser(state) { + if (null === state.activity.users) { + return []; + } + const existingUserIds = state.activity.users.map(p => p.id); + return [state.activity.accompanyingPeriod.user] + .filter( + u => u !== null && !existingUserIds.includes(u.id) + ); + }, + suggestedResources(state) { + const resources = state.activity.accompanyingPeriod.resources; + const existingPersonIds = state.activity.persons.map(p => p.id); + const existingThirdPartyIds = state.activity.thirdParties.map(p => p.id); + return state.activity.accompanyingPeriod.resources + .map(r => r.resource) + .filter(r => + (r.type === 'person' && !existingPersonIds.includes(r.id)) || + (r.type === 'thirdparty' && !existingThirdPartyIds.includes(r.id)) + ); + } } diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/index.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/index.js index 0011b2f3f..5eecb9471 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/index.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/index.js @@ -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; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/mutations.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/mutations.js index 6e8923f6b..2aaba18b1 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/mutations.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/mutations.js @@ -1,41 +1,72 @@ +import {createUserData, calendarRangeToFullCalendarEvent} from './utils'; + export default { - // ConcernedGroups - addPersonsInvolved(state, payload) { - //console.log('### mutation addPersonsInvolved', payload.result.type); - switch (payload.result.type) { - case 'person': - state.activity.persons.push(payload.result); - break; - case 'thirdparty': - state.activity.thirdParties.push(payload.result); - break; - case 'user': - state.activity.users.push(payload.result); - break; - }; - }, - removePersonInvolved(state, payload) { - //console.log('### mutation removePersonInvolved', payload.type); - switch (payload.type) { - case 'person': - state.activity.persons = state.activity.persons.filter(person => person !== payload); - break; - case 'thirdparty': - state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); - break; - case 'user': - state.activity.users = state.activity.users.filter(user => user !== payload); - break; - }; - }, - // Calendar - setEvents(state, payload) { - console.log(payload) - state.currentEvent = {start: payload.start, end: payload.end} - }, - // Location - updateLocation(state, value) { - console.log('### mutation: updateLocation', value); - state.activity.location = value; + 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); + switch (payload.result.type) { + case 'person': + state.activity.persons.push(payload.result); + break; + case 'thirdparty': + state.activity.thirdParties.push(payload.result); + break; + case 'user': + state.activity.users.push(payload.result); + break; } + ; + }, + removePersonInvolved(state, payload) { + //console.log('### mutation removePersonInvolved', payload.type); + switch (payload.type) { + case 'person': + state.activity.persons = state.activity.persons.filter(person => person !== payload); + break; + case 'thirdparty': + state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); + break; + case 'user': + state.activity.users = state.activity.users.filter(user => user !== payload); + break; + } + ; + }, + 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); + state.activity.location = value; + } }; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/utils.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/utils.js index 724754bce..d2e35ca04 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/utils.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store/utils.js @@ -1,27 +1,48 @@ const addIdToValue = (string, id) => { - let array = string ? string.split(',') : []; - array.push(id.toString()); - let str = array.join(); - return str; + let array = string ? string.split(',') : []; + array.push(id.toString()); + let str = array.join(); + return str; }; const removeIdFromValue = (string, id) => { - let array = string.split(','); - array = array.filter(el => el !== id.toString()); - let str = array.join(); - return str; + let array = string.split(','); + array = array.filter(el => el !== id.toString()); + let str = array.join(); + return str; }; /* * Assign missing keys for the ConcernedGroups component */ const mapEntity = (entity) => { - Object.assign(entity, {thirdParties: entity.professionals, users: entity.invites}); - return entity; + Object.assign(entity, {thirdParties: entity.professionals, users: entity.invites}); + 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, - removeIdFromValue, - mapEntity + addIdToValue, + calendarRangeToFullCalendarEvent, + removeIdFromValue, + mapEntity, + createUserData, }; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_api/api.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_api/api.js index 7aad8ace2..b2bee8afe 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_api/api.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_api/api.js @@ -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 => { diff --git a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js index 91839e5a2..334230f20 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js +++ b/src/Bundle/ChillMainBundle/Resources/public/module/pick-entity/index.js @@ -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 === '[]'){ diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue index e3991fe2f..6dcca0d8a 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/OnTheFly/components/OnTheFly.vue @@ -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')