mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-18 07:52:23 +01:00
Merge branch 'erb' into es6
This commit is contained in:
commit
185ea30db3
@ -15,27 +15,27 @@
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
// # list of supported authentication methods
|
||||
// list of supported authentication methods
|
||||
const METHODS = {
|
||||
'DatabaseProvider': 'local_database',
|
||||
'OAuth2Provider': 'o_auth2'
|
||||
}
|
||||
|
||||
// #
|
||||
// Iterate through the provided array and return the index of the requested element
|
||||
// @param elements {Array<{id:*}>}
|
||||
// @param id {*} id of the element to retrieve in the list
|
||||
// @returns {number} index of the requested element, in the provided array
|
||||
// #
|
||||
/**
|
||||
* Iterate through the provided array and return the index of the requested element
|
||||
* @param elements {Array<{id:*}>}
|
||||
* @param id {*} id of the element to retrieve in the list
|
||||
* @returns {number} index of the requested element, in the provided array
|
||||
*/
|
||||
const findIdxById = (elements, id) =>
|
||||
(elements.map(elem => elem.id)).indexOf(id)
|
||||
|
||||
// #
|
||||
// For OAuth2 ententications, mapping the user's ID is mendatory. This function will check that this mapping
|
||||
// is effective and will return false otherwise
|
||||
// @param mappings {Array<Object>} expected: $scope.provider.providable_attributes.o_auth2_mappings_attributes
|
||||
// @returns {Boolean} true if the mapping is declared
|
||||
// #
|
||||
/**
|
||||
* For OAuth2 ententications, mapping the user's ID is mendatory. This function will check that this mapping
|
||||
* is effective and will return false otherwise
|
||||
* @param mappings {Array<Object>} expected: $scope.provider.providable_attributes.o_auth2_mappings_attributes
|
||||
* @returns {Boolean} true if the mapping is declared
|
||||
*/
|
||||
const check_oauth2_id_is_mapped = function (mappings) {
|
||||
for (let mapping of Array.from(mappings)) {
|
||||
if ((mapping.local_model === 'user') && (mapping.local_field === 'uid') && !mapping._destroy) {
|
||||
@ -45,36 +45,36 @@ const check_oauth2_id_is_mapped = function (mappings) {
|
||||
return false
|
||||
}
|
||||
|
||||
// #
|
||||
// Provides a set of common callback methods and data to the $scope parameter. These methods are used
|
||||
// in the various authentication providers' controllers.
|
||||
//
|
||||
// Provides :
|
||||
// - $scope.authMethods
|
||||
// - $scope.mappingFields
|
||||
// - $scope.cancel()
|
||||
// - $scope.defineDataMapping(mapping)
|
||||
//
|
||||
// Requires :
|
||||
// - mappingFieldsPromise: retrieved by AuthProvider.mapping_fields()
|
||||
// - $state (Ui-Router) [ 'app.admin.members' ]
|
||||
// #
|
||||
/**
|
||||
* Provides a set of common callback methods and data to the $scope parameter. These methods are used
|
||||
* in the various authentication providers' controllers.
|
||||
*
|
||||
* Provides :
|
||||
* - $scope.authMethods
|
||||
* - $scope.mappingFields
|
||||
* - $scope.cancel()
|
||||
* - $scope.defineDataMapping(mapping)
|
||||
*
|
||||
* Requires :
|
||||
* - mappingFieldsPromise: retrieved by AuthProvider.mapping_fields()
|
||||
* - $state (Ui-Router) [ 'app.admin.members' ]
|
||||
*/
|
||||
class AuthenticationController {
|
||||
constructor ($scope, $state, $uibModal, mappingFieldsPromise) {
|
||||
// # list of supported authentication methods
|
||||
// list of supported authentication methods
|
||||
$scope.authMethods = METHODS
|
||||
|
||||
// # list of fields that can be mapped through the SSO
|
||||
// list of fields that can be mapped through the SSO
|
||||
$scope.mappingFields = mappingFieldsPromise
|
||||
|
||||
// #
|
||||
// Changes the admin's view to the members list page
|
||||
// #
|
||||
/**
|
||||
* Changes the admin's view to the members list page
|
||||
*/
|
||||
$scope.cancel = () => $state.go('app.admin.members')
|
||||
|
||||
// #
|
||||
// Open a modal allowing to specify the data mapping for the given field
|
||||
// #
|
||||
/**
|
||||
* Open a modal allowing to specify the data mapping for the given field
|
||||
*/
|
||||
$scope.defineDataMapping = mapping =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/authentications/_data_mapping.html" %>',
|
||||
@ -91,14 +91,14 @@ class AuthenticationController {
|
||||
},
|
||||
|
||||
controller: ['$scope', '$uibModalInstance', 'field', 'datatype', function ($scope, $uibModalInstance, field, datatype) {
|
||||
// # parent field
|
||||
// parent field
|
||||
$scope.field = field
|
||||
// # expected data type
|
||||
// expected data type
|
||||
$scope.datatype = datatype
|
||||
// # data transformation rules
|
||||
// data transformation rules
|
||||
$scope.transformation =
|
||||
{ rules: field.transformation || { type: datatype } }
|
||||
// # available transformation formats
|
||||
// available transformation formats
|
||||
$scope.formats = {
|
||||
date: [
|
||||
{
|
||||
@ -124,7 +124,7 @@ class AuthenticationController {
|
||||
]
|
||||
}
|
||||
|
||||
// # Create a new mapping between anything and an expected integer
|
||||
// Create a new mapping between anything and an expected integer
|
||||
$scope.addIntegerMapping = function () {
|
||||
if (!angular.isArray($scope.transformation.rules.mapping)) {
|
||||
$scope.transformation.rules.mapping = []
|
||||
@ -132,10 +132,10 @@ class AuthenticationController {
|
||||
return $scope.transformation.rules.mapping.push({ from: '', to: 0 })
|
||||
}
|
||||
|
||||
// # close and save the modifications
|
||||
// close and save the modifications
|
||||
$scope.ok = () => $uibModalInstance.close($scope.transformation.rules)
|
||||
|
||||
// # do not save the modifications
|
||||
// do not save the modifications
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss()
|
||||
}
|
||||
] })
|
||||
@ -143,21 +143,21 @@ class AuthenticationController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Page listing all authentication providers
|
||||
// #
|
||||
/**
|
||||
* Page listing all authentication providers
|
||||
*/
|
||||
Application.Controllers.controller('AuthentificationController', ['$scope', '$state', '$rootScope', 'dialogs', 'growl', 'authProvidersPromise', 'AuthProvider', '_t',
|
||||
function ($scope, $state, $rootScope, dialogs, growl, authProvidersPromise, AuthProvider, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # full list of authentication providers
|
||||
// full list of authentication providers
|
||||
$scope.providers = authProvidersPromise
|
||||
|
||||
// #
|
||||
// Translate the classname into an explicit textual message
|
||||
// @param type {string} Ruby polymorphic model classname
|
||||
// @returns {string}
|
||||
// #
|
||||
/**
|
||||
* Translate the classname into an explicit textual message
|
||||
* @param type {string} Ruby polymorphic model classname
|
||||
* @returns {string}
|
||||
*/
|
||||
$scope.getType = function (type) {
|
||||
const text = METHODS[type]
|
||||
if (typeof text !== 'undefined') {
|
||||
@ -167,11 +167,11 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Translate the status string into an explicit textual message
|
||||
// @param status {string} active | pending | previous
|
||||
// @returns {string}
|
||||
// #
|
||||
/**
|
||||
* Translate the status string into an explicit textual message
|
||||
* @param status {string} active | pending | previous
|
||||
* @returns {string}
|
||||
*/
|
||||
$scope.getState = function (status) {
|
||||
switch (status) {
|
||||
case 'active': return _t('active')
|
||||
@ -181,11 +181,11 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Ask for confirmation then delete the specified provider
|
||||
// @param providers {Array} full list of authentication providers
|
||||
// @param provider {Object} provider to delete
|
||||
// #
|
||||
/**
|
||||
* Ask for confirmation then delete the specified provider
|
||||
* @param providers {Array} full list of authentication providers
|
||||
* @param provider {Object} provider to delete
|
||||
*/
|
||||
return $scope.destroyProvider = (providers, provider) =>
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
@ -210,23 +210,23 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
|
||||
])
|
||||
|
||||
// #
|
||||
// Page to add a new authentication provider
|
||||
// #
|
||||
/**
|
||||
* Page to add a new authentication provider
|
||||
*/
|
||||
Application.Controllers.controller('NewAuthenticationController', ['$scope', '$state', '$rootScope', '$uibModal', 'dialogs', 'growl', 'mappingFieldsPromise', 'authProvidersPromise', 'AuthProvider', '_t',
|
||||
function ($scope, $state, $rootScope, $uibModal, dialogs, growl, mappingFieldsPromise, authProvidersPromise, AuthProvider, _t) {
|
||||
$scope.mode = 'creation'
|
||||
|
||||
// # default parameters for the new authentication provider
|
||||
// default parameters for the new authentication provider
|
||||
$scope.provider = {
|
||||
name: '',
|
||||
providable_type: '',
|
||||
providable_attributes: {}
|
||||
}
|
||||
|
||||
// #
|
||||
// Initialize some provider's specific properties when selecting the provider type
|
||||
// #
|
||||
/**
|
||||
* Initialize some provider's specific properties when selecting the provider type
|
||||
*/
|
||||
$scope.updateProvidable = function () {
|
||||
// === OAuth2Provider ===
|
||||
if ($scope.provider.providable_type === 'OAuth2Provider') {
|
||||
@ -237,9 +237,9 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
}
|
||||
// Add others providers initializers here if needed ...
|
||||
|
||||
// #
|
||||
// Validate and save the provider parameters in database
|
||||
// #
|
||||
/**
|
||||
* Validate and save the provider parameters in database
|
||||
*/
|
||||
$scope.registerProvider = function () {
|
||||
// === DatabaseProvider ===
|
||||
let provider
|
||||
@ -292,24 +292,24 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
}
|
||||
}
|
||||
|
||||
// # Using the AuthenticationController
|
||||
// Using the AuthenticationController
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Page to edit an already added authentication provider
|
||||
// #
|
||||
/**
|
||||
* Page to edit an already added authentication provider
|
||||
*/
|
||||
Application.Controllers.controller('EditAuthenticationController', ['$scope', '$state', '$stateParams', '$rootScope', '$uibModal', 'dialogs', 'growl', 'providerPromise', 'mappingFieldsPromise', 'AuthProvider', '_t',
|
||||
function ($scope, $state, $stateParams, $rootScope, $uibModal, dialogs, growl, providerPromise, mappingFieldsPromise, AuthProvider, _t) {
|
||||
// # parameters of the currently edited authentication provider
|
||||
// parameters of the currently edited authentication provider
|
||||
$scope.provider = providerPromise
|
||||
|
||||
$scope.mode = 'edition'
|
||||
|
||||
// #
|
||||
// Update the current provider with the new inputs
|
||||
// #
|
||||
/**
|
||||
* Update the current provider with the new inputs
|
||||
*/
|
||||
$scope.updateProvider = function () {
|
||||
// check the ID mapping
|
||||
if (!check_oauth2_id_is_mapped($scope.provider.providable_attributes.o_auth2_mappings_attributes)) {
|
||||
@ -323,7 +323,7 @@ Application.Controllers.controller('EditAuthenticationController', ['$scope', '$
|
||||
, () => growl.error(_t('an_error_occurred_unable_to_update_the_provider')))
|
||||
}
|
||||
|
||||
// # Using the AuthenticationController
|
||||
// Using the AuthenticationController
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise)
|
||||
}
|
||||
])
|
||||
|
@ -14,9 +14,9 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
// #
|
||||
// Controller used in the calendar management page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the calendar management page
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('AdminCalendarController', ['$scope', '$state', '$uibModal', 'moment', 'Availability', 'Slot', 'Setting', 'Export', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', 'machinesPromise', '_t', 'uiCalendarConfig', 'CalendarConfig',
|
||||
function ($scope, $state, $uibModal, moment, Availability, Slot, Setting, Export, growl, dialogs, bookingWindowStart, bookingWindowEnd, machinesPromise, _t, uiCalendarConfig, CalendarConfig) {
|
||||
@ -34,20 +34,20 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # list of the FabLab machines
|
||||
// list of the FabLab machines
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
// # currently selected availability
|
||||
// currently selected availability
|
||||
$scope.availability = null
|
||||
|
||||
// # bind the availabilities slots with full-Calendar events
|
||||
// bind the availabilities slots with full-Calendar events
|
||||
$scope.eventSources = []
|
||||
$scope.eventSources.push({
|
||||
url: '/api/availabilities',
|
||||
textColor: 'black'
|
||||
})
|
||||
|
||||
// # fullCalendar (v2) configuration
|
||||
// fullCalendar (v2) configuration
|
||||
$scope.calendarConfig = CalendarConfig({
|
||||
slotDuration: BASE_SLOT,
|
||||
snapDuration: BOOKING_SNAP,
|
||||
@ -69,10 +69,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Open a confirmation modal to cancel the booking of a user for the currently selected event.
|
||||
// @param slot {Object} reservation slot of a user, inherited from $resource
|
||||
// #
|
||||
/**
|
||||
* Open a confirmation modal to cancel the booking of a user for the currently selected event.
|
||||
* @param slot {Object} reservation slot of a user, inherited from $resource
|
||||
*/
|
||||
$scope.cancelBooking = slot =>
|
||||
// open a confirmation dialog
|
||||
dialogs.confirm({
|
||||
@ -106,11 +106,11 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
)
|
||||
)
|
||||
|
||||
// #
|
||||
// Open a confirmation modal to remove a machine for the currently selected availability,
|
||||
// except if it is the last machine of the reservation.
|
||||
// @param machine {Object} must contain the machine ID and name
|
||||
// #
|
||||
/**
|
||||
* Open a confirmation modal to remove a machine for the currently selected availability,
|
||||
* except if it is the last machine of the reservation.
|
||||
* @param machine {Object} must contain the machine ID and name
|
||||
*/
|
||||
$scope.removeMachine = function (machine) {
|
||||
if ($scope.availability.machine_ids.length === 1) {
|
||||
return growl.error(_t('admin_calendar.unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather'))
|
||||
@ -154,10 +154,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to alert the admin that the export request was acknowledged and is
|
||||
// processing right now.
|
||||
// #
|
||||
/**
|
||||
* Callback to alert the admin that the export request was acknowledged and is
|
||||
* processing right now.
|
||||
*/
|
||||
$scope.alertExport = type =>
|
||||
Export.status({ category: 'availabilities', type }).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
@ -165,9 +165,9 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Mark the selected slot as unavailable for new reservations or allow reservations again on it
|
||||
// #
|
||||
/**
|
||||
* Mark the selected slot as unavailable for new reservations or allow reservations again on it
|
||||
*/
|
||||
$scope.toggleLockReservations = function () {
|
||||
// first, define a shortcut to the lock property
|
||||
const locked = $scope.availability.lock
|
||||
@ -210,9 +210,9 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Confirm and destroy the slot in $scope.availability
|
||||
// #
|
||||
/**
|
||||
* Confirm and destroy the slot in $scope.availability
|
||||
*/
|
||||
$scope.removeSlot = () =>
|
||||
// open a confirmation dialog
|
||||
dialogs.confirm({
|
||||
@ -238,11 +238,11 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Return an enumerable meaninful string for the gender of the provider user
|
||||
// @param user {Object} Database user record
|
||||
// @return {string} 'male' or 'female'
|
||||
// #
|
||||
/**
|
||||
* Return an enumerable meaninful string for the gender of the provider user
|
||||
* @param user {Object} Database user record
|
||||
* @return {string} 'male' or 'female'
|
||||
*/
|
||||
var getGender = function (user) {
|
||||
if (user.profile) {
|
||||
if (user.profile.gender === 'true') { return 'male' } else { return 'female' }
|
||||
@ -251,7 +251,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
|
||||
// Triggered when the admin drag on the agenda to create a new reservable slot.
|
||||
// @see http://fullcalendar.io/docs/selection/select_callback/
|
||||
// #
|
||||
//
|
||||
var calendarSelectCb = function (start, end, jsEvent, view) {
|
||||
start = moment.tz(start.toISOString(), Fablab.timezone)
|
||||
end = moment.tz(end.toISOString(), Fablab.timezone)
|
||||
@ -296,10 +296,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('unselect')
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when the admin clicks on a availability slot in the agenda.
|
||||
// @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
// #
|
||||
/**
|
||||
* Triggered when the admin clicks on a availability slot in the agenda.
|
||||
* @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.availability = event
|
||||
|
||||
@ -312,11 +312,11 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
// Append the event tag into the block, just after the event title.
|
||||
// @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
// #
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
* Append the event tag into the block, just after the event title.
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element) {
|
||||
element.find('.fc-content').prepend('<span class="remove-event">x </span>')
|
||||
if (event.tags.length > 0) {
|
||||
@ -329,10 +329,10 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
// force return to prevent coffee-script auto-return to return random value (possiblity falsy)
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when resource fetching starts/stops.
|
||||
// @see https://fullcalendar.io/docs/resource_data/loading/
|
||||
// #
|
||||
/**
|
||||
* Triggered when resource fetching starts/stops.
|
||||
* @see https://fullcalendar.io/docs/resource_data/loading/
|
||||
*/
|
||||
return loadingCb = function (isLoading, view) {
|
||||
if (isLoading) {
|
||||
// we remove existing events when fetching starts to prevent duplicates
|
||||
@ -343,42 +343,42 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the slot creation modal window
|
||||
// #
|
||||
/**
|
||||
* Controller used in the slot creation modal window
|
||||
*/
|
||||
Application.Controllers.controller('CreateEventModalController', ['$scope', '$uibModalInstance', 'moment', 'start', 'end', 'machinesPromise', 'Availability', 'trainingsPromise', 'spacesPromise', 'Tag', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, moment, start, end, machinesPromise, Availability, trainingsPromise, spacesPromise, Tag, growl, _t) {
|
||||
// # $uibModal parameter
|
||||
// $uibModal parameter
|
||||
$scope.start = start
|
||||
|
||||
// # $uibModal parameter
|
||||
// $uibModal parameter
|
||||
$scope.end = end
|
||||
|
||||
// # machines list
|
||||
// machines list
|
||||
$scope.machines = machinesPromise.filter(m => !m.disabled)
|
||||
|
||||
// # trainings list
|
||||
// trainings list
|
||||
$scope.trainings = trainingsPromise.filter(t => !t.disabled)
|
||||
|
||||
// # spaces list
|
||||
// spaces list
|
||||
$scope.spaces = spacesPromise.filter(s => !s.disabled)
|
||||
|
||||
// # machines associated with the created slot
|
||||
// machines associated with the created slot
|
||||
$scope.selectedMachines = []
|
||||
|
||||
// # training associated with the created slot
|
||||
// training associated with the created slot
|
||||
$scope.selectedTraining = null
|
||||
|
||||
// # space associated with the created slot
|
||||
// space associated with the created slot
|
||||
$scope.selectedSpace = null
|
||||
|
||||
// # UI step
|
||||
// UI step
|
||||
$scope.step = 1
|
||||
|
||||
// # the user is not able to edit the ending time of the availability, unless he set the type to 'training'
|
||||
// the user is not able to edit the ending time of the availability, unless he set the type to 'training'
|
||||
$scope.endDateReadOnly = true
|
||||
|
||||
// # timepickers configuration
|
||||
// timepickers configuration
|
||||
$scope.timepickers = {
|
||||
start: {
|
||||
hstep: 1,
|
||||
@ -390,17 +390,17 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
}
|
||||
}
|
||||
|
||||
// # slot details
|
||||
// slot details
|
||||
$scope.availability = {
|
||||
start_at: start,
|
||||
end_at: end,
|
||||
available_type: 'machines' // default
|
||||
}
|
||||
|
||||
// #
|
||||
// Adds or removes the provided machine from the current slot
|
||||
// @param machine {Object}
|
||||
// #
|
||||
/**
|
||||
* Adds or removes the provided machine from the current slot
|
||||
* @param machine {Object}
|
||||
*/
|
||||
$scope.toggleSelection = function (machine) {
|
||||
const index = $scope.selectedMachines.indexOf(machine)
|
||||
if (index > -1) {
|
||||
@ -410,9 +410,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback for the modal window validation: save the slot and closes the modal
|
||||
// #
|
||||
/**
|
||||
* Callback for the modal window validation: save the slot and closes the modal
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
if ($scope.availability.available_type === 'machines') {
|
||||
if ($scope.selectedMachines.length > 0) {
|
||||
@ -431,27 +431,27 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
, availability => $uibModalInstance.close(availability))
|
||||
}
|
||||
|
||||
// #
|
||||
// Move the modal UI to the next step
|
||||
// #
|
||||
/**
|
||||
* Move the modal UI to the next step
|
||||
*/
|
||||
$scope.next = function () {
|
||||
if ($scope.step === 1) { $scope.setNbTotalPlaces() }
|
||||
return $scope.step++
|
||||
}
|
||||
|
||||
// #
|
||||
// Move the modal UI to the next step
|
||||
// #
|
||||
/**
|
||||
* Move the modal UI to the next step
|
||||
*/
|
||||
$scope.previous = () => $scope.step--
|
||||
|
||||
// #
|
||||
// Callback to cancel the slot creation
|
||||
// #
|
||||
/**
|
||||
* Callback to cancel the slot creation
|
||||
*/
|
||||
$scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
|
||||
// #
|
||||
// For training avaiabilities, set the maximum number of people allowed to register on this slot
|
||||
// #
|
||||
/**
|
||||
* For training avaiabilities, set the maximum number of people allowed to register on this slot
|
||||
*/
|
||||
$scope.setNbTotalPlaces = function () {
|
||||
if ($scope.availability.available_type === 'training') {
|
||||
return $scope.availability.nb_total_places = $scope.selectedTraining.nb_total_places
|
||||
@ -462,9 +462,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.trainings.length > 0) {
|
||||
$scope.selectedTraining = $scope.trainings[0]
|
||||
@ -475,9 +475,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
|
||||
Tag.query().$promise.then(data => $scope.tags = data)
|
||||
|
||||
// # When we configure a machine availability, do not let the user change the end time, as the total
|
||||
// # time must be dividable by 60 minutes (base slot duration). For training availabilities, the user
|
||||
// # can configure any duration as it does not matters.
|
||||
// When we configure a machine availability, do not let the user change the end time, as the total
|
||||
// time must be dividable by 60 minutes (base slot duration). For training availabilities, the user
|
||||
// can configure any duration as it does not matters.
|
||||
$scope.$watch('availability.available_type', function (newValue, oldValue, scope) {
|
||||
if ((newValue === 'machines') || (newValue === 'space')) {
|
||||
$scope.endDateReadOnly = true
|
||||
@ -489,8 +489,8 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
}
|
||||
})
|
||||
|
||||
// # When the start date is changed, if we are configuring a machine availability,
|
||||
// # maintain the relative length of the slot (ie. change the end time accordingly)
|
||||
// When the start date is changed, if we are configuring a machine availability,
|
||||
// maintain the relative length of the slot (ie. change the end time accordingly)
|
||||
$scope.$watch('start', function (newValue, oldValue, scope) {
|
||||
// for machine or space availabilities, adjust the end time
|
||||
if (($scope.availability.available_type === 'machines') || ($scope.availability.available_type === 'space')) {
|
||||
@ -507,9 +507,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
return $scope.availability.start_at = $scope.start
|
||||
})
|
||||
|
||||
// # Maintain consistency between the end time and the date object in the availability object
|
||||
// Maintain consistency between the end time and the date object in the availability object
|
||||
return $scope.$watch('end', function (newValue, oldValue, scope) {
|
||||
// # we prevent the admin from setting the end of the availability before its begining
|
||||
// we prevent the admin from setting the end of the availability before its begining
|
||||
if (moment($scope.start).add(1, 'hour').isAfter(newValue)) {
|
||||
$scope.end = oldValue
|
||||
}
|
||||
@ -518,7 +518,7 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
})
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -15,30 +15,30 @@
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
// #
|
||||
// Provides a set of common properties and methods to the $scope parameter. They are used
|
||||
// in the various events' admin controllers.
|
||||
//
|
||||
// Provides :
|
||||
// - $scope.datePicker = {}
|
||||
// - $scope.submited(content)
|
||||
// - $scope.cancel()
|
||||
// - $scope.addFile()
|
||||
// - $scope.deleteFile(file)
|
||||
// - $scope.fileinputClass(v)
|
||||
// - $scope.toggleStartDatePicker($event)
|
||||
// - $scope.toggleEndDatePicker($event)
|
||||
// - $scope.toggleRecurrenceEnd(e)
|
||||
// - $scope.addPrice()
|
||||
// - $scope.removePrice(price, $event)
|
||||
//
|
||||
// Requires :
|
||||
// - $scope.event.event_files_attributes = []
|
||||
// - $state (Ui-Router) [ 'app.public.events_list' ]
|
||||
// #
|
||||
/**
|
||||
* Provides a set of common properties and methods to the $scope parameter. They are used
|
||||
* in the various events' admin controllers.
|
||||
*
|
||||
* Provides :
|
||||
* - $scope.datePicker = {}
|
||||
* - $scope.submited(content)
|
||||
* - $scope.cancel()
|
||||
* - $scope.addFile()
|
||||
* - $scope.deleteFile(file)
|
||||
* - $scope.fileinputClass(v)
|
||||
* - $scope.toggleStartDatePicker($event)
|
||||
* - $scope.toggleEndDatePicker($event)
|
||||
* - $scope.toggleRecurrenceEnd(e)
|
||||
* - $scope.addPrice()
|
||||
* - $scope.removePrice(price, $event)
|
||||
*
|
||||
* Requires :
|
||||
* - $scope.event.event_files_attributes = []
|
||||
* - $state (Ui-Router) [ 'app.public.events_list' ]
|
||||
*/
|
||||
class EventsController {
|
||||
constructor ($scope, $state) {
|
||||
// # default parameters for AngularUI-Bootstrap datepicker
|
||||
// default parameters for AngularUI-Bootstrap datepicker
|
||||
$scope.datePicker = {
|
||||
format: Fablab.uibDateFormat,
|
||||
startOpened: false, // default: datePicker is not shown
|
||||
@ -49,12 +49,12 @@ class EventsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
// Intended to be the callback when an upload is done: any raised error will be stacked in the
|
||||
// $scope.alerts array. If everything goes fine, the user is redirected to the project page.
|
||||
// @param content {Object} JSON - The upload's result
|
||||
// #
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
* Intended to be the callback when an upload is done: any raised error will be stacked in the
|
||||
* $scope.alerts array. If everything goes fine, the user is redirected to the project page.
|
||||
* @param content {Object} JSON - The upload's result
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -66,16 +66,16 @@ class EventsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the user's view to the events list page
|
||||
// #
|
||||
/**
|
||||
* Changes the user's view to the events list page
|
||||
*/
|
||||
$scope.cancel = () => $state.go('app.public.events_list')
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -84,17 +84,17 @@ class EventsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// This will create a single new empty entry into the event's attachements list.
|
||||
// #
|
||||
/**
|
||||
* This will create a single new empty entry into the event's attachements list.
|
||||
*/
|
||||
$scope.addFile = () => $scope.event.event_files_attributes.push({})
|
||||
|
||||
// #
|
||||
// This will remove the given file from the event's attachements list. If the file was previously uploaded
|
||||
// to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
// the attachements array.
|
||||
// @param file {Object} the file to delete
|
||||
// #
|
||||
/**
|
||||
* This will remove the given file from the event's attachements list. If the file was previously uploaded
|
||||
* to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
* the attachements array.
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.event.event_files_attributes.indexOf(file)
|
||||
if (file.id != null) {
|
||||
@ -104,45 +104,45 @@ class EventsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Show/Hide the "start" datepicker (open the drop down/close it)
|
||||
// #
|
||||
/**
|
||||
* Show/Hide the "start" datepicker (open the drop down/close it)
|
||||
*/
|
||||
$scope.toggleStartDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.startOpened = !$scope.datePicker.startOpened
|
||||
}
|
||||
|
||||
// #
|
||||
// Show/Hide the "end" datepicker (open the drop down/close it)
|
||||
// #
|
||||
/**
|
||||
* Show/Hide the "end" datepicker (open the drop down/close it)
|
||||
*/
|
||||
$scope.toggleEndDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.endOpened = !$scope.datePicker.endOpened
|
||||
}
|
||||
|
||||
// #
|
||||
// Masks/displays the recurrence pane allowing the admin to set the current event as recursive
|
||||
// #
|
||||
/**
|
||||
* Masks/displays the recurrence pane allowing the admin to set the current event as recursive
|
||||
*/
|
||||
$scope.toggleRecurrenceEnd = function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return $scope.datePicker.recurrenceEndOpened = !$scope.datePicker.recurrenceEndOpened
|
||||
}
|
||||
|
||||
// #
|
||||
// Initialize a new price item in the additional prices list
|
||||
// #
|
||||
/**
|
||||
* Initialize a new price item in the additional prices list
|
||||
*/
|
||||
$scope.addPrice = () =>
|
||||
$scope.event.prices.push({
|
||||
category: null,
|
||||
amount: null
|
||||
})
|
||||
|
||||
// #
|
||||
// Remove the price or mark it as 'to delete'
|
||||
// #
|
||||
/**
|
||||
* Remove the price or mark it as 'to delete'
|
||||
*/
|
||||
$scope.removePrice = function (price, event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
@ -156,48 +156,48 @@ class EventsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used in the events listing page (admin view)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the events listing page (admin view)
|
||||
*/
|
||||
Application.Controllers.controller('AdminEventsController', ['$scope', '$state', 'dialogs', '$uibModal', 'growl', 'Event', 'Category', 'EventTheme', 'AgeRange', 'PriceCategory', 'eventsPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '_t',
|
||||
function ($scope, $state, dialogs, $uibModal, growl, Event, Category, EventTheme, AgeRange, PriceCategory, eventsPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # By default, the pagination mode is activated to limit the page size
|
||||
// By default, the pagination mode is activated to limit the page size
|
||||
$scope.paginateActive = true
|
||||
|
||||
// # The events displayed on the page
|
||||
// The events displayed on the page
|
||||
$scope.events = eventsPromise
|
||||
|
||||
// # Current virtual page
|
||||
// Current virtual page
|
||||
$scope.page = 1
|
||||
|
||||
// # Temporary datastore for creating new elements
|
||||
// Temporary datastore for creating new elements
|
||||
$scope.inserted = {
|
||||
category: null,
|
||||
theme: null,
|
||||
age_range: null
|
||||
}
|
||||
|
||||
// # List of categories for the events
|
||||
// List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
// # List of events themes
|
||||
// List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
// # List of age ranges
|
||||
// List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
// # List of price categories for the events
|
||||
// List of price categories for the events
|
||||
$scope.priceCategories = priceCategoriesPromise
|
||||
|
||||
// # Default: we display all events (no restriction)
|
||||
// Default: we display all events (no restriction)
|
||||
$scope.eventsScope =
|
||||
{ selected: '' }
|
||||
|
||||
// #
|
||||
// Adds a bucket of events to the bottom of the page, grouped by month
|
||||
// #
|
||||
/**
|
||||
* Adds a bucket of events to the bottom of the page, grouped by month
|
||||
*/
|
||||
$scope.loadMoreEvents = function () {
|
||||
$scope.page += 1
|
||||
return Event.query({ page: $scope.page, scope: $scope.eventsScope.selected }, function (data) {
|
||||
@ -206,12 +206,12 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Saves a new element / Update an existing one to the server (form validation callback)
|
||||
// @param model {string} model name
|
||||
// @param data {Object} element name
|
||||
// @param [id] {number} element id, in case of update
|
||||
// #
|
||||
/**
|
||||
* Saves a new element / Update an existing one to the server (form validation callback)
|
||||
* @param model {string} model name
|
||||
* @param data {Object} element name
|
||||
* @param [id] {number} element id, in case of update
|
||||
*/
|
||||
$scope.saveElement = function (model, data, id) {
|
||||
if (id != null) {
|
||||
return getModel(model)[0].update({ id }, data)
|
||||
@ -220,11 +220,11 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Deletes the element at the specified index
|
||||
// @param model {string} model name
|
||||
// @param index {number} element index in the $scope[model] array
|
||||
// #
|
||||
/**
|
||||
* Deletes the element at the specified index
|
||||
* @param model {string} model name
|
||||
* @param index {number} element index in the $scope[model] array
|
||||
*/
|
||||
$scope.removeElement = function (model, index) {
|
||||
if ((model === 'category') && (getModel(model)[1].length === 1)) {
|
||||
growl.error(_t('at_least_one_category_is_required') + ' ' + _t('unable_to_delete_the_last_one'))
|
||||
@ -250,10 +250,10 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
)
|
||||
}
|
||||
|
||||
// #
|
||||
// Creates a new empty entry in the $scope[model] array
|
||||
// @param model {string} model name
|
||||
// #
|
||||
/**
|
||||
* Creates a new empty entry in the $scope[model] array
|
||||
* @param model {string} model name
|
||||
*/
|
||||
$scope.addElement = function (model) {
|
||||
$scope.inserted[model] = {
|
||||
name: '',
|
||||
@ -262,12 +262,12 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
return getModel(model)[1].push($scope.inserted[model])
|
||||
}
|
||||
|
||||
// #
|
||||
// Removes the newly inserted but not saved element / Cancel the current element modification
|
||||
// @param model {string} model name
|
||||
// @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
// @param index {number} element index in the $scope[model] array
|
||||
// #
|
||||
/**
|
||||
* Removes the newly inserted but not saved element / Cancel the current element modification
|
||||
* @param model {string} model name
|
||||
* @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
* @param index {number} element index in the $scope[model] array
|
||||
*/
|
||||
$scope.cancelElement = function (model, rowform, index) {
|
||||
if (getModel(model)[1][index].id != null) {
|
||||
return rowform.$cancel()
|
||||
@ -276,10 +276,10 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the definition of a new price category.
|
||||
// Save it once filled and handle the result.
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the definition of a new price category.
|
||||
* Save it once filled and handle the result.
|
||||
*/
|
||||
$scope.newPriceCategory = () =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/events/price_form.html" %>',
|
||||
@ -299,12 +299,12 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
})
|
||||
)
|
||||
|
||||
// #
|
||||
// Update the given price category with the new properties
|
||||
// to specify in a modal dialog
|
||||
// @param index {number} index of the caterory in the $scope.priceCategories array
|
||||
// @param id {number} price category ID, must match the ID of the category at the index specified above
|
||||
// #
|
||||
/**
|
||||
* Update the given price category with the new properties
|
||||
* to specify in a modal dialog
|
||||
* @param index {number} index of the caterory in the $scope.priceCategories array
|
||||
* @param id {number} price category ID, must match the ID of the category at the index specified above
|
||||
*/
|
||||
$scope.editPriceCategory = function (id, index) {
|
||||
if ($scope.priceCategories[index].id !== id) {
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'))
|
||||
@ -329,11 +329,11 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Delete the given price category from the API
|
||||
// @param index {number} index of the caterory in the $scope.priceCategories array
|
||||
// @param id {number} price category ID, must match the ID of the category at the index specified above
|
||||
// #
|
||||
/**
|
||||
* Delete the given price category from the API
|
||||
* @param index {number} index of the caterory in the $scope.priceCategories array
|
||||
* @param id {number} price category ID, must match the ID of the category at the index specified above
|
||||
*/
|
||||
$scope.removePriceCategory = function (id, index) {
|
||||
if ($scope.priceCategories[index].id !== id) {
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'))
|
||||
@ -360,10 +360,10 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when the admin changes the events filter (all, passed, future).
|
||||
// We request the first page of corresponding events to the API
|
||||
// #
|
||||
/**
|
||||
* Triggered when the admin changes the events filter (all, passed, future).
|
||||
* We request the first page of corresponding events to the API
|
||||
*/
|
||||
$scope.changeScope = function () {
|
||||
Event.query({ page: 1, scope: $scope.eventsScope.selected }, function (data) {
|
||||
$scope.events = data
|
||||
@ -374,17 +374,17 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () => paginationCheck(eventsPromise, $scope.events)
|
||||
|
||||
// #
|
||||
// Check if all events are already displayed OR if the button 'load more events'
|
||||
// is required
|
||||
// @param lastEvents {Array} last events loaded onto the diplay (ie. last "page")
|
||||
// @param events {Array} full list of events displayed on the page (not only the last retrieved)
|
||||
// #
|
||||
/**
|
||||
* Check if all events are already displayed OR if the button 'load more events'
|
||||
* is required
|
||||
* @param lastEvents {Array} last events loaded onto the diplay (ie. last "page")
|
||||
* @param events {Array} full list of events displayed on the page (not only the last retrieved)
|
||||
*/
|
||||
var paginationCheck = function (lastEvents, events) {
|
||||
if (lastEvents.length > 0) {
|
||||
if (events.length >= lastEvents[0].nb_total_events) {
|
||||
@ -397,11 +397,11 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Return the model and the datastore matching the given name
|
||||
// @param name {string} 'category', 'theme' or 'age_range'
|
||||
// @return {[Object, Array]} model and datastore
|
||||
// #
|
||||
/**
|
||||
* Return the model and the datastore matching the given name
|
||||
* @param name {string} 'category', 'theme' or 'age_range'
|
||||
* @return {[Object, Array]} model and datastore
|
||||
*/
|
||||
var getModel = function (name) {
|
||||
switch (name) {
|
||||
case 'category': return [Category, $scope.categories]
|
||||
@ -417,44 +417,44 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the reservations listing page for a specific event
|
||||
// #
|
||||
/**
|
||||
* Controller used in the reservations listing page for a specific event
|
||||
*/
|
||||
Application.Controllers.controller('ShowEventReservationsController', ['$scope', 'eventPromise', 'reservationsPromise', function ($scope, eventPromise, reservationsPromise) {
|
||||
// # retrieve the event from the ID provided in the current URL
|
||||
// retrieve the event from the ID provided in the current URL
|
||||
$scope.event = eventPromise
|
||||
|
||||
// # list of reservations for the current event
|
||||
// list of reservations for the current event
|
||||
return $scope.reservations = reservationsPromise
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the event creation page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the event creation page
|
||||
*/
|
||||
Application.Controllers.controller('NewEventController', ['$scope', '$state', 'CSRF', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise', '_t',
|
||||
function ($scope, $state, CSRF, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise, _t) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/events/'
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # List of categories for the events
|
||||
// List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
// # List of events themes
|
||||
// List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
// # List of age ranges
|
||||
// List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
// # List of availables price's categories
|
||||
// List of availables price's categories
|
||||
$scope.priceCategories = priceCategoriesPromise
|
||||
|
||||
// # Default event parameters
|
||||
// Default event parameters
|
||||
$scope.event = {
|
||||
event_files_attributes: [],
|
||||
start_date: new Date(),
|
||||
@ -467,7 +467,7 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
|
||||
prices: []
|
||||
}
|
||||
|
||||
// # Possible types of recurrences for an event
|
||||
// Possible types of recurrences for an event
|
||||
$scope.recurrenceTypes = [
|
||||
{ label: _t('none'), value: 'none' },
|
||||
{ label: _t('every_days'), value: 'day' },
|
||||
@ -476,44 +476,44 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
|
||||
{ label: _t('every_year'), value: 'year' }
|
||||
]
|
||||
|
||||
// # Using the EventsController
|
||||
// Using the EventsController
|
||||
return new EventsController($scope, $state)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the events edition page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the events edition page
|
||||
*/
|
||||
Application.Controllers.controller('EditEventController', ['$scope', '$state', '$stateParams', 'CSRF', 'eventPromise', 'categoriesPromise', 'themesPromise', 'ageRangesPromise', 'priceCategoriesPromise',
|
||||
function ($scope, $state, $stateParams, CSRF, eventPromise, categoriesPromise, themesPromise, ageRangesPromise, priceCategoriesPromise) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/events/${$stateParams.id}`
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
|
||||
// # Retrieve the event details, in case of error the user is redirected to the events listing
|
||||
// Retrieve the event details, in case of error the user is redirected to the events listing
|
||||
$scope.event = eventPromise
|
||||
|
||||
// # List of categories for the events
|
||||
// List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
|
||||
// # List of availables price's categories
|
||||
// List of availables price's categories
|
||||
$scope.priceCategories = priceCategoriesPromise
|
||||
|
||||
// # List of events themes
|
||||
// List of events themes
|
||||
$scope.themes = themesPromise
|
||||
|
||||
// # List of age ranges
|
||||
// List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
@ -521,11 +521,11 @@ Application.Controllers.controller('EditEventController', ['$scope', '$state', '
|
||||
$scope.event.start_date = moment($scope.event.start_date).toDate()
|
||||
$scope.event.end_date = moment($scope.event.end_date).toDate()
|
||||
|
||||
// # Using the EventsController
|
||||
// Using the EventsController
|
||||
return new EventsController($scope, $state)
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -14,9 +14,9 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
// #
|
||||
// Controller used in the admin invoices listing page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the admin invoices listing page
|
||||
*/
|
||||
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'invoices', '$uibModal', 'growl', '$filter', 'Setting', 'settings', '_t',
|
||||
function ($scope, $state, Invoice, invoices, $uibModal, growl, $filter, Setting, settings, _t) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
@ -26,7 +26,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # List of all users invoices
|
||||
// List of all users invoices
|
||||
$scope.invoices = invoices
|
||||
|
||||
// Invoices filters
|
||||
@ -42,10 +42,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
// true when all invoices are loaded
|
||||
$scope.noMoreResults = false
|
||||
|
||||
// # Default invoices ordering/sorting
|
||||
// Default invoices ordering/sorting
|
||||
$scope.orderInvoice = '-reference'
|
||||
|
||||
// # Invoices parameters
|
||||
// Invoices parameters
|
||||
$scope.invoice = {
|
||||
logo: null,
|
||||
reference: {
|
||||
@ -76,19 +76,19 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
}
|
||||
}
|
||||
|
||||
// # Placeholding date for the invoice creation
|
||||
// Placeholding date for the invoice creation
|
||||
$scope.today = moment()
|
||||
|
||||
// # Placeholding date for the reservation begin
|
||||
// Placeholding date for the reservation begin
|
||||
$scope.inOneWeek = moment().add(1, 'week').startOf('hour')
|
||||
|
||||
// # Placeholding date for the reservation end
|
||||
// Placeholding date for the reservation end
|
||||
$scope.inOneWeekAndOneHour = moment().add(1, 'week').add(1, 'hour').startOf('hour')
|
||||
|
||||
// #
|
||||
// Change the invoices ordering criterion to the one provided
|
||||
// @param orderBy {string} ordering criterion
|
||||
// #
|
||||
/**
|
||||
* Change the invoices ordering criterion to the one provided
|
||||
* @param orderBy {string} ordering criterion
|
||||
*/
|
||||
$scope.setOrderInvoice = function (orderBy) {
|
||||
if ($scope.orderInvoice === orderBy) {
|
||||
$scope.orderInvoice = `-${orderBy}`
|
||||
@ -100,10 +100,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
return invoiceSearch()
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal window asking the admin the details to refund the user about the provided invoice
|
||||
// @param invoice {Object} invoice inherited from angular's $resource
|
||||
// #
|
||||
/**
|
||||
* Open a modal window asking the admin the details to refund the user about the provided invoice
|
||||
* @param invoice {Object} invoice inherited from angular's $resource
|
||||
*/
|
||||
$scope.generateAvoirForInvoice = function (invoice) {
|
||||
// open modal
|
||||
const modalInstance = $uibModal.open({
|
||||
@ -124,10 +124,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Generate an invoice reference sample from the parametrized model
|
||||
// @returns {string} invoice reference sample
|
||||
// #
|
||||
/**
|
||||
* Generate an invoice reference sample from the parametrized model
|
||||
* @returns {string} invoice reference sample
|
||||
*/
|
||||
$scope.mkReference = function () {
|
||||
let sample = $scope.invoice.reference.model
|
||||
if (sample) {
|
||||
@ -149,10 +149,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
return sample
|
||||
}
|
||||
|
||||
// #
|
||||
// Generate an order nmuber sample from the parametrized model
|
||||
// @returns {string} invoice reference sample
|
||||
// #
|
||||
/**
|
||||
* Generate an order nmuber sample from the parametrized model
|
||||
* @returns {string} invoice reference sample
|
||||
*/
|
||||
$scope.mkNumber = function () {
|
||||
let sample = $scope.invoice.number.model
|
||||
if (sample) {
|
||||
@ -170,9 +170,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
return sample
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the user to edit the invoice reference generation template
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the invoice reference generation template
|
||||
*/
|
||||
$scope.openEditReference = function () {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
@ -202,9 +202,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
)
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the user to edit the invoice code
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the invoice code
|
||||
*/
|
||||
$scope.openEditCode = function () {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
@ -254,9 +254,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the user to edit the invoice number
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the invoice number
|
||||
*/
|
||||
$scope.openEditInvoiceNb = function () {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
@ -286,10 +286,10 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
)
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the user to edit the VAT parameters for the invoices
|
||||
// The VAT can be disabled and its rate can be configured
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the VAT parameters for the invoices
|
||||
* The VAT can be disabled and its rate can be configured
|
||||
*/
|
||||
$scope.openEditVAT = function () {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
@ -339,9 +339,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to save the value of the text zone when editing is done
|
||||
// #
|
||||
/**
|
||||
* Callback to save the value of the text zone when editing is done
|
||||
*/
|
||||
$scope.textEditEnd = function (event) {
|
||||
const parsed = parseHtml($scope.invoice.text.content)
|
||||
return Setting.update({ name: 'invoice_text' }, { value: parsed }, function (data) {
|
||||
@ -354,9 +354,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to save the value of the legal information zone when editing is done
|
||||
// #
|
||||
/**
|
||||
* Callback to save the value of the legal information zone when editing is done
|
||||
*/
|
||||
$scope.legalsEditEnd = function (event) {
|
||||
const parsed = parseHtml($scope.invoice.legals.content)
|
||||
return Setting.update({ name: 'invoice_legals' }, { value: parsed }, function (data) {
|
||||
@ -369,19 +369,19 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback when any of the filters changes.
|
||||
// Full reload the results list
|
||||
// #
|
||||
/**
|
||||
* Callback when any of the filters changes.
|
||||
* Full reload the results list
|
||||
*/
|
||||
$scope.handleFilterChange = function () {
|
||||
resetSearchInvoice()
|
||||
return invoiceSearch()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback for the 'load more' button.
|
||||
// Will load the next results of the current search, if any
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'load more' button.
|
||||
* Will load the next results of the current search, if any
|
||||
*/
|
||||
$scope.showNextInvoices = function () {
|
||||
$scope.page += 1
|
||||
return invoiceSearch(true)
|
||||
@ -389,9 +389,9 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if (!invoices[0] || (invoices[0].maxInvoices <= $scope.invoices.length)) {
|
||||
$scope.noMoreResults = true
|
||||
@ -424,20 +424,20 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Output the given integer with leading zeros. If the given value is longer than the given
|
||||
// length, it will be truncated.
|
||||
// @param value {number} the integer to pad
|
||||
// @param length {number} the length of the resulting string.
|
||||
// #
|
||||
/**
|
||||
* Output the given integer with leading zeros. If the given value is longer than the given
|
||||
* length, it will be truncated.
|
||||
* @param value {number} the integer to pad
|
||||
* @param length {number} the length of the resulting string.
|
||||
*/
|
||||
var padWithZeros = (value, length) => (1e15 + value + '').slice(-length)
|
||||
|
||||
// #
|
||||
// Remove every unsupported html tag from the given html text (like <p>, <span>, ...).
|
||||
// The supported tags are <b>, <u>, <i> and <br>.
|
||||
// @param html {string} single line html text
|
||||
// @return {string} multi line simplified html text
|
||||
// #
|
||||
/**
|
||||
* Remove every unsupported html tag from the given html text (like <p>, <span>, ...).
|
||||
* The supported tags are <b>, <u>, <i> and <br>.
|
||||
* @param html {string} single line html text
|
||||
* @return {string} multi line simplified html text
|
||||
*/
|
||||
var parseHtml = html =>
|
||||
html = html.replace(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/g, function (match, p1, offset, string) {
|
||||
if (['b', 'u', 'i', 'br'].includes(p1)) {
|
||||
@ -447,19 +447,19 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Reinitialize the context of invoices' search to display new results set
|
||||
// #
|
||||
/**
|
||||
* Reinitialize the context of invoices' search to display new results set
|
||||
*/
|
||||
var resetSearchInvoice = function () {
|
||||
$scope.page = 1
|
||||
return $scope.noMoreResults = false
|
||||
}
|
||||
|
||||
// #
|
||||
// Run a search query with the current parameters set concerning invoices, then affect or concat the results
|
||||
// to $scope.invoices
|
||||
// @param concat {boolean} if true, the result will be append to $scope.invoices instead of being affected
|
||||
// #
|
||||
/**
|
||||
* Run a search query with the current parameters set concerning invoices, then affect or concat the results
|
||||
* to $scope.invoices
|
||||
* @param concat {boolean} if true, the result will be append to $scope.invoices instead of being affected
|
||||
*/
|
||||
var invoiceSearch = concat =>
|
||||
Invoice.list({
|
||||
query: {
|
||||
@ -482,32 +482,32 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
}
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the invoice refunding modal window
|
||||
// #
|
||||
/**
|
||||
* Controller used in the invoice refunding modal window
|
||||
*/
|
||||
Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModalInstance', 'invoice', 'Invoice', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, invoice, Invoice, growl, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # invoice linked to the current refund
|
||||
// invoice linked to the current refund
|
||||
$scope.invoice = invoice
|
||||
|
||||
// # Associative array containing invoice_item ids associated with boolean values
|
||||
// Associative array containing invoice_item ids associated with boolean values
|
||||
$scope.partial = {}
|
||||
|
||||
// # Default refund parameters
|
||||
// Default refund parameters
|
||||
$scope.avoir = {
|
||||
invoice_id: invoice.id,
|
||||
subscription_to_expire: false,
|
||||
invoice_items_ids: []
|
||||
}
|
||||
|
||||
// # Possible refunding methods
|
||||
// Possible refunding methods
|
||||
$scope.avoirModes = [
|
||||
{ name: _t('none'), value: 'none' },
|
||||
{ name: _t('by_cash'), value: 'cash' },
|
||||
@ -516,12 +516,12 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
{ name: _t('by_wallet'), value: 'wallet' }
|
||||
]
|
||||
|
||||
// # If a subscription was took with the current invoice, should it be canceled or not
|
||||
// If a subscription was took with the current invoice, should it be canceled or not
|
||||
$scope.subscriptionExpireOptions = {}
|
||||
$scope.subscriptionExpireOptions[_t('yes')] = true
|
||||
$scope.subscriptionExpireOptions[_t('no')] = false
|
||||
|
||||
// # AngularUI-Bootstrap datepicker parameters to define when to refund
|
||||
// AngularUI-Bootstrap datepicker parameters to define when to refund
|
||||
$scope.datePicker = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -530,18 +530,18 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to open the datepicker
|
||||
// #
|
||||
/**
|
||||
* Callback to open the datepicker
|
||||
*/
|
||||
$scope.openDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = true
|
||||
}
|
||||
|
||||
// #
|
||||
// Validate the refunding and generate a refund invoice
|
||||
// #
|
||||
/**
|
||||
* Validate the refunding and generate a refund invoice
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
// check that at least 1 element of the invoice is refunded
|
||||
$scope.avoir.invoice_items_ids = []
|
||||
@ -564,18 +564,18 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Cancel the refund, dismiss the modal window
|
||||
// #
|
||||
/**
|
||||
* Cancel the refund, dismiss the modal window
|
||||
*/
|
||||
$scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// # if the invoice was payed with stripe, allow to refund through stripe
|
||||
// if the invoice was payed with stripe, allow to refund through stripe
|
||||
Invoice.get({ id: invoice.id }, function (data) {
|
||||
$scope.invoice = data
|
||||
// default : all elements of the invoice are refund
|
||||
@ -588,7 +588,7 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
}
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -17,30 +17,30 @@
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
// #
|
||||
// Provides a set of common properties and methods to the $scope parameter. They are used
|
||||
// in the various members' admin controllers.
|
||||
//
|
||||
// Provides :
|
||||
// - $scope.groups = [{Group}]
|
||||
// - $scope.trainings = [{Training}]
|
||||
// - $scope.plans = []
|
||||
// - $scope.datePicker = {}
|
||||
// - $scope.submited(content)
|
||||
// - $scope.cancel()
|
||||
// - $scope.fileinputClass(v)
|
||||
// - $scope.openDatePicker($event)
|
||||
// - $scope.openSubscriptionDatePicker($event)
|
||||
//
|
||||
// Requires :
|
||||
// - $state (Ui-Router) [ 'app.admin.members' ]
|
||||
// #
|
||||
/**
|
||||
* Provides a set of common properties and methods to the $scope parameter. They are used
|
||||
* in the various members' admin controllers.
|
||||
*
|
||||
* Provides :
|
||||
* - $scope.groups = [{Group}]
|
||||
* - $scope.trainings = [{Training}]
|
||||
* - $scope.plans = []
|
||||
* - $scope.datePicker = {}
|
||||
* - $scope.submited(content)
|
||||
* - $scope.cancel()
|
||||
* - $scope.fileinputClass(v)
|
||||
* - $scope.openDatePicker($event)
|
||||
* - $scope.openSubscriptionDatePicker($event)
|
||||
*
|
||||
* Requires :
|
||||
* - $state (Ui-Router) [ 'app.admin.members' ]
|
||||
*/
|
||||
class MembersController {
|
||||
constructor ($scope, $state, Group, Training) {
|
||||
// # Retrieve the profiles groups (eg. students ...)
|
||||
// Retrieve the profiles groups (eg. students ...)
|
||||
Group.query(groups => $scope.groups = groups.filter(g => (g.slug !== 'admins') && !g.disabled))
|
||||
|
||||
// # Retrieve the list of available trainings
|
||||
// Retrieve the list of available trainings
|
||||
Training.query().$promise.then(data =>
|
||||
$scope.trainings = data.map(d =>
|
||||
({
|
||||
@ -51,7 +51,7 @@ class MembersController {
|
||||
)
|
||||
)
|
||||
|
||||
// # Default parameters for AngularUI-Bootstrap datepicker
|
||||
// Default parameters for AngularUI-Bootstrap datepicker
|
||||
$scope.datePicker = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -61,32 +61,32 @@ class MembersController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Shows the birth day datepicker
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Shows the birth day datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.openDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = true
|
||||
}
|
||||
|
||||
// #
|
||||
// Shows the end of subscription datepicker
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Shows the end of subscription datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.openSubscriptionDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.subscription_date_opened = true
|
||||
}
|
||||
|
||||
// #
|
||||
// For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
// Intended to be the callback when an upload is done: any raised error will be stacked in the
|
||||
// $scope.alerts array. If everything goes fine, the user is redirected to the members listing page.
|
||||
// @param content {Object} JSON - The upload's result
|
||||
// #
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
* Intended to be the callback when an upload is done: any raised error will be stacked in the
|
||||
* $scope.alerts array. If everything goes fine, the user is redirected to the members listing page.
|
||||
* @param content {Object} JSON - The upload's result
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -103,16 +103,16 @@ class MembersController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the admin's view to the members list page
|
||||
// #
|
||||
/**
|
||||
* Changes the admin's view to the members list page
|
||||
*/
|
||||
$scope.cancel = () => $state.go('app.admin.members')
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -123,9 +123,9 @@ class MembersController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used in the members/groups management page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the members/groups management page
|
||||
*/
|
||||
Application.Controllers.controller('AdminMembersController', ['$scope', '$sce', 'membersPromise', 'adminsPromise', 'growl', 'Admin', 'dialogs', '_t', 'Member', 'Export',
|
||||
function ($scope, $sce, membersPromise, adminsPromise, growl, Admin, dialogs, _t, Member, Export) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
@ -135,30 +135,30 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # members list
|
||||
// members list
|
||||
$scope.members = membersPromise
|
||||
|
||||
$scope.member = {
|
||||
// # Members plain-text filtering. Default: not filtered
|
||||
// Members plain-text filtering. Default: not filtered
|
||||
searchText: '',
|
||||
// # Members ordering/sorting. Default: not sorted
|
||||
// Members ordering/sorting. Default: not sorted
|
||||
order: 'id',
|
||||
// # currently displayed page of members
|
||||
// currently displayed page of members
|
||||
page: 1,
|
||||
// # true when all members where loaded
|
||||
// true when all members where loaded
|
||||
noMore: false
|
||||
}
|
||||
|
||||
// # admins list
|
||||
// admins list
|
||||
$scope.admins = adminsPromise.admins
|
||||
|
||||
// # Admins ordering/sorting. Default: not sorted
|
||||
// Admins ordering/sorting. Default: not sorted
|
||||
$scope.orderAdmin = null
|
||||
|
||||
// #
|
||||
// Change the members ordering criterion to the one provided
|
||||
// @param orderBy {string} ordering criterion
|
||||
// #
|
||||
/**
|
||||
* Change the members ordering criterion to the one provided
|
||||
* @param orderBy {string} ordering criterion
|
||||
*/
|
||||
$scope.setOrderMember = function (orderBy) {
|
||||
if ($scope.member.order === orderBy) {
|
||||
$scope.member.order = `-${orderBy}`
|
||||
@ -170,10 +170,10 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
return memberSearch()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the admins ordering criterion to the one provided
|
||||
// @param orderBy {string} ordering criterion
|
||||
// #
|
||||
/**
|
||||
* Change the admins ordering criterion to the one provided
|
||||
* @param orderBy {string} ordering criterion
|
||||
*/
|
||||
$scope.setOrderAdmin = function (orderAdmin) {
|
||||
if ($scope.orderAdmin === orderAdmin) {
|
||||
return $scope.orderAdmin = `-${orderAdmin}`
|
||||
@ -182,11 +182,11 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Ask for confirmation then delete the specified administrator
|
||||
// @param admins {Array} full list of administrators
|
||||
// @param admin {Object} administrator to delete
|
||||
// #
|
||||
/**
|
||||
* Ask for confirmation then delete the specified administrator
|
||||
* @param admins {Array} full list of administrators
|
||||
* @param admin {Object} administrator to delete
|
||||
*/
|
||||
$scope.destroyAdmin = (admins, admin) =>
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
@ -206,27 +206,27 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
, error => growl.error(_t('unable_to_delete_the_administrator')))
|
||||
)
|
||||
|
||||
// #
|
||||
// Callback for the 'load more' button.
|
||||
// Will load the next results of the current search, if any
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'load more' button.
|
||||
* Will load the next results of the current search, if any
|
||||
*/
|
||||
$scope.showNextMembers = function () {
|
||||
$scope.member.page += 1
|
||||
return memberSearch(true)
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback when the search field content changes: reload the search results
|
||||
// #
|
||||
/**
|
||||
* Callback when the search field content changes: reload the search results
|
||||
*/
|
||||
$scope.updateTextSearch = function () {
|
||||
resetSearchMember()
|
||||
return memberSearch()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to alert the admin that the export request was acknowledged and is
|
||||
// processing right now.
|
||||
// #
|
||||
/**
|
||||
* Callback to alert the admin that the export request was acknowledged and is
|
||||
* processing right now.
|
||||
*/
|
||||
$scope.alertExport = type =>
|
||||
Export.status({ category: 'users', type }).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
@ -236,37 +236,37 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if (!membersPromise[0] || (membersPromise[0].maxMembers <= $scope.members.length)) {
|
||||
return $scope.member.noMore = true
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Iterate through the provided array and return the index of the requested admin
|
||||
// @param admins {Array} full list of users with role 'admin'
|
||||
// @param id {Number} user id of the admin to retrieve in the list
|
||||
// @returns {Number} index of the requested admin, in the provided array
|
||||
// #
|
||||
/**
|
||||
* Iterate through the provided array and return the index of the requested admin
|
||||
* @param admins {Array} full list of users with role 'admin'
|
||||
* @param id {Number} user id of the admin to retrieve in the list
|
||||
* @returns {Number} index of the requested admin, in the provided array
|
||||
*/
|
||||
var findAdminIdxById = (admins, id) =>
|
||||
(admins.map(admin => admin.id)).indexOf(id)
|
||||
|
||||
// #
|
||||
// Reinitialize the context of members's search to display new results set
|
||||
// #
|
||||
/**
|
||||
* Reinitialize the context of members's search to display new results set
|
||||
*/
|
||||
var resetSearchMember = function () {
|
||||
$scope.member.noMore = false
|
||||
return $scope.member.page = 1
|
||||
}
|
||||
|
||||
// #
|
||||
// Run a search query with the current parameters set ($scope.member[searchText,order,page])
|
||||
// and affect or append the result in $scope.members, depending on the concat parameter
|
||||
// @param concat {boolean} if true, the result will be append to $scope.members instead of being affected
|
||||
// #
|
||||
/**
|
||||
* Run a search query with the current parameters set ($scope.member[searchText,order,page])
|
||||
* and affect or append the result in $scope.members, depending on the concat parameter
|
||||
* @param concat {boolean} if true, the result will be append to $scope.members instead of being affected
|
||||
*/
|
||||
var memberSearch = concat =>
|
||||
Member.list({ query: { search: $scope.member.searchText, order_by: $scope.member.order, page: $scope.member.page, size: USERS_PER_PAGE } }, function (members) {
|
||||
if (concat) {
|
||||
@ -280,35 +280,35 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
}
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the member edition page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the member edition page
|
||||
*/
|
||||
Application.Controllers.controller('EditMemberController', ['$scope', '$state', '$stateParams', 'Member', 'Training', 'dialogs', 'growl', 'Group', 'Subscription', 'CSRF', 'memberPromise', 'tagsPromise', '$uibModal', 'Plan', '$filter', '_t', 'walletPromise', 'transactionsPromise', 'activeProviderPromise', 'Wallet',
|
||||
function ($scope, $state, $stateParams, Member, Training, dialogs, growl, Group, Subscription, CSRF, memberPromise, tagsPromise, $uibModal, Plan, $filter, _t, walletPromise, transactionsPromise, activeProviderPromise, Wallet) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/members/${$stateParams.id}`
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'patch'
|
||||
|
||||
// # List of tags associables with user
|
||||
// List of tags associables with user
|
||||
$scope.tags = tagsPromise
|
||||
|
||||
// # The user to edit
|
||||
// The user to edit
|
||||
$scope.user = memberPromise
|
||||
|
||||
// # Should the passord be modified?
|
||||
// Should the passord be modified?
|
||||
$scope.password =
|
||||
{ change: false }
|
||||
|
||||
// # the user subscription
|
||||
// the user subscription
|
||||
if (($scope.user.subscribed_plan != null) && ($scope.user.subscription != null)) {
|
||||
$scope.subscription = $scope.user.subscription
|
||||
$scope.subscription.expired_at = $scope.subscription.expired_at
|
||||
@ -320,29 +320,29 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
})
|
||||
}
|
||||
|
||||
// # Available trainings list
|
||||
// Available trainings list
|
||||
$scope.trainings = []
|
||||
|
||||
// # Profiles types (student/standard/...)
|
||||
// Profiles types (student/standard/...)
|
||||
$scope.groups = []
|
||||
|
||||
// # the user wallet
|
||||
// the user wallet
|
||||
$scope.wallet = walletPromise
|
||||
|
||||
// # user wallet transactions
|
||||
// user wallet transactions
|
||||
$scope.transactions = transactionsPromise
|
||||
|
||||
// # used in wallet partial template to identify parent view
|
||||
// used in wallet partial template to identify parent view
|
||||
$scope.view = 'member_edit'
|
||||
|
||||
// current active authentication provider
|
||||
$scope.activeProvider = activeProviderPromise
|
||||
|
||||
// #
|
||||
// Open a modal dialog, allowing the admin to extend the current user's subscription (freely or not)
|
||||
// @param subscription {Object} User's subscription object
|
||||
// @param free {boolean} True if the extent is offered, false otherwise
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog, allowing the admin to extend the current user's subscription (freely or not)
|
||||
* @param subscription {Object} User's subscription object
|
||||
* @param free {boolean} True if the extent is offered, false otherwise
|
||||
*/
|
||||
$scope.updateSubscriptionModal = function (subscription, free) {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
@ -380,36 +380,36 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
return modalInstance.result.then(subscription => $scope.subscription.expired_at = subscription.expired_at)
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the admin to set a subscription for the given user.
|
||||
// @param user {Object} User object, user currently reviewed, as recovered from GET /api/members/:id
|
||||
// @param plans {Array} List of plans, availables for the currently reviewed user, as recovered from GET /api/plans
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the admin to set a subscription for the given user.
|
||||
* @param user {Object} User object, user currently reviewed, as recovered from GET /api/members/:id
|
||||
* @param plans {Array} List of plans, availables for the currently reviewed user, as recovered from GET /api/plans
|
||||
*/
|
||||
$scope.createSubscriptionModal = function (user, plans) {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: '<%= asset_path "admin/subscriptions/create_modal.html" %>',
|
||||
size: 'lg',
|
||||
controller: ['$scope', '$uibModalInstance', 'Subscription', 'Group', function ($scope, $uibModalInstance, Subscription, Group) {
|
||||
// # selected user
|
||||
// selected user
|
||||
$scope.user = user
|
||||
|
||||
// # available plans for the selected user
|
||||
// available plans for the selected user
|
||||
$scope.plans = plans
|
||||
|
||||
// #
|
||||
// Generate a string identifying the given plan by literal humain-readable name
|
||||
// @param plan {Object} Plan object, as recovered from GET /api/plan/:id
|
||||
// @param groups {Array} List of Groups objects, as recovered from GET /api/groups
|
||||
// @param short {boolean} If true, the generated name will contains the group slug, otherwise the group full name
|
||||
// will be included.
|
||||
// @returns {String}
|
||||
// #
|
||||
/**
|
||||
* Generate a string identifying the given plan by literal humain-readable name
|
||||
* @param plan {Object} Plan object, as recovered from GET /api/plan/:id
|
||||
* @param groups {Array} List of Groups objects, as recovered from GET /api/groups
|
||||
* @param short {boolean} If true, the generated name will contains the group slug, otherwise the group full name
|
||||
* will be included.
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.humanReadablePlanName = (plan, groups, short) => `${$filter('humanReadablePlanName')(plan, groups, short)}`
|
||||
|
||||
// #
|
||||
// Modal dialog validation callback
|
||||
// #
|
||||
/**
|
||||
* Modal dialog validation callback
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$scope.subscription.user_id = user.id
|
||||
return Subscription.save({ }, { subscription: $scope.subscription }, function (_subscription) {
|
||||
@ -420,9 +420,9 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
, error => growl.error(_t('a_problem_occurred_while_taking_the_subscription')))
|
||||
}
|
||||
|
||||
// #
|
||||
// Modal dialog cancellation callback
|
||||
// #
|
||||
/**
|
||||
* Modal dialog cancellation callback
|
||||
*/
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
}
|
||||
] })
|
||||
@ -453,18 +453,18 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to open/close the date picker
|
||||
// #
|
||||
/**
|
||||
* Callback to open/close the date picker
|
||||
*/
|
||||
$scope.toggleDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened
|
||||
}
|
||||
|
||||
// #
|
||||
// Modal dialog validation callback
|
||||
// #
|
||||
/**
|
||||
* Modal dialog validation callback
|
||||
*/
|
||||
$scope.ok = () =>
|
||||
Wallet.credit({ id: wallet.id }, {
|
||||
amount: $scope.amount,
|
||||
@ -478,9 +478,9 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
}
|
||||
, error => growl.error(_t('a_problem_occurred_for_wallet_credit')))
|
||||
|
||||
// #
|
||||
// Modal dialog cancellation callback
|
||||
// #
|
||||
/**
|
||||
* Modal dialog cancellation callback
|
||||
*/
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
}
|
||||
] })
|
||||
@ -491,23 +491,23 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// To use as callback in Array.prototype.filter to get only enabled plans
|
||||
// #
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = plan => !plan.disabled
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// init the birth date to JS object
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate()
|
||||
|
||||
// # the user subscription
|
||||
// the user subscription
|
||||
if (($scope.user.subscribed_plan != null) && ($scope.user.subscription != null)) {
|
||||
$scope.subscription = $scope.user.subscription
|
||||
$scope.subscription.expired_at = $scope.subscription.expired_at
|
||||
@ -523,36 +523,36 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
return new MembersController($scope, $state, Group, Training)
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the member's creation page (admin view)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the member's creation page (admin view)
|
||||
*/
|
||||
Application.Controllers.controller('NewMemberController', ['$scope', '$state', '$stateParams', 'Member', 'Training', 'Group', 'CSRF',
|
||||
function ($scope, $state, $stateParams, Member, Training, Group, CSRF) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/members'
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # Should the passord be set manually or generated?
|
||||
// Should the passord be set manually or generated?
|
||||
$scope.password =
|
||||
{ change: false }
|
||||
|
||||
// # Default member's profile parameters
|
||||
// Default member's profile parameters
|
||||
$scope.user =
|
||||
{ plan_interval: '' }
|
||||
|
||||
// # Callback when the admin check/unckeck the box telling that the new user is an organization.
|
||||
// # Disable or enable the organization fields in the form, accordingly
|
||||
// Callback when the admin check/unckeck the box telling that the new user is an organization.
|
||||
// Disable or enable the organization fields in the form, accordingly
|
||||
$scope.toggleOrganization = function () {
|
||||
if ($scope.user.organization) {
|
||||
if (!$scope.user.profile) { $scope.user.profile = {} }
|
||||
@ -562,16 +562,16 @@ Application.Controllers.controller('NewMemberController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// # Using the MembersController
|
||||
// Using the MembersController
|
||||
return new MembersController($scope, $state, Group, Training)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the admin's creation page (admin view)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the admin's creation page (admin view)
|
||||
*/
|
||||
Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'Admin', 'growl', '_t', function ($state, $scope, Admin, growl, _t) {
|
||||
// # default admin profile
|
||||
// default admin profile
|
||||
let getGender
|
||||
$scope.admin = {
|
||||
profile_attributes: {
|
||||
@ -579,7 +579,7 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
}
|
||||
}
|
||||
|
||||
// # Default parameters for AngularUI-Bootstrap datepicker
|
||||
// Default parameters for AngularUI-Bootstrap datepicker
|
||||
$scope.datePicker = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false,
|
||||
@ -588,15 +588,15 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Shows the birth day datepicker
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Shows the birth day datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.openDatePicker = $event => $scope.datePicker.opened = true
|
||||
|
||||
// #
|
||||
// Send the new admin, currently stored in $scope.admin, to the server for database saving
|
||||
// #
|
||||
/**
|
||||
* Send the new admin, currently stored in $scope.admin, to the server for database saving
|
||||
*/
|
||||
$scope.saveAdmin = () =>
|
||||
Admin.save({}, { admin: $scope.admin }, function () {
|
||||
growl.success(_t('administrator_successfully_created_he_will_receive_his_connection_directives_by_email', { GENDER: getGender($scope.admin) }, 'messageformat'))
|
||||
@ -606,11 +606,11 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Return an enumerable meaninful string for the gender of the provider user
|
||||
// @param user {Object} Database user record
|
||||
// @return {string} 'male' or 'female'
|
||||
// #
|
||||
/**
|
||||
* Return an enumerable meaninful string for the gender of the provider user
|
||||
* @param user {Object} Database user record
|
||||
* @return {string} 'male' or 'female'
|
||||
*/
|
||||
return getGender = function (user) {
|
||||
if (user.profile_attributes) {
|
||||
if (user.profile_attributes.gender) { return 'male' } else { return 'female' }
|
||||
|
@ -25,20 +25,20 @@ class PlanController {
|
||||
// protection against request forgery
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # groups list
|
||||
// groups list
|
||||
$scope.groups = groups.filter(g => (g.slug !== 'admins') && !g.disabled)
|
||||
|
||||
// # users with role 'partner', notifiables for a partner plan
|
||||
// users with role 'partner', notifiables for a partner plan
|
||||
$scope.partners = partners.users
|
||||
|
||||
// # Subscriptions prices, machines prices and training prices, per groups
|
||||
// Subscriptions prices, machines prices and training prices, per groups
|
||||
$scope.group_pricing = prices
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -47,10 +47,10 @@ class PlanController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Mark the provided file for deletion
|
||||
// @param file {Object}
|
||||
// #
|
||||
/**
|
||||
* Mark the provided file for deletion
|
||||
* @param file {Object}
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
if ((file != null) && (file.id != null)) {
|
||||
return file._destroy = true
|
||||
@ -59,30 +59,30 @@ class PlanController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used in the plan creation form
|
||||
// #
|
||||
/**
|
||||
* Controller used in the plan creation form
|
||||
*/
|
||||
Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal', 'groups', 'prices', 'partners', 'CSRF', '$state', 'growl', '_t',
|
||||
function ($scope, $uibModal, groups, prices, partners, CSRF, $state, growl, _t) {
|
||||
({
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// # when creating a new contact for a partner plan, this ID will be sent to the server
|
||||
// when creating a new contact for a partner plan, this ID will be sent to the server
|
||||
NEW_PARTNER_ID: null
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
})
|
||||
|
||||
// # current form is used to create a new plan
|
||||
// current form is used to create a new plan
|
||||
$scope.mode = 'creation'
|
||||
|
||||
// # prices bindings
|
||||
// prices bindings
|
||||
$scope.prices = {
|
||||
training: {},
|
||||
machine: {}
|
||||
}
|
||||
|
||||
// # form inputs bindings
|
||||
// form inputs bindings
|
||||
$scope.plan = {
|
||||
type: null,
|
||||
group_id: null,
|
||||
@ -95,21 +95,21 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
ui_weight: 0
|
||||
}
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/plans/'
|
||||
|
||||
// # HTTP method for the rest API
|
||||
// HTTP method for the rest API
|
||||
$scope.method = 'POST'
|
||||
|
||||
// #
|
||||
// Checks if the partner contact is a valid data. Used in the form validation process
|
||||
// @returns {boolean}
|
||||
// #
|
||||
/**
|
||||
* Checks if the partner contact is a valid data. Used in the form validation process
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$scope.partnerIsValid = () => ($scope.plan.type === 'Plan') || ($scope.plan.partnerId || ($scope.plan.partnerContact && $scope.plan.partnerContact.email))
|
||||
|
||||
// #
|
||||
// Open a modal dialog allowing the admin to create a new partner user
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog allowing the admin to create a new partner user
|
||||
*/
|
||||
$scope.openPartnerNewModal = function (subscription) {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
@ -136,11 +136,11 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Display some messages and redirect the user, once the form was submitted, depending on the result status
|
||||
// (failed/succeeded).
|
||||
// @param content {Object}
|
||||
// #
|
||||
/**
|
||||
* Display some messages and redirect the user, once the form was submitted, depending on the result status
|
||||
* (failed/succeeded).
|
||||
* @param content {Object}
|
||||
*/
|
||||
$scope.afterSubmit = function (content) {
|
||||
if ((content.id == null) && (content.plan_ids == null)) {
|
||||
return growl.error(_t('new_plan.unable_to_create_the_subscription_please_try_again'))
|
||||
@ -160,43 +160,43 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the plan edition form
|
||||
// #
|
||||
/**
|
||||
* Controller used in the plan edition form
|
||||
*/
|
||||
Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'spaces', 'prices', 'partners', 'CSRF', '$state', '$stateParams', 'growl', '$filter', '_t', 'Plan',
|
||||
function ($scope, groups, plans, planPromise, machines, spaces, prices, partners, CSRF, $state, $stateParams, growl, $filter, _t, Plan) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # List of spaces
|
||||
// List of spaces
|
||||
$scope.spaces = spaces
|
||||
|
||||
// # List of plans
|
||||
// List of plans
|
||||
$scope.plans = plans
|
||||
|
||||
// # List of machines
|
||||
// List of machines
|
||||
$scope.machines = machines
|
||||
|
||||
// # List of groups
|
||||
// List of groups
|
||||
$scope.groups = groups
|
||||
|
||||
// # current form is used for edition mode
|
||||
// current form is used for edition mode
|
||||
$scope.mode = 'edition'
|
||||
|
||||
// # edited plan data
|
||||
// edited plan data
|
||||
$scope.plan = planPromise
|
||||
if ($scope.plan.type === null) { $scope.plan.type = 'Plan' }
|
||||
if ($scope.plan.disabled) { $scope.plan.disabled = 'true' }
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/plans/${$stateParams.id}`
|
||||
|
||||
// # HTTP method for the rest API
|
||||
// HTTP method for the rest API
|
||||
$scope.method = 'PATCH'
|
||||
|
||||
// #
|
||||
// If a parent plan was set ($scope.plan.parent), the prices will be copied from this parent plan into
|
||||
// the current plan prices list. Otherwise, the current plan prices will be erased.
|
||||
// #
|
||||
/**
|
||||
* If a parent plan was set ($scope.plan.parent), the prices will be copied from this parent plan into
|
||||
* the current plan prices list. Otherwise, the current plan prices will be erased.
|
||||
*/
|
||||
$scope.copyPricesFromPlan = function () {
|
||||
if ($scope.plan.parent) {
|
||||
return Plan.get({ id: $scope.plan.parent }, parentPlan =>
|
||||
@ -229,10 +229,10 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Display some messages once the form was submitted, depending on the result status (failed/succeeded)
|
||||
// @param content {Object}
|
||||
// #
|
||||
/**
|
||||
* Display some messages once the form was submitted, depending on the result status (failed/succeeded)
|
||||
* @param content {Object}
|
||||
*/
|
||||
$scope.afterSubmit = function (content) {
|
||||
if ((content.id == null) && (content.plan_ids == null)) {
|
||||
return growl.error(_t('edit_plan.unable_to_save_subscription_changes_please_try_again'))
|
||||
@ -242,21 +242,21 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Generate a string identifying the given plan by literal humain-readable name
|
||||
// @param plan {Object} Plan object, as recovered from GET /api/plan/:id
|
||||
// @param groups {Array} List of Groups objects, as recovered from GET /api/groups
|
||||
// @param short {boolean} If true, the generated name will contains the group slug, otherwise the group full name
|
||||
// will be included.
|
||||
// @returns {String}
|
||||
// #
|
||||
/**
|
||||
* Generate a string identifying the given plan by literal humain-readable name
|
||||
* @param plan {Object} Plan object, as recovered from GET /api/plan/:id
|
||||
* @param groups {Array} List of Groups objects, as recovered from GET /api/groups
|
||||
* @param short {boolean} If true, the generated name will contains the group slug, otherwise the group full name
|
||||
* will be included.
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.humanReadablePlanName = (plan, groups, short) => `${$filter('humanReadablePlanName')(plan, groups, short)}`
|
||||
|
||||
// #
|
||||
// Retrieve the machine from its ID
|
||||
// @param machine_id {number} machine identifier
|
||||
// @returns {Object} Machine
|
||||
// #
|
||||
/**
|
||||
* Retrieve the machine from its ID
|
||||
* @param machine_id {number} machine identifier
|
||||
* @returns {Object} Machine
|
||||
*/
|
||||
$scope.getMachine = function (machine_id) {
|
||||
for (let machine of Array.from($scope.machines)) {
|
||||
if (machine.id === machine_id) {
|
||||
@ -265,11 +265,11 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve the space from its ID
|
||||
// @param space_id {number} space identifier
|
||||
// @returns {Object} Space
|
||||
// #
|
||||
/**
|
||||
* Retrieve the space from its ID
|
||||
* @param space_id {number} space identifier
|
||||
* @returns {Object} Space
|
||||
*/
|
||||
$scope.getSpace = function (space_id) {
|
||||
for (let space of Array.from($scope.spaces)) {
|
||||
if (space.id === space_id) {
|
||||
@ -280,14 +280,14 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () =>
|
||||
// Using the PlansController
|
||||
new PlanController($scope, groups, prices, partners, CSRF)
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -15,66 +15,66 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
// #
|
||||
// Controller used in the prices edition page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the prices edition page
|
||||
*/
|
||||
Application.Controllers.controller('EditPricingController', ['$scope', '$state', '$uibModal', '$filter', 'TrainingsPricing', 'Credit', 'Pricing', 'Plan', 'Coupon', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', 'couponsPromise', 'spacesPromise', 'spacesPricesPromise', 'spacesCreditsPromise', '_t',
|
||||
function ($scope, $state, $uibModal, $filter, TrainingsPricing, Credit, Pricing, Plan, Coupon, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, couponsPromise, spacesPromise, spacesPricesPromise, spacesCreditsPromise, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
// # List of machines prices (not considering any plan)
|
||||
// List of machines prices (not considering any plan)
|
||||
$scope.machinesPrices = machinesPricesPromise
|
||||
|
||||
// # List of trainings pricing
|
||||
// List of trainings pricing
|
||||
$scope.trainingsPricings = trainingsPricingsPromise
|
||||
|
||||
// # List of available subscriptions plans (eg. student/month, PME/year ...)
|
||||
// List of available subscriptions plans (eg. student/month, PME/year ...)
|
||||
$scope.plans = plans
|
||||
$scope.enabledPlans = plans.filter(p => !p.disabled)
|
||||
|
||||
// # List of groups (eg. normal, student ...)
|
||||
// List of groups (eg. normal, student ...)
|
||||
$scope.groups = groups.filter(g => g.slug !== 'admins')
|
||||
$scope.enabledGroups = groups.filter(g => (g.slug !== 'admins') && !g.disabled)
|
||||
|
||||
// # Associate free machine hours with subscriptions
|
||||
// Associate free machine hours with subscriptions
|
||||
$scope.machineCredits = machineCreditsPromise
|
||||
|
||||
// # Array of associations (plan <-> training)
|
||||
// Array of associations (plan <-> training)
|
||||
$scope.trainingCredits = trainingCreditsPromise
|
||||
|
||||
// # Associate a plan with all its trainings ids
|
||||
// Associate a plan with all its trainings ids
|
||||
$scope.trainingCreditsGroups = {}
|
||||
|
||||
// # List of trainings
|
||||
// List of trainings
|
||||
$scope.trainings = trainingsPromise.filter(t => !t.disabled)
|
||||
|
||||
// # List of machines
|
||||
// List of machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.enabledMachines = machinesPromise.filter(m => !m.disabled)
|
||||
|
||||
// # List of coupons
|
||||
// List of coupons
|
||||
$scope.coupons = couponsPromise
|
||||
|
||||
// # List of spaces
|
||||
// List of spaces
|
||||
$scope.spaces = spacesPromise
|
||||
$scope.enabledSpaces = spacesPromise.filter(s => !s.disabled)
|
||||
|
||||
// # Associate free space hours with subscriptions
|
||||
// Associate free space hours with subscriptions
|
||||
$scope.spaceCredits = spacesCreditsPromise
|
||||
|
||||
// # List of spaces prices (not considering any plan)
|
||||
// List of spaces prices (not considering any plan)
|
||||
$scope.spacesPrices = spacesPricesPromise
|
||||
|
||||
// # The plans list ordering. Default: by group
|
||||
// The plans list ordering. Default: by group
|
||||
$scope.orderPlans = 'group_id'
|
||||
|
||||
// # Status of the drop-down menu in Credits tab
|
||||
// Status of the drop-down menu in Credits tab
|
||||
$scope.status =
|
||||
{ isopen: false }
|
||||
|
||||
// # Default: we show only enabled plans
|
||||
// Default: we show only enabled plans
|
||||
$scope.planFiltering = 'enabled'
|
||||
|
||||
// # Available options for filtering plans by status
|
||||
// Available options for filtering plans by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
@ -97,11 +97,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve a plan from its given identifier and returns it
|
||||
// @param id {number} plan ID
|
||||
// @returns {Object} Plan, inherits from $resource
|
||||
// #
|
||||
/**
|
||||
* Retrieve a plan from its given identifier and returns it
|
||||
* @param id {number} plan ID
|
||||
* @returns {Object} Plan, inherits from $resource
|
||||
*/
|
||||
$scope.getPlanFromId = function (id) {
|
||||
for (let plan of Array.from($scope.plans)) {
|
||||
if (plan.id === parseInt(id)) {
|
||||
@ -110,11 +110,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve a group from its given identifier and returns it
|
||||
// @param id {number} group ID
|
||||
// @returns {Object} Group, inherits from $resource
|
||||
// #
|
||||
/**
|
||||
* Retrieve a group from its given identifier and returns it
|
||||
* @param id {number} group ID
|
||||
* @returns {Object} Group, inherits from $resource
|
||||
*/
|
||||
$scope.getGroupFromId = function (groups, id) {
|
||||
for (let group of Array.from(groups)) {
|
||||
if (group.id === parseInt(id)) {
|
||||
@ -123,12 +123,12 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Returns a human readable string of named trainings, according to the provided array.
|
||||
// $scope.trainings may contains the full list of training. The returned string will only contains the trainings
|
||||
// whom ID are given in the provided parameter
|
||||
// @param trainings {Array<number>} trainings IDs array
|
||||
// #
|
||||
/**
|
||||
* Returns a human readable string of named trainings, according to the provided array.
|
||||
* $scope.trainings may contains the full list of training. The returned string will only contains the trainings
|
||||
* whom ID are given in the provided parameter
|
||||
* @param trainings {Array<number>} trainings IDs array
|
||||
*/
|
||||
$scope.showTrainings = function (trainings) {
|
||||
if (!angular.isArray(trainings) || !(trainings.length > 0)) {
|
||||
return _t('pricing.none')
|
||||
@ -143,11 +143,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
if (selected.length) { return selected.join(' | ') } else { return _t('pricing.none') }
|
||||
}
|
||||
|
||||
// #
|
||||
// Validation callback when editing training's credits. Save the changes.
|
||||
// @param newdata {Object} training and associated plans
|
||||
// @param planId {number|string} plan id
|
||||
// #
|
||||
/**
|
||||
* Validation callback when editing training's credits. Save the changes.
|
||||
* @param newdata {Object} training and associated plans
|
||||
* @param planId {number|string} plan id
|
||||
*/
|
||||
$scope.saveTrainingCredits = function (newdata, planId) {
|
||||
// save the number of credits
|
||||
Plan.update({ id: planId },
|
||||
@ -202,16 +202,16 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Cancel the current training credit modification
|
||||
// @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
// #
|
||||
/**
|
||||
* Cancel the current training credit modification
|
||||
* @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
*/
|
||||
$scope.cancelTrainingCredit = rowform => rowform.$cancel()
|
||||
|
||||
// #
|
||||
// Create a new empty entry in the $scope.machineCredits array
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Create a new empty entry in the $scope.machineCredits array
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.addMachineCredit = function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
@ -221,11 +221,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return $scope.status.isopen = !$scope.status.isopen
|
||||
}
|
||||
|
||||
// #
|
||||
// In the Credits tab, return the name of the machine/space associated with the given credit
|
||||
// @param credit {Object} credit object, inherited from $resource
|
||||
// @returns {String}
|
||||
// #
|
||||
/**
|
||||
* In the Credits tab, return the name of the machine/space associated with the given credit
|
||||
* @param credit {Object} credit object, inherited from $resource
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.showCreditableName = function (credit) {
|
||||
let selected = _t('pricing.not_set')
|
||||
if (credit && credit.creditable_id) {
|
||||
@ -238,11 +238,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return selected
|
||||
}
|
||||
|
||||
// #
|
||||
// In the Credits tab, return the machine/space associated with the given credit
|
||||
// @param credit {Object} credit object, inherited from $resource
|
||||
// @returns {Object}
|
||||
// #
|
||||
/**
|
||||
* In the Credits tab, return the machine/space associated with the given credit
|
||||
* @param credit {Object} credit object, inherited from $resource
|
||||
* @returns {Object}
|
||||
*/
|
||||
$scope.getCreditable = function (credit) {
|
||||
let selected
|
||||
if (credit && credit.creditable_id) {
|
||||
@ -263,12 +263,12 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return selected
|
||||
}
|
||||
|
||||
// #
|
||||
// Validation callback when editing machine's credits. Save the changes.
|
||||
// This will prevent the creation of two credits associating the same machine and plan.
|
||||
// @param data {Object} machine, associated plan and number of credit hours.
|
||||
// @param [id] {number} credit id for edition, create a new credit object if not provided
|
||||
// #
|
||||
/**
|
||||
* Validation callback when editing machine's credits. Save the changes.
|
||||
* This will prevent the creation of two credits associating the same machine and plan.
|
||||
* @param data {Object} machine, associated plan and number of credit hours.
|
||||
* @param [id] {number} credit id for edition, create a new credit object if not provided
|
||||
*/
|
||||
$scope.saveMachineCredit = function (data, id) {
|
||||
for (let mc of Array.from($scope.machineCredits)) {
|
||||
if ((mc.plan_id === data.plan_id) && (mc.creditable_id === data.creditable_id) && ((id === null) || (mc.id !== id))) {
|
||||
@ -297,11 +297,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Removes the newly inserted but not saved machine credit / Cancel the current machine credit modification
|
||||
// @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
// @param index {number} credit index in the $scope.machineCredits array
|
||||
// #
|
||||
/**
|
||||
* Removes the newly inserted but not saved machine credit / Cancel the current machine credit modification
|
||||
* @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
* @param index {number} credit index in the $scope.machineCredits array
|
||||
*/
|
||||
$scope.cancelMachineCredit = function (rowform, index) {
|
||||
if ($scope.machineCredits[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
@ -310,19 +310,19 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Deletes the machine credit at the specified index
|
||||
// @param index {number} machine credit index in the $scope.machineCredits array
|
||||
// #
|
||||
/**
|
||||
* Deletes the machine credit at the specified index
|
||||
* @param index {number} machine credit index in the $scope.machineCredits array
|
||||
*/
|
||||
$scope.removeMachineCredit = function (index) {
|
||||
Credit.delete($scope.machineCredits[index])
|
||||
return $scope.machineCredits.splice(index, 1)
|
||||
}
|
||||
|
||||
// #
|
||||
// Create a new empty entry in the $scope.spaceCredits array
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Create a new empty entry in the $scope.spaceCredits array
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.addSpaceCredit = function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
@ -332,12 +332,12 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return $scope.status.isopen = !$scope.status.isopen
|
||||
}
|
||||
|
||||
// #
|
||||
// Validation callback when editing space's credits. Save the changes.
|
||||
// This will prevent the creation of two credits associated with the same space and plan.
|
||||
// @param data {Object} space, associated plan and number of credit hours.
|
||||
// @param [id] {number} credit id for edition, create a new credit object if not provided
|
||||
// #
|
||||
/**
|
||||
* Validation callback when editing space's credits. Save the changes.
|
||||
* This will prevent the creation of two credits associated with the same space and plan.
|
||||
* @param data {Object} space, associated plan and number of credit hours.
|
||||
* @param [id] {number} credit id for edition, create a new credit object if not provided
|
||||
*/
|
||||
$scope.saveSpaceCredit = function (data, id) {
|
||||
for (let sc of Array.from($scope.spaceCredits)) {
|
||||
if ((sc.plan_id === data.plan_id) && (sc.creditable_id === data.creditable_id) && ((id === null) || (sc.id !== id))) {
|
||||
@ -366,11 +366,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Removes the newly inserted but not saved space credit / Cancel the current space credit modification
|
||||
// @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
// @param index {number} credit index in the $scope.spaceCredits array
|
||||
// #
|
||||
/**
|
||||
* Removes the newly inserted but not saved space credit / Cancel the current space credit modification
|
||||
* @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
* @param index {number} credit index in the $scope.spaceCredits array
|
||||
*/
|
||||
$scope.cancelSpaceCredit = function (rowform, index) {
|
||||
if ($scope.spaceCredits[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
@ -379,30 +379,30 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Deletes the space credit at the specified index
|
||||
// @param index {number} space credit index in the $scope.spaceCredits array
|
||||
// #
|
||||
/**
|
||||
* Deletes the space credit at the specified index
|
||||
* @param index {number} space credit index in the $scope.spaceCredits array
|
||||
*/
|
||||
$scope.removeSpaceCredit = function (index) {
|
||||
Credit.delete($scope.spaceCredits[index])
|
||||
return $scope.spaceCredits.splice(index, 1)
|
||||
}
|
||||
|
||||
// #
|
||||
// If the plan does not have a type, return a default value for display purposes
|
||||
// @param type {string|undefined|null} plan's type (eg. 'partner')
|
||||
// @returns {string}
|
||||
// #
|
||||
/**
|
||||
* If the plan does not have a type, return a default value for display purposes
|
||||
* @param type {string|undefined|null} plan's type (eg. 'partner')
|
||||
* @returns {string}
|
||||
*/
|
||||
$scope.getPlanType = function (type) {
|
||||
if (type === 'PartnerPlan') {
|
||||
return _t('pricing.partner')
|
||||
} else { return _t('pricing.standard') }
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the plans ordering criterion to the one provided
|
||||
// @param orderBy {string} ordering criterion
|
||||
// #
|
||||
/**
|
||||
* Change the plans ordering criterion to the one provided
|
||||
* @param orderBy {string} ordering criterion
|
||||
*/
|
||||
$scope.setOrderPlans = function (orderBy) {
|
||||
if ($scope.orderPlans === orderBy) {
|
||||
return $scope.orderPlans = `-${orderBy}`
|
||||
@ -411,9 +411,9 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve a price from prices array by a machineId and a groupId
|
||||
// #
|
||||
/**
|
||||
* Retrieve a price from prices array by a machineId and a groupId
|
||||
*/
|
||||
$scope.findPriceBy = function (prices, machineId, groupId) {
|
||||
for (let price of Array.from(prices)) {
|
||||
if ((price.priceable_id === machineId) && (price.group_id === groupId)) {
|
||||
@ -422,9 +422,9 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// update a price for a machine and a group, not considering any plan
|
||||
// #
|
||||
/**
|
||||
* update a price for a machine and a group, not considering any plan
|
||||
*/
|
||||
$scope.updatePrice = function (data, price) {
|
||||
if (data != null) {
|
||||
return Price.update({ id: price.id }, { price: { amount: data } }).$promise
|
||||
@ -433,10 +433,10 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Delete the specified subcription plan
|
||||
// @param id {number} plan id
|
||||
// #
|
||||
/**
|
||||
* Delete the specified subcription plan
|
||||
* @param id {number} plan id
|
||||
*/
|
||||
$scope.deletePlan = function (plans, id) {
|
||||
if (typeof id !== 'number') {
|
||||
return console.error('[EditPricingController::deletePlan] Error: invalid id parameter')
|
||||
@ -467,21 +467,21 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Generate a string identifying the given plan by literal humain-readable name
|
||||
// @param plan {Object} Plan object, as recovered from GET /api/plan/:id
|
||||
// @param groups {Array} List of Groups objects, as recovered from GET /api/groups
|
||||
// @param short {boolean} If true, the generated name will contains the group slug, otherwise the group full name
|
||||
// will be included.
|
||||
// @returns {String}
|
||||
// #
|
||||
/**
|
||||
* Generate a string identifying the given plan by literal humain-readable name
|
||||
* @param plan {Object} Plan object, as recovered from GET /api/plan/:id
|
||||
* @param groups {Array} List of Groups objects, as recovered from GET /api/groups
|
||||
* @param short {boolean} If true, the generated name will contains the group slug, otherwise the group full name
|
||||
* will be included.
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.humanReadablePlanName = (plan, groups, short) => `${$filter('humanReadablePlanName')(plan, groups, short)}`
|
||||
|
||||
// #
|
||||
// Delete a coupon from the server's database and, in case of success, from the list in memory
|
||||
// @param coupons {Array<Object>} should be called with $scope.coupons
|
||||
// @param id {number} ID of the coupon to delete
|
||||
// #
|
||||
/**
|
||||
* Delete a coupon from the server's database and, in case of success, from the list in memory
|
||||
* @param coupons {Array<Object>} should be called with $scope.coupons
|
||||
* @param id {number} ID of the coupon to delete
|
||||
*/
|
||||
$scope.deleteCoupon = function (coupons, id) {
|
||||
if (typeof id !== 'number') {
|
||||
return console.error('[EditPricingController::deleteCoupon] Error: invalid id parameter')
|
||||
@ -516,10 +516,10 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal allowing to select an user and send him the details of the provided coupon
|
||||
// @param coupon {Object} The coupon to send
|
||||
// #
|
||||
/**
|
||||
* Open a modal allowing to select an user and send him the details of the provided coupon
|
||||
* @param coupon {Object} The coupon to send
|
||||
*/
|
||||
$scope.sendCouponToUser = coupon =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/pricing/sendCoupon.html" %>',
|
||||
@ -528,14 +528,14 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
},
|
||||
size: 'md',
|
||||
controller: ['$scope', '$uibModalInstance', 'Coupon', 'coupon', '_t', function ($scope, $uibModalInstance, Coupon, coupon, _t) {
|
||||
// # Member, receiver of the coupon
|
||||
// Member, receiver of the coupon
|
||||
$scope.ctrl =
|
||||
{ member: null }
|
||||
|
||||
// # Details of the coupon to send
|
||||
// Details of the coupon to send
|
||||
$scope.coupon = coupon
|
||||
|
||||
// # Callback to validate sending of the coupon
|
||||
// Callback to validate sending of the coupon
|
||||
$scope.ok = () =>
|
||||
Coupon.send({ coupon_code: coupon.code, user_id: $scope.ctrl.member.id }, function (res) {
|
||||
growl.success(_t('pricing.coupon_successfully_sent_to_USER', { USER: $scope.ctrl.member.name }))
|
||||
@ -543,20 +543,20 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
, err => growl.error(_t('pricing.an_error_occurred_unable_to_send_the_coupon')))
|
||||
|
||||
// # Callback to close the modal and cancel the sending process
|
||||
// Callback to close the modal and cancel the sending process
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
}
|
||||
] })
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
$scope.trainingCreditsGroups = groupCreditsByPlan($scope.trainingCredits)
|
||||
|
||||
// # adds empty array for plan which hasn't any credits yet
|
||||
// adds empty array for plan which hasn't any credits yet
|
||||
return (() => {
|
||||
const result = []
|
||||
for (let plan of Array.from($scope.plans)) {
|
||||
@ -570,19 +570,19 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
})()
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve an item index by its ID from the given array of objects
|
||||
// @param items {Array<{id:number}>}
|
||||
// @param id {number}
|
||||
// @returns {number} item index in the provided array
|
||||
// #
|
||||
/**
|
||||
* Retrieve an item index by its ID from the given array of objects
|
||||
* @param items {Array<{id:number}>}
|
||||
* @param id {number}
|
||||
* @returns {number} item index in the provided array
|
||||
*/
|
||||
var findItemIdxById = (items, id) =>
|
||||
(items.map(item => item.id)).indexOf(id)
|
||||
|
||||
// #
|
||||
// Group the given credits array into a map associating the plan ID with its associated trainings/machines
|
||||
// @return {Object} the association map
|
||||
// #
|
||||
/**
|
||||
* Group the given credits array into a map associating the plan ID with its associated trainings/machines
|
||||
* @return {Object} the association map
|
||||
*/
|
||||
var groupCreditsByPlan = function (credits) {
|
||||
const creditsMap = {}
|
||||
angular.forEach(credits, function (c) {
|
||||
@ -594,11 +594,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return creditsMap
|
||||
}
|
||||
|
||||
// #
|
||||
// Iterate through $scope.traininfCredits to find the credit matching the given criterion
|
||||
// @param trainingId {number|string} training ID
|
||||
// @param planId {number|string} plan ID
|
||||
// #
|
||||
/**
|
||||
* Iterate through $scope.traininfCredits to find the credit matching the given criterion
|
||||
* @param trainingId {number|string} training ID
|
||||
* @param planId {number|string} plan ID
|
||||
*/
|
||||
var findTrainingCredit = function (trainingId, planId) {
|
||||
trainingId = parseInt(trainingId)
|
||||
planId = parseInt(planId)
|
||||
@ -610,11 +610,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve a training from its given identifier and returns it
|
||||
// @param id {number} training ID
|
||||
// @returns {Object} Training inherited from $resource
|
||||
// #
|
||||
/**
|
||||
* Retrieve a training from its given identifier and returns it
|
||||
* @param id {number} training ID
|
||||
* @returns {Object} Training inherited from $resource
|
||||
*/
|
||||
var getTrainingFromId = function (id) {
|
||||
for (let training of Array.from($scope.trainings)) {
|
||||
if (training.id === parseInt(id)) {
|
||||
@ -623,7 +623,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -19,70 +19,70 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// # search window size
|
||||
// search window size
|
||||
const RESULTS_PER_PAGE = 20
|
||||
|
||||
// # keep search context for (delay in minutes) ...
|
||||
// keep search context for (delay in minutes) ...
|
||||
const ES_SCROLL_TIME = 1
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # ui-view transitions optimization: if true, the stats will never be refreshed
|
||||
// ui-view transitions optimization: if true, the stats will never be refreshed
|
||||
$scope.preventRefresh = false
|
||||
|
||||
// # statistics structure in elasticSearch
|
||||
// statistics structure in elasticSearch
|
||||
$scope.statistics = statisticsPromise
|
||||
|
||||
// # fablab users list
|
||||
// fablab users list
|
||||
$scope.members = membersPromise
|
||||
|
||||
// # statistics data recovered from elasticSearch
|
||||
// statistics data recovered from elasticSearch
|
||||
$scope.data = null
|
||||
|
||||
// # when did the search was triggered
|
||||
// when did the search was triggered
|
||||
$scope.searchDate = null
|
||||
|
||||
// # id of the elastic search context
|
||||
// id of the elastic search context
|
||||
$scope.scrollId = null
|
||||
|
||||
// # total number of results for the current query
|
||||
// total number of results for the current query
|
||||
$scope.totalHits = null
|
||||
|
||||
// # configuration of the widget allowing to pick the ages range
|
||||
// configuration of the widget allowing to pick the ages range
|
||||
$scope.agePicker = {
|
||||
show: false,
|
||||
start: null,
|
||||
end: null
|
||||
}
|
||||
|
||||
// # total CA for the current view
|
||||
// total CA for the current view
|
||||
$scope.sumCA = 0
|
||||
|
||||
// # average users' age for the current view
|
||||
// average users' age for the current view
|
||||
$scope.averageAge = 0
|
||||
|
||||
// # total of the stat field for non simple types
|
||||
// total of the stat field for non simple types
|
||||
$scope.sumStat = 0
|
||||
|
||||
// # Results of custom aggregations for the current type
|
||||
// Results of custom aggregations for the current type
|
||||
$scope.customAggs = {}
|
||||
|
||||
// # default: results are not sorted
|
||||
// default: results are not sorted
|
||||
$scope.sorting = {
|
||||
ca: 'none',
|
||||
date: 'desc'
|
||||
}
|
||||
|
||||
// # active tab will be set here
|
||||
// active tab will be set here
|
||||
$scope.selectedIndex = null
|
||||
|
||||
// # type filter binding
|
||||
// type filter binding
|
||||
$scope.type = {
|
||||
selected: null,
|
||||
active: null
|
||||
}
|
||||
|
||||
// # selected custom filter
|
||||
// selected custom filter
|
||||
$scope.customFilter = {
|
||||
show: false,
|
||||
criterion: {},
|
||||
@ -99,14 +99,14 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
} // France: the week starts on monday
|
||||
}
|
||||
|
||||
// # available custom filters
|
||||
// available custom filters
|
||||
$scope.filters = []
|
||||
|
||||
// # default: we do not open the datepicker menu
|
||||
// default: we do not open the datepicker menu
|
||||
$scope.datePicker =
|
||||
{ show: false }
|
||||
|
||||
// # datePicker parameters for interval beginning
|
||||
// datePicker parameters for interval beginning
|
||||
$scope.datePickerStart = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -118,7 +118,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// # datePicker parameters for interval ending
|
||||
// datePicker parameters for interval ending
|
||||
$scope.datePickerEnd = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -130,29 +130,29 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to open the datepicker (interval start)
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Callback to open the datepicker (interval start)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleStartDatePicker = $event => toggleDatePicker($event, $scope.datePickerStart)
|
||||
|
||||
// #
|
||||
// Callback to open the datepicker (interval end)
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Callback to open the datepicker (interval end)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleEndDatePicker = $event => toggleDatePicker($event, $scope.datePickerEnd)
|
||||
|
||||
// #
|
||||
// Callback to open the datepicker (custom filter)
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Callback to open the datepicker (custom filter)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleCustomDatePicker = $event => toggleDatePicker($event, $scope.customFilter.datePicker)
|
||||
|
||||
// #
|
||||
// Callback called when the active tab is changed.
|
||||
// recover the current tab and store its value in $scope.selectedIndex
|
||||
// @param tab {Object} elasticsearch statistic structure (from statistic_indices table)
|
||||
// #
|
||||
/**
|
||||
* Callback called when the active tab is changed.
|
||||
* recover the current tab and store its value in $scope.selectedIndex
|
||||
* @param tab {Object} elasticsearch statistic structure (from statistic_indices table)
|
||||
*/
|
||||
$scope.setActiveTab = function (tab) {
|
||||
$scope.selectedIndex = tab
|
||||
$scope.type.selected = tab.types[0]
|
||||
@ -166,10 +166,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return refreshStats()
|
||||
}
|
||||
|
||||
// #
|
||||
// Returns true if the provided tab must be hidden due to some global or local configuration
|
||||
// @param tab {Object} elasticsearch statistic structure (from statistic_indices table)
|
||||
// #
|
||||
/**
|
||||
* Returns true if the provided tab must be hidden due to some global or local configuration
|
||||
* @param tab {Object} elasticsearch statistic structure (from statistic_indices table)
|
||||
*/
|
||||
$scope.hiddenTab = function (tab) {
|
||||
if (tab.table) {
|
||||
if ((tab.es_type_key === 'subscription') && $rootScope.fablabWithoutPlans) {
|
||||
@ -184,9 +184,9 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to validate the filters and send a new request to elastic
|
||||
// #
|
||||
/**
|
||||
* Callback to validate the filters and send a new request to elastic
|
||||
*/
|
||||
$scope.validateFilterChange = function () {
|
||||
$scope.agePicker.show = false
|
||||
$scope.customFilter.show = false
|
||||
@ -195,24 +195,24 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return refreshStats()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to validate the dates range and refresh the data from elastic
|
||||
// #
|
||||
/**
|
||||
* Callback to validate the dates range and refresh the data from elastic
|
||||
*/
|
||||
$scope.validateDateChange = function () {
|
||||
$scope.datePicker.show = false
|
||||
return refreshStats()
|
||||
}
|
||||
|
||||
// #
|
||||
// Parse the given date and return a user-friendly string
|
||||
// @param date {Date} JS date or ant moment.js compatible date string
|
||||
// #
|
||||
/**
|
||||
* Parse the given date and return a user-friendly string
|
||||
* @param date {Date} JS date or ant moment.js compatible date string
|
||||
*/
|
||||
$scope.formatDate = date => moment(date).format('LL')
|
||||
|
||||
// #
|
||||
// Parse the sex and return a user-friendly string
|
||||
// @param sex {string} 'male' | 'female'
|
||||
// #
|
||||
/**
|
||||
* Parse the sex and return a user-friendly string
|
||||
* @param sex {string} 'male' | 'female'
|
||||
*/
|
||||
$scope.formatSex = function (sex) {
|
||||
if (sex === 'male') {
|
||||
return _t('man')
|
||||
@ -222,10 +222,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve the label for the given subtype in the current type
|
||||
// @param key {string} statistic subtype key
|
||||
// #
|
||||
/**
|
||||
* Retrieve the label for the given subtype in the current type
|
||||
* @param key {string} statistic subtype key
|
||||
*/
|
||||
$scope.formatSubtype = function (key) {
|
||||
let label = ''
|
||||
angular.forEach($scope.type.active.subtypes, function (subtype) {
|
||||
@ -236,10 +236,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return label
|
||||
}
|
||||
|
||||
// #
|
||||
// Helper usable in ng-switch to determine the input type to display for custom filter value
|
||||
// @param filter {Object} custom filter criterion
|
||||
// #
|
||||
/**
|
||||
* Helper usable in ng-switch to determine the input type to display for custom filter value
|
||||
* @param filter {Object} custom filter criterion
|
||||
*/
|
||||
$scope.getCustomValueInputType = function (filter) {
|
||||
if (filter && filter.values) {
|
||||
if (typeof (filter.values[0]) === 'string') {
|
||||
@ -252,10 +252,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the sorting order and refresh the results to match the new order
|
||||
// @param filter {Object} any filter
|
||||
// #
|
||||
/**
|
||||
* Change the sorting order and refresh the results to match the new order
|
||||
* @param filter {Object} any filter
|
||||
*/
|
||||
$scope.toggleSorting = function (filter) {
|
||||
switch ($scope.sorting[filter]) {
|
||||
case 'none': $scope.sorting[filter] = 'asc'; break
|
||||
@ -265,19 +265,19 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return refreshStats()
|
||||
}
|
||||
|
||||
// #
|
||||
// Return the user's name from his given ID
|
||||
// @param id {number} user ID
|
||||
// #
|
||||
/**
|
||||
* Return the user's name from his given ID
|
||||
* @param id {number} user ID
|
||||
*/
|
||||
$scope.getUserNameFromId = function (id) {
|
||||
const name = $scope.members[id]
|
||||
return (name || `ID ${id}`)
|
||||
}
|
||||
|
||||
// #
|
||||
// Run a scroll query to elasticsearch to append the next packet of results to those displayed.
|
||||
// If the ES search context has expired when the user ask for more results, we re-run the whole query.
|
||||
// #
|
||||
/**
|
||||
* Run a scroll query to elasticsearch to append the next packet of results to those displayed.
|
||||
* If the ES search context has expired when the user ask for more results, we re-run the whole query.
|
||||
*/
|
||||
$scope.showMoreResults = function () {
|
||||
// if all results were retrieved, do nothing
|
||||
if ($scope.data.length >= $scope.totalHits) {
|
||||
@ -303,9 +303,9 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal dialog asking the user for details about exporting the statistics tables to an excel file
|
||||
// #
|
||||
/**
|
||||
* Open a modal dialog asking the user for details about exporting the statistics tables to an excel file
|
||||
*/
|
||||
$scope.exportToExcel = function () {
|
||||
const options = {
|
||||
templateUrl: '<%= asset_path "admin/statistics/export.html" %>',
|
||||
@ -337,9 +337,9 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () =>
|
||||
// workaround for angular-bootstrap::tabs behavior: on tab deletion, another tab will be selected
|
||||
// which will cause every tabs to reload, one by one, when the view is closed
|
||||
@ -349,20 +349,20 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Generic function to toggle a bootstrap datePicker
|
||||
// @param $event {Object} jQuery event object
|
||||
// @param datePicker {Object} settings object of the concerned datepicker. Must have an 'opened' property
|
||||
// #
|
||||
/**
|
||||
* Generic function to toggle a bootstrap datePicker
|
||||
* @param $event {Object} jQuery event object
|
||||
* @param datePicker {Object} settings object of the concerned datepicker. Must have an 'opened' property
|
||||
*/
|
||||
var toggleDatePicker = function ($event, datePicker) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return datePicker.opened = !datePicker.opened
|
||||
}
|
||||
|
||||
// #
|
||||
// Force update the statistics table, querying elasticSearch according to the current config values
|
||||
// #
|
||||
/**
|
||||
* Force update the statistics table, querying elasticSearch according to the current config values
|
||||
*/
|
||||
var refreshStats = function () {
|
||||
if ($scope.selectedIndex && !$scope.preventRefresh) {
|
||||
$scope.data = []
|
||||
@ -395,14 +395,14 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Run the elasticSearch query to retreive the /stats/type aggregations
|
||||
// @param index {String} elasticSearch document type (account|event|machine|project|subscription|training)
|
||||
// @param type {String} statistics type (month|year|booking|hour|user|project)
|
||||
// @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
||||
// @param callback {function} function be to run after results were retrieved, it will receive
|
||||
// two parameters : results {Object}, error {String} (if any)
|
||||
// #
|
||||
/**
|
||||
* Run the elasticSearch query to retreive the /stats/type aggregations
|
||||
* @param index {String} elasticSearch document type (account|event|machine|project|subscription|training)
|
||||
* @param type {String} statistics type (month|year|booking|hour|user|project)
|
||||
* @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
||||
* @param callback {function} function be to run after results were retrieved, it will receive
|
||||
* two parameters : results {Object}, error {String} (if any)
|
||||
*/
|
||||
var queryElasticStats = function (index, type, custom, callback) {
|
||||
// handle invalid callback
|
||||
if (typeof (callback) !== 'function') {
|
||||
@ -431,17 +431,17 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Build an object representing the content of the REST-JSON query to elasticSearch,
|
||||
// based on the provided parameters for row data recovering.
|
||||
// @param type {String} statistics type (month|year|booking|hour|user|project)
|
||||
// @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
||||
// @param ageMin {Number|null} filter by age: range lower value OR null to do not filter
|
||||
// @param ageMax {Number|null} filter by age: range higher value OR null to do not filter
|
||||
// @param intervalBegin {moment} statitics interval beginning (moment.js type)
|
||||
// @param intervalEnd {moment} statitics interval ending (moment.js type)
|
||||
// @param sortings {Array|null} elasticSearch criteria for sorting the results
|
||||
// #
|
||||
/**
|
||||
* Build an object representing the content of the REST-JSON query to elasticSearch,
|
||||
* based on the provided parameters for row data recovering.
|
||||
* @param type {String} statistics type (month|year|booking|hour|user|project)
|
||||
* @param custom {{key:{string}, value:{string}}|null} custom filter property or null to disable this filter
|
||||
* @param ageMin {Number|null} filter by age: range lower value OR null to do not filter
|
||||
* @param ageMax {Number|null} filter by age: range higher value OR null to do not filter
|
||||
* @param intervalBegin {moment} statitics interval beginning (moment.js type)
|
||||
* @param intervalEnd {moment} statitics interval ending (moment.js type)
|
||||
* @param sortings {Array|null} elasticSearch criteria for sorting the results
|
||||
*/
|
||||
var buildElasticDataQuery = function (type, custom, ageMin, ageMax, intervalBegin, intervalEnd, sortings) {
|
||||
const q = {
|
||||
'query': {
|
||||
@ -512,11 +512,11 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return q
|
||||
}
|
||||
|
||||
// #
|
||||
// Build the elasticSearch query DSL to match the selected cutom filter
|
||||
// @param custom {Object} if custom is empty or undefined, an empty string will be returned
|
||||
// @returns {{match:{*}}|string}
|
||||
// #
|
||||
/**
|
||||
* Build the elasticSearch query DSL to match the selected cutom filter
|
||||
* @param custom {Object} if custom is empty or undefined, an empty string will be returned
|
||||
* @returns {{match:{*}}|string}
|
||||
*/
|
||||
var buildElasticCustomCriterion = function (custom) {
|
||||
if (custom) {
|
||||
const criterion = {
|
||||
@ -534,10 +534,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Parse the provided criteria array and return the corresponding elasticSearch syntax
|
||||
// @param criteria {Array} array of {key_to_sort:order}
|
||||
// #
|
||||
/**
|
||||
* Parse the provided criteria array and return the corresponding elasticSearch syntax
|
||||
* @param criteria {Array} array of {key_to_sort:order}
|
||||
*/
|
||||
var buildElasticSortCriteria = function (criteria) {
|
||||
const crits = []
|
||||
angular.forEach(criteria, function (value, key) {
|
||||
@ -550,10 +550,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return crits
|
||||
}
|
||||
|
||||
// #
|
||||
// Fullfil the list of available options in the custom filter panel. The list will be based on common
|
||||
// properties and on index-specific properties (additional_fields)
|
||||
// #
|
||||
/**
|
||||
* Fullfil the list of available options in the custom filter panel. The list will be based on common
|
||||
* properties and on index-specific properties (additional_fields)
|
||||
*/
|
||||
var buildCustomFiltersList = function () {
|
||||
$scope.filters = []
|
||||
|
||||
@ -587,10 +587,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Build and return an object according to the custom filter set by the user, used to request elasticsearch
|
||||
// @return {Object|null}
|
||||
// #
|
||||
/**
|
||||
* Build and return an object according to the custom filter set by the user, used to request elasticsearch
|
||||
* @return {Object|null}
|
||||
*/
|
||||
var buildCustomFilterQuery = function () {
|
||||
let custom = null
|
||||
if (!angular.isUndefinedOrNull($scope.customFilter.criterion) &&
|
||||
@ -612,32 +612,32 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
|
||||
Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$uibModalInstance', 'Export', 'dates', 'query', 'index', 'type', 'CSRF', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, Export, dates, query, index, type, CSRF, growl, _t) {
|
||||
// # Retrieve Anti-CSRF tokens from cookies
|
||||
// Retrieve Anti-CSRF tokens from cookies
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # Bindings for date range
|
||||
// Bindings for date range
|
||||
$scope.dates = dates
|
||||
|
||||
// # Body of the query to export
|
||||
// Body of the query to export
|
||||
$scope.query = JSON.stringify(query)
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/stats/${index.key}/export`
|
||||
|
||||
// # Key of the current search' statistic type
|
||||
// Key of the current search' statistic type
|
||||
$scope.typeKey = type.key
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # Anti-CSRF token to inject into the download form
|
||||
// Anti-CSRF token to inject into the download form
|
||||
$scope.csrfToken = angular.element('meta[name="csrf-token"]')[0].content
|
||||
|
||||
// # Binding of the export type (global / current)
|
||||
// Binding of the export type (global / current)
|
||||
$scope.export =
|
||||
{ type: 'current' }
|
||||
|
||||
// # datePicker parameters for interval beginning
|
||||
// datePicker parameters for interval beginning
|
||||
$scope.exportStart = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -648,7 +648,7 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
}
|
||||
}
|
||||
|
||||
// # datePicker parameters for interval ending
|
||||
// datePicker parameters for interval ending
|
||||
$scope.exportEnd = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -659,22 +659,22 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to open the datepicker (interval start)
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Callback to open the datepicker (interval start)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleStartDatePicker = $event => $scope.exportStart.opened = !$scope.exportStart.opened
|
||||
|
||||
// #
|
||||
// Callback to open the datepicker (interval end)
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Callback to open the datepicker (interval end)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleEndDatePicker = $event => $scope.exportEnd.opened = !$scope.exportEnd.opened
|
||||
|
||||
// #
|
||||
// Callback when exchanging the export type between 'global' and 'current view'
|
||||
// Adjust the query and the requesting url according to this type.
|
||||
// #
|
||||
/**
|
||||
* Callback when exchanging the export type between 'global' and 'current view'
|
||||
* Adjust the query and the requesting url according to this type.
|
||||
*/
|
||||
$scope.setRequest = function () {
|
||||
if ($scope.export.type === 'global') {
|
||||
$scope.actionUrl = '/stats/global/export'
|
||||
@ -700,9 +700,9 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to close the modal, telling the caller what is exported
|
||||
// #
|
||||
/**
|
||||
* Callback to close the modal, telling the caller what is exported
|
||||
*/
|
||||
$scope.exportData = function () {
|
||||
const statusQry = { category: 'statistics', type: $scope.export.type, query: $scope.query }
|
||||
if ($scope.export.type !== 'global') {
|
||||
@ -719,9 +719,9 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
return $uibModalInstance.close(statusQry)
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to cancel the export and close the modal
|
||||
// #
|
||||
/**
|
||||
* Callback to cancel the export and close the modal
|
||||
*/
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
}
|
||||
])
|
||||
|
@ -16,27 +16,27 @@
|
||||
|
||||
/* 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)
|
||||
// - $scope.onDisableToggled
|
||||
//
|
||||
// Requires :
|
||||
// - $state (Ui-Router) [ 'app.admin.trainings' ]
|
||||
// - $scope.training
|
||||
// #
|
||||
/**
|
||||
* 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)
|
||||
* - $scope.onDisableToggled
|
||||
*
|
||||
* Requires :
|
||||
* - $state (Ui-Router) [ 'app.admin.trainings' ]
|
||||
* - $scope.training
|
||||
/*
|
||||
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
|
||||
// #
|
||||
/*
|
||||
* 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 = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -53,21 +53,21 @@ class TrainingsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the current user's view, redirecting him to the machines list
|
||||
// #
|
||||
/**
|
||||
* Changes the current user's view, redirecting him to the machines list
|
||||
*/
|
||||
$scope.cancel = () => $state.go('app.admin.trainings')
|
||||
|
||||
// #
|
||||
// Force the 'public_page' attribute to false when the current training is disabled
|
||||
// #
|
||||
/**
|
||||
* Force the 'public_page' attribute to false when the current training is disabled
|
||||
*/
|
||||
$scope.onDisableToggled = () => $scope.training.public_page = !$scope.training.disabled
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -78,117 +78,117 @@ class TrainingsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used in the training creation page (admin)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the training creation page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('NewTrainingController', [ '$scope', '$state', 'machinesPromise', 'CSRF',
|
||||
function ($scope, $state, machinesPromise, CSRF) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # Form action on the following URL
|
||||
// Form action on the following URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/trainings/'
|
||||
|
||||
// # list of machines
|
||||
// list of machines
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # Using the TrainingsController
|
||||
// Using the TrainingsController
|
||||
return new TrainingsController($scope, $state)
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the training edition page (admin)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the training edition page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('EditTrainingController', [ '$scope', '$state', '$stateParams', 'trainingPromise', 'machinesPromise', 'CSRF',
|
||||
function ($scope, $state, $stateParams, trainingPromise, machinesPromise, CSRF) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # Form action on the following URL
|
||||
// Form action on the following URL
|
||||
$scope.method = 'patch'
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/trainings/${$stateParams.id}`
|
||||
|
||||
// # Details of the training to edit (id in URL)
|
||||
// Details of the training to edit (id in URL)
|
||||
$scope.training = trainingPromise
|
||||
|
||||
// # list of machines
|
||||
// list of machines
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # Using the TrainingsController
|
||||
// Using the TrainingsController
|
||||
return new TrainingsController($scope, $state)
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the trainings management page, allowing admins users to see and manage the list of trainings and reservations.
|
||||
// #
|
||||
/**
|
||||
* 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',
|
||||
function ($scope, $state, $uibModal, Training, trainingsPromise, machinesPromise, _t, growl, dialogs) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # list of trainings
|
||||
// list of trainings
|
||||
let groupAvailabilities
|
||||
$scope.trainings = trainingsPromise
|
||||
|
||||
// # simplified list of machines
|
||||
// simplified list of machines
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
// # Training to monitor, binded with drop-down selection
|
||||
// Training to monitor, binded with drop-down selection
|
||||
$scope.monitoring =
|
||||
{ training: null }
|
||||
|
||||
// # list of training availabilies, grouped by date
|
||||
// list of training availabilies, grouped by date
|
||||
$scope.groupedAvailabilities = {}
|
||||
|
||||
// # default: accordions are not open
|
||||
// default: accordions are not open
|
||||
$scope.accordions = {}
|
||||
|
||||
// # Binding for the parseInt function
|
||||
// Binding for the parseInt function
|
||||
$scope.parseInt = parseInt
|
||||
|
||||
// # Default: we show only enabled trainings
|
||||
// Default: we show only enabled trainings
|
||||
$scope.trainingFiltering = 'enabled'
|
||||
|
||||
// # Available options for filtering trainings by status
|
||||
// Available options for filtering trainings by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
]
|
||||
|
||||
// #
|
||||
// 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}
|
||||
// #
|
||||
/**
|
||||
* 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 = function (training) {
|
||||
const selected = []
|
||||
angular.forEach($scope.machines, function (m) {
|
||||
@ -199,11 +199,11 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
if (selected.length) { return selected.join(', ') } else { return _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
|
||||
// #
|
||||
/**
|
||||
* 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 = function (rowform, index) {
|
||||
if ($scope.trainings[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
@ -212,13 +212,13 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// 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
|
||||
// #
|
||||
/**
|
||||
* 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" %>',
|
||||
@ -227,10 +227,10 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
|
||||
$scope.usersToValid = []
|
||||
|
||||
// #
|
||||
// Mark/unmark the provided user for training validation
|
||||
// @param user {Object} from the availability.reservation_users list
|
||||
// #
|
||||
/**
|
||||
* Mark/unmark the provided user for training validation
|
||||
* @param user {Object} from the availability.reservation_users list
|
||||
*/
|
||||
$scope.toggleSelection = function (user) {
|
||||
const index = $scope.usersToValid.indexOf(user)
|
||||
if (index > -1) {
|
||||
@ -240,9 +240,9 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Validates the modifications (training validations) and save them to the server
|
||||
// #
|
||||
/**
|
||||
* Validates the modifications (training validations) and save them to the server
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
const users = $scope.usersToValid.map(u => u.id)
|
||||
return Training.update({ id: training.id }, {
|
||||
@ -257,18 +257,18 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Cancel the modifications and close the modal window
|
||||
// #
|
||||
/**
|
||||
* Cancel the modifications and close the modal window
|
||||
*/
|
||||
return $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
|
||||
// #
|
||||
/**
|
||||
* 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: {
|
||||
@ -288,23 +288,23 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
, 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'
|
||||
// #
|
||||
/**
|
||||
* Takes a month number and return its localized literal name
|
||||
* @param {Number} from 0 to 11
|
||||
* @returns {String} eg. 'janvier'
|
||||
*/
|
||||
$scope.formatMonth = function (number) {
|
||||
number = parseInt(number)
|
||||
return 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'
|
||||
// #
|
||||
/**
|
||||
* 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 = function (day, month, year) {
|
||||
day = parseInt(day)
|
||||
month = parseInt(month)
|
||||
@ -313,10 +313,10 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
return moment({ year, month, 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.
|
||||
// #
|
||||
/**
|
||||
* 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 }, function (training) {
|
||||
$scope.groupedAvailabilities = groupAvailabilities([training])
|
||||
@ -331,11 +331,11 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
|
||||
/* 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]
|
||||
// #
|
||||
/**
|
||||
* 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]
|
||||
*/
|
||||
return groupAvailabilities = function (trainings) {
|
||||
const tree = {}
|
||||
for (let training of Array.from(trainings)) {
|
||||
|
@ -465,7 +465,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco
|
||||
}
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -166,11 +166,11 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
// Message displayed to the end user about rules that applies to events reservations
|
||||
$scope.eventExplicationsAlert = settingsPromise.event_explications_alert
|
||||
|
||||
// #
|
||||
// Callback to delete the provided event (admins only)
|
||||
// @param event {$resource} angular's Event $resource
|
||||
// #
|
||||
$scope.deleteEvent = function(event) {
|
||||
/**
|
||||
* Callback to delete the provided event (admins only)
|
||||
* @param event {$resource} angular's Event $resource
|
||||
*/
|
||||
$scope.deleteEvent = event =>
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
@ -192,9 +192,9 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
)
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to call when the number of tickets to book changes in the current booking
|
||||
// #
|
||||
/**
|
||||
* Callback to call when the number of tickets to book changes in the current booking
|
||||
*/
|
||||
$scope.changeNbPlaces = function () {
|
||||
// compute the total remaning places
|
||||
let remain = $scope.event.nb_free_places - $scope.reserve.nbReservePlaces
|
||||
@ -220,18 +220,18 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
return $scope.computeEventAmount()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to reset the current reservation parameters
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Callback to reset the current reservation parameters
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.cancelReserve = function (e) {
|
||||
e.preventDefault()
|
||||
return resetEventReserve()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to allow the user to set the details for his reservation
|
||||
// #
|
||||
/**
|
||||
* Callback to allow the user to set the details for his reservation
|
||||
*/
|
||||
$scope.reserveEvent = function () {
|
||||
if ($scope.event.nb_total_places > 0) {
|
||||
$scope.reserveSuccess = false
|
||||
@ -248,10 +248,10 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
// reservations. (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
* reservations. (admins only)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
resetEventReserve()
|
||||
$scope.reserveSuccess = false
|
||||
@ -263,9 +263,9 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to trigger the payment process of the current reservation
|
||||
// #
|
||||
/**
|
||||
* Callback to trigger the payment process of the current reservation
|
||||
*/
|
||||
$scope.payEvent = function () {
|
||||
// first, we check that a user was selected
|
||||
if (Object.keys($scope.ctrl.member).length > 0) {
|
||||
@ -287,9 +287,9 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to validate the booking of a free event
|
||||
// #
|
||||
/**
|
||||
* Callback to validate the booking of a free event
|
||||
*/
|
||||
$scope.validReserveEvent = function () {
|
||||
const reservation = {
|
||||
user_id: $scope.ctrl.member.id,
|
||||
@ -333,12 +333,12 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to alter an already booked reservation date. A modal window will be opened to allow the user to choose
|
||||
// a new date for his reservation (if any available)
|
||||
// @param reservation {{id:number, reservable_id:number, nb_reserve_places:number}}
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Callback to alter an already booked reservation date. A modal window will be opened to allow the user to choose
|
||||
* a new date for his reservation (if any available)
|
||||
* @param reservation {{id:number, reservable_id:number, nb_reserve_places:number}}
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.modifyReservation = function (reservation, e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
@ -409,10 +409,10 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Checks if the provided reservation is able to be moved (date change)
|
||||
// @param reservation {{total_booked_seats:number}}
|
||||
// #
|
||||
/**
|
||||
* Checks if the provided reservation is able to be moved (date change)
|
||||
* @param reservation {{total_booked_seats:number}}
|
||||
*/
|
||||
$scope.reservationCanModify = function (reservation) {
|
||||
const slotStart = moment(reservation.slots[0].start_at)
|
||||
const now = moment()
|
||||
@ -424,10 +424,10 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
return (isAble && $scope.enableBookingMove && (slotStart.diff(now, 'hours') >= $scope.moveBookingDelay))
|
||||
}
|
||||
|
||||
// #
|
||||
// Compute the total amount for the current reservation according to the previously set parameters
|
||||
// and assign the result in $scope.reserve.amountTotal
|
||||
// #
|
||||
/**
|
||||
* Compute the total amount for the current reservation according to the previously set parameters
|
||||
* and assign the result in $scope.reserve.amountTotal
|
||||
*/
|
||||
$scope.computeEventAmount = function () {
|
||||
// first we check that a user was selected
|
||||
if (Object.keys($scope.ctrl.member).length > 0) {
|
||||
@ -441,24 +441,20 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Return the URL allowing to share the current project on the Facebook social network
|
||||
// #
|
||||
$scope.shareOnFacebook = function() {
|
||||
return `https://www.facebook.com/share.php?u=${$state.href('app.public.events_show', { id: $scope.event.id }, { absolute: true }).replace('#', '%23')}`;
|
||||
}
|
||||
/**
|
||||
* Return the URL allowing to share the current project on the Facebook social network
|
||||
*/
|
||||
$scope.shareOnFacebook = () => `https://www.facebook.com/share.php?u=${$state.href('app.public.events_show', { id: $scope.event.id }, { absolute: true }).replace('#', '%23')}`
|
||||
|
||||
// #
|
||||
// Return the URL allowing to share the current project on the Twitter social network
|
||||
// #
|
||||
$scope.shareOnTwitter = function() {
|
||||
return `https://twitter.com/intent/tweet?url=${encodeURIComponent($state.href('app.public.events_show', { id: $scope.event.id }, { absolute: true }))}&text=${encodeURIComponent($scope.event.title)}`;
|
||||
}
|
||||
/**
|
||||
* Return the URL allowing to share the current project on the Twitter social network
|
||||
*/
|
||||
$scope.shareOnTwitter = () => `https://twitter.com/intent/tweet?url=${encodeURIComponent($state.href('app.public.events_show', { id: $scope.event.id }, { absolute: true }))}&text=${encodeURIComponent($scope.event.title)}`
|
||||
|
||||
// #
|
||||
// Return the textual description of the conditions applyable to the given price's category
|
||||
// @param category_id {number} ID of the price's category
|
||||
// #
|
||||
/**
|
||||
* Return the textual description of the conditions applyable to the given price's category
|
||||
* @param category_id {number} ID of the price's category
|
||||
*/
|
||||
$scope.getPriceCategoryConditions = function (category_id) {
|
||||
for (let cat of Array.from($scope.priceCategories)) {
|
||||
if (cat.id === category_id) {
|
||||
@ -469,9 +465,9 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// set the controlled user as the current user if the current user is not an admin
|
||||
if ($scope.currentUser) {
|
||||
@ -496,27 +492,22 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Retrieve the reservations for the couple event / user
|
||||
// @param reservable_id {number} the current event id
|
||||
// @param reservable_type {string} 'Event'
|
||||
// @param user_id {number} the user's id (current or managed)
|
||||
// #
|
||||
const getReservations = function(reservable_id, reservable_type, user_id) {
|
||||
Reservation.query({
|
||||
reservable_id,
|
||||
reservable_type,
|
||||
user_id
|
||||
}).$promise.then(function(reservations) { $scope.reservations = reservations; })
|
||||
}
|
||||
/**
|
||||
* Retrieve the reservations for the couple event / user
|
||||
* @param reservable_id {number} the current event id
|
||||
* @param reservable_type {string} 'Event'
|
||||
* @param user_id {number} the user's id (current or managed)
|
||||
*/
|
||||
var getReservations = (reservable_id, reservable_type, user_id) =>
|
||||
Reservation.query({ reservable_id, reservable_type, user_id }).$promise.then(reservations => $scope.reservations = reservations)
|
||||
|
||||
// #
|
||||
// Create an hash map implementing the Reservation specs
|
||||
// @param member {Object} User as retrieved from the API: current user / selected user if current is admin
|
||||
// @param reserve {Object} Reservation parameters (places...)
|
||||
// @param event {Object} Current event
|
||||
// @return {{user_id:number, reservable_id:number, reservable_type:string, slots_attributes:Array<Object>, nb_reserve_places:number}}
|
||||
// #
|
||||
/**
|
||||
* Create an hash map implementing the Reservation specs
|
||||
* @param member {Object} User as retreived from the API: current user / selected user if current is admin
|
||||
* @param reserve {Object} Reservation parameters (places...)
|
||||
* @param event {Object} Current event
|
||||
* @return {{user_id:number, reservable_id:number, reservable_type:string, slots_attributes:Array<Object>, nb_reserve_places:number}}
|
||||
*/
|
||||
var mkReservation = function (member, reserve, event) {
|
||||
const reservation = {
|
||||
user_id: member.id,
|
||||
@ -547,12 +538,12 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
return reservation
|
||||
}
|
||||
|
||||
// #
|
||||
// Format the parameters expected by /api/prices/compute or /api/reservations and return the resulting object
|
||||
// @param reservation {Object} as returned by mkReservation()
|
||||
// @param coupon {Object} Coupon as returned from the API
|
||||
// @return {{reservation:Object, coupon_code:string}}
|
||||
// #
|
||||
/**
|
||||
* Format the parameters expected by /api/prices/compute or /api/reservations and return the resulting object
|
||||
* @param reservation {Object} as returned by mkReservation()
|
||||
* @param coupon {Object} Coupon as returned from the API
|
||||
* @return {{reservation:Object, coupon_code:string}}
|
||||
*/
|
||||
var mkRequestParams = function (reservation, coupon) {
|
||||
const params = {
|
||||
reservation,
|
||||
@ -562,9 +553,9 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
return params
|
||||
}
|
||||
|
||||
// #
|
||||
// Set the current reservation to the default values. This implies to reservation form to be hidden.
|
||||
// #
|
||||
/**
|
||||
* Set the current reservation to the default values. This implies to reservation form to be hidden.
|
||||
*/
|
||||
var resetEventReserve = function () {
|
||||
if ($scope.event) {
|
||||
$scope.reserve = {
|
||||
@ -587,11 +578,11 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal window which trigger the stripe payment process
|
||||
// @param reservation {Object} to book
|
||||
// #
|
||||
const payByStripe = function(reservation) {
|
||||
/**
|
||||
* Open a modal window which trigger the stripe payment process
|
||||
* @param reservation {Object} to book
|
||||
*/
|
||||
var payByStripe = reservation =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "stripe/payment_modal.html" %>',
|
||||
size: 'md',
|
||||
@ -659,11 +650,11 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}).result['finally'](null).then(function(reservation) { afterPayment(reservation); })
|
||||
};
|
||||
|
||||
// #
|
||||
// Open a modal window which trigger the local payment process
|
||||
// @param reservation {Object} to book
|
||||
// #
|
||||
const payOnSite = function(reservation) {
|
||||
/**
|
||||
* Open a modal window which trigger the local payment process
|
||||
* @param reservation {Object} to book
|
||||
*/
|
||||
var payOnSite = reservation =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "shared/valid_reservation_modal.html" %>',
|
||||
size: 'sm',
|
||||
@ -737,10 +728,10 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
.result['finally'](null).then(function(reservation) { afterPayment(reservation) })
|
||||
}
|
||||
|
||||
// #
|
||||
// What to do after the payment was successful
|
||||
// @param reservation {Object} booked reservation
|
||||
// #
|
||||
/**
|
||||
* What to do after the payment was successful
|
||||
* @param resveration {Object} booked reservation
|
||||
*/
|
||||
var afterPayment = function (reservation) {
|
||||
$scope.event.nb_free_places = $scope.event.nb_free_places - reservation.total_booked_seats
|
||||
resetEventReserve()
|
||||
@ -752,7 +743,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
}
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -16,29 +16,29 @@
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
// #
|
||||
// Provides a set of common callback methods to the $scope parameter. These methods are used
|
||||
// in the various machines' admin controllers.
|
||||
//
|
||||
// Provides :
|
||||
// - $scope.submited(content)
|
||||
// - $scope.cancel()
|
||||
// - $scope.fileinputClass(v)
|
||||
// - $scope.addFile()
|
||||
// - $scope.deleteFile(file)
|
||||
//
|
||||
// Requires :
|
||||
// - $scope.machine.machine_files_attributes = []
|
||||
// - $state (Ui-Router) [ 'app.public.machines_list' ]
|
||||
// #
|
||||
/**
|
||||
* Provides a set of common callback methods to the $scope parameter. These methods are used
|
||||
* in the various machines' admin controllers.
|
||||
*
|
||||
* Provides :
|
||||
* - $scope.submited(content)
|
||||
* - $scope.cancel()
|
||||
* - $scope.fileinputClass(v)
|
||||
* - $scope.addFile()
|
||||
* - $scope.deleteFile(file)
|
||||
*
|
||||
* Requires :
|
||||
* - $scope.machine.machine_files_attributes = []
|
||||
* - $state (Ui-Router) [ 'app.public.machines_list' ]
|
||||
/*
|
||||
class MachinesController {
|
||||
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 machines list.
|
||||
// @param content {Object} JSON - The upload's result
|
||||
// #
|
||||
/*
|
||||
* 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 machines list.
|
||||
* @param content {Object} JSON - The upload's result
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -55,16 +55,16 @@ class MachinesController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the current user's view, redirecting him to the machines list
|
||||
// #
|
||||
/**
|
||||
* Changes the current user's view, redirecting him to the machines list
|
||||
*/
|
||||
$scope.cancel = () => $state.go('app.public.machines_list')
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -73,17 +73,17 @@ class MachinesController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// This will create a single new empty entry into the machine attachements list.
|
||||
// #
|
||||
/**
|
||||
* This will create a single new empty entry into the machine attachements list.
|
||||
*/
|
||||
$scope.addFile = () => $scope.machine.machine_files_attributes.push({})
|
||||
|
||||
// #
|
||||
// This will remove the given file from the machine attachements list. If the file was previously uploaded
|
||||
// to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
// the attachements array.
|
||||
// @param file {Object} the file to delete
|
||||
// #
|
||||
/**
|
||||
* This will remove the given file from the machine attachements list. If the file was previously uploaded
|
||||
* to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
* the attachements array.
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.machine.machine_files_attributes.indexOf(file)
|
||||
if (file.id != null) {
|
||||
@ -95,14 +95,14 @@ class MachinesController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Manages the transition when a user clicks on the reservation button.
|
||||
// According to the status of user currently logged into the system, redirect him to the reservation page,
|
||||
// or display a modal window asking him to complete a training before he can book a machine reservation.
|
||||
// @param machine {{id:number}} An object containg the id of the machine to book,
|
||||
// the object will be completed before the fonction returns.
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Manages the transition when a user clicks on the reservation button.
|
||||
* According to the status of user currently logged into the system, redirect him to the reservation page,
|
||||
* or display a modal window asking him to complete a training before he can book a machine reservation.
|
||||
* @param machine {{id:number}} An object containg the id of the machine to book,
|
||||
* the object will be completed before the fonction returns.
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
const _reserveMachine = function (machine, e) {
|
||||
const _this = this
|
||||
e.preventDefault()
|
||||
@ -177,21 +177,21 @@ const _reserveMachine = function (machine, e) {
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used in the public listing page, allowing everyone to see the list of machines
|
||||
// #
|
||||
/**
|
||||
* Controller used in the public listing page, allowing everyone to see the list of machines
|
||||
*/
|
||||
Application.Controllers.controller('MachinesController', ['$scope', '$state', '_t', 'Machine', '$uibModal', 'machinesPromise', function ($scope, $state, _t, Machine, $uibModal, machinesPromise) {
|
||||
// # Retrieve the list of machines
|
||||
// Retrieve the list of machines
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
// #
|
||||
// Redirect the user to the machine details page
|
||||
// #
|
||||
/**
|
||||
* Redirect the user to the machine details page
|
||||
*/
|
||||
$scope.showMachine = machine => $state.go('app.public.machines_show', { id: machine.slug })
|
||||
|
||||
// #
|
||||
// Callback to book a reservation for the current machine
|
||||
// #
|
||||
/**
|
||||
* Callback to book a reservation for the current machine
|
||||
*/
|
||||
$scope.reserveMachine = _reserveMachine.bind({
|
||||
$scope,
|
||||
$state,
|
||||
@ -200,10 +200,10 @@ Application.Controllers.controller('MachinesController', ['$scope', '$state', '_
|
||||
Machine
|
||||
})
|
||||
|
||||
// # Default: we show only enabled machines
|
||||
// Default: we show only enabled machines
|
||||
$scope.machineFiltering = 'enabled'
|
||||
|
||||
// # Available options for filtering machines by status
|
||||
// Available options for filtering machines by status
|
||||
return $scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
@ -212,70 +212,70 @@ Application.Controllers.controller('MachinesController', ['$scope', '$state', '_
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the machine creation page (admin)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the machine creation page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('NewMachineController', ['$scope', '$state', 'CSRF', function ($scope, $state, CSRF) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/machines/'
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # default machine parameters
|
||||
// default machine parameters
|
||||
$scope.machine =
|
||||
{ machine_files_attributes: [] }
|
||||
|
||||
// # Using the MachinesController
|
||||
// Using the MachinesController
|
||||
return new MachinesController($scope, $state)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the machine edition page (admin)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the machine edition page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('EditMachineController', ['$scope', '$state', '$stateParams', 'machinePromise', 'CSRF', function ($scope, $state, $stateParams, machinePromise, CSRF) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/machines/${$stateParams.id}`
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
|
||||
// # Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list
|
||||
// Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list
|
||||
$scope.machine = machinePromise
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # Using the MachinesController
|
||||
// Using the MachinesController
|
||||
return new MachinesController($scope, $state)
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the machine details page (public)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the machine details page (public)
|
||||
*/
|
||||
Application.Controllers.controller('ShowMachineController', ['$scope', '$state', '$uibModal', '$stateParams', '_t', 'Machine', 'growl', 'machinePromise', 'dialogs',
|
||||
function ($scope, $state, $uibModal, $stateParams, _t, Machine, growl, machinePromise, dialogs) {
|
||||
// # Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list
|
||||
// Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list
|
||||
$scope.machine = machinePromise
|
||||
|
||||
// #
|
||||
// Callback to delete the current machine (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to delete the current machine (admins only)
|
||||
*/
|
||||
$scope.delete = function (machine) {
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
@ -299,9 +299,9 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to book a reservation for the current machine
|
||||
// #
|
||||
/**
|
||||
* Callback to book a reservation for the current machine
|
||||
*/
|
||||
return $scope.reserveMachine = _reserveMachine.bind({
|
||||
$scope,
|
||||
$state,
|
||||
@ -312,10 +312,10 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the machine reservation page (for logged users who have completed the training and admins).
|
||||
// This controller workflow is pretty similar to the trainings reservation controller.
|
||||
// #
|
||||
/**
|
||||
* Controller used in the machine reservation page (for logged users who have completed the training and admins).
|
||||
* This controller workflow is pretty similar to the trainings reservation controller.
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('ReserveMachineController', ['$scope', '$stateParams', '_t', 'moment', 'Auth', '$timeout', 'Member', 'Availability', 'plansPromise', 'groupsPromise', 'machinePromise', 'settingsPromise', 'uiCalendarConfig', 'CalendarConfig',
|
||||
function ($scope, $stateParams, _t, moment, Auth, $timeout, Member, Availability, plansPromise, groupsPromise, machinePromise, settingsPromise, uiCalendarConfig, CalendarConfig) {
|
||||
@ -332,19 +332,19 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # bind the machine availabilities with full-Calendar events
|
||||
// bind the machine availabilities with full-Calendar events
|
||||
$scope.eventSources = []
|
||||
|
||||
// # indicates the state of the current view : calendar or plans information
|
||||
// indicates the state of the current view : calendar or plans information
|
||||
$scope.plansAreShown = false
|
||||
|
||||
// # will store the user's plan if he choosed to buy one
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
|
||||
// # the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
// the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.planSelectionTime = null
|
||||
|
||||
// # mapping of fullCalendar events.
|
||||
// mapping of fullCalendar events.
|
||||
$scope.events = {
|
||||
reserved: [], // Slots that the user wants to book
|
||||
modifiable: null, // Slot that the user wants to change
|
||||
@ -353,16 +353,16 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
moved: null // Slots that were just moved by the user (change done) -> {newSlot:* oldSlot: *}
|
||||
}
|
||||
|
||||
// # the moment when the slot selection changed for the last time, used to trigger changes in the cart
|
||||
// the moment when the slot selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.selectionTime = null
|
||||
|
||||
// # the last clicked event in the calender
|
||||
// the last clicked event in the calender
|
||||
$scope.selectedEvent = null
|
||||
|
||||
// # the application global settings
|
||||
// the application global settings
|
||||
$scope.settings = settingsPromise
|
||||
|
||||
// # list of plans, classified by group
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
for (let group of Array.from(groupsPromise)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
@ -372,14 +372,14 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
}
|
||||
|
||||
// # the user to deal with, ie. the current user for non-admins
|
||||
// the user to deal with, ie. the current user for non-admins
|
||||
$scope.ctrl =
|
||||
{ member: {} }
|
||||
|
||||
// # current machine to reserve
|
||||
// current machine to reserve
|
||||
$scope.machine = machinePromise
|
||||
|
||||
// # fullCalendar (v2) configuration
|
||||
// fullCalendar (v2) configuration
|
||||
$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')),
|
||||
@ -391,24 +391,24 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
}
|
||||
})
|
||||
|
||||
// # Global config: message to the end user concerning the subscriptions rules
|
||||
// Global config: message to the end user concerning the subscriptions rules
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert
|
||||
|
||||
// # Global config: message to the end user concerning the machine bookings
|
||||
// Global config: message to the end user concerning the machine bookings
|
||||
$scope.machineExplicationsAlert = settingsPromise.machine_explications_alert
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'added to cart'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'added to cart'
|
||||
*/
|
||||
$scope.markSlotAsAdded = function () {
|
||||
$scope.selectedEvent.backgroundColor = FREE_SLOT_BORDER_COLOR
|
||||
$scope.selectedEvent.title = _t('i_reserve')
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
*/
|
||||
$scope.markSlotAsRemoved = function (slot) {
|
||||
slot.backgroundColor = 'white'
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
@ -421,23 +421,23 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
// #
|
||||
/**
|
||||
* Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
*/
|
||||
$scope.slotCancelled = () => $scope.markSlotAsRemoved($scope.selectedEvent)
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
*/
|
||||
$scope.markSlotAsModifying = function () {
|
||||
$scope.selectedEvent.backgroundColor = '#eee'
|
||||
$scope.selectedEvent.title = _t('i_change')
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
*/
|
||||
$scope.changeModifyMachineSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -450,9 +450,9 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
// #
|
||||
/**
|
||||
* When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
*/
|
||||
$scope.modifyMachineSlot = function () {
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? _t('i_ve_reserved') : _t('not_available')
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -471,9 +471,9 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Cancel the current booking modification, reseting the whole process
|
||||
// #
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
*/
|
||||
$scope.cancelModifyMachineSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -485,20 +485,20 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
// reservations. (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
* reservations. (admins only)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
return Member.get({ id: $scope.ctrl.member.id }, member => $scope.ctrl.member = member)
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
e.preventDefault()
|
||||
$scope.plansAreShown = false
|
||||
@ -506,15 +506,15 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Switch the user's view from the reservation agenda to the plan subscription
|
||||
// #
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = () => $scope.plansAreShown = true
|
||||
|
||||
// #
|
||||
// Add the provided plan to the current shopping cart
|
||||
// @param plan {Object} the plan to subscribe
|
||||
// #
|
||||
/**
|
||||
* Add the provided plan to the current shopping cart
|
||||
* @param plan {Object} the plan to subscribe
|
||||
*/
|
||||
$scope.selectPlan = function (plan) {
|
||||
// toggle selected plan
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
@ -525,11 +525,11 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Once the reservation is booked (payment process successfully completed), change the event style
|
||||
// in fullCalendar, update the user's subscription and free-credits if needed
|
||||
// @param reservation {Object}
|
||||
// #
|
||||
/**
|
||||
* Once the reservation is booked (payment process successfully completed), change the event style
|
||||
* in fullCalendar, update the user's subscription and free-credits if needed
|
||||
* @param reservation {Object}
|
||||
*/
|
||||
$scope.afterPayment = function (reservation) {
|
||||
angular.forEach($scope.events.reserved, function (machineSlot, key) {
|
||||
machineSlot.is_reserved = true
|
||||
@ -556,16 +556,16 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
return refetchCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// To use as callback in Array.prototype.filter to get only enabled plans
|
||||
// #
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = plan => !plan.disabled
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
Availability.machine({ machineId: $stateParams.id }, availabilities =>
|
||||
$scope.eventSources.push({
|
||||
@ -579,22 +579,22 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when the user click on a reservation slot in the agenda.
|
||||
// Defines the behavior to adopt depending on the slot status (already booked, free, ready to be reserved ...),
|
||||
// the user's subscription (current or about to be took) and the time (the user cannot modify a booked reservation
|
||||
// if it's too late).
|
||||
// #
|
||||
/**
|
||||
* Triggered when the user click on a reservation slot in the agenda.
|
||||
* Defines the behavior to adopt depending on the slot status (already booked, free, ready to be reserved ...),
|
||||
* the user's subscription (current or about to be took) and the time (the user cannot modify a booked reservation
|
||||
* if it's too late).
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.selectedEvent = event
|
||||
return $scope.selectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
// Append the event tag into the block, just after the event title.
|
||||
// @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
// #
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
* Append the event tag into the block, just after the event title.
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element) {
|
||||
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
|
||||
let html = ''
|
||||
@ -605,14 +605,14 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
// This will allow the user to modify the reservation he just booked. The associated user will also be registered
|
||||
// with the slot.
|
||||
// @param slot {Object}
|
||||
// @param reservation {Object}
|
||||
// @param user {Object} user associated with the slot
|
||||
// #
|
||||
/**
|
||||
* After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
* This will allow the user to modify the reservation he just booked. The associated user will also be registered
|
||||
* with the slot.
|
||||
* @param slot {Object}
|
||||
* @param reservation {Object}
|
||||
* @param user {Object} user associated with the slot
|
||||
*/
|
||||
var updateMachineSlot = (slot, reservation, user) =>
|
||||
angular.forEach(reservation.slots, function (s) {
|
||||
if (slot.start.isSame(s.start_at)) {
|
||||
@ -621,21 +621,21 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Update the calendar's display to render the new attributes of the events
|
||||
// #
|
||||
/**
|
||||
* Update the calendar's display to render the new attributes of the events
|
||||
*/
|
||||
var updateCalendar = () => uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
|
||||
// #
|
||||
// Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
// #
|
||||
/**
|
||||
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
*/
|
||||
var refetchCalendar = () =>
|
||||
$timeout(function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -16,18 +16,18 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
function ($scope, $rootScope, $state, $uibModal, Auth, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # list of groups
|
||||
// list of groups
|
||||
let plan
|
||||
$scope.groups = groupsPromise.filter(g => (g.slug !== 'admins') & !g.disabled)
|
||||
|
||||
// # default : do not show the group changing form
|
||||
// # group ID of the current/selected user
|
||||
// default : do not show the group changing form
|
||||
// group ID of the current/selected user
|
||||
$scope.group = {
|
||||
change: false,
|
||||
id: null
|
||||
}
|
||||
|
||||
// # list of plans, classified by group
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
for (var group of Array.from($scope.groups)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
@ -37,34 +37,34 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
}
|
||||
|
||||
// # user to deal with
|
||||
// user to deal with
|
||||
$scope.ctrl = {
|
||||
member: null,
|
||||
member_id: null
|
||||
}
|
||||
|
||||
// # already subscribed plan of the current user
|
||||
// already subscribed plan of the current user
|
||||
$scope.paid =
|
||||
{ plan: null }
|
||||
|
||||
// # plan to subscribe (shopping cart)
|
||||
// plan to subscribe (shopping cart)
|
||||
$scope.selectedPlan = null
|
||||
|
||||
// # Discount coupon to apply to the basket, if any
|
||||
// Discount coupon to apply to the basket, if any
|
||||
$scope.coupon =
|
||||
{ applied: null }
|
||||
|
||||
// # Storage for the total price (plan price + coupon, if any)
|
||||
// Storage for the total price (plan price + coupon, if any)
|
||||
$scope.cart =
|
||||
{ total: null }
|
||||
|
||||
// # text that appears in the bottom-right box of the page (subscriptions rules details)
|
||||
// text that appears in the bottom-right box of the page (subscriptions rules details)
|
||||
$scope.subscriptionExplicationsAlert = subscriptionExplicationsPromise.setting.value
|
||||
|
||||
// #
|
||||
// Callback to deal with the subscription of the user selected in the dropdown list instead of the current user's
|
||||
// subscription. (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to deal with the subscription of the user selected in the dropdown list instead of the current user's
|
||||
* subscription. (admins only)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
$scope.selectedPlan = null
|
||||
$scope.paid.plan = null
|
||||
@ -75,10 +75,10 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Add the provided plan to the shopping basket
|
||||
// @param plan {Object} The plan to subscribe to
|
||||
// #
|
||||
/**
|
||||
* Add the provided plan to the shopping basket
|
||||
* @param plan {Object} The plan to subscribe to
|
||||
*/
|
||||
$scope.selectPlan = function (plan) {
|
||||
if ($scope.isAuthenticated()) {
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
@ -92,9 +92,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to trigger the payment process of the subscription
|
||||
// #
|
||||
/**
|
||||
* Callback to trigger the payment process of the subscription
|
||||
*/
|
||||
$scope.openSubscribePlanModal = () =>
|
||||
Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }, function (wallet) {
|
||||
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount)
|
||||
@ -107,9 +107,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Return the group object, identified by the ID set in $scope.group.id
|
||||
// #
|
||||
/**
|
||||
* Return the group object, identified by the ID set in $scope.group.id
|
||||
*/
|
||||
$scope.getUserGroup = function () {
|
||||
for (group of Array.from($scope.groups)) {
|
||||
if (group.id === $scope.group.id) {
|
||||
@ -118,9 +118,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the group of the current/selected user to the one set in $scope.group.id
|
||||
// #
|
||||
/**
|
||||
* Change the group of the current/selected user to the one set in $scope.group.id
|
||||
*/
|
||||
$scope.selectGroup = () =>
|
||||
Member.update({ id: $scope.ctrl.member.id }, { user: { group_id: $scope.group.id } }, function (user) {
|
||||
$scope.ctrl.member = user
|
||||
@ -142,22 +142,22 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
return console.error(err)
|
||||
})
|
||||
|
||||
// #
|
||||
// Return an enumerable meaninful string for the gender of the provider user
|
||||
// @param user {Object} Database user record
|
||||
// @return {string} 'male' or 'female'
|
||||
// #
|
||||
/**
|
||||
* Return an enumerable meaninful string for the gender of the provider user
|
||||
* @param user {Object} Database user record
|
||||
* @return {string} 'male' or 'female'
|
||||
*/
|
||||
$scope.getGender = function (user) {
|
||||
if (user && user.profile) {
|
||||
if (user.profile.gender === 'true') { return 'male' } else { return 'female' }
|
||||
} else { return 'other' }
|
||||
}
|
||||
|
||||
// #
|
||||
// Test if the provided date is in the future
|
||||
// @param dateTime {Date}
|
||||
// @return {boolean}
|
||||
// #
|
||||
/**
|
||||
* Test if the provided date is in the future
|
||||
* @param dateTime {Date}
|
||||
* @return {boolean}
|
||||
*/
|
||||
$scope.isInFuture = function (dateTime) {
|
||||
if (moment().diff(moment(dateTime)) < 0) {
|
||||
return true
|
||||
@ -166,16 +166,16 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// To use as callback in Array.prototype.filter to get only enabled plans
|
||||
// #
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = plan => !plan.disabled
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.currentUser) {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
@ -195,10 +195,10 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Compute the total amount for the current reservation according to the previously set parameters
|
||||
// and assign the result in $scope.reserve.amountTotal
|
||||
// #
|
||||
/**
|
||||
* Compute the total amount for the current reservation according to the previously set parameters
|
||||
* and assign the result in $scope.reserve.amountTotal
|
||||
*/
|
||||
var updateCartPrice = function () {
|
||||
// first we check that a user was selected
|
||||
if (Object.keys($scope.ctrl.member).length > 0) {
|
||||
@ -218,9 +218,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal window which trigger the stripe payment process
|
||||
// #
|
||||
/**
|
||||
* Open a modal window which trigger the stripe payment process
|
||||
*/
|
||||
var payByStripe = () =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "stripe/payment_modal.html" %>',
|
||||
@ -251,11 +251,11 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
// retrieve the CGV
|
||||
CustomAsset.get({ name: 'cgv-file' }, cgv => $scope.cgv = cgv.custom_asset)
|
||||
|
||||
// #
|
||||
// Callback for click on the 'proceed' button.
|
||||
// Handle the stripe's card tokenization process response and save the subscription to the API with the
|
||||
// card token just created.
|
||||
// #
|
||||
/**
|
||||
* Callback for click on the 'proceed' button.
|
||||
* Handle the stripe's card tokenization process response and save the subscription to the API with the
|
||||
* card token just created.
|
||||
*/
|
||||
return $scope.payment = function (status, response) {
|
||||
if (response.error) {
|
||||
return growl.error(response.error.message)
|
||||
@ -289,9 +289,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
return $scope.coupon.applied = null
|
||||
})
|
||||
|
||||
// #
|
||||
// Open a modal window which trigger the local payment process
|
||||
// #
|
||||
/**
|
||||
* Open a modal window which trigger the local payment process
|
||||
*/
|
||||
var payOnSite = () =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "plans/payment_modal.html" %>',
|
||||
@ -336,10 +336,10 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback for the 'proceed' button.
|
||||
// Save the subscription to the API
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'proceed' button.
|
||||
* Save the subscription to the API
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$scope.attempting = true
|
||||
return Subscription.save({
|
||||
@ -359,10 +359,10 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback for the 'cancel' button.
|
||||
// Close the modal box.
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'cancel' button.
|
||||
* Close the modal box.
|
||||
*/
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
}
|
||||
] })
|
||||
@ -375,7 +375,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
return $scope.coupon.applied = null
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
@ -17,37 +17,37 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
function ($scope, $rootScope, $state, $window, _t, growl, CSRF, Auth, Member, settingsPromise, activeProviderPromise, groupsPromise, cguFile, memberPromise, Session, dialogs, AuthProvider) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/members/${memberPromise.id}`
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'patch'
|
||||
|
||||
// # genre of the application name (eg. "_le_ Fablab" or "_la_ Fabrique")
|
||||
// genre of the application name (eg. "_le_ Fablab" or "_la_ Fabrique")
|
||||
$scope.nameGenre = settingsPromise.name_genre
|
||||
|
||||
// # name of the current fablab application (eg. "Fablab de la Casemate")
|
||||
// name of the current fablab application (eg. "Fablab de la Casemate")
|
||||
$scope.fablabName = settingsPromise.fablab_name
|
||||
|
||||
// # information from the current SSO provider
|
||||
// information from the current SSO provider
|
||||
$scope.activeProvider = activeProviderPromise
|
||||
|
||||
// # list of user's groups (student/standard/...)
|
||||
// list of user's groups (student/standard/...)
|
||||
$scope.groups = groupsPromise
|
||||
|
||||
// # current user, contains information retrieved from the SSO
|
||||
// current user, contains information retrieved from the SSO
|
||||
$scope.user = memberPromise
|
||||
|
||||
// # disallow the user to change his password as he connect from SSO
|
||||
// disallow the user to change his password as he connect from SSO
|
||||
$scope.preventPassword = true
|
||||
|
||||
// # mapping of fields to disable
|
||||
// mapping of fields to disable
|
||||
$scope.preventField = {}
|
||||
|
||||
// # CGU
|
||||
// CGU
|
||||
$scope.cgu = cguFile.custom_asset
|
||||
|
||||
// # Angular-Bootstrap datepicker configuration for birthday
|
||||
// Angular-Bootstrap datepicker configuration for birthday
|
||||
$scope.datePicker = {
|
||||
format: Fablab.uibDateFormat,
|
||||
opened: false, // default: datePicker is not shown
|
||||
@ -56,23 +56,23 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to diplay the datepicker as a dropdown when clicking on the input field
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Callback to diplay the datepicker as a dropdown when clicking on the input field
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.openDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = true
|
||||
}
|
||||
|
||||
// #
|
||||
// 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's profile is updated and the user is
|
||||
// redirected to the home page
|
||||
// @param content {Object} JSON - The upload's result
|
||||
// #
|
||||
/**
|
||||
* 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's profile is updated and the user is
|
||||
* redirected to the home page
|
||||
* @param content {Object} JSON - The upload's result
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -96,11 +96,11 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -109,9 +109,9 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Merge the current user into the account with the given auth_token
|
||||
// #
|
||||
/**
|
||||
* Merge the current user into the account with the given auth_token
|
||||
*/
|
||||
$scope.registerAuthToken = () =>
|
||||
Member.merge({ id: $rootScope.currentUser.id }, { user: { auth_token: $scope.user.auth_token } }, function (user) {
|
||||
$scope.user = user
|
||||
@ -128,10 +128,10 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Return the email given by the SSO provider, parsed if needed
|
||||
// @return {String} E-mail of the current user
|
||||
// #
|
||||
/**
|
||||
* Return the email given by the SSO provider, parsed if needed
|
||||
* @return {String} E-mail of the current user
|
||||
*/
|
||||
$scope.ssoEmail = function () {
|
||||
const { email } = memberPromise
|
||||
if (email) {
|
||||
@ -143,10 +143,10 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
return email
|
||||
}
|
||||
|
||||
// #
|
||||
// Test if the user's mail is marked as duplicate
|
||||
// @return {boolean}
|
||||
// #
|
||||
/**
|
||||
* Test if the user's mail is marked as duplicate
|
||||
* @return {boolean}
|
||||
*/
|
||||
$scope.hasDuplicate = function () {
|
||||
const { email } = memberPromise
|
||||
if (email) {
|
||||
@ -154,10 +154,10 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Ask for email confirmation and send the SSO merging token again
|
||||
// @param $event {Object} jQuery event object
|
||||
// #
|
||||
/**
|
||||
* Ask for email confirmation and send the SSO merging token again
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.resendCode = function (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
@ -176,9 +176,9 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
)
|
||||
}
|
||||
|
||||
// #
|
||||
// Disconnect and re-connect the user to the SSO to force the synchronisation of the profile's data
|
||||
// #
|
||||
/**
|
||||
* Disconnect and re-connect the user to the SSO to force the synchronisation of the profile's data
|
||||
*/
|
||||
$scope.syncProfile = () =>
|
||||
Auth.logout().then(function (oldUser) {
|
||||
Session.destroy()
|
||||
@ -193,9 +193,9 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
@ -206,7 +206,7 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
return angular.forEach(activeProviderPromise.mapping, map => $scope.preventField[map] = true)
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
|
||||
|
@ -17,33 +17,33 @@
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
// #
|
||||
// Provides a set of common properties and methods to the $scope parameter. They are used
|
||||
// in the various projects' admin controllers.
|
||||
//
|
||||
// Provides :
|
||||
// - $scope.totalSteps
|
||||
// - $scope.machines = [{Machine}]
|
||||
// - $scope.components = [{Component}]
|
||||
// - $scope.themes = [{Theme}]
|
||||
// - $scope.licences = [{Licence}]
|
||||
// - $scope.allowedExtensions = [{String}]
|
||||
// - $scope.submited(content)
|
||||
// - $scope.cancel()
|
||||
// - $scope.addFile()
|
||||
// - $scope.deleteFile(file)
|
||||
// - $scope.addStep()
|
||||
// - $scope.deleteStep(step)
|
||||
// - $scope.changeStepIndex(step, newIdx)
|
||||
//
|
||||
// Requires :
|
||||
// - $scope.project.project_caos_attributes = []
|
||||
// - $scope.project.project_steps_attributes = []
|
||||
// - $state (Ui-Router) [ 'app.public.projects_show', 'app.public.projects_list' ]
|
||||
// #
|
||||
/**
|
||||
* Provides a set of common properties and methods to the $scope parameter. They are used
|
||||
* in the various projects' admin controllers.
|
||||
*
|
||||
* Provides :
|
||||
* - $scope.totalSteps
|
||||
* - $scope.machines = [{Machine}]
|
||||
* - $scope.components = [{Component}]
|
||||
* - $scope.themes = [{Theme}]
|
||||
* - $scope.licences = [{Licence}]
|
||||
* - $scope.allowedExtensions = [{String}]
|
||||
* - $scope.submited(content)
|
||||
* - $scope.cancel()
|
||||
* - $scope.addFile()
|
||||
* - $scope.deleteFile(file)
|
||||
* - $scope.addStep()
|
||||
* - $scope.deleteStep(step)
|
||||
* - $scope.changeStepIndex(step, newIdx)
|
||||
*
|
||||
* Requires :
|
||||
* - $scope.project.project_caos_attributes = []
|
||||
* - $scope.project.project_steps_attributes = []
|
||||
* - $state (Ui-Router) [ 'app.public.projects_show', 'app.public.projects_list' ]
|
||||
*/
|
||||
class ProjectsController {
|
||||
constructor ($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, Diacritics, dialogs, allowedExtensions, _t) {
|
||||
// # Retrieve the list of machines from the server
|
||||
// Retrieve the list of machines from the server
|
||||
Machine.query().$promise.then(data =>
|
||||
$scope.machines = data.map(d =>
|
||||
({
|
||||
@ -53,7 +53,7 @@ class ProjectsController {
|
||||
)
|
||||
)
|
||||
|
||||
// # Retrieve the list of components from the server
|
||||
// Retrieve the list of components from the server
|
||||
Component.query().$promise.then(data =>
|
||||
$scope.components = data.map(d =>
|
||||
({
|
||||
@ -63,7 +63,7 @@ class ProjectsController {
|
||||
)
|
||||
)
|
||||
|
||||
// # Retrieve the list of themes from the server
|
||||
// Retrieve the list of themes from the server
|
||||
Theme.query().$promise.then(data =>
|
||||
$scope.themes = data.map(d =>
|
||||
({
|
||||
@ -73,7 +73,7 @@ class ProjectsController {
|
||||
)
|
||||
)
|
||||
|
||||
// # Retrieve the list of licences from the server
|
||||
// Retrieve the list of licences from the server
|
||||
Licence.query().$promise.then(data =>
|
||||
$scope.licences = data.map(d =>
|
||||
({
|
||||
@ -83,18 +83,18 @@ class ProjectsController {
|
||||
)
|
||||
)
|
||||
|
||||
// # Total number of documentation steps for the current project
|
||||
// Total number of documentation steps for the current project
|
||||
$scope.totalSteps = $scope.project.project_steps_attributes.length
|
||||
|
||||
// # List of extensions allowed for CAD attachements upload
|
||||
// List of extensions allowed for CAD attachements upload
|
||||
$scope.allowedExtensions = allowedExtensions
|
||||
|
||||
// #
|
||||
// For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
// Intended to be the callback when an upload is done: any raised error will be stacked in the
|
||||
// $scope.alerts array. If everything goes fine, the user is redirected to the project page.
|
||||
// @param content {Object} JSON - The upload's result
|
||||
// #
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
* Intended to be the callback when an upload is done: any raised error will be stacked in the
|
||||
* $scope.alerts array. If everything goes fine, the user is redirected to the project page.
|
||||
* @param content {Object} JSON - The upload's result
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -113,11 +113,11 @@ class ProjectsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -126,17 +126,17 @@ class ProjectsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// This will create a single new empty entry into the project's CAO attachements list.
|
||||
// #
|
||||
/**
|
||||
* This will create a single new empty entry into the project's CAO attachements list.
|
||||
*/
|
||||
$scope.addFile = () => $scope.project.project_caos_attributes.push({})
|
||||
|
||||
// #
|
||||
// This will remove the given file from the project's CAO attachements list. If the file was previously uploaded
|
||||
// to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
// the CAO attachements array.
|
||||
// @param file {Object} the file to delete
|
||||
// #
|
||||
/**
|
||||
* This will remove the given file from the project's CAO attachements list. If the file was previously uploaded
|
||||
* to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
* the CAO attachements array.
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.project.project_caos_attributes.indexOf(file)
|
||||
if (file.id != null) {
|
||||
@ -146,20 +146,20 @@ class ProjectsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// This will create a single new empty entry into the project's steps list.
|
||||
// #
|
||||
/**
|
||||
* This will create a single new empty entry into the project's steps list.
|
||||
*/
|
||||
$scope.addStep = function () {
|
||||
$scope.totalSteps += 1
|
||||
return $scope.project.project_steps_attributes.push({ step_nb: $scope.totalSteps, project_step_images_attributes: [] })
|
||||
}
|
||||
|
||||
// #
|
||||
// This will remove the given step from the project's steps list. If the step was previously saved
|
||||
// on the server, it will be marked for deletion for the next saving. Otherwise, it will be simply truncated from
|
||||
// the steps array.
|
||||
// @param file {Object} the file to delete
|
||||
// #
|
||||
/**
|
||||
* This will remove the given step from the project's steps list. If the step was previously saved
|
||||
* on the server, it will be marked for deletion for the next saving. Otherwise, it will be simply truncated from
|
||||
* the steps array.
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteStep = step =>
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
@ -195,13 +195,13 @@ class ProjectsController {
|
||||
})()
|
||||
})
|
||||
|
||||
// #
|
||||
// Change the step_nb property of the given step to the new value provided. The step that was previously at this
|
||||
// index will be assigned to the old position of the provided step.
|
||||
// @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// @param step {Object} the project's step to reindex
|
||||
// @param newIdx {number} the new index to assign to the step
|
||||
// #
|
||||
/**
|
||||
* Change the step_nb property of the given step to the new value provided. The step that was previously at this
|
||||
* index will be assigned to the old position of the provided step.
|
||||
* @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
* @param step {Object} the project's step to reindex
|
||||
* @param newIdx {number} the new index to assign to the step
|
||||
*/
|
||||
$scope.changeStepIndex = function (event, step, newIdx) {
|
||||
if (event) { event.preventDefault() }
|
||||
for (let s of Array.from($scope.project.project_steps_attributes)) {
|
||||
@ -224,16 +224,16 @@ class ProjectsController {
|
||||
, error => console.error(error))
|
||||
}
|
||||
|
||||
// #
|
||||
// This will create a single new empty entry into the project's step image list.
|
||||
// #
|
||||
/**
|
||||
* This will create a single new empty entry into the project's step image list.
|
||||
*/
|
||||
$scope.addProjectStepImage = step => step.project_step_images_attributes.push({})
|
||||
|
||||
// #
|
||||
// This will remove the given image from the project's step image list.
|
||||
// @param step {Object} the project step has images
|
||||
// @param image {Object} the image to delete
|
||||
// #
|
||||
/**
|
||||
* This will remove the given image from the project's step image list.
|
||||
* @param step {Object} the project step has images
|
||||
* @param image {Object} the image to delete
|
||||
*/
|
||||
$scope.deleteProjectStepImage = function (step, image) {
|
||||
const index = step.project_step_images_attributes.indexOf(image)
|
||||
if (image.id != null) {
|
||||
@ -245,9 +245,9 @@ class ProjectsController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used on projects listing page
|
||||
// #
|
||||
/**
|
||||
* Controller used on projects listing page
|
||||
*/
|
||||
Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise', 'paginationService', 'OpenlabProject', '$window', 'growl', '_t', '$location', '$timeout',
|
||||
function ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise, paginationService, OpenlabProject, $window, growl, _t, $location, $timeout) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
@ -257,16 +257,16 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # Fab-manager's instance ID in the openLab network
|
||||
// Fab-manager's instance ID in the openLab network
|
||||
$scope.openlabAppId = Fablab.openlabAppId
|
||||
|
||||
// # Is openLab enabled on the instance?
|
||||
// Is openLab enabled on the instance?
|
||||
$scope.openlab = {
|
||||
projectsActive: Fablab.openlabProjectsActive,
|
||||
searchOverWholeNetwork: false
|
||||
}
|
||||
|
||||
// # default search parameters
|
||||
// default search parameters
|
||||
$scope.search = {
|
||||
q: ($location.$$search.q || ''),
|
||||
from: ($location.$$search.from || undefined),
|
||||
@ -275,16 +275,16 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
theme_id: (parseInt($location.$$search.theme_id) || undefined)
|
||||
}
|
||||
|
||||
// # list of projects to display
|
||||
// list of projects to display
|
||||
$scope.projects = []
|
||||
|
||||
// # list of machines / used for filtering
|
||||
// list of machines / used for filtering
|
||||
$scope.machines = machinesPromise
|
||||
|
||||
// # list of themes / used for filtering
|
||||
// list of themes / used for filtering
|
||||
$scope.themes = themesPromise
|
||||
|
||||
// # list of components / used for filtering
|
||||
// list of components / used for filtering
|
||||
$scope.components = componentsPromise
|
||||
|
||||
$scope.searchOverWholeNetworkChanged = () =>
|
||||
@ -334,10 +334,10 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to switch the user's view to the detailled project page
|
||||
// @param project {{slug:string}} The project to display
|
||||
// #
|
||||
/**
|
||||
* Callback to switch the user's view to the detailled project page
|
||||
* @param project {{slug:string}} The project to display
|
||||
*/
|
||||
$scope.showProject = function (project) {
|
||||
if (($scope.openlab.searchOverWholeNetwork === true) && (project.app_id !== Fablab.openlabAppId)) {
|
||||
$window.open(project.project_url, '_blank')
|
||||
@ -347,9 +347,9 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// function to set all url query search parameters from search object
|
||||
// #
|
||||
/**
|
||||
* function to set all url query search parameters from search object
|
||||
*/
|
||||
$scope.setUrlQueryParams = function (search) {
|
||||
updateUrlParam('page', 1)
|
||||
updateUrlParam('q', search.q)
|
||||
@ -361,9 +361,9 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($location.$$search.whole_network === 'f') {
|
||||
$scope.openlab.searchOverWholeNetwork = false
|
||||
@ -373,10 +373,10 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
return $scope.triggerSearch()
|
||||
}
|
||||
|
||||
// #
|
||||
// function to update url query param, little hack to turn off reloadOnSearch and re-enable it after setting the params
|
||||
// params example: 'q' , 'presse-purée'
|
||||
// #
|
||||
/**
|
||||
* function to update url query param, little hack to turn off reloadOnSearch and re-enable it after setting the params
|
||||
* params example: 'q' , 'presse-purée'
|
||||
*/
|
||||
var updateUrlParam = function (name, value) {
|
||||
$state.current.reloadOnSearch = false
|
||||
$location.search(name, value)
|
||||
@ -399,25 +399,25 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
return project
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the project creation page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the project creation page
|
||||
*/
|
||||
Application.Controllers.controller('NewProjectController', ['$scope', '$state', 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'Diacritics', 'dialogs', 'allowedExtensions', '_t',
|
||||
function ($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, Diacritics, dialogs, allowedExtensions, _t) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/projects/'
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # Default project parameters
|
||||
// Default project parameters
|
||||
$scope.project = {
|
||||
project_steps_attributes: [],
|
||||
project_caos_attributes: []
|
||||
@ -425,25 +425,25 @@ Application.Controllers.controller('NewProjectController', ['$scope', '$state',
|
||||
|
||||
$scope.matchingMembers = []
|
||||
|
||||
// # Using the ProjectsController
|
||||
// Using the ProjectsController
|
||||
return new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, Diacritics, dialogs, allowedExtensions, _t)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the project edition page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the project edition page
|
||||
*/
|
||||
Application.Controllers.controller('EditProjectController', ['$scope', '$state', '$stateParams', 'Project', 'Machine', 'Member', 'Component', 'Theme', 'Licence', '$document', 'CSRF', 'projectPromise', 'Diacritics', 'dialogs', 'allowedExtensions', '_t',
|
||||
function ($scope, $state, $stateParams, Project, Machine, Member, Component, Theme, Licence, $document, CSRF, projectPromise, Diacritics, dialogs, allowedExtensions, _t) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/projects/${$stateParams.id}`
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
|
||||
// # Retrieve the project's details, if an error occured, redirect the user to the projects list page
|
||||
// Retrieve the project's details, if an error occured, redirect the user to the projects list page
|
||||
$scope.project = projectPromise
|
||||
|
||||
$scope.matchingMembers = $scope.project.project_users.map(u =>
|
||||
@ -453,28 +453,28 @@ Application.Controllers.controller('EditProjectController', ['$scope', '$state',
|
||||
})
|
||||
)
|
||||
|
||||
// # Using the ProjectsController
|
||||
// Using the ProjectsController
|
||||
return new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, Diacritics, dialogs, allowedExtensions, _t)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the public project's details page
|
||||
// #
|
||||
/**
|
||||
* Controller used in the public project's details page
|
||||
*/
|
||||
Application.Controllers.controller('ShowProjectController', ['$scope', '$state', 'projectPromise', '$location', '$uibModal', 'dialogs', '_t',
|
||||
function ($scope, $state, projectPromise, $location, $uibModal, dialogs, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # Store the project's details
|
||||
// Store the project's details
|
||||
$scope.project = projectPromise
|
||||
$scope.projectUrl = $location.absUrl()
|
||||
$scope.disqusShortname = Fablab.disqusShortname
|
||||
|
||||
// #
|
||||
// Test if the provided user has the edition rights on the current project
|
||||
// @param [user] {{id:number}} (optional) the user to check rights
|
||||
// @returns boolean
|
||||
// #
|
||||
/**
|
||||
* Test if the provided user has the edition rights on the current project
|
||||
* @param [user] {{id:number}} (optional) the user to check rights
|
||||
* @returns boolean
|
||||
*/
|
||||
$scope.projectEditableBy = function (user) {
|
||||
if ((user == null)) { return false }
|
||||
if ($scope.project.author_id === user.id) { return true }
|
||||
@ -485,20 +485,20 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
return canEdit
|
||||
}
|
||||
|
||||
// #
|
||||
// Test if the provided user has the deletion rights on the current project
|
||||
// @param [user] {{id:number}} (optional) the user to check rights
|
||||
// @returns boolean
|
||||
// #
|
||||
/**
|
||||
* Test if the provided user has the deletion rights on the current project
|
||||
* @param [user] {{id:number}} (optional) the user to check rights
|
||||
* @returns boolean
|
||||
*/
|
||||
$scope.projectDeletableBy = function (user) {
|
||||
if ((user == null)) { return false }
|
||||
if ($scope.project.author_id === user.id) { return true }
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to delete the current project. Then, the user is redirected to the projects list page,
|
||||
// which is refreshed. Admins and project owner only are allowed to delete a project
|
||||
// #
|
||||
/**
|
||||
* Callback to delete the current project. Then, the user is redirected to the projects list page,
|
||||
* which is refreshed. Admins and project owner only are allowed to delete a project
|
||||
*/
|
||||
$scope.deleteProject = function () {
|
||||
// check the permissions
|
||||
if (($scope.currentUser.role === 'admin') || $scope.projectDeletableBy($scope.currentUser)) {
|
||||
@ -521,10 +521,10 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal box containg a form that allow the end-user to signal an abusive content
|
||||
// @param e {Object} jQuery event
|
||||
// #
|
||||
/**
|
||||
* Open a modal box containg a form that allow the end-user to signal an abusive content
|
||||
* @param e {Object} jQuery event
|
||||
*/
|
||||
$scope.signalAbuse = function (e) {
|
||||
if (e) { e.preventDefault() }
|
||||
|
||||
@ -559,14 +559,14 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
] })
|
||||
}
|
||||
|
||||
// #
|
||||
// Return the URL allowing to share the current project on the Facebook social network
|
||||
// #
|
||||
/**
|
||||
* Return the URL allowing to share the current project on the Facebook social network
|
||||
*/
|
||||
$scope.shareOnFacebook = () => `https://www.facebook.com/share.php?u=${$state.href('app.public.projects_show', { id: $scope.project.slug }, { absolute: true }).replace('#', '%23')}`
|
||||
|
||||
// #
|
||||
// Return the URL allowing to share the current project on the Twitter social network
|
||||
// #
|
||||
/**
|
||||
* Return the URL allowing to share the current project on the Twitter social network
|
||||
*/
|
||||
return $scope.shareOnTwitter = () => `https://twitter.com/intent/tweet?url=${encodeURIComponent($state.href('app.public.projects_show', { id: $scope.project.slug }, { absolute: true }))}&text=${encodeURIComponent($scope.project.name)}`
|
||||
}
|
||||
])
|
||||
|
@ -16,29 +16,29 @@
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
// #
|
||||
// Provides a set of common callback methods to the $scope parameter. These methods are used
|
||||
// in the various spaces' admin controllers.
|
||||
//
|
||||
// Provides :
|
||||
// - $scope.submited(content)
|
||||
// - $scope.cancel()
|
||||
// - $scope.fileinputClass(v)
|
||||
// - $scope.addFile()
|
||||
// - $scope.deleteFile(file)
|
||||
//
|
||||
// Requires :
|
||||
// - $scope.space.space_files_attributes = []
|
||||
// - $state (Ui-Router) [ 'app.public.spaces_list' ]
|
||||
// #
|
||||
/**
|
||||
* Provides a set of common callback methods to the $scope parameter. These methods are used
|
||||
* in the various spaces' admin controllers.
|
||||
*
|
||||
* Provides :
|
||||
* - $scope.submited(content)
|
||||
* - $scope.cancel()
|
||||
* - $scope.fileinputClass(v)
|
||||
* - $scope.addFile()
|
||||
* - $scope.deleteFile(file)
|
||||
*
|
||||
* Requires :
|
||||
* - $scope.space.space_files_attributes = []
|
||||
* - $state (Ui-Router) [ 'app.public.spaces_list' ]
|
||||
/*
|
||||
class SpacesController {
|
||||
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 spaces list.
|
||||
// @param content {Object} JSON - The upload's result
|
||||
// #
|
||||
/*
|
||||
* 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 spaces list.
|
||||
* @param content {Object} JSON - The upload's result
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
@ -55,16 +55,16 @@ class SpacesController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the current user's view, redirecting him to the spaces list
|
||||
// #
|
||||
/**
|
||||
* Changes the current user's view, redirecting him to the spaces list
|
||||
*/
|
||||
$scope.cancel = () => $state.go('app.public.spaces_list')
|
||||
|
||||
// #
|
||||
// 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)
|
||||
// #
|
||||
/**
|
||||
* 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 = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
@ -73,17 +73,17 @@ class SpacesController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// This will create a single new empty entry into the space attachements list.
|
||||
// #
|
||||
/**
|
||||
* This will create a single new empty entry into the space attachements list.
|
||||
*/
|
||||
$scope.addFile = () => $scope.space.space_files_attributes.push({})
|
||||
|
||||
// #
|
||||
// This will remove the given file from the space attachements list. If the file was previously uploaded
|
||||
// to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
// the attachements array.
|
||||
// @param file {Object} the file to delete
|
||||
// #
|
||||
/**
|
||||
* This will remove the given file from the space attachements list. If the file was previously uploaded
|
||||
* to the server, it will be marked for deletion on the server. Otherwise, it will be simply truncated from
|
||||
* the attachements array.
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.space.space_files_attributes.indexOf(file)
|
||||
if (file.id != null) {
|
||||
@ -95,27 +95,27 @@ class SpacesController {
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Controller used in the public listing page, allowing everyone to see the list of spaces
|
||||
// #
|
||||
/**
|
||||
* Controller used in the public listing page, allowing everyone to see the list of spaces
|
||||
*/
|
||||
Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spacesPromise', function ($scope, $state, spacesPromise) {
|
||||
// # Retrieve the list of spaces
|
||||
// Retrieve the list of spaces
|
||||
$scope.spaces = spacesPromise
|
||||
|
||||
// #
|
||||
// Redirect the user to the space details page
|
||||
// #
|
||||
/**
|
||||
* Redirect the user to the space details page
|
||||
*/
|
||||
$scope.showSpace = space => $state.go('app.public.space_show', { id: space.slug })
|
||||
|
||||
// #
|
||||
// Callback to book a reservation for the current space
|
||||
// #
|
||||
/**
|
||||
* Callback to book a reservation for the current space
|
||||
*/
|
||||
$scope.reserveSpace = space => $state.go('app.logged.space_reserve', { id: space.slug })
|
||||
|
||||
// # Default: we show only enabled spaces
|
||||
// Default: we show only enabled spaces
|
||||
$scope.spaceFiltering = 'enabled'
|
||||
|
||||
// # Available options for filtering spaces by status
|
||||
// Available options for filtering spaces by status
|
||||
return $scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
@ -124,64 +124,64 @@ Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spa
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the space creation page (admin)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the space creation page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('NewSpaceController', ['$scope', '$state', 'CSRF', function ($scope, $state, CSRF) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/spaces/'
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
|
||||
// # default space parameters
|
||||
// default space parameters
|
||||
$scope.space =
|
||||
{ space_files_attributes: [] }
|
||||
|
||||
// # Using the SpacesController
|
||||
// Using the SpacesController
|
||||
return new SpacesController($scope, $state)
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the space edition page (admin)
|
||||
// #
|
||||
/**
|
||||
* Controller used in the space edition page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('EditSpaceController', ['$scope', '$state', '$stateParams', 'spacePromise', 'CSRF', function ($scope, $state, $stateParams, spacePromise, CSRF) {
|
||||
CSRF.setMetaTags()
|
||||
|
||||
// # API URL where the form will be posted
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/spaces/${$stateParams.id}`
|
||||
|
||||
// # Form action on the above URL
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
|
||||
// # space to modify
|
||||
// space to modify
|
||||
$scope.space = spacePromise
|
||||
|
||||
// # Using the SpacesController
|
||||
// Using the SpacesController
|
||||
return new SpacesController($scope, $state)
|
||||
}
|
||||
])
|
||||
|
||||
Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', 'spacePromise', '_t', 'dialogs', 'growl', function ($scope, $state, spacePromise, _t, dialogs, growl) {
|
||||
// # Details of the space witch id/slug is provided in the URL
|
||||
// Details of the space witch id/slug is provided in the URL
|
||||
$scope.space = spacePromise
|
||||
|
||||
// #
|
||||
// Callback to book a reservation for the current space
|
||||
// @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Callback to book a reservation for the current space
|
||||
* @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.reserveSpace = function (event) {
|
||||
event.preventDefault()
|
||||
return $state.go('app.logged.space_reserve', { id: $scope.space.slug })
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to book a reservation for the current space
|
||||
// @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Callback to book a reservation for the current space
|
||||
* @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
return $scope.deleteSpace = function (event) {
|
||||
event.preventDefault()
|
||||
// check the permissions
|
||||
@ -208,11 +208,11 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the spaces reservation agenda page.
|
||||
// This controller is very similar to the machine reservation controller with one major difference: here, there is many places
|
||||
// per slots.
|
||||
// #
|
||||
/**
|
||||
* Controller used in the spaces reservation agenda page.
|
||||
* This controller is very similar to the machine reservation controller with one major difference: here, there is many places
|
||||
* per slots.
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateParams', 'Auth', '$timeout', 'Availability', 'Member', 'availabilitySpacesPromise', 'plansPromise', 'groupsPromise', 'settingsPromise', 'spacePromise', '_t', 'uiCalendarConfig', 'CalendarConfig',
|
||||
function ($scope, $stateParams, Auth, $timeout, Availability, Member, availabilitySpacesPromise, plansPromise, groupsPromise, settingsPromise, spacePromise, _t, uiCalendarConfig, CalendarConfig) {
|
||||
@ -229,14 +229,14 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # bind the spaces availabilities with full-Calendar events
|
||||
// bind the spaces availabilities with full-Calendar events
|
||||
$scope.eventSources = [ { events: availabilitySpacesPromise, textColor: 'black' } ]
|
||||
|
||||
// # the user to deal with, ie. the current user for non-admins
|
||||
// the user to deal with, ie. the current user for non-admins
|
||||
$scope.ctrl =
|
||||
{ member: {} }
|
||||
|
||||
// # list of plans, classified by group
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
for (let group of Array.from(groupsPromise)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
@ -246,7 +246,7 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
}
|
||||
|
||||
// # mapping of fullCalendar events.
|
||||
// mapping of fullCalendar events.
|
||||
$scope.events = {
|
||||
reserved: [], // Slots that the user wants to book
|
||||
modifiable: null, // Slot that the user wants to change
|
||||
@ -255,25 +255,25 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
moved: null // Slots that were just moved by the user (change done) -> {newSlot:* oldSlot: *}
|
||||
}
|
||||
|
||||
// # the moment when the slot selection changed for the last time, used to trigger changes in the cart
|
||||
// the moment when the slot selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.selectionTime = null
|
||||
|
||||
// # the last clicked event in the calender
|
||||
// the last clicked event in the calender
|
||||
$scope.selectedEvent = null
|
||||
|
||||
// # indicates the state of the current view : calendar or plans information
|
||||
// indicates the state of the current view : calendar or plans information
|
||||
$scope.plansAreShown = false
|
||||
|
||||
// # will store the user's plan if he choosed to buy one
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
|
||||
// # the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
// the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.planSelectionTime = null
|
||||
|
||||
// # Selected space
|
||||
// Selected space
|
||||
$scope.space = spacePromise
|
||||
|
||||
// # fullCalendar (v2) configuration
|
||||
// fullCalendar (v2) configuration
|
||||
$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')),
|
||||
@ -285,26 +285,26 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
}
|
||||
})
|
||||
|
||||
// # Application global settings
|
||||
// Application global settings
|
||||
$scope.settings = settingsPromise
|
||||
|
||||
// # Global config: message to the end user concerning the subscriptions rules
|
||||
// Global config: message to the end user concerning the subscriptions rules
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert
|
||||
|
||||
// # Global config: message to the end user concerning the space reservation
|
||||
// Global config: message to the end user concerning the space reservation
|
||||
$scope.spaceExplicationsAlert = settingsPromise.space_explications_alert
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'added to cart'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'added to cart'
|
||||
*/
|
||||
$scope.markSlotAsAdded = function () {
|
||||
$scope.selectedEvent.backgroundColor = SELECTED_EVENT_BG_COLOR
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
*/
|
||||
$scope.markSlotAsRemoved = function (slot) {
|
||||
slot.backgroundColor = 'white'
|
||||
slot.title = ''
|
||||
@ -318,23 +318,23 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
// #
|
||||
/**
|
||||
* Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
*/
|
||||
$scope.slotCancelled = () => $scope.markSlotAsRemoved($scope.selectedEvent)
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
*/
|
||||
$scope.markSlotAsModifying = function () {
|
||||
$scope.selectedEvent.backgroundColor = '#eee'
|
||||
$scope.selectedEvent.title = _t('space_reserve.i_change')
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
*/
|
||||
$scope.changeModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -347,9 +347,9 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
// #
|
||||
/**
|
||||
* When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
*/
|
||||
$scope.modifyTrainingSlot = function () {
|
||||
$scope.events.placable.title = _t('space_reserve.i_ve_reserved')
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -369,9 +369,9 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Cancel the current booking modification, reseting the whole process
|
||||
// #
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
*/
|
||||
$scope.cancelModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -383,10 +383,10 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
// reservations. (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
* reservations. (admins only)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
if ($scope.ctrl.member) {
|
||||
Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
||||
@ -407,10 +407,10 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return $scope.plansAreShown = false
|
||||
}
|
||||
|
||||
// #
|
||||
// Add the provided plan to the current shopping cart
|
||||
// @param plan {Object} the plan to subscribe
|
||||
// #
|
||||
/**
|
||||
* Add the provided plan to the current shopping cart
|
||||
* @param plan {Object} the plan to subscribe
|
||||
*/
|
||||
$scope.selectPlan = function (plan) {
|
||||
// toggle selected plan
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
@ -421,10 +421,10 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
e.preventDefault()
|
||||
$scope.plansAreShown = false
|
||||
@ -432,16 +432,16 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Switch the user's view from the reservation agenda to the plan subscription
|
||||
// #
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = () => $scope.plansAreShown = true
|
||||
|
||||
// #
|
||||
// Once the reservation is booked (payment process successfully completed), change the event style
|
||||
// in fullCalendar, update the user's subscription and free-credits if needed
|
||||
// @param reservation {Object}
|
||||
// #
|
||||
/**
|
||||
* Once the reservation is booked (payment process successfully completed), change the event style
|
||||
* in fullCalendar, update the user's subscription and free-credits if needed
|
||||
* @param reservation {Object}
|
||||
*/
|
||||
$scope.afterPayment = function (reservation) {
|
||||
angular.forEach($scope.events.paid, function (spaceSlot, key) {
|
||||
spaceSlot.is_reserved = true
|
||||
@ -466,29 +466,29 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return refetchCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// To use as callback in Array.prototype.filter to get only enabled plans
|
||||
// #
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = plan => !plan.disabled
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return Member.get({ id: $scope.currentUser.id }, member => $scope.ctrl.member = member)
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when the user clicks on a reservation slot in the agenda.
|
||||
// Defines the behavior to adopt depending on the slot status (already booked, free, ready to be reserved ...),
|
||||
// the user's subscription (current or about to be took) and the time (the user cannot modify a booked reservation
|
||||
// if it's too late).
|
||||
// @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
// #
|
||||
/**
|
||||
* Triggered when the user clicks on a reservation slot in the agenda.
|
||||
* Defines the behavior to adopt depending on the slot status (already booked, free, ready to be reserved ...),
|
||||
* the user's subscription (current or about to be took) and the time (the user cannot modify a booked reservation
|
||||
* if it's too late).
|
||||
* @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.selectedEvent = event
|
||||
if ($stateParams.id === 'all') {
|
||||
@ -497,11 +497,11 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
return $scope.selectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
// Append the event tag into the block, just after the event title.
|
||||
// @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
// #
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
* Append the event tag into the block, just after the event title.
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element, view) {
|
||||
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
|
||||
let html = ''
|
||||
@ -512,12 +512,12 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
// This will allow the user to modify the reservation he just booked.
|
||||
// @param slot {Object}
|
||||
// @param reservation {Object}
|
||||
// #
|
||||
/**
|
||||
* After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
* This will allow the user to modify the reservation he just booked.
|
||||
* @param slot {Object}
|
||||
* @param reservation {Object}
|
||||
*/
|
||||
var updateSpaceSlotId = (slot, reservation) =>
|
||||
angular.forEach(reservation.slots, function (s) {
|
||||
if (slot.start_at === slot.start_at) {
|
||||
@ -525,21 +525,21 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Update the calendar's display to render the new attributes of the events
|
||||
// #
|
||||
/**
|
||||
* Update the calendar's display to render the new attributes of the events
|
||||
*/
|
||||
var updateCalendar = () => uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
|
||||
// #
|
||||
// Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
// #
|
||||
/**
|
||||
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
*/
|
||||
var refetchCalendar = () =>
|
||||
$timeout(function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
|
||||
|
@ -14,35 +14,35 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
// #
|
||||
// Public listing of the trainings
|
||||
// #
|
||||
/**
|
||||
* Public listing of the trainings
|
||||
*/
|
||||
Application.Controllers.controller('TrainingsController', ['$scope', '$state', 'trainingsPromise', function ($scope, $state, trainingsPromise) {
|
||||
// # List of trainings
|
||||
// List of trainings
|
||||
$scope.trainings = trainingsPromise
|
||||
|
||||
// #
|
||||
// Callback for the 'reserve' button
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'reserve' button
|
||||
*/
|
||||
$scope.reserveTraining = (training, event) => $state.go('app.logged.trainings_reserve', { id: training.slug })
|
||||
|
||||
// #
|
||||
// Callback for the 'show' button
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'show' button
|
||||
*/
|
||||
return $scope.showTraining = training => $state.go('app.public.training_show', { id: training.slug })
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Public view of a specific training
|
||||
// #
|
||||
/**
|
||||
* Public view of a specific training
|
||||
*/
|
||||
Application.Controllers.controller('ShowTrainingController', ['$scope', '$state', 'trainingPromise', 'growl', '_t', 'dialogs', function ($scope, $state, trainingPromise, growl, _t, dialogs) {
|
||||
// # Current training
|
||||
// Current training
|
||||
$scope.training = trainingPromise
|
||||
|
||||
// #
|
||||
// Callback to delete the current training (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to delete the current training (admins only)
|
||||
*/
|
||||
$scope.delete = function (training) {
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
@ -66,23 +66,23 @@ Application.Controllers.controller('ShowTrainingController', ['$scope', '$state'
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback for the 'reserve' button
|
||||
// #
|
||||
/**
|
||||
* Callback for the 'reserve' button
|
||||
*/
|
||||
$scope.reserveTraining = (training, event) => $state.go('app.logged.trainings_reserve', { id: training.id })
|
||||
|
||||
// #
|
||||
// Revert view to the full list of trainings ("<-" button)
|
||||
// #
|
||||
/**
|
||||
* Revert view to the full list of trainings ("<-" button)
|
||||
*/
|
||||
return $scope.cancel = event => $state.go('app.public.trainings_list')
|
||||
}
|
||||
])
|
||||
|
||||
// #
|
||||
// Controller used in the training reservation agenda page.
|
||||
// This controller is very similar to the machine reservation controller with one major difference: here, ONLY ONE
|
||||
// training can be reserved during the reservation process (the shopping cart may contains only one training and a subscription).
|
||||
// #
|
||||
/**
|
||||
* Controller used in the training reservation agenda page.
|
||||
* This controller is very similar to the machine reservation controller with one major difference: here, ONLY ONE
|
||||
* training can be reserved during the reservation process (the shopping cart may contains only one training and a subscription).
|
||||
*/
|
||||
|
||||
Application.Controllers.controller('ReserveTrainingController', ['$scope', '$stateParams', 'Auth', '$timeout', 'Availability', 'Member', 'availabilityTrainingsPromise', 'plansPromise', 'groupsPromise', 'settingsPromise', 'trainingPromise', '_t', 'uiCalendarConfig', 'CalendarConfig',
|
||||
function ($scope, $stateParams, Auth, $timeout, Availability, Member, availabilityTrainingsPromise, plansPromise, groupsPromise, settingsPromise, trainingPromise, _t, uiCalendarConfig, CalendarConfig) {
|
||||
@ -96,14 +96,14 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// # bind the trainings availabilities with full-Calendar events
|
||||
// bind the trainings availabilities with full-Calendar events
|
||||
$scope.eventSources = [ { events: availabilityTrainingsPromise, textColor: 'black' } ]
|
||||
|
||||
// # the user to deal with, ie. the current user for non-admins
|
||||
// the user to deal with, ie. the current user for non-admins
|
||||
$scope.ctrl =
|
||||
{ member: {} }
|
||||
|
||||
// # list of plans, classified by group
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
for (let group of Array.from(groupsPromise)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
@ -113,7 +113,7 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
}
|
||||
|
||||
// # mapping of fullCalendar events.
|
||||
// mapping of fullCalendar events.
|
||||
$scope.events = {
|
||||
reserved: [], // Slots that the user wants to book
|
||||
modifiable: null, // Slot that the user wants to change
|
||||
@ -122,28 +122,28 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
moved: null // Slots that were just moved by the user (change done) -> {newSlot:* oldSlot: *}
|
||||
}
|
||||
|
||||
// # the moment when the slot selection changed for the last time, used to trigger changes in the cart
|
||||
// the moment when the slot selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.selectionTime = null
|
||||
|
||||
// # the last clicked event in the calender
|
||||
// the last clicked event in the calender
|
||||
$scope.selectedEvent = null
|
||||
|
||||
// # indicates the state of the current view : calendar or plans information
|
||||
// indicates the state of the current view : calendar or plans information
|
||||
$scope.plansAreShown = false
|
||||
|
||||
// # will store the user's plan if he choosed to buy one
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
|
||||
// # the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
// the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.planSelectionTime = null
|
||||
|
||||
// # Selected training
|
||||
// Selected training
|
||||
$scope.training = trainingPromise
|
||||
|
||||
// # 'all' OR training's slug
|
||||
// 'all' OR training's slug
|
||||
$scope.mode = $stateParams.id
|
||||
|
||||
// # fullCalendar (v2) configuration
|
||||
// fullCalendar (v2) configuration
|
||||
$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')),
|
||||
@ -155,29 +155,29 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
}
|
||||
})
|
||||
|
||||
// # Application global settings
|
||||
// Application global settings
|
||||
$scope.settings = settingsPromise
|
||||
|
||||
// # Global config: message to the end user concerning the subscriptions rules
|
||||
// Global config: message to the end user concerning the subscriptions rules
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert
|
||||
|
||||
// # Global config: message to the end user concerning the training reservation
|
||||
// Global config: message to the end user concerning the training reservation
|
||||
$scope.trainingExplicationsAlert = settingsPromise.training_explications_alert
|
||||
|
||||
// # Global config: message to the end user giving advice about the training reservation
|
||||
// Global config: message to the end user giving advice about the training reservation
|
||||
$scope.trainingInformationMessage = settingsPromise.training_information_message
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'added to cart'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'added to cart'
|
||||
*/
|
||||
$scope.markSlotAsAdded = function () {
|
||||
$scope.selectedEvent.backgroundColor = SELECTED_EVENT_BG_COLOR
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
*/
|
||||
$scope.markSlotAsRemoved = function (slot) {
|
||||
slot.backgroundColor = 'white'
|
||||
slot.title = slot.training.name
|
||||
@ -191,23 +191,23 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
// #
|
||||
/**
|
||||
* Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
*/
|
||||
$scope.slotCancelled = () => $scope.markSlotAsRemoved($scope.selectedEvent)
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'currently looking for a new destination to exchange'
|
||||
*/
|
||||
$scope.markSlotAsModifying = function () {
|
||||
$scope.selectedEvent.backgroundColor = '#eee'
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('i_change')
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
// #
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'the slot being exchanged will take this place'
|
||||
*/
|
||||
$scope.changeModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -220,9 +220,9 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
// #
|
||||
/**
|
||||
* When modifying an already booked reservation, callback when the modification was successfully done.
|
||||
*/
|
||||
$scope.modifyTrainingSlot = function () {
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? $scope.events.placable.training.name + ' - ' + _t('i_ve_reserved') : $scope.events.placable.training.name
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -242,9 +242,9 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Cancel the current booking modification, reseting the whole process
|
||||
// #
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
*/
|
||||
$scope.cancelModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
@ -256,10 +256,10 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return updateCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
// reservations. (admins only)
|
||||
// #
|
||||
/**
|
||||
* Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
* reservations. (admins only)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
if ($scope.ctrl.member) {
|
||||
Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
||||
@ -281,10 +281,10 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return $scope.plansAreShown = false
|
||||
}
|
||||
|
||||
// #
|
||||
// Add the provided plan to the current shopping cart
|
||||
// @param plan {Object} the plan to subscribe
|
||||
// #
|
||||
/**
|
||||
* Add the provided plan to the current shopping cart
|
||||
* @param plan {Object} the plan to subscribe
|
||||
*/
|
||||
$scope.selectPlan = function (plan) {
|
||||
// toggle selected plan
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
@ -295,10 +295,10 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Changes the user current view from the plan subsription screen to the machine reservation agenda
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
e.preventDefault()
|
||||
$scope.plansAreShown = false
|
||||
@ -306,16 +306,16 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Switch the user's view from the reservation agenda to the plan subscription
|
||||
// #
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = () => $scope.plansAreShown = true
|
||||
|
||||
// #
|
||||
// Once the reservation is booked (payment process successfully completed), change the event style
|
||||
// in fullCalendar, update the user's subscription and free-credits if needed
|
||||
// @param reservation {Object}
|
||||
// #
|
||||
/**
|
||||
* Once the reservation is booked (payment process successfully completed), change the event style
|
||||
* in fullCalendar, update the user's subscription and free-credits if needed
|
||||
* @param reservation {Object}
|
||||
*/
|
||||
$scope.afterPayment = function (reservation) {
|
||||
$scope.events.paid[0].backgroundColor = 'white'
|
||||
$scope.events.paid[0].is_reserved = true
|
||||
@ -338,29 +338,29 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return refetchCalendar()
|
||||
}
|
||||
|
||||
// #
|
||||
// To use as callback in Array.prototype.filter to get only enabled plans
|
||||
// #
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = plan => !plan.disabled
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return Member.get({ id: $scope.currentUser.id }, member => $scope.ctrl.member = member)
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when the user clicks on a reservation slot in the agenda.
|
||||
// Defines the behavior to adopt depending on the slot status (already booked, free, ready to be reserved ...),
|
||||
// the user's subscription (current or about to be took) and the time (the user cannot modify a booked reservation
|
||||
// if it's too late).
|
||||
// @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
// #
|
||||
/**
|
||||
* Triggered when the user clicks on a reservation slot in the agenda.
|
||||
* Defines the behavior to adopt depending on the slot status (already booked, free, ready to be reserved ...),
|
||||
* the user's subscription (current or about to be took) and the time (the user cannot modify a booked reservation
|
||||
* if it's too late).
|
||||
* @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.selectedEvent = event
|
||||
if ($stateParams.id === 'all') {
|
||||
@ -369,11 +369,11 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
return $scope.selectionTime = new Date()
|
||||
}
|
||||
|
||||
// #
|
||||
// Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
// Append the event tag into the block, just after the event title.
|
||||
// @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
// #
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
* Append the event tag into the block, just after the event title.
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element, view) {
|
||||
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
|
||||
let html = ''
|
||||
@ -384,12 +384,12 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
// This will allow the user to modify the reservation he just booked.
|
||||
// @param slot {Object}
|
||||
// @param reservation {Object}
|
||||
// #
|
||||
/**
|
||||
* After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
* This will allow the user to modify the reservation he just booked.
|
||||
* @param slot {Object}
|
||||
* @param reservation {Object}
|
||||
*/
|
||||
var updateTrainingSlotId = (slot, reservation) =>
|
||||
angular.forEach(reservation.slots, function (s) {
|
||||
if (slot.start_at === slot.start_at) {
|
||||
@ -397,21 +397,21 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Update the calendar's display to render the new attributes of the events
|
||||
// #
|
||||
/**
|
||||
* Update the calendar's display to render the new attributes of the events
|
||||
*/
|
||||
var updateCalendar = () => uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
|
||||
// #
|
||||
// Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
// #
|
||||
/**
|
||||
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
*/
|
||||
var refetchCalendar = () =>
|
||||
$timeout(function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
})
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the controller
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
}
|
||||
|
||||
|
@ -39,48 +39,48 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
},
|
||||
templateUrl: '<%= asset_path "shared/_cart.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// # will store the user's plan if he choosed to buy one
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
|
||||
// # total amount of the bill to pay
|
||||
// total amount of the bill to pay
|
||||
$scope.amountTotal = 0
|
||||
|
||||
// # total amount of the elements in the cart, without considering any coupon
|
||||
// total amount of the elements in the cart, without considering any coupon
|
||||
$scope.totalNoCoupon = 0
|
||||
|
||||
// # Discount coupon to apply to the basket, if any
|
||||
// Discount coupon to apply to the basket, if any
|
||||
$scope.coupon =
|
||||
{ applied: null }
|
||||
|
||||
// # Global config: is the user authorized to change his bookings slots?
|
||||
// Global config: is the user authorized to change his bookings slots?
|
||||
$scope.enableBookingMove = ($scope.settings.booking_move_enable === 'true')
|
||||
|
||||
// # Global config: delay in hours before a booking while changing the booking slot is forbidden
|
||||
// Global config: delay in hours before a booking while changing the booking slot is forbidden
|
||||
$scope.moveBookingDelay = parseInt($scope.settings.booking_move_delay)
|
||||
|
||||
// # Global config: is the user authorized to cancel his bookings?
|
||||
// Global config: is the user authorized to cancel his bookings?
|
||||
$scope.enableBookingCancel = ($scope.settings.booking_cancel_enable === 'true')
|
||||
|
||||
// # Global config: delay in hours before a booking while the cancellation is forbidden
|
||||
// Global config: delay in hours before a booking while the cancellation is forbidden
|
||||
$scope.cancelBookingDelay = parseInt($scope.settings.booking_cancel_delay)
|
||||
|
||||
// #
|
||||
// Add the provided slot to the shopping cart (state transition from free to 'about to be reserved')
|
||||
// and increment the total amount of the cart if needed.
|
||||
// @param slot {Object} fullCalendar event object
|
||||
// #
|
||||
/**
|
||||
* Add the provided slot to the shopping cart (state transition from free to 'about to be reserved')
|
||||
* and increment the total amount of the cart if needed.
|
||||
* @param slot {Object} fullCalendar event object
|
||||
*/
|
||||
$scope.validateSlot = function (slot) {
|
||||
slot.isValid = true
|
||||
return updateCartPrice()
|
||||
}
|
||||
|
||||
// #
|
||||
// Remove the provided slot from the shopping cart (state transition from 'about to be reserved' to free)
|
||||
// and decrement the total amount of the cart if needed.
|
||||
// @param slot {Object} fullCalendar event object
|
||||
// @param index {number} index of the slot in the reservation array
|
||||
// @param [event] {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Remove the provided slot from the shopping cart (state transition from 'about to be reserved' to free)
|
||||
* and decrement the total amount of the cart if needed.
|
||||
* @param slot {Object} fullCalendar event object
|
||||
* @param index {number} index of the slot in the reservation array
|
||||
* @param [event] {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.removeSlot = function (slot, index, event) {
|
||||
if (event) { event.preventDefault() }
|
||||
$scope.events.reserved.splice(index, 1)
|
||||
@ -94,10 +94,10 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return updateCartPrice()
|
||||
}
|
||||
|
||||
// #
|
||||
// Checks that every selected slots were added to the shopping cart. Ie. will return false if
|
||||
// any checked slot was not validated by the user.
|
||||
// #
|
||||
/**
|
||||
* Checks that every selected slots were added to the shopping cart. Ie. will return false if
|
||||
* any checked slot was not validated by the user.
|
||||
*/
|
||||
$scope.isSlotsValid = function () {
|
||||
let isValid = true
|
||||
angular.forEach($scope.events.reserved, function (m) {
|
||||
@ -106,9 +106,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return isValid
|
||||
}
|
||||
|
||||
// #
|
||||
// Switch the user's view from the reservation agenda to the plan subscription
|
||||
// #
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = function () {
|
||||
// first, we ensure that a user was selected (admin) or logged (member)
|
||||
if (Object.keys($scope.user).length > 0) {
|
||||
@ -119,9 +119,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Validates the shopping chart and redirect the user to the payment step
|
||||
// #
|
||||
/**
|
||||
* Validates the shopping chart and redirect the user to the payment step
|
||||
*/
|
||||
$scope.payCart = function () {
|
||||
// first, we check that a user was selected
|
||||
if (Object.keys($scope.user).length > 0) {
|
||||
@ -143,9 +143,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// When modifying an already booked reservation, confirm the modification.
|
||||
// #
|
||||
/**
|
||||
* When modifying an already booked reservation, confirm the modification.
|
||||
*/
|
||||
$scope.modifySlot = () =>
|
||||
Slot.update({ id: $scope.events.modifiable.id }, {
|
||||
slot: {
|
||||
@ -171,10 +171,10 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return console.error(err)
|
||||
})
|
||||
|
||||
// #
|
||||
// Cancel the current booking modification, reseting the whole process
|
||||
// @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
* @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.cancelModifySlot = function (event) {
|
||||
if (event) { event.preventDefault() }
|
||||
if (typeof $scope.onSlotModifyCancel === 'function') { $scope.onSlotModifyCancel() }
|
||||
@ -182,20 +182,20 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return $scope.events.modifiable = null
|
||||
}
|
||||
|
||||
// #
|
||||
// When modifying an already booked reservation, cancel the choice of the new slot
|
||||
// @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
// #
|
||||
/**
|
||||
* When modifying an already booked reservation, cancel the choice of the new slot
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.removeSlotToPlace = function (e) {
|
||||
e.preventDefault()
|
||||
if (typeof $scope.onSlotModifyUnselect === 'function') { $scope.onSlotModifyUnselect() }
|
||||
return $scope.events.placable = null
|
||||
}
|
||||
|
||||
// #
|
||||
// Checks if $scope.events.modifiable and $scope.events.placable have tag incompatibilities
|
||||
// @returns {boolean} true in case of incompatibility
|
||||
// #
|
||||
/**
|
||||
* Checks if $scope.events.modifiable and $scope.events.placable have tag incompatibilities
|
||||
* @returns {boolean} true in case of incompatibility
|
||||
*/
|
||||
$scope.tagMissmatch = function () {
|
||||
if ($scope.events.placable.tag_ids.length === 0) { return false }
|
||||
for (let tag of Array.from($scope.events.modifiable.tags)) {
|
||||
@ -206,17 +206,17 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return false
|
||||
}
|
||||
|
||||
// #
|
||||
// Check if the currently logged user has teh 'admin' role?
|
||||
// @returns {boolean}
|
||||
// #
|
||||
/**
|
||||
* Check if the currently logged user has teh 'admin' role?
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$scope.isAdmin = () => $rootScope.currentUser && ($rootScope.currentUser.role === 'admin')
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
// #
|
||||
// Kind of constructor: these actions will be realized first when the directive is loaded
|
||||
// #
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the directive is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
// What the binded slot
|
||||
$scope.$watch('slotSelectionTime', function (newValue, oldValue) {
|
||||
@ -243,9 +243,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
})
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback triggered when the selected slot changed
|
||||
// #
|
||||
/**
|
||||
* Callback triggered when the selected slot changed
|
||||
*/
|
||||
var slotSelectionChanged = function () {
|
||||
if ($scope.slot) {
|
||||
if (!$scope.slot.is_reserved && !$scope.events.modifiable && !$scope.slot.is_completed) {
|
||||
@ -328,9 +328,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Reset the parameters that may lead to a wrong price but leave the content (events added to cart)
|
||||
// #
|
||||
/**
|
||||
* Reset the parameters that may lead to a wrong price but leave the content (events added to cart)
|
||||
*/
|
||||
var resetCartState = function () {
|
||||
$scope.selectedPlan = null
|
||||
$scope.coupon.applied = null
|
||||
@ -340,10 +340,10 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return $scope.events.placable = null
|
||||
}
|
||||
|
||||
// #
|
||||
// Determines if the provided booked slot is able to be modified by the user.
|
||||
// @param slot {Object} fullCalendar event object
|
||||
// #
|
||||
/**
|
||||
* Determines if the provided booked slot is able to be modified by the user.
|
||||
* @param slot {Object} fullCalendar event object
|
||||
*/
|
||||
var slotCanBeModified = function (slot) {
|
||||
if ($scope.isAdmin()) { return true }
|
||||
const slotStart = moment(slot.start)
|
||||
@ -355,10 +355,10 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Determines if the provided booked slot is able to be canceled by the user.
|
||||
// @param slot {Object} fullCalendar event object
|
||||
// #
|
||||
/**
|
||||
* Determines if the provided booked slot is able to be canceled by the user.
|
||||
* @param slot {Object} fullCalendar event object
|
||||
*/
|
||||
var slotCanBeCanceled = function (slot) {
|
||||
if ($scope.isAdmin()) { return true }
|
||||
const slotStart = moment(slot.start)
|
||||
@ -370,9 +370,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback triggered when the selected slot changed
|
||||
// #
|
||||
/**
|
||||
* Callback triggered when the selected slot changed
|
||||
*/
|
||||
var planSelectionChanged = function () {
|
||||
if (Auth.isAuthenticated()) {
|
||||
if ($scope.selectedPlan !== $scope.plan) {
|
||||
@ -389,9 +389,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Update the total price of the current selection/reservation
|
||||
// #
|
||||
/**
|
||||
* Update the total price of the current selection/reservation
|
||||
*/
|
||||
var updateCartPrice = function () {
|
||||
if (Object.keys($scope.user).length > 0) {
|
||||
const r = mkReservation($scope.user, $scope.events.reserved, $scope.selectedPlan)
|
||||
@ -417,12 +417,12 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
})
|
||||
)
|
||||
|
||||
// #
|
||||
// Format the parameters expected by /api/prices/compute or /api/reservations and return the resulting object
|
||||
// @param reservation {Object} as returned by mkReservation()
|
||||
// @param coupon {Object} Coupon as returned from the API
|
||||
// @return {{reservation:Object, coupon_code:string}}
|
||||
// #
|
||||
/**
|
||||
* Format the parameters expected by /api/prices/compute or /api/reservations and return the resulting object
|
||||
* @param reservation {Object} as returned by mkReservation()
|
||||
* @param coupon {Object} Coupon as returned from the API
|
||||
* @return {{reservation:Object, coupon_code:string}}
|
||||
*/
|
||||
var mkRequestParams = function (reservation, coupon) {
|
||||
const params = {
|
||||
reservation,
|
||||
@ -432,13 +432,13 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return params
|
||||
}
|
||||
|
||||
// #
|
||||
// Create an hash map implementing the Reservation specs
|
||||
// @param member {Object} User as retreived from the API: current user / selected user if current is admin
|
||||
// @param slots {Array<Object>} Array of fullCalendar events: slots selected on the calendar
|
||||
// @param [plan] {Object} Plan as retrived from the API: plan to buy with the current reservation
|
||||
// @return {{user_id:Number, reservable_id:Number, reservable_type:String, slots_attributes:Array<Object>, plan_id:Number|null}}
|
||||
// #
|
||||
/**
|
||||
* Create an hash map implementing the Reservation specs
|
||||
* @param member {Object} User as retreived from the API: current user / selected user if current is admin
|
||||
* @param slots {Array<Object>} Array of fullCalendar events: slots selected on the calendar
|
||||
* @param [plan] {Object} Plan as retrived from the API: plan to buy with the current reservation
|
||||
* @return {{user_id:Number, reservable_id:Number, reservable_type:String, slots_attributes:Array<Object>, plan_id:Number|null}}
|
||||
*/
|
||||
var mkReservation = function (member, slots, plan = null) {
|
||||
const reservation = {
|
||||
user_id: member.id,
|
||||
@ -459,9 +459,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return reservation
|
||||
}
|
||||
|
||||
// #
|
||||
// Open a modal window that allows the user to process a credit card payment for his current shopping cart.
|
||||
// #
|
||||
/**
|
||||
* Open a modal window that allows the user to process a credit card payment for his current shopping cart.
|
||||
*/
|
||||
var payByStripe = reservation =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "stripe/payment_modal.html" %>',
|
||||
@ -500,9 +500,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
// Used in wallet info template to interpolate some translations
|
||||
$scope.numberFilter = $filter('number')
|
||||
|
||||
// #
|
||||
// Callback to process the payment with Stripe, triggered on button click
|
||||
// #
|
||||
/**
|
||||
* Callback to process the payment with Stripe, triggered on button click
|
||||
*/
|
||||
return $scope.payment = function (status, response) {
|
||||
if (response.error) {
|
||||
return growl.error(response.error.message)
|
||||
@ -538,9 +538,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
] })
|
||||
.result['finally'](null).then(reservation => afterPayment(reservation))
|
||||
|
||||
// #
|
||||
// Open a modal window that allows the user to process a local payment for his current shopping cart (admin only).
|
||||
// #
|
||||
/**
|
||||
* Open a modal window that allows the user to process a local payment for his current shopping cart (admin only).
|
||||
*/
|
||||
var payOnSite = reservation =>
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "shared/valid_reservation_modal.html" %>',
|
||||
@ -587,9 +587,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to process the local payment, triggered on button click
|
||||
// #
|
||||
/**
|
||||
* Callback to process the local payment, triggered on button click
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$scope.attempting = true
|
||||
return Reservation.save(mkRequestParams($scope.reservation, coupon), function (reservation) {
|
||||
@ -607,9 +607,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
] })
|
||||
.result['finally'](null).then(reservation => afterPayment(reservation))
|
||||
|
||||
// #
|
||||
// Actions to run after the payment was successfull
|
||||
// #
|
||||
/**
|
||||
* Actions to run after the payment was successfull
|
||||
*/
|
||||
var afterPayment = function (reservation) {
|
||||
// we set the cart content as 'paid' to display a summary of the transaction
|
||||
$scope.events.paid = $scope.events.reserved
|
||||
@ -622,7 +622,7 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return $scope.selectedPlan = null
|
||||
}
|
||||
|
||||
// # !!! MUST BE CALLED AT THE END of the directive
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize()
|
||||
}
|
||||
})
|
||||
|
@ -40,9 +40,9 @@ Application.Directives.directive('coupon', [ '$rootScope', 'Coupon', '_t', ($roo
|
||||
}
|
||||
})
|
||||
|
||||
// #
|
||||
// Callback to validate the code
|
||||
// #
|
||||
/**
|
||||
* Callback to validate the code
|
||||
*/
|
||||
$scope.validateCode = function () {
|
||||
$scope.messages = []
|
||||
if ($scope.couponCode === '') {
|
||||
@ -66,9 +66,9 @@ Application.Directives.directive('coupon', [ '$rootScope', 'Coupon', '_t', ($roo
|
||||
}
|
||||
}
|
||||
|
||||
// #
|
||||
// Callback to remove the message at provided index from the displayed list
|
||||
// #
|
||||
/**
|
||||
* Callback to remove the message at provided index from the displayed list
|
||||
*/
|
||||
return $scope.closeMessage = index => $scope.messages.splice(index, 1)
|
||||
}
|
||||
})
|
||||
|
@ -11,14 +11,14 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
// #
|
||||
// This directive will allow to select a member.
|
||||
// Please surround it with a ng-if directive to prevent it from being used by a non-admin user.
|
||||
// The resulting member will be set into the parent $scope (=> $scope.ctrl.member).
|
||||
// The directive takes an optional parameter "subscription" as a "boolean string" that will filter the user
|
||||
// which have a valid running subscription or not.
|
||||
// Usage: <select-member [subscription="false|true"]></select-member>
|
||||
// #
|
||||
/**
|
||||
* This directive will allow to select a member.
|
||||
* Please surround it with a ng-if directive to prevent it from being used by a non-admin user.
|
||||
* The resulting member will be set into the parent $scope (=> $scope.ctrl.member).
|
||||
* The directive takes an optional parameter "subscription" as a "boolean string" that will filter the user
|
||||
* which have a valid running subscription or not.
|
||||
* Usage: <select-member [subscription="false|true"]></select-member>
|
||||
*/
|
||||
Application.Directives.directive('selectMember', [ 'Diacritics', 'Member', (Diacritics, Member) =>
|
||||
({
|
||||
restrict: 'E',
|
||||
|
@ -38,7 +38,7 @@ angular.module('application.router', ['ui.router'])
|
||||
]
|
||||
},
|
||||
onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', function ($rootScope, logoFile, logoBlackFile) {
|
||||
// # Application logo
|
||||
// Application logo
|
||||
$rootScope.logo = logoFile.custom_asset
|
||||
return $rootScope.logoBlack = logoBlackFile.custom_asset
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user