mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
filter calendar by machine/formation/event or disponible
This commit is contained in:
parent
0b1a19cd76
commit
70d623f65a
@ -4,52 +4,54 @@
|
||||
# Controller used in the public calendar global
|
||||
##
|
||||
|
||||
Application.Controllers.controller "CalendarController", ["$scope", "$state", "$uibModal", "moment", "Availability", 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', '_t', 'uiCalendarConfig', 'CalendarConfig'
|
||||
($scope, $state, $uibModal, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, _t, uiCalendarConfig, CalendarConfig) ->
|
||||
Application.Controllers.controller "CalendarController", ["$scope", "$state", "$uibModal", "moment", "Availability", 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', '_t', 'uiCalendarConfig', 'CalendarConfig', 'trainingsPromise', 'machinesPromise',
|
||||
($scope, $state, $uibModal, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, _t, uiCalendarConfig, CalendarConfig, trainingsPromise, machinesPromise) ->
|
||||
|
||||
|
||||
### PRIVATE STATIC CONSTANTS ###
|
||||
availableTypes = ['machines', 'training', 'event']
|
||||
availabilitySource =
|
||||
url: "/api/availabilities/public?#{$.param({available_type: availableTypes})}"
|
||||
textColor: 'black'
|
||||
currentMachineEvent = null
|
||||
machinesPromise.forEach((m) -> m.checked = true)
|
||||
trainingsPromise.forEach((t) -> t.checked = true)
|
||||
|
||||
|
||||
### PUBLIC SCOPE ###
|
||||
|
||||
## List of trainings
|
||||
$scope.trainings = trainingsPromise
|
||||
|
||||
## List of machines
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
## variable for filter event
|
||||
$scope.evt = true
|
||||
|
||||
## variable for show/hidden slot no dispo
|
||||
$scope.dispo = true
|
||||
|
||||
## add availabilities source to event sources
|
||||
$scope.eventSources = []
|
||||
|
||||
## fullCalendar (v2) configuration
|
||||
$scope.calendarConfig = CalendarConfig
|
||||
events: availabilitySource.url
|
||||
slotEventOverlap: true
|
||||
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'))
|
||||
eventClick: (event, jsEvent, view)->
|
||||
calendarEventClickCb(event, jsEvent, view)
|
||||
viewRender: (view, element) ->
|
||||
viewRenderCb(view, element)
|
||||
eventRender: (event, element, view) ->
|
||||
eventRenderCb(event, element)
|
||||
## filter availabilities if have change
|
||||
$scope.filterAvailabilities = ->
|
||||
$scope.filter =
|
||||
trainings: $scope.isSelectAll('trainings')
|
||||
machines: $scope.isSelectAll('machines')
|
||||
$scope.calendarConfig.events = availabilitySourceUrl()
|
||||
|
||||
$scope.filterAvailableType = (type) ->
|
||||
index = availableTypes.indexOf(type)
|
||||
if index != -1
|
||||
availableTypes.splice(index, 1)
|
||||
else
|
||||
availableTypes.push(type)
|
||||
availabilitySource.url = "/api/availabilities/public?#{$.param({available_type: availableTypes})}"
|
||||
$scope.calendarConfig.events = availabilitySource.url
|
||||
## check all formation/machine is select in filter
|
||||
$scope.isSelectAll = (type) ->
|
||||
$scope[type].length == $scope[type].filter((t) -> t.checked).length
|
||||
|
||||
## a variable for formation/machine checkbox is or not checked
|
||||
$scope.filter =
|
||||
trainings: $scope.isSelectAll('trainings')
|
||||
machines: $scope.isSelectAll('machines')
|
||||
|
||||
## toggle to select all formation/machine
|
||||
$scope.toggleFilter = (type) ->
|
||||
$scope[type].forEach((t) -> t.checked = $scope.filter[type])
|
||||
$scope.filterAvailabilities()
|
||||
|
||||
$scope.isAvailableTypeInactive = (type) ->
|
||||
index = availableTypes.indexOf(type)
|
||||
index == -1 ? true : false
|
||||
|
||||
### PRIVATE SCOPE ###
|
||||
|
||||
@ -98,4 +100,36 @@ Application.Controllers.controller "CalendarController", ["$scope", "$state", "$
|
||||
html += "<span class='label label-success text-white'>#{tag.name}</span> "
|
||||
element.find('.fc-title').append("<br/>"+html)
|
||||
return
|
||||
|
||||
getFilter = ->
|
||||
t = $scope.trainings.filter((t) -> t.checked).map((t) -> t.id)
|
||||
m = $scope.machines.filter((m) -> m.checked).map((m) -> m.id)
|
||||
{t: t, m: m, evt: $scope.evt, dispo: $scope.dispo}
|
||||
|
||||
availabilitySourceUrl = ->
|
||||
"/api/availabilities/public?#{$.param(getFilter())}"
|
||||
|
||||
initialize = ->
|
||||
## fullCalendar (v2) configuration
|
||||
$scope.calendarConfig = CalendarConfig
|
||||
events: availabilitySourceUrl()
|
||||
slotEventOverlap: true
|
||||
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'))
|
||||
eventClick: (event, jsEvent, view)->
|
||||
calendarEventClickCb(event, jsEvent, view)
|
||||
viewRender: (view, element) ->
|
||||
viewRenderCb(view, element)
|
||||
eventRender: (event, element, view) ->
|
||||
eventRenderCb(event, element)
|
||||
|
||||
|
||||
|
||||
|
||||
## !!! MUST BE CALLED AT THE END of the controller
|
||||
initialize()
|
||||
]
|
||||
|
@ -511,6 +511,12 @@ angular.module('application.router', ['ui.router']).
|
||||
bookingWindowEnd: ['Setting', (Setting)->
|
||||
Setting.get(name: 'booking_window_end').$promise
|
||||
]
|
||||
trainingsPromise: ['Training', (Training)->
|
||||
Training.query().$promise
|
||||
]
|
||||
machinesPromise: ['Machine', (Machine)->
|
||||
Machine.query().$promise
|
||||
]
|
||||
translations: [ 'Translations', (Translations) ->
|
||||
Translations.query(['app.public.calendar']).$promise
|
||||
]
|
||||
|
@ -12,14 +12,10 @@
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper calendar-filter">
|
||||
<div>
|
||||
<i class="fa fa-filter"></i>
|
||||
<span translate>{{ 'filter' }}</span>
|
||||
</div>
|
||||
<span class="badge text-sm bg-formation" ng-class="{'inactive': isAvailableTypeInactive('training')}" translate ng-click="filterAvailableType('training')">{{ 'trainings' }}</span>
|
||||
<span class="badge text-sm bg-machine" ng-class="{'inactive': isAvailableTypeInactive('machines')}" translate ng-click="filterAvailableType('machines')">{{ 'machines' }}</span>
|
||||
<span class="badge text-sm bg-event" ng-class="{'inactive': isAvailableTypeInactive('event')}" translate ng-click="filterAvailableType('event')">{{ 'events' }}</span>
|
||||
<section class="heading-actions wrapper">
|
||||
<span class="badge text-sm bg-formation m-t" translate>{{ 'trainings' }}</span>
|
||||
<span class="badge text-sm bg-machine" translate>{{ 'machines' }}</span>
|
||||
<span class="badge text-sm bg-event" translate>{{ 'events' }}</span>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@ -29,8 +25,46 @@
|
||||
|
||||
<section class="row no-gutter">
|
||||
|
||||
<div class="col-sm-12 col-md-12 col-lg-12">
|
||||
<div class="col-sm-9 col-md-9 col-lg-9">
|
||||
<div ui-calendar="calendarConfig" ng-model="eventSources" calendar="calendar" class="wrapper-lg public-calendar"></div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3 col-lg-3">
|
||||
<div class="widget panel b-a m m-t-lg">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 translate>{{ 'filter' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<div>
|
||||
<div class="row">
|
||||
<h3 class="col-md-11" translate>{{ 'trainings' }}</h3>
|
||||
<input class="col-md-1" type="checkbox" ng-model="filter.trainings" ng-change="toggleFilter('trainings')">
|
||||
</div>
|
||||
<div ng-repeat="t in trainings" class="row">
|
||||
<span class="col-md-11">{{::t.name}}</span>
|
||||
<input class="col-md-1" type="checkbox" ng-model="t.checked" ng-change="filterAvailabilities()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="m-t">
|
||||
<div class="row">
|
||||
<h3 class="col-md-11" translate>{{ 'machines' }}</h3>
|
||||
<input class="col-md-1" type="checkbox" ng-model="filter.machines" ng-change="toggleFilter('machines')">
|
||||
</div>
|
||||
<div ng-repeat="m in machines" class="row">
|
||||
<span class="col-md-11">{{::m.name}}</span>
|
||||
<input class="col-md-1" type="checkbox" ng-model="m.checked" ng-change="filterAvailabilities()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="m-t row">
|
||||
<h3 class="col-md-11" translate>{{ 'events' }}</h3>
|
||||
<input class="col-md-1" type="checkbox" ng-model="evt" ng-change="filterAvailabilities()">
|
||||
</div>
|
||||
<div class="m-t row">
|
||||
<h3 class="col-md-11" translate>{{ 'show_no_disponible' }}</h3>
|
||||
<input class="col-md-1" type="checkbox" ng-model="dispo" ng-change="filterAvailabilities()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
@ -17,20 +17,21 @@ class API::AvailabilitiesController < API::ApiController
|
||||
def public
|
||||
start_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:start])
|
||||
end_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:end]).end_of_day
|
||||
available_type = params[:available_type] || []
|
||||
@reservations = Reservation.includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at >= ? AND slots.end_at <= ?', start_date, end_date)
|
||||
if in_same_day(start_date, end_date)
|
||||
@training_and_event_availabilities = Availability.includes(:tags, :trainings, :event, :slots).where(available_type: available_type.dup.delete_if {|t| t == 'machines'})
|
||||
@training_and_event_availabilities = Availability.includes(:tags, :trainings, :event, :slots).where(available_type: ['training', 'event'])
|
||||
.where('start_at >= ? AND end_at <= ?', start_date, end_date)
|
||||
@machine_availabilities = Availability.includes(:tags, :machines).where(available_type: available_type.dup.delete_if {|t| t == 'training' or t == 'event'})
|
||||
@machine_availabilities = Availability.includes(:tags, :machines).where(available_type: 'machines')
|
||||
.where('start_at >= ? AND end_at <= ?', start_date, end_date)
|
||||
@machine_slots = []
|
||||
@machine_availabilities.each do |a|
|
||||
a.machines.each do |machine|
|
||||
((a.end_at - a.start_at)/SLOT_DURATION.minutes).to_i.times do |i|
|
||||
slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: machine, title: machine.name)
|
||||
slot = verify_machine_is_reserved(slot, @reservations, current_user, '')
|
||||
@machine_slots << slot
|
||||
if params[:m] and params[:m].include?(machine.id.to_s)
|
||||
((a.end_at - a.start_at)/SLOT_DURATION.minutes).to_i.times do |i|
|
||||
slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: machine, title: machine.name)
|
||||
slot = verify_machine_is_reserved(slot, @reservations, current_user, '')
|
||||
@machine_slots << slot
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -38,12 +39,16 @@ class API::AvailabilitiesController < API::ApiController
|
||||
else
|
||||
|
||||
@availabilities = Availability.includes(:tags, :machines, :trainings, :event, :slots)
|
||||
.where(available_type: available_type)
|
||||
.where('start_at >= ? AND end_at <= ?', start_date, end_date)
|
||||
@availabilities.each do |a|
|
||||
a = verify_training_event_is_reserved(a, @reservations)
|
||||
if a.available_type != 'machines'
|
||||
a = verify_training_event_is_reserved(a, @reservations)
|
||||
end
|
||||
end
|
||||
end
|
||||
machine_ids = params[:m] || []
|
||||
@title_filter = {machine_ids: machine_ids.map(&:to_i)}
|
||||
@availabilities = filter_availabilites(@availabilities)
|
||||
end
|
||||
|
||||
def show
|
||||
@ -220,4 +225,36 @@ class API::AvailabilitiesController < API::ApiController
|
||||
def in_same_day(start_date, end_date)
|
||||
(end_date.to_date - start_date.to_date).to_i == 1
|
||||
end
|
||||
|
||||
def filter_availabilites(availabilities)
|
||||
availabilities_filtered = []
|
||||
availabilities.to_ary.each do |a|
|
||||
# machine slot
|
||||
if !a.try(:available_type)
|
||||
availabilities_filtered << a
|
||||
else
|
||||
# training
|
||||
if params[:t] and a.available_type == 'training'
|
||||
if params[:t].include?(a.trainings.first.id.to_s)
|
||||
availabilities_filtered << a
|
||||
end
|
||||
end
|
||||
# machines
|
||||
if params[:m] and a.available_type == 'machines'
|
||||
if (params[:m].map(&:to_i) & a.machine_ids).any?
|
||||
availabilities_filtered << a
|
||||
end
|
||||
end
|
||||
# event
|
||||
if params[:evt] and params[:evt] == 'true' and a.available_type == 'event'
|
||||
availabilities_filtered << a
|
||||
end
|
||||
end
|
||||
end
|
||||
availabilities_filtered.delete_if do |a|
|
||||
if params[:dispo] == 'false'
|
||||
a.is_reserved or (a.try(:is_completed) and a.is_completed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -39,9 +39,12 @@ class Availability < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def title
|
||||
def title(filter = {})
|
||||
if available_type == 'machines'
|
||||
machines.map(&:name).join(' - ')
|
||||
if filter[:machine_ids]
|
||||
return machines.to_ary.delete_if {|m| !filter[:machine_ids].include?(m.id)}.map(&:name).join(' - ')
|
||||
end
|
||||
return machines.map(&:name).join(' - ')
|
||||
elsif available_type == 'event'
|
||||
event.name
|
||||
else
|
||||
|
@ -1,12 +1,12 @@
|
||||
json.array!(@availabilities) do |availability|
|
||||
json.id availability.id
|
||||
json.title availability.title
|
||||
json.start availability.start_at.iso8601
|
||||
json.end availability.end_at.iso8601
|
||||
json.textColor 'black'
|
||||
json.backgroundColor 'white'
|
||||
# availability object
|
||||
if availability.try(:available_type)
|
||||
json.title availability.title(@title_filter)
|
||||
if availability.available_type == 'event'
|
||||
json.event_id availability.event.id
|
||||
end
|
||||
@ -35,6 +35,7 @@ json.array!(@availabilities) do |availability|
|
||||
|
||||
# machine slot object ( here => availability = slot )
|
||||
else
|
||||
json.title availability.title
|
||||
json.machine_id availability.machine.id
|
||||
json.borderColor machines_slot_border_color(availability)
|
||||
json.tag_ids availability.availability.tag_ids
|
||||
@ -42,5 +43,6 @@ json.array!(@availabilities) do |availability|
|
||||
json.id t.id
|
||||
json.name t.name
|
||||
end
|
||||
json.is_reserved availability.is_reserved
|
||||
end
|
||||
end
|
||||
|
@ -231,3 +231,4 @@ en:
|
||||
|
||||
calendar:
|
||||
calendar: "Calendar"
|
||||
show_no_disponible: "Show the slots no disponibles"
|
||||
|
@ -233,3 +233,4 @@ fr:
|
||||
|
||||
calendar:
|
||||
calendar: "Calendrier"
|
||||
show_no_disponible: "Afficher les crénaux non disponibles"
|
||||
|
Loading…
x
Reference in New Issue
Block a user