1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-29 18:52:22 +01:00

fix spaces reservation calendar

This commit is contained in:
Sylvain 2020-10-05 12:12:22 +02:00
parent 5a0185dd48
commit d701260fae
5 changed files with 61 additions and 44 deletions

View File

@ -307,8 +307,8 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
* per slots. * per slots.
*/ */
Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateParams', 'Auth', '$timeout', 'Availability', 'Member', 'availabilitySpacesPromise', 'plansPromise', 'groupsPromise', 'settingsPromise', 'spacePromise', '_t', 'uiCalendarConfig', 'CalendarConfig', Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateParams', 'Auth', '$timeout', 'Availability', 'Member', 'plansPromise', 'groupsPromise', 'settingsPromise', 'spacePromise', '_t', 'uiCalendarConfig', 'CalendarConfig',
function ($scope, $stateParams, Auth, $timeout, Availability, Member, availabilitySpacesPromise, plansPromise, groupsPromise, settingsPromise, spacePromise, _t, uiCalendarConfig, CalendarConfig) { function ($scope, $stateParams, Auth, $timeout, Availability, Member, plansPromise, groupsPromise, settingsPromise, spacePromise, _t, uiCalendarConfig, CalendarConfig) {
/* PRIVATE STATIC CONSTANTS */ /* PRIVATE STATIC CONSTANTS */
// Color of the selected event backgound // Color of the selected event backgound
@ -323,7 +323,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
/* PUBLIC SCOPE */ /* PUBLIC SCOPE */
// bind the spaces availabilities with full-Calendar events // bind the spaces availabilities with full-Calendar events
$scope.eventSources = [ { events: availabilitySpacesPromise, textColor: 'black' } ]; $scope.eventSources = [];
// the user to deal with, ie. the current user for non-admins // the user to deal with, ie. the current user for non-admins
$scope.ctrl = $scope.ctrl =
@ -394,7 +394,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
*/ */
$scope.markSlotAsAdded = function () { $scope.markSlotAsAdded = function () {
$scope.selectedEvent.backgroundColor = SELECTED_EVENT_BG_COLOR; $scope.selectedEvent.backgroundColor = SELECTED_EVENT_BG_COLOR;
return updateCalendar(); updateEvents($scope.selectedEvent);
}; };
/** /**
@ -404,13 +404,13 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
slot.backgroundColor = 'white'; slot.backgroundColor = 'white';
slot.title = ''; slot.title = '';
slot.borderColor = FREE_SLOT_BORDER_COLOR; slot.borderColor = FREE_SLOT_BORDER_COLOR;
slot.id = null; slot.slot_id = null;
slot.isValid = false; slot.isValid = false;
slot.is_reserved = false; slot.is_reserved = false;
slot.can_modify = false; slot.can_modify = false;
slot.offered = false; slot.offered = false;
if (slot.is_completed) { slot.is_completed = false; } if (slot.is_completed) { slot.is_completed = false; }
return updateCalendar(); updateEvents(slot);
}; };
/** /**
@ -424,50 +424,58 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
$scope.markSlotAsModifying = function () { $scope.markSlotAsModifying = function () {
$scope.selectedEvent.backgroundColor = '#eee'; $scope.selectedEvent.backgroundColor = '#eee';
$scope.selectedEvent.title = _t('app.logged.space_reserve.i_change'); $scope.selectedEvent.title = _t('app.logged.space_reserve.i_change');
return updateCalendar(); updateEvents($scope.selectedEvent);
}; };
/** /**
* Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place' * Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
*/ */
$scope.changeModifyTrainingSlot = function () { $scope.changeModifySpaceSlot = function () {
if ($scope.events.placable) { if ($scope.events.placable) {
$scope.events.placable.backgroundColor = 'white'; $scope.events.placable.backgroundColor = 'white';
$scope.events.placable.title = ''; $scope.events.placable.title = '';
updateEvents($scope.events.placable);
} }
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) { if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
$scope.selectedEvent.backgroundColor = '#bbb'; $scope.selectedEvent.backgroundColor = '#bbb';
$scope.selectedEvent.title = _t('app.logged.space_reserve.i_shift'); $scope.selectedEvent.title = _t('app.logged.space_reserve.i_shift');
updateEvents($scope.selectedEvent);
} }
return updateCalendar();
}; };
/** /**
* When modifying an already booked reservation, callback when the modification was successfully done. * When modifying an already booked reservation, callback when the modification was successfully done.
*/ */
$scope.modifyTrainingSlot = function () { $scope.modifySpaceSlot = function () {
$scope.events.placable.title = _t('app.logged.space_reserve.i_ve_reserved'); const save = {
$scope.events.placable.backgroundColor = 'white'; slotId: $scope.events.modifiable.slot_id,
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor; borderColor: $scope.events.modifiable.borderColor,
$scope.events.placable.id = $scope.events.modifiable.id; user: angular.copy($scope.events.modifiable.user),
$scope.events.placable.is_reserved = true; title: _t('app.logged.space_reserve.i_ve_reserved')
$scope.events.placable.can_modify = true; };
$scope.events.modifiable.backgroundColor = 'white'; $scope.events.modifiable.backgroundColor = 'white';
$scope.events.modifiable.title = ''; $scope.events.modifiable.title = '';
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR; $scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR;
$scope.events.modifiable.id = null; $scope.events.modifiable.slot_id = null;
$scope.events.modifiable.is_reserved = false; $scope.events.modifiable.is_reserved = false;
$scope.events.modifiable.can_modify = false; $scope.events.modifiable.can_modify = false;
if ($scope.events.modifiable.is_completed) { $scope.events.modifiable.is_completed = false; } if ($scope.events.modifiable.is_completed) { $scope.events.modifiable.is_completed = false; }
updateEvents($scope.events.modifiable);
return updateCalendar(); $scope.events.placable.title = save.title;
$scope.events.placable.backgroundColor = 'white';
$scope.events.placable.borderColor = save.borderColor;
$scope.events.placable.slot_id = save.slotId;
$scope.events.placable.is_reserved = true;
$scope.events.placable.can_modify = true;
updateEvents($scope.events.placable);
}; };
/** /**
* Cancel the current booking modification, reseting the whole process * Cancel the current booking modification, reseting the whole process
*/ */
$scope.cancelModifyTrainingSlot = function () { $scope.cancelModifySpaceSlot = function () {
if ($scope.events.placable) { if ($scope.events.placable) {
$scope.events.placable.backgroundColor = 'white'; $scope.events.placable.backgroundColor = 'white';
$scope.events.placable.title = ''; $scope.events.placable.title = '';
@ -475,7 +483,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
$scope.events.modifiable.title = _t('app.logged.space_reserve.i_ve_reserved'); $scope.events.modifiable.title = _t('app.logged.space_reserve.i_ve_reserved');
$scope.events.modifiable.backgroundColor = 'white'; $scope.events.modifiable.backgroundColor = 'white';
return updateCalendar(); updateEvents($scope.events.placable, $scope.events.modifiable);
}; };
/** /**
@ -544,7 +552,8 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
spaceSlot.title = _t('app.logged.space_reserve.i_ve_reserved'); spaceSlot.title = _t('app.logged.space_reserve.i_ve_reserved');
spaceSlot.backgroundColor = 'white'; spaceSlot.backgroundColor = 'white';
spaceSlot.borderColor = RESERVED_SLOT_BORDER_COLOR; spaceSlot.borderColor = RESERVED_SLOT_BORDER_COLOR;
return updateSpaceSlotId(spaceSlot, reservation); updateSpaceSlotId(spaceSlot, reservation);
updateEvents(spaceSlot);
}); });
if ($scope.selectedPlan) { if ($scope.selectedPlan) {
@ -558,7 +567,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits); Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits); Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
return refetchCalendar(); refetchCalendar();
}; };
/** /**
@ -573,8 +582,18 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
*/ */
const initialize = function () { const initialize = function () {
if ($scope.currentUser.role !== 'admin') { if ($scope.currentUser.role !== 'admin') {
return Member.get({ id: $scope.currentUser.id }, function (member) { $scope.ctrl.member = member; }); Member.get({ id: $scope.currentUser.id }, function (member) { $scope.ctrl.member = member; });
} }
// we load the availabilities from a callback function of the $scope.eventSources, instead of resolving a promise
// in the router because this allows to refetchEvents from fullCalendar API.
$scope.eventSources.push({
events: function (start, end, timezone, callback) {
Availability.spaces({ spaceId: $stateParams.id }, function (availabilities) {
callback(availabilities);
});
},
textColor: 'black'
});
}; };
/** /**
@ -584,12 +603,9 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
* if it's too late). * if it's too late).
* @see http://fullcalendar.io/docs/mouse/eventClick/ * @see http://fullcalendar.io/docs/mouse/eventClick/
*/ */
var calendarEventClickCb = function (event, jsEvent, view) { const calendarEventClickCb = function (event, jsEvent, view) {
$scope.selectedEvent = event; $scope.selectedEvent = event;
if ($stateParams.id === 'all') { $scope.selectionTime = new Date();
$scope.training = event.training;
}
return $scope.selectionTime = new Date();
}; };
/** /**
@ -597,7 +613,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
* Append the event tag into the block, just after the event title. * Append the event tag into the block, just after the event title.
* @see http://fullcalendar.io/docs/event_rendering/eventRender/ * @see http://fullcalendar.io/docs/event_rendering/eventRender/
*/ */
var eventRenderCb = function (event, element, view) { const eventRenderCb = function (event, element, view) {
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) { if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
let html = ''; let html = '';
for (let tag of Array.from(event.tags)) { for (let tag of Array.from(event.tags)) {
@ -613,27 +629,29 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
* @param slot {Object} * @param slot {Object}
* @param reservation {Object} * @param reservation {Object}
*/ */
var updateSpaceSlotId = function (slot, reservation) { const updateSpaceSlotId = function (slot, reservation) {
angular.forEach(reservation.slots, function (s) { angular.forEach(reservation.slots, function (s) {
if (slot.start_at === slot.start_at) { if (slot.start.isSame(s.start_at)) {
return slot.id = s.id; slot.slot_id = s.id;
} }
}); });
}; };
/** /**
* Update the calendar's display to render the new attributes of the events * Update the calendar's display to render the new attributes of the events
* @param events Object[] events to update in full-calendar
*/ */
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents'); }; const updateEvents = function (...events) {
const realEvents = events.filter(e => !_.isNil(e));
uiCalendarConfig.calendars.calendar.fullCalendar('updateEvents', realEvents);
};
/** /**
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events * Asynchronously fetch the events from the API and refresh the calendar's view with these new events
*/ */
var refetchCalendar = function () { const refetchCalendar = function () {
$timeout(function () { uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents');
});
}; };
// !!! MUST BE CALLED AT THE END of the controller // !!! MUST BE CALLED AT THE END of the controller

View File

@ -440,7 +440,7 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
} else if ($scope.slot.is_reserved && (slotCanBeModified($scope.slot) || slotCanBeCanceled($scope.slot)) && !$scope.events.modifiable && ($scope.events.reserved.length === 0)) { } else if ($scope.slot.is_reserved && (slotCanBeModified($scope.slot) || slotCanBeCanceled($scope.slot)) && !$scope.events.modifiable && ($scope.events.reserved.length === 0)) {
// slot is reserved and is ok to be modified or cancelled // slot is reserved and is ok to be modified or cancelled
// but we are not currently running a modification or having any slots in the cart // but we are not currently running a modification or having any slots in the cart
// -> first the affect the modification/cancellation rights attributes to the current slot // -> first affect the modification/cancellation rights attributes to the current slot
resetCartState(); resetCartState();
$scope.slot.movable = slotCanBeModified($scope.slot); $scope.slot.movable = slotCanBeModified($scope.slot);
$scope.slot.cancelable = slotCanBeCanceled($scope.slot); $scope.slot.cancelable = slotCanBeCanceled($scope.slot);

View File

@ -433,7 +433,6 @@ angular.module('application.router', ['ui.router'])
}, },
resolve: { resolve: {
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }], spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }],
availabilitySpacesPromise: ['Availability', '$stateParams', function (Availability, $stateParams) { return Availability.spaces({ spaceId: $stateParams.id }).$promise; }],
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }], plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }], groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
settingsPromise: ['Setting', function (Setting) { settingsPromise: ['Setting', function (Setting) {

View File

@ -40,9 +40,9 @@
on-slot-added-to-cart="markSlotAsAdded" on-slot-added-to-cart="markSlotAsAdded"
on-slot-removed-from-cart="markSlotAsRemoved" on-slot-removed-from-cart="markSlotAsRemoved"
on-slot-start-to-modify="markSlotAsModifying" on-slot-start-to-modify="markSlotAsModifying"
on-slot-modify-success="modifyTrainingSlot" on-slot-modify-success="modifySpaceSlot"
on-slot-modify-cancel="cancelModifyTrainingSlot" on-slot-modify-cancel="cancelModifySpaceSlot"
on-slot-modify-unselect="changeModifyTrainingSlot" on-slot-modify-unselect="changeModifySpaceSlot"
on-slot-cancel-success="slotCancelled" on-slot-cancel-success="slotCancelled"
after-payment="afterPayment" after-payment="afterPayment"
reservable-id="{{space.id}}" reservable-id="{{space.id}}"

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
json.array!(@slots) do |slot| json.array!(@slots) do |slot|
json.id slot.id if slot.id json.slot_id slot.id if slot.id
json.can_modify slot.can_modify json.can_modify slot.can_modify
json.title slot.title json.title slot.title
json.start slot.start_at.iso8601 json.start slot.start_at.iso8601