1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-11-29 10:24:20 +01:00
fab-manager/app/assets/javascripts/controllers/admin/trainings.coffee.erb

339 lines
9.8 KiB
Plaintext

'use strict'
### 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) ->
### PUBLIC SCOPE ###
## list of trainings
$scope.trainings = trainingsPromise
## simplified list of machines
$scope.machines = machinesPromise
## Training to monitor, binded with drop-down selection
$scope.monitoring =
training: null
## 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)->
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'))
##
# 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')
##
# Callback when the drop-down selection is changed.
# The selected training details will be loaded from the API and rendered into the accordions.
##
$scope.selectTrainingToMonitor = ->
Training.availabilities {id: $scope.monitoring.training.id}, (training) ->
$scope.groupedAvailabilities = groupAvailabilities([training])
# we open current year/month by default
now = moment()
$scope.accordions[training.name] = {}
$scope.accordions[training.name][now.year()] =
isOpenFirst: true
$scope.accordions[training.name][now.year()][now.month()] =
isOpenFirst: true
### PRIVATE SCOPE ###
##
# 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
]