fetch remote calendar and show on FullCalendar frame

This commit is contained in:
Julien Fastré 2022-05-23 15:00:32 +02:00
parent e2052fe71d
commit f825c69ce5
9 changed files with 151 additions and 30 deletions

View File

@ -269,6 +269,10 @@ class CalendarController extends AbstractController
*/
public function newAction(Request $request): Response
{
if (!$this->remoteCalendarConnector->isReady()) {
return $this->remoteCalendarConnector->getMakeReadyResponse($request->getUri());
}
$view = null;
$em = $this->getDoctrine()->getManager();

View File

@ -13,6 +13,8 @@ namespace Chill\CalendarBundle\Controller;
use Chill\CalendarBundle\RemoteCalendar\Connector\RemoteCalendarConnectorInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Serializer\Model\Collection;
use DateTimeImmutable;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@ -30,8 +32,11 @@ class RemoteCalendarProxyController
private SerializerInterface $serializer;
public function __construct(RemoteCalendarConnectorInterface $remoteCalendarConnector, SerializerInterface $serializer)
private PaginatorFactory $paginatorFactory;
public function __construct(PaginatorFactory $paginatorFactory, RemoteCalendarConnectorInterface $remoteCalendarConnector, SerializerInterface $serializer)
{
$this->paginatorFactory = $paginatorFactory;
$this->remoteCalendarConnector = $remoteCalendarConnector;
$this->serializer = $serializer;
}
@ -41,30 +46,38 @@ class RemoteCalendarProxyController
*/
public function listEventForCalendar(User $user, Request $request): Response
{
if ($request->query->has('startDate')) {
$startDate = DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s', $request->query->get('startDate') . 'T00:00:00');
if (false === $startDate) {
throw new BadRequestHttpException('startDate on bad format');
}
} else {
throw new BadRequestHttpException('startDate not provided');
if (!$request->query->has('dateFrom')) {
throw new BadRequestHttpException('You must provide a dateFrom parameter');
}
if ($request->query->has('endDate')) {
$endDate = DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s', $request->query->get('endDate') . 'T23:59:59');
if (false === $endDate) {
throw new BadRequestHttpException('endDate on bad format');
}
} else {
throw new BadRequestHttpException('endDate not provided');
if (false === $dateFrom = DateTimeImmutable::createFromFormat(
DateTimeImmutable::ATOM,
$request->query->get('dateFrom')
)) {
throw new BadRequestHttpException('dateFrom not parsable');
}
$events = $this->remoteCalendarConnector->listEventsForUser($user, $startDate, $endDate);
if (!$request->query->has('dateTo')) {
throw new BadRequestHttpException('You must provide a dateTo parameter');
}
if (false === $dateTo = DateTimeImmutable::createFromFormat(
DateTimeImmutable::ATOM,
$request->query->get('dateTo')
)) {
throw new BadRequestHttpException('dateTo not parsable');
}
$events = $this->remoteCalendarConnector->listEventsForUser($user, $dateFrom, $dateTo);
$paginator = $this->paginatorFactory->create(count($events));
if (count($events) > 0) {
$paginator->setItemsPerPage($paginator->getTotalItems());
}
$collection = new Collection($events, $paginator);
return new JsonResponse(
$this->serializer->serialize($events, 'json', ['groups' => ['read']]),
$this->serializer->serialize($collection, 'json', ['groups' => ['read']]),
JsonResponse::HTTP_OK,
[],
true

View File

@ -35,7 +35,7 @@ export default {
},
remoteShow: {
set (value) {
this.$store.commit('showUserOnCalendar', {user: this.user, remote: value});
this.$store.commit('showUserOnCalendar', {user: this.user, remotes: value});
},
get() {
return this.$store.getters.isRemoteShownOnCalendarForUser(this.user);

View File

@ -33,7 +33,16 @@ const fetchCalendarRangeForUser = (user, start, end) => {
return fetchResults(uri, {dateFrom, dateTo});
}
const fetchCalendarRemoteForUser = (user, start, end) => {
const uri = `/api/1.0/calendar/proxy/calendar/by-user/${user.id}/events`;
const dateFrom = datetimeToISO(start);
const dateTo = datetimeToISO(end);
return fetchResults(uri, {dateFrom, dateTo});
}
export {
whoami,
fetchCalendarRangeForUser,
fetchCalendarRemoteForUser,
};

View File

@ -4,7 +4,10 @@ import {
removeIdFromValue,
mapEntity
} from './utils';
import {fetchCalendarRangeForUser} from './../api';
import {
fetchCalendarRangeForUser,
fetchCalendarRemoteForUser,
} from './../api';
export default {
setCurrentDatesView({ commit, dispatch }, {start, end}) {
@ -21,8 +24,16 @@ export default {
for (const uid of state.currentView.users.keys()) {
console.log('fetchCalendarEventsFor', uid);
promises.push(
dispatch('fetchCalendarRangeForUser',
{user: state.usersData.get(uid).user, start: state.currentView.start, end: state.currentView.end})
dispatch(
'fetchCalendarRangeForUser',
{user: state.usersData.get(uid).user, start: state.currentView.start, end: state.currentView.end}
)
);
promises.push(
dispatch(
'fetchCalendarRemotesForUser',
{user: state.usersData.get(uid).user, start: state.currentView.start, end: state.currentView.end}
)
);
}
@ -37,6 +48,15 @@ export default {
});
}
},
fetchCalendarRemotesForUser({ commit, getters }, { user, start, end }) {
if (!getters.isCalendarRemoteLoadedForUser({user, start, end})) {
return fetchCalendarRemoteForUser(user, start, end).then((remotes) => {
commit('addCalendarRemotesForUser', {user, remotes, start, end});
return Promise.resolve();
});
}
},
addPersonsInvolved({ commit, dispatch }, payload) {
console.log('### action addPersonsInvolved', payload.result.type);
switch (payload.result.type) {
@ -51,7 +71,7 @@ export default {
case 'user':
let aUsers = document.getElementById("chill_activitybundle_activity_users");
aUsers.value = addIdToValue(aUsers.value, payload.result.id);
commit('showUserOnCalendar', {user: payload.result, ranges: false, remote: true});
commit('showUserOnCalendar', {user: payload.result, ranges: false, remotes: true});
dispatch('fetchCalendarEvents');
break;
};

View File

@ -47,7 +47,7 @@ export default {
if (kinds.ranges && userData.calendarRanges.length > 0) {
console.log('adding ranges for user', userId);
const s = {
'id': `ranges_${userId}`,
id: `ranges_${userId}`,
events: userData.calendarRanges,
color: userData.mainColor,
backgroundColor: 'white',
@ -61,6 +61,22 @@ export default {
} else {
console.log('not adding ranges for user', userId);
}
if (kinds.remotes && userData.remotes.length > 0) {
console.log('adding remotes for user', userId);
const s = {
'id': `remote_${userId}`,
events: userData.remotes,
color: userData.mainColor,
textColor: 'black',
editable: false,
};
console.log('remote source', s);
sources.push(s);
} else {
console.log('not adding remotes for user', userId);
}
}
console.log('eventSources', sources);
@ -112,6 +128,27 @@ export default {
return false;
},
/**
* return true if there was a fetch query for event between this date (start and end),
* those date are included.
*
* @param state
* @param getters
* @returns {(function({user: *, start: *, end: *}): (boolean))|*}
*/
isCalendarRemoteLoadedForUser: (state, getters) => ({user, start, end}) => {
if (!getters.hasUserData(user)) {
return false;
}
for (let interval of getters.getUserData(user).remotesLoaded) {
if (start >= interval.start && end <= interval.end) {
return true;
}
}
return false;
},
/**
* return true if the user ranges are shown on calendar
*
@ -142,7 +179,7 @@ export default {
return false;
}
return k.remote;
return k.remotes;
},

View File

@ -54,7 +54,7 @@ whoami().then(me => {
});
if (null !== store.getters.getMainUser) {
store.commit('showUserOnCalendar', {ranges: true, remote: true, user: store.getters.getMainUser});
store.commit('showUserOnCalendar', {ranges: true, remotes: true, user: store.getters.getMainUser});
}
export default store;

View File

@ -1,4 +1,8 @@
import {createUserData, calendarRangeToFullCalendarEvent} from './utils';
import {
createUserData,
calendarRangeToFullCalendarEvent,
remoteToFullCalendarEvent,
} from './utils';
export default {
setWhoAmiI(state, me) {
@ -8,7 +12,7 @@ export default {
state.currentView.start = start;
state.currentView.end = end;
},
showUserOnCalendar(state, {user, ranges, remote}) {
showUserOnCalendar(state, {user, ranges, remotes}) {
if (!state.usersData.has(user.id)) {
state.usersData.set(user.id, createUserData(user, state.usersData.size));
}
@ -19,7 +23,7 @@ export default {
user.id,
{
ranges: typeof ranges !== 'undefined' ? ranges : cur.ranges,
remote: typeof remote !== 'undefined' ? remote : cur.remote,
remotes: typeof remotes !== 'undefined' ? remotes : cur.remotes,
}
);
},
@ -85,6 +89,27 @@ export default {
userData.calendarRanges = userData.calendarRanges.concat(eventRanges);
userData.calendarRangesLoaded.push({start, end});
},
addCalendarRemotesForUser(state, {user, remotes, start, end}) {
let userData;
if (state.usersData.has(user.id)) {
userData = state.usersData.get(user.id);
} else {
userData = createUserData(user, state.usersData.size);
state.usersData.set(user.id, userData);
}
const eventRemotes = remotes
.filter(r => !state.existingEvents.has(`remote_${r.id}`))
.map(r => {
// add to existing ids
state.existingEvents.add(`remote_${r.id}`);
return r;
})
.map(r => remoteToFullCalendarEvent(r));
userData.remotes = userData.remotes.concat(eventRemotes);
userData.remotesLoaded.push({start, end});
},
/*
// Calendar
setEvents(state, payload) {

View File

@ -29,6 +29,8 @@ const createUserData = (user, colorIndex) => {
user: user,
calendarRanges: [],
calendarRangesLoaded: [],
remotes: [],
remotesLoaded: [],
mainColor: COLORS[colorId],
}
}
@ -44,10 +46,21 @@ const calendarRangeToFullCalendarEvent = (entity) => {
};
}
const remoteToFullCalendarEvent = (entity) => {
return {
id: `range_${entity.id}`,
title: entity.title,
start: entity.startDate.datetime8601,
end: entity.endDate.datetime8601,
allDay: false,
};
}
export {
addIdToValue,
calendarRangeToFullCalendarEvent,
removeIdFromValue,
remoteToFullCalendarEvent,
mapEntity,
createUserData,
};