From fb26a2e358749bf32e36bcaf125dbfcf578a283e Mon Sep 17 00:00:00 2001 From: Peng DU Date: Wed, 13 Jul 2016 19:12:16 +0200 Subject: [PATCH] add public calendar menu, view, controller, routes and refactoring calldendar config --- .../controllers/admin/calendar.coffee.erb | 37 ++------------- .../javascripts/controllers/calendar.coffee | 32 +++++++++++++ .../controllers/machines.coffee.erb | 47 ++----------------- .../controllers/main_nav.coffee.erb | 5 ++ .../controllers/trainings.coffee.erb | 43 ++--------------- app/assets/javascripts/router.coffee.erb | 18 +++++++ .../javascripts/services/calendar.coffee | 38 +++++++++++++++ app/assets/stylesheets/app.plugins.scss | 2 +- .../templates/calendar/calendar.html.erb | 32 +++++++++++++ .../api/availabilities_controller.rb | 8 ++++ config/locales/app.public.en.yml | 4 ++ config/locales/app.public.fr.yml | 4 ++ config/locales/app.shared.en.yml | 1 + config/locales/app.shared.fr.yml | 1 + config/routes.rb | 1 + 15 files changed, 160 insertions(+), 113 deletions(-) create mode 100644 app/assets/javascripts/controllers/calendar.coffee create mode 100644 app/assets/javascripts/services/calendar.coffee create mode 100644 app/assets/templates/calendar/calendar.html.erb diff --git a/app/assets/javascripts/controllers/admin/calendar.coffee.erb b/app/assets/javascripts/controllers/admin/calendar.coffee.erb index 414c5b1b2..85dd92c1f 100644 --- a/app/assets/javascripts/controllers/admin/calendar.coffee.erb +++ b/app/assets/javascripts/controllers/admin/calendar.coffee.erb @@ -4,8 +4,8 @@ # Controller used in the calendar management page ## -Application.Controllers.controller "AdminCalendarController", ["$scope", "$state", "$uibModal", "moment", "Availability", 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', '_t', 'uiCalendarConfig' -($scope, $state, $uibModal, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, _t, uiCalendarConfig) -> +Application.Controllers.controller "AdminCalendarController", ["$scope", "$state", "$uibModal", "moment", "Availability", 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', '_t', 'uiCalendarConfig', 'CalendarConfig' +($scope, $state, $uibModal, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, _t, uiCalendarConfig, CalendarConfig) -> @@ -17,9 +17,6 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state # The bookings can be positioned every half hours BOOKING_SNAP = '00:30:00' - # The calendar will be initialized positioned under 9:00 AM - DEFAULT_CALENDAR_POSITION = '09:00:00' - # We do not allow the creation of slots that are not a multiple of 60 minutes SLOT_MULTIPLE = 60 @@ -40,33 +37,13 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state textColor: 'black' ## fullCalendar (v2) configuration - $scope.calendarConfig = - timezone: Fablab.timezone - lang: Fablab.fullcalendar_locale - header: - left: 'month agendaWeek' - center: 'title' - right: 'today prev,next' - firstDay: 1 # Week start on monday (France) - scrollTime: DEFAULT_CALENDAR_POSITION + $scope.calendarConfig = CalendarConfig slotDuration: BASE_SLOT snapDuration: BOOKING_SNAP - allDayDefault: false - minTime: "00:00:00" - maxTime: "24:00:00" - height: 'auto' - buttonIcons: - prev: 'left-single-arrow' - next: 'right-single-arrow' - timeFormat: - agenda:'H:mm' - month: 'H(:mm)' - axisFormat: 'H:mm' - - allDaySlot: false - defaultView: 'agendaWeek' selectable: true selecHelper: true + minTime: moment.duration(moment(bookingWindowStart.setting.value).format('HH:mm:ss')) + maxTime: moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')) select: (start, end, jsEvent, view) -> calendarSelectCb(start, end, jsEvent, view) eventClick: (event, jsEvent, view)-> @@ -74,10 +51,6 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state eventRender: (event, element, view) -> eventRenderCb(event, element) - ## fullCalendar time bounds (up & down) - $scope.calendarConfig.minTime = moment.duration(moment(bookingWindowStart.setting.value).format('HH:mm:ss')) - $scope.calendarConfig.maxTime = moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')) - ## diff --git a/app/assets/javascripts/controllers/calendar.coffee b/app/assets/javascripts/controllers/calendar.coffee new file mode 100644 index 000000000..e47fea5b1 --- /dev/null +++ b/app/assets/javascripts/controllers/calendar.coffee @@ -0,0 +1,32 @@ +'use strict' + +## +# Controller used in the public calendar global +## + +Application.Controllers.controller "CalendarController", ["$scope", "$uibModal", "moment", "Availability", 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', '_t', 'uiCalendarConfig', 'CalendarConfig' +($scope, $uibModal, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, _t, uiCalendarConfig, CalendarConfig) -> + + + ### PRIVATE STATIC CONSTANTS ### + + + + ### PUBLIC SCOPE ### + + ## bind the availabilities slots with full-Calendar events + $scope.eventSources = [] + $scope.eventSources.push + url: '/api/availabilities/public' + textColor: 'black' + + ## fullCalendar (v2) configuration + $scope.calendarConfig = CalendarConfig + header: + left: 'month agendaWeek agendaDay' + center: 'title' + right: 'today prev,next' + minTime: moment.duration(moment(bookingWindowStart.setting.value).format('HH:mm:ss')) + maxTime: moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')) + +] diff --git a/app/assets/javascripts/controllers/machines.coffee.erb b/app/assets/javascripts/controllers/machines.coffee.erb index bdde9eb89..79f299d62 100644 --- a/app/assets/javascripts/controllers/machines.coffee.erb +++ b/app/assets/javascripts/controllers/machines.coffee.erb @@ -268,22 +268,13 @@ Application.Controllers.controller "ShowMachineController", ['$scope', '$state', # This controller workflow is pretty similar to the trainings reservation controller. ## -Application.Controllers.controller "ReserveMachineController", ["$scope", "$state", '$stateParams', "$uibModal", '_t', "moment", 'Machine', 'Auth', 'dialogs', '$timeout', 'Price', 'Member', 'Availability', 'Slot', 'Setting', 'CustomAsset', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'uiCalendarConfig', -($scope, $state, $stateParams, $uibModal, _t, moment, Machine, Auth, dialogs, $timeout, Price, Member, Availability, Slot, Setting, CustomAsset, plansPromise, groupsPromise, growl, settingsPromise, uiCalendarConfig) -> +Application.Controllers.controller "ReserveMachineController", ["$scope", "$state", '$stateParams', "$uibModal", '_t', "moment", 'Machine', 'Auth', 'dialogs', '$timeout', 'Price', 'Member', 'Availability', 'Slot', 'Setting', 'CustomAsset', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'uiCalendarConfig', 'CalendarConfig' +($scope, $state, $stateParams, $uibModal, _t, moment, Machine, Auth, dialogs, $timeout, Price, Member, Availability, Slot, Setting, CustomAsset, plansPromise, groupsPromise, growl, settingsPromise, uiCalendarConfig, CalendarConfig) -> ### PRIVATE STATIC CONSTANTS ### - # The calendar is divided in slots of 60 minutes - BASE_SLOT = '01:00:00' - - # The calendar will be initialized positioned under 9:00 AM - DEFAULT_CALENDAR_POSITION = '09:00:00' - - # The user is unable to modify his already booked reservation 1 day before it occurs - PREVENT_BOOKING_MODIFICATION_DELAY = 1 - # Slot already booked by the current user FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::MACHINE_COLOR %>' @@ -340,31 +331,9 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", "$stat $scope.machine = {} ## fullCalendar (v2) configuration - $scope.calendarConfig = - timezone: Fablab.timezone - lang: Fablab.fullcalendar_locale - header: - left: 'month agendaWeek' - center: 'title' - right: 'today prev,next' - firstDay: 1 # Week start on monday (France) - scrollTime: DEFAULT_CALENDAR_POSITION - slotDuration: BASE_SLOT - allDayDefault: false - minTime: '00:00:00' - maxTime: '24:00:00' - height: 'auto' - buttonIcons: - prev: 'left-single-arrow' - next: 'right-single-arrow' - timeFormat: - agenda:'H:mm' - month: 'H(:mm)' - axisFormat: 'H:mm' - - allDaySlot: false - defaultView: 'agendaWeek' - editable: false + $scope.calendarConfig = CalendarConfig + minTime: moment.duration(moment(settingsPromise.booking_window_start).format('HH:mm:ss')) + maxTime: moment.duration(moment(settingsPromise.booking_window_end).format('HH:mm:ss')) eventClick: (event, jsEvent, view) -> calendarEventClickCb(event, jsEvent, view) eventRender: (event, element, view) -> @@ -388,12 +357,6 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", "$stat ## Global config: delay in hours before a booking while the cancellation is forbidden $scope.cancelBookingDelay = parseInt(settingsPromise.booking_cancel_delay) - ## Global config: calendar window in the morning - $scope.calendarConfig.minTime = moment.duration(moment(settingsPromise.booking_window_start).format('HH:mm:ss')) - - ## Global config: calendar window in the evening - $scope.calendarConfig.maxTime = moment.duration(moment(settingsPromise.booking_window_end).format('HH:mm:ss')) - ## diff --git a/app/assets/javascripts/controllers/main_nav.coffee.erb b/app/assets/javascripts/controllers/main_nav.coffee.erb index bfc731048..d5edef990 100644 --- a/app/assets/javascripts/controllers/main_nav.coffee.erb +++ b/app/assets/javascripts/controllers/main_nav.coffee.erb @@ -28,6 +28,11 @@ Application.Controllers.controller "MainNavController", ["$scope", "$location", linkText: 'events_registrations' linkIcon: 'tags' } + { + state: 'app.public.calendar' + linkText: 'public_calendar' + linkIcon: 'calendar' + } { state: 'app.public.projects_list' linkText: 'projects_gallery' diff --git a/app/assets/javascripts/controllers/trainings.coffee.erb b/app/assets/javascripts/controllers/trainings.coffee.erb index 3f364f597..c6d7f2fb3 100644 --- a/app/assets/javascripts/controllers/trainings.coffee.erb +++ b/app/assets/javascripts/controllers/trainings.coffee.erb @@ -51,22 +51,13 @@ Application.Controllers.controller "ShowTrainingController", ['$scope', '$state' # training can be reserved during the reservation process (the shopping cart may contains only one training and a subscription). ## -Application.Controllers.controller "ReserveTrainingController", ["$scope", "$state", '$stateParams', '$filter', '$compile', "$uibModal", 'Auth', 'dialogs', '$timeout', 'Price', 'Availability', 'Slot', 'Member', 'Setting', 'CustomAsset', 'availabilityTrainingsPromise', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'trainingPromise', '_t', 'uiCalendarConfig' -($scope, $state, $stateParams, $filter, $compile, $uibModal, Auth, dialogs, $timeout, Price, Availability, Slot, Member, Setting, CustomAsset, availabilityTrainingsPromise, plansPromise, groupsPromise, growl, settingsPromise, trainingPromise, _t, uiCalendarConfig) -> +Application.Controllers.controller "ReserveTrainingController", ["$scope", "$state", '$stateParams', '$filter', '$compile', "$uibModal", 'Auth', 'dialogs', '$timeout', 'Price', 'Availability', 'Slot', 'Member', 'Setting', 'CustomAsset', 'availabilityTrainingsPromise', 'plansPromise', 'groupsPromise', 'growl', 'settingsPromise', 'trainingPromise', '_t', 'uiCalendarConfig', 'CalendarConfig' +($scope, $state, $stateParams, $filter, $compile, $uibModal, Auth, dialogs, $timeout, Price, Availability, Slot, Member, Setting, CustomAsset, availabilityTrainingsPromise, plansPromise, groupsPromise, growl, settingsPromise, trainingPromise, _t, uiCalendarConfig, CalendarConfig) -> ### PRIVATE STATIC CONSTANTS ### - # The calendar is divided in slots of 60 minutes - BASE_SLOT = '01:00:00' - - # The calendar will be initialized positioned under 9:00 AM - DEFAULT_CALENDAR_POSITION = '09:00:00' - - # The user is unable to modify his already booked reservation 1 day before it occurs - PREVENT_BOOKING_MODIFICATION_DELAY = 1 - # Color of the selected event backgound SELECTED_EVENT_BG_COLOR = '#ffdd00' @@ -117,31 +108,9 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta $scope.training = trainingPromise ## fullCalendar (v2) configuration - $scope.calendarConfig = - timezone: Fablab.timezone - lang: Fablab.fullcalendar_locale - header: - left: 'month agendaWeek' - center: 'title' - right: 'today prev,next' - firstDay: 1 # Week start on monday (France) - scrollTime: DEFAULT_CALENDAR_POSITION - slotDuration: BASE_SLOT - allDayDefault: false - minTime: '00:00:00' - maxTime: '24:00:00' - height: 'auto' - buttonIcons: - prev: 'left-single-arrow' - next: 'right-single-arrow' - timeFormat: - agenda:'H:mm' - month: 'H(:mm)' - axisFormat: 'H:mm' - - allDaySlot: false - defaultView: 'agendaWeek' - editable: false + $scope.calendarConfig = CalendarConfig + minTime: moment.duration(moment(settingsPromise.booking_window_start).format('HH:mm:ss')) + maxTime: moment.duration(moment(settingsPromise.booking_window_end).format('HH:mm:ss')) eventClick: (event, jsEvent, view) -> calendarEventClickCb(event, jsEvent, view) eventAfterAllRender: (view)-> @@ -157,8 +126,6 @@ Application.Controllers.controller "ReserveTrainingController", ["$scope", "$sta $scope.moveBookingDelay = parseInt(settingsPromise.booking_move_delay) $scope.enableBookingCancel = (settingsPromise.booking_cancel_enable == "true") $scope.cancelBookingDelay = parseInt(settingsPromise.booking_cancel_delay) - $scope.calendarConfig.minTime = moment.duration(moment(settingsPromise.booking_window_start).format('HH:mm:ss')) - $scope.calendarConfig.maxTime = moment.duration(moment(settingsPromise.booking_window_end).format('HH:mm:ss')) diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index 9f84e5c03..2b9a36468 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -497,6 +497,24 @@ angular.module('application.router', ['ui.router']). Translations.query(['app.public.events_show', 'app.shared.member_select', 'app.shared.stripe', 'app.shared.valid_reservation_modal']).$promise ] + # calendar global (trainings, machines and events) + .state 'app.public.calendar', + url: '/calendar' + views: + 'main@': + templateUrl: '<%= asset_path "calendar/calendar.html" %>' + controller: 'CalendarController' + resolve: + bookingWindowStart: ['Setting', (Setting)-> + Setting.get(name: 'booking_window_start').$promise + ] + bookingWindowEnd: ['Setting', (Setting)-> + Setting.get(name: 'booking_window_end').$promise + ] + translations: [ 'Translations', (Translations) -> + Translations.query(['app.public.calendar']).$promise + ] + # --- namespace /admin/... --- # calendar .state 'app.admin.calendar', diff --git a/app/assets/javascripts/services/calendar.coffee b/app/assets/javascripts/services/calendar.coffee new file mode 100644 index 000000000..61af184d6 --- /dev/null +++ b/app/assets/javascripts/services/calendar.coffee @@ -0,0 +1,38 @@ +'use strict' + +Application.Services.factory 'CalendarConfig', [-> + (options = {}) -> + # The calendar is divided in slots of 1 hour + BASE_SLOT = '01:00:00' + + # The calendar will be initialized positioned under 9:00 AM + DEFAULT_CALENDAR_POSITION = '09:00:00' + + defaultOptions = + timezone: Fablab.timezone + lang: Fablab.fullcalendar_locale + header: + left: 'month agendaWeek' + center: 'title' + right: 'today prev,next' + firstDay: 1 # Week start on monday (France) + scrollTime: DEFAULT_CALENDAR_POSITION + slotDuration: BASE_SLOT + allDayDefault: false + minTime: "00:00:00" + maxTime: "24:00:00" + height: 'auto' + buttonIcons: + prev: 'left-single-arrow' + next: 'right-single-arrow' + timeFormat: + agenda:'H:mm' + month: 'H(:mm)' + axisFormat: 'H:mm' + + allDaySlot: false + defaultView: 'agendaWeek' + editable: false + + Object.assign({}, defaultOptions, options) +] diff --git a/app/assets/stylesheets/app.plugins.scss b/app/assets/stylesheets/app.plugins.scss index 9d39c291c..0032e8a7a 100644 --- a/app/assets/stylesheets/app.plugins.scss +++ b/app/assets/stylesheets/app.plugins.scss @@ -91,7 +91,7 @@ cursor: pointer; z-index: 9999; text-align: right; - .training-reserve &, .machine-reserve & { display: none; } + .training-reserve &, .machine-reserve &, .public-calendar & { display: none; } } .fc-v-event.fc-end { diff --git a/app/assets/templates/calendar/calendar.html.erb b/app/assets/templates/calendar/calendar.html.erb new file mode 100644 index 000000000..ef13482cd --- /dev/null +++ b/app/assets/templates/calendar/calendar.html.erb @@ -0,0 +1,32 @@ +
+
+
+
+ +
+
+
+
+

{{ 'calendar' }}

+
+
+ +
+
+ {{ 'trainings' }} + {{ 'machines' }} + {{ 'events' }} +
+
+ +
+
+ + +
+ +
+
+
+ +
diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index c5e4b5cd8..e7d93c597 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -14,6 +14,14 @@ class API::AvailabilitiesController < API::ApiController .where('start_at >= ? AND end_at <= ?', start_date, end_date) end + def public + start_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:start]) + end_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:end]).end_of_day + @availabilities = Availability.includes(:machines,:tags,:trainings).where.not(available_type: 'event') + .where('start_at >= ? AND end_at <= ?', start_date, end_date) + render :index + end + def show authorize Availability end diff --git a/config/locales/app.public.en.yml b/config/locales/app.public.en.yml index 8bf99007c..7f3780c48 100644 --- a/config/locales/app.public.en.yml +++ b/config/locales/app.public.en.yml @@ -32,6 +32,7 @@ en: events_registrations: "Events registrations" projects_gallery: "Projects gallery" subscriptions: "Subscriptions" + public_calendar: "Calendar" # left menu (admin) trainings_monitoring: "Trainings monitoring" @@ -227,3 +228,6 @@ en: book: "Book" change_the_reservation: "Change the reservation" you_can_shift_this_reservation_on_the_following_slots: "You can shift this reservation on the following slots:" + + calendar: + calendar: "Calendar" diff --git a/config/locales/app.public.fr.yml b/config/locales/app.public.fr.yml index 838a80c2d..c23fd97a7 100644 --- a/config/locales/app.public.fr.yml +++ b/config/locales/app.public.fr.yml @@ -32,6 +32,7 @@ fr: events_registrations: "Inscriptions aux évènements" projects_gallery: "Galerie de projets" subscriptions: "Abonnements" + public_calendar: "Calendrier" # menu de gauche (partie admin) trainings_monitoring: "Suivi formations" @@ -229,3 +230,6 @@ fr: book: "Réserver" change_the_reservation: "Modifier la réservation" you_can_shift_this_reservation_on_the_following_slots: "Vous pouvez déplacer cette réservation sur les créneaux suivants :" + + calendar: + calendar: "Calendrier" diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index 2ec91ab08..085df0b1a 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -29,6 +29,7 @@ en: confirmation_required: "Confirmation required" description: "Description" machines: "Machines" + events: "Events" materials: "Materials" date: "Date" price: "Price" diff --git a/config/locales/app.shared.fr.yml b/config/locales/app.shared.fr.yml index 4d01c6fa5..49372cdde 100644 --- a/config/locales/app.shared.fr.yml +++ b/config/locales/app.shared.fr.yml @@ -29,6 +29,7 @@ fr: confirmation_required: "Confirmation requise" description: "Description" machines: "Machines" + events: "Events" materials: "Matériaux" date: "Date" price: "Prix" diff --git a/config/routes.rb b/config/routes.rb index 0707c695b..2e9b80b13 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -66,6 +66,7 @@ Rails.application.routes.draw do get 'machines/:machine_id', action: 'machine', on: :collection get 'trainings/:training_id', action: 'trainings', on: :collection get 'reservations', on: :member + get 'public', on: :collection end resources :groups, only: [:index, :create, :update, :destroy]