2016-03-23 18:39:41 +01:00
|
|
|
'use strict'
|
|
|
|
|
2016-07-13 18:15:14 +02:00
|
|
|
### COMMON CODE ###
|
|
|
|
|
|
|
|
##
|
|
|
|
# Provides a set of common callback methods to the $scope parameter. These methods are used
|
|
|
|
# in the various trainings' admin controllers.
|
|
|
|
#
|
|
|
|
# Provides :
|
|
|
|
# - $scope.submited(content)
|
|
|
|
# - $scope.fileinputClass(v)
|
|
|
|
#
|
|
|
|
# Requires :
|
|
|
|
# - $state (Ui-Router) [ 'app.admin.trainings' ]
|
|
|
|
##
|
|
|
|
class TrainingsController
|
|
|
|
constructor: ($scope, $state) ->
|
|
|
|
|
|
|
|
##
|
|
|
|
# For use with ngUpload (https://github.com/twilson63/ngUpload).
|
|
|
|
# Intended to be the callback when the upload is done: any raised error will be stacked in the
|
|
|
|
# $scope.alerts array. If everything goes fine, the user is redirected to the trainings list.
|
|
|
|
# @param content {Object} JSON - The upload's result
|
|
|
|
##
|
|
|
|
$scope.submited = (content) ->
|
|
|
|
if !content.id?
|
|
|
|
$scope.alerts = []
|
|
|
|
angular.forEach content, (v, k)->
|
|
|
|
angular.forEach v, (err)->
|
|
|
|
$scope.alerts.push
|
|
|
|
msg: k+': '+err
|
|
|
|
type: 'danger'
|
|
|
|
else
|
|
|
|
$state.go('app.admin.trainings')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Changes the current user's view, redirecting him to the machines list
|
|
|
|
##
|
|
|
|
$scope.cancel = ->
|
|
|
|
$state.go('app.admin.trainings')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# For use with 'ng-class', returns the CSS class name for the uploads previews.
|
|
|
|
# The preview may show a placeholder or the content of the file depending on the upload state.
|
|
|
|
# @param v {*} any attribute, will be tested for truthiness (see JS evaluation rules)
|
|
|
|
##
|
|
|
|
$scope.fileinputClass = (v)->
|
|
|
|
if v
|
|
|
|
'fileinput-exists'
|
|
|
|
else
|
|
|
|
'fileinput-new'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Controller used in the training creation page (admin)
|
|
|
|
##
|
|
|
|
Application.Controllers.controller "NewTrainingController", [ '$scope', '$state', 'machinesPromise', 'CSRF'
|
|
|
|
, ($scope, $state, machinesPromise, CSRF) ->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### PUBLIC SCOPE ###
|
|
|
|
|
|
|
|
## Form action on the following URL
|
|
|
|
$scope.method = 'post'
|
|
|
|
|
|
|
|
## API URL where the form will be posted
|
|
|
|
$scope.actionUrl = '/api/trainings/'
|
|
|
|
|
|
|
|
## list of machines
|
|
|
|
$scope.machines = machinesPromise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### PRIVATE SCOPE ###
|
|
|
|
|
|
|
|
##
|
|
|
|
# Kind of constructor: these actions will be realized first when the controller is loaded
|
|
|
|
##
|
|
|
|
initialize = ->
|
|
|
|
CSRF.setMetaTags()
|
|
|
|
|
|
|
|
## Using the TrainingsController
|
|
|
|
new TrainingsController($scope, $state)
|
|
|
|
|
|
|
|
|
|
|
|
## !!! MUST BE CALLED AT THE END of the controller
|
|
|
|
initialize()
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Controller used in the training edition page (admin)
|
|
|
|
##
|
|
|
|
Application.Controllers.controller "EditTrainingController", [ '$scope', '$state', '$stateParams', 'trainingPromise', 'machinesPromise', 'CSRF'
|
|
|
|
, ($scope, $state, $stateParams, trainingPromise, machinesPromise, CSRF) ->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### PUBLIC SCOPE ###
|
|
|
|
|
|
|
|
## Form action on the following URL
|
|
|
|
$scope.method = 'patch'
|
|
|
|
|
|
|
|
## API URL where the form will be posted
|
|
|
|
$scope.actionUrl = '/api/trainings/' + $stateParams.id
|
|
|
|
|
|
|
|
## Details of the training to edit (id in URL)
|
|
|
|
$scope.training = trainingPromise
|
|
|
|
|
|
|
|
## list of machines
|
|
|
|
$scope.machines = machinesPromise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### PRIVATE SCOPE ###
|
|
|
|
|
|
|
|
##
|
|
|
|
# Kind of constructor: these actions will be realized first when the controller is loaded
|
|
|
|
##
|
|
|
|
initialize = ->
|
|
|
|
CSRF.setMetaTags()
|
|
|
|
|
|
|
|
## Using the TrainingsController
|
|
|
|
new TrainingsController($scope, $state)
|
|
|
|
|
|
|
|
|
|
|
|
## !!! MUST BE CALLED AT THE END of the controller
|
|
|
|
initialize()
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Controller used in the trainings management page, allowing admins users to see and manage the list of trainings and reservations.
|
|
|
|
##
|
|
|
|
Application.Controllers.controller "TrainingsAdminController", ["$scope", "$state", "$uibModal", 'Training', 'trainingsPromise', 'machinesPromise', '_t', 'growl', 'dialogs'
|
|
|
|
, ($scope, $state, $uibModal, Training, trainingsPromise, machinesPromise, _t, growl, dialogs) ->
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### PUBLIC SCOPE ###
|
|
|
|
|
|
|
|
## list of trainings
|
|
|
|
$scope.trainings = trainingsPromise
|
|
|
|
|
|
|
|
## simplified list of machines
|
|
|
|
$scope.machines = machinesPromise
|
|
|
|
|
2016-06-15 12:01:09 +02:00
|
|
|
## Training to monitor, binded with drop-down selection
|
|
|
|
$scope.monitoring =
|
|
|
|
training: null
|
|
|
|
|
2016-03-23 18:39:41 +01:00
|
|
|
## list of training availabilies, grouped by date
|
|
|
|
$scope.groupedAvailabilities = {}
|
|
|
|
|
|
|
|
## default: accordions are not open
|
|
|
|
$scope.accordions = {}
|
|
|
|
|
|
|
|
## Binding for the parseInt function
|
|
|
|
$scope.parseInt = parseInt
|
|
|
|
|
|
|
|
##
|
|
|
|
# In the trainings listing tab, return the stringified list of machines associated with the provided training
|
|
|
|
# @param training {Object} Training object, inherited from $resource
|
|
|
|
# @returns {string}
|
|
|
|
##
|
|
|
|
$scope.showMachines = (training) ->
|
|
|
|
selected = []
|
|
|
|
angular.forEach $scope.machines, (m) ->
|
|
|
|
if (training.machine_ids.indexOf(m.id) >= 0)
|
|
|
|
selected.push(m.name)
|
|
|
|
return if selected.length then selected.join(', ') else _t('none')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Removes the newly inserted but not saved training / Cancel the current training modification
|
|
|
|
# @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
|
|
|
# @param index {number} training index in the $scope.trainings array
|
|
|
|
##
|
|
|
|
$scope.cancelTraining = (rowform, index) ->
|
|
|
|
if $scope.trainings[index].id?
|
|
|
|
rowform.$cancel()
|
|
|
|
else
|
|
|
|
$scope.trainings.splice(index, 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# In the trainings monitoring tab, callback to open a modal window displaying the current bookings for the
|
|
|
|
# provided training slot. The admin will be then able to validate the training for the users that followed
|
|
|
|
# the training.
|
|
|
|
# @param training {Object} Training object, inherited from $resource
|
|
|
|
# @param availability {Object} time slot when the training occurs
|
|
|
|
##
|
|
|
|
$scope.showReservations = (training, availability) ->
|
|
|
|
$uibModal.open
|
|
|
|
templateUrl: '<%= asset_path "admin/trainings/validTrainingModal.html" %>'
|
|
|
|
controller: ['$scope', '$uibModalInstance', ($scope, $uibModalInstance) ->
|
|
|
|
$scope.availability = availability
|
|
|
|
|
|
|
|
$scope.usersToValid = []
|
|
|
|
|
|
|
|
##
|
|
|
|
# Mark/unmark the provided user for training validation
|
|
|
|
# @param user {Object} from the availability.reservation_users list
|
|
|
|
##
|
|
|
|
$scope.toggleSelection = (user) ->
|
|
|
|
index = $scope.usersToValid.indexOf(user)
|
|
|
|
if index > -1
|
|
|
|
$scope.usersToValid.splice(index, 1)
|
|
|
|
else
|
|
|
|
$scope.usersToValid.push user
|
|
|
|
|
|
|
|
##
|
|
|
|
# Validates the modifications (training validations) and save them to the server
|
|
|
|
##
|
|
|
|
$scope.ok = ->
|
|
|
|
users = $scope.usersToValid.map (u) ->
|
|
|
|
u.id
|
|
|
|
Training.update {id: training.id},
|
|
|
|
training:
|
|
|
|
users: users
|
|
|
|
, -> # success
|
|
|
|
angular.forEach $scope.usersToValid, (u) ->
|
|
|
|
u.is_valid = true
|
|
|
|
$scope.usersToValid = []
|
|
|
|
$uibModalInstance.close(training)
|
|
|
|
|
|
|
|
##
|
|
|
|
# Cancel the modifications and close the modal window
|
|
|
|
##
|
|
|
|
$scope.cancel = ->
|
|
|
|
$uibModalInstance.dismiss('cancel')
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Delete the provided training and, in case of sucess, remove it from the trainings list afterwards
|
|
|
|
# @param index {number} index of the provided training in $scope.trainings
|
|
|
|
# @param training {Object} training to delete
|
|
|
|
##
|
|
|
|
$scope.removeTraining = (index, training)->
|
2016-07-13 18:15:14 +02:00
|
|
|
dialogs.confirm
|
|
|
|
resolve:
|
|
|
|
object: ->
|
|
|
|
title: _t('confirmation_required')
|
|
|
|
msg: _t('do_you_really_want_to_delete_this_training')
|
|
|
|
, -> # deletion confirmed
|
|
|
|
training.$delete ->
|
|
|
|
$scope.trainings.splice(index, 1)
|
|
|
|
growl.info(_t('training_successfully_deleted'))
|
|
|
|
, (error)->
|
|
|
|
growl.warning(_t('unable_to_delete_the_training_because_some_users_alredy_booked_it'))
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Takes a month number and return its localized literal name
|
|
|
|
# @param {Number} from 0 to 11
|
|
|
|
# @returns {String} eg. 'janvier'
|
|
|
|
##
|
|
|
|
$scope.formatMonth = (number) ->
|
|
|
|
number = parseInt(number)
|
|
|
|
moment().month(number).format('MMMM')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
# Given a day, month and year, return a localized literal name for the day
|
|
|
|
# @param day {Number} from 1 to 31
|
|
|
|
# @param month {Number} from 0 to 11
|
|
|
|
# @param year {Number} Gregorian's year number
|
|
|
|
# @returns {String} eg. 'mercredi 12'
|
|
|
|
##
|
|
|
|
$scope.formatDay = (day, month, year) ->
|
|
|
|
day = parseInt(day)
|
|
|
|
month = parseInt(month)
|
|
|
|
year = parseInt(year)
|
|
|
|
|
|
|
|
moment({year: year, month:month, day:day}).format('dddd D')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
2016-06-15 12:01:09 +02:00
|
|
|
# Callback when the drop-down selection is changed.
|
|
|
|
# The selected training details will be loaded from the API and rendered into the accordions.
|
2016-03-23 18:39:41 +01:00
|
|
|
##
|
2016-06-15 12:01:09 +02:00
|
|
|
$scope.selectTrainingToMonitor = ->
|
2016-07-19 12:16:41 +02:00
|
|
|
Training.availabilities {id: $scope.monitoring.training.id}, (training) ->
|
2016-06-15 12:01:09 +02:00
|
|
|
$scope.groupedAvailabilities = groupAvailabilities([training])
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-15 12:01:09 +02:00
|
|
|
### PRIVATE SCOPE ###
|
|
|
|
|
2016-03-23 18:39:41 +01:00
|
|
|
##
|
|
|
|
# Group the trainings availabilites by trainings and by dates and return the resulting tree
|
|
|
|
# @param trainings {Array} $scope.trainings is expected here
|
|
|
|
# @returns {Object} Tree constructed as /training_name/year/month/day/[availabilities]
|
|
|
|
##
|
|
|
|
groupAvailabilities = (trainings) ->
|
|
|
|
tree = {}
|
|
|
|
for training in trainings
|
|
|
|
tree[training.name] = {}
|
|
|
|
tree[training.name].training = training
|
|
|
|
for availability in training.availabilities
|
|
|
|
start = moment(availability.start_at)
|
|
|
|
|
|
|
|
# init the tree structure
|
|
|
|
if typeof tree[training.name][start.year()] == 'undefined'
|
|
|
|
tree[training.name][start.year()] = {}
|
|
|
|
if typeof tree[training.name][start.year()][start.month()] == 'undefined'
|
|
|
|
tree[training.name][start.year()][start.month()] = {}
|
|
|
|
if typeof tree[training.name][start.year()][start.month()][start.date()] == 'undefined'
|
|
|
|
tree[training.name][start.year()][start.month()][start.date()] = []
|
|
|
|
|
|
|
|
# add the availability at its right place
|
|
|
|
tree[training.name][start.year()][start.month()][start.date()].push( availability )
|
|
|
|
tree
|
|
|
|
|
|
|
|
]
|