1
0
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:
Peng DU 2016-07-14 18:36:52 +02:00
parent 0b1a19cd76
commit 70d623f65a
8 changed files with 172 additions and 54 deletions

View File

@ -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()
]

View File

@ -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
]

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -231,3 +231,4 @@ en:
calendar:
calendar: "Calendar"
show_no_disponible: "Show the slots no disponibles"

View File

@ -233,3 +233,4 @@ fr:
calendar:
calendar: "Calendrier"
show_no_disponible: "Afficher les crénaux non disponibles"