mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
added semicolons
This commit is contained in:
parent
8cd533b5a6
commit
f528b2021d
@ -1,4 +1,7 @@
|
||||
{
|
||||
"extends": "standard"
|
||||
"extends": "standard",
|
||||
"rules": {
|
||||
"semi": ["error", "always"]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,21 +9,21 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('AboutController', ['$scope', 'Setting', 'CustomAsset', function ($scope, Setting, CustomAsset) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
Setting.get({ name: 'about_title' }, data => $scope.aboutTitle = data.setting)
|
||||
Setting.get({ name: 'about_title' }, data => $scope.aboutTitle = data.setting);
|
||||
|
||||
Setting.get({ name: 'about_body' }, data => $scope.aboutBody = data.setting)
|
||||
Setting.get({ name: 'about_body' }, data => $scope.aboutBody = data.setting);
|
||||
|
||||
Setting.get({ name: 'about_contacts' }, data => $scope.aboutContacts = data.setting)
|
||||
Setting.get({ name: 'about_contacts' }, data => $scope.aboutContacts = data.setting);
|
||||
|
||||
// retrieve the CGU
|
||||
CustomAsset.get({ name: 'cgu-file' }, cgu => $scope.cgu = cgu.custom_asset)
|
||||
CustomAsset.get({ name: 'cgu-file' }, cgu => $scope.cgu = cgu.custom_asset);
|
||||
|
||||
// retrieve the CGV
|
||||
return CustomAsset.get({ name: 'cgv-file' }, cgv => $scope.cgv = cgv.custom_asset)
|
||||
return CustomAsset.get({ name: 'cgv-file' }, cgv => $scope.cgv = cgv.custom_asset);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -11,7 +11,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
const METHODS = {
|
||||
'DatabaseProvider': 'local_database',
|
||||
'OAuth2Provider': 'o_auth2'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterate through the provided array and return the index of the requested element
|
||||
@ -28,8 +28,8 @@ const METHODS = {
|
||||
* @returns {number} index of the requested element, in the provided array
|
||||
*/
|
||||
const findIdxById = function (elements, id) {
|
||||
return (elements.map(function (elem) { return elem.id })).indexOf(id)
|
||||
}
|
||||
return (elements.map(function (elem) { return elem.id; })).indexOf(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* For OAuth2 authentications, mapping the user's ID is mandatory. This function will check that this mapping
|
||||
@ -40,11 +40,11 @@ const findIdxById = function (elements, id) {
|
||||
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) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides a set of common callback methods and data to the $scope parameter. These methods are used
|
||||
@ -63,15 +63,15 @@ const check_oauth2_id_is_mapped = function (mappings) {
|
||||
class AuthenticationController {
|
||||
constructor ($scope, $state, $uibModal, mappingFieldsPromise) {
|
||||
// list of supported authentication methods
|
||||
$scope.authMethods = METHODS
|
||||
$scope.authMethods = METHODS;
|
||||
|
||||
// list of fields that can be mapped through the SSO
|
||||
$scope.mappingFields = mappingFieldsPromise
|
||||
$scope.mappingFields = mappingFieldsPromise;
|
||||
|
||||
/**
|
||||
* Changes the admin's view to the members list page
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.admin.members') }
|
||||
$scope.cancel = function () { $state.go('app.admin.members'); };
|
||||
|
||||
/**
|
||||
* Open a modal allowing to specify the data mapping for the given field
|
||||
@ -81,11 +81,11 @@ class AuthenticationController {
|
||||
templateUrl: '<%= asset_path "admin/authentications/_data_mapping.html" %>',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
field () { return mapping },
|
||||
field () { return mapping; },
|
||||
datatype () {
|
||||
for (let field of Array.from($scope.mappingFields[mapping.local_model])) {
|
||||
if (field[0] === mapping.local_field) {
|
||||
return field[1]
|
||||
return field[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,12 +93,12 @@ class AuthenticationController {
|
||||
|
||||
controller: ['$scope', '$uibModalInstance', 'field', 'datatype', function ($scope, $uibModalInstance, field, datatype) {
|
||||
// parent field
|
||||
$scope.field = field
|
||||
$scope.field = field;
|
||||
// expected data type
|
||||
$scope.datatype = datatype
|
||||
$scope.datatype = datatype;
|
||||
// data transformation rules
|
||||
$scope.transformation =
|
||||
{ rules: field.transformation || { type: datatype } }
|
||||
{ rules: field.transformation || { type: datatype } };
|
||||
// available transformation formats
|
||||
$scope.formats = {
|
||||
date: [
|
||||
@ -123,25 +123,25 @@ class AuthenticationController {
|
||||
value: 'timestamp-ms'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new mapping between anything and an expected integer
|
||||
$scope.addIntegerMapping = function () {
|
||||
if (!angular.isArray($scope.transformation.rules.mapping)) {
|
||||
$scope.transformation.rules.mapping = []
|
||||
$scope.transformation.rules.mapping = [];
|
||||
}
|
||||
return $scope.transformation.rules.mapping.push({ from: '', to: 0 })
|
||||
}
|
||||
return $scope.transformation.rules.mapping.push({ from: '', to: 0 });
|
||||
};
|
||||
|
||||
// close and save the modifications
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.transformation.rules) }
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.transformation.rules); };
|
||||
|
||||
// do not save the modifications
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss() }
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss(); };
|
||||
}
|
||||
] })
|
||||
.result['finally'](null).then(function (transfo_rules) { mapping.transformation = transfo_rules })
|
||||
}
|
||||
.result['finally'](null).then(function (transfo_rules) { mapping.transformation = transfo_rules; });
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// full list of authentication providers
|
||||
$scope.providers = authProvidersPromise
|
||||
$scope.providers = authProvidersPromise;
|
||||
|
||||
/**
|
||||
* Translate the classname into an explicit textual message
|
||||
@ -161,13 +161,13 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
* @returns {string}
|
||||
*/
|
||||
$scope.getType = function (type) {
|
||||
const text = METHODS[type]
|
||||
const text = METHODS[type];
|
||||
if (typeof text !== 'undefined') {
|
||||
return _t(text)
|
||||
return _t(text);
|
||||
} else {
|
||||
return _t('unknown') + type
|
||||
return _t('unknown') + type;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate the status string into an explicit textual message
|
||||
@ -176,12 +176,12 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
*/
|
||||
$scope.getState = function (status) {
|
||||
switch (status) {
|
||||
case 'active': return _t('active')
|
||||
case 'pending': return _t('pending')
|
||||
case 'previous': return _t('previous_provider')
|
||||
default: return _t('unknown') + status
|
||||
case 'active': return _t('active');
|
||||
case 'pending': return _t('pending');
|
||||
case 'previous': return _t('previous_provider');
|
||||
default: return _t('unknown') + status;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ask for confirmation then delete the specified provider
|
||||
@ -196,7 +196,7 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_the_TYPE_authentication_provider_NAME', { TYPE: $scope.getType(provider.providable_type), NAME: provider.name })
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -205,31 +205,31 @@ Application.Controllers.controller('AuthentificationController', ['$scope', '$st
|
||||
AuthProvider.delete(
|
||||
{ id: provider.id },
|
||||
function () {
|
||||
providers.splice(findIdxById(providers, provider.id), 1)
|
||||
growl.success(_t('authentication_provider_successfully_deleted'))
|
||||
providers.splice(findIdxById(providers, provider.id), 1);
|
||||
growl.success(_t('authentication_provider_successfully_deleted'));
|
||||
},
|
||||
function () { growl.error(_t('an_error_occurred_unable_to_delete_the_specified_provider')) }
|
||||
)
|
||||
function () { growl.error(_t('an_error_occurred_unable_to_delete_the_specified_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'
|
||||
$scope.mode = 'creation';
|
||||
|
||||
// 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
|
||||
@ -238,10 +238,10 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
// === OAuth2Provider ===
|
||||
if ($scope.provider.providable_type === 'OAuth2Provider') {
|
||||
if (typeof $scope.provider.providable_attributes.o_auth2_mappings_attributes === 'undefined') {
|
||||
return $scope.provider.providable_attributes['o_auth2_mappings_attributes'] = []
|
||||
return $scope.provider.providable_attributes['o_auth2_mappings_attributes'] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// Add others providers initializers here if needed ...
|
||||
|
||||
/**
|
||||
@ -249,25 +249,25 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
*/
|
||||
$scope.registerProvider = function () {
|
||||
// === DatabaseProvider ===
|
||||
let provider
|
||||
let provider;
|
||||
if ($scope.provider.providable_type === 'DatabaseProvider') {
|
||||
// prevent from adding mode than 1
|
||||
for (provider of Array.from(authProvidersPromise)) {
|
||||
if (provider.providable_type === 'DatabaseProvider') {
|
||||
growl.error(_t('a_local_database_provider_already_exists_unable_to_create_another'))
|
||||
return false
|
||||
growl.error(_t('a_local_database_provider_already_exists_unable_to_create_another'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return AuthProvider.save({ auth_provider: $scope.provider }, function (provider) {
|
||||
growl.success(_t('local_provider_successfully_saved'))
|
||||
return $state.go('app.admin.members')
|
||||
})
|
||||
growl.success(_t('local_provider_successfully_saved'));
|
||||
return $state.go('app.admin.members');
|
||||
});
|
||||
// === OAuth2Provider ===
|
||||
} else if ($scope.provider.providable_type === 'OAuth2Provider') {
|
||||
// check the ID mapping
|
||||
if (!check_oauth2_id_is_mapped($scope.provider.providable_attributes.o_auth2_mappings_attributes)) {
|
||||
growl.error(_t('it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'))
|
||||
return false
|
||||
growl.error(_t('it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'));
|
||||
return false;
|
||||
}
|
||||
// discourage the use of unsecure SSO
|
||||
if (!($scope.provider.providable_attributes.base_url.indexOf('https://') > -1)) {
|
||||
@ -281,30 +281,30 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
msg: _t('beware_the_oauth2_authenticatoin_provider_you_are_about_to_add_isnt_using_HTTPS') +
|
||||
_t('this_is_a_serious_security_issue_on_internet_and_should_never_be_used_except_for_testing_purposes') +
|
||||
_t('do_you_really_want_to_continue')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // unsecured http confirmed
|
||||
AuthProvider.save({ auth_provider: $scope.provider }, function (provider) {
|
||||
growl.success(_t('unsecured_oauth2_provider_successfully_added'))
|
||||
return $state.go('app.admin.members')
|
||||
})
|
||||
growl.success(_t('unsecured_oauth2_provider_successfully_added'));
|
||||
return $state.go('app.admin.members');
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
AuthProvider.save({ auth_provider: $scope.provider }, function (provider) {
|
||||
growl.success(_t('oauth2_provider_successfully_added'))
|
||||
return $state.go('app.admin.members')
|
||||
})
|
||||
growl.success(_t('oauth2_provider_successfully_added'));
|
||||
return $state.go('app.admin.members');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Using the AuthenticationController
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise)
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Page to edit an already added authentication provider
|
||||
@ -312,9 +312,9 @@ Application.Controllers.controller('NewAuthenticationController', ['$scope', '$s
|
||||
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
|
||||
$scope.provider = providerPromise
|
||||
$scope.provider = providerPromise;
|
||||
|
||||
$scope.mode = 'edition'
|
||||
$scope.mode = 'edition';
|
||||
|
||||
/**
|
||||
* Update the current provider with the new inputs
|
||||
@ -322,21 +322,21 @@ Application.Controllers.controller('EditAuthenticationController', ['$scope', '$
|
||||
$scope.updateProvider = function () {
|
||||
// check the ID mapping
|
||||
if (!check_oauth2_id_is_mapped($scope.provider.providable_attributes.o_auth2_mappings_attributes)) {
|
||||
growl.error(_t('it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'))
|
||||
return false
|
||||
growl.error(_t('it_is_required_to_set_the_matching_between_User.uid_and_the_API_to_add_this_provider'));
|
||||
return false;
|
||||
}
|
||||
return AuthProvider.update(
|
||||
{ id: $scope.provider.id },
|
||||
{ auth_provider: $scope.provider },
|
||||
function (provider) {
|
||||
growl.success(_t('provider_successfully_updated'))
|
||||
$state.go('app.admin.members')
|
||||
growl.success(_t('provider_successfully_updated'));
|
||||
$state.go('app.admin.members');
|
||||
},
|
||||
function () { growl.error(_t('an_error_occurred_unable_to_update_the_provider')) }
|
||||
)
|
||||
}
|
||||
function () { growl.error(_t('an_error_occurred_unable_to_update_the_provider')); }
|
||||
);
|
||||
};
|
||||
|
||||
// Using the AuthenticationController
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise)
|
||||
return new AuthenticationController($scope, $state, $uibModal, mappingFieldsPromise);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -12,7 +12,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in the calendar management page
|
||||
@ -23,29 +23,29 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// The calendar is divided in slots of 30 minutes
|
||||
let loadingCb
|
||||
const BASE_SLOT = '00:30:00'
|
||||
let loadingCb;
|
||||
const BASE_SLOT = '00:30:00';
|
||||
|
||||
// The bookings can be positioned every half hours
|
||||
const BOOKING_SNAP = '00:30:00'
|
||||
const BOOKING_SNAP = '00:30:00';
|
||||
|
||||
// We do not allow the creation of slots that are not a multiple of 60 minutes
|
||||
const SLOT_MULTIPLE = 60
|
||||
const SLOT_MULTIPLE = 60;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// list of the FabLab machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
// currently selected availability
|
||||
$scope.availability = null
|
||||
$scope.availability = null;
|
||||
|
||||
// bind the availabilities slots with full-Calendar events
|
||||
$scope.eventSources = []
|
||||
$scope.eventSources = [];
|
||||
$scope.eventSources.push({
|
||||
url: '/api/availabilities',
|
||||
textColor: 'black'
|
||||
})
|
||||
});
|
||||
|
||||
// fullCalendar (v2) configuration
|
||||
$scope.calendarConfig = CalendarConfig({
|
||||
@ -56,18 +56,18 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
minTime: moment.duration(moment(bookingWindowStart.setting.value).format('HH:mm:ss')),
|
||||
maxTime: moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')),
|
||||
select (start, end, jsEvent, view) {
|
||||
return calendarSelectCb(start, end, jsEvent, view)
|
||||
return calendarSelectCb(start, end, jsEvent, view);
|
||||
},
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view)
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element)
|
||||
return eventRenderCb(event, element);
|
||||
},
|
||||
loading (isLoading, view) {
|
||||
return loadingCb(isLoading, view)
|
||||
return loadingCb(isLoading, view);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* Open a confirmation modal to cancel the booking of a user for the currently selected event.
|
||||
@ -84,7 +84,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
msg: _t('admin_calendar.do_you_really_want_to_cancel_the_USER_s_reservation_the_DATE_at_TIME_concerning_RESERVATION'
|
||||
, { GENDER: getGender($scope.currentUser), USER: slot.user.name, DATE: moment(slot.start_at).format('L'), TIME: moment(slot.start_at).format('LT'), RESERVATION: slot.reservable.name }
|
||||
, 'messageformat')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -96,20 +96,20 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
// update the canceled_at attribute
|
||||
for (let resa of Array.from($scope.reservations)) {
|
||||
if (resa.slot_id === data.id) {
|
||||
resa.canceled_at = data.canceled_at
|
||||
break
|
||||
resa.canceled_at = data.canceled_at;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// notify the admin
|
||||
return growl.success(_t('admin_calendar.reservation_was_successfully_cancelled'))
|
||||
return growl.success(_t('admin_calendar.reservation_was_successfully_cancelled'));
|
||||
},
|
||||
function (data, status) { // failed
|
||||
growl.error(_t('admin_calendar.reservation_cancellation_failed'))
|
||||
growl.error(_t('admin_calendar.reservation_cancellation_failed'));
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a confirmation modal to remove a machine for the currently selected availability,
|
||||
@ -118,7 +118,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
*/
|
||||
$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'))
|
||||
return growl.error(_t('admin_calendar.unable_to_remove_the_last_machine_of_the_slot_delete_the_slot_rather'));
|
||||
} else {
|
||||
// open a confirmation dialog
|
||||
return dialogs.confirm({
|
||||
@ -129,36 +129,36 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
msg: _t('admin_calendar.do_you_really_want_to_remove_MACHINE_from_this_slot', { GENDER: getGender($scope.currentUser), MACHINE: machine.name }, 'messageformat') + ' ' +
|
||||
_t('admin_calendar.this_will_prevent_any_new_reservation_on_this_slot_but_wont_cancel_those_existing') + ' ' +
|
||||
_t('admin_calendar.beware_this_cannot_be_reverted')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () {
|
||||
// the admin has confirmed, remove the machine
|
||||
const machines = $scope.availability.machine_ids
|
||||
const machines = $scope.availability.machine_ids;
|
||||
for (let m_id = 0; m_id < machines.length; m_id++) {
|
||||
const key = machines[m_id]
|
||||
const key = machines[m_id];
|
||||
if (m_id === machine.id) {
|
||||
machines.splice(key, 1)
|
||||
machines.splice(key, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return Availability.update({ id: $scope.availability.id }, { availability: { machines_attributes: [{ id: machine.id, _destroy: true }] } }
|
||||
, function (data, status) { // success
|
||||
// update the machine_ids attribute
|
||||
$scope.availability.machine_ids = data.machine_ids
|
||||
$scope.availability.title = data.title
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
$scope.availability.machine_ids = data.machine_ids;
|
||||
$scope.availability.title = data.title;
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents');
|
||||
// notify the admin
|
||||
return growl.success(_t('admin_calendar.the_machine_was_successfully_removed_from_the_slot'))
|
||||
return growl.success(_t('admin_calendar.the_machine_was_successfully_removed_from_the_slot'));
|
||||
}
|
||||
, function (data, status) { // failed
|
||||
growl.error(_t('admin_calendar.deletion_failed'))
|
||||
growl.error(_t('admin_calendar.deletion_failed'));
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to alert the admin that the export request was acknowledged and is
|
||||
@ -167,26 +167,26 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
$scope.alertExport = function (type) {
|
||||
Export.status({ category: 'availabilities', type }).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
return growl.success(_t('admin_calendar.export_is_running_you_ll_be_notified_when_its_ready'))
|
||||
return growl.success(_t('admin_calendar.export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
const locked = $scope.availability.lock;
|
||||
// then check if we'll allow reservations locking
|
||||
let prevent = !locked // if currently locked, allow unlock anyway
|
||||
let prevent = !locked; // if currently locked, allow unlock anyway
|
||||
if (!locked) {
|
||||
prevent = false
|
||||
prevent = false;
|
||||
angular.forEach($scope.reservations, function (r) {
|
||||
if (r.canceled_at === null) {
|
||||
return prevent = true
|
||||
return prevent = true;
|
||||
}
|
||||
}) // if currently unlocked and has any non-cancelled reservation, disallow locking
|
||||
}); // if currently unlocked and has any non-cancelled reservation, disallow locking
|
||||
}
|
||||
if (!prevent) {
|
||||
// open a confirmation dialog
|
||||
@ -197,7 +197,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
return {
|
||||
title: _t('admin_calendar.confirmation_required'),
|
||||
msg: locked ? _t('admin_calendar.do_you_really_want_to_allow_reservations') : _t('admin_calendar.do_you_really_want_to_block_this_slot')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -207,21 +207,21 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
{ id: $scope.availability.id },
|
||||
{ lock: !locked },
|
||||
function (data) { // success
|
||||
$scope.availability = data
|
||||
growl.success(locked ? _t('admin_calendar.unlocking_success') : _t('admin_calendar.locking_success'))
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
$scope.availability = data;
|
||||
growl.success(locked ? _t('admin_calendar.unlocking_success') : _t('admin_calendar.locking_success'));
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
|
||||
},
|
||||
function (error) { // failed
|
||||
growl.error(locked ? _t('admin_calendar.unlocking_failed') : _t('admin_calendar.locking_failed'))
|
||||
console.error(error)
|
||||
growl.error(locked ? _t('admin_calendar.unlocking_failed') : _t('admin_calendar.locking_failed'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return growl.error(_t('admin_calendar.unlockable_because_reservations'))
|
||||
return growl.error(_t('admin_calendar.unlockable_because_reservations'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Confirm and destroy the slot in $scope.availability
|
||||
@ -235,7 +235,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
return {
|
||||
title: _t('admin_calendar.confirmation_required'),
|
||||
msg: _t('admin_calendar.do_you_really_want_to_delete_this_slot')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -244,17 +244,17 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
Availability.delete(
|
||||
{ id: $scope.availability.id },
|
||||
function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents', $scope.availability.id)
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents', $scope.availability.id);
|
||||
|
||||
growl.success(_t('admin_calendar.the_slot_START-END_has_been_successfully_deleted', { START: moment(event.start).format('LL LT'), END: moment(event.end).format('LT') }))
|
||||
$scope.availability = null
|
||||
growl.success(_t('admin_calendar.the_slot_START-END_has_been_successfully_deleted', { START: moment(event.start).format('LL LT'), END: moment(event.end).format('LT') }));
|
||||
$scope.availability = null;
|
||||
},
|
||||
function () {
|
||||
growl.error(_t('admin_calendar.unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member', { START: moment(event.start).format('LL LT'), END: moment(event.end).format('LT') }))
|
||||
})
|
||||
growl.error(_t('admin_calendar.unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member', { START: moment(event.start).format('LL LT'), END: moment(event.end).format('LT') }));
|
||||
});
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -265,31 +265,31 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
*/
|
||||
var getGender = function (user) {
|
||||
if (user.profile) {
|
||||
if (user.profile.gender === 'true') { return 'male' } else { return 'female' }
|
||||
} else { return 'other' }
|
||||
}
|
||||
if (user.profile.gender === 'true') { return 'male'; } else { return 'female'; }
|
||||
} else { return 'other'; }
|
||||
};
|
||||
|
||||
// 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)
|
||||
start = moment.tz(start.toISOString(), Fablab.timezone);
|
||||
end = moment.tz(end.toISOString(), Fablab.timezone);
|
||||
// first we check that the selected slot is an N-hours multiple (ie. not decimal)
|
||||
if (Number.isInteger(parseInt((end.valueOf() - start.valueOf()) / (SLOT_MULTIPLE * 1000), 10) / SLOT_MULTIPLE)) {
|
||||
const today = new Date()
|
||||
const today = new Date();
|
||||
if (parseInt((start.valueOf() - today) / (60 * 1000), 10) >= 0) {
|
||||
// then we open a modal window to let the admin specify the slot type
|
||||
const modalInstance = $uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/calendar/eventModal.html" %>',
|
||||
controller: 'CreateEventModalController',
|
||||
resolve: {
|
||||
start () { return start },
|
||||
end () { return end },
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise }]
|
||||
} })
|
||||
start () { return start; },
|
||||
end () { return end; },
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }]
|
||||
} });
|
||||
// when the modal is closed, we send the slot to the server for saving
|
||||
modalInstance.result.then(
|
||||
function (availability) {
|
||||
@ -308,31 +308,31 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
machine_ids: availability.machine_ids
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
},
|
||||
function () { uiCalendarConfig.calendars.calendar.fullCalendar('unselect') }
|
||||
)
|
||||
function () { uiCalendarConfig.calendars.calendar.fullCalendar('unselect'); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('unselect')
|
||||
}
|
||||
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/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.availability = event
|
||||
$scope.availability = event;
|
||||
|
||||
// if the user has clicked on the delete event button, delete the event
|
||||
if ($(jsEvent.target).hasClass('remove-event')) {
|
||||
return $scope.removeSlot()
|
||||
return $scope.removeSlot();
|
||||
// if the user has only clicked on the event, display its reservations
|
||||
} else {
|
||||
return Availability.reservations({ id: event.id }, function (reservations) { $scope.reservations = reservations })
|
||||
return Availability.reservations({ id: event.id }, function (reservations) { $scope.reservations = reservations; });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
@ -340,16 +340,16 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
* @see http://fullcalendar.io/docs/event_rendering/eventRender/
|
||||
*/
|
||||
var eventRenderCb = function (event, element) {
|
||||
element.find('.fc-content').prepend('<span class="remove-event">x </span>')
|
||||
element.find('.fc-content').prepend('<span class="remove-event">x </span>');
|
||||
if (event.tags.length > 0) {
|
||||
let html = ''
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
html += `<span class='label label-success text-white'>${tag.name}</span> `
|
||||
html += `<span class='label label-success text-white'>${tag.name}</span> `;
|
||||
}
|
||||
element.find('.fc-title').append(`<br/>${html}`)
|
||||
element.find('.fc-title').append(`<br/>${html}`);
|
||||
}
|
||||
// force return to prevent coffee-script auto-return to return random value (possiblity falsy)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when resource fetching starts/stops.
|
||||
@ -358,12 +358,12 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
return loadingCb = function (isLoading, view) {
|
||||
if (isLoading) {
|
||||
// we remove existing events when fetching starts to prevent duplicates
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the slot creation modal window
|
||||
@ -371,34 +371,34 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
|
||||
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
|
||||
$scope.start = start
|
||||
$scope.start = start;
|
||||
|
||||
// $uibModal parameter
|
||||
$scope.end = end
|
||||
$scope.end = end;
|
||||
|
||||
// machines list
|
||||
$scope.machines = machinesPromise.filter(function (m) { return !m.disabled })
|
||||
$scope.machines = machinesPromise.filter(function (m) { return !m.disabled; });
|
||||
|
||||
// trainings list
|
||||
$scope.trainings = trainingsPromise.filter(function (t) { return !t.disabled })
|
||||
$scope.trainings = trainingsPromise.filter(function (t) { return !t.disabled; });
|
||||
|
||||
// spaces list
|
||||
$scope.spaces = spacesPromise.filter(function (s) { return !s.disabled })
|
||||
$scope.spaces = spacesPromise.filter(function (s) { return !s.disabled; });
|
||||
|
||||
// machines associated with the created slot
|
||||
$scope.selectedMachines = []
|
||||
$scope.selectedMachines = [];
|
||||
|
||||
// training associated with the created slot
|
||||
$scope.selectedTraining = null
|
||||
$scope.selectedTraining = null;
|
||||
|
||||
// space associated with the created slot
|
||||
$scope.selectedSpace = null
|
||||
$scope.selectedSpace = null;
|
||||
|
||||
// UI step
|
||||
$scope.step = 1
|
||||
$scope.step = 1;
|
||||
|
||||
// the user is not able to edit the ending time of the availability, unless he set the type to 'training'
|
||||
$scope.endDateReadOnly = true
|
||||
$scope.endDateReadOnly = true;
|
||||
|
||||
// timepickers configuration
|
||||
$scope.timepickers = {
|
||||
@ -410,27 +410,27 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
hstep: 1,
|
||||
mstep: 5
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 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}
|
||||
*/
|
||||
$scope.toggleSelection = function (machine) {
|
||||
const index = $scope.selectedMachines.indexOf(machine)
|
||||
const index = $scope.selectedMachines.indexOf(machine);
|
||||
if (index > -1) {
|
||||
return $scope.selectedMachines.splice(index, 1)
|
||||
return $scope.selectedMachines.splice(index, 1);
|
||||
} else {
|
||||
return $scope.selectedMachines.push(machine)
|
||||
return $scope.selectedMachines.push(machine);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the modal window validation: save the slot and closes the modal
|
||||
@ -438,49 +438,49 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
$scope.ok = function () {
|
||||
if ($scope.availability.available_type === 'machines') {
|
||||
if ($scope.selectedMachines.length > 0) {
|
||||
$scope.availability.machine_ids = $scope.selectedMachines.map(function (m) { return m.id })
|
||||
$scope.availability.machine_ids = $scope.selectedMachines.map(function (m) { return m.id; });
|
||||
} else {
|
||||
growl.error(_t('admin_calendar.you_should_select_at_least_a_machine'))
|
||||
return
|
||||
growl.error(_t('admin_calendar.you_should_select_at_least_a_machine'));
|
||||
return;
|
||||
}
|
||||
} else if ($scope.availability.available_type === 'training') {
|
||||
$scope.availability.training_ids = [$scope.selectedTraining.id]
|
||||
$scope.availability.training_ids = [$scope.selectedTraining.id];
|
||||
} else if ($scope.availability.available_type === 'space') {
|
||||
$scope.availability.space_ids = [$scope.selectedSpace.id]
|
||||
$scope.availability.space_ids = [$scope.selectedSpace.id];
|
||||
}
|
||||
return Availability.save(
|
||||
{ availability: $scope.availability }
|
||||
, function (availability) { $uibModalInstance.close(availability) })
|
||||
}
|
||||
, function (availability) { $uibModalInstance.close(availability); });
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the modal UI to the next step
|
||||
*/
|
||||
$scope.next = function () {
|
||||
if ($scope.step === 1) { $scope.setNbTotalPlaces() }
|
||||
return $scope.step++
|
||||
}
|
||||
if ($scope.step === 1) { $scope.setNbTotalPlaces(); }
|
||||
return $scope.step++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the modal UI to the next step
|
||||
*/
|
||||
$scope.previous = function () { return $scope.step-- }
|
||||
$scope.previous = function () { return $scope.step--; };
|
||||
|
||||
/**
|
||||
* Callback to cancel the slot creation
|
||||
*/
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
|
||||
/**
|
||||
* 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
|
||||
return $scope.availability.nb_total_places = $scope.selectedTraining.nb_total_places;
|
||||
} else if ($scope.availability.available_type === 'space') {
|
||||
return $scope.availability.nb_total_places = $scope.selectedSpace.default_places
|
||||
return $scope.availability.nb_total_places = $scope.selectedSpace.default_places;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -489,58 +489,58 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.trainings.length > 0) {
|
||||
$scope.selectedTraining = $scope.trainings[0]
|
||||
$scope.selectedTraining = $scope.trainings[0];
|
||||
}
|
||||
if ($scope.spaces.length > 0) {
|
||||
$scope.selectedSpace = $scope.spaces[0]
|
||||
$scope.selectedSpace = $scope.spaces[0];
|
||||
}
|
||||
|
||||
Tag.query().$promise.then(function (data) { $scope.tags = data })
|
||||
Tag.query().$promise.then(function (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.
|
||||
$scope.$watch('availability.available_type', function (newValue, oldValue, scope) {
|
||||
if ((newValue === 'machines') || (newValue === 'space')) {
|
||||
$scope.endDateReadOnly = true
|
||||
const diff = moment($scope.end).diff($scope.start, 'hours') // the result is rounded down by moment.js
|
||||
$scope.end = moment($scope.start).add(diff, 'hours').toDate()
|
||||
return $scope.availability.end_at = $scope.end
|
||||
$scope.endDateReadOnly = true;
|
||||
const diff = moment($scope.end).diff($scope.start, 'hours'); // the result is rounded down by moment.js
|
||||
$scope.end = moment($scope.start).add(diff, 'hours').toDate();
|
||||
return $scope.availability.end_at = $scope.end;
|
||||
} else {
|
||||
return $scope.endDateReadOnly = false
|
||||
return $scope.endDateReadOnly = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// 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')) {
|
||||
end = moment($scope.end)
|
||||
end.add(moment(newValue).diff(oldValue), 'milliseconds')
|
||||
$scope.end = end.toDate()
|
||||
end = moment($scope.end);
|
||||
end.add(moment(newValue).diff(oldValue), 'milliseconds');
|
||||
$scope.end = end.toDate();
|
||||
} else { // for training availabilities
|
||||
// prevent the admin from setting the begining after the and
|
||||
if (moment(newValue).add(1, 'hour').isAfter($scope.end)) {
|
||||
$scope.start = oldValue
|
||||
$scope.start = oldValue;
|
||||
}
|
||||
}
|
||||
// update availability object
|
||||
return $scope.availability.start_at = $scope.start
|
||||
})
|
||||
return $scope.availability.start_at = $scope.start;
|
||||
});
|
||||
|
||||
// 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
|
||||
if (moment($scope.start).add(1, 'hour').isAfter(newValue)) {
|
||||
$scope.end = oldValue
|
||||
$scope.end = oldValue;
|
||||
}
|
||||
// update availability object
|
||||
return $scope.availability.end_at = $scope.end
|
||||
})
|
||||
}
|
||||
return $scope.availability.end_at = $scope.end;
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
// The validity per user defines how many time a user may ba able to use the same coupon
|
||||
// Here are the various options for this parameter
|
||||
const userValidities = ['once', 'forever']
|
||||
const userValidities = ['once', 'forever'];
|
||||
|
||||
/**
|
||||
* Controller used in the coupon creation page
|
||||
@ -24,10 +24,10 @@ Application.Controllers.controller('NewCouponController', ['$scope', '$state', '
|
||||
$scope.coupon = {
|
||||
active: true,
|
||||
type: 'percent_off'
|
||||
}
|
||||
};
|
||||
|
||||
// Options for the validity per user
|
||||
$scope.validities = userValidities
|
||||
$scope.validities = userValidities;
|
||||
|
||||
// Default parameters for AngularUI-Bootstrap datepicker (used for coupon validity limit selection)
|
||||
$scope.datePicker = {
|
||||
@ -37,17 +37,17 @@ Application.Controllers.controller('NewCouponController', ['$scope', '$state', '
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows/hides the validity limit datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to save the new coupon in $scope.coupon and redirect the user to the listing page
|
||||
@ -55,11 +55,11 @@ Application.Controllers.controller('NewCouponController', ['$scope', '$state', '
|
||||
return $scope.saveCoupon = () =>
|
||||
Coupon.save({ coupon: $scope.coupon }, coupon => $state.go('app.admin.pricing')
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_create_the_coupon_check_code_already_used'))
|
||||
return console.error(err)
|
||||
})
|
||||
growl.error(_t('unable_to_create_the_coupon_check_code_already_used'));
|
||||
return console.error(err);
|
||||
});
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the coupon edition page
|
||||
@ -69,16 +69,16 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Used in the form to freeze unmodifiable fields
|
||||
$scope.mode = 'EDIT'
|
||||
$scope.mode = 'EDIT';
|
||||
|
||||
// Coupon to edit
|
||||
$scope.coupon = couponPromise
|
||||
$scope.coupon = couponPromise;
|
||||
|
||||
// Options for the validity per user
|
||||
$scope.validities = userValidities
|
||||
$scope.validities = userValidities;
|
||||
|
||||
// Mapping for validation errors
|
||||
$scope.errors = {}
|
||||
$scope.errors = {};
|
||||
|
||||
// Default parameters for AngularUI-Bootstrap datepicker (used for coupon validity limit selection)
|
||||
$scope.datePicker = {
|
||||
@ -88,29 +88,29 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows/hides the validity limit datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to save the coupon's changes to the API
|
||||
*/
|
||||
$scope.updateCoupon = function () {
|
||||
$scope.errors = {}
|
||||
$scope.errors = {};
|
||||
return Coupon.update({ id: $scope.coupon.id }, { coupon: $scope.coupon }, coupon => $state.go('app.admin.pricing')
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_update_the_coupon_an_error_occurred'))
|
||||
return $scope.errors = err.data
|
||||
})
|
||||
}
|
||||
growl.error(_t('unable_to_update_the_coupon_an_error_occurred'));
|
||||
return $scope.errors = err.data;
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -120,11 +120,11 @@ Application.Controllers.controller('EditCouponController', ['$scope', '$state',
|
||||
const initialize = function () {
|
||||
// parse the date if any
|
||||
if (couponPromise.valid_until) {
|
||||
return $scope.coupon.valid_until = moment(couponPromise.valid_until).toDate()
|
||||
return $scope.coupon.valid_until = moment(couponPromise.valid_until).toDate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -11,7 +11,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
@ -47,7 +47,7 @@ class EventsController {
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
@ -57,19 +57,19 @@ class EventsController {
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
angular.forEach(content, function (v, k) {
|
||||
angular.forEach(v, function (err) { $scope.alerts.push({ msg: k + ': ' + err, type: 'danger' }) })
|
||||
})
|
||||
angular.forEach(v, function (err) { $scope.alerts.push({ msg: k + ': ' + err, type: 'danger' }); });
|
||||
});
|
||||
} else {
|
||||
$state.go('app.public.events_list')
|
||||
$state.go('app.public.events_list');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the user's view to the events list page
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.public.events_list') }
|
||||
$scope.cancel = function () { $state.go('app.public.events_list'); };
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -78,16 +78,16 @@ class EventsController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This will create a single new empty entry into the event's attachements list.
|
||||
*/
|
||||
$scope.addFile = function () { $scope.event.event_files_attributes.push({}) }
|
||||
$scope.addFile = function () { $scope.event.event_files_attributes.push({}); };
|
||||
|
||||
/**
|
||||
* This will remove the given file from the event's attachements list. If the file was previously uploaded
|
||||
@ -96,40 +96,40 @@ class EventsController {
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.event.event_files_attributes.indexOf(file)
|
||||
const index = $scope.event.event_files_attributes.indexOf(file);
|
||||
if (file.id != null) {
|
||||
return file._destroy = true
|
||||
return file._destroy = true;
|
||||
} else {
|
||||
return $scope.event.event_files_attributes.splice(index, 1)
|
||||
return $scope.event.event_files_attributes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.startOpened = !$scope.datePicker.startOpened;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
$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
|
||||
*/
|
||||
$scope.toggleRecurrenceEnd = function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
return $scope.datePicker.recurrenceEndOpened = !$scope.datePicker.recurrenceEndOpened
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return $scope.datePicker.recurrenceEndOpened = !$scope.datePicker.recurrenceEndOpened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize a new price item in the additional prices list
|
||||
@ -138,22 +138,22 @@ class EventsController {
|
||||
$scope.event.prices.push({
|
||||
category: null,
|
||||
amount: null
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the price or mark it as 'to delete'
|
||||
*/
|
||||
$scope.removePrice = function (price, event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (price.id) {
|
||||
price._destroy = true
|
||||
price._destroy = true;
|
||||
} else {
|
||||
const index = $scope.event.prices.indexOf(price)
|
||||
$scope.event.prices.splice(index, 1)
|
||||
const index = $scope.event.prices.indexOf(price);
|
||||
$scope.event.prices.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,47 +165,47 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// By default, the pagination mode is activated to limit the page size
|
||||
$scope.paginateActive = true
|
||||
$scope.paginateActive = true;
|
||||
|
||||
// The events displayed on the page
|
||||
$scope.events = eventsPromise
|
||||
$scope.events = eventsPromise;
|
||||
|
||||
// Current virtual page
|
||||
$scope.page = 1
|
||||
$scope.page = 1;
|
||||
|
||||
// Temporary datastore for creating new elements
|
||||
$scope.inserted = {
|
||||
category: null,
|
||||
theme: null,
|
||||
age_range: null
|
||||
}
|
||||
};
|
||||
|
||||
// List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
$scope.categories = categoriesPromise;
|
||||
|
||||
// List of events themes
|
||||
$scope.themes = themesPromise
|
||||
$scope.themes = themesPromise;
|
||||
|
||||
// List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
$scope.ageRanges = ageRangesPromise;
|
||||
|
||||
// List of price categories for the events
|
||||
$scope.priceCategories = priceCategoriesPromise
|
||||
$scope.priceCategories = priceCategoriesPromise;
|
||||
|
||||
// Default: we display all events (no restriction)
|
||||
$scope.eventsScope =
|
||||
{ selected: '' }
|
||||
{ selected: '' };
|
||||
|
||||
/**
|
||||
* Adds a bucket of events to the bottom of the page, grouped by month
|
||||
*/
|
||||
$scope.loadMoreEvents = function () {
|
||||
$scope.page += 1
|
||||
$scope.page += 1;
|
||||
return Event.query({ page: $scope.page, scope: $scope.eventsScope.selected }, function (data) {
|
||||
$scope.events = $scope.events.concat(data)
|
||||
return paginationCheck(data, $scope.events)
|
||||
})
|
||||
}
|
||||
$scope.events = $scope.events.concat(data);
|
||||
return paginationCheck(data, $scope.events);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves a new element / Update an existing one to the server (form validation callback)
|
||||
@ -215,11 +215,11 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.saveElement = function (model, data, id) {
|
||||
if (id != null) {
|
||||
return getModel(model)[0].update({ id }, data)
|
||||
return getModel(model)[0].update({ id }, data);
|
||||
} else {
|
||||
return getModel(model)[0].save(data, function (resp) { getModel(model)[1][getModel(model)[1].length - 1].id = resp.id })
|
||||
return getModel(model)[0].save(data, function (resp) { getModel(model)[1][getModel(model)[1].length - 1].id = resp.id; });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the element at the specified index
|
||||
@ -228,12 +228,12 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$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'))
|
||||
return false
|
||||
growl.error(_t('at_least_one_category_is_required') + ' ' + _t('unable_to_delete_the_last_one'));
|
||||
return false;
|
||||
}
|
||||
if (getModel(model)[1][index].related_to > 0) {
|
||||
growl.error(_t('unable_to_delete_ELEMENT_already_in_use_NUMBER_times', { ELEMENT: model, NUMBER: getModel(model)[1][index].related_to }, 'messageformat'))
|
||||
return false
|
||||
growl.error(_t('unable_to_delete_ELEMENT_already_in_use_NUMBER_times', { ELEMENT: model, NUMBER: getModel(model)[1][index].related_to }, 'messageformat'));
|
||||
return false;
|
||||
}
|
||||
return dialogs.confirm({
|
||||
resolve: {
|
||||
@ -241,15 +241,15 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_ELEMENT', { ELEMENT: model }, 'messageformat')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () { // delete confirmed
|
||||
getModel(model)[0].delete(getModel(model)[1][index], null, function () { getModel(model)[1].splice(index, 1) }
|
||||
, function () { growl.error(_t('unable_to_delete_an_error_occured')) })
|
||||
})
|
||||
}
|
||||
getModel(model)[0].delete(getModel(model)[1][index], null, function () { getModel(model)[1].splice(index, 1); }
|
||||
, function () { growl.error(_t('unable_to_delete_an_error_occured')); });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new empty entry in the $scope[model] array
|
||||
@ -259,9 +259,9 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
$scope.inserted[model] = {
|
||||
name: '',
|
||||
related_to: 0
|
||||
}
|
||||
return getModel(model)[1].push($scope.inserted[model])
|
||||
}
|
||||
};
|
||||
return getModel(model)[1].push($scope.inserted[model]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved element / Cancel the current element modification
|
||||
@ -271,11 +271,11 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.cancelElement = function (model, rowform, index) {
|
||||
if (getModel(model)[1][index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return getModel(model)[1].splice(index, 1)
|
||||
return getModel(model)[1].splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog allowing the definition of a new price category.
|
||||
@ -286,20 +286,20 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
templateUrl: '<%= asset_path "admin/events/price_form.html" %>',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
category () { return {} }
|
||||
category () { return {}; }
|
||||
},
|
||||
controller: 'PriceCategoryController' }).result['finally'](null).then(function (p_cat) {
|
||||
// save the price category to the API
|
||||
PriceCategory.save(p_cat, function (cat) {
|
||||
$scope.priceCategories.push(cat)
|
||||
return growl.success(_t('price_category_successfully_created'))
|
||||
$scope.priceCategories.push(cat);
|
||||
return growl.success(_t('price_category_successfully_created'));
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_add_the_price_category_check_name_already_used'))
|
||||
return console.error(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
growl.error(_t('unable_to_add_the_price_category_check_name_already_used'));
|
||||
return console.error(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Update the given price category with the new properties
|
||||
* to specify in a modal dialog
|
||||
@ -308,27 +308,27 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.editPriceCategory = function (id, index) {
|
||||
if ($scope.priceCategories[index].id !== id) {
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'))
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'));
|
||||
} else {
|
||||
return $uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/events/price_form.html" %>',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
category () { return $scope.priceCategories[index] }
|
||||
category () { return $scope.priceCategories[index]; }
|
||||
},
|
||||
controller: 'PriceCategoryController' }).result['finally'](null).then(function (p_cat) {
|
||||
// update the price category to the API
|
||||
PriceCategory.update({ id }, { price_category: p_cat }, function (cat) {
|
||||
$scope.priceCategories[index] = cat
|
||||
return growl.success(_t('price_category_successfully_updated'))
|
||||
$scope.priceCategories[index] = cat;
|
||||
return growl.success(_t('price_category_successfully_updated'));
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('unable_to_update_the_price_category'))
|
||||
return console.error(err)
|
||||
})
|
||||
})
|
||||
growl.error(_t('unable_to_update_the_price_category'));
|
||||
return console.error(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the given price category from the API
|
||||
@ -337,9 +337,9 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.removePriceCategory = function (id, index) {
|
||||
if ($scope.priceCategories[index].id !== id) {
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'))
|
||||
return growl.error(_t('unexpected_error_occurred_please_refresh'));
|
||||
} else if ($scope.priceCategories[index].events > 0) {
|
||||
return growl.error(_t('unable_to_delete_this_price_category_because_it_is_already_used'))
|
||||
return growl.error(_t('unable_to_delete_this_price_category_because_it_is_already_used'));
|
||||
} else {
|
||||
return dialogs.confirm(
|
||||
{
|
||||
@ -348,7 +348,7 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_price_category')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -356,15 +356,15 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
PriceCategory.remove(
|
||||
{ id },
|
||||
function () { // successfully deleted
|
||||
growl.success(_t('price_category_successfully_deleted'))
|
||||
$scope.priceCategories.splice(index, 1)
|
||||
growl.success(_t('price_category_successfully_deleted'));
|
||||
$scope.priceCategories.splice(index, 1);
|
||||
},
|
||||
function () { growl.error(_t('price_category_deletion_failed')) }
|
||||
)
|
||||
function () { growl.error(_t('price_category_deletion_failed')); }
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when the admin changes the events filter (all, passed, future).
|
||||
@ -372,18 +372,18 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.changeScope = function () {
|
||||
Event.query({ page: 1, scope: $scope.eventsScope.selected }, function (data) {
|
||||
$scope.events = data
|
||||
return paginationCheck(data, $scope.events)
|
||||
})
|
||||
return $scope.page = 1
|
||||
}
|
||||
$scope.events = data;
|
||||
return paginationCheck(data, $scope.events);
|
||||
});
|
||||
return $scope.page = 1;
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () { paginationCheck(eventsPromise, $scope.events) }
|
||||
const initialize = function () { paginationCheck(eventsPromise, $scope.events); };
|
||||
|
||||
/**
|
||||
* Check if all events are already displayed OR if the button 'load more events'
|
||||
@ -394,14 +394,14 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
var paginationCheck = function (lastEvents, events) {
|
||||
if (lastEvents.length > 0) {
|
||||
if (events.length >= lastEvents[0].nb_total_events) {
|
||||
return $scope.paginateActive = false
|
||||
return $scope.paginateActive = false;
|
||||
} else {
|
||||
return $scope.paginateActive = true
|
||||
return $scope.paginateActive = true;
|
||||
}
|
||||
} else {
|
||||
return $scope.paginateActive = false
|
||||
return $scope.paginateActive = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the model and the datastore matching the given name
|
||||
@ -410,54 +410,54 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
|
||||
*/
|
||||
var getModel = function (name) {
|
||||
switch (name) {
|
||||
case 'category': return [Category, $scope.categories]
|
||||
case 'theme': return [EventTheme, $scope.themes]
|
||||
case 'age_range': return [AgeRange, $scope.ageRanges]
|
||||
default: return [null, []]
|
||||
case 'category': return [Category, $scope.categories];
|
||||
case 'theme': return [EventTheme, $scope.themes];
|
||||
case 'age_range': return [AgeRange, $scope.ageRanges];
|
||||
default: return [null, []];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// init the controller (call at the end !)
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* 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
|
||||
$scope.event = eventPromise
|
||||
$scope.event = eventPromise;
|
||||
|
||||
// list of reservations for the current event
|
||||
return $scope.reservations = reservationsPromise
|
||||
}])
|
||||
return $scope.reservations = reservationsPromise;
|
||||
}]);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/events/'
|
||||
$scope.actionUrl = '/api/events/';
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
$scope.categories = categoriesPromise;
|
||||
|
||||
// List of events themes
|
||||
$scope.themes = themesPromise
|
||||
$scope.themes = themesPromise;
|
||||
|
||||
// List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
$scope.ageRanges = ageRangesPromise;
|
||||
|
||||
// List of availables price's categories
|
||||
$scope.priceCategories = priceCategoriesPromise
|
||||
$scope.priceCategories = priceCategoriesPromise;
|
||||
|
||||
// Default event parameters
|
||||
$scope.event = {
|
||||
@ -470,7 +470,7 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
|
||||
recurrence: 'none',
|
||||
category_id: null,
|
||||
prices: []
|
||||
}
|
||||
};
|
||||
|
||||
// Possible types of recurrences for an event
|
||||
$scope.recurrenceTypes = [
|
||||
@ -479,12 +479,12 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
|
||||
{ label: _t('every_week'), value: 'week' },
|
||||
{ label: _t('every_month'), value: 'month' },
|
||||
{ label: _t('every_year'), value: 'year' }
|
||||
]
|
||||
];
|
||||
|
||||
// Using the EventsController
|
||||
return new EventsController($scope, $state)
|
||||
return new EventsController($scope, $state);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the events edition page
|
||||
@ -494,25 +494,25 @@ Application.Controllers.controller('EditEventController', ['$scope', '$state', '
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/events/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/events/${$stateParams.id}`;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
$scope.method = 'put';
|
||||
|
||||
// Retrieve the event details, in case of error the user is redirected to the events listing
|
||||
$scope.event = eventPromise
|
||||
$scope.event = eventPromise;
|
||||
|
||||
// List of categories for the events
|
||||
$scope.categories = categoriesPromise
|
||||
$scope.categories = categoriesPromise;
|
||||
|
||||
// List of availables price's categories
|
||||
$scope.priceCategories = priceCategoriesPromise
|
||||
$scope.priceCategories = priceCategoriesPromise;
|
||||
|
||||
// List of events themes
|
||||
$scope.themes = themesPromise
|
||||
$scope.themes = themesPromise;
|
||||
|
||||
// List of age ranges
|
||||
$scope.ageRanges = ageRangesPromise
|
||||
$scope.ageRanges = ageRangesPromise;
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -520,17 +520,17 @@ Application.Controllers.controller('EditEventController', ['$scope', '$state', '
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// init the dates to JS objects
|
||||
$scope.event.start_date = moment($scope.event.start_date).toDate()
|
||||
$scope.event.end_date = moment($scope.event.end_date).toDate()
|
||||
$scope.event.start_date = moment($scope.event.start_date).toDate();
|
||||
$scope.event.end_date = moment($scope.event.end_date).toDate();
|
||||
|
||||
// Using the EventsController
|
||||
return new EventsController($scope, $state)
|
||||
}
|
||||
return new EventsController($scope, $state);
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -15,51 +15,51 @@
|
||||
* DS205: Consider reworking code to avoid use of IIFEs
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('GraphsController', ['$scope', '$state', '$rootScope', 'es', 'Statistics', '_t',
|
||||
function ($scope, $state, $rootScope, es, Statistics, _t) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// height of the HTML/SVG charts elements in pixels
|
||||
const CHART_HEIGHT = 500
|
||||
const CHART_HEIGHT = 500;
|
||||
|
||||
// Label of the charts' horizontal axes
|
||||
const X_AXIS_LABEL = _t('date')
|
||||
const X_AXIS_LABEL = _t('date');
|
||||
|
||||
// Label of the charts' vertical axes
|
||||
const Y_AXIS_LABEL = _t('number')
|
||||
const Y_AXIS_LABEL = _t('number');
|
||||
|
||||
// Colors for the line charts. Each new line uses the next color in this array
|
||||
const CHART_COLORS = ['#b35a94', '#1c5794', '#00b49e', '#6fac48', '#ebcf4a', '#fd7e33', '#ca3436', '#a26e3a']
|
||||
const CHART_COLORS = ['#b35a94', '#1c5794', '#00b49e', '#6fac48', '#ebcf4a', '#fd7e33', '#ca3436', '#a26e3a'];
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// ui-view transitions optimization: if true, the charts will never be refreshed
|
||||
$scope.preventRefresh = false
|
||||
$scope.preventRefresh = false;
|
||||
|
||||
// statistics structure in elasticSearch
|
||||
$scope.statistics = []
|
||||
$scope.statistics = [];
|
||||
|
||||
// statistics data recovered from elasticSearch
|
||||
$scope.data = null
|
||||
$scope.data = null;
|
||||
|
||||
// default interval: one day
|
||||
$scope.display =
|
||||
{ interval: 'week' }
|
||||
{ interval: 'week' };
|
||||
|
||||
// active tab will be set here
|
||||
$scope.selectedIndex = null
|
||||
$scope.selectedIndex = null;
|
||||
|
||||
// for palmares graphs, filters values are stored here
|
||||
$scope.ranking = {
|
||||
sortCriterion: 'ca',
|
||||
groupCriterion: 'subType'
|
||||
}
|
||||
};
|
||||
|
||||
// default: we do not open the datepicker menu
|
||||
$scope.datePicker =
|
||||
{ show: false }
|
||||
{ show: false };
|
||||
|
||||
// datePicker parameters for interval beginning
|
||||
$scope.datePickerStart = {
|
||||
@ -71,7 +71,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// datePicker parameters for interval ending
|
||||
$scope.datePickerEnd = {
|
||||
@ -83,19 +83,19 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval start)
|
||||
* @param {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleStartDatePicker = $event => toggleDatePicker($event, $scope.datePickerStart)
|
||||
$scope.toggleStartDatePicker = $event => toggleDatePicker($event, $scope.datePickerStart);
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval end)
|
||||
* @param {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleEndDatePicker = $event => toggleDatePicker($event, $scope.datePickerEnd)
|
||||
$scope.toggleEndDatePicker = $event => toggleDatePicker($event, $scope.datePickerEnd);
|
||||
|
||||
/**
|
||||
* Callback called when the active tab is changed.
|
||||
@ -103,23 +103,23 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
* @param tab {Object} elasticsearch statistic structure
|
||||
*/
|
||||
$scope.setActiveTab = function (tab) {
|
||||
$scope.selectedIndex = tab
|
||||
$scope.ranking.groupCriterion = 'subType'
|
||||
$scope.selectedIndex = tab;
|
||||
$scope.ranking.groupCriterion = 'subType';
|
||||
if (tab.ca) {
|
||||
$scope.ranking.sortCriterion = 'ca'
|
||||
$scope.ranking.sortCriterion = 'ca';
|
||||
} else {
|
||||
$scope.ranking.sortCriterion = tab.types[0].key
|
||||
$scope.ranking.sortCriterion = tab.types[0].key;
|
||||
}
|
||||
return refreshChart()
|
||||
}
|
||||
return refreshChart();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to close the date-picking popup and refresh the results
|
||||
*/
|
||||
$scope.validateDateChange = function () {
|
||||
$scope.datePicker.show = false
|
||||
return refreshChart()
|
||||
}
|
||||
$scope.datePicker.show = false;
|
||||
return refreshChart();
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -128,25 +128,25 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
*/
|
||||
const initialize = function () {
|
||||
Statistics.query(function (stats) {
|
||||
$scope.statistics = stats
|
||||
$scope.statistics = stats;
|
||||
// watch the interval changes to refresh the graph
|
||||
$scope.$watch(scope => scope.display.interval
|
||||
, (newValue, oldValue) => refreshChart())
|
||||
, (newValue, oldValue) => refreshChart());
|
||||
$scope.$watch(scope => scope.ranking.sortCriterion
|
||||
, (newValue, oldValue) => refreshChart())
|
||||
, (newValue, oldValue) => refreshChart());
|
||||
$scope.$watch(scope => scope.ranking.groupCriterion
|
||||
, (newValue, oldValue) => refreshChart())
|
||||
return refreshChart()
|
||||
})
|
||||
, (newValue, oldValue) => refreshChart());
|
||||
return refreshChart();
|
||||
});
|
||||
|
||||
// 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
|
||||
return $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
|
||||
if ((fromState.name === 'app.admin.stats_graphs') && (Object.keys(fromParams).length === 0)) {
|
||||
return $scope.preventRefresh = true
|
||||
return $scope.preventRefresh = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic function to toggle a bootstrap datePicker
|
||||
@ -154,10 +154,10 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
* @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
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return datePicker.opened = !datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Query elasticSearch according to the current parameters and update the chart
|
||||
@ -166,19 +166,19 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
if ($scope.selectedIndex && !$scope.preventRefresh) {
|
||||
return query($scope.selectedIndex, function (aggregations, error) {
|
||||
if (error) {
|
||||
return console.error(error)
|
||||
return console.error(error);
|
||||
} else {
|
||||
if ($scope.selectedIndex.graph.chart_type !== 'discreteBarChart') {
|
||||
$scope.data = formatAggregations(aggregations)
|
||||
return angular.forEach($scope.data, (datum, key) => updateChart($scope.selectedIndex.graph.chart_type, datum, key))
|
||||
$scope.data = formatAggregations(aggregations);
|
||||
return angular.forEach($scope.data, (datum, key) => updateChart($scope.selectedIndex.graph.chart_type, datum, key));
|
||||
} else {
|
||||
$scope.data = formatRankingAggregations(aggregations, $scope.selectedIndex.graph.limit, $scope.ranking.groupCriterion)
|
||||
return updateChart($scope.selectedIndex.graph.chart_type, $scope.data.ranking, $scope.selectedIndex.es_type_key)
|
||||
$scope.data = formatRankingAggregations(aggregations, $scope.selectedIndex.graph.limit, $scope.ranking.groupCriterion);
|
||||
return updateChart($scope.selectedIndex.graph.chart_type, $scope.data.ranking, $scope.selectedIndex.es_type_key);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used in NVD3 to print timestamps as literal dates on the X axis
|
||||
@ -187,45 +187,45 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
/* WARNING !! These tests (typeof/instanceof) may become broken on nvd3 update */
|
||||
if ($scope.display.interval === 'day') {
|
||||
if ((typeof d === 'number') || d instanceof Date) {
|
||||
return d3.time.format(Fablab.d3DateFormat)(moment(d).toDate())
|
||||
return d3.time.format(Fablab.d3DateFormat)(moment(d).toDate());
|
||||
} else { // typeof d == 'string'
|
||||
return d
|
||||
return d;
|
||||
}
|
||||
} else if ($scope.display.interval === 'week') {
|
||||
if ((typeof x === 'number') || d instanceof Date) {
|
||||
return d3.time.format(_t('week_short') + ' %U')(moment(d).toDate())
|
||||
return d3.time.format(_t('week_short') + ' %U')(moment(d).toDate());
|
||||
} else if (typeof d === 'number') {
|
||||
return _t('week_of_START_to_END', { START: moment(d).format('L'), END: moment(d).add(6, 'days').format('L') })
|
||||
return _t('week_of_START_to_END', { START: moment(d).format('L'), END: moment(d).add(6, 'days').format('L') });
|
||||
} else { // typeof d == 'string'
|
||||
return d
|
||||
return d;
|
||||
}
|
||||
} else if ($scope.display.interval === 'month') {
|
||||
if (typeof d === 'number') {
|
||||
const label = moment(d).format('MMMM YYYY')
|
||||
return label.substr(0, 1).toUpperCase() + label.substr(1).toLowerCase()
|
||||
const label = moment(d).format('MMMM YYYY');
|
||||
return label.substr(0, 1).toUpperCase() + label.substr(1).toLowerCase();
|
||||
} else { // typeof d == 'string'
|
||||
return d
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Format aggregations as retuned by elasticSearch to an understandable format for NVD3
|
||||
* @param aggs {Object} as returned by elasticsearch
|
||||
*/
|
||||
var formatAggregations = function (aggs) {
|
||||
const format = {}
|
||||
const format = {};
|
||||
|
||||
angular.forEach(aggs, function (type, type_key) { // go through aggs[$TYPE] where $TYPE = month|year|hour|booking|...
|
||||
format[type_key] = []
|
||||
format[type_key] = [];
|
||||
if (type.subgroups) {
|
||||
return angular.forEach(type.subgroups.buckets, subgroup => // go through aggs.$TYPE.subgroups.buckets where each bucket represent a $SUBTYPE
|
||||
angular.forEach($scope.selectedIndex.types, function (cur_type) { // in the mean time, go through the types of the current index (active tab) ...
|
||||
if (cur_type.key === type_key) { // ... looking for the type matching $TYPE
|
||||
return (() => {
|
||||
const result = []
|
||||
const result = [];
|
||||
for (let it_st = 0, end = cur_type.subtypes.length - 1; it_st <= end; it_st++) { // when we've found it, iterate over its subtypes ...
|
||||
const cur_subtype = cur_type.subtypes[it_st]
|
||||
const cur_subtype = cur_type.subtypes[it_st];
|
||||
if (subgroup.key === cur_subtype.key) { // ... which match $SUBTYPE
|
||||
// then we construct NVD3 dataSource according to these information
|
||||
var dataSource = {
|
||||
@ -234,31 +234,31 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
total: 0,
|
||||
color: CHART_COLORS[it_st],
|
||||
area: true
|
||||
}
|
||||
};
|
||||
// finally, we iterate over 'intervals' buckets witch contains
|
||||
// per date aggregations for our current dataSource
|
||||
angular.forEach(subgroup.intervals.buckets, function (interval) {
|
||||
dataSource.values.push({
|
||||
x: interval.key,
|
||||
y: interval.total.value
|
||||
})
|
||||
return dataSource.total += parseInt(interval.total.value)
|
||||
})
|
||||
dataSource.key += ` (${dataSource.total})`
|
||||
result.push(format[type_key].push(dataSource))
|
||||
});
|
||||
return dataSource.total += parseInt(interval.total.value);
|
||||
});
|
||||
dataSource.key += ` (${dataSource.total})`;
|
||||
result.push(format[type_key].push(dataSource));
|
||||
} else {
|
||||
result.push(undefined)
|
||||
result.push(undefined);
|
||||
}
|
||||
}
|
||||
return result
|
||||
})()
|
||||
return result;
|
||||
})();
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
return format
|
||||
}
|
||||
});
|
||||
return format;
|
||||
};
|
||||
|
||||
/**
|
||||
* Format aggregations for ranking charts to an understandable format for NVD3
|
||||
@ -268,31 +268,31 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
*/
|
||||
var formatRankingAggregations = function (aggs, limit, typeKey) {
|
||||
const format =
|
||||
{ ranking: [] }
|
||||
{ ranking: [] };
|
||||
|
||||
let it = 0
|
||||
let it = 0;
|
||||
while (it < aggs.subgroups.buckets.length) {
|
||||
const bucket = aggs.subgroups.buckets[it]
|
||||
const bucket = aggs.subgroups.buckets[it];
|
||||
const dataSource = {
|
||||
values: [],
|
||||
key: getRankingLabel(bucket.key, typeKey),
|
||||
color: CHART_COLORS[it],
|
||||
area: true
|
||||
}
|
||||
};
|
||||
dataSource.values.push({
|
||||
x: getRankingLabel(bucket.key, typeKey),
|
||||
y: bucket.total.value
|
||||
})
|
||||
format.ranking.push(dataSource)
|
||||
it++
|
||||
});
|
||||
format.ranking.push(dataSource);
|
||||
it++;
|
||||
}
|
||||
const getY = object => object.values[0].y
|
||||
format.ranking = stableSort(format.ranking, 'DESC', getY).slice(0, limit)
|
||||
const getY = object => object.values[0].y;
|
||||
format.ranking = stableSort(format.ranking, 'DESC', getY).slice(0, limit);
|
||||
for (let i = 0, end = format.ranking.length; i <= end; i++) {
|
||||
if (typeof format.ranking[i] === 'undefined') { format.ranking.splice(i, 1) }
|
||||
if (typeof format.ranking[i] === 'undefined') { format.ranking.splice(i, 1); }
|
||||
}
|
||||
return format
|
||||
}
|
||||
return format;
|
||||
};
|
||||
|
||||
/**
|
||||
* For BarCharts, return the label for a given bar
|
||||
@ -305,7 +305,7 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
for (let type of Array.from($scope.selectedIndex.types)) {
|
||||
for (let subtype of Array.from(type.subtypes)) {
|
||||
if (subtype.key === key) {
|
||||
return subtype.label
|
||||
return subtype.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -313,15 +313,15 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
for (let field of Array.from($scope.selectedIndex.additional_fields)) {
|
||||
if (field.key === typeKey) {
|
||||
switch (field.data_type) {
|
||||
case 'date': return moment(key).format('LL'); break
|
||||
case 'list': return key.name; break
|
||||
default: return key
|
||||
case 'date': return moment(key).format('LL'); break;
|
||||
case 'list': return key.name; break;
|
||||
default: return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare the elasticSearch query for the stats matching the current controller's parameters
|
||||
@ -333,57 +333,57 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
var query = function (index, callback) {
|
||||
// invalid callback handeling
|
||||
if (typeof (callback) !== 'function') {
|
||||
console.error('[graphsController::query] Error: invalid callback provided')
|
||||
return
|
||||
console.error('[graphsController::query] Error: invalid callback provided');
|
||||
return;
|
||||
}
|
||||
if (!index) {
|
||||
callback([], '[graphsController::query] Error: invalid index provided')
|
||||
return
|
||||
callback([], '[graphsController::query] Error: invalid index provided');
|
||||
return;
|
||||
}
|
||||
|
||||
if (index.graph.chart_type !== 'discreteBarChart') {
|
||||
// list statistics types
|
||||
const stat_types = []
|
||||
const stat_types = [];
|
||||
for (let t of Array.from(index.types)) {
|
||||
if (t.graph) {
|
||||
stat_types.push(t.key)
|
||||
stat_types.push(t.key);
|
||||
}
|
||||
}
|
||||
|
||||
// exception handeling
|
||||
if (stat_types.length === 0) {
|
||||
callback([], 'Error: Unable to retrieve any graphical statistic types in the provided index')
|
||||
callback([], 'Error: Unable to retrieve any graphical statistic types in the provided index');
|
||||
}
|
||||
|
||||
let type_it = 0
|
||||
const results = {}
|
||||
let error = ''
|
||||
let type_it = 0;
|
||||
const results = {};
|
||||
let error = '';
|
||||
var recursiveCb = function () {
|
||||
if (type_it < stat_types.length) {
|
||||
return queryElasticStats(index.es_type_key, stat_types[type_it], function (prevResults, prevError) {
|
||||
if (prevError) {
|
||||
console.error(`[graphsController::query] ${prevError}`)
|
||||
error += `\n${prevError}`
|
||||
console.error(`[graphsController::query] ${prevError}`);
|
||||
error += `\n${prevError}`;
|
||||
}
|
||||
results[stat_types[type_it]] = prevResults
|
||||
type_it++
|
||||
return recursiveCb()
|
||||
})
|
||||
results[stat_types[type_it]] = prevResults;
|
||||
type_it++;
|
||||
return recursiveCb();
|
||||
});
|
||||
} else {
|
||||
return callback(results)
|
||||
return callback(results);
|
||||
}
|
||||
}
|
||||
return recursiveCb()
|
||||
};
|
||||
return recursiveCb();
|
||||
} else { // palmares (ranking)
|
||||
return queryElasticRanking(index.es_type_key, $scope.ranking.groupCriterion, $scope.ranking.sortCriterion, function (results, error) {
|
||||
if (error) {
|
||||
return callback([], error)
|
||||
return callback([], error);
|
||||
} else {
|
||||
return callback(results)
|
||||
return callback(results);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the elasticSearch query to retreive the /stats/type aggregations
|
||||
@ -395,11 +395,11 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
var queryElasticStats = function (esType, statType, callback) {
|
||||
// handle invalid callback
|
||||
if (typeof (callback) !== 'function') {
|
||||
console.error('[graphsController::queryElasticStats] Error: invalid callback provided')
|
||||
return
|
||||
console.error('[graphsController::queryElasticStats] Error: invalid callback provided');
|
||||
return;
|
||||
}
|
||||
if (!esType || !statType) {
|
||||
callback([], '[graphsController::queryElasticStats] Error: invalid parameters provided')
|
||||
callback([], '[graphsController::queryElasticStats] Error: invalid parameters provided');
|
||||
}
|
||||
|
||||
// run query
|
||||
@ -416,12 +416,12 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
}
|
||||
, function (error, response) {
|
||||
if (error) {
|
||||
return callback([], `Error: something unexpected occurred during elasticSearch query: ${error}`)
|
||||
return callback([], `Error: something unexpected occurred during elasticSearch query: ${error}`);
|
||||
} else {
|
||||
return callback(response.aggregations)
|
||||
return callback(response.aggregations);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* For ranking displays, run the elasticSearch query to retreive the /stats/type aggregations
|
||||
@ -434,10 +434,10 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
var queryElasticRanking = function (esType, groupKey, sortKey, callback) {
|
||||
// handle invalid callback
|
||||
if (typeof (callback) !== 'function') {
|
||||
return console.error('[graphsController::queryElasticRanking] Error: invalid callback provided')
|
||||
return console.error('[graphsController::queryElasticRanking] Error: invalid callback provided');
|
||||
}
|
||||
if (!esType || !groupKey || !sortKey) {
|
||||
return callback([], '[graphsController::queryElasticRanking] Error: invalid parameters provided')
|
||||
return callback([], '[graphsController::queryElasticRanking] Error: invalid parameters provided');
|
||||
}
|
||||
|
||||
// run query
|
||||
@ -450,18 +450,18 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
}
|
||||
, function (error, response) {
|
||||
if (error) {
|
||||
return callback([], `Error: something unexpected occurred during elasticSearch query: ${error}`)
|
||||
return callback([], `Error: something unexpected occurred during elasticSearch query: ${error}`);
|
||||
} else {
|
||||
return callback(response.aggregations)
|
||||
return callback(response.aggregations);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a final elastic results bucket and return a D3 compatible object
|
||||
* @param bucket {{key_as_string:{String}, key:{Number}, doc_count:{Number}, total:{{value:{Number}}}}} interval bucket
|
||||
*/
|
||||
const parseElasticBucket = bucket => [ bucket.key, bucket.total.value ]
|
||||
const parseElasticBucket = bucket => [ bucket.key, bucket.total.value ];
|
||||
|
||||
/**
|
||||
* Build an object representing the content of the REST-JSON query to elasticSearch, based on the parameters
|
||||
@ -519,18 +519,18 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// scale weeks on sunday as nvd3 supports only these weeks
|
||||
if (interval === 'week') {
|
||||
q.aggregations.subgroups.aggregations.intervals.date_histogram['offset'] = '-1d'
|
||||
q.aggregations.subgroups.aggregations.intervals.date_histogram['offset'] = '-1d';
|
||||
// scale days to UTC time
|
||||
} else if (interval === 'day') {
|
||||
const offset = moment().utcOffset()
|
||||
q.aggregations.subgroups.aggregations.intervals.date_histogram['offset'] = (-offset) + 'm'
|
||||
const offset = moment().utcOffset();
|
||||
q.aggregations.subgroups.aggregations.intervals.date_histogram['offset'] = (-offset) + 'm';
|
||||
}
|
||||
return q
|
||||
}
|
||||
return q;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build an object representing the content of the REST-JSON query to elasticSearch, based on the parameters
|
||||
@ -587,21 +587,21 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// results must be sorted and limited later by angular
|
||||
if (sortKey !== 'ca') {
|
||||
angular.forEach(q.query.bool.must, function (must) {
|
||||
if (must.term) {
|
||||
return must.term.type = sortKey
|
||||
return must.term.type = sortKey;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
q.aggregations.subgroups.aggregations.total.sum.field = sortKey
|
||||
q.aggregations.subgroups.aggregations.total.sum.field = sortKey;
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
return q;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redraw the NDV3 chart using the provided data
|
||||
@ -610,76 +610,76 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
* @param type {String} which chart to update (statistic type key)
|
||||
*/
|
||||
var updateChart = function (chart_type, data, type) {
|
||||
const id = `#chart-${type} svg`
|
||||
const id = `#chart-${type} svg`;
|
||||
|
||||
// clean old charts
|
||||
d3.selectAll(id + ' > *').remove()
|
||||
d3.selectAll(id + ' > *').remove();
|
||||
|
||||
return nv.addGraph(function () {
|
||||
// no data or many dates, display line charts
|
||||
let chart
|
||||
let chart;
|
||||
if ((data.length === 0) || ((data[0].values.length > 1) && (chart_type !== 'discreteBarChart'))) {
|
||||
if (chart_type === 'stackedAreaChart') {
|
||||
chart = nv.models.stackedAreaChart().useInteractiveGuideline(true)
|
||||
chart = nv.models.stackedAreaChart().useInteractiveGuideline(true);
|
||||
} else {
|
||||
chart = nv.models.lineChart().useInteractiveGuideline(true)
|
||||
chart = nv.models.lineChart().useInteractiveGuideline(true);
|
||||
}
|
||||
|
||||
if (data.length > 0) {
|
||||
if ($scope.display.interval === 'day') {
|
||||
setTimeScale(chart.xAxis, chart.xScale, [d3.time.day, data[0].values.length])
|
||||
setTimeScale(chart.xAxis, chart.xScale, [d3.time.day, data[0].values.length]);
|
||||
} else if ($scope.display.interval === 'week') {
|
||||
setTimeScale(chart.xAxis, chart.xScale, [d3.time.week, data[0].values.length])
|
||||
setTimeScale(chart.xAxis, chart.xScale, [d3.time.week, data[0].values.length]);
|
||||
} else if ($scope.display.interval === 'month') {
|
||||
setTimeScale(chart.xAxis, chart.xScale, [d3.time.month, data[0].values.length])
|
||||
setTimeScale(chart.xAxis, chart.xScale, [d3.time.month, data[0].values.length]);
|
||||
}
|
||||
}
|
||||
|
||||
chart.xAxis.tickFormat(xAxisTickFormatFunction)
|
||||
chart.yAxis.tickFormat(d3.format('d'))
|
||||
chart.xAxis.tickFormat(xAxisTickFormatFunction);
|
||||
chart.yAxis.tickFormat(d3.format('d'));
|
||||
|
||||
chart.xAxis.axisLabel(X_AXIS_LABEL)
|
||||
chart.yAxis.axisLabel(Y_AXIS_LABEL)
|
||||
chart.xAxis.axisLabel(X_AXIS_LABEL);
|
||||
chart.yAxis.axisLabel(Y_AXIS_LABEL);
|
||||
|
||||
// only one date, display histograms
|
||||
} else {
|
||||
chart = nv.models.discreteBarChart()
|
||||
chart.tooltip.enabled(false)
|
||||
chart.showValues(true)
|
||||
chart.x(d => d.label)
|
||||
chart.y(d => d.value)
|
||||
data = prepareDataForBarChart(data, type)
|
||||
chart = nv.models.discreteBarChart();
|
||||
chart.tooltip.enabled(false);
|
||||
chart.showValues(true);
|
||||
chart.x(d => d.label);
|
||||
chart.y(d => d.value);
|
||||
data = prepareDataForBarChart(data, type);
|
||||
}
|
||||
|
||||
// common for each charts
|
||||
chart.margin({ left: 100, right: 100 })
|
||||
chart.noData(_t('no_data_for_this_period'))
|
||||
chart.height(CHART_HEIGHT)
|
||||
chart.margin({ left: 100, right: 100 });
|
||||
chart.noData(_t('no_data_for_this_period'));
|
||||
chart.height(CHART_HEIGHT);
|
||||
|
||||
// add new chart to the page
|
||||
d3.select(id).datum(data).transition().duration(350).call(chart)
|
||||
d3.select(id).datum(data).transition().duration(350).call(chart);
|
||||
|
||||
// resize the graph when the page is resized
|
||||
nv.utils.windowResize(chart.update)
|
||||
nv.utils.windowResize(chart.update);
|
||||
// return the chart
|
||||
return chart
|
||||
})
|
||||
}
|
||||
return chart;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an NVD3 line chart axis, scale it to display ordinated dates, according to the given arguments
|
||||
*/
|
||||
var setTimeScale = function (nvd3Axis, nvd3Scale, argsArray) {
|
||||
const scale = d3.time.scale()
|
||||
const scale = d3.time.scale();
|
||||
|
||||
nvd3Axis.scale(scale)
|
||||
nvd3Scale(scale)
|
||||
nvd3Axis.scale(scale);
|
||||
nvd3Scale(scale);
|
||||
|
||||
if (!argsArray && !argsArray.length) {
|
||||
const oldTicks = nvd3Axis.axis.ticks
|
||||
return nvd3Axis.axis.ticks = () => oldTicks.apply(nvd3Axis.axis, argsArray)
|
||||
const oldTicks = nvd3Axis.axis.ticks;
|
||||
return nvd3Axis.axis.ticks = () => oldTicks.apply(nvd3Axis.axis, argsArray);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate line chart data in dates row to bar chart data, one bar per type.
|
||||
@ -689,19 +689,19 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
key: type,
|
||||
values: []
|
||||
}
|
||||
]
|
||||
];
|
||||
for (let info of Array.from(data)) {
|
||||
if (info) {
|
||||
newData[0].values.push({
|
||||
'label': info.key,
|
||||
'value': info.values[0].y,
|
||||
'color': info.color
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return newData
|
||||
}
|
||||
return newData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort the provided array, in the specified order, on the value returned by the callback.
|
||||
@ -714,37 +714,37 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro
|
||||
*/
|
||||
var stableSort = function (array, order, getValue) {
|
||||
// prepare sorting
|
||||
const keys_order = []
|
||||
const result = []
|
||||
const keys_order = [];
|
||||
const result = [];
|
||||
for (let i = 0, end = array.length; i <= end; i++) {
|
||||
keys_order[array[i]] = i
|
||||
result.push(array[i])
|
||||
keys_order[array[i]] = i;
|
||||
result.push(array[i]);
|
||||
}
|
||||
|
||||
// callback for javascript native Array.sort()
|
||||
const sort_fc = function (a, b) {
|
||||
const val_a = getValue(a)
|
||||
const val_b = getValue(b)
|
||||
const val_a = getValue(a);
|
||||
const val_b = getValue(b);
|
||||
if (val_a === val_b) {
|
||||
return keys_order[a] - keys_order[b]
|
||||
return keys_order[a] - keys_order[b];
|
||||
}
|
||||
if (val_a < val_b) {
|
||||
if (order === 'ASC') {
|
||||
return -1
|
||||
} else { return 1 }
|
||||
return -1;
|
||||
} else { return 1; }
|
||||
} else {
|
||||
if (order === 'ASC') {
|
||||
return 1
|
||||
} else { return -1 }
|
||||
return 1;
|
||||
} else { return -1; }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// finish the sort
|
||||
result.sort(sort_fc)
|
||||
return result
|
||||
}
|
||||
result.sort(sort_fc);
|
||||
return result;
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -13,17 +13,17 @@
|
||||
*/
|
||||
Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise', 'Group', 'growl', '_t', function ($scope, groupsPromise, Group, growl, _t) {
|
||||
// List of users groups
|
||||
$scope.groups = groupsPromise
|
||||
$scope.groups = groupsPromise;
|
||||
|
||||
// Default: we show only enabled groups
|
||||
$scope.groupFiltering = 'enabled'
|
||||
$scope.groupFiltering = 'enabled';
|
||||
|
||||
// Available options for filtering groups by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved group / Cancel the current group modification
|
||||
@ -32,20 +32,20 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
|
||||
*/
|
||||
$scope.cancelGroup = function (rowform, index) {
|
||||
if ($scope.groups[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.groups.splice(index, 1)
|
||||
return $scope.groups.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new empty entry in the $scope.groups array
|
||||
*/
|
||||
$scope.addGroup = function () {
|
||||
$scope.inserted =
|
||||
{ name: '' }
|
||||
return $scope.groups.push($scope.inserted)
|
||||
}
|
||||
{ name: '' };
|
||||
return $scope.groups.push($scope.inserted);
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves a new group / Update an existing group to the server (form validation callback)
|
||||
@ -55,18 +55,18 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
|
||||
$scope.saveGroup = function (data, id) {
|
||||
if (id != null) {
|
||||
return Group.update({ id }, { group: data }, response => growl.success(_t('group_form.changes_successfully_saved'))
|
||||
, error => growl.error(_t('group_form.an_error_occurred_while_saving_changes')))
|
||||
, error => growl.error(_t('group_form.an_error_occurred_while_saving_changes')));
|
||||
} else {
|
||||
return Group.save({ group: data }, function (resp) {
|
||||
growl.success(_t('group_form.new_group_successfully_saved'))
|
||||
return $scope.groups[$scope.groups.length - 1].id = resp.id
|
||||
growl.success(_t('group_form.new_group_successfully_saved'));
|
||||
return $scope.groups[$scope.groups.length - 1].id = resp.id;
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('.group_forman_error_occurred_when_saving_the_new_group'))
|
||||
return $scope.groups.splice($scope.groups.length - 1, 1)
|
||||
})
|
||||
growl.error(_t('.group_forman_error_occurred_when_saving_the_new_group'));
|
||||
return $scope.groups.splice($scope.groups.length - 1, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the group at the specified index
|
||||
@ -74,27 +74,27 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise
|
||||
*/
|
||||
$scope.removeGroup = index =>
|
||||
Group.delete({ id: $scope.groups[index].id }, function (resp) {
|
||||
growl.success(_t('group_form.group_successfully_deleted'))
|
||||
return $scope.groups.splice(index, 1)
|
||||
growl.success(_t('group_form.group_successfully_deleted'));
|
||||
return $scope.groups.splice(index, 1);
|
||||
}
|
||||
, error => growl.error(_t('group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it')))
|
||||
, error => growl.error(_t('group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it')));
|
||||
|
||||
/**
|
||||
* Enable/disable the group at the specified index
|
||||
* @param index {number} group index in the $scope.groups array
|
||||
*/
|
||||
return $scope.toggleDisableGroup = function (index) {
|
||||
const group = $scope.groups[index]
|
||||
const group = $scope.groups[index];
|
||||
if (!group.disabled && (group.users > 0)) {
|
||||
return growl.error(_t('group_form.unable_to_disable_group_with_users', { USERS: group.users }, 'messageformat'))
|
||||
return growl.error(_t('group_form.unable_to_disable_group_with_users', { USERS: group.users }, 'messageformat'));
|
||||
} else {
|
||||
return Group.update({ id: group.id }, { group: { disabled: !group.disabled } }, function (response) {
|
||||
$scope.groups[index] = response
|
||||
return growl.success(_t('group_form.group_successfully_enabled_disabled', { STATUS: response.disabled }, 'messageformat'))
|
||||
$scope.groups[index] = response;
|
||||
return growl.success(_t('group_form.group_successfully_enabled_disabled', { STATUS: response.disabled }, 'messageformat'));
|
||||
}
|
||||
, error => growl.error(_t('group_form.unable_to_enable_disable_group', { STATUS: !group.disabled }, 'messageformat')))
|
||||
, error => growl.error(_t('group_form.unable_to_enable_disable_group', { STATUS: !group.disabled }, 'messageformat')));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -12,7 +12,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in the admin invoices listing page
|
||||
@ -22,28 +22,28 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// number of invoices loaded each time we click on 'load more...'
|
||||
const INVOICES_PER_PAGE = 20
|
||||
const INVOICES_PER_PAGE = 20;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// List of all users invoices
|
||||
$scope.invoices = invoices
|
||||
$scope.invoices = invoices;
|
||||
|
||||
// Invoices filters
|
||||
$scope.searchInvoice = {
|
||||
date: null,
|
||||
name: '',
|
||||
reference: ''
|
||||
}
|
||||
};
|
||||
|
||||
// currently displayed page of invoices (search results)
|
||||
$scope.page = 1
|
||||
$scope.page = 1;
|
||||
|
||||
// true when all invoices are loaded
|
||||
$scope.noMoreResults = false
|
||||
$scope.noMoreResults = false;
|
||||
|
||||
// Default invoices ordering/sorting
|
||||
$scope.orderInvoice = '-reference'
|
||||
$scope.orderInvoice = '-reference';
|
||||
|
||||
// Invoices parameters
|
||||
$scope.invoice = {
|
||||
@ -74,16 +74,16 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
legals: {
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Placeholding date for the invoice creation
|
||||
$scope.today = moment()
|
||||
$scope.today = moment();
|
||||
|
||||
// Placeholding date for the reservation begin
|
||||
$scope.inOneWeek = moment().add(1, 'week').startOf('hour')
|
||||
$scope.inOneWeek = moment().add(1, 'week').startOf('hour');
|
||||
|
||||
// Placeholding date for the reservation end
|
||||
$scope.inOneWeekAndOneHour = moment().add(1, 'week').add(1, 'hour').startOf('hour')
|
||||
$scope.inOneWeekAndOneHour = moment().add(1, 'week').add(1, 'hour').startOf('hour');
|
||||
|
||||
/**
|
||||
* Change the invoices ordering criterion to the one provided
|
||||
@ -91,14 +91,14 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
*/
|
||||
$scope.setOrderInvoice = function (orderBy) {
|
||||
if ($scope.orderInvoice === orderBy) {
|
||||
$scope.orderInvoice = `-${orderBy}`
|
||||
$scope.orderInvoice = `-${orderBy}`;
|
||||
} else {
|
||||
$scope.orderInvoice = orderBy
|
||||
$scope.orderInvoice = orderBy;
|
||||
}
|
||||
|
||||
resetSearchInvoice()
|
||||
return invoiceSearch()
|
||||
}
|
||||
resetSearchInvoice();
|
||||
return invoiceSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal window asking the admin the details to refund the user about the provided invoice
|
||||
@ -110,65 +110,65 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
templateUrl: '<%= asset_path "admin/invoices/avoirModal.html" %>',
|
||||
controller: 'AvoirModalController',
|
||||
resolve: {
|
||||
invoice () { return invoice }
|
||||
invoice () { return invoice; }
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// once done, update the invoice model and inform the admin
|
||||
return modalInstance.result.then(function (res) {
|
||||
$scope.invoices.unshift(res.avoir)
|
||||
$scope.invoices.unshift(res.avoir);
|
||||
return Invoice.get({ id: invoice.id }, function (data) {
|
||||
invoice.has_avoir = data.has_avoir
|
||||
return growl.success(_t('refund_invoice_successfully_created'))
|
||||
})
|
||||
})
|
||||
}
|
||||
invoice.has_avoir = data.has_avoir;
|
||||
return growl.success(_t('refund_invoice_successfully_created'));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an invoice reference sample from the parametrized model
|
||||
* @returns {string} invoice reference sample
|
||||
*/
|
||||
$scope.mkReference = function () {
|
||||
let sample = $scope.invoice.reference.model
|
||||
let sample = $scope.invoice.reference.model;
|
||||
if (sample) {
|
||||
// invoice number per day (dd..dd)
|
||||
sample = sample.replace(/d+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(2, match.length) })
|
||||
sample = sample.replace(/d+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(2, match.length); });
|
||||
// invoice number per month (mm..mm)
|
||||
sample = sample.replace(/m+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(12, match.length) })
|
||||
sample = sample.replace(/m+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(12, match.length); });
|
||||
// invoice number per year (yy..yy)
|
||||
sample = sample.replace(/y+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(8, match.length) })
|
||||
sample = sample.replace(/y+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(8, match.length); });
|
||||
// date information
|
||||
sample = sample.replace(/[YMD]+(?![^\[]*])/g, function (match, offset, string) { return $scope.today.format(match) })
|
||||
sample = sample.replace(/[YMD]+(?![^\[]*])/g, function (match, offset, string) { return $scope.today.format(match); });
|
||||
// information about online selling (X[text])
|
||||
sample = sample.replace(/X\[([^\]]+)\]/g, function (match, p1, offset, string) { return p1 })
|
||||
sample = sample.replace(/X\[([^\]]+)\]/g, function (match, p1, offset, string) { return p1; });
|
||||
// information about wallet (W[text]) - does not apply here
|
||||
sample = sample.replace(/W\[([^\]]+)\]/g, '')
|
||||
sample = sample.replace(/W\[([^\]]+)\]/g, '');
|
||||
// information about refunds (R[text]) - does not apply here
|
||||
sample = sample.replace(/R\[([^\]]+)\]/g, '')
|
||||
sample = sample.replace(/R\[([^\]]+)\]/g, '');
|
||||
}
|
||||
return sample
|
||||
}
|
||||
return sample;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an order nmuber sample from the parametrized model
|
||||
* @returns {string} invoice reference sample
|
||||
*/
|
||||
$scope.mkNumber = function () {
|
||||
let sample = $scope.invoice.number.model
|
||||
let sample = $scope.invoice.number.model;
|
||||
if (sample) {
|
||||
// global order number (nn..nn)
|
||||
sample = sample.replace(/n+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(327, match.length) })
|
||||
sample = sample.replace(/n+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(327, match.length); });
|
||||
// order number per year (yy..yy)
|
||||
sample = sample.replace(/y+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(8, match.length) })
|
||||
sample = sample.replace(/y+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(8, match.length); });
|
||||
// order number per month (mm..mm)
|
||||
sample = sample.replace(/m+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(12, match.length) })
|
||||
sample = sample.replace(/m+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(12, match.length); });
|
||||
// order number per day (dd..dd)
|
||||
sample = sample.replace(/d+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(2, match.length) })
|
||||
sample = sample.replace(/d+(?![^\[]*])/g, function (match, offset, string) { return padWithZeros(2, match.length); });
|
||||
// date information
|
||||
sample = sample.replace(/[YMD]+(?![^\[]*])/g, function (match, offset, string) { return $scope.today.format(match) })
|
||||
sample = sample.replace(/[YMD]+(?![^\[]*])/g, function (match, offset, string) { return $scope.today.format(match); });
|
||||
}
|
||||
return sample
|
||||
}
|
||||
return sample;
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the invoice reference generation template
|
||||
@ -180,27 +180,27 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
size: 'lg',
|
||||
resolve: {
|
||||
model () {
|
||||
return $scope.invoice.reference.model
|
||||
return $scope.invoice.reference.model;
|
||||
}
|
||||
},
|
||||
controller ($scope, $uibModalInstance, model) {
|
||||
$scope.model = model
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.model) }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.model = model;
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.model); };
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
modalInstance.result.then(function (model) {
|
||||
Setting.update({ name: 'invoice_reference' }, { value: model }, function (data) {
|
||||
$scope.invoice.reference.model = model
|
||||
growl.success(_t('invoice_reference_successfully_saved'))
|
||||
$scope.invoice.reference.model = model;
|
||||
growl.success(_t('invoice_reference_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_invoice_reference'))
|
||||
console.error(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
growl.error(_t('an_error_occurred_while_saving_invoice_reference'));
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the invoice code
|
||||
@ -212,47 +212,47 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
size: 'lg',
|
||||
resolve: {
|
||||
model () {
|
||||
return $scope.invoice.code.model
|
||||
return $scope.invoice.code.model;
|
||||
},
|
||||
active () {
|
||||
return $scope.invoice.code.active
|
||||
return $scope.invoice.code.active;
|
||||
}
|
||||
},
|
||||
controller ($scope, $uibModalInstance, model, active) {
|
||||
$scope.codeModel = model
|
||||
$scope.isSelected = active
|
||||
$scope.codeModel = model;
|
||||
$scope.isSelected = active;
|
||||
|
||||
$scope.ok = function () { $uibModalInstance.close({ model: $scope.codeModel, active: $scope.isSelected }) }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.ok = function () { $uibModalInstance.close({ model: $scope.codeModel, active: $scope.isSelected }); };
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return modalInstance.result.then(function (result) {
|
||||
Setting.update({ name: 'invoice_code-value' }, { value: result.model }, function (data) {
|
||||
$scope.invoice.code.model = result.model
|
||||
$scope.invoice.code.model = result.model;
|
||||
if (result.active) {
|
||||
return growl.success(_t('invoicing_code_succesfully_saved'))
|
||||
return growl.success(_t('invoicing_code_succesfully_saved'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_invoicing_code'))
|
||||
return console.error(error)
|
||||
})
|
||||
growl.error(_t('an_error_occurred_while_saving_the_invoicing_code'));
|
||||
return console.error(error);
|
||||
});
|
||||
|
||||
return Setting.update({ name: 'invoice_code-active' }, { value: result.active ? 'true' : 'false' }, function (data) {
|
||||
$scope.invoice.code.active = result.active
|
||||
$scope.invoice.code.active = result.active;
|
||||
if (result.active) {
|
||||
return growl.success(_t('code_successfully_activated'))
|
||||
return growl.success(_t('code_successfully_activated'));
|
||||
} else {
|
||||
return growl.success(_t('code_successfully_disabled'))
|
||||
return growl.success(_t('code_successfully_disabled'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_activating_the_invoicing_code'))
|
||||
return console.error(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
growl.error(_t('an_error_occurred_while_activating_the_invoicing_code'));
|
||||
return console.error(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the invoice number
|
||||
@ -264,27 +264,27 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
size: 'lg',
|
||||
resolve: {
|
||||
model () {
|
||||
return $scope.invoice.number.model
|
||||
return $scope.invoice.number.model;
|
||||
}
|
||||
},
|
||||
controller ($scope, $uibModalInstance, model) {
|
||||
$scope.model = model
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.model) }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.model = model;
|
||||
$scope.ok = function () { $uibModalInstance.close($scope.model); };
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return modalInstance.result.then(function (model) {
|
||||
Setting.update({ name: 'invoice_order-nb' }, { value: model }, function (data) {
|
||||
$scope.invoice.number.model = model
|
||||
return growl.success(_t('order_number_successfully_saved'))
|
||||
$scope.invoice.number.model = model;
|
||||
return growl.success(_t('order_number_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_order_number'))
|
||||
return console.error(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
growl.error(_t('an_error_occurred_while_saving_the_order_number'));
|
||||
return console.error(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog allowing the user to edit the VAT parameters for the invoices
|
||||
@ -297,95 +297,95 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
size: 'lg',
|
||||
resolve: {
|
||||
rate () {
|
||||
return $scope.invoice.VAT.rate
|
||||
return $scope.invoice.VAT.rate;
|
||||
},
|
||||
active () {
|
||||
return $scope.invoice.VAT.active
|
||||
return $scope.invoice.VAT.active;
|
||||
}
|
||||
},
|
||||
controller ($scope, $uibModalInstance, rate, active) {
|
||||
$scope.rate = rate
|
||||
$scope.isSelected = active
|
||||
$scope.rate = rate;
|
||||
$scope.isSelected = active;
|
||||
|
||||
$scope.ok = function () { $uibModalInstance.close({ rate: $scope.rate, active: $scope.isSelected }) }
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.ok = function () { $uibModalInstance.close({ rate: $scope.rate, active: $scope.isSelected }); };
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return modalInstance.result.then(function (result) {
|
||||
Setting.update({ name: 'invoice_VAT-rate' }, { value: result.rate + '' }, function (data) {
|
||||
$scope.invoice.VAT.rate = result.rate
|
||||
$scope.invoice.VAT.rate = result.rate;
|
||||
if (result.active) {
|
||||
return growl.success(_t('VAT_rate_successfully_saved'))
|
||||
return growl.success(_t('VAT_rate_successfully_saved'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_VAT_rate'))
|
||||
return console.error(error)
|
||||
})
|
||||
growl.error(_t('an_error_occurred_while_saving_the_VAT_rate'));
|
||||
return console.error(error);
|
||||
});
|
||||
|
||||
return Setting.update({ name: 'invoice_VAT-active' }, { value: result.active ? 'true' : 'false' }, function (data) {
|
||||
$scope.invoice.VAT.active = result.active
|
||||
$scope.invoice.VAT.active = result.active;
|
||||
if (result.active) {
|
||||
return growl.success(_t('VAT_successfully_activated'))
|
||||
return growl.success(_t('VAT_successfully_activated'));
|
||||
} else {
|
||||
return growl.success(_t('VAT_successfully_disabled'))
|
||||
return growl.success(_t('VAT_successfully_disabled'));
|
||||
}
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_activating_the_VAT'))
|
||||
return console.error(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
growl.error(_t('an_error_occurred_while_activating_the_VAT'));
|
||||
return console.error(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to save the value of the text zone when editing is done
|
||||
*/
|
||||
$scope.textEditEnd = function (event) {
|
||||
const parsed = parseHtml($scope.invoice.text.content)
|
||||
const parsed = parseHtml($scope.invoice.text.content);
|
||||
return Setting.update({ name: 'invoice_text' }, { value: parsed }, function (data) {
|
||||
$scope.invoice.text.content = parsed
|
||||
return growl.success(_t('text_successfully_saved'))
|
||||
$scope.invoice.text.content = parsed;
|
||||
return growl.success(_t('text_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_text'))
|
||||
return console.error(error)
|
||||
})
|
||||
}
|
||||
growl.error(_t('an_error_occurred_while_saving_the_text'));
|
||||
return console.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
const parsed = parseHtml($scope.invoice.legals.content);
|
||||
return Setting.update({ name: 'invoice_legals' }, { value: parsed }, function (data) {
|
||||
$scope.invoice.legals.content = parsed
|
||||
return growl.success(_t('address_and_legal_information_successfully_saved'))
|
||||
$scope.invoice.legals.content = parsed;
|
||||
return growl.success(_t('address_and_legal_information_successfully_saved'));
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_address_and_the_legal_information'))
|
||||
return console.error(error)
|
||||
})
|
||||
}
|
||||
growl.error(_t('an_error_occurred_while_saving_the_address_and_the_legal_information'));
|
||||
return console.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback when any of the filters changes.
|
||||
* Full reload the results list
|
||||
*/
|
||||
$scope.handleFilterChange = function () {
|
||||
resetSearchInvoice()
|
||||
return invoiceSearch()
|
||||
}
|
||||
resetSearchInvoice();
|
||||
return invoiceSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
$scope.page += 1;
|
||||
return invoiceSearch(true);
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -394,23 +394,23 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
*/
|
||||
const initialize = function () {
|
||||
if (!invoices[0] || (invoices[0].maxInvoices <= $scope.invoices.length)) {
|
||||
$scope.noMoreResults = true
|
||||
$scope.noMoreResults = true;
|
||||
}
|
||||
|
||||
// retrieve settings from the DB through the API
|
||||
$scope.invoice.legals.content = settings['invoice_legals']
|
||||
$scope.invoice.text.content = settings['invoice_text']
|
||||
$scope.invoice.VAT.rate = parseFloat(settings['invoice_VAT-rate'])
|
||||
$scope.invoice.VAT.active = (settings['invoice_VAT-active'] === 'true')
|
||||
$scope.invoice.number.model = settings['invoice_order-nb']
|
||||
$scope.invoice.code.model = settings['invoice_code-value']
|
||||
$scope.invoice.code.active = (settings['invoice_code-active'] === 'true')
|
||||
$scope.invoice.reference.model = settings['invoice_reference']
|
||||
$scope.invoice.legals.content = settings['invoice_legals'];
|
||||
$scope.invoice.text.content = settings['invoice_text'];
|
||||
$scope.invoice.VAT.rate = parseFloat(settings['invoice_VAT-rate']);
|
||||
$scope.invoice.VAT.active = (settings['invoice_VAT-active'] === 'true');
|
||||
$scope.invoice.number.model = settings['invoice_order-nb'];
|
||||
$scope.invoice.code.model = settings['invoice_code-value'];
|
||||
$scope.invoice.code.active = (settings['invoice_code-active'] === 'true');
|
||||
$scope.invoice.reference.model = settings['invoice_reference'];
|
||||
$scope.invoice.logo = {
|
||||
filetype: 'image/png',
|
||||
filename: 'logo.png',
|
||||
base64: settings['invoice_logo']
|
||||
}
|
||||
};
|
||||
|
||||
// Watch the logo, when a change occurs, save it
|
||||
return $scope.$watch('invoice.logo', function () {
|
||||
@ -418,15 +418,15 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
return Setting.update(
|
||||
{ name: 'invoice_logo' },
|
||||
{ value: $scope.invoice.logo.base64 },
|
||||
function (data) { growl.success(_t('logo_successfully_saved')) },
|
||||
function (data) { growl.success(_t('logo_successfully_saved')); },
|
||||
function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_logo'))
|
||||
return console.error(error)
|
||||
growl.error(_t('an_error_occurred_while_saving_the_logo'));
|
||||
return console.error(error);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Output the given integer with leading zeros. If the given value is longer than the given
|
||||
@ -434,7 +434,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
* @param value {number} the integer to pad
|
||||
* @param length {number} the length of the resulting string.
|
||||
*/
|
||||
var padWithZeros = function (value, length) { return (1e15 + value + '').slice(-length) }
|
||||
var padWithZeros = function (value, length) { return (1e15 + value + '').slice(-length); };
|
||||
|
||||
/**
|
||||
* Remove every unsupported html tag from the given html text (like <p>, <span>, ...).
|
||||
@ -445,20 +445,20 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
var parseHtml = function (html) {
|
||||
return html.replace(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/g, function (match, p1, offset, string) {
|
||||
if (['b', 'u', 'i', 'br'].includes(p1)) {
|
||||
return match
|
||||
return match;
|
||||
} else {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Reinitialize the context of invoices' search to display new results set
|
||||
*/
|
||||
var resetSearchInvoice = function () {
|
||||
$scope.page = 1
|
||||
return $scope.noMoreResults = false
|
||||
}
|
||||
$scope.page = 1;
|
||||
return $scope.noMoreResults = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a search query with the current parameters set concerning invoices, then affect or concat the results
|
||||
@ -477,21 +477,21 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
}
|
||||
}, function (invoices) {
|
||||
if (concat) {
|
||||
$scope.invoices = $scope.invoices.concat(invoices)
|
||||
$scope.invoices = $scope.invoices.concat(invoices);
|
||||
} else {
|
||||
$scope.invoices = invoices
|
||||
$scope.invoices = invoices;
|
||||
}
|
||||
|
||||
if (!invoices[0] || (invoices[0].maxInvoices <= $scope.invoices.length)) {
|
||||
return $scope.noMoreResults = true
|
||||
return $scope.noMoreResults = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the invoice refunding modal window
|
||||
@ -501,17 +501,17 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// invoice linked to the current refund
|
||||
$scope.invoice = invoice
|
||||
$scope.invoice = invoice;
|
||||
|
||||
// Associative array containing invoice_item ids associated with boolean values
|
||||
$scope.partial = {}
|
||||
$scope.partial = {};
|
||||
|
||||
// Default refund parameters
|
||||
$scope.avoir = {
|
||||
invoice_id: invoice.id,
|
||||
subscription_to_expire: false,
|
||||
invoice_items_ids: []
|
||||
}
|
||||
};
|
||||
|
||||
// Possible refunding methods
|
||||
$scope.avoirModes = [
|
||||
@ -520,12 +520,12 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
{ name: _t('by_cheque'), value: 'cheque' },
|
||||
{ name: _t('by_transfer'), value: 'transfer' },
|
||||
{ name: _t('by_wallet'), value: 'wallet' }
|
||||
]
|
||||
];
|
||||
|
||||
// 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
|
||||
$scope.subscriptionExpireOptions = {};
|
||||
$scope.subscriptionExpireOptions[_t('yes')] = true;
|
||||
$scope.subscriptionExpireOptions[_t('no')] = false;
|
||||
|
||||
// AngularUI-Bootstrap datepicker parameters to define when to refund
|
||||
$scope.datePicker = {
|
||||
@ -534,47 +534,47 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker
|
||||
*/
|
||||
$scope.openDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = true
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 = []
|
||||
$scope.avoir.invoice_items_ids = [];
|
||||
for (let itemId in $scope.partial) {
|
||||
const refundItem = $scope.partial[itemId]
|
||||
if (refundItem) { $scope.avoir.invoice_items_ids.push(parseInt(itemId)) }
|
||||
const refundItem = $scope.partial[itemId];
|
||||
if (refundItem) { $scope.avoir.invoice_items_ids.push(parseInt(itemId)); }
|
||||
}
|
||||
|
||||
if ($scope.avoir.invoice_items_ids.length === 0) {
|
||||
return growl.error(_t('you_must_select_at_least_one_element_to_create_a_refund'))
|
||||
return growl.error(_t('you_must_select_at_least_one_element_to_create_a_refund'));
|
||||
} else {
|
||||
return Invoice.save(
|
||||
{ avoir: $scope.avoir },
|
||||
function (avoir) { // success
|
||||
$uibModalInstance.close({ avoir, invoice: $scope.invoice })
|
||||
$uibModalInstance.close({ avoir, invoice: $scope.invoice });
|
||||
},
|
||||
function (err) { // failed
|
||||
growl.error(_t('unable_to_create_the_refund'))
|
||||
growl.error(_t('unable_to_create_the_refund'));
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the refund, dismiss the modal window
|
||||
*/
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -584,19 +584,19 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
const initialize = function () {
|
||||
// if the invoice was payed with stripe, allow to refund through stripe
|
||||
Invoice.get({ id: invoice.id }, function (data) {
|
||||
$scope.invoice = data
|
||||
$scope.invoice = data;
|
||||
// default : all elements of the invoice are refund
|
||||
return Array.from(data.items).map(function (item) {
|
||||
return ($scope.partial[item.id] = (typeof item.avoir_item_id !== 'number'))
|
||||
})
|
||||
})
|
||||
return ($scope.partial[item.id] = (typeof item.avoir_item_id !== 'number'));
|
||||
});
|
||||
});
|
||||
|
||||
if (invoice.stripe) {
|
||||
return $scope.avoirModes.push({ name: _t('online_payment'), value: 'stripe' })
|
||||
return $scope.avoirModes.push({ name: _t('online_payment'), value: 'stripe' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -13,7 +13,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
class MembersController {
|
||||
constructor ($scope, $state, Group, Training) {
|
||||
// Retrieve the profiles groups (eg. students ...)
|
||||
Group.query(function (groups) { $scope.groups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled }) })
|
||||
Group.query(function (groups) { $scope.groups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; }); });
|
||||
|
||||
// Retrieve the list of available trainings
|
||||
Training.query().$promise.then(function (data) {
|
||||
@ -47,9 +47,9 @@ class MembersController {
|
||||
id: d.id,
|
||||
name: d.name,
|
||||
disabled: d.disabled
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Default parameters for AngularUI-Bootstrap datepicker
|
||||
$scope.datePicker = {
|
||||
@ -59,27 +59,27 @@ class MembersController {
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the birth day datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.openDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = true
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.subscription_date_opened = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
@ -89,24 +89,24 @@ class MembersController {
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
return angular.forEach(content, function (v, k) {
|
||||
angular.forEach(v, function (err) {
|
||||
$scope.alerts.push({
|
||||
msg: k + ': ' + err,
|
||||
type: 'danger'
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return $state.go('app.admin.members')
|
||||
return $state.go('app.admin.members');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the admin's view to the members list page
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.admin.members') }
|
||||
$scope.cancel = function () { $state.go('app.admin.members'); };
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -115,11 +115,11 @@ class MembersController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,12 +131,12 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// number of users loaded each time we click on 'load more...'
|
||||
const USERS_PER_PAGE = 20
|
||||
const USERS_PER_PAGE = 20;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// members list
|
||||
$scope.members = membersPromise
|
||||
$scope.members = membersPromise;
|
||||
|
||||
$scope.member = {
|
||||
// Members plain-text filtering. Default: not filtered
|
||||
@ -147,13 +147,13 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
page: 1,
|
||||
// true when all members where loaded
|
||||
noMore: false
|
||||
}
|
||||
};
|
||||
|
||||
// admins list
|
||||
$scope.admins = adminsPromise.admins
|
||||
$scope.admins = adminsPromise.admins;
|
||||
|
||||
// Admins ordering/sorting. Default: not sorted
|
||||
$scope.orderAdmin = null
|
||||
$scope.orderAdmin = null;
|
||||
|
||||
/**
|
||||
* Change the members ordering criterion to the one provided
|
||||
@ -161,14 +161,14 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
*/
|
||||
$scope.setOrderMember = function (orderBy) {
|
||||
if ($scope.member.order === orderBy) {
|
||||
$scope.member.order = `-${orderBy}`
|
||||
$scope.member.order = `-${orderBy}`;
|
||||
} else {
|
||||
$scope.member.order = orderBy
|
||||
$scope.member.order = orderBy;
|
||||
}
|
||||
|
||||
resetSearchMember()
|
||||
return memberSearch()
|
||||
}
|
||||
resetSearchMember();
|
||||
return memberSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the admins ordering criterion to the one provided
|
||||
@ -176,11 +176,11 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
*/
|
||||
$scope.setOrderAdmin = function (orderAdmin) {
|
||||
if ($scope.orderAdmin === orderAdmin) {
|
||||
return $scope.orderAdmin = `-${orderAdmin}`
|
||||
return $scope.orderAdmin = `-${orderAdmin}`;
|
||||
} else {
|
||||
return $scope.orderAdmin = orderAdmin
|
||||
return $scope.orderAdmin = orderAdmin;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ask for confirmation then delete the specified administrator
|
||||
@ -195,7 +195,7 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: $sce.trustAsHtml(_t('do_you_really_want_to_delete_this_administrator_this_cannot_be_undone') + '<br/><br/>' + _t('this_may_take_a_while_please_wait'))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -203,31 +203,31 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
Admin.delete(
|
||||
{ id: admin.id },
|
||||
function () {
|
||||
admins.splice(findAdminIdxById(admins, admin.id), 1)
|
||||
return growl.success(_t('administrator_successfully_deleted'))
|
||||
admins.splice(findAdminIdxById(admins, admin.id), 1);
|
||||
return growl.success(_t('administrator_successfully_deleted'));
|
||||
},
|
||||
function (error) { growl.error(_t('unable_to_delete_the_administrator')) }
|
||||
)
|
||||
function (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
|
||||
*/
|
||||
$scope.showNextMembers = function () {
|
||||
$scope.member.page += 1
|
||||
return memberSearch(true)
|
||||
}
|
||||
$scope.member.page += 1;
|
||||
return memberSearch(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback when the search field content changes: reload the search results
|
||||
*/
|
||||
$scope.updateTextSearch = function () {
|
||||
resetSearchMember()
|
||||
return memberSearch()
|
||||
}
|
||||
resetSearchMember();
|
||||
return memberSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to alert the admin that the export request was acknowledged and is
|
||||
@ -236,10 +236,10 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
$scope.alertExport = function (type) {
|
||||
Export.status({ category: 'users', type }).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
return growl.success(_t('export_is_running_you_ll_be_notified_when_its_ready'))
|
||||
return growl.success(_t('export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -248,9 +248,9 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
*/
|
||||
const initialize = function () {
|
||||
if (!membersPromise[0] || (membersPromise[0].maxMembers <= $scope.members.length)) {
|
||||
return $scope.member.noMore = true
|
||||
return $scope.member.noMore = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterate through the provided array and return the index of the requested admin
|
||||
@ -259,16 +259,16 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
* @returns {Number} index of the requested admin, in the provided array
|
||||
*/
|
||||
var findAdminIdxById = function (admins, id) {
|
||||
return (admins.map(function (admin) { return admin.id })).indexOf(id)
|
||||
}
|
||||
return (admins.map(function (admin) { return admin.id; })).indexOf(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reinitialize the context of members's search to display new results set
|
||||
*/
|
||||
var resetSearchMember = function () {
|
||||
$scope.member.noMore = false
|
||||
return $scope.member.page = 1
|
||||
}
|
||||
$scope.member.noMore = false;
|
||||
return $scope.member.page = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a search query with the current parameters set ($scope.member[searchText,order,page])
|
||||
@ -285,21 +285,21 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
}
|
||||
}, function (members) {
|
||||
if (concat) {
|
||||
$scope.members = $scope.members.concat(members)
|
||||
$scope.members = $scope.members.concat(members);
|
||||
} else {
|
||||
$scope.members = members
|
||||
$scope.members = members;
|
||||
}
|
||||
|
||||
if (!members[0] || (members[0].maxMembers <= $scope.members.length)) {
|
||||
return $scope.member.noMore = true
|
||||
return $scope.member.noMore = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the member edition page
|
||||
@ -309,51 +309,51 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/members/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/members/${$stateParams.id}`;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'patch'
|
||||
$scope.method = 'patch';
|
||||
|
||||
// List of tags associables with user
|
||||
$scope.tags = tagsPromise
|
||||
$scope.tags = tagsPromise;
|
||||
|
||||
// The user to edit
|
||||
$scope.user = memberPromise
|
||||
$scope.user = memberPromise;
|
||||
|
||||
// Should the passord be modified?
|
||||
$scope.password =
|
||||
{ change: false }
|
||||
{ change: false };
|
||||
|
||||
// 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
|
||||
$scope.subscription = $scope.user.subscription;
|
||||
$scope.subscription.expired_at = $scope.subscription.expired_at;
|
||||
} else {
|
||||
Plan.query({ group_id: $scope.user.group_id }, function (plans) {
|
||||
$scope.plans = plans
|
||||
$scope.plans = plans;
|
||||
return Array.from($scope.plans).map(function (plan) {
|
||||
return (plan.nameToDisplay = $filter('humanReadablePlanName')(plan))
|
||||
})
|
||||
})
|
||||
return (plan.nameToDisplay = $filter('humanReadablePlanName')(plan));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Available trainings list
|
||||
$scope.trainings = []
|
||||
$scope.trainings = [];
|
||||
|
||||
// Profiles types (student/standard/...)
|
||||
$scope.groups = []
|
||||
$scope.groups = [];
|
||||
|
||||
// the user wallet
|
||||
$scope.wallet = walletPromise
|
||||
$scope.wallet = walletPromise;
|
||||
|
||||
// user wallet transactions
|
||||
$scope.transactions = transactionsPromise
|
||||
$scope.transactions = transactionsPromise;
|
||||
|
||||
// used in wallet partial template to identify parent view
|
||||
$scope.view = 'member_edit'
|
||||
$scope.view = 'member_edit';
|
||||
|
||||
// current active authentication provider
|
||||
$scope.activeProvider = activeProviderPromise
|
||||
$scope.activeProvider = activeProviderPromise;
|
||||
|
||||
/**
|
||||
* Open a modal dialog, allowing the admin to extend the current user's subscription (freely or not)
|
||||
@ -366,8 +366,8 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
templateUrl: '<%= asset_path "admin/subscriptions/expired_at_modal.html" %>',
|
||||
size: 'lg',
|
||||
controller: ['$scope', '$uibModalInstance', 'Subscription', function ($scope, $uibModalInstance, Subscription) {
|
||||
$scope.new_expired_at = angular.copy(subscription.expired_at)
|
||||
$scope.free = free
|
||||
$scope.new_expired_at = angular.copy(subscription.expired_at);
|
||||
$scope.free = free;
|
||||
$scope.datePicker = {
|
||||
opened: false,
|
||||
format: Fablab.uibDateFormat,
|
||||
@ -375,32 +375,32 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
startingDay: Fablab.weekStartingDay
|
||||
},
|
||||
minDate: new Date()
|
||||
}
|
||||
};
|
||||
|
||||
$scope.openDatePicker = function (ev) {
|
||||
ev.preventDefault()
|
||||
ev.stopPropagation()
|
||||
return $scope.datePicker.opened = true
|
||||
}
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
return $scope.datePicker.opened = true;
|
||||
};
|
||||
|
||||
$scope.ok = function () {
|
||||
Subscription.update(
|
||||
{ id: subscription.id },
|
||||
{ subscription: { expired_at: $scope.new_expired_at, free } },
|
||||
function (_subscription) {
|
||||
growl.success(_t('you_successfully_changed_the_expiration_date_of_the_user_s_subscription'))
|
||||
return $uibModalInstance.close(_subscription)
|
||||
growl.success(_t('you_successfully_changed_the_expiration_date_of_the_user_s_subscription'));
|
||||
return $uibModalInstance.close(_subscription);
|
||||
},
|
||||
function (error) { growl.error(_t('a_problem_occurred_while_saving_the_date')) }
|
||||
)
|
||||
}
|
||||
function (error) { growl.error(_t('a_problem_occurred_while_saving_the_date')); }
|
||||
);
|
||||
};
|
||||
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
})
|
||||
});
|
||||
// once the form was validated successfully ...
|
||||
return modalInstance.result.then(function (subscription) { $scope.subscription.expired_at = subscription.expired_at })
|
||||
}
|
||||
return modalInstance.result.then(function (subscription) { $scope.subscription.expired_at = subscription.expired_at; });
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog allowing the admin to set a subscription for the given user.
|
||||
@ -414,10 +414,10 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
size: 'lg',
|
||||
controller: ['$scope', '$uibModalInstance', 'Subscription', 'Group', function ($scope, $uibModalInstance, Subscription, Group) {
|
||||
// selected user
|
||||
$scope.user = user
|
||||
$scope.user = user;
|
||||
|
||||
// available plans for the selected user
|
||||
$scope.plans = plans
|
||||
$scope.plans = plans;
|
||||
|
||||
/**
|
||||
* Generate a string identifying the given plan by literal human-readable name
|
||||
@ -427,33 +427,33 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
* will be included.
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.humanReadablePlanName = function (plan, groups, short) { return `${$filter('humanReadablePlanName')(plan, groups, short)}` }
|
||||
$scope.humanReadablePlanName = function (plan, groups, short) { return `${$filter('humanReadablePlanName')(plan, groups, short)}`; };
|
||||
|
||||
/**
|
||||
* Modal dialog validation callback
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$scope.subscription.user_id = user.id
|
||||
$scope.subscription.user_id = user.id;
|
||||
return Subscription.save({ }, { subscription: $scope.subscription }, function (_subscription) {
|
||||
growl.success(_t('subscription_successfully_purchased'))
|
||||
$uibModalInstance.close(_subscription)
|
||||
return $state.reload()
|
||||
growl.success(_t('subscription_successfully_purchased'));
|
||||
$uibModalInstance.close(_subscription);
|
||||
return $state.reload();
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('a_problem_occurred_while_taking_the_subscription'))
|
||||
console.error(error)
|
||||
})
|
||||
}
|
||||
growl.error(_t('a_problem_occurred_while_taking_the_subscription'));
|
||||
console.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Modal dialog cancellation callback
|
||||
*/
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
})
|
||||
});
|
||||
// once the form was validated succesfully ...
|
||||
return modalInstance.result.then(function (subscription) { $scope.subscription = subscription })
|
||||
}
|
||||
return modalInstance.result.then(function (subscription) { $scope.subscription = subscription; });
|
||||
};
|
||||
|
||||
$scope.createWalletCreditModal = function (user, wallet) {
|
||||
const modalInstance = $uibModal.open({
|
||||
@ -461,13 +461,13 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
templateUrl: '<%= asset_path "wallet/credit_modal.html" %>',
|
||||
controller: ['$scope', '$uibModalInstance', 'Wallet', function ($scope, $uibModalInstance, Wallet) {
|
||||
// default: do not generate a refund invoice
|
||||
$scope.generate_avoir = false
|
||||
$scope.generate_avoir = false;
|
||||
|
||||
// date of the generated refund invoice
|
||||
$scope.avoir_date = null
|
||||
$scope.avoir_date = null;
|
||||
|
||||
// optional description shown on the refund invoice
|
||||
$scope.description = ''
|
||||
$scope.description = '';
|
||||
|
||||
// default configuration for the avoir date selector widget
|
||||
$scope.datePicker = {
|
||||
@ -476,16 +476,16 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to open/close the date picker
|
||||
*/
|
||||
$scope.toggleDatePicker = function ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = !$scope.datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Modal dialog validation callback
|
||||
@ -500,33 +500,33 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
avoir_description: $scope.description
|
||||
},
|
||||
function (_wallet) {
|
||||
growl.success(_t('wallet_credit_successfully'))
|
||||
return $uibModalInstance.close(_wallet)
|
||||
growl.success(_t('wallet_credit_successfully'));
|
||||
return $uibModalInstance.close(_wallet);
|
||||
},
|
||||
function (error) {
|
||||
growl.error(_t('a_problem_occurred_for_wallet_credit'))
|
||||
console.error(error)
|
||||
growl.error(_t('a_problem_occurred_for_wallet_credit'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Modal dialog cancellation callback
|
||||
*/
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
] })
|
||||
] });
|
||||
// once the form was validated succesfully ...
|
||||
return modalInstance.result.then(function (wallet) {
|
||||
$scope.wallet = wallet
|
||||
return Wallet.transactions({ id: wallet.id }, function (transactions) { $scope.transactions = transactions })
|
||||
})
|
||||
}
|
||||
$scope.wallet = wallet;
|
||||
return Wallet.transactions({ id: wallet.id }, function (transactions) { $scope.transactions = transactions; });
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled }
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled; };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -534,83 +534,83 @@ Application.Controllers.controller('EditMemberController', ['$scope', '$state',
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// init the birth date to JS object
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate()
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate();
|
||||
|
||||
// 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
|
||||
$scope.subscription = $scope.user.subscription;
|
||||
$scope.subscription.expired_at = $scope.subscription.expired_at;
|
||||
} else {
|
||||
Plan.query({ group_id: $scope.user.group_id }, function (plans) {
|
||||
$scope.plans = plans
|
||||
$scope.plans = plans;
|
||||
return Array.from($scope.plans).map(function (plan) {
|
||||
return (plan.nameToDisplay = `${plan.base_name} - ${plan.interval}`)
|
||||
})
|
||||
})
|
||||
return (plan.nameToDisplay = `${plan.base_name} - ${plan.interval}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Using the MembersController
|
||||
return new MembersController($scope, $state, Group, Training)
|
||||
}
|
||||
return new MembersController($scope, $state, Group, Training);
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/members'
|
||||
$scope.actionUrl = '/api/members';
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// Should the passord be set manually or generated?
|
||||
$scope.password =
|
||||
{ change: false }
|
||||
{ change: false };
|
||||
|
||||
// Default member's profile parameters
|
||||
$scope.user =
|
||||
{ plan_interval: '' }
|
||||
{ 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
|
||||
$scope.toggleOrganization = function () {
|
||||
if ($scope.user.organization) {
|
||||
if (!$scope.user.profile) { $scope.user.profile = {} }
|
||||
return $scope.user.profile.organization = {}
|
||||
if (!$scope.user.profile) { $scope.user.profile = {}; }
|
||||
return $scope.user.profile.organization = {};
|
||||
} else {
|
||||
return $scope.user.profile.organization = undefined
|
||||
return $scope.user.profile.organization = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Using the MembersController
|
||||
return new MembersController($scope, $state, Group, Training)
|
||||
return new MembersController($scope, $state, Group, Training);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* 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
|
||||
let getGender
|
||||
let getGender;
|
||||
$scope.admin = {
|
||||
profile_attributes: {
|
||||
gender: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Default parameters for AngularUI-Bootstrap datepicker
|
||||
$scope.datePicker = {
|
||||
@ -619,13 +619,13 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the birth day datepicker
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.openDatePicker = function ($event) { $scope.datePicker.opened = true }
|
||||
$scope.openDatePicker = function ($event) { $scope.datePicker.opened = true; };
|
||||
|
||||
/**
|
||||
* Send the new admin, currently stored in $scope.admin, to the server for database saving
|
||||
@ -635,14 +635,14 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
{},
|
||||
{ admin: $scope.admin },
|
||||
function () {
|
||||
growl.success(_t('administrator_successfully_created_he_will_receive_his_connection_directives_by_email', { GENDER: getGender($scope.admin) }, 'messageformat'))
|
||||
return $state.go('app.admin.members')
|
||||
growl.success(_t('administrator_successfully_created_he_will_receive_his_connection_directives_by_email', { GENDER: getGender($scope.admin) }, 'messageformat'));
|
||||
return $state.go('app.admin.members');
|
||||
}
|
||||
, function (error) {
|
||||
console.log(error)
|
||||
console.log(error);
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -653,9 +653,9 @@ Application.Controllers.controller('NewAdminController', ['$state', '$scope', 'A
|
||||
*/
|
||||
return getGender = function (user) {
|
||||
if (user.profile_attributes) {
|
||||
if (user.profile_attributes.gender) { return 'male' } else { return 'female' }
|
||||
} else { return 'other' }
|
||||
}
|
||||
if (user.profile_attributes.gender) { return 'male'; } else { return 'female'; }
|
||||
} else { return 'other'; }
|
||||
};
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -15,46 +15,46 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// clients list
|
||||
$scope.clients = clientsPromise
|
||||
$scope.order = null
|
||||
$scope.clientFormVisible = false
|
||||
$scope.client = {}
|
||||
$scope.clients = clientsPromise;
|
||||
$scope.order = null;
|
||||
$scope.clientFormVisible = false;
|
||||
$scope.client = {};
|
||||
|
||||
$scope.toggleForm = () => $scope.clientFormVisible = !$scope.clientFormVisible
|
||||
$scope.toggleForm = () => $scope.clientFormVisible = !$scope.clientFormVisible;
|
||||
|
||||
// Change the order criterion to the one provided
|
||||
// @param orderBy {string} ordering criterion
|
||||
//
|
||||
$scope.setOrder = function (orderBy) {
|
||||
if ($scope.order === orderBy) {
|
||||
return $scope.order = `-${orderBy}`
|
||||
return $scope.order = `-${orderBy}`;
|
||||
} else {
|
||||
return $scope.order = orderBy
|
||||
return $scope.order = orderBy;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.saveClient = function (client) {
|
||||
if (client.id != null) {
|
||||
OpenAPIClient.update({ id: client.id }, { open_api_client: client }, function (clientResp) {
|
||||
client = clientResp
|
||||
return growl.success(_t('client_successfully_updated'))
|
||||
})
|
||||
client = clientResp;
|
||||
return growl.success(_t('client_successfully_updated'));
|
||||
});
|
||||
} else {
|
||||
OpenAPIClient.save({ open_api_client: client }, function (client) {
|
||||
$scope.clients.push(client)
|
||||
return growl.success(_t('client_successfully_created'))
|
||||
})
|
||||
$scope.clients.push(client);
|
||||
return growl.success(_t('client_successfully_created'));
|
||||
});
|
||||
}
|
||||
|
||||
$scope.clientFormVisible = false
|
||||
$scope.clientForm.$setPristine()
|
||||
return $scope.client = {}
|
||||
}
|
||||
$scope.clientFormVisible = false;
|
||||
$scope.clientForm.$setPristine();
|
||||
return $scope.client = {};
|
||||
};
|
||||
|
||||
$scope.editClient = function (client) {
|
||||
$scope.clientFormVisible = true
|
||||
return $scope.client = client
|
||||
}
|
||||
$scope.clientFormVisible = true;
|
||||
return $scope.client = client;
|
||||
};
|
||||
|
||||
$scope.deleteClient = index =>
|
||||
dialogs.confirm({
|
||||
@ -63,16 +63,16 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_open_api_client')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, () =>
|
||||
OpenAPIClient.delete({ id: $scope.clients[index].id }, function () {
|
||||
$scope.clients.splice(index, 1)
|
||||
return growl.success(_t('client_successfully_deleted'))
|
||||
$scope.clients.splice(index, 1);
|
||||
return growl.success(_t('client_successfully_deleted'));
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return $scope.resetToken = client =>
|
||||
dialogs.confirm({
|
||||
@ -81,16 +81,16 @@ Application.Controllers.controller('OpenAPIClientsController', ['$scope', 'clien
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_revoke_this_open_api_access')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, () =>
|
||||
OpenAPIClient.resetToken({ id: client.id }, {}, function (clientResp) {
|
||||
client.token = clientResp.token
|
||||
return growl.success(_t('access_successfully_revoked'))
|
||||
client.token = clientResp.token;
|
||||
return growl.success(_t('access_successfully_revoked'));
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -16,23 +16,23 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
class PlanController {
|
||||
constructor ($scope, groups, prices, partners, CSRF) {
|
||||
// protection against request forgery
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// groups list
|
||||
$scope.groups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled })
|
||||
$scope.groups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; });
|
||||
|
||||
// users with role 'partner', notifiables for a partner plan
|
||||
$scope.partners = partners.users
|
||||
$scope.partners = partners.users;
|
||||
|
||||
// Subscriptions prices, machines prices and training prices, per groups
|
||||
$scope.group_pricing = prices
|
||||
$scope.group_pricing = prices;
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -41,11 +41,11 @@ class PlanController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark the provided file for deletion
|
||||
@ -53,9 +53,9 @@ class PlanController {
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
if ((file != null) && (file.id != null)) {
|
||||
return file._destroy = true
|
||||
return file._destroy = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,13 +67,13 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// current form is used to create a new plan
|
||||
$scope.mode = 'creation'
|
||||
$scope.mode = 'creation';
|
||||
|
||||
// prices bindings
|
||||
$scope.prices = {
|
||||
training: {},
|
||||
machine: {}
|
||||
}
|
||||
};
|
||||
|
||||
// form inputs bindings
|
||||
$scope.plan = {
|
||||
@ -86,19 +86,19 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
partnerId: null,
|
||||
partnerContact: null,
|
||||
ui_weight: 0
|
||||
}
|
||||
};
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/plans/'
|
||||
$scope.actionUrl = '/api/plans/';
|
||||
|
||||
// HTTP method for the rest API
|
||||
$scope.method = 'POST'
|
||||
$scope.method = 'POST';
|
||||
|
||||
/**
|
||||
* Checks if the partner contact is a valid data. Used in the form validation process
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$scope.partnerIsValid = function () { return ($scope.plan.type === 'Plan') || ($scope.plan.partnerId || ($scope.plan.partnerContact && $scope.plan.partnerContact.email)) }
|
||||
$scope.partnerIsValid = function () { return ($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
|
||||
@ -109,32 +109,32 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
templateUrl: '<%= asset_path "shared/_partner_new_modal.html" %>',
|
||||
size: 'lg',
|
||||
controller: ['$scope', '$uibModalInstance', 'User', function ($scope, $uibModalInstance, User) {
|
||||
$scope.partner = {}
|
||||
$scope.partner = {};
|
||||
|
||||
$scope.ok = function () {
|
||||
User.save(
|
||||
{},
|
||||
{ user: $scope.partner },
|
||||
function (user) {
|
||||
$scope.partner.id = user.id
|
||||
$scope.partner.name = `${user.first_name} ${user.last_name}`
|
||||
$uibModalInstance.close($scope.partner)
|
||||
$scope.partner.id = user.id;
|
||||
$scope.partner.name = `${user.first_name} ${user.last_name}`;
|
||||
$uibModalInstance.close($scope.partner);
|
||||
},
|
||||
function (error) {
|
||||
growl.error(_t('new_plan.unable_to_save_this_user_check_that_there_isnt_an_already_a_user_with_the_same_name'))
|
||||
console.error(error)
|
||||
growl.error(_t('new_plan.unable_to_save_this_user_check_that_there_isnt_an_already_a_user_with_the_same_name'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
}
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
);
|
||||
};
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
})
|
||||
});
|
||||
// once the form was validated successfully ...
|
||||
return modalInstance.result.then(function (partner) {
|
||||
$scope.partners.push(partner)
|
||||
return $scope.plan.partnerId = partner.id
|
||||
})
|
||||
}
|
||||
$scope.partners.push(partner);
|
||||
return $scope.plan.partnerId = partner.id;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Display some messages and redirect the user, once the form was submitted, depending on the result status
|
||||
@ -143,22 +143,22 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal',
|
||||
*/
|
||||
$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'))
|
||||
return growl.error(_t('new_plan.unable_to_create_the_subscription_please_try_again'));
|
||||
} else {
|
||||
growl.success(_t('new_plan.successfully_created_subscription(s)_dont_forget_to_redefine_prices'))
|
||||
growl.success(_t('new_plan.successfully_created_subscription(s)_dont_forget_to_redefine_prices'));
|
||||
if (content.plan_ids != null) {
|
||||
return $state.go('app.admin.pricing')
|
||||
return $state.go('app.admin.pricing');
|
||||
} else {
|
||||
if (content.id != null) {
|
||||
return $state.go('app.admin.plans.edit', { id: content.id })
|
||||
return $state.go('app.admin.plans.edit', { id: content.id });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return new PlanController($scope, groups, prices, partners, CSRF)
|
||||
return new PlanController($scope, groups, prices, partners, CSRF);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the plan edition form
|
||||
@ -168,30 +168,30 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// List of spaces
|
||||
$scope.spaces = spaces
|
||||
$scope.spaces = spaces;
|
||||
|
||||
// List of plans
|
||||
$scope.plans = plans
|
||||
$scope.plans = plans;
|
||||
|
||||
// List of machines
|
||||
$scope.machines = machines
|
||||
$scope.machines = machines;
|
||||
|
||||
// List of groups
|
||||
$scope.groups = groups
|
||||
$scope.groups = groups;
|
||||
|
||||
// current form is used for edition mode
|
||||
$scope.mode = 'edition'
|
||||
$scope.mode = 'edition';
|
||||
|
||||
// edited plan data
|
||||
$scope.plan = planPromise
|
||||
if ($scope.plan.type === null) { $scope.plan.type = 'Plan' }
|
||||
if ($scope.plan.disabled) { $scope.plan.disabled = 'true' }
|
||||
$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
|
||||
$scope.actionUrl = `/api/plans/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/plans/${$stateParams.id}`;
|
||||
|
||||
// HTTP method for the rest API
|
||||
$scope.method = 'PATCH'
|
||||
$scope.method = 'PATCH';
|
||||
|
||||
/**
|
||||
* If a parent plan was set ($scope.plan.parent), the prices will be copied from this parent plan into
|
||||
@ -202,34 +202,34 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
return Plan.get({ id: $scope.plan.parent }, function (parentPlan) {
|
||||
Array.from(parentPlan.prices).map(function (parentPrice) {
|
||||
return (function () {
|
||||
const result = []
|
||||
const result = [];
|
||||
for (let childKey in $scope.plan.prices) {
|
||||
const childPrice = $scope.plan.prices[childKey]
|
||||
const childPrice = $scope.plan.prices[childKey];
|
||||
if ((childPrice.priceable_type === parentPrice.priceable_type) && (childPrice.priceable_id === parentPrice.priceable_id)) {
|
||||
$scope.plan.prices[childKey].amount = parentPrice.amount
|
||||
break
|
||||
$scope.plan.prices[childKey].amount = parentPrice.amount;
|
||||
break;
|
||||
} else {
|
||||
result.push(undefined)
|
||||
result.push(undefined);
|
||||
}
|
||||
}
|
||||
return result
|
||||
})()
|
||||
})
|
||||
return result;
|
||||
})();
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// if no plan were selected, unset every prices
|
||||
} else {
|
||||
return (function () {
|
||||
const result = []
|
||||
const result = [];
|
||||
for (let key in $scope.plan.prices) {
|
||||
const price = $scope.plan.prices[key]
|
||||
result.push($scope.plan.prices[key].amount = 0)
|
||||
const price = $scope.plan.prices[key];
|
||||
result.push($scope.plan.prices[key].amount = 0);
|
||||
}
|
||||
return result
|
||||
})()
|
||||
return result;
|
||||
})();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Display some messages once the form was submitted, depending on the result status (failed/succeeded)
|
||||
@ -237,12 +237,12 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
*/
|
||||
$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'))
|
||||
return growl.error(_t('edit_plan.unable_to_save_subscription_changes_please_try_again'));
|
||||
} else {
|
||||
growl.success(_t('edit_plan.subscription_successfully_changed'))
|
||||
return $state.go('app.admin.pricing')
|
||||
growl.success(_t('edit_plan.subscription_successfully_changed'));
|
||||
return $state.go('app.admin.pricing');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a string identifying the given plan by literal humain-readable name
|
||||
@ -252,7 +252,7 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
* will be included.
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.humanReadablePlanName = function (plan, groups, short) { return `${$filter('humanReadablePlanName')(plan, groups, short)}` }
|
||||
$scope.humanReadablePlanName = function (plan, groups, short) { return `${$filter('humanReadablePlanName')(plan, groups, short)}`; };
|
||||
|
||||
/**
|
||||
* Retrieve the machine from its ID
|
||||
@ -262,10 +262,10 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
$scope.getMachine = function (machine_id) {
|
||||
for (let machine of Array.from($scope.machines)) {
|
||||
if (machine.id === machine_id) {
|
||||
return machine
|
||||
return machine;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the space from its ID
|
||||
@ -275,12 +275,12 @@ Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'p
|
||||
$scope.getSpace = function (space_id) {
|
||||
for (let space of Array.from($scope.spaces)) {
|
||||
if (space.id === space_id) {
|
||||
return space
|
||||
return space;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Using the PlansController
|
||||
return new PlanController($scope, groups, prices, partners, CSRF)
|
||||
return new PlanController($scope, groups, prices, partners, CSRF);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in price category creation/edition form dialog
|
||||
@ -17,16 +17,16 @@
|
||||
Application.Controllers.controller('PriceCategoryController', ['$scope', '$uibModalInstance', 'category',
|
||||
function ($scope, $uibModalInstance, category) {
|
||||
// Price category to edit/empty object for new category
|
||||
$scope.category = category
|
||||
$scope.category = category;
|
||||
|
||||
/**
|
||||
* Callback for form validation
|
||||
*/
|
||||
$scope.ok = () => $uibModalInstance.close($scope.category)
|
||||
$scope.ok = () => $uibModalInstance.close($scope.category);
|
||||
|
||||
/**
|
||||
* Do not validate the modifications, hide the modal
|
||||
*/
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel')
|
||||
return $scope.cancel = () => $uibModalInstance.dismiss('cancel');
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -13,7 +13,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in the prices edition page
|
||||
@ -22,80 +22,80 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
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)
|
||||
$scope.machinesPrices = machinesPricesPromise
|
||||
$scope.machinesPrices = machinesPricesPromise;
|
||||
|
||||
// List of trainings pricing
|
||||
$scope.trainingsPricings = trainingsPricingsPromise
|
||||
$scope.trainingsPricings = trainingsPricingsPromise;
|
||||
|
||||
// List of available subscriptions plans (eg. student/month, PME/year ...)
|
||||
$scope.plans = plans
|
||||
$scope.enabledPlans = plans.filter(function (p) { return !p.disabled })
|
||||
$scope.plans = plans;
|
||||
$scope.enabledPlans = plans.filter(function (p) { return !p.disabled; });
|
||||
|
||||
// List of groups (eg. normal, student ...)
|
||||
$scope.groups = groups.filter(function (g) { return g.slug !== 'admins' })
|
||||
$scope.enabledGroups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled })
|
||||
$scope.groups = groups.filter(function (g) { return g.slug !== 'admins'; });
|
||||
$scope.enabledGroups = groups.filter(function (g) { return (g.slug !== 'admins') && !g.disabled; });
|
||||
|
||||
// Associate free machine hours with subscriptions
|
||||
$scope.machineCredits = machineCreditsPromise
|
||||
$scope.machineCredits = machineCreditsPromise;
|
||||
|
||||
// Array of associations (plan <-> training)
|
||||
$scope.trainingCredits = trainingCreditsPromise
|
||||
$scope.trainingCredits = trainingCreditsPromise;
|
||||
|
||||
// Associate a plan with all its trainings ids
|
||||
$scope.trainingCreditsGroups = {}
|
||||
$scope.trainingCreditsGroups = {};
|
||||
|
||||
// List of trainings
|
||||
$scope.trainings = trainingsPromise.filter(function (t) { return !t.disabled })
|
||||
$scope.trainings = trainingsPromise.filter(function (t) { return !t.disabled; });
|
||||
|
||||
// List of machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.enabledMachines = machinesPromise.filter(function (m) { return !m.disabled })
|
||||
$scope.machines = machinesPromise;
|
||||
$scope.enabledMachines = machinesPromise.filter(function (m) { return !m.disabled; });
|
||||
|
||||
// List of coupons
|
||||
$scope.coupons = couponsPromise
|
||||
$scope.coupons = couponsPromise;
|
||||
|
||||
// List of spaces
|
||||
$scope.spaces = spacesPromise
|
||||
$scope.enabledSpaces = spacesPromise.filter(function (s) { return !s.disabled })
|
||||
$scope.spaces = spacesPromise;
|
||||
$scope.enabledSpaces = spacesPromise.filter(function (s) { return !s.disabled; });
|
||||
|
||||
// Associate free space hours with subscriptions
|
||||
$scope.spaceCredits = spacesCreditsPromise
|
||||
$scope.spaceCredits = spacesCreditsPromise;
|
||||
|
||||
// List of spaces prices (not considering any plan)
|
||||
$scope.spacesPrices = spacesPricesPromise
|
||||
$scope.spacesPrices = spacesPricesPromise;
|
||||
|
||||
// The plans list ordering. Default: by group
|
||||
$scope.orderPlans = 'group_id'
|
||||
$scope.orderPlans = 'group_id';
|
||||
|
||||
// Status of the drop-down menu in Credits tab
|
||||
$scope.status =
|
||||
{ isopen: false }
|
||||
{ isopen: false };
|
||||
|
||||
// Default: we show only enabled plans
|
||||
$scope.planFiltering = 'enabled'
|
||||
$scope.planFiltering = 'enabled';
|
||||
|
||||
// Available options for filtering plans by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
]
|
||||
];
|
||||
|
||||
$scope.findTrainingsPricing = function (trainingsPricings, trainingId, groupId) {
|
||||
for (let trainingsPricing of Array.from(trainingsPricings)) {
|
||||
if ((trainingsPricing.training_id === trainingId) && (trainingsPricing.group_id === groupId)) {
|
||||
return trainingsPricing
|
||||
return trainingsPricing;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.updateTrainingsPricing = function (data, trainingsPricing) {
|
||||
if (data != null) {
|
||||
return TrainingsPricing.update({ id: trainingsPricing.id }, { trainings_pricing: { amount: data } }).$promise
|
||||
return TrainingsPricing.update({ id: trainingsPricing.id }, { trainings_pricing: { amount: data } }).$promise;
|
||||
} else {
|
||||
return _t('pricing.please_specify_a_number')
|
||||
return _t('pricing.please_specify_a_number');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a plan from its given identifier and returns it
|
||||
@ -105,10 +105,10 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$scope.getPlanFromId = function (id) {
|
||||
for (let plan of Array.from($scope.plans)) {
|
||||
if (plan.id === parseInt(id)) {
|
||||
return plan
|
||||
return plan;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a group from its given identifier and returns it
|
||||
@ -118,10 +118,10 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$scope.getGroupFromId = function (groups, id) {
|
||||
for (let group of Array.from(groups)) {
|
||||
if (group.id === parseInt(id)) {
|
||||
return group
|
||||
return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a human readable string of named trainings, according to the provided array.
|
||||
@ -131,17 +131,17 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.showTrainings = function (trainings) {
|
||||
if (!angular.isArray(trainings) || !(trainings.length > 0)) {
|
||||
return _t('pricing.none')
|
||||
return _t('pricing.none');
|
||||
}
|
||||
|
||||
const selected = []
|
||||
const selected = [];
|
||||
angular.forEach($scope.trainings, function (t) {
|
||||
if (trainings.indexOf(t.id) >= 0) {
|
||||
return selected.push(t.name)
|
||||
return selected.push(t.name);
|
||||
}
|
||||
})
|
||||
if (selected.length) { return selected.join(' | ') } else { return _t('pricing.none') }
|
||||
}
|
||||
});
|
||||
if (selected.length) { return selected.join(' | '); } else { return _t('pricing.none'); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Validation callback when editing training's credits. Save the changes.
|
||||
@ -155,10 +155,10 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
{ training_credit_nb: newdata.training_credits }
|
||||
, angular.noop() // do nothing in case of success
|
||||
, function (error) {
|
||||
growl.error(_t('pricing.an_error_occurred_while_saving_the_number_of_credits'))
|
||||
console.error(error)
|
||||
growl.error(_t('pricing.an_error_occurred_while_saving_the_number_of_credits'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// save the associated trainings
|
||||
return angular.forEach($scope.trainingCreditsGroups, function (original, key) {
|
||||
@ -167,22 +167,22 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
// iterate through the previous credits to remove
|
||||
angular.forEach(original, function (oldTrainingId) {
|
||||
if (newdata.training_ids.indexOf(oldTrainingId) === -1) {
|
||||
const tc = findTrainingCredit(oldTrainingId, planId)
|
||||
const tc = findTrainingCredit(oldTrainingId, planId);
|
||||
if (tc) {
|
||||
return tc.$delete({}
|
||||
, function () {
|
||||
$scope.trainingCredits.splice($scope.trainingCredits.indexOf(tc), 1)
|
||||
return $scope.trainingCreditsGroups[planId].splice($scope.trainingCreditsGroups[planId].indexOf(tc.id), 1)
|
||||
$scope.trainingCredits.splice($scope.trainingCredits.indexOf(tc), 1);
|
||||
return $scope.trainingCreditsGroups[planId].splice($scope.trainingCreditsGroups[planId].indexOf(tc.id), 1);
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('pricing.an_error_occurred_while_deleting_credit_with_the_TRAINING', { TRAINING: tc.creditable.name }))
|
||||
console.error(error)
|
||||
})
|
||||
growl.error(_t('pricing.an_error_occurred_while_deleting_credit_with_the_TRAINING', { TRAINING: tc.creditable.name }));
|
||||
console.error(error);
|
||||
});
|
||||
} else {
|
||||
return growl.error(_t('pricing.an_error_occurred_unable_to_find_the_credit_to_revoke'))
|
||||
return growl.error(_t('pricing.an_error_occurred_unable_to_find_the_credit_to_revoke'));
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// iterate through the new credits to add
|
||||
return angular.forEach(newdata.training_ids, function (newTrainingId) {
|
||||
@ -195,39 +195,39 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
}
|
||||
}
|
||||
, function (newTc) { // success
|
||||
$scope.trainingCredits.push(newTc)
|
||||
return $scope.trainingCreditsGroups[newTc.plan_id].push(newTc.creditable_id)
|
||||
$scope.trainingCredits.push(newTc);
|
||||
return $scope.trainingCreditsGroups[newTc.plan_id].push(newTc.creditable_id);
|
||||
}
|
||||
, function (error) { // failed
|
||||
const training = getTrainingFromId(newTrainingId)
|
||||
growl.error(_t('pricing.an_error_occurred_while_creating_credit_with_the_TRAINING', { TRAINING: training.name }))
|
||||
return console.error(error)
|
||||
})
|
||||
const training = getTrainingFromId(newTrainingId);
|
||||
growl.error(_t('pricing.an_error_occurred_while_creating_credit_with_the_TRAINING', { TRAINING: training.name }));
|
||||
return console.error(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the current training credit modification
|
||||
* @param rowform {Object} see http://vitalets.github.io/angular-xeditable/
|
||||
*/
|
||||
$scope.cancelTrainingCredit = function (rowform) { rowform.$cancel() }
|
||||
$scope.cancelTrainingCredit = function (rowform) { rowform.$cancel(); };
|
||||
|
||||
/**
|
||||
* 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()
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$scope.inserted =
|
||||
{ creditable_type: 'Machine' }
|
||||
$scope.machineCredits.push($scope.inserted)
|
||||
return $scope.status.isopen = !$scope.status.isopen
|
||||
}
|
||||
{ creditable_type: 'Machine' };
|
||||
$scope.machineCredits.push($scope.inserted);
|
||||
return $scope.status.isopen = !$scope.status.isopen;
|
||||
};
|
||||
|
||||
/**
|
||||
* In the Credits tab, return the name of the machine/space associated with the given credit
|
||||
@ -235,16 +235,16 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.showCreditableName = function (credit) {
|
||||
let selected = _t('pricing.not_set')
|
||||
let selected = _t('pricing.not_set');
|
||||
if (credit && credit.creditable_id) {
|
||||
const object = $scope.getCreditable(credit)
|
||||
selected = object.name
|
||||
const object = $scope.getCreditable(credit);
|
||||
selected = object.name;
|
||||
if (credit.creditable_type === 'Machine') {
|
||||
selected += ` ( id. ${object.id} )`
|
||||
selected += ` ( id. ${object.id} )`;
|
||||
}
|
||||
}
|
||||
return selected
|
||||
}
|
||||
return selected;
|
||||
};
|
||||
|
||||
/**
|
||||
* In the Credits tab, return the machine/space associated with the given credit
|
||||
@ -252,24 +252,24 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* @returns {Object}
|
||||
*/
|
||||
$scope.getCreditable = function (credit) {
|
||||
let selected
|
||||
let selected;
|
||||
if (credit && credit.creditable_id) {
|
||||
if (credit.creditable_type === 'Machine') {
|
||||
angular.forEach($scope.machines, function (m) {
|
||||
if (m.id === credit.creditable_id) {
|
||||
return selected = m
|
||||
return selected = m;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else if (credit.creditable_type === 'Space') {
|
||||
angular.forEach($scope.spaces, function (s) {
|
||||
if (s.id === credit.creditable_id) {
|
||||
return selected = s
|
||||
return selected = s;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
return selected
|
||||
}
|
||||
return selected;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validation callback when editing machine's credits. Save the changes.
|
||||
@ -280,31 +280,31 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$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))) {
|
||||
growl.error(_t('pricing.error_a_credit_linking_this_machine_with_that_subscription_already_exists'))
|
||||
growl.error(_t('pricing.error_a_credit_linking_this_machine_with_that_subscription_already_exists'));
|
||||
if (!id) {
|
||||
$scope.machineCredits.pop()
|
||||
$scope.machineCredits.pop();
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('pricing.changes_have_been_successfully_saved')) })
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('pricing.changes_have_been_successfully_saved')); });
|
||||
} else {
|
||||
data.creditable_type = 'Machine'
|
||||
data.creditable_type = 'Machine';
|
||||
return Credit.save(
|
||||
{ credit: data }
|
||||
, function (resp) {
|
||||
$scope.machineCredits[$scope.machineCredits.length - 1].id = resp.id
|
||||
return growl.success(_t('pricing.credit_was_successfully_saved'))
|
||||
$scope.machineCredits[$scope.machineCredits.length - 1].id = resp.id;
|
||||
return growl.success(_t('pricing.credit_was_successfully_saved'));
|
||||
}
|
||||
, function (err) {
|
||||
$scope.machineCredits.pop()
|
||||
growl.error(_t('pricing.error_creating_credit'))
|
||||
console.error(err)
|
||||
})
|
||||
$scope.machineCredits.pop();
|
||||
growl.error(_t('pricing.error_creating_credit'));
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved machine credit / Cancel the current machine credit modification
|
||||
@ -313,33 +313,33 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.cancelMachineCredit = function (rowform, index) {
|
||||
if ($scope.machineCredits[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.machineCredits.splice(index, 1)
|
||||
return $scope.machineCredits.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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])
|
||||
$scope.machineCredits.splice(index, 1)
|
||||
}
|
||||
Credit.delete($scope.machineCredits[index]);
|
||||
$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-
|
||||
*/
|
||||
$scope.addSpaceCredit = function (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$scope.inserted =
|
||||
{ creditable_type: 'Space' }
|
||||
$scope.spaceCredits.push($scope.inserted)
|
||||
$scope.status.isopen = !$scope.status.isopen
|
||||
}
|
||||
{ creditable_type: 'Space' };
|
||||
$scope.spaceCredits.push($scope.inserted);
|
||||
$scope.status.isopen = !$scope.status.isopen;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validation callback when editing space's credits. Save the changes.
|
||||
@ -350,30 +350,30 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$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))) {
|
||||
growl.error(_t('pricing.error_a_credit_linking_this_space_with_that_subscription_already_exists'))
|
||||
growl.error(_t('pricing.error_a_credit_linking_this_space_with_that_subscription_already_exists'));
|
||||
if (!id) {
|
||||
$scope.spaceCredits.pop()
|
||||
$scope.spaceCredits.pop();
|
||||
}
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != null) {
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('pricing.changes_have_been_successfully_saved')) })
|
||||
return Credit.update({ id }, { credit: data }, function () { growl.success(_t('pricing.changes_have_been_successfully_saved')); });
|
||||
} else {
|
||||
data.creditable_type = 'Space'
|
||||
data.creditable_type = 'Space';
|
||||
return Credit.save(
|
||||
{ credit: data }
|
||||
, function (resp) {
|
||||
$scope.spaceCredits[$scope.spaceCredits.length - 1].id = resp.id
|
||||
return growl.success(_t('pricing.credit_was_successfully_saved'))
|
||||
$scope.spaceCredits[$scope.spaceCredits.length - 1].id = resp.id;
|
||||
return growl.success(_t('pricing.credit_was_successfully_saved'));
|
||||
}
|
||||
, function (err) {
|
||||
$scope.spaceCredits.pop()
|
||||
return growl.error(_t('pricing.error_creating_credit'))
|
||||
})
|
||||
$scope.spaceCredits.pop();
|
||||
return growl.error(_t('pricing.error_creating_credit'));
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved space credit / Cancel the current space credit modification
|
||||
@ -382,20 +382,20 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.cancelSpaceCredit = function (rowform, index) {
|
||||
if ($scope.spaceCredits[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.spaceCredits.splice(index, 1)
|
||||
return $scope.spaceCredits.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
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
|
||||
@ -404,9 +404,9 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.getPlanType = function (type) {
|
||||
if (type === 'PartnerPlan') {
|
||||
return _t('pricing.partner')
|
||||
} else { return _t('pricing.standard') }
|
||||
}
|
||||
return _t('pricing.partner');
|
||||
} else { return _t('pricing.standard'); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the plans ordering criterion to the one provided
|
||||
@ -414,11 +414,11 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.setOrderPlans = function (orderBy) {
|
||||
if ($scope.orderPlans === orderBy) {
|
||||
return $scope.orderPlans = `-${orderBy}`
|
||||
return $scope.orderPlans = `-${orderBy}`;
|
||||
} else {
|
||||
return $scope.orderPlans = orderBy
|
||||
return $scope.orderPlans = orderBy;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a price from prices array by a machineId and a groupId
|
||||
@ -426,21 +426,21 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$scope.findPriceBy = function (prices, machineId, groupId) {
|
||||
for (let price of Array.from(prices)) {
|
||||
if ((price.priceable_id === machineId) && (price.group_id === groupId)) {
|
||||
return price
|
||||
return price;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
return Price.update({ id: price.id }, { price: { amount: data } }).$promise;
|
||||
} else {
|
||||
return _t('pricing.please_specify_a_number')
|
||||
return _t('pricing.please_specify_a_number');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the specified subcription plan
|
||||
@ -448,7 +448,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.deletePlan = function (plans, id) {
|
||||
if (typeof id !== 'number') {
|
||||
return console.error('[EditPricingController::deletePlan] Error: invalid id parameter')
|
||||
return console.error('[EditPricingController::deletePlan] Error: invalid id parameter');
|
||||
} else {
|
||||
// open a confirmation dialog
|
||||
return dialogs.confirm(
|
||||
@ -458,7 +458,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return {
|
||||
title: _t('pricing.confirmation_required'),
|
||||
msg: _t('pricing.do_you_really_want_to_delete_this_subscription_plan')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -467,18 +467,18 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
Plan.delete(
|
||||
{ id },
|
||||
function (res) {
|
||||
growl.success(_t('pricing.subscription_plan_was_successfully_deleted'))
|
||||
return $scope.plans.splice(findItemIdxById(plans, id), 1)
|
||||
growl.success(_t('pricing.subscription_plan_was_successfully_deleted'));
|
||||
return $scope.plans.splice(findItemIdxById(plans, id), 1);
|
||||
},
|
||||
function (error) {
|
||||
if (error.statusText) { console.error(`[EditPricingController::deletePlan] Error: ${error.statusText}`) }
|
||||
growl.error(_t('pricing.unable_to_delete_the_specified_subscription_an_error_occurred'))
|
||||
if (error.statusText) { console.error(`[EditPricingController::deletePlan] Error: ${error.statusText}`); }
|
||||
growl.error(_t('pricing.unable_to_delete_the_specified_subscription_an_error_occurred'));
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a string identifying the given plan by literal humain-readable name
|
||||
@ -488,7 +488,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* will be included.
|
||||
* @returns {String}
|
||||
*/
|
||||
$scope.humanReadablePlanName = function (plan, groups, short) { return `${$filter('humanReadablePlanName')(plan, groups, short)}` }
|
||||
$scope.humanReadablePlanName = function (plan, groups, short) { return `${$filter('humanReadablePlanName')(plan, groups, short)}`; };
|
||||
|
||||
/**
|
||||
* Delete a coupon from the server's database and, in case of success, from the list in memory
|
||||
@ -497,7 +497,7 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.deleteCoupon = function (coupons, id) {
|
||||
if (typeof id !== 'number') {
|
||||
return console.error('[EditPricingController::deleteCoupon] Error: invalid id parameter')
|
||||
return console.error('[EditPricingController::deleteCoupon] Error: invalid id parameter');
|
||||
} else {
|
||||
// open a confirmation dialog
|
||||
return dialogs.confirm({
|
||||
@ -506,28 +506,28 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
return {
|
||||
title: _t('pricing.confirmation_required'),
|
||||
msg: _t('pricing.do_you_really_want_to_delete_this_coupon')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () {
|
||||
// the admin has confirmed, delete the coupon
|
||||
Coupon.delete({ id }, function (res) {
|
||||
growl.success(_t('coupon_was_successfully_deleted'))
|
||||
return $scope.coupons.splice(findItemIdxById(coupons, id), 1)
|
||||
growl.success(_t('coupon_was_successfully_deleted'));
|
||||
return $scope.coupons.splice(findItemIdxById(coupons, id), 1);
|
||||
}
|
||||
|
||||
, function (error) {
|
||||
if (error.statusText) { console.error(`[EditPricingController::deleteCoupon] Error: ${error.statusText}`) }
|
||||
if (error.statusText) { console.error(`[EditPricingController::deleteCoupon] Error: ${error.statusText}`); }
|
||||
if (error.status === 422) {
|
||||
return growl.error(_t('pricing.unable_to_delete_the_specified_coupon_already_in_use'))
|
||||
return growl.error(_t('pricing.unable_to_delete_the_specified_coupon_already_in_use'));
|
||||
} else {
|
||||
return growl.error(_t('pricing.unable_to_delete_the_specified_coupon_an_unexpected_error_occurred'))
|
||||
return growl.error(_t('pricing.unable_to_delete_the_specified_coupon_an_unexpected_error_occurred'));
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal allowing to select an user and send him the details of the provided coupon
|
||||
@ -537,33 +537,33 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/pricing/sendCoupon.html" %>',
|
||||
resolve: {
|
||||
coupon () { return coupon }
|
||||
coupon () { return coupon; }
|
||||
},
|
||||
size: 'md',
|
||||
controller: ['$scope', '$uibModalInstance', 'Coupon', 'coupon', '_t', function ($scope, $uibModalInstance, Coupon, coupon, _t) {
|
||||
// Member, receiver of the coupon
|
||||
$scope.ctrl =
|
||||
{ member: null }
|
||||
{ member: null };
|
||||
|
||||
// Details of the coupon to send
|
||||
$scope.coupon = coupon
|
||||
$scope.coupon = coupon;
|
||||
|
||||
// Callback to validate sending of the coupon
|
||||
$scope.ok = function () {
|
||||
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 }))
|
||||
return $uibModalInstance.close({ user_id: $scope.ctrl.member.id })
|
||||
growl.success(_t('pricing.coupon_successfully_sent_to_USER', { USER: $scope.ctrl.member.name }));
|
||||
return $uibModalInstance.close({ user_id: $scope.ctrl.member.id });
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('pricing.an_error_occurred_unable_to_send_the_coupon'))
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
growl.error(_t('pricing.an_error_occurred_unable_to_send_the_coupon'));
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
// Callback to close the modal and cancel the sending process
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -571,21 +571,21 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
$scope.trainingCreditsGroups = groupCreditsByPlan($scope.trainingCredits)
|
||||
$scope.trainingCreditsGroups = groupCreditsByPlan($scope.trainingCredits);
|
||||
|
||||
// adds empty array for plan which hasn't any credits yet
|
||||
return (function () {
|
||||
const result = []
|
||||
const result = [];
|
||||
for (let plan of Array.from($scope.plans)) {
|
||||
if ($scope.trainingCreditsGroups[plan.id] == null) {
|
||||
result.push($scope.trainingCreditsGroups[plan.id] = [])
|
||||
result.push($scope.trainingCreditsGroups[plan.id] = []);
|
||||
} else {
|
||||
result.push(undefined)
|
||||
result.push(undefined);
|
||||
}
|
||||
}
|
||||
return result
|
||||
})()
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve an item index by its ID from the given array of objects
|
||||
@ -594,23 +594,23 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* @returns {number} item index in the provided array
|
||||
*/
|
||||
var findItemIdxById = function (items, id) {
|
||||
return (items.map(function (item) { return item.id })).indexOf(id)
|
||||
}
|
||||
return (items.map(function (item) { return 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
|
||||
*/
|
||||
var groupCreditsByPlan = function (credits) {
|
||||
const creditsMap = {}
|
||||
const creditsMap = {};
|
||||
angular.forEach(credits, function (c) {
|
||||
if (!creditsMap[c.plan_id]) {
|
||||
creditsMap[c.plan_id] = []
|
||||
creditsMap[c.plan_id] = [];
|
||||
}
|
||||
return creditsMap[c.plan_id].push(c.creditable_id)
|
||||
})
|
||||
return creditsMap
|
||||
}
|
||||
return creditsMap[c.plan_id].push(c.creditable_id);
|
||||
});
|
||||
return creditsMap;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterate through $scope.traininfCredits to find the credit matching the given criterion
|
||||
@ -618,15 +618,15 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
* @param planId {number|string} plan ID
|
||||
*/
|
||||
var findTrainingCredit = function (trainingId, planId) {
|
||||
trainingId = parseInt(trainingId)
|
||||
planId = parseInt(planId)
|
||||
trainingId = parseInt(trainingId);
|
||||
planId = parseInt(planId);
|
||||
|
||||
for (let credit of Array.from($scope.trainingCredits)) {
|
||||
if ((credit.plan_id === planId) && (credit.creditable_id === trainingId)) {
|
||||
return credit
|
||||
return credit;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve a training from its given identifier and returns it
|
||||
@ -636,12 +636,12 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state',
|
||||
var getTrainingFromId = function (id) {
|
||||
for (let training of Array.from($scope.trainings)) {
|
||||
if (training.id === parseInt(id)) {
|
||||
return training
|
||||
return training;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -10,18 +10,18 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('ProjectElementsController', ['$scope', '$state', 'Component', 'Licence', 'Theme', 'componentsPromise', 'licencesPromise', 'themesPromise',
|
||||
function ($scope, $state, Component, Licence, Theme, componentsPromise, licencesPromise, themesPromise) {
|
||||
// Materials list (plastic, wood ...)
|
||||
$scope.components = componentsPromise
|
||||
$scope.components = componentsPromise;
|
||||
|
||||
// Licences list (Creative Common ...)
|
||||
$scope.licences = licencesPromise
|
||||
$scope.licences = licencesPromise;
|
||||
|
||||
// Themes list (cooking, sport ...)
|
||||
$scope.themes = themesPromise
|
||||
$scope.themes = themesPromise;
|
||||
|
||||
/**
|
||||
* Saves a new component / Update an existing material to the server (form validation callback)
|
||||
@ -30,29 +30,29 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
*/
|
||||
$scope.saveComponent = function (data, id) {
|
||||
if (id != null) {
|
||||
return Component.update({ id }, data)
|
||||
return Component.update({ id }, data);
|
||||
} else {
|
||||
return Component.save(data, resp => $scope.components[$scope.components.length - 1].id = resp.id)
|
||||
return Component.save(data, resp => $scope.components[$scope.components.length - 1].id = resp.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the component at the specified index
|
||||
* @param index {number} component index in the $scope.components array
|
||||
*/
|
||||
$scope.removeComponent = function (index) {
|
||||
Component.delete($scope.components[index])
|
||||
return $scope.components.splice(index, 1)
|
||||
}
|
||||
Component.delete($scope.components[index]);
|
||||
return $scope.components.splice(index, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new empty entry in the $scope.components array
|
||||
*/
|
||||
$scope.addComponent = function () {
|
||||
$scope.inserted =
|
||||
{ name: '' }
|
||||
return $scope.components.push($scope.inserted)
|
||||
}
|
||||
{ name: '' };
|
||||
return $scope.components.push($scope.inserted);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved component / Cancel the current component modification
|
||||
@ -61,11 +61,11 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
*/
|
||||
$scope.cancelComponent = function (rowform, index) {
|
||||
if ($scope.components[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.components.splice(index, 1)
|
||||
return $scope.components.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves a new theme / Update an existing theme to the server (form validation callback)
|
||||
@ -74,29 +74,29 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
*/
|
||||
$scope.saveTheme = function (data, id) {
|
||||
if (id != null) {
|
||||
return Theme.update({ id }, data)
|
||||
return Theme.update({ id }, data);
|
||||
} else {
|
||||
return Theme.save(data, resp => $scope.themes[$scope.themes.length - 1].id = resp.id)
|
||||
return Theme.save(data, resp => $scope.themes[$scope.themes.length - 1].id = resp.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the theme at the specified index
|
||||
* @param index {number} theme index in the $scope.themes array
|
||||
*/
|
||||
$scope.removeTheme = function (index) {
|
||||
Theme.delete($scope.themes[index])
|
||||
return $scope.themes.splice(index, 1)
|
||||
}
|
||||
Theme.delete($scope.themes[index]);
|
||||
return $scope.themes.splice(index, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new empty entry in the $scope.themes array
|
||||
*/
|
||||
$scope.addTheme = function () {
|
||||
$scope.inserted =
|
||||
{ name: '' }
|
||||
return $scope.themes.push($scope.inserted)
|
||||
}
|
||||
{ name: '' };
|
||||
return $scope.themes.push($scope.inserted);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved theme / Cancel the current theme modification
|
||||
@ -105,11 +105,11 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
*/
|
||||
$scope.cancelTheme = function (rowform, index) {
|
||||
if ($scope.themes[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.themes.splice(index, 1)
|
||||
return $scope.themes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves a new licence / Update an existing licence to the server (form validation callback)
|
||||
@ -118,20 +118,20 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
*/
|
||||
$scope.saveLicence = function (data, id) {
|
||||
if (id != null) {
|
||||
return Licence.update({ id }, data)
|
||||
return Licence.update({ id }, data);
|
||||
} else {
|
||||
return Licence.save(data, resp => $scope.licences[$scope.licences.length - 1].id = resp.id)
|
||||
return Licence.save(data, resp => $scope.licences[$scope.licences.length - 1].id = resp.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the licence at the specified index
|
||||
* @param index {number} licence index in the $scope.licences array
|
||||
*/
|
||||
$scope.removeLicence = function (index) {
|
||||
Licence.delete($scope.licences[index])
|
||||
return $scope.licences.splice(index, 1)
|
||||
}
|
||||
Licence.delete($scope.licences[index]);
|
||||
return $scope.licences.splice(index, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new empty entry in the $scope.licences array
|
||||
@ -140,9 +140,9 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
$scope.inserted = {
|
||||
name: '',
|
||||
description: ''
|
||||
}
|
||||
return $scope.licences.push($scope.inserted)
|
||||
}
|
||||
};
|
||||
return $scope.licences.push($scope.inserted);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved licence / Cancel the current licence modification
|
||||
@ -151,10 +151,10 @@ Application.Controllers.controller('ProjectElementsController', ['$scope', '$sta
|
||||
*/
|
||||
return $scope.cancelLicence = function (rowform, index) {
|
||||
if ($scope.licences[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.licences.splice(index, 1)
|
||||
return $scope.licences.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -10,7 +10,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('SettingsController', ['$scope', 'Setting', 'growl', 'settingsPromise', 'cgvFile', 'cguFile', 'logoFile', 'logoBlackFile', 'faviconFile', 'profileImageFile', 'CSRF', '_t',
|
||||
function ($scope, Setting, growl, settingsPromise, cgvFile, cguFile, logoFile, logoBlackFile, faviconFile, profileImageFile, CSRF, _t) {
|
||||
@ -20,7 +20,7 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
$scope.timepicker = {
|
||||
hstep: 1,
|
||||
mstep: 15
|
||||
}
|
||||
};
|
||||
|
||||
// API URL where the upload forms will be posted
|
||||
$scope.actionUrl = {
|
||||
@ -30,7 +30,7 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
logoBlack: '/api/custom_assets',
|
||||
favicon: '/api/custom_assets',
|
||||
profileImage: '/api/custom_assets'
|
||||
}
|
||||
};
|
||||
|
||||
// Form actions on the above URL
|
||||
$scope.methods = {
|
||||
@ -40,84 +40,84 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
logoBlack: 'post',
|
||||
favicon: 'post',
|
||||
profileImage: 'post'
|
||||
}
|
||||
};
|
||||
|
||||
// Are we uploading the files currently (if so, display the loader)
|
||||
$scope.loader = {
|
||||
cgu: false,
|
||||
cgv: false
|
||||
}
|
||||
};
|
||||
|
||||
// various parametrable settings
|
||||
$scope.twitterSetting = { name: 'twitter_name', value: settingsPromise.twitter_name }
|
||||
$scope.aboutTitleSetting = { name: 'about_title', value: settingsPromise.about_title }
|
||||
$scope.aboutBodySetting = { name: 'about_body', value: settingsPromise.about_body }
|
||||
$scope.aboutContactsSetting = { name: 'about_contacts', value: settingsPromise.about_contacts }
|
||||
$scope.homeBlogpostSetting = { name: 'home_blogpost', value: settingsPromise.home_blogpost }
|
||||
$scope.machineExplicationsAlert = { name: 'machine_explications_alert', value: settingsPromise.machine_explications_alert }
|
||||
$scope.trainingExplicationsAlert = { name: 'training_explications_alert', value: settingsPromise.training_explications_alert }
|
||||
$scope.trainingInformationMessage = { name: 'training_information_message', value: settingsPromise.training_information_message }
|
||||
$scope.subscriptionExplicationsAlert = { name: 'subscription_explications_alert', value: settingsPromise.subscription_explications_alert }
|
||||
$scope.eventExplicationsAlert = { name: 'event_explications_alert', value: settingsPromise.event_explications_alert }
|
||||
$scope.spaceExplicationsAlert = { name: 'space_explications_alert', value: settingsPromise.space_explications_alert }
|
||||
$scope.windowStart = { name: 'booking_window_start', value: settingsPromise.booking_window_start }
|
||||
$scope.windowEnd = { name: 'booking_window_end', value: settingsPromise.booking_window_end }
|
||||
$scope.mainColorSetting = { name: 'main_color', value: settingsPromise.main_color }
|
||||
$scope.secondColorSetting = { name: 'secondary_color', value: settingsPromise.secondary_color }
|
||||
$scope.fablabName = { name: 'fablab_name', value: settingsPromise.fablab_name }
|
||||
$scope.nameGenre = { name: 'name_genre', value: settingsPromise.name_genre }
|
||||
$scope.machinesSortBy = { name: 'machines_sort_by', value: settingsPromise.machines_sort_by }
|
||||
$scope.cguFile = cguFile.custom_asset
|
||||
$scope.cgvFile = cgvFile.custom_asset
|
||||
$scope.customLogo = logoFile.custom_asset
|
||||
$scope.customLogoBlack = logoBlackFile.custom_asset
|
||||
$scope.customFavicon = faviconFile.custom_asset
|
||||
$scope.profileImage = profileImageFile.custom_asset
|
||||
$scope.twitterSetting = { name: 'twitter_name', value: settingsPromise.twitter_name };
|
||||
$scope.aboutTitleSetting = { name: 'about_title', value: settingsPromise.about_title };
|
||||
$scope.aboutBodySetting = { name: 'about_body', value: settingsPromise.about_body };
|
||||
$scope.aboutContactsSetting = { name: 'about_contacts', value: settingsPromise.about_contacts };
|
||||
$scope.homeBlogpostSetting = { name: 'home_blogpost', value: settingsPromise.home_blogpost };
|
||||
$scope.machineExplicationsAlert = { name: 'machine_explications_alert', value: settingsPromise.machine_explications_alert };
|
||||
$scope.trainingExplicationsAlert = { name: 'training_explications_alert', value: settingsPromise.training_explications_alert };
|
||||
$scope.trainingInformationMessage = { name: 'training_information_message', value: settingsPromise.training_information_message };
|
||||
$scope.subscriptionExplicationsAlert = { name: 'subscription_explications_alert', value: settingsPromise.subscription_explications_alert };
|
||||
$scope.eventExplicationsAlert = { name: 'event_explications_alert', value: settingsPromise.event_explications_alert };
|
||||
$scope.spaceExplicationsAlert = { name: 'space_explications_alert', value: settingsPromise.space_explications_alert };
|
||||
$scope.windowStart = { name: 'booking_window_start', value: settingsPromise.booking_window_start };
|
||||
$scope.windowEnd = { name: 'booking_window_end', value: settingsPromise.booking_window_end };
|
||||
$scope.mainColorSetting = { name: 'main_color', value: settingsPromise.main_color };
|
||||
$scope.secondColorSetting = { name: 'secondary_color', value: settingsPromise.secondary_color };
|
||||
$scope.fablabName = { name: 'fablab_name', value: settingsPromise.fablab_name };
|
||||
$scope.nameGenre = { name: 'name_genre', value: settingsPromise.name_genre };
|
||||
$scope.machinesSortBy = { name: 'machines_sort_by', value: settingsPromise.machines_sort_by };
|
||||
$scope.cguFile = cguFile.custom_asset;
|
||||
$scope.cgvFile = cgvFile.custom_asset;
|
||||
$scope.customLogo = logoFile.custom_asset;
|
||||
$scope.customLogoBlack = logoBlackFile.custom_asset;
|
||||
$scope.customFavicon = faviconFile.custom_asset;
|
||||
$scope.profileImage = profileImageFile.custom_asset;
|
||||
|
||||
$scope.enableMove = {
|
||||
name: 'booking_move_enable',
|
||||
value: (settingsPromise.booking_move_enable === 'true')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.moveDelay = {
|
||||
name: 'booking_move_delay',
|
||||
value: parseInt(settingsPromise.booking_move_delay, 10)
|
||||
}
|
||||
};
|
||||
|
||||
$scope.enableCancel = {
|
||||
name: 'booking_cancel_enable',
|
||||
value: (settingsPromise.booking_cancel_enable === 'true')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.cancelDelay = {
|
||||
name: 'booking_cancel_delay',
|
||||
value: parseInt(settingsPromise.booking_cancel_delay, 10)
|
||||
}
|
||||
};
|
||||
|
||||
$scope.enableReminder = {
|
||||
name: 'reminder_enable',
|
||||
value: (settingsPromise.reminder_enable === 'true')
|
||||
}
|
||||
};
|
||||
|
||||
$scope.reminderDelay = {
|
||||
name: 'reminder_delay',
|
||||
value: parseInt(settingsPromise.reminder_delay, 10)
|
||||
}
|
||||
};
|
||||
|
||||
$scope.visibilityYearly = {
|
||||
name: 'visibility_yearly',
|
||||
value: parseInt(settingsPromise.visibility_yearly, 10)
|
||||
}
|
||||
};
|
||||
|
||||
$scope.visibilityOthers = {
|
||||
name: 'visibility_others',
|
||||
value: parseInt(settingsPromise.visibility_others, 10)
|
||||
}
|
||||
};
|
||||
|
||||
$scope.displayNameEnable = {
|
||||
name: 'display_name_enable',
|
||||
value: (settingsPromise.display_name_enable === 'true')
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -126,11 +126,11 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to save the setting value to the database
|
||||
@ -138,24 +138,24 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
*/
|
||||
$scope.save = function (setting) {
|
||||
// trim empty html
|
||||
let value
|
||||
let value;
|
||||
if ((setting.value === '<br>') || (setting.value === '<p><br></p>')) {
|
||||
setting.value = ''
|
||||
setting.value = '';
|
||||
}
|
||||
// convert dates to ISO format
|
||||
if (setting.value instanceof Date) {
|
||||
setting.value = setting.value.toISOString()
|
||||
setting.value = setting.value.toISOString();
|
||||
}
|
||||
|
||||
if (setting.value !== null) {
|
||||
value = setting.value.toString()
|
||||
value = setting.value.toString();
|
||||
} else {
|
||||
({ value } = setting)
|
||||
({ value } = setting);
|
||||
}
|
||||
|
||||
return Setting.update({ name: setting.name }, { value }, data => growl.success(_t('settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`settings.${setting.name}`) }))
|
||||
, error => console.log(error))
|
||||
}
|
||||
, error => console.log(error));
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
@ -165,46 +165,46 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.custom_asset == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
return angular.forEach(content, (v, k) =>
|
||||
angular.forEach(v, err => growl.error(err))
|
||||
)
|
||||
);
|
||||
} else {
|
||||
growl.success(_t('settings.file_successfully_updated'))
|
||||
growl.success(_t('settings.file_successfully_updated'));
|
||||
if (content.custom_asset.name === 'cgu-file') {
|
||||
$scope.cguFile = content.custom_asset
|
||||
$scope.methods.cgu = 'put'
|
||||
if (!($scope.actionUrl.cgu.indexOf('/cgu-file') > 0)) { $scope.actionUrl.cgu += '/cgu-file' }
|
||||
return $scope.loader.cgu = false
|
||||
$scope.cguFile = content.custom_asset;
|
||||
$scope.methods.cgu = 'put';
|
||||
if (!($scope.actionUrl.cgu.indexOf('/cgu-file') > 0)) { $scope.actionUrl.cgu += '/cgu-file'; }
|
||||
return $scope.loader.cgu = false;
|
||||
} else if (content.custom_asset.name === 'cgv-file') {
|
||||
$scope.cgvFile = content.custom_asset
|
||||
$scope.methods.cgv = 'put'
|
||||
if (!($scope.actionUrl.cgv.indexOf('/cgv-file') > 0)) { $scope.actionUrl.cgv += '/cgv-file' }
|
||||
return $scope.loader.cgv = false
|
||||
$scope.cgvFile = content.custom_asset;
|
||||
$scope.methods.cgv = 'put';
|
||||
if (!($scope.actionUrl.cgv.indexOf('/cgv-file') > 0)) { $scope.actionUrl.cgv += '/cgv-file'; }
|
||||
return $scope.loader.cgv = false;
|
||||
} else if (content.custom_asset.name === 'logo-file') {
|
||||
$scope.customLogo = content.custom_asset
|
||||
$scope.methods.logo = 'put'
|
||||
if (!($scope.actionUrl.logo.indexOf('/logo-file') > 0)) { return $scope.actionUrl.logo += '/logo-file' }
|
||||
$scope.customLogo = content.custom_asset;
|
||||
$scope.methods.logo = 'put';
|
||||
if (!($scope.actionUrl.logo.indexOf('/logo-file') > 0)) { return $scope.actionUrl.logo += '/logo-file'; }
|
||||
} else if (content.custom_asset.name === 'logo-black-file') {
|
||||
$scope.customLogoBlack = content.custom_asset
|
||||
$scope.methods.logoBlack = 'put'
|
||||
if (!($scope.actionUrl.logoBlack.indexOf('/logo-black-file') > 0)) { return $scope.actionUrl.logoBlack += '/logo-black-file' }
|
||||
$scope.customLogoBlack = content.custom_asset;
|
||||
$scope.methods.logoBlack = 'put';
|
||||
if (!($scope.actionUrl.logoBlack.indexOf('/logo-black-file') > 0)) { return $scope.actionUrl.logoBlack += '/logo-black-file'; }
|
||||
} else if (content.custom_asset.name === 'favicon-file') {
|
||||
$scope.customFavicon = content.custom_asset
|
||||
$scope.methods.favicon = 'put'
|
||||
if (!($scope.actionUrl.favicon.indexOf('/favicon-file') > 0)) { return $scope.actionUrl.favicon += '/favicon-file' }
|
||||
$scope.customFavicon = content.custom_asset;
|
||||
$scope.methods.favicon = 'put';
|
||||
if (!($scope.actionUrl.favicon.indexOf('/favicon-file') > 0)) { return $scope.actionUrl.favicon += '/favicon-file'; }
|
||||
} else if (content.custom_asset.name === 'profile-image-file') {
|
||||
$scope.profileImage = content.custom_asset
|
||||
$scope.methods.profileImage = 'put'
|
||||
if (!($scope.actionUrl.profileImage.indexOf('/profile-image-file') > 0)) { return $scope.actionUrl.profileImage += '/profile-image-file' }
|
||||
$scope.profileImage = content.custom_asset;
|
||||
$scope.methods.profileImage = 'put';
|
||||
if (!($scope.actionUrl.profileImage.indexOf('/profile-image-file') > 0)) { return $scope.actionUrl.profileImage += '/profile-image-file'; }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param target {String} 'cgu' | 'cgv'
|
||||
*/
|
||||
$scope.addLoader = target => $scope.loader[target] = true
|
||||
$scope.addLoader = target => $scope.loader[target] = true;
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -213,44 +213,44 @@ Application.Controllers.controller('SettingsController', ['$scope', 'Setting', '
|
||||
*/
|
||||
const initialize = function () {
|
||||
// set the authenticity tokens in the forms
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// we prevent the admin from setting the closing time before the opening time
|
||||
$scope.$watch('windowEnd.value', function (newValue, oldValue, scope) {
|
||||
if ($scope.windowStart && moment($scope.windowStart.value).isAfter(newValue)) {
|
||||
return $scope.windowEnd.value = oldValue
|
||||
return $scope.windowEnd.value = oldValue;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// change form methods to PUT if items already exists
|
||||
if (cguFile.custom_asset) {
|
||||
$scope.methods.cgu = 'put'
|
||||
$scope.actionUrl.cgu += '/cgu-file'
|
||||
$scope.methods.cgu = 'put';
|
||||
$scope.actionUrl.cgu += '/cgu-file';
|
||||
}
|
||||
if (cgvFile.custom_asset) {
|
||||
$scope.methods.cgv = 'put'
|
||||
$scope.actionUrl.cgv += '/cgv-file'
|
||||
$scope.methods.cgv = 'put';
|
||||
$scope.actionUrl.cgv += '/cgv-file';
|
||||
}
|
||||
if (logoFile.custom_asset) {
|
||||
$scope.methods.logo = 'put'
|
||||
$scope.actionUrl.logo += '/logo-file'
|
||||
$scope.methods.logo = 'put';
|
||||
$scope.actionUrl.logo += '/logo-file';
|
||||
}
|
||||
if (logoBlackFile.custom_asset) {
|
||||
$scope.methods.logoBlack = 'put'
|
||||
$scope.actionUrl.logoBlack += '/logo-black-file'
|
||||
$scope.methods.logoBlack = 'put';
|
||||
$scope.actionUrl.logoBlack += '/logo-black-file';
|
||||
}
|
||||
if (faviconFile.custom_asset) {
|
||||
$scope.methods.favicon = 'put'
|
||||
$scope.actionUrl.favicon += '/favicon-file'
|
||||
$scope.methods.favicon = 'put';
|
||||
$scope.actionUrl.favicon += '/favicon-file';
|
||||
}
|
||||
if (profileImageFile.custom_asset) {
|
||||
$scope.methods.profileImage = 'put'
|
||||
return $scope.actionUrl.profileImage += '/profile-image-file'
|
||||
$scope.methods.profileImage = 'put';
|
||||
return $scope.actionUrl.profileImage += '/profile-image-file';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// init the controller (call at the end !)
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -13,74 +13,74 @@
|
||||
* DS205: Consider reworking code to avoid use of IIFEs
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('StatisticsController', ['$scope', '$state', '$rootScope', '$uibModal', 'es', 'Member', '_t', 'membersPromise', 'statisticsPromise',
|
||||
function ($scope, $state, $rootScope, $uibModal, es, Member, _t, membersPromise, statisticsPromise) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// search window size
|
||||
const RESULTS_PER_PAGE = 20
|
||||
const RESULTS_PER_PAGE = 20;
|
||||
|
||||
// keep search context for (delay in minutes) ...
|
||||
const ES_SCROLL_TIME = 1
|
||||
const ES_SCROLL_TIME = 1;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// ui-view transitions optimization: if true, the stats will never be refreshed
|
||||
$scope.preventRefresh = false
|
||||
$scope.preventRefresh = false;
|
||||
|
||||
// statistics structure in elasticSearch
|
||||
$scope.statistics = statisticsPromise
|
||||
$scope.statistics = statisticsPromise;
|
||||
|
||||
// fablab users list
|
||||
$scope.members = membersPromise
|
||||
$scope.members = membersPromise;
|
||||
|
||||
// statistics data recovered from elasticSearch
|
||||
$scope.data = null
|
||||
$scope.data = null;
|
||||
|
||||
// when did the search was triggered
|
||||
$scope.searchDate = null
|
||||
$scope.searchDate = null;
|
||||
|
||||
// id of the elastic search context
|
||||
$scope.scrollId = null
|
||||
$scope.scrollId = null;
|
||||
|
||||
// total number of results for the current query
|
||||
$scope.totalHits = null
|
||||
$scope.totalHits = null;
|
||||
|
||||
// configuration of the widget allowing to pick the ages range
|
||||
$scope.agePicker = {
|
||||
show: false,
|
||||
start: null,
|
||||
end: null
|
||||
}
|
||||
};
|
||||
|
||||
// total CA for the current view
|
||||
$scope.sumCA = 0
|
||||
$scope.sumCA = 0;
|
||||
|
||||
// average users' age for the current view
|
||||
$scope.averageAge = 0
|
||||
$scope.averageAge = 0;
|
||||
|
||||
// total of the stat field for non simple types
|
||||
$scope.sumStat = 0
|
||||
$scope.sumStat = 0;
|
||||
|
||||
// Results of custom aggregations for the current type
|
||||
$scope.customAggs = {}
|
||||
$scope.customAggs = {};
|
||||
|
||||
// default: results are not sorted
|
||||
$scope.sorting = {
|
||||
ca: 'none',
|
||||
date: 'desc'
|
||||
}
|
||||
};
|
||||
|
||||
// active tab will be set here
|
||||
$scope.selectedIndex = null
|
||||
$scope.selectedIndex = null;
|
||||
|
||||
// type filter binding
|
||||
$scope.type = {
|
||||
selected: null,
|
||||
active: null
|
||||
}
|
||||
};
|
||||
|
||||
// selected custom filter
|
||||
$scope.customFilter = {
|
||||
@ -97,14 +97,14 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
startingDay: 1
|
||||
}
|
||||
} // France: the week starts on monday
|
||||
}
|
||||
};
|
||||
|
||||
// available custom filters
|
||||
$scope.filters = []
|
||||
$scope.filters = [];
|
||||
|
||||
// default: we do not open the datepicker menu
|
||||
$scope.datePicker =
|
||||
{ show: false }
|
||||
{ show: false };
|
||||
|
||||
// datePicker parameters for interval beginning
|
||||
$scope.datePickerStart = {
|
||||
@ -116,7 +116,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// datePicker parameters for interval ending
|
||||
$scope.datePickerEnd = {
|
||||
@ -128,25 +128,25 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval start)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleStartDatePicker = function ($event) { toggleDatePicker($event, $scope.datePickerStart) }
|
||||
$scope.toggleStartDatePicker = function ($event) { toggleDatePicker($event, $scope.datePickerStart); };
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval end)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleEndDatePicker = function ($event) { toggleDatePicker($event, $scope.datePickerEnd) }
|
||||
$scope.toggleEndDatePicker = function ($event) { toggleDatePicker($event, $scope.datePickerEnd); };
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (custom filter)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleCustomDatePicker = function ($event) { toggleDatePicker($event, $scope.customFilter.datePicker) }
|
||||
$scope.toggleCustomDatePicker = function ($event) { toggleDatePicker($event, $scope.customFilter.datePicker); };
|
||||
|
||||
/**
|
||||
* Callback called when the active tab is changed.
|
||||
@ -154,17 +154,17 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* @param tab {Object} elasticsearch statistic structure (from statistic_indices table)
|
||||
*/
|
||||
$scope.setActiveTab = function (tab) {
|
||||
$scope.selectedIndex = tab
|
||||
$scope.type.selected = tab.types[0]
|
||||
$scope.type.active = $scope.type.selected
|
||||
$scope.customFilter.criterion = {}
|
||||
$scope.customFilter.value = null
|
||||
$scope.customFilter.exclude = false
|
||||
$scope.sorting.ca = 'none'
|
||||
$scope.sorting.date = 'desc'
|
||||
buildCustomFiltersList()
|
||||
return refreshStats()
|
||||
}
|
||||
$scope.selectedIndex = tab;
|
||||
$scope.type.selected = tab.types[0];
|
||||
$scope.type.active = $scope.type.selected;
|
||||
$scope.customFilter.criterion = {};
|
||||
$scope.customFilter.value = null;
|
||||
$scope.customFilter.exclude = false;
|
||||
$scope.sorting.ca = 'none';
|
||||
$scope.sorting.date = 'desc';
|
||||
buildCustomFiltersList();
|
||||
return refreshStats();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the provided tab must be hidden due to some global or local configuration
|
||||
@ -173,41 +173,41 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
$scope.hiddenTab = function (tab) {
|
||||
if (tab.table) {
|
||||
if ((tab.es_type_key === 'subscription') && $rootScope.fablabWithoutPlans) {
|
||||
return true
|
||||
return true;
|
||||
} else if ((tab.es_type_key === 'space') && $rootScope.fablabWithoutSpaces) {
|
||||
return true
|
||||
return true;
|
||||
} else {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to validate the filters and send a new request to elastic
|
||||
*/
|
||||
$scope.validateFilterChange = function () {
|
||||
$scope.agePicker.show = false
|
||||
$scope.customFilter.show = false
|
||||
$scope.type.active = $scope.type.selected
|
||||
buildCustomFiltersList()
|
||||
return refreshStats()
|
||||
}
|
||||
$scope.agePicker.show = false;
|
||||
$scope.customFilter.show = false;
|
||||
$scope.type.active = $scope.type.selected;
|
||||
buildCustomFiltersList();
|
||||
return refreshStats();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to validate the dates range and refresh the data from elastic
|
||||
*/
|
||||
$scope.validateDateChange = function () {
|
||||
$scope.datePicker.show = false
|
||||
return refreshStats()
|
||||
}
|
||||
$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
|
||||
*/
|
||||
$scope.formatDate = function (date) { return moment(date).format('LL') }
|
||||
$scope.formatDate = function (date) { return moment(date).format('LL'); };
|
||||
|
||||
/**
|
||||
* Parse the sex and return a user-friendly string
|
||||
@ -215,26 +215,26 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.formatSex = function (sex) {
|
||||
if (sex === 'male') {
|
||||
return _t('man')
|
||||
return _t('man');
|
||||
}
|
||||
if (sex === 'female') {
|
||||
return _t('woman')
|
||||
return _t('woman');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the label for the given subtype in the current type
|
||||
* @param key {string} statistic subtype key
|
||||
*/
|
||||
$scope.formatSubtype = function (key) {
|
||||
let label = ''
|
||||
let label = '';
|
||||
angular.forEach($scope.type.active.subtypes, function (subtype) {
|
||||
if (subtype.key === key) {
|
||||
return label = subtype.label
|
||||
return label = subtype.label;
|
||||
}
|
||||
})
|
||||
return label
|
||||
}
|
||||
});
|
||||
return label;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper usable in ng-switch to determine the input type to display for custom filter value
|
||||
@ -243,14 +243,14 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
$scope.getCustomValueInputType = function (filter) {
|
||||
if (filter && filter.values) {
|
||||
if (typeof (filter.values[0]) === 'string') {
|
||||
return filter.values[0]
|
||||
return filter.values[0];
|
||||
} else if (typeof (filter.values[0] === 'object')) {
|
||||
return 'input_select'
|
||||
return 'input_select';
|
||||
}
|
||||
} else {
|
||||
return 'input_text'
|
||||
return 'input_text';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the sorting order and refresh the results to match the new order
|
||||
@ -258,21 +258,21 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
*/
|
||||
$scope.toggleSorting = function (filter) {
|
||||
switch ($scope.sorting[filter]) {
|
||||
case 'none': $scope.sorting[filter] = 'asc'; break
|
||||
case 'asc': $scope.sorting[filter] = 'desc'; break
|
||||
case 'desc': $scope.sorting[filter] = 'none'; break
|
||||
case 'none': $scope.sorting[filter] = 'asc'; break;
|
||||
case 'asc': $scope.sorting[filter] = 'desc'; break;
|
||||
case 'desc': $scope.sorting[filter] = 'none'; break;
|
||||
}
|
||||
return refreshStats()
|
||||
}
|
||||
return refreshStats();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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}`)
|
||||
}
|
||||
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.
|
||||
@ -281,12 +281,12 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
$scope.showMoreResults = function () {
|
||||
// if all results were retrieved, do nothing
|
||||
if ($scope.data.length >= $scope.totalHits) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (moment($scope.searchDate).add(ES_SCROLL_TIME, 'minutes').isBefore(moment())) {
|
||||
// elastic search context has expired, so we run again the whole query
|
||||
return refreshStats()
|
||||
return refreshStats();
|
||||
} else {
|
||||
return es.scroll({
|
||||
'scroll': ES_SCROLL_TIME + 'm',
|
||||
@ -294,14 +294,14 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
, function (error, response) {
|
||||
if (error) {
|
||||
return console.error(`Error: something unexpected occurred during elasticSearch scroll query: ${error}`)
|
||||
return console.error(`Error: something unexpected occurred during elasticSearch scroll query: ${error}`);
|
||||
} else {
|
||||
$scope.scrollId = response._scroll_id
|
||||
return $scope.data = $scope.data.concat(response.hits.hits)
|
||||
$scope.scrollId = response._scroll_id;
|
||||
return $scope.data = $scope.data.concat(response.hits.hits);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog asking the user for details about exporting the statistics tables to an excel file
|
||||
@ -316,24 +316,24 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
return {
|
||||
start: $scope.datePickerStart.selected,
|
||||
end: $scope.datePickerEnd.selected
|
||||
}
|
||||
};
|
||||
},
|
||||
query () {
|
||||
const custom = buildCustomFilterQuery()
|
||||
return buildElasticDataQuery($scope.type.active.key, custom, $scope.agePicker.start, $scope.agePicker.end, moment($scope.datePickerStart.selected), moment($scope.datePickerEnd.selected), $scope.sorting)
|
||||
const custom = buildCustomFilterQuery();
|
||||
return buildElasticDataQuery($scope.type.active.key, custom, $scope.agePicker.start, $scope.agePicker.end, moment($scope.datePickerStart.selected), moment($scope.datePickerEnd.selected), $scope.sorting);
|
||||
},
|
||||
index () {
|
||||
return { key: $scope.selectedIndex.es_type_key }
|
||||
return { key: $scope.selectedIndex.es_type_key };
|
||||
},
|
||||
type () {
|
||||
return { key: $scope.type.active.key }
|
||||
return { key: $scope.type.active.key };
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return $uibModal.open(options)
|
||||
.result['finally'](null).then(function (info) { console.log(info) })
|
||||
}
|
||||
.result['finally'](null).then(function (info) { console.log(info); });
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -345,10 +345,10 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
// which will cause every tabs to reload, one by one, when the view is closed
|
||||
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
|
||||
if ((fromState.name === 'app.admin.statistics') && (Object.keys(fromParams).length === 0)) {
|
||||
return $scope.preventRefresh = true
|
||||
return $scope.preventRefresh = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic function to toggle a bootstrap datePicker
|
||||
@ -356,45 +356,45 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
* @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
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return datePicker.opened = !datePicker.opened;
|
||||
};
|
||||
|
||||
/**
|
||||
* Force update the statistics table, querying elasticSearch according to the current config values
|
||||
*/
|
||||
var refreshStats = function () {
|
||||
if ($scope.selectedIndex && !$scope.preventRefresh) {
|
||||
$scope.data = []
|
||||
$scope.sumCA = 0
|
||||
$scope.averageAge = 0
|
||||
$scope.sumStat = 0
|
||||
$scope.customAggs = {}
|
||||
$scope.totalHits = null
|
||||
$scope.searchDate = new Date()
|
||||
let custom = buildCustomFilterQuery()
|
||||
$scope.data = [];
|
||||
$scope.sumCA = 0;
|
||||
$scope.averageAge = 0;
|
||||
$scope.sumStat = 0;
|
||||
$scope.customAggs = {};
|
||||
$scope.totalHits = null;
|
||||
$scope.searchDate = new Date();
|
||||
let custom = buildCustomFilterQuery();
|
||||
return queryElasticStats($scope.selectedIndex.es_type_key, $scope.type.active.key, custom, function (res, err) {
|
||||
if (err) {
|
||||
return console.error(`[statisticsController::refreshStats] Unable to refresh due to ${err}`)
|
||||
return console.error(`[statisticsController::refreshStats] Unable to refresh due to ${err}`);
|
||||
} else {
|
||||
$scope.data = res.hits.hits
|
||||
$scope.totalHits = res.hits.total
|
||||
$scope.sumCA = res.aggregations.total_ca.value
|
||||
$scope.averageAge = Math.round(res.aggregations.average_age.value * 100) / 100
|
||||
$scope.sumStat = res.aggregations.total_stat.value
|
||||
$scope.scrollId = res._scroll_id
|
||||
$scope.data = res.hits.hits;
|
||||
$scope.totalHits = res.hits.total;
|
||||
$scope.sumCA = res.aggregations.total_ca.value;
|
||||
$scope.averageAge = Math.round(res.aggregations.average_age.value * 100) / 100;
|
||||
$scope.sumStat = res.aggregations.total_stat.value;
|
||||
$scope.scrollId = res._scroll_id;
|
||||
return (function () {
|
||||
const result = []
|
||||
const result = [];
|
||||
for (custom of Array.from($scope.type.active.custom_aggregations)) {
|
||||
result.push($scope.customAggs[custom.field] = res.aggregations[custom.field].value)
|
||||
result.push($scope.customAggs[custom.field] = res.aggregations[custom.field].value);
|
||||
}
|
||||
return result
|
||||
})()
|
||||
return result;
|
||||
})();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the elasticSearch query to retreive the /stats/type aggregations
|
||||
@ -407,8 +407,8 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
var queryElasticStats = function (index, type, custom, callback) {
|
||||
// handle invalid callback
|
||||
if (typeof (callback) !== 'function') {
|
||||
console.error('[statisticsController::queryElasticStats] Error: invalid callback provided')
|
||||
return
|
||||
console.error('[statisticsController::queryElasticStats] Error: invalid callback provided');
|
||||
return;
|
||||
}
|
||||
|
||||
// run query
|
||||
@ -425,12 +425,12 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
}
|
||||
, function (error, response) {
|
||||
if (error) {
|
||||
return callback({}, `Error: something unexpected occurred during elasticSearch query: ${error}`)
|
||||
return callback({}, `Error: something unexpected occurred during elasticSearch query: ${error}`);
|
||||
} else {
|
||||
return callback(response)
|
||||
return callback(response);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Build an object representing the content of the REST-JSON query to elasticSearch,
|
||||
@ -464,7 +464,7 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// optional date range
|
||||
if ((typeof ageMin === 'number') && (typeof ageMax === 'number')) {
|
||||
q.query.bool.must.push({
|
||||
@ -474,22 +474,22 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
'lte': ageMax
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
// optional criterion
|
||||
if (custom) {
|
||||
const criterion = buildElasticCustomCriterion(custom)
|
||||
const criterion = buildElasticCustomCriterion(custom);
|
||||
if (custom.exclude) {
|
||||
q.query.bool.must_not = [
|
||||
{ 'term': criterion.match }
|
||||
]
|
||||
];
|
||||
} else {
|
||||
q.query.bool.must.push(criterion)
|
||||
q.query.bool.must.push(criterion);
|
||||
}
|
||||
}
|
||||
|
||||
if (sortings) {
|
||||
q['sort'] = buildElasticSortCriteria(sortings)
|
||||
q['sort'] = buildElasticSortCriteria(sortings);
|
||||
}
|
||||
|
||||
// aggregations (avg age & CA sum)
|
||||
@ -509,9 +509,9 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
'field': 'stat'
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
};
|
||||
return q;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build the elasticSearch query DSL to match the selected cutom filter
|
||||
@ -522,34 +522,34 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
if (custom) {
|
||||
const criterion = {
|
||||
'match': {}
|
||||
}
|
||||
};
|
||||
switch ($scope.getCustomValueInputType($scope.customFilter.criterion)) {
|
||||
case 'input_date': criterion.match[custom.key] = moment(custom.value).format('YYYY-MM-DD'); break
|
||||
case 'input_select': criterion.match[custom.key] = custom.value.key; break
|
||||
case 'input_list': criterion.match[custom.key + '.name'] = custom.value; break
|
||||
default: criterion.match[custom.key] = custom.value
|
||||
case 'input_date': criterion.match[custom.key] = moment(custom.value).format('YYYY-MM-DD'); break;
|
||||
case 'input_select': criterion.match[custom.key] = custom.value.key; break;
|
||||
case 'input_list': criterion.match[custom.key + '.name'] = custom.value; break;
|
||||
default: criterion.match[custom.key] = custom.value;
|
||||
}
|
||||
return criterion
|
||||
return criterion;
|
||||
} else {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 = []
|
||||
const crits = [];
|
||||
angular.forEach(criteria, function (value, key) {
|
||||
if ((typeof value !== 'undefined') && (value !== null) && (value !== 'none')) {
|
||||
const c = {}
|
||||
c[key] = { 'order': value }
|
||||
return crits.push(c)
|
||||
const c = {};
|
||||
c[key] = { 'order': value };
|
||||
return crits.push(c);
|
||||
}
|
||||
})
|
||||
return crits
|
||||
}
|
||||
});
|
||||
return crits;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fullfil the list of available options in the custom filter panel. The list will be based on common
|
||||
@ -563,76 +563,76 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state',
|
||||
{ key: 'age', label: _t('age'), values: ['input_number'] },
|
||||
{ key: 'subType', label: _t('type'), values: $scope.type.active.subtypes },
|
||||
{ key: 'ca', label: _t('revenue'), values: ['input_number'] }
|
||||
]
|
||||
];
|
||||
|
||||
if (!$scope.type.active.simple) {
|
||||
const f = { key: 'stat', label: $scope.type.active.label, values: ['input_number'] }
|
||||
$scope.filters.push(f)
|
||||
const f = { key: 'stat', label: $scope.type.active.label, values: ['input_number'] };
|
||||
$scope.filters.push(f);
|
||||
}
|
||||
|
||||
return angular.forEach($scope.selectedIndex.additional_fields, function (field) {
|
||||
const filter = { key: field.key, label: field.label, values: [] }
|
||||
const filter = { key: field.key, label: field.label, values: [] };
|
||||
switch (field.data_type) {
|
||||
case 'index': filter.values.push('input_number'); break
|
||||
case 'number': filter.values.push('input_number'); break
|
||||
case 'date': filter.values.push('input_date'); break
|
||||
case 'list': filter.values.push('input_list'); break
|
||||
default: filter.values.push('input_text')
|
||||
case 'index': filter.values.push('input_number'); break;
|
||||
case 'number': filter.values.push('input_number'); break;
|
||||
case 'date': filter.values.push('input_date'); break;
|
||||
case 'list': filter.values.push('input_list'); break;
|
||||
default: filter.values.push('input_text');
|
||||
}
|
||||
|
||||
return $scope.filters.push(filter)
|
||||
})
|
||||
}
|
||||
return $scope.filters.push(filter);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
let custom = null;
|
||||
if (!angular.isUndefinedOrNull($scope.customFilter.criterion) &&
|
||||
!angular.isUndefinedOrNull($scope.customFilter.criterion.key) &&
|
||||
!angular.isUndefinedOrNull($scope.customFilter.value)) {
|
||||
custom = {}
|
||||
custom.key = $scope.customFilter.criterion.key
|
||||
custom.value = $scope.customFilter.value
|
||||
custom.exclude = $scope.customFilter.exclude
|
||||
custom = {};
|
||||
custom.key = $scope.customFilter.criterion.key;
|
||||
custom.value = $scope.customFilter.value;
|
||||
custom.exclude = $scope.customFilter.exclude;
|
||||
}
|
||||
return custom
|
||||
}
|
||||
return custom;
|
||||
};
|
||||
|
||||
// init the controller (call at the end !)
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
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
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// Bindings for date range
|
||||
$scope.dates = dates
|
||||
$scope.dates = dates;
|
||||
|
||||
// Body of the query to export
|
||||
$scope.query = JSON.stringify(query)
|
||||
$scope.query = JSON.stringify(query);
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/stats/${index.key}/export`
|
||||
$scope.actionUrl = `/stats/${index.key}/export`;
|
||||
|
||||
// Key of the current search' statistic type
|
||||
$scope.typeKey = type.key
|
||||
$scope.typeKey = type.key;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// Anti-CSRF token to inject into the download form
|
||||
$scope.csrfToken = angular.element('meta[name="csrf-token"]')[0].content
|
||||
$scope.csrfToken = angular.element('meta[name="csrf-token"]')[0].content;
|
||||
|
||||
// Binding of the export type (global / current)
|
||||
$scope.export =
|
||||
{ type: 'current' }
|
||||
{ type: 'current' };
|
||||
|
||||
// datePicker parameters for interval beginning
|
||||
$scope.exportStart = {
|
||||
@ -643,7 +643,7 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// datePicker parameters for interval ending
|
||||
$scope.exportEnd = {
|
||||
@ -654,19 +654,19 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval start)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleStartDatePicker = function ($event) { $scope.exportStart.opened = !$scope.exportStart.opened }
|
||||
$scope.toggleStartDatePicker = function ($event) { $scope.exportStart.opened = !$scope.exportStart.opened; };
|
||||
|
||||
/**
|
||||
* Callback to open the datepicker (interval end)
|
||||
* @param $event {Object} jQuery event object
|
||||
*/
|
||||
$scope.toggleEndDatePicker = function ($event) { $scope.exportEnd.opened = !$scope.exportEnd.opened }
|
||||
$scope.toggleEndDatePicker = function ($event) { $scope.exportEnd.opened = !$scope.exportEnd.opened; };
|
||||
|
||||
/**
|
||||
* Callback when exchanging the export type between 'global' and 'current view'
|
||||
@ -674,7 +674,7 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
*/
|
||||
$scope.setRequest = function () {
|
||||
if ($scope.export.type === 'global') {
|
||||
$scope.actionUrl = '/stats/global/export'
|
||||
$scope.actionUrl = '/stats/global/export';
|
||||
return $scope.query = JSON.stringify({
|
||||
'query': {
|
||||
'bool': {
|
||||
@ -690,35 +690,35 @@ Application.Controllers.controller('ExportStatisticsController', [ '$scope', '$u
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
$scope.actionUrl = `/stats/${index.key}/export`
|
||||
$scope.query = JSON.stringify(query)
|
||||
$scope.actionUrl = `/stats/${index.key}/export`;
|
||||
$scope.query = JSON.stringify(query);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 }
|
||||
const statusQry = { category: 'statistics', type: $scope.export.type, query: $scope.query };
|
||||
if ($scope.export.type !== 'global') {
|
||||
statusQry['type'] = index.key
|
||||
statusQry['key'] = type.key
|
||||
statusQry['type'] = index.key;
|
||||
statusQry['key'] = type.key;
|
||||
}
|
||||
|
||||
Export.status(statusQry).then(function (res) {
|
||||
if (!res.data.exists) {
|
||||
return growl.success(_t('export_is_running_you_ll_be_notified_when_its_ready'))
|
||||
return growl.success(_t('export_is_running_you_ll_be_notified_when_its_ready'));
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return $uibModalInstance.close(statusQry)
|
||||
}
|
||||
return $uibModalInstance.close(statusQry);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to cancel the export and close the modal
|
||||
*/
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', 'Tag', 'growl', '_t', function ($scope, tagsPromise, Tag, growl, _t) {
|
||||
// List of users's tags
|
||||
$scope.tags = tagsPromise
|
||||
$scope.tags = tagsPromise;
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved tag / Cancel the current tag modification
|
||||
@ -22,20 +22,20 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
|
||||
*/
|
||||
$scope.cancelTag = function (rowform, index) {
|
||||
if ($scope.tags[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.tags.splice(index, 1)
|
||||
return $scope.tags.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new empty entry in the $scope.tags array
|
||||
*/
|
||||
$scope.addTag = function () {
|
||||
$scope.inserted =
|
||||
{ name: '' }
|
||||
return $scope.tags.push($scope.inserted)
|
||||
}
|
||||
{ name: '' };
|
||||
return $scope.tags.push($scope.inserted);
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves a new tag / Update an existing tag to the server (form validation callback)
|
||||
@ -45,18 +45,18 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
|
||||
$scope.saveTag = function (data, id) {
|
||||
if (id != null) {
|
||||
return Tag.update({ id }, { tag: data }, response => growl.success(_t('changes_successfully_saved'))
|
||||
, error => growl.error(_t('an_error_occurred_while_saving_changes')))
|
||||
, error => growl.error(_t('an_error_occurred_while_saving_changes')));
|
||||
} else {
|
||||
return Tag.save({ tag: data }, function (resp) {
|
||||
growl.success(_t('new_tag_successfully_saved'))
|
||||
return $scope.tags[$scope.tags.length - 1].id = resp.id
|
||||
growl.success(_t('new_tag_successfully_saved'));
|
||||
return $scope.tags[$scope.tags.length - 1].id = resp.id;
|
||||
}
|
||||
, function (error) {
|
||||
growl.error(_t('an_error_occurred_while_saving_the_new_tag'))
|
||||
return $scope.tags.splice($scope.tags.length - 1, 1)
|
||||
})
|
||||
growl.error(_t('an_error_occurred_while_saving_the_new_tag'));
|
||||
return $scope.tags.splice($scope.tags.length - 1, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the tag at the specified index
|
||||
@ -65,10 +65,10 @@ Application.Controllers.controller('TagsController', ['$scope', 'tagsPromise', '
|
||||
return $scope.removeTag = index =>
|
||||
// TODO add confirmation : les utilisateurs seront déasociés
|
||||
Tag.delete({ id: $scope.tags[index].id }, function (resp) {
|
||||
growl.success(_t('tag_successfully_deleted'))
|
||||
return $scope.tags.splice(index, 1)
|
||||
growl.success(_t('tag_successfully_deleted'));
|
||||
return $scope.tags.splice(index, 1);
|
||||
}
|
||||
, error => growl.error(_t('an_error_occurred_and_the_tag_deletion_failed')))
|
||||
, error => growl.error(_t('an_error_occurred_and_the_tag_deletion_failed')));
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -12,7 +12,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
@ -39,29 +39,29 @@ class TrainingsController {
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
return angular.forEach(content, function (v, k) {
|
||||
angular.forEach(v, function (err) {
|
||||
$scope.alerts.push({
|
||||
msg: k + ': ' + err,
|
||||
type: 'danger'
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return $state.go('app.admin.trainings')
|
||||
return $state.go('app.admin.trainings');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the current user's view, redirecting him to the machines list
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.admin.trainings') }
|
||||
$scope.cancel = function () { $state.go('app.admin.trainings'); };
|
||||
|
||||
/**
|
||||
* Force the 'public_page' attribute to false when the current training is disabled
|
||||
*/
|
||||
$scope.onDisableToggled = function () { $scope.training.public_page = !$scope.training.disabled }
|
||||
$scope.onDisableToggled = function () { $scope.training.public_page = !$scope.training.disabled; };
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -70,11 +70,11 @@ class TrainingsController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,13 +86,13 @@ Application.Controllers.controller('NewTrainingController', [ '$scope', '$state'
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Form action on the following URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/trainings/'
|
||||
$scope.actionUrl = '/api/trainings/';
|
||||
|
||||
// list of machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -100,16 +100,16 @@ Application.Controllers.controller('NewTrainingController', [ '$scope', '$state'
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// Using the TrainingsController
|
||||
return new TrainingsController($scope, $state)
|
||||
}
|
||||
return new TrainingsController($scope, $state);
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the training edition page (admin)
|
||||
@ -119,16 +119,16 @@ Application.Controllers.controller('EditTrainingController', [ '$scope', '$state
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Form action on the following URL
|
||||
$scope.method = 'patch'
|
||||
$scope.method = 'patch';
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/trainings/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/trainings/${$stateParams.id}`;
|
||||
|
||||
// Details of the training to edit (id in URL)
|
||||
$scope.training = trainingPromise
|
||||
$scope.training = trainingPromise;
|
||||
|
||||
// list of machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -136,16 +136,16 @@ Application.Controllers.controller('EditTrainingController', [ '$scope', '$state
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// Using the TrainingsController
|
||||
return new TrainingsController($scope, $state)
|
||||
}
|
||||
return new TrainingsController($scope, $state);
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the trainings management page, allowing admins users to see and manage the list of trainings and reservations.
|
||||
@ -155,34 +155,34 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// list of trainings
|
||||
let groupAvailabilities
|
||||
$scope.trainings = trainingsPromise
|
||||
let groupAvailabilities;
|
||||
$scope.trainings = trainingsPromise;
|
||||
|
||||
// simplified list of machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
// Training to monitor, binded with drop-down selection
|
||||
$scope.monitoring =
|
||||
{ training: null }
|
||||
{ training: null };
|
||||
|
||||
// list of training availabilies, grouped by date
|
||||
$scope.groupedAvailabilities = {}
|
||||
$scope.groupedAvailabilities = {};
|
||||
|
||||
// default: accordions are not open
|
||||
$scope.accordions = {}
|
||||
$scope.accordions = {};
|
||||
|
||||
// Binding for the parseInt function
|
||||
$scope.parseInt = parseInt
|
||||
$scope.parseInt = parseInt;
|
||||
|
||||
// Default: we show only enabled trainings
|
||||
$scope.trainingFiltering = 'enabled'
|
||||
$scope.trainingFiltering = 'enabled';
|
||||
|
||||
// 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
|
||||
@ -190,14 +190,14 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
* @returns {string}
|
||||
*/
|
||||
$scope.showMachines = function (training) {
|
||||
const selected = []
|
||||
const selected = [];
|
||||
angular.forEach($scope.machines, function (m) {
|
||||
if (training.machine_ids.indexOf(m.id) >= 0) {
|
||||
return selected.push(m.name)
|
||||
return selected.push(m.name);
|
||||
}
|
||||
})
|
||||
if (selected.length) { return selected.join(', ') } else { return _t('none') }
|
||||
}
|
||||
});
|
||||
if (selected.length) { return selected.join(', '); } else { return _t('none'); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the newly inserted but not saved training / Cancel the current training modification
|
||||
@ -206,11 +206,11 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
*/
|
||||
$scope.cancelTraining = function (rowform, index) {
|
||||
if ($scope.trainings[index].id != null) {
|
||||
return rowform.$cancel()
|
||||
return rowform.$cancel();
|
||||
} else {
|
||||
return $scope.trainings.splice(index, 1)
|
||||
return $scope.trainings.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* In the trainings monitoring tab, callback to open a modal window displaying the current bookings for the
|
||||
@ -223,47 +223,47 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "admin/trainings/validTrainingModal.html" %>',
|
||||
controller: ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {
|
||||
$scope.availability = availability
|
||||
$scope.availability = availability;
|
||||
|
||||
$scope.usersToValid = []
|
||||
$scope.usersToValid = [];
|
||||
|
||||
/**
|
||||
* 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)
|
||||
const index = $scope.usersToValid.indexOf(user);
|
||||
if (index > -1) {
|
||||
return $scope.usersToValid.splice(index, 1)
|
||||
return $scope.usersToValid.splice(index, 1);
|
||||
} else {
|
||||
return $scope.usersToValid.push(user)
|
||||
return $scope.usersToValid.push(user);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the modifications (training validations) and save them to the server
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
const users = $scope.usersToValid.map(function (u) { return u.id })
|
||||
const users = $scope.usersToValid.map(function (u) { return u.id; });
|
||||
return Training.update({ id: training.id }, {
|
||||
training: {
|
||||
users
|
||||
}
|
||||
}
|
||||
, function () { // success
|
||||
angular.forEach($scope.usersToValid, function (u) { u.is_valid = true })
|
||||
$scope.usersToValid = []
|
||||
return $uibModalInstance.close(training)
|
||||
})
|
||||
}
|
||||
angular.forEach($scope.usersToValid, function (u) { u.is_valid = true; });
|
||||
$scope.usersToValid = [];
|
||||
return $uibModalInstance.close(training);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the modifications and close the modal window
|
||||
*/
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
] })
|
||||
}
|
||||
] });
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the provided training and, in case of success, remove it from the trainings list afterwards
|
||||
@ -278,22 +278,22 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_training')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // deletion confirmed
|
||||
training.$delete(function () {
|
||||
$scope.trainings.splice(index, 1)
|
||||
growl.info(_t('training_successfully_deleted'))
|
||||
$scope.trainings.splice(index, 1);
|
||||
growl.info(_t('training_successfully_deleted'));
|
||||
},
|
||||
function (error) {
|
||||
growl.warning(_t('unable_to_delete_the_training_because_some_users_alredy_booked_it'))
|
||||
console.error(error)
|
||||
})
|
||||
growl.warning(_t('unable_to_delete_the_training_because_some_users_alredy_booked_it'));
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a month number and return its localized literal name
|
||||
@ -301,9 +301,9 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
* @returns {String} eg. 'janvier'
|
||||
*/
|
||||
$scope.formatMonth = function (number) {
|
||||
number = parseInt(number)
|
||||
return moment().month(number).format('MMMM')
|
||||
}
|
||||
number = parseInt(number);
|
||||
return moment().month(number).format('MMMM');
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a day, month and year, return a localized literal name for the day
|
||||
@ -313,12 +313,12 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
* @returns {String} eg. 'mercredi 12'
|
||||
*/
|
||||
$scope.formatDay = function (day, month, year) {
|
||||
day = parseInt(day)
|
||||
month = parseInt(month)
|
||||
year = parseInt(year)
|
||||
day = parseInt(day);
|
||||
month = parseInt(month);
|
||||
year = parseInt(year);
|
||||
|
||||
return moment({ year, month, day }).format('dddd D')
|
||||
}
|
||||
return moment({ year, month, day }).format('dddd D');
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback when the drop-down selection is changed.
|
||||
@ -326,14 +326,14 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
*/
|
||||
$scope.selectTrainingToMonitor = function () {
|
||||
Training.availabilities({ id: $scope.monitoring.training.id }, function (training) {
|
||||
$scope.groupedAvailabilities = groupAvailabilities([training])
|
||||
$scope.groupedAvailabilities = groupAvailabilities([training]);
|
||||
// we open current year/month by default
|
||||
const now = moment()
|
||||
$scope.accordions[training.name] = {}
|
||||
$scope.accordions[training.name][now.year()] = { isOpenFirst: true }
|
||||
$scope.accordions[training.name][now.year()][now.month()] = { isOpenFirst: true }
|
||||
})
|
||||
}
|
||||
const now = moment();
|
||||
$scope.accordions[training.name] = {};
|
||||
$scope.accordions[training.name][now.year()] = { isOpenFirst: true };
|
||||
$scope.accordions[training.name][now.year()][now.month()] = { isOpenFirst: true };
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -343,30 +343,30 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
* @returns {Object} Tree constructed as /training_name/year/month/day/[availabilities]
|
||||
*/
|
||||
return groupAvailabilities = function (trainings) {
|
||||
const tree = {}
|
||||
const tree = {};
|
||||
for (let training of Array.from(trainings)) {
|
||||
tree[training.name] = {}
|
||||
tree[training.name].training = training
|
||||
tree[training.name] = {};
|
||||
tree[training.name].training = training;
|
||||
for (let availability of Array.from(training.availabilities)) {
|
||||
const start = moment(availability.start_at)
|
||||
const start = moment(availability.start_at);
|
||||
|
||||
// init the tree structure
|
||||
if (typeof tree[training.name][start.year()] === 'undefined') {
|
||||
tree[training.name][start.year()] = {}
|
||||
tree[training.name][start.year()] = {};
|
||||
}
|
||||
if (typeof tree[training.name][start.year()][start.month()] === 'undefined') {
|
||||
tree[training.name][start.year()][start.month()] = {}
|
||||
tree[training.name][start.year()][start.month()] = {};
|
||||
}
|
||||
if (typeof tree[training.name][start.year()][start.month()][start.date()] === 'undefined') {
|
||||
tree[training.name][start.year()][start.month()][start.date()] = []
|
||||
tree[training.name][start.year()][start.month()][start.date()] = [];
|
||||
}
|
||||
|
||||
// add the availability at its right place
|
||||
tree[training.name][start.year()][start.month()][start.date()].push(availability)
|
||||
tree[training.name][start.year()][start.month()][start.date()].push(availability);
|
||||
}
|
||||
}
|
||||
return tree
|
||||
}
|
||||
return tree;
|
||||
};
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -10,7 +10,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in the public calendar global
|
||||
@ -19,40 +19,40 @@
|
||||
Application.Controllers.controller('CalendarController', ['$scope', '$state', '$aside', 'moment', 'Availability', 'Slot', 'Setting', 'growl', 'dialogs', 'bookingWindowStart', 'bookingWindowEnd', '_t', 'uiCalendarConfig', 'CalendarConfig', 'trainingsPromise', 'machinesPromise', 'spacesPromise',
|
||||
function ($scope, $state, $aside, moment, Availability, Slot, Setting, growl, dialogs, bookingWindowStart, bookingWindowEnd, _t, uiCalendarConfig, CalendarConfig, trainingsPromise, machinesPromise, spacesPromise) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
let currentMachineEvent = null
|
||||
machinesPromise.forEach(m => m.checked = true)
|
||||
trainingsPromise.forEach(t => t.checked = true)
|
||||
spacesPromise.forEach(s => s.checked = true)
|
||||
let currentMachineEvent = null;
|
||||
machinesPromise.forEach(m => m.checked = true);
|
||||
trainingsPromise.forEach(t => t.checked = true);
|
||||
spacesPromise.forEach(s => s.checked = true);
|
||||
|
||||
// check all formation/machine is select in filter
|
||||
const isSelectAll = (type, scope) => scope[type].length === scope[type].filter(t => t.checked).length
|
||||
const isSelectAll = (type, scope) => scope[type].length === scope[type].filter(t => t.checked).length;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// List of trainings
|
||||
$scope.trainings = trainingsPromise.filter(t => !t.disabled)
|
||||
$scope.trainings = trainingsPromise.filter(t => !t.disabled);
|
||||
|
||||
// List of machines
|
||||
$scope.machines = machinesPromise.filter(t => !t.disabled)
|
||||
$scope.machines = machinesPromise.filter(t => !t.disabled);
|
||||
|
||||
// List of spaces
|
||||
$scope.spaces = spacesPromise.filter(t => !t.disabled)
|
||||
$scope.spaces = spacesPromise.filter(t => !t.disabled);
|
||||
|
||||
// add availabilities source to event sources
|
||||
$scope.eventSources = []
|
||||
$scope.eventSources = [];
|
||||
|
||||
// filter availabilities if have change
|
||||
$scope.filterAvailabilities = function (filter, scope) {
|
||||
if (!scope) { scope = $scope }
|
||||
if (!scope) { scope = $scope; }
|
||||
scope.filter = ($scope.filter = {
|
||||
trainings: isSelectAll('trainings', scope),
|
||||
machines: isSelectAll('machines', scope),
|
||||
spaces: isSelectAll('spaces', scope),
|
||||
evt: filter.evt,
|
||||
dispo: filter.dispo
|
||||
})
|
||||
return $scope.calendarConfig.events = availabilitySourceUrl()
|
||||
}
|
||||
});
|
||||
return $scope.calendarConfig.events = availabilitySourceUrl();
|
||||
};
|
||||
|
||||
// a variable for formation/machine/event/dispo checkbox is or not checked
|
||||
$scope.filter = {
|
||||
@ -61,13 +61,13 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
spaces: isSelectAll('spaces', $scope),
|
||||
evt: true,
|
||||
dispo: true
|
||||
}
|
||||
};
|
||||
|
||||
// toggle to select all formation/machine
|
||||
$scope.toggleFilter = function (type, filter) {
|
||||
$scope[type].forEach(t => t.checked = filter[type])
|
||||
return $scope.filterAvailabilities(filter, $scope)
|
||||
}
|
||||
$scope[type].forEach(t => t.checked = filter[type]);
|
||||
return $scope.filterAvailabilities(filter, $scope);
|
||||
};
|
||||
|
||||
$scope.openFilterAside = () =>
|
||||
$aside.open({
|
||||
@ -77,112 +77,112 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
backdrop: false,
|
||||
resolve: {
|
||||
trainings () {
|
||||
return $scope.trainings
|
||||
return $scope.trainings;
|
||||
},
|
||||
machines () {
|
||||
return $scope.machines
|
||||
return $scope.machines;
|
||||
},
|
||||
spaces () {
|
||||
return $scope.spaces
|
||||
return $scope.spaces;
|
||||
},
|
||||
filter () {
|
||||
return $scope.filter
|
||||
return $scope.filter;
|
||||
},
|
||||
toggleFilter () {
|
||||
return $scope.toggleFilter
|
||||
return $scope.toggleFilter;
|
||||
},
|
||||
filterAvailabilities () {
|
||||
return $scope.filterAvailabilities
|
||||
return $scope.filterAvailabilities;
|
||||
}
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', 'trainings', 'machines', 'spaces', 'filter', 'toggleFilter', 'filterAvailabilities', function ($scope, $uibModalInstance, trainings, machines, spaces, filter, toggleFilter, filterAvailabilities) {
|
||||
$scope.trainings = trainings
|
||||
$scope.machines = machines
|
||||
$scope.spaces = spaces
|
||||
$scope.filter = filter
|
||||
$scope.trainings = trainings;
|
||||
$scope.machines = machines;
|
||||
$scope.spaces = spaces;
|
||||
$scope.filter = filter;
|
||||
|
||||
$scope.toggleFilter = (type, filter) => toggleFilter(type, filter)
|
||||
$scope.toggleFilter = (type, filter) => toggleFilter(type, filter);
|
||||
|
||||
$scope.filterAvailabilities = filter => filterAvailabilities(filter, $scope)
|
||||
$scope.filterAvailabilities = filter => filterAvailabilities(filter, $scope);
|
||||
|
||||
return $scope.close = function (e) {
|
||||
$uibModalInstance.dismiss()
|
||||
return e.stopPropagation()
|
||||
}
|
||||
$uibModalInstance.dismiss();
|
||||
return e.stopPropagation();
|
||||
};
|
||||
}
|
||||
] })
|
||||
] });
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
const calendarEventClickCb = function (event, jsEvent, view) {
|
||||
// current calendar object
|
||||
const { calendar } = uiCalendarConfig.calendars
|
||||
const { calendar } = uiCalendarConfig.calendars;
|
||||
if (event.available_type === 'machines') {
|
||||
currentMachineEvent = event
|
||||
calendar.fullCalendar('changeView', 'agendaDay')
|
||||
return calendar.fullCalendar('gotoDate', event.start)
|
||||
currentMachineEvent = event;
|
||||
calendar.fullCalendar('changeView', 'agendaDay');
|
||||
return calendar.fullCalendar('gotoDate', event.start);
|
||||
} else if (event.available_type === 'space') {
|
||||
calendar.fullCalendar('changeView', 'agendaDay')
|
||||
return calendar.fullCalendar('gotoDate', event.start)
|
||||
calendar.fullCalendar('changeView', 'agendaDay');
|
||||
return calendar.fullCalendar('gotoDate', event.start);
|
||||
} else if (event.available_type === 'event') {
|
||||
return $state.go('app.public.events_show', { id: event.event_id })
|
||||
return $state.go('app.public.events_show', { id: event.event_id });
|
||||
} else if (event.available_type === 'training') {
|
||||
return $state.go('app.public.training_show', { id: event.training_id })
|
||||
return $state.go('app.public.training_show', { id: event.training_id });
|
||||
} else {
|
||||
if (event.machine_id) {
|
||||
return $state.go('app.public.machines_show', { id: event.machine_id })
|
||||
return $state.go('app.public.machines_show', { id: event.machine_id });
|
||||
} else if (event.space_id) {
|
||||
return $state.go('app.public.space_show', { id: event.space_id })
|
||||
return $state.go('app.public.space_show', { id: event.space_id });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// agendaDay view: disable slotEventOverlap
|
||||
// agendaWeek view: enable slotEventOverlap
|
||||
const toggleSlotEventOverlap = function (view) {
|
||||
// set defaultView, because when we change slotEventOverlap
|
||||
// ui-calendar will trigger rerender calendar
|
||||
$scope.calendarConfig.defaultView = view.type
|
||||
const today = currentMachineEvent ? currentMachineEvent.start : moment().utc().startOf('day')
|
||||
$scope.calendarConfig.defaultView = view.type;
|
||||
const today = currentMachineEvent ? currentMachineEvent.start : moment().utc().startOf('day');
|
||||
if ((today > view.intervalStart) && (today < view.intervalEnd) && (today !== view.intervalStart)) {
|
||||
$scope.calendarConfig.defaultDate = today
|
||||
$scope.calendarConfig.defaultDate = today;
|
||||
} else {
|
||||
$scope.calendarConfig.defaultDate = view.intervalStart
|
||||
$scope.calendarConfig.defaultDate = view.intervalStart;
|
||||
}
|
||||
if (view.type === 'agendaDay') {
|
||||
return $scope.calendarConfig.slotEventOverlap = false
|
||||
return $scope.calendarConfig.slotEventOverlap = false;
|
||||
} else {
|
||||
return $scope.calendarConfig.slotEventOverlap = true
|
||||
return $scope.calendarConfig.slotEventOverlap = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// function is called when calendar view is rendered or changed
|
||||
const viewRenderCb = function (view, element) {
|
||||
toggleSlotEventOverlap(view)
|
||||
toggleSlotEventOverlap(view);
|
||||
if (view.type === 'agendaDay') {
|
||||
// get availabilties by 1 day for show machine slots
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const eventRenderCb = function (event, element) {
|
||||
if (event.tags.length > 0) {
|
||||
let html = ''
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
html += `<span class='label label-success text-white'>${tag.name}</span> `
|
||||
html += `<span class='label label-success text-white'>${tag.name}</span> `;
|
||||
}
|
||||
element.find('.fc-title').append(`<br/>${html}`)
|
||||
element.find('.fc-title').append(`<br/>${html}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getFilter = function () {
|
||||
const t = $scope.trainings.filter(t => t.checked).map(t => t.id)
|
||||
const m = $scope.machines.filter(m => m.checked).map(m => m.id)
|
||||
const s = $scope.spaces.filter(s => s.checked).map(s => s.id)
|
||||
return { t, m, s, evt: $scope.filter.evt, dispo: $scope.filter.dispo }
|
||||
}
|
||||
const t = $scope.trainings.filter(t => t.checked).map(t => t.id);
|
||||
const m = $scope.machines.filter(m => m.checked).map(m => m.id);
|
||||
const s = $scope.spaces.filter(s => s.checked).map(s => s.id);
|
||||
return { t, m, s, evt: $scope.filter.evt, dispo: $scope.filter.dispo };
|
||||
};
|
||||
|
||||
var availabilitySourceUrl = () => `/api/availabilities/public?${$.param(getFilter())}`
|
||||
var availabilitySourceUrl = () => `/api/availabilities/public?${$.param(getFilter())}`;
|
||||
|
||||
const initialize = () =>
|
||||
// fullCalendar (v2) configuration
|
||||
@ -198,17 +198,17 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$
|
||||
maxTime: moment.duration(moment(bookingWindowEnd.setting.value).format('HH:mm:ss')),
|
||||
defaultView: window.innerWidth <= 480 ? 'agendaDay' : 'agendaWeek',
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view)
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
viewRender (view, element) {
|
||||
return viewRenderCb(view, element)
|
||||
return viewRenderCb(view, element);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element)
|
||||
return eventRenderCb(event, element);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -10,24 +10,24 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('DashboardController', ['$scope', 'memberPromise', 'SocialNetworks', function ($scope, memberPromise, SocialNetworks) {
|
||||
// Current user's profile
|
||||
$scope.user = memberPromise
|
||||
$scope.user = memberPromise;
|
||||
|
||||
// List of social networks associated with this user and toggle 'show all' state
|
||||
$scope.social = {
|
||||
showAllLinks: false,
|
||||
networks: SocialNetworks
|
||||
}
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () => $scope.social.networks = filterNetworks()
|
||||
const initialize = () => $scope.social.networks = filterNetworks();
|
||||
|
||||
/**
|
||||
* Filter social network or website that are associated with the profile of the user provided in promise
|
||||
@ -35,17 +35,17 @@ Application.Controllers.controller('DashboardController', ['$scope', 'memberProm
|
||||
* @return {Array}
|
||||
*/
|
||||
var filterNetworks = function () {
|
||||
const networks = []
|
||||
const networks = [];
|
||||
for (let network of Array.from(SocialNetworks)) {
|
||||
if ($scope.user.profile[network] && ($scope.user.profile[network].length > 0)) {
|
||||
networks.push(network)
|
||||
networks.push(network);
|
||||
}
|
||||
}
|
||||
return networks
|
||||
}
|
||||
return networks;
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,36 +8,36 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', 'Twitter', 'lastMembersPromise', 'lastProjectsPromise', 'upcomingEventsPromise', 'homeBlogpostPromise', 'twitterNamePromise',
|
||||
function ($scope, $stateParams, Twitter, lastMembersPromise, lastProjectsPromise, upcomingEventsPromise, homeBlogpostPromise, twitterNamePromise) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// The last registered members who confirmed their addresses
|
||||
$scope.lastMembers = lastMembersPromise
|
||||
$scope.lastMembers = lastMembersPromise;
|
||||
|
||||
// The last tweets from the Fablab official twitter account
|
||||
$scope.lastTweets = []
|
||||
$scope.lastTweets = [];
|
||||
|
||||
// The last projects published/documented on the plateform
|
||||
$scope.lastProjects = lastProjectsPromise
|
||||
$scope.lastProjects = lastProjectsPromise;
|
||||
|
||||
// The closest upcoming events
|
||||
$scope.upcomingEvents = upcomingEventsPromise
|
||||
$scope.upcomingEvents = upcomingEventsPromise;
|
||||
|
||||
// The admin blogpost
|
||||
$scope.homeBlogpost = homeBlogpostPromise.setting.value
|
||||
$scope.homeBlogpost = homeBlogpostPromise.setting.value;
|
||||
|
||||
// Twitter username
|
||||
$scope.twitterName = twitterNamePromise.setting.value
|
||||
$scope.twitterName = twitterNamePromise.setting.value;
|
||||
|
||||
/**
|
||||
* Test if the provided event run on a single day or not
|
||||
* @param event {Object} single event from the $scope.upcomingEvents array
|
||||
* @returns {boolean} false if the event runs on more that 1 day
|
||||
*/
|
||||
$scope.isOneDayEvent = event => moment(event.start_date).isSame(event.end_date, 'day')
|
||||
$scope.isOneDayEvent = event => moment(event.start_date).isSame(event.end_date, 'day');
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -47,16 +47,16 @@ Application.Controllers.controller('HomeController', ['$scope', '$stateParams',
|
||||
const initialize = function () {
|
||||
// we retrieve tweets from here instead of ui-router's promise because, if adblock stop the API request,
|
||||
// this prevent the whole home page to be blocked
|
||||
$scope.lastTweets = Twitter.query({ limit: 1 })
|
||||
$scope.lastTweets = Twitter.query({ limit: 1 });
|
||||
|
||||
// if we recieve a token to reset the password as GET parameter, trigger the
|
||||
// changePassword modal from the parent controller
|
||||
if ($stateParams.reset_password_token) {
|
||||
return $scope.$parent.editPassword($stateParams.reset_password_token)
|
||||
return $scope.$parent.editPassword($stateParams.reset_password_token);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -12,7 +12,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
@ -41,24 +41,24 @@ class MachinesController {
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
angular.forEach(content, function (v, k) {
|
||||
angular.forEach(function (v, err) {
|
||||
$scope.alerts.push({
|
||||
msg: k + ': ' + err,
|
||||
type: 'danger'
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return $state.go('app.public.machines_list')
|
||||
return $state.go('app.public.machines_list');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the current user's view, redirecting him to the machines list
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.public.machines_list') }
|
||||
$scope.cancel = function () { $state.go('app.public.machines_list'); };
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -67,16 +67,16 @@ class MachinesController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This will create a single new empty entry into the machine attachements list.
|
||||
*/
|
||||
$scope.addFile = function () { $scope.machine.machine_files_attributes.push({}) }
|
||||
$scope.addFile = function () { $scope.machine.machine_files_attributes.push({}); };
|
||||
|
||||
/**
|
||||
* This will remove the given file from the machine attachements list. If the file was previously uploaded
|
||||
@ -85,13 +85,13 @@ class MachinesController {
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.machine.machine_files_attributes.indexOf(file)
|
||||
const index = $scope.machine.machine_files_attributes.indexOf(file);
|
||||
if (file.id != null) {
|
||||
return file._destroy = true
|
||||
return file._destroy = true;
|
||||
} else {
|
||||
return $scope.machine.machine_files_attributes.splice(index, 1)
|
||||
return $scope.machine.machine_files_attributes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,16 +104,16 @@ class MachinesController {
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
const _reserveMachine = function (machine, e) {
|
||||
const _this = this
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const _this = this;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// retrieve the full machine object
|
||||
return machine = _this.Machine.get({ id: machine.id }, function () {
|
||||
// if the currently logged'in user has completed the training for this machine, or this machine does not require
|
||||
// a prior training, just redirect him to the machine's booking page
|
||||
if (machine.current_user_is_training || (machine.trainings.length === 0)) {
|
||||
return _this.$state.go('app.logged.machines_reserve', { id: machine.slug })
|
||||
return _this.$state.go('app.logged.machines_reserve', { id: machine.slug });
|
||||
} else {
|
||||
// otherwise, if a user is authenticated ...
|
||||
if (_this.$scope.isAuthenticated()) {
|
||||
@ -123,59 +123,59 @@ const _reserveMachine = function (machine, e) {
|
||||
return _this.$uibModal.open({
|
||||
templateUrl: '<%= asset_path "machines/training_reservation_modal.html" %>',
|
||||
controller: ['$scope', '$uibModalInstance', '$state', function ($scope, $uibModalInstance, $state) {
|
||||
$scope.machine = machine
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.machine = machine;
|
||||
return $scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
] })
|
||||
] });
|
||||
// ... but does not have booked the training, tell him to register for a training session first
|
||||
// unless all associated trainings are disabled
|
||||
} else {
|
||||
// if all trainings are disabled, just redirect the user to the reservation calendar
|
||||
if (machine.trainings.map(function (t) { return t.disabled }).reduce(function (acc, val) { return acc && val }, true)) {
|
||||
return _this.$state.go('app.logged.machines_reserve', { id: machine.slug })
|
||||
if (machine.trainings.map(function (t) { return t.disabled; }).reduce(function (acc, val) { return acc && val; }, true)) {
|
||||
return _this.$state.go('app.logged.machines_reserve', { id: machine.slug });
|
||||
// otherwise open the information modal
|
||||
} else {
|
||||
return _this.$uibModal.open({
|
||||
templateUrl: '<%= asset_path "machines/request_training_modal.html" %>',
|
||||
controller: ['$scope', '$uibModalInstance', '$state', function ($scope, $uibModalInstance, $state) {
|
||||
$scope.machine = machine
|
||||
$scope.member = _this.$scope.currentUser
|
||||
$scope.machine = machine;
|
||||
$scope.member = _this.$scope.currentUser;
|
||||
|
||||
// transform the name of the trainings associated with the machine to integrate them in a sentence
|
||||
$scope.humanizeTrainings = function () {
|
||||
let text = ''
|
||||
let text = '';
|
||||
angular.forEach($scope.machine.trainings, function (training) {
|
||||
if (text.length > 0) {
|
||||
text += _this._t('machines_list._or_the_')
|
||||
text += _this._t('machines_list._or_the_');
|
||||
}
|
||||
return text += training.name.substr(0, 1).toLowerCase() + training.name.substr(1)
|
||||
})
|
||||
return text
|
||||
}
|
||||
return text += training.name.substr(0, 1).toLowerCase() + training.name.substr(1);
|
||||
});
|
||||
return text;
|
||||
};
|
||||
|
||||
// modal is closed with validation
|
||||
$scope.ok = function () {
|
||||
$state.go('app.logged.trainings_reserve', { id: $scope.machine.trainings[0].id })
|
||||
return $uibModalInstance.close(machine)
|
||||
}
|
||||
$state.go('app.logged.trainings_reserve', { id: $scope.machine.trainings[0].id });
|
||||
return $uibModalInstance.close(machine);
|
||||
};
|
||||
|
||||
// modal is closed with escaping
|
||||
return $scope.cancel = function (e) {
|
||||
e.preventDefault()
|
||||
return $uibModalInstance.dismiss('cancel')
|
||||
}
|
||||
e.preventDefault();
|
||||
return $uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
}
|
||||
] })
|
||||
] });
|
||||
}
|
||||
}
|
||||
|
||||
// if the user is not logged, open the login modal window
|
||||
} else {
|
||||
return _this.$scope.login()
|
||||
return _this.$scope.login();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Controller used in the public listing page, allowing everyone to see the list of machines
|
||||
@ -183,12 +183,12 @@ const _reserveMachine = function (machine, e) {
|
||||
Application.Controllers.controller('MachinesController', ['$scope', '$state', '_t', 'Machine', '$uibModal', 'machinesPromise',
|
||||
function ($scope, $state, _t, Machine, $uibModal, machinesPromise) {
|
||||
// Retrieve the list of machines
|
||||
$scope.machines = machinesPromise
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
/**
|
||||
* Redirect the user to the machine details page
|
||||
*/
|
||||
$scope.showMachine = function (machine) { $state.go('app.public.machines_show', { id: machine.slug }) }
|
||||
$scope.showMachine = function (machine) { $state.go('app.public.machines_show', { id: machine.slug }); };
|
||||
|
||||
/**
|
||||
* Callback to book a reservation for the current machine
|
||||
@ -199,40 +199,40 @@ Application.Controllers.controller('MachinesController', ['$scope', '$state', '_
|
||||
_t,
|
||||
$uibModal,
|
||||
Machine
|
||||
})
|
||||
});
|
||||
|
||||
// Default: we show only enabled machines
|
||||
$scope.machineFiltering = 'enabled'
|
||||
$scope.machineFiltering = 'enabled';
|
||||
|
||||
// Available options for filtering machines by status
|
||||
return $scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
]
|
||||
];
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the machine creation page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('NewMachineController', ['$scope', '$state', 'CSRF', function ($scope, $state, CSRF) {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/machines/'
|
||||
$scope.actionUrl = '/api/machines/';
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// default machine parameters
|
||||
$scope.machine =
|
||||
{ machine_files_attributes: [] }
|
||||
{ machine_files_attributes: [] };
|
||||
|
||||
// Using the MachinesController
|
||||
return new MachinesController($scope, $state)
|
||||
return new MachinesController($scope, $state);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the machine edition page (admin)
|
||||
@ -242,13 +242,13 @@ Application.Controllers.controller('EditMachineController', ['$scope', '$state',
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/machines/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/machines/${$stateParams.id}`;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
$scope.method = 'put';
|
||||
|
||||
// Retrieve the details for the machine id in the URL, if an error occurs redirect the user to the machines list
|
||||
$scope.machine = machinePromise
|
||||
$scope.machine = machinePromise;
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -256,16 +256,16 @@ Application.Controllers.controller('EditMachineController', ['$scope', '$state',
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// Using the MachinesController
|
||||
return new MachinesController($scope, $state)
|
||||
}
|
||||
return new MachinesController($scope, $state);
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the machine details page (public)
|
||||
@ -273,7 +273,7 @@ Application.Controllers.controller('EditMachineController', ['$scope', '$state',
|
||||
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
|
||||
$scope.machine = machinePromise
|
||||
$scope.machine = machinePromise;
|
||||
|
||||
/**
|
||||
* Callback to delete the current machine (admins only)
|
||||
@ -281,7 +281,7 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
$scope.delete = function (machine) {
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
console.error(_t('unauthorized_operation'))
|
||||
console.error(_t('unauthorized_operation'));
|
||||
} else {
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
@ -289,19 +289,19 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_machine')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () { // deletion confirmed
|
||||
// delete the machine then redirect to the machines listing
|
||||
machine.$delete(
|
||||
function () { $state.go('app.public.machines_list') },
|
||||
function (error) { growl.warning(_t('the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users')); console.error(error) }
|
||||
)
|
||||
})
|
||||
function () { $state.go('app.public.machines_list'); },
|
||||
function (error) { growl.warning(_t('the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users')); console.error(error); }
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to book a reservation for the current machine
|
||||
@ -312,9 +312,9 @@ Application.Controllers.controller('ShowMachineController', ['$scope', '$state',
|
||||
_t,
|
||||
$uibModal,
|
||||
Machine
|
||||
})
|
||||
});
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used in the machine reservation page (for logged users who have completed the training and admins).
|
||||
@ -326,27 +326,27 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// Slot free to be booked
|
||||
const FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::MACHINE_COLOR %>'
|
||||
const FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::MACHINE_COLOR %>';
|
||||
|
||||
// Slot already booked by another user
|
||||
const UNAVAILABLE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::MACHINE_IS_RESERVED_BY_USER %>'
|
||||
const UNAVAILABLE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::MACHINE_IS_RESERVED_BY_USER %>';
|
||||
|
||||
// Slot already booked by the current user
|
||||
const BOOKED_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::IS_RESERVED_BY_CURRENT_USER %>'
|
||||
const BOOKED_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::IS_RESERVED_BY_CURRENT_USER %>';
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// bind the machine availabilities with full-Calendar events
|
||||
$scope.eventSources = []
|
||||
$scope.eventSources = [];
|
||||
|
||||
// indicates the state of the current view : calendar or plans information
|
||||
$scope.plansAreShown = false
|
||||
$scope.plansAreShown = false;
|
||||
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
|
||||
// the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.planSelectionTime = null
|
||||
$scope.planSelectionTime = null;
|
||||
|
||||
// mapping of fullCalendar events.
|
||||
$scope.events = {
|
||||
@ -355,165 +355,165 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
placable: null, // Destination slot for the change
|
||||
paid: [], // Slots that were just booked by the user (transaction ok)
|
||||
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
|
||||
$scope.selectionTime = null
|
||||
$scope.selectionTime = null;
|
||||
|
||||
// the last clicked event in the calender
|
||||
$scope.selectedEvent = null
|
||||
$scope.selectedEvent = null;
|
||||
|
||||
// the application global settings
|
||||
$scope.settings = settingsPromise
|
||||
$scope.settings = settingsPromise;
|
||||
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
$scope.plansClassifiedByGroup = [];
|
||||
for (let group of Array.from(groupsPromise)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] };
|
||||
for (let plan of Array.from(plansPromise)) {
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan) }
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan); }
|
||||
}
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
$scope.plansClassifiedByGroup.push(groupObj);
|
||||
}
|
||||
|
||||
// the user to deal with, ie. the current user for non-admins
|
||||
$scope.ctrl =
|
||||
{ member: {} }
|
||||
{ member: {} };
|
||||
|
||||
// current machine to reserve
|
||||
$scope.machine = machinePromise
|
||||
$scope.machine = machinePromise;
|
||||
|
||||
// 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')),
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view)
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element)
|
||||
return eventRenderCb(event, element);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Global config: message to the end user concerning the subscriptions rules
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert;
|
||||
|
||||
// Global config: message to the end user concerning the machine bookings
|
||||
$scope.machineExplicationsAlert = settingsPromise.machine_explications_alert
|
||||
$scope.machineExplicationsAlert = settingsPromise.machine_explications_alert;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
$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'
|
||||
*/
|
||||
$scope.markSlotAsRemoved = function (slot) {
|
||||
slot.backgroundColor = 'white'
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
slot.title = ''
|
||||
slot.isValid = false
|
||||
slot.id = null
|
||||
slot.is_reserved = false
|
||||
slot.can_modify = false
|
||||
slot.offered = false
|
||||
return updateCalendar()
|
||||
}
|
||||
slot.backgroundColor = 'white';
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR;
|
||||
slot.title = '';
|
||||
slot.isValid = false;
|
||||
slot.id = null;
|
||||
slot.is_reserved = false;
|
||||
slot.can_modify = false;
|
||||
slot.offered = false;
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
*/
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent) }
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent); };
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
$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'
|
||||
*/
|
||||
$scope.changeModifyMachineSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
$scope.events.placable.title = ''
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = '';
|
||||
}
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
|
||||
$scope.selectedEvent.backgroundColor = '#bbb'
|
||||
$scope.selectedEvent.title = _t('i_shift')
|
||||
$scope.selectedEvent.backgroundColor = '#bbb';
|
||||
$scope.selectedEvent.title = _t('i_shift');
|
||||
}
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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'
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor
|
||||
$scope.events.placable.id = $scope.events.modifiable.id
|
||||
$scope.events.placable.is_reserved = true
|
||||
$scope.events.placable.can_modify = true
|
||||
$scope.events.placable.title = $scope.currentUser.role !== 'admin' ? _t('i_ve_reserved') : _t('not_available');
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor;
|
||||
$scope.events.placable.id = $scope.events.modifiable.id;
|
||||
$scope.events.placable.is_reserved = true;
|
||||
$scope.events.placable.can_modify = true;
|
||||
|
||||
$scope.events.modifiable.backgroundColor = 'white'
|
||||
$scope.events.modifiable.title = ''
|
||||
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
$scope.events.modifiable.id = null
|
||||
$scope.events.modifiable.is_reserved = false
|
||||
$scope.events.modifiable.can_modify = false
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
$scope.events.modifiable.title = '';
|
||||
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR;
|
||||
$scope.events.modifiable.id = null;
|
||||
$scope.events.modifiable.is_reserved = false;
|
||||
$scope.events.modifiable.can_modify = false;
|
||||
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
*/
|
||||
$scope.cancelModifyMachineSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
$scope.events.placable.title = ''
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = '';
|
||||
}
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? _t('i_ve_reserved') : _t('not_available')
|
||||
$scope.events.modifiable.backgroundColor = 'white'
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? _t('i_ve_reserved') : _t('not_available');
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
|
||||
return updateCalendar()
|
||||
}
|
||||
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)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
Member.get({ id: $scope.ctrl.member.id }, function (member) { $scope.ctrl.member = member })
|
||||
}
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectedPlan = null;
|
||||
Member.get({ id: $scope.ctrl.member.id }, function (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-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
e.preventDefault()
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectPlan($scope.selectedPlan)
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
e.preventDefault();
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectPlan($scope.selectedPlan);
|
||||
return $scope.planSelectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = function () { $scope.plansAreShown = true }
|
||||
$scope.showPlans = function () { $scope.plansAreShown = true; };
|
||||
|
||||
/**
|
||||
* Add the provided plan to the current shopping cart
|
||||
@ -522,12 +522,12 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
$scope.selectPlan = function (plan) {
|
||||
// toggle selected plan
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
$scope.selectedPlan = plan
|
||||
$scope.selectedPlan = plan;
|
||||
} else {
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
return $scope.planSelectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Once the reservation is booked (payment process successfully completed), change the event style
|
||||
@ -536,34 +536,34 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
*/
|
||||
$scope.afterPayment = function (reservation) {
|
||||
angular.forEach($scope.events.reserved, function (machineSlot, key) {
|
||||
machineSlot.is_reserved = true
|
||||
machineSlot.can_modify = true
|
||||
machineSlot.is_reserved = true;
|
||||
machineSlot.can_modify = true;
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
machineSlot.title = _t('i_ve_reserved')
|
||||
machineSlot.borderColor = BOOKED_SLOT_BORDER_COLOR
|
||||
updateMachineSlot(machineSlot, reservation, $scope.currentUser)
|
||||
machineSlot.title = _t('i_ve_reserved');
|
||||
machineSlot.borderColor = BOOKED_SLOT_BORDER_COLOR;
|
||||
updateMachineSlot(machineSlot, reservation, $scope.currentUser);
|
||||
} else {
|
||||
machineSlot.title = _t('not_available')
|
||||
machineSlot.borderColor = UNAVAILABLE_SLOT_BORDER_COLOR
|
||||
updateMachineSlot(machineSlot, reservation, $scope.ctrl.member)
|
||||
machineSlot.title = _t('not_available');
|
||||
machineSlot.borderColor = UNAVAILABLE_SLOT_BORDER_COLOR;
|
||||
updateMachineSlot(machineSlot, reservation, $scope.ctrl.member);
|
||||
}
|
||||
return machineSlot.backgroundColor = 'white'
|
||||
})
|
||||
return machineSlot.backgroundColor = 'white';
|
||||
});
|
||||
|
||||
if ($scope.selectedPlan) {
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
|
||||
return refetchCalendar()
|
||||
}
|
||||
return refetchCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled }
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled; };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -575,13 +575,13 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
$scope.eventSources.push({
|
||||
events: availabilities,
|
||||
textColor: 'black'
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return $scope.ctrl.member = $scope.currentUser
|
||||
return $scope.ctrl.member = $scope.currentUser;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when the user click on a reservation slot in the agenda.
|
||||
@ -590,9 +590,9 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
* if it's too late).
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.selectedEvent = event
|
||||
return $scope.selectionTime = new Date()
|
||||
}
|
||||
$scope.selectedEvent = event;
|
||||
return $scope.selectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
@ -601,13 +601,13 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
*/
|
||||
var eventRenderCb = function (event, element) {
|
||||
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
|
||||
let html = ''
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
html += `<span class='label label-success text-white' title='${tag.name}'>${tag.name}</span>`
|
||||
html += `<span class='label label-success text-white' title='${tag.name}'>${tag.name}</span>`;
|
||||
}
|
||||
element.find('.fc-time').append(html)
|
||||
element.find('.fc-time').append(html);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
@ -620,28 +620,28 @@ Application.Controllers.controller('ReserveMachineController', ['$scope', '$stat
|
||||
var updateMachineSlot = function (slot, reservation, user) {
|
||||
angular.forEach(reservation.slots, function (s) {
|
||||
if (slot.start.isSame(s.start_at)) {
|
||||
slot.id = s.id
|
||||
return slot.user = user
|
||||
slot.id = s.id;
|
||||
return slot.user = user;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the calendar's display to render the new attributes of the events
|
||||
*/
|
||||
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents') }
|
||||
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents'); };
|
||||
|
||||
/**
|
||||
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
*/
|
||||
var refetchCalendar = function () {
|
||||
$timeout(function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
})
|
||||
}
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents');
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Navigation controller. List the links availables in the left navigation pane and their icon.
|
||||
@ -48,14 +48,14 @@ Application.Controllers.controller('MainNavController', ['$scope', '$location',
|
||||
linkIcon: 'th'
|
||||
}
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
if (!Fablab.withoutPlans) {
|
||||
$scope.navLinks.push({
|
||||
state: 'app.public.plans',
|
||||
linkText: 'subscriptions',
|
||||
linkIcon: 'credit-card'
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (!Fablab.withoutSpaces) {
|
||||
@ -63,10 +63,10 @@ Application.Controllers.controller('MainNavController', ['$scope', '$location',
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'reserve_a_space',
|
||||
linkIcon: 'rocket'
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
Fablab.adminNavLinks = Fablab.adminNavLinks || []
|
||||
Fablab.adminNavLinks = Fablab.adminNavLinks || [];
|
||||
const adminNavLinks = [
|
||||
{
|
||||
state: 'app.admin.trainings',
|
||||
@ -123,16 +123,16 @@ Application.Controllers.controller('MainNavController', ['$scope', '$location',
|
||||
linkText: 'open_api_clients',
|
||||
linkIcon: 'cloud'
|
||||
}
|
||||
].concat(Fablab.adminNavLinks)
|
||||
].concat(Fablab.adminNavLinks);
|
||||
|
||||
$scope.adminNavLinks = adminNavLinks
|
||||
$scope.adminNavLinks = adminNavLinks;
|
||||
|
||||
if (!Fablab.withoutSpaces) {
|
||||
return $scope.adminNavLinks.splice(7, 0, {
|
||||
state: 'app.public.spaces_list',
|
||||
linkText: 'manage_the_spaces',
|
||||
linkIcon: 'rocket'
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -11,7 +11,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in the members listing page
|
||||
@ -20,37 +20,37 @@ Application.Controllers.controller('MembersController', ['$scope', 'Member', 'me
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// number of invoices loaded each time we click on 'load more...'
|
||||
const MEMBERS_PER_PAGE = 10
|
||||
const MEMBERS_PER_PAGE = 10;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// currently displayed page of members
|
||||
$scope.page = 1
|
||||
$scope.page = 1;
|
||||
|
||||
// members list
|
||||
$scope.members = membersPromise
|
||||
$scope.members = membersPromise;
|
||||
|
||||
// true when all members are loaded
|
||||
$scope.noMoreResults = false
|
||||
$scope.noMoreResults = false;
|
||||
|
||||
/**
|
||||
* Callback for the 'load more' button.
|
||||
* Will load the next results of the current search, if any
|
||||
*/
|
||||
$scope.showNextMembers = function () {
|
||||
$scope.page += 1
|
||||
$scope.page += 1;
|
||||
return Member.query({
|
||||
requested_attributes: '[profile]',
|
||||
page: $scope.page,
|
||||
size: MEMBERS_PER_PAGE
|
||||
}, function (members) {
|
||||
$scope.members = $scope.members.concat(members)
|
||||
$scope.members = $scope.members.concat(members);
|
||||
|
||||
if (!members[0] || (members[0].maxMembers <= $scope.members.length)) {
|
||||
return $scope.noMoreResults = true
|
||||
return $scope.noMoreResults = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -59,15 +59,15 @@ Application.Controllers.controller('MembersController', ['$scope', 'Member', 'me
|
||||
*/
|
||||
const initialize = function () {
|
||||
if (!membersPromise[0] || (membersPromise[0].maxMembers <= $scope.members.length)) {
|
||||
return $scope.noMoreResults = true
|
||||
return $scope.noMoreResults = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used when editing the current user's profile
|
||||
@ -77,36 +77,36 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/members/${$scope.currentUser.id}`
|
||||
$scope.actionUrl = `/api/members/${$scope.currentUser.id}`;
|
||||
|
||||
// list of groups
|
||||
$scope.groups = groups.filter(g => !g.disabled)
|
||||
$scope.groups = groups.filter(g => !g.disabled);
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'patch'
|
||||
$scope.method = 'patch';
|
||||
|
||||
// Current user's profile
|
||||
$scope.user = memberPromise
|
||||
$scope.user = memberPromise;
|
||||
|
||||
// default : do not show the group changing form
|
||||
$scope.group =
|
||||
{ change: false }
|
||||
{ change: false };
|
||||
|
||||
// group ID of the current/selected user
|
||||
$scope.userGroup = memberPromise.group_id
|
||||
$scope.userGroup = memberPromise.group_id;
|
||||
|
||||
// active authentication provider parameters
|
||||
$scope.activeProvider = activeProviderPromise
|
||||
$scope.activeProvider = activeProviderPromise;
|
||||
|
||||
// allow the user to change his password except if he connect from an SSO
|
||||
$scope.preventPassword = false
|
||||
$scope.preventPassword = false;
|
||||
|
||||
// mapping of fields to disable
|
||||
$scope.preventField = {}
|
||||
$scope.preventField = {};
|
||||
|
||||
// Should the passord be modified?
|
||||
$scope.password =
|
||||
{ change: false }
|
||||
{ change: false };
|
||||
|
||||
// Angular-Bootstrap datepicker configuration for birthday
|
||||
$scope.datePicker = {
|
||||
@ -115,7 +115,7 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the group object, identified by the ID set in $scope.userGroup
|
||||
@ -123,36 +123,36 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
$scope.getUserGroup = function () {
|
||||
for (let group of Array.from($scope.groups)) {
|
||||
if (group.id === $scope.userGroup) {
|
||||
return group
|
||||
return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the group of the current user to the one set in $scope.userGroup
|
||||
*/
|
||||
$scope.selectGroup = () =>
|
||||
Member.update({ id: $scope.user.id }, { user: { group_id: $scope.userGroup } }, function (user) {
|
||||
$scope.user = user
|
||||
$rootScope.currentUser = user
|
||||
Auth._currentUser.group_id = user.group_id
|
||||
$scope.group.change = false
|
||||
return growl.success(_t('your_group_has_been_successfully_changed'))
|
||||
$scope.user = user;
|
||||
$rootScope.currentUser = user;
|
||||
Auth._currentUser.group_id = user.group_id;
|
||||
$scope.group.change = false;
|
||||
return growl.success(_t('your_group_has_been_successfully_changed'));
|
||||
}
|
||||
, function (err) {
|
||||
growl.error(_t('an_unexpected_error_prevented_your_group_from_being_changed'))
|
||||
return console.error(err)
|
||||
})
|
||||
growl.error(_t('an_unexpected_error_prevented_your_group_from_being_changed'));
|
||||
return console.error(err);
|
||||
});
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
@ -163,7 +163,7 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
return angular.forEach(content, (v, k) =>
|
||||
angular.forEach(v, err =>
|
||||
$scope.alerts.push({
|
||||
@ -171,18 +171,18 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
type: 'danger'
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$scope.currentUser.profile.user_avatar = content.profile.user_avatar
|
||||
Auth._currentUser.profile.user_avatar = content.profile.user_avatar
|
||||
$scope.currentUser.name = content.name
|
||||
Auth._currentUser.name = content.name
|
||||
$scope.currentUser = content
|
||||
Auth._currentUser = content
|
||||
$rootScope.currentUser = content
|
||||
return $state.go('app.public.home')
|
||||
$scope.currentUser.profile.user_avatar = content.profile.user_avatar;
|
||||
Auth._currentUser.profile.user_avatar = content.profile.user_avatar;
|
||||
$scope.currentUser.name = content.name;
|
||||
Auth._currentUser.name = content.name;
|
||||
$scope.currentUser = content;
|
||||
Auth._currentUser = content;
|
||||
$rootScope.currentUser = content;
|
||||
return $state.go('app.public.home');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ask for confirmation then delete the current user's account
|
||||
@ -195,22 +195,22 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_your_account') + ' ' + _t('all_data_relative_to_your_projects_will_be_lost')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, () => // cancel confirmed
|
||||
Member.remove({ id: user.id }, () =>
|
||||
Auth.logout().then(function () {
|
||||
$state.go('app.public.home')
|
||||
return growl.success(_t('your_user_account_has_been_successfully_deleted_goodbye'))
|
||||
$state.go('app.public.home');
|
||||
return growl.success(_t('your_user_account_has_been_successfully_deleted_goodbye'));
|
||||
})
|
||||
|
||||
, function (error) {
|
||||
console.log(error)
|
||||
return growl.error(_t('an_error_occured_preventing_your_account_from_being_deleted'))
|
||||
console.log(error);
|
||||
return growl.error(_t('an_error_occured_preventing_your_account_from_being_deleted'));
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -219,11 +219,11 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the of the properties editable by the user are linked to the SSO
|
||||
@ -232,22 +232,22 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
$scope.hasSsoFields = () =>
|
||||
// if check if keys > 1 because there's a minimum of 1 mapping (id <-> provider-uid)
|
||||
// so the user may want to edit his profile on the SSO if at least 2 mappings exists
|
||||
Object.keys($scope.preventField).length > 1
|
||||
Object.keys($scope.preventField).length > 1;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
$rootScope.currentUser = null
|
||||
$rootScope.toCheckNotifications = false
|
||||
Session.destroy();
|
||||
$rootScope.currentUser = null;
|
||||
$rootScope.toCheckNotifications = false;
|
||||
$scope.notifications = {
|
||||
total: 0,
|
||||
unread: 0
|
||||
}
|
||||
return $window.location.href = $scope.activeProvider.link_to_sso_connect
|
||||
})
|
||||
};
|
||||
return $window.location.href = $scope.activeProvider.link_to_sso_connect;
|
||||
});
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -255,42 +255,42 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// init the birth date to JS object
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate()
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate();
|
||||
|
||||
if ($scope.activeProvider.providable_type !== 'DatabaseProvider') {
|
||||
$scope.preventPassword = true
|
||||
$scope.preventPassword = true;
|
||||
}
|
||||
// bind fields protection with sso fields
|
||||
return angular.forEach(activeProviderPromise.mapping, map => $scope.preventField[map] = true)
|
||||
}
|
||||
return angular.forEach(activeProviderPromise.mapping, map => $scope.preventField[map] = true);
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Controller used on the public user's profile page (seeing another user's profile)
|
||||
*/
|
||||
Application.Controllers.controller('ShowProfileController', ['$scope', 'memberPromise', 'SocialNetworks', function ($scope, memberPromise, SocialNetworks) {
|
||||
// Selected user's information
|
||||
$scope.user = memberPromise // DEPENDENCY WITH NAVINUM GAMIFICATION PLUGIN !!!!
|
||||
$scope.user = memberPromise; // DEPENDENCY WITH NAVINUM GAMIFICATION PLUGIN !!!!
|
||||
|
||||
// List of social networks associated with this user and toggle 'show all' state
|
||||
$scope.social = {
|
||||
showAllLinks: false,
|
||||
networks: SocialNetworks
|
||||
}
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () => $scope.social.networks = filterNetworks()
|
||||
const initialize = () => $scope.social.networks = filterNetworks();
|
||||
|
||||
/**
|
||||
* Filter social network or website that are associated with the profile of the user provided in promise
|
||||
@ -298,17 +298,17 @@ Application.Controllers.controller('ShowProfileController', ['$scope', 'memberPr
|
||||
* @return {Array}
|
||||
*/
|
||||
var filterNetworks = function () {
|
||||
const networks = []
|
||||
const networks = [];
|
||||
for (let network of Array.from(SocialNetworks)) {
|
||||
if ($scope.user.profile[network] && ($scope.user.profile[network].length > 0)) {
|
||||
networks.push(network)
|
||||
networks.push(network);
|
||||
}
|
||||
}
|
||||
return networks
|
||||
}
|
||||
return networks;
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -10,7 +10,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Controller used in notifications page
|
||||
@ -20,27 +20,27 @@ Application.Controllers.controller('NotificationsController', ['$scope', 'Notifi
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// Number of notifications added to the page when the user clicks on 'load next notifications'
|
||||
const NOTIFICATIONS_PER_PAGE = 15
|
||||
const NOTIFICATIONS_PER_PAGE = 15;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Array containg the archived notifications (already read)
|
||||
$scope.notificationsRead = []
|
||||
$scope.notificationsRead = [];
|
||||
|
||||
// Array containg the new notifications (not read)
|
||||
$scope.notificationsUnread = []
|
||||
$scope.notificationsUnread = [];
|
||||
|
||||
// Total number of notifications for the current user
|
||||
$scope.total = 0
|
||||
$scope.total = 0;
|
||||
|
||||
// Total number of unread notifications for the current user
|
||||
$scope.totalUnread = 0
|
||||
$scope.totalUnread = 0;
|
||||
|
||||
// By default, the pagination mode is activated to limit the page size
|
||||
$scope.paginateActive = true
|
||||
$scope.paginateActive = true;
|
||||
|
||||
// The currently displayed page number
|
||||
$scope.page = 1
|
||||
$scope.page = 1;
|
||||
|
||||
/**
|
||||
* Mark the provided notification as read, updating its status on the server and moving it
|
||||
@ -49,22 +49,22 @@ Application.Controllers.controller('NotificationsController', ['$scope', 'Notifi
|
||||
* @param e {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||
*/
|
||||
$scope.markAsRead = function (notification, e) {
|
||||
e.preventDefault()
|
||||
e.preventDefault();
|
||||
return Notification.update({ id: notification.id }, {
|
||||
id: notification.id,
|
||||
is_read: true
|
||||
}
|
||||
, function (updatedNotif) {
|
||||
// remove notif from unreads
|
||||
const index = $scope.notificationsUnread.indexOf(notification)
|
||||
$scope.notificationsUnread.splice(index, 1)
|
||||
const index = $scope.notificationsUnread.indexOf(notification);
|
||||
$scope.notificationsUnread.splice(index, 1);
|
||||
// add update notif to read
|
||||
$scope.notificationsRead.push(updatedNotif)
|
||||
$scope.notificationsRead.push(updatedNotif);
|
||||
// update counters
|
||||
$scope.$parent.notifications.unread -= 1
|
||||
return $scope.totalUnread -= 1
|
||||
})
|
||||
}
|
||||
$scope.$parent.notifications.unread -= 1;
|
||||
return $scope.totalUnread -= 1;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark every unread notifications as read and move them for the unread list to to read array.
|
||||
@ -74,15 +74,15 @@ Application.Controllers.controller('NotificationsController', ['$scope', 'Notifi
|
||||
, function () { // success
|
||||
// add notifs to read
|
||||
angular.forEach($scope.notificationsUnread, function (n) {
|
||||
n.is_read = true
|
||||
return $scope.notificationsRead.push(n)
|
||||
})
|
||||
n.is_read = true;
|
||||
return $scope.notificationsRead.push(n);
|
||||
});
|
||||
// clear unread
|
||||
$scope.notificationsUnread = []
|
||||
$scope.notificationsUnread = [];
|
||||
// update counters
|
||||
$scope.$parent.notifications.unread = 0
|
||||
return $scope.totalUnread = 0
|
||||
})
|
||||
$scope.$parent.notifications.unread = 0;
|
||||
return $scope.totalUnread = 0;
|
||||
});
|
||||
|
||||
/**
|
||||
* Request the server to retrieve the next notifications and add them
|
||||
@ -90,29 +90,29 @@ Application.Controllers.controller('NotificationsController', ['$scope', 'Notifi
|
||||
*/
|
||||
$scope.addMoreNotifications = function () {
|
||||
Notification.query({ page: $scope.page }, function (notifications) {
|
||||
$scope.total = notifications.totals.total
|
||||
$scope.totalUnread = notifications.totals.unread
|
||||
$scope.total = notifications.totals.total;
|
||||
$scope.totalUnread = notifications.totals.unread;
|
||||
angular.forEach(notifications.notifications, function (notif) {
|
||||
if (notif.is_read) {
|
||||
return $scope.notificationsRead.push(notif)
|
||||
return $scope.notificationsRead.push(notif);
|
||||
} else {
|
||||
return $scope.notificationsUnread.push(notif)
|
||||
return $scope.notificationsUnread.push(notif);
|
||||
}
|
||||
})
|
||||
return $scope.paginateActive = (notifications.totals.total > ($scope.notificationsRead.length + $scope.notificationsUnread.length))
|
||||
})
|
||||
});
|
||||
return $scope.paginateActive = (notifications.totals.total > ($scope.notificationsRead.length + $scope.notificationsUnread.length));
|
||||
});
|
||||
|
||||
return $scope.page += 1
|
||||
}
|
||||
return $scope.page += 1;
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = () => $scope.addMoreNotifications()
|
||||
const initialize = () => $scope.addMoreNotifications();
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -10,69 +10,69 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScope', '$state', '$uibModal', 'Auth', 'dialogs', 'growl', 'plansPromise', 'groupsPromise', 'Subscription', 'Member', 'subscriptionExplicationsPromise', '_t', 'Wallet', 'helpers',
|
||||
function ($scope, $rootScope, $state, $uibModal, Auth, dialogs, growl, plansPromise, groupsPromise, Subscription, Member, subscriptionExplicationsPromise, _t, Wallet, helpers) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// list of groups
|
||||
$scope.groups = groupsPromise.filter(function (g) { return (g.slug !== 'admins') & !g.disabled })
|
||||
$scope.groups = groupsPromise.filter(function (g) { return (g.slug !== 'admins') & !g.disabled; });
|
||||
|
||||
// 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
|
||||
$scope.plansClassifiedByGroup = []
|
||||
$scope.plansClassifiedByGroup = [];
|
||||
for (var group of Array.from($scope.groups)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] };
|
||||
for (let plan of Array.from(plansPromise)) {
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan) }
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan); }
|
||||
}
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
$scope.plansClassifiedByGroup.push(groupObj);
|
||||
}
|
||||
|
||||
// user to deal with
|
||||
$scope.ctrl = {
|
||||
member: null,
|
||||
member_id: null
|
||||
}
|
||||
};
|
||||
|
||||
// already subscribed plan of the current user
|
||||
$scope.paid =
|
||||
{ plan: null }
|
||||
{ plan: null };
|
||||
|
||||
// plan to subscribe (shopping cart)
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
|
||||
// Discount coupon to apply to the basket, if any
|
||||
$scope.coupon =
|
||||
{ applied: null }
|
||||
{ applied: null };
|
||||
|
||||
// Storage for the total price (plan price + coupon, if any)
|
||||
$scope.cart =
|
||||
{ total: null }
|
||||
{ total: null };
|
||||
|
||||
// text that appears in the bottom-right box of the page (subscriptions rules details)
|
||||
$scope.subscriptionExplicationsAlert = subscriptionExplicationsPromise.setting.value
|
||||
$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)
|
||||
*/
|
||||
$scope.updateMember = function () {
|
||||
$scope.selectedPlan = null
|
||||
$scope.paid.plan = null
|
||||
$scope.group.change = false
|
||||
$scope.selectedPlan = null;
|
||||
$scope.paid.plan = null;
|
||||
$scope.group.change = false;
|
||||
return Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
||||
$scope.ctrl.member = member
|
||||
return $scope.group.id = $scope.ctrl.member.group_id
|
||||
})
|
||||
}
|
||||
$scope.ctrl.member = member;
|
||||
return $scope.group.id = $scope.ctrl.member.group_id;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the provided plan to the shopping basket
|
||||
@ -81,31 +81,31 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
$scope.selectPlan = function (plan) {
|
||||
if ($scope.isAuthenticated()) {
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
$scope.selectedPlan = plan
|
||||
return updateCartPrice()
|
||||
$scope.selectedPlan = plan;
|
||||
return updateCartPrice();
|
||||
} else {
|
||||
return $scope.selectedPlan = null
|
||||
return $scope.selectedPlan = null;
|
||||
}
|
||||
} else {
|
||||
return $scope.login()
|
||||
return $scope.login();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger the payment process of the subscription
|
||||
*/
|
||||
$scope.openSubscribePlanModal = function () {
|
||||
Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }, function (wallet) {
|
||||
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount)
|
||||
const amountToPay = helpers.getAmountToPay($scope.cart.total, wallet.amount);
|
||||
if (($scope.currentUser.role !== 'admin') && (amountToPay > 0)) {
|
||||
return payByStripe()
|
||||
return payByStripe();
|
||||
} else {
|
||||
if (($scope.currentUser.role === 'admin') || (amountToPay === 0)) {
|
||||
return payOnSite()
|
||||
return payOnSite();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the group object, identified by the ID set in $scope.group.id
|
||||
@ -113,35 +113,35 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
$scope.getUserGroup = function () {
|
||||
for (group of Array.from($scope.groups)) {
|
||||
if (group.id === $scope.group.id) {
|
||||
return group
|
||||
return group;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the group of the current/selected user to the one set in $scope.group.id
|
||||
*/
|
||||
$scope.selectGroup = function () {
|
||||
Member.update({ id: $scope.ctrl.member.id }, { user: { group_id: $scope.group.id } }, function (user) {
|
||||
$scope.ctrl.member = user
|
||||
$scope.group.change = false
|
||||
$scope.ctrl.member = user;
|
||||
$scope.group.change = false;
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
$rootScope.currentUser = user
|
||||
Auth._currentUser.group_id = user.group_id
|
||||
growl.success(_t('your_group_was_successfully_changed'))
|
||||
$rootScope.currentUser = user;
|
||||
Auth._currentUser.group_id = user.group_id;
|
||||
growl.success(_t('your_group_was_successfully_changed'));
|
||||
} else {
|
||||
growl.success(_t('the_user_s_group_was_successfully_changed'))
|
||||
growl.success(_t('the_user_s_group_was_successfully_changed'));
|
||||
}
|
||||
}
|
||||
, function (err) {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
growl.error(_t('an_error_prevented_your_group_from_being_changed'))
|
||||
growl.error(_t('an_error_prevented_your_group_from_being_changed'));
|
||||
} else {
|
||||
growl.error(_t('an_error_prevented_to_change_the_user_s_group'))
|
||||
growl.error(_t('an_error_prevented_to_change_the_user_s_group'));
|
||||
}
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an enumerable meaninful string for the gender of the provider user
|
||||
@ -150,9 +150,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
*/
|
||||
$scope.getGender = function (user) {
|
||||
if (user && user.profile) {
|
||||
if (user.profile.gender === 'true') { return 'male' } else { return 'female' }
|
||||
} else { return 'other' }
|
||||
}
|
||||
if (user.profile.gender === 'true') { return 'male'; } else { return 'female'; }
|
||||
} else { return 'other'; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if the provided date is in the future
|
||||
@ -160,13 +160,13 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
* @return {boolean}
|
||||
*/
|
||||
$scope.isInFuture = function (dateTime) {
|
||||
return (moment().diff(moment(dateTime)) < 0)
|
||||
}
|
||||
return (moment().diff(moment(dateTime)) < 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled }
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled; };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -176,21 +176,21 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
const initialize = function () {
|
||||
if ($scope.currentUser) {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
$scope.ctrl.member = $scope.currentUser
|
||||
$scope.paid.plan = $scope.currentUser.subscribed_plan
|
||||
$scope.group.id = $scope.currentUser.group_id
|
||||
$scope.ctrl.member = $scope.currentUser;
|
||||
$scope.paid.plan = $scope.currentUser.subscribed_plan;
|
||||
$scope.group.id = $scope.currentUser.group_id;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$on('devise:new-session', function (event, user) { $scope.ctrl.member = user })
|
||||
$scope.$on('devise:new-session', function (event, user) { $scope.ctrl.member = user; });
|
||||
|
||||
// watch when a coupon is applied to re-compute the total price
|
||||
return $scope.$watch('coupon.applied', function (newValue, oldValue) {
|
||||
if ((newValue !== null) || (oldValue !== null)) {
|
||||
return updateCartPrice()
|
||||
return updateCartPrice();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute the total amount for the current reservation according to the previously set parameters
|
||||
@ -199,21 +199,21 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
var updateCartPrice = function () {
|
||||
// first we check that a user was selected
|
||||
if (Object.keys($scope.ctrl.member).length > 0) {
|
||||
$scope.cart.total = $scope.selectedPlan.amount
|
||||
$scope.cart.total = $scope.selectedPlan.amount;
|
||||
// apply the coupon if any
|
||||
if ($scope.coupon.applied) {
|
||||
let discount
|
||||
let discount;
|
||||
if ($scope.coupon.applied.type === 'percent_off') {
|
||||
discount = ($scope.cart.total * $scope.coupon.applied.percent_off) / 100
|
||||
discount = ($scope.cart.total * $scope.coupon.applied.percent_off) / 100;
|
||||
} else if ($scope.coupon.applied.type === 'amount_off') {
|
||||
discount = $scope.coupon.applied.amount_off
|
||||
discount = $scope.coupon.applied.amount_off;
|
||||
}
|
||||
return $scope.cart.total -= discount
|
||||
return $scope.cart.total -= discount;
|
||||
}
|
||||
} else {
|
||||
return $scope.reserve.amountTotal = null
|
||||
return $scope.reserve.amountTotal = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal window which trigger the stripe payment process
|
||||
@ -223,30 +223,30 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
templateUrl: '<%= asset_path "stripe/payment_modal.html" %>',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
selectedPlan () { return $scope.selectedPlan },
|
||||
member () { return $scope.ctrl.member },
|
||||
price () { return $scope.cart.total },
|
||||
selectedPlan () { return $scope.selectedPlan; },
|
||||
member () { return $scope.ctrl.member; },
|
||||
price () { return $scope.cart.total; },
|
||||
wallet () {
|
||||
return Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }).$promise
|
||||
return Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }).$promise;
|
||||
},
|
||||
coupon () { return $scope.coupon.applied }
|
||||
coupon () { return $scope.coupon.applied; }
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'price', 'Subscription', 'CustomAsset', 'wallet', 'helpers', '$filter', 'coupon',
|
||||
function ($scope, $uibModalInstance, $state, selectedPlan, member, price, Subscription, CustomAsset, wallet, helpers, $filter, coupon) {
|
||||
// User's wallet amount
|
||||
$scope.walletAmount = wallet.amount
|
||||
$scope.walletAmount = wallet.amount;
|
||||
|
||||
// Final price to pay by the user
|
||||
$scope.amount = helpers.getAmountToPay(price, wallet.amount)
|
||||
$scope.amount = helpers.getAmountToPay(price, wallet.amount);
|
||||
|
||||
// The plan that the user is about to subscribe
|
||||
$scope.selectedPlan = selectedPlan
|
||||
$scope.selectedPlan = selectedPlan;
|
||||
|
||||
// Used in wallet info template to interpolate some translations
|
||||
$scope.numberFilter = $filter('number')
|
||||
$scope.numberFilter = $filter('number');
|
||||
|
||||
// retrieve the CGV
|
||||
CustomAsset.get({ name: 'cgv-file' }, function (cgv) { $scope.cgv = cgv.custom_asset })
|
||||
CustomAsset.get({ name: 'cgv-file' }, function (cgv) { $scope.cgv = cgv.custom_asset; });
|
||||
|
||||
/**
|
||||
* Callback for click on the 'proceed' button.
|
||||
@ -255,9 +255,9 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
*/
|
||||
$scope.payment = function (status, response) {
|
||||
if (response.error) {
|
||||
growl.error(response.error.message)
|
||||
growl.error(response.error.message);
|
||||
} else {
|
||||
$scope.attempting = true
|
||||
$scope.attempting = true;
|
||||
Subscription.save({
|
||||
coupon_code: ((coupon ? coupon.code : undefined)),
|
||||
subscription: {
|
||||
@ -267,26 +267,26 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
, function (data) { // success
|
||||
$uibModalInstance.close(data)
|
||||
$uibModalInstance.close(data);
|
||||
}
|
||||
, function (data, status) { // failed
|
||||
$scope.alerts = []
|
||||
$scope.alerts.push({ msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' })
|
||||
$scope.attempting = false
|
||||
$scope.alerts = [];
|
||||
$scope.alerts.push({ msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
$scope.attempting = false;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
]
|
||||
}).result['finally'](null).then(function (subscription) {
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
$scope.paid.plan = angular.copy($scope.selectedPlan)
|
||||
$scope.selectedPlan = null
|
||||
$scope.coupon.applied = null
|
||||
})
|
||||
}
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
$scope.paid.plan = angular.copy($scope.selectedPlan);
|
||||
$scope.selectedPlan = null;
|
||||
$scope.coupon.applied = null;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal window which trigger the local payment process
|
||||
@ -296,42 +296,42 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
templateUrl: '<%= asset_path "plans/payment_modal.html" %>',
|
||||
size: 'sm',
|
||||
resolve: {
|
||||
selectedPlan () { return $scope.selectedPlan },
|
||||
member () { return $scope.ctrl.member },
|
||||
price () { return $scope.cart.total },
|
||||
selectedPlan () { return $scope.selectedPlan; },
|
||||
member () { return $scope.ctrl.member; },
|
||||
price () { return $scope.cart.total; },
|
||||
wallet () {
|
||||
return Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }).$promise
|
||||
return Wallet.getWalletByUser({ user_id: $scope.ctrl.member.id }).$promise;
|
||||
},
|
||||
coupon () { return $scope.coupon.applied }
|
||||
coupon () { return $scope.coupon.applied; }
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'selectedPlan', 'member', 'price', 'Subscription', 'wallet', 'helpers', '$filter', 'coupon',
|
||||
function ($scope, $uibModalInstance, $state, selectedPlan, member, price, Subscription, wallet, helpers, $filter, coupon) {
|
||||
// user wallet amount
|
||||
$scope.walletAmount = wallet.amount
|
||||
$scope.walletAmount = wallet.amount;
|
||||
|
||||
// subcription price, coupon subtracted if any
|
||||
$scope.price = price
|
||||
$scope.price = price;
|
||||
|
||||
// price to pay
|
||||
$scope.amount = helpers.getAmountToPay($scope.price, wallet.amount)
|
||||
$scope.amount = helpers.getAmountToPay($scope.price, wallet.amount);
|
||||
|
||||
// Used in wallet info template to interpolate some translations
|
||||
$scope.numberFilter = $filter('number')
|
||||
$scope.numberFilter = $filter('number');
|
||||
|
||||
// The plan that the user is about to subscribe
|
||||
$scope.plan = selectedPlan
|
||||
$scope.plan = selectedPlan;
|
||||
|
||||
// The member who is subscribing a plan
|
||||
$scope.member = member
|
||||
$scope.member = member;
|
||||
|
||||
// Button label
|
||||
if ($scope.amount > 0) {
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat')
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat');
|
||||
} else {
|
||||
if ((price.price > 0) && ($scope.walletAmount === 0)) {
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat')
|
||||
$scope.validButtonName = _t('confirm_payment_of_html', { ROLE: $scope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat');
|
||||
} else {
|
||||
$scope.validButtonName = _t('confirm')
|
||||
$scope.validButtonName = _t('confirm');
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,7 +340,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
* Save the subscription to the API
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$scope.attempting = true
|
||||
$scope.attempting = true;
|
||||
Subscription.save({
|
||||
coupon_code: ((coupon ? coupon.code : undefined)),
|
||||
subscription: {
|
||||
@ -349,34 +349,34 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
|
||||
}
|
||||
}
|
||||
, function (data) { // success
|
||||
$uibModalInstance.close(data)
|
||||
$uibModalInstance.close(data);
|
||||
}
|
||||
, function (data, status) { // failed
|
||||
$scope.alerts = []
|
||||
$scope.alerts.push({ msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' })
|
||||
$scope.attempting = false
|
||||
$scope.alerts = [];
|
||||
$scope.alerts.push({ msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
$scope.attempting = false;
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the 'cancel' button.
|
||||
* Close the modal box.
|
||||
*/
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
]
|
||||
}).result['finally'](null).then(function (reservation) {
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
$scope.ctrl.member = null
|
||||
$scope.paid.plan = angular.copy($scope.selectedPlan)
|
||||
$scope.selectedPlan = null
|
||||
return $scope.coupon.applied = null
|
||||
})
|
||||
}
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
$scope.ctrl.member = null;
|
||||
$scope.paid.plan = angular.copy($scope.selectedPlan);
|
||||
$scope.selectedPlan = null;
|
||||
return $scope.coupon.applied = null;
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -11,41 +11,41 @@
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('CompleteProfileController', ['$scope', '$rootScope', '$state', '$window', '_t', 'growl', 'CSRF', 'Auth', 'Member', 'settingsPromise', 'activeProviderPromise', 'groupsPromise', 'cguFile', 'memberPromise', 'Session', 'dialogs', 'AuthProvider',
|
||||
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
|
||||
$scope.actionUrl = `/api/members/${memberPromise.id}`
|
||||
$scope.actionUrl = `/api/members/${memberPromise.id}`;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'patch'
|
||||
$scope.method = 'patch';
|
||||
|
||||
// genre of the application name (eg. "_le_ Fablab" or "_la_ Fabrique")
|
||||
$scope.nameGenre = settingsPromise.name_genre
|
||||
$scope.nameGenre = settingsPromise.name_genre;
|
||||
|
||||
// name of the current fablab application (eg. "Fablab de la Casemate")
|
||||
$scope.fablabName = settingsPromise.fablab_name
|
||||
$scope.fablabName = settingsPromise.fablab_name;
|
||||
|
||||
// information from the current SSO provider
|
||||
$scope.activeProvider = activeProviderPromise
|
||||
$scope.activeProvider = activeProviderPromise;
|
||||
|
||||
// list of user's groups (student/standard/...)
|
||||
$scope.groups = groupsPromise
|
||||
$scope.groups = groupsPromise;
|
||||
|
||||
// current user, contains information retrieved from the SSO
|
||||
$scope.user = memberPromise
|
||||
$scope.user = memberPromise;
|
||||
|
||||
// disallow the user to change his password as he connect from SSO
|
||||
$scope.preventPassword = true
|
||||
$scope.preventPassword = true;
|
||||
|
||||
// mapping of fields to disable
|
||||
$scope.preventField = {}
|
||||
$scope.preventField = {};
|
||||
|
||||
// CGU
|
||||
$scope.cgu = cguFile.custom_asset
|
||||
$scope.cgu = cguFile.custom_asset;
|
||||
|
||||
// Angular-Bootstrap datepicker configuration for birthday
|
||||
$scope.datePicker = {
|
||||
@ -54,17 +54,17 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
options: {
|
||||
startingDay: Fablab.weekStartingDay
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
return $scope.datePicker.opened = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
@ -75,26 +75,26 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
angular.forEach(content, function (v, k) {
|
||||
angular.forEach(v, function (err) {
|
||||
$scope.alerts.push({
|
||||
msg: k + ': ' + err,
|
||||
type: 'danger'
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$scope.user.profile.user_avatar = content.profile.user_avatar
|
||||
Auth._currentUser.profile.user_avatar = content.profile.user_avatar
|
||||
$scope.user.name = content.name
|
||||
Auth._currentUser.name = content.name
|
||||
$scope.user = content
|
||||
Auth._currentUser = content
|
||||
$rootScope.currentUser = content
|
||||
return $state.go('app.public.home')
|
||||
$scope.user.profile.user_avatar = content.profile.user_avatar;
|
||||
Auth._currentUser.profile.user_avatar = content.profile.user_avatar;
|
||||
$scope.user.name = content.name;
|
||||
Auth._currentUser.name = content.name;
|
||||
$scope.user = content;
|
||||
Auth._currentUser = content;
|
||||
$rootScope.currentUser = content;
|
||||
return $state.go('app.public.home');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -103,99 +103,99 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Merge the current user into the account with the given auth_token
|
||||
*/
|
||||
$scope.registerAuthToken = function () {
|
||||
Member.merge({ id: $rootScope.currentUser.id }, { user: { auth_token: $scope.user.auth_token } }, function (user) {
|
||||
$scope.user = user
|
||||
Auth._currentUser = user
|
||||
$rootScope.currentUser = user
|
||||
$state.go('app.public.home')
|
||||
$scope.user = user;
|
||||
Auth._currentUser = user;
|
||||
$rootScope.currentUser = user;
|
||||
$state.go('app.public.home');
|
||||
}
|
||||
, function (err) {
|
||||
if (err.data.error) {
|
||||
growl.error(err.data.error)
|
||||
growl.error(err.data.error);
|
||||
} else {
|
||||
growl.error(_t('an_unexpected_error_occurred_check_your_authentication_code'))
|
||||
console.error(err)
|
||||
growl.error(_t('an_unexpected_error_occurred_check_your_authentication_code'));
|
||||
console.error(err);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
const { email } = memberPromise;
|
||||
if (email) {
|
||||
const duplicate = email.match(/^<([^>]+)>.{20}-duplicate$/)
|
||||
const duplicate = email.match(/^<([^>]+)>.{20}-duplicate$/);
|
||||
if (duplicate) {
|
||||
return duplicate[1]
|
||||
return duplicate[1];
|
||||
}
|
||||
}
|
||||
return email
|
||||
}
|
||||
return email;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if the user's mail is marked as duplicate
|
||||
* @return {boolean}
|
||||
*/
|
||||
$scope.hasDuplicate = function () {
|
||||
const { email } = memberPromise
|
||||
const { email } = memberPromise;
|
||||
if (email) {
|
||||
return !(email.match(/^<([^>]+)>.{20}-duplicate$/) === null)
|
||||
return !(email.match(/^<([^>]+)>.{20}-duplicate$/) === null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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()
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
dialogs.confirm(
|
||||
{
|
||||
templateUrl: '<%= asset_path "profile/resend_code_modal.html" %>',
|
||||
resolve: {
|
||||
object () {
|
||||
return { email: memberPromise.email }
|
||||
return { email: memberPromise.email };
|
||||
}
|
||||
}
|
||||
},
|
||||
function (email) {
|
||||
// Request the server to send an auth-migration email to the current user
|
||||
AuthProvider.send_code({ email },
|
||||
function (res) { growl.info(_t('code_successfully_sent_again')) },
|
||||
function (err) { growl.error(err.data.error) }
|
||||
)
|
||||
function (res) { growl.info(_t('code_successfully_sent_again')); },
|
||||
function (err) { growl.error(err.data.error); }
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Disconnect and re-connect the user to the SSO to force the synchronisation of the profile's data
|
||||
*/
|
||||
$scope.syncProfile = function () {
|
||||
Auth.logout().then(function (oldUser) {
|
||||
Session.destroy()
|
||||
$rootScope.currentUser = null
|
||||
$rootScope.toCheckNotifications = false
|
||||
Session.destroy();
|
||||
$rootScope.currentUser = null;
|
||||
$rootScope.toCheckNotifications = false;
|
||||
$scope.notifications = {
|
||||
total: 0,
|
||||
unread: 0
|
||||
}
|
||||
$window.location.href = activeProviderPromise.link_to_sso_connect
|
||||
})
|
||||
}
|
||||
};
|
||||
$window.location.href = activeProviderPromise.link_to_sso_connect;
|
||||
});
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -203,17 +203,17 @@ Application.Controllers.controller('CompleteProfileController', ['$scope', '$roo
|
||||
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||
*/
|
||||
const initialize = function () {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// init the birth date to JS object
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate()
|
||||
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate();
|
||||
|
||||
// bind fields protection with sso fields
|
||||
angular.forEach(activeProviderPromise.mapping, function (map) { $scope.preventField[map] = true })
|
||||
}
|
||||
angular.forEach(activeProviderPromise.mapping, function (map) { $scope.preventField[map] = true; });
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -13,7 +13,7 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/* COMMON CODE */
|
||||
|
||||
@ -49,9 +49,9 @@ class ProjectsController {
|
||||
return ({
|
||||
id: d.id,
|
||||
name: d.name
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Retrieve the list of components from the server
|
||||
Component.query().$promise.then(function (data) {
|
||||
@ -59,9 +59,9 @@ class ProjectsController {
|
||||
return ({
|
||||
id: d.id,
|
||||
name: d.name
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Retrieve the list of themes from the server
|
||||
Theme.query().$promise.then(function (data) {
|
||||
@ -69,9 +69,9 @@ class ProjectsController {
|
||||
return ({
|
||||
id: d.id,
|
||||
name: d.name
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Retrieve the list of licences from the server
|
||||
Licence.query().$promise.then(function (data) {
|
||||
@ -79,15 +79,15 @@ class ProjectsController {
|
||||
return ({
|
||||
id: d.id,
|
||||
name: d.name
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Total number of documentation steps for the current project
|
||||
$scope.totalSteps = $scope.project.project_steps_attributes.length
|
||||
$scope.totalSteps = $scope.project.project_steps_attributes.length;
|
||||
|
||||
// List of extensions allowed for CAD attachements upload
|
||||
$scope.allowedExtensions = allowedExtensions
|
||||
$scope.allowedExtensions = allowedExtensions;
|
||||
|
||||
/**
|
||||
* For use with ngUpload (https://github.com/twilson63/ngUpload).
|
||||
@ -97,21 +97,21 @@ class ProjectsController {
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
angular.forEach(content, function (v, k) {
|
||||
angular.forEach(v, function (err) {
|
||||
$scope.alerts.push({
|
||||
msg: k + ': ' + err,
|
||||
type: 'danger'
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
// using https://github.com/oblador/angular-scroll
|
||||
$('section[ui-view=main]').scrollTop(0, 200)
|
||||
$('section[ui-view=main]').scrollTop(0, 200);
|
||||
} else {
|
||||
return $state.go('app.public.projects_show', { id: content.slug })
|
||||
return $state.go('app.public.projects_show', { id: content.slug });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -120,16 +120,16 @@ class ProjectsController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This will create a single new empty entry into the project's CAO attachements list.
|
||||
*/
|
||||
$scope.addFile = function () { $scope.project.project_caos_attributes.push({}) }
|
||||
$scope.addFile = function () { $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
|
||||
@ -138,21 +138,21 @@ class ProjectsController {
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.project.project_caos_attributes.indexOf(file)
|
||||
const index = $scope.project.project_caos_attributes.indexOf(file);
|
||||
if (file.id != null) {
|
||||
return file._destroy = true
|
||||
return file._destroy = true;
|
||||
} else {
|
||||
return $scope.project.project_caos_attributes.splice(index, 1)
|
||||
return $scope.project.project_caos_attributes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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: [] })
|
||||
}
|
||||
$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
|
||||
@ -167,34 +167,34 @@ class ProjectsController {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_step')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () { // deletion confirmed
|
||||
const index = $scope.project.project_steps_attributes.indexOf(step)
|
||||
const index = $scope.project.project_steps_attributes.indexOf(step);
|
||||
if (step.id != null) {
|
||||
step._destroy = true
|
||||
step._destroy = true;
|
||||
} else {
|
||||
$scope.project.project_steps_attributes.splice(index, 1)
|
||||
$scope.project.project_steps_attributes.splice(index, 1);
|
||||
}
|
||||
|
||||
// update the new total number of steps
|
||||
$scope.totalSteps -= 1
|
||||
$scope.totalSteps -= 1;
|
||||
// reindex the remaining steps
|
||||
return (function () {
|
||||
const result = []
|
||||
const result = [];
|
||||
for (let s of Array.from($scope.project.project_steps_attributes)) {
|
||||
if (s.step_nb > step.step_nb) {
|
||||
result.push(s.step_nb -= 1)
|
||||
result.push(s.step_nb -= 1);
|
||||
} else {
|
||||
result.push(undefined)
|
||||
result.push(undefined);
|
||||
}
|
||||
}
|
||||
return result
|
||||
})()
|
||||
})
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the step_nb property of the given step to the new value provided. The step that was previously at this
|
||||
@ -204,34 +204,34 @@ class ProjectsController {
|
||||
* @param newIdx {number} the new index to assign to the step
|
||||
*/
|
||||
$scope.changeStepIndex = function (event, step, newIdx) {
|
||||
if (event) { event.preventDefault() }
|
||||
if (event) { event.preventDefault(); }
|
||||
for (let s of Array.from($scope.project.project_steps_attributes)) {
|
||||
if (s.step_nb === newIdx) {
|
||||
s.step_nb = step.step_nb
|
||||
step.step_nb = newIdx
|
||||
break
|
||||
s.step_nb = step.step_nb;
|
||||
step.step_nb = newIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
$scope.autoCompleteName = function (nameLookup) {
|
||||
if (!nameLookup) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
const asciiName = Diacritics.remove(nameLookup)
|
||||
const asciiName = Diacritics.remove(nameLookup);
|
||||
|
||||
Member.search(
|
||||
{ query: asciiName },
|
||||
function (users) { $scope.matchingMembers = users },
|
||||
function (error) { console.error(error) }
|
||||
)
|
||||
}
|
||||
function (users) { $scope.matchingMembers = users; },
|
||||
function (error) { console.error(error); }
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* This will create a single new empty entry into the project's step image list.
|
||||
*/
|
||||
$scope.addProjectStepImage = function (step) { step.project_step_images_attributes.push({}) }
|
||||
$scope.addProjectStepImage = function (step) { step.project_step_images_attributes.push({}); };
|
||||
|
||||
/**
|
||||
* This will remove the given image from the project's step image list.
|
||||
@ -239,13 +239,13 @@ class ProjectsController {
|
||||
* @param image {Object} the image to delete
|
||||
*/
|
||||
$scope.deleteProjectStepImage = function (step, image) {
|
||||
const index = step.project_step_images_attributes.indexOf(image)
|
||||
const index = step.project_step_images_attributes.indexOf(image);
|
||||
if (image.id != null) {
|
||||
return image._destroy = true
|
||||
return image._destroy = true;
|
||||
} else {
|
||||
return step.project_step_images_attributes.splice(index, 1)
|
||||
return step.project_step_images_attributes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,18 +257,18 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// Number of projects added to the page when the user clicks on 'load more projects'
|
||||
const PROJECTS_PER_PAGE = 16
|
||||
const PROJECTS_PER_PAGE = 16;
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Fab-manager's instance ID in the openLab network
|
||||
$scope.openlabAppId = Fablab.openlabAppId
|
||||
$scope.openlabAppId = Fablab.openlabAppId;
|
||||
|
||||
// Is openLab enabled on the instance?
|
||||
$scope.openlab = {
|
||||
projectsActive: Fablab.openlabProjectsActive,
|
||||
searchOverWholeNetwork: false
|
||||
}
|
||||
};
|
||||
|
||||
// default search parameters
|
||||
$scope.search = {
|
||||
@ -277,69 +277,69 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
machine_id: (parseInt($location.$$search.machine_id) || undefined),
|
||||
component_id: (parseInt($location.$$search.component_id) || undefined),
|
||||
theme_id: (parseInt($location.$$search.theme_id) || undefined)
|
||||
}
|
||||
};
|
||||
|
||||
// list of projects to display
|
||||
$scope.projects = []
|
||||
$scope.projects = [];
|
||||
|
||||
// list of machines / used for filtering
|
||||
$scope.machines = machinesPromise
|
||||
$scope.machines = machinesPromise;
|
||||
|
||||
// list of themes / used for filtering
|
||||
$scope.themes = themesPromise
|
||||
$scope.themes = themesPromise;
|
||||
|
||||
// list of components / used for filtering
|
||||
$scope.components = componentsPromise
|
||||
$scope.components = componentsPromise;
|
||||
|
||||
$scope.searchOverWholeNetworkChanged = function () {
|
||||
setTimeout(
|
||||
function () { $scope.resetFiltersAndTriggerSearch() },
|
||||
function () { $scope.resetFiltersAndTriggerSearch(); },
|
||||
150
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.loadMore = function () {
|
||||
if ($scope.openlab.searchOverWholeNetwork === true) {
|
||||
return $scope.projectsPagination.loadMore({ q: $scope.search.q })
|
||||
return $scope.projectsPagination.loadMore({ q: $scope.search.q });
|
||||
} else {
|
||||
return $scope.projectsPagination.loadMore({ search: $scope.search })
|
||||
return $scope.projectsPagination.loadMore({ search: $scope.search });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.resetFiltersAndTriggerSearch = function () {
|
||||
$scope.search.q = ''
|
||||
$scope.search.from = undefined
|
||||
$scope.search.machine_id = undefined
|
||||
$scope.search.component_id = undefined
|
||||
$scope.search.theme_id = undefined
|
||||
$scope.setUrlQueryParams($scope.search)
|
||||
return $scope.triggerSearch()
|
||||
}
|
||||
$scope.search.q = '';
|
||||
$scope.search.from = undefined;
|
||||
$scope.search.machine_id = undefined;
|
||||
$scope.search.component_id = undefined;
|
||||
$scope.search.theme_id = undefined;
|
||||
$scope.setUrlQueryParams($scope.search);
|
||||
return $scope.triggerSearch();
|
||||
};
|
||||
|
||||
$scope.triggerSearch = function () {
|
||||
const currentPage = parseInt($location.$$search.page) || 1
|
||||
const currentPage = parseInt($location.$$search.page) || 1;
|
||||
if ($scope.openlab.searchOverWholeNetwork === true) {
|
||||
updateUrlParam('whole_network', 't')
|
||||
$scope.projectsPagination = new paginationService.Instance(OpenlabProject, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreOpenlabCallback)
|
||||
updateUrlParam('whole_network', 't');
|
||||
$scope.projectsPagination = new paginationService.Instance(OpenlabProject, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreOpenlabCallback);
|
||||
return OpenlabProject.query({ q: $scope.search.q, page: currentPage, per_page: PROJECTS_PER_PAGE }, function (projectsPromise) {
|
||||
if (projectsPromise.errors != null) {
|
||||
growl.error(_t('openlab_search_not_available_at_the_moment'))
|
||||
$scope.openlab.searchOverWholeNetwork = false
|
||||
return $scope.triggerSearch()
|
||||
growl.error(_t('openlab_search_not_available_at_the_moment'));
|
||||
$scope.openlab.searchOverWholeNetwork = false;
|
||||
return $scope.triggerSearch();
|
||||
} else {
|
||||
$scope.projectsPagination.totalCount = projectsPromise.meta.total
|
||||
return $scope.projects = normalizeProjectsAttrs(projectsPromise.projects)
|
||||
$scope.projectsPagination.totalCount = projectsPromise.meta.total;
|
||||
return $scope.projects = normalizeProjectsAttrs(projectsPromise.projects);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
updateUrlParam('whole_network', 'f')
|
||||
$scope.projectsPagination = new paginationService.Instance(Project, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreCallback, 'search')
|
||||
updateUrlParam('whole_network', 'f');
|
||||
$scope.projectsPagination = new paginationService.Instance(Project, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreCallback, 'search');
|
||||
return Project.search({ search: $scope.search, page: currentPage, per_page: PROJECTS_PER_PAGE }, function (projectsPromise) {
|
||||
$scope.projectsPagination.totalCount = projectsPromise.meta.total
|
||||
return $scope.projects = projectsPromise.projects
|
||||
})
|
||||
$scope.projectsPagination.totalCount = projectsPromise.meta.total;
|
||||
return $scope.projects = projectsPromise.projects;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to switch the user's view to the detailled project page
|
||||
@ -347,24 +347,24 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
*/
|
||||
$scope.showProject = function (project) {
|
||||
if (($scope.openlab.searchOverWholeNetwork === true) && (project.app_id !== Fablab.openlabAppId)) {
|
||||
$window.open(project.project_url, '_blank')
|
||||
return true
|
||||
$window.open(project.project_url, '_blank');
|
||||
return true;
|
||||
} else {
|
||||
return $state.go('app.public.projects_show', { id: project.slug })
|
||||
return $state.go('app.public.projects_show', { id: project.slug });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* function to set all url query search parameters from search object
|
||||
*/
|
||||
$scope.setUrlQueryParams = function (search) {
|
||||
updateUrlParam('page', 1)
|
||||
updateUrlParam('q', search.q)
|
||||
updateUrlParam('from', search.from)
|
||||
updateUrlParam('theme_id', search.theme_id)
|
||||
updateUrlParam('component_id', search.component_id)
|
||||
return updateUrlParam('machine_id', search.machine_id)
|
||||
}
|
||||
updateUrlParam('page', 1);
|
||||
updateUrlParam('q', search.q);
|
||||
updateUrlParam('from', search.from);
|
||||
updateUrlParam('theme_id', search.theme_id);
|
||||
updateUrlParam('component_id', search.component_id);
|
||||
return updateUrlParam('machine_id', search.machine_id);
|
||||
};
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -373,98 +373,98 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($location.$$search.whole_network === 'f') {
|
||||
$scope.openlab.searchOverWholeNetwork = false
|
||||
$scope.openlab.searchOverWholeNetwork = false;
|
||||
} else {
|
||||
$scope.openlab.searchOverWholeNetwork = $scope.openlab.projectsActive || false
|
||||
$scope.openlab.searchOverWholeNetwork = $scope.openlab.projectsActive || false;
|
||||
}
|
||||
return $scope.triggerSearch()
|
||||
}
|
||||
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'
|
||||
*/
|
||||
var updateUrlParam = function (name, value) {
|
||||
$state.current.reloadOnSearch = false
|
||||
$location.search(name, value)
|
||||
return $timeout(function () { $state.current.reloadOnSearch = undefined })
|
||||
}
|
||||
$state.current.reloadOnSearch = false;
|
||||
$location.search(name, value);
|
||||
return $timeout(function () { $state.current.reloadOnSearch = undefined; });
|
||||
};
|
||||
|
||||
var loadMoreCallback = function (projectsPromise) {
|
||||
$scope.projects = $scope.projects.concat(projectsPromise.projects)
|
||||
return updateUrlParam('page', $scope.projectsPagination.currentPage)
|
||||
}
|
||||
$scope.projects = $scope.projects.concat(projectsPromise.projects);
|
||||
return updateUrlParam('page', $scope.projectsPagination.currentPage);
|
||||
};
|
||||
|
||||
var loadMoreOpenlabCallback = function (projectsPromise) {
|
||||
$scope.projects = $scope.projects.concat(normalizeProjectsAttrs(projectsPromise.projects))
|
||||
return updateUrlParam('page', $scope.projectsPagination.currentPage)
|
||||
}
|
||||
$scope.projects = $scope.projects.concat(normalizeProjectsAttrs(projectsPromise.projects));
|
||||
return updateUrlParam('page', $scope.projectsPagination.currentPage);
|
||||
};
|
||||
|
||||
var normalizeProjectsAttrs = function (projects) {
|
||||
projects.map(function (project) {
|
||||
project.project_image = project.image_url
|
||||
return project
|
||||
})
|
||||
}
|
||||
project.project_image = project.image_url;
|
||||
return project;
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/projects/'
|
||||
$scope.actionUrl = '/api/projects/';
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// Default project parameters
|
||||
$scope.project = {
|
||||
project_steps_attributes: [],
|
||||
project_caos_attributes: []
|
||||
}
|
||||
};
|
||||
|
||||
$scope.matchingMembers = []
|
||||
$scope.matchingMembers = [];
|
||||
|
||||
// Using the ProjectsController
|
||||
return new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, Diacritics, dialogs, allowedExtensions, _t)
|
||||
return new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, Diacritics, dialogs, allowedExtensions, _t);
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/projects/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/projects/${$stateParams.id}`;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
$scope.method = 'put';
|
||||
|
||||
// Retrieve the project's details, if an error occured, redirect the user to the projects list page
|
||||
$scope.project = projectPromise
|
||||
$scope.project = projectPromise;
|
||||
|
||||
$scope.matchingMembers = $scope.project.project_users.map(function (u) {
|
||||
return ({
|
||||
id: u.id,
|
||||
name: u.full_name
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
// Using the ProjectsController
|
||||
return new ProjectsController($scope, $state, Project, Machine, Member, Component, Theme, Licence, $document, Diacritics, dialogs, allowedExtensions, _t)
|
||||
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
|
||||
@ -474,9 +474,9 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// Store the project's details
|
||||
$scope.project = projectPromise
|
||||
$scope.projectUrl = $location.absUrl()
|
||||
$scope.disqusShortname = Fablab.disqusShortname
|
||||
$scope.project = projectPromise;
|
||||
$scope.projectUrl = $location.absUrl();
|
||||
$scope.disqusShortname = Fablab.disqusShortname;
|
||||
|
||||
/**
|
||||
* Test if the provided user has the edition rights on the current project
|
||||
@ -484,14 +484,14 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
* @returns boolean
|
||||
*/
|
||||
$scope.projectEditableBy = function (user) {
|
||||
if ((user == null)) { return false }
|
||||
if ($scope.project.author_id === user.id) { return true }
|
||||
let canEdit = false
|
||||
if ((user == null)) { return false; }
|
||||
if ($scope.project.author_id === user.id) { return true; }
|
||||
let canEdit = false;
|
||||
angular.forEach($scope.project.project_users, function (u) {
|
||||
if ((u.id === user.id) && u.is_valid) { return canEdit = true }
|
||||
})
|
||||
return canEdit
|
||||
}
|
||||
if ((u.id === user.id) && u.is_valid) { return canEdit = true; }
|
||||
});
|
||||
return canEdit;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if the provided user has the deletion rights on the current project
|
||||
@ -499,9 +499,9 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
* @returns boolean
|
||||
*/
|
||||
$scope.projectDeletableBy = function (user) {
|
||||
if ((user == null)) { return false }
|
||||
if ($scope.project.author_id === user.id) { return true }
|
||||
}
|
||||
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,
|
||||
@ -517,40 +517,40 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_project')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () { // cancel confirmed
|
||||
$scope.project.$delete(function () { $state.go('app.public.projects_list', {}, { reload: true }) })
|
||||
})
|
||||
$scope.project.$delete(function () { $state.go('app.public.projects_list', {}, { reload: true }); });
|
||||
});
|
||||
} else {
|
||||
return console.error(_t('unauthorized_operation'))
|
||||
return console.error(_t('unauthorized_operation'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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() }
|
||||
if (e) { e.preventDefault(); }
|
||||
|
||||
$uibModal.open({
|
||||
templateUrl: '<%= asset_path "shared/signalAbuseModal.html" %>',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
project () { return $scope.project }
|
||||
project () { return $scope.project; }
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '_t', 'growl', 'Abuse', 'project', function ($scope, $uibModalInstance, _t, growl, Abuse, project) {
|
||||
// signaler's profile & signalement infos
|
||||
$scope.signaler = {
|
||||
signaled_type: 'Project',
|
||||
signaled_id: project.id
|
||||
}
|
||||
};
|
||||
|
||||
// callback for signaling cancellation
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
|
||||
// callback for form validation
|
||||
return $scope.ok = function () {
|
||||
@ -559,27 +559,27 @@ Application.Controllers.controller('ShowProjectController', ['$scope', '$state',
|
||||
{ abuse: $scope.signaler },
|
||||
function (res) {
|
||||
// creation successful
|
||||
growl.success(_t('your_report_was_successful_thanks'))
|
||||
return $uibModalInstance.close(res)
|
||||
growl.success(_t('your_report_was_successful_thanks'));
|
||||
return $uibModalInstance.close(res);
|
||||
}
|
||||
, function (error) {
|
||||
// creation failed...
|
||||
growl.error(_t('an_error_occured_while_sending_your_report'))
|
||||
growl.error(_t('an_error_occured_while_sending_your_report'));
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.projects_show', { id: $scope.project.slug }, { absolute: true }).replace('#', '%23')}` }
|
||||
$scope.shareOnFacebook = function () { return `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
|
||||
*/
|
||||
$scope.shareOnTwitter = function () { return `https://twitter.com/intent/tweet?url=${encodeURIComponent($state.href('app.public.projects_show', { id: $scope.project.slug }, { absolute: true }))}&text=${encodeURIComponent($scope.project.name)}` }
|
||||
$scope.shareOnTwitter = function () { return `https://twitter.com/intent/tweet?url=${encodeURIComponent($state.href('app.public.projects_show', { id: $scope.project.slug }, { absolute: true }))}&text=${encodeURIComponent($scope.project.name)}`; };
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -41,24 +41,24 @@ class SpacesController {
|
||||
*/
|
||||
$scope.submited = function (content) {
|
||||
if ((content.id == null)) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
angular.forEach(content, function (v, k) {
|
||||
angular.forEach(v, function (err) {
|
||||
$scope.alerts.push({
|
||||
msg: k + ': ' + err,
|
||||
type: 'danger'
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$state.go('app.public.spaces_list')
|
||||
$state.go('app.public.spaces_list');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the current user's view, redirecting him to the spaces list
|
||||
*/
|
||||
$scope.cancel = function () { $state.go('app.public.spaces_list') }
|
||||
$scope.cancel = function () { $state.go('app.public.spaces_list'); };
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
@ -67,16 +67,16 @@ class SpacesController {
|
||||
*/
|
||||
$scope.fileinputClass = function (v) {
|
||||
if (v) {
|
||||
return 'fileinput-exists'
|
||||
return 'fileinput-exists';
|
||||
} else {
|
||||
return 'fileinput-new'
|
||||
return 'fileinput-new';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This will create a single new empty entry into the space attachments list.
|
||||
*/
|
||||
$scope.addFile = function () { $scope.space.space_files_attributes.push({}) }
|
||||
$scope.addFile = function () { $scope.space.space_files_attributes.push({}); };
|
||||
|
||||
/**
|
||||
* This will remove the given file from the space attachments list. If the file was previously uploaded
|
||||
@ -85,13 +85,13 @@ class SpacesController {
|
||||
* @param file {Object} the file to delete
|
||||
*/
|
||||
$scope.deleteFile = function (file) {
|
||||
const index = $scope.space.space_files_attributes.indexOf(file)
|
||||
const index = $scope.space.space_files_attributes.indexOf(file);
|
||||
if (file.id != null) {
|
||||
return file._destroy = true
|
||||
return file._destroy = true;
|
||||
} else {
|
||||
return $scope.space.space_files_attributes.splice(index, 1)
|
||||
return $scope.space.space_files_attributes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,92 +100,92 @@ class SpacesController {
|
||||
*/
|
||||
Application.Controllers.controller('SpacesController', ['$scope', '$state', 'spacesPromise', function ($scope, $state, spacesPromise) {
|
||||
// Retrieve the list of spaces
|
||||
$scope.spaces = spacesPromise
|
||||
$scope.spaces = spacesPromise;
|
||||
|
||||
/**
|
||||
* Redirect the user to the space details page
|
||||
*/
|
||||
$scope.showSpace = function (space) { $state.go('app.public.space_show', { id: space.slug }) }
|
||||
$scope.showSpace = function (space) { $state.go('app.public.space_show', { id: space.slug }); };
|
||||
|
||||
/**
|
||||
* Callback to book a reservation for the current space
|
||||
*/
|
||||
$scope.reserveSpace = function (space) { $state.go('app.logged.space_reserve', { id: space.slug }) }
|
||||
$scope.reserveSpace = function (space) { $state.go('app.logged.space_reserve', { id: space.slug }); };
|
||||
|
||||
// Default: we show only enabled spaces
|
||||
$scope.spaceFiltering = 'enabled'
|
||||
$scope.spaceFiltering = 'enabled';
|
||||
|
||||
// Available options for filtering spaces by status
|
||||
$scope.filterDisabled = [
|
||||
'enabled',
|
||||
'disabled',
|
||||
'all'
|
||||
]
|
||||
}])
|
||||
];
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Controller used in the space creation page (admin)
|
||||
*/
|
||||
Application.Controllers.controller('NewSpaceController', ['$scope', '$state', 'CSRF', function ($scope, $state, CSRF) {
|
||||
CSRF.setMetaTags()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = '/api/spaces/'
|
||||
$scope.actionUrl = '/api/spaces/';
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'post'
|
||||
$scope.method = 'post';
|
||||
|
||||
// default space parameters
|
||||
$scope.space =
|
||||
{ space_files_attributes: [] }
|
||||
{ space_files_attributes: [] };
|
||||
|
||||
// Using the SpacesController
|
||||
return new SpacesController($scope, $state)
|
||||
}])
|
||||
return new SpacesController($scope, $state);
|
||||
}]);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
CSRF.setMetaTags();
|
||||
|
||||
// API URL where the form will be posted
|
||||
$scope.actionUrl = `/api/spaces/${$stateParams.id}`
|
||||
$scope.actionUrl = `/api/spaces/${$stateParams.id}`;
|
||||
|
||||
// Form action on the above URL
|
||||
$scope.method = 'put'
|
||||
$scope.method = 'put';
|
||||
|
||||
// space to modify
|
||||
$scope.space = spacePromise
|
||||
$scope.space = spacePromise;
|
||||
|
||||
// Using the SpacesController
|
||||
return new SpacesController($scope, $state)
|
||||
}])
|
||||
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
|
||||
$scope.space = spacePromise
|
||||
$scope.space = spacePromise;
|
||||
|
||||
/**
|
||||
* 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 })
|
||||
}
|
||||
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-
|
||||
*/
|
||||
$scope.deleteSpace = function (event) {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return console.error(_t('space_show.unauthorized_operation'))
|
||||
return console.error(_t('space_show.unauthorized_operation'));
|
||||
} else {
|
||||
return dialogs.confirm({
|
||||
resolve: {
|
||||
@ -193,7 +193,7 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
|
||||
return {
|
||||
title: _t('space_show.confirmation_required'),
|
||||
msg: _t('space_show.do_you_really_want_to_delete_this_space')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,17 +201,17 @@ Application.Controllers.controller('ShowSpaceController', ['$scope', '$state', '
|
||||
// delete the machine then redirect to the machines listing
|
||||
$scope.space.$delete(
|
||||
function () {
|
||||
$state.go('app.public.spaces_list')
|
||||
$state.go('app.public.spaces_list');
|
||||
},
|
||||
function (error) {
|
||||
growl.warning(_t('space_show.the_space_cant_be_deleted_because_it_is_already_reserved_by_some_users'))
|
||||
console.error(error)
|
||||
growl.warning(_t('space_show.the_space_cant_be_deleted_because_it_is_already_reserved_by_some_users'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}])
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Controller used in the spaces reservation agenda page.
|
||||
@ -224,31 +224,31 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// Color of the selected event backgound
|
||||
const SELECTED_EVENT_BG_COLOR = '#ffdd00'
|
||||
const SELECTED_EVENT_BG_COLOR = '#ffdd00';
|
||||
|
||||
// Slot free to be booked
|
||||
const FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::SPACE_COLOR %>'
|
||||
const FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::SPACE_COLOR %>';
|
||||
|
||||
// Slot with reservation from current user
|
||||
const RESERVED_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::IS_RESERVED_BY_CURRENT_USER %>'
|
||||
const RESERVED_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::IS_RESERVED_BY_CURRENT_USER %>';
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// bind the spaces availabilities with full-Calendar events
|
||||
$scope.eventSources = [ { events: availabilitySpacesPromise, textColor: 'black' } ]
|
||||
$scope.eventSources = [ { events: availabilitySpacesPromise, textColor: 'black' } ];
|
||||
|
||||
// the user to deal with, ie. the current user for non-admins
|
||||
$scope.ctrl =
|
||||
{ member: {} }
|
||||
{ member: {} };
|
||||
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
$scope.plansClassifiedByGroup = [];
|
||||
for (let group of Array.from(groupsPromise)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] };
|
||||
for (let plan of Array.from(plansPromise)) {
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan) }
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan); }
|
||||
}
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
$scope.plansClassifiedByGroup.push(groupObj);
|
||||
}
|
||||
|
||||
// mapping of fullCalendar events.
|
||||
@ -258,135 +258,135 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
placable: null, // Destination slot for the change
|
||||
paid: [], // Slots that were just booked by the user (transaction ok)
|
||||
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
|
||||
$scope.selectionTime = null
|
||||
$scope.selectionTime = null;
|
||||
|
||||
// the last clicked event in the calender
|
||||
$scope.selectedEvent = null
|
||||
$scope.selectedEvent = null;
|
||||
|
||||
// indicates the state of the current view : calendar or plans information
|
||||
$scope.plansAreShown = false
|
||||
$scope.plansAreShown = false;
|
||||
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
|
||||
// the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.planSelectionTime = null
|
||||
$scope.planSelectionTime = null;
|
||||
|
||||
// Selected space
|
||||
$scope.space = spacePromise
|
||||
$scope.space = spacePromise;
|
||||
|
||||
// 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')),
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view)
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element, view)
|
||||
return eventRenderCb(event, element, view);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Application global settings
|
||||
$scope.settings = settingsPromise
|
||||
$scope.settings = settingsPromise;
|
||||
|
||||
// Global config: message to the end user concerning the subscriptions rules
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert;
|
||||
|
||||
// Global config: message to the end user concerning the space reservation
|
||||
$scope.spaceExplicationsAlert = settingsPromise.space_explications_alert
|
||||
$scope.spaceExplicationsAlert = settingsPromise.space_explications_alert;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
$scope.selectedEvent.backgroundColor = SELECTED_EVENT_BG_COLOR;
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the last selected slot's appearence to looks like 'never added to cart'
|
||||
*/
|
||||
$scope.markSlotAsRemoved = function (slot) {
|
||||
slot.backgroundColor = 'white'
|
||||
slot.title = ''
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
slot.id = null
|
||||
slot.isValid = false
|
||||
slot.is_reserved = false
|
||||
slot.can_modify = false
|
||||
slot.offered = false
|
||||
if (slot.is_completed) { slot.is_completed = false }
|
||||
return updateCalendar()
|
||||
}
|
||||
slot.backgroundColor = 'white';
|
||||
slot.title = '';
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR;
|
||||
slot.id = null;
|
||||
slot.isValid = false;
|
||||
slot.is_reserved = false;
|
||||
slot.can_modify = false;
|
||||
slot.offered = false;
|
||||
if (slot.is_completed) { slot.is_completed = false; }
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
*/
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent) }
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent); };
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
$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'
|
||||
*/
|
||||
$scope.changeModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
$scope.events.placable.title = ''
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = '';
|
||||
}
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
|
||||
$scope.selectedEvent.backgroundColor = '#bbb'
|
||||
$scope.selectedEvent.title = _t('space_reserve.i_shift')
|
||||
$scope.selectedEvent.backgroundColor = '#bbb';
|
||||
$scope.selectedEvent.title = _t('space_reserve.i_shift');
|
||||
}
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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'
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor
|
||||
$scope.events.placable.id = $scope.events.modifiable.id
|
||||
$scope.events.placable.is_reserved = true
|
||||
$scope.events.placable.can_modify = true
|
||||
$scope.events.placable.title = _t('space_reserve.i_ve_reserved');
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor;
|
||||
$scope.events.placable.id = $scope.events.modifiable.id;
|
||||
$scope.events.placable.is_reserved = true;
|
||||
$scope.events.placable.can_modify = true;
|
||||
|
||||
$scope.events.modifiable.backgroundColor = 'white'
|
||||
$scope.events.modifiable.title = ''
|
||||
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
$scope.events.modifiable.id = null
|
||||
$scope.events.modifiable.is_reserved = false
|
||||
$scope.events.modifiable.can_modify = false
|
||||
if ($scope.events.modifiable.is_completed) { $scope.events.modifiable.is_completed = false }
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
$scope.events.modifiable.title = '';
|
||||
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR;
|
||||
$scope.events.modifiable.id = null;
|
||||
$scope.events.modifiable.is_reserved = false;
|
||||
$scope.events.modifiable.can_modify = false;
|
||||
if ($scope.events.modifiable.is_completed) { $scope.events.modifiable.is_completed = false; }
|
||||
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
*/
|
||||
$scope.cancelModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
$scope.events.placable.title = ''
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = '';
|
||||
}
|
||||
$scope.events.modifiable.title = _t('space_reserve.i_ve_reserved')
|
||||
$scope.events.modifiable.backgroundColor = 'white'
|
||||
$scope.events.modifiable.title = _t('space_reserve.i_ve_reserved');
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
@ -395,22 +395,22 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
$scope.updateMember = function () {
|
||||
if ($scope.ctrl.member) {
|
||||
Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
||||
$scope.ctrl.member = member
|
||||
$scope.ctrl.member = member;
|
||||
return Availability.spaces({ spaceId: $scope.space.id, member_id: $scope.ctrl.member.id }, function (spaces) {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents')
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents');
|
||||
return $scope.eventSources.splice(0, 1, {
|
||||
events: spaces,
|
||||
textColor: 'black'
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
// as the events are re-fetched for the new user, we must re-init the cart
|
||||
$scope.events.reserved = []
|
||||
$scope.selectedPlan = null
|
||||
return $scope.plansAreShown = false
|
||||
}
|
||||
$scope.events.reserved = [];
|
||||
$scope.selectedPlan = null;
|
||||
return $scope.plansAreShown = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the provided plan to the current shopping cart
|
||||
@ -419,28 +419,28 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
$scope.selectPlan = function (plan) {
|
||||
// toggle selected plan
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
$scope.selectedPlan = plan
|
||||
$scope.selectedPlan = plan;
|
||||
} else {
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
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-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
e.preventDefault()
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
e.preventDefault();
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectedPlan = null;
|
||||
return $scope.planSelectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = function () { $scope.plansAreShown = true }
|
||||
$scope.showPlans = function () { $scope.plansAreShown = true; };
|
||||
|
||||
/**
|
||||
* Once the reservation is booked (payment process successfully completed), change the event style
|
||||
@ -449,32 +449,32 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
*/
|
||||
$scope.afterPayment = function (reservation) {
|
||||
angular.forEach($scope.events.paid, function (spaceSlot, key) {
|
||||
spaceSlot.is_reserved = true
|
||||
spaceSlot.can_modify = true
|
||||
spaceSlot.title = _t('space_reserve.i_ve_reserved')
|
||||
spaceSlot.backgroundColor = 'white'
|
||||
spaceSlot.borderColor = RESERVED_SLOT_BORDER_COLOR
|
||||
return updateSpaceSlotId(spaceSlot, reservation)
|
||||
})
|
||||
spaceSlot.is_reserved = true;
|
||||
spaceSlot.can_modify = true;
|
||||
spaceSlot.title = _t('space_reserve.i_ve_reserved');
|
||||
spaceSlot.backgroundColor = 'white';
|
||||
spaceSlot.borderColor = RESERVED_SLOT_BORDER_COLOR;
|
||||
return updateSpaceSlotId(spaceSlot, reservation);
|
||||
});
|
||||
|
||||
if ($scope.selectedPlan) {
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
$scope.ctrl.member.training_credits = angular.copy(reservation.user.training_credits)
|
||||
$scope.ctrl.member.machine_credits = angular.copy(reservation.user.machine_credits)
|
||||
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits)
|
||||
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits)
|
||||
$scope.ctrl.member.training_credits = angular.copy(reservation.user.training_credits);
|
||||
$scope.ctrl.member.machine_credits = angular.copy(reservation.user.machine_credits);
|
||||
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
|
||||
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
|
||||
|
||||
return refetchCalendar()
|
||||
}
|
||||
return refetchCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled }
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled; };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -483,9 +483,9 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return Member.get({ id: $scope.currentUser.id }, function (member) { $scope.ctrl.member = member })
|
||||
return Member.get({ id: $scope.currentUser.id }, function (member) { $scope.ctrl.member = member; });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when the user clicks on a reservation slot in the agenda.
|
||||
@ -495,12 +495,12 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
* @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.selectedEvent = event
|
||||
$scope.selectedEvent = event;
|
||||
if ($stateParams.id === 'all') {
|
||||
$scope.training = event.training
|
||||
$scope.training = event.training;
|
||||
}
|
||||
return $scope.selectionTime = new Date()
|
||||
}
|
||||
return $scope.selectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
@ -509,13 +509,13 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
*/
|
||||
var eventRenderCb = function (event, element, view) {
|
||||
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
|
||||
let html = ''
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
html += `<span class='label label-success text-white' title='${tag.name}'>${tag.name}</span>`
|
||||
html += `<span class='label label-success text-white' title='${tag.name}'>${tag.name}</span>`;
|
||||
}
|
||||
element.find('.fc-time').append(html)
|
||||
element.find('.fc-time').append(html);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
@ -526,28 +526,28 @@ Application.Controllers.controller('ReserveSpaceController', ['$scope', '$stateP
|
||||
var updateSpaceSlotId = function (slot, reservation) {
|
||||
angular.forEach(reservation.slots, function (s) {
|
||||
if (slot.start_at === slot.start_at) {
|
||||
return slot.id = s.id
|
||||
return slot.id = s.id;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the calendar's display to render the new attributes of the events
|
||||
*/
|
||||
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents') }
|
||||
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents'); };
|
||||
|
||||
/**
|
||||
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
*/
|
||||
var refetchCalendar = function () {
|
||||
$timeout(function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
})
|
||||
}
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents');
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -12,7 +12,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Public listing of the trainings
|
||||
@ -20,18 +20,18 @@
|
||||
Application.Controllers.controller('TrainingsController', ['$scope', '$state', 'trainingsPromise',
|
||||
function ($scope, $state, trainingsPromise) {
|
||||
// List of trainings
|
||||
$scope.trainings = trainingsPromise
|
||||
$scope.trainings = trainingsPromise;
|
||||
|
||||
/**
|
||||
* Callback for the 'reserve' button
|
||||
*/
|
||||
$scope.reserveTraining = function (training, event) { $state.go('app.logged.trainings_reserve', { id: training.slug }) }
|
||||
$scope.reserveTraining = function (training, event) { $state.go('app.logged.trainings_reserve', { id: training.slug }); };
|
||||
|
||||
/**
|
||||
* Callback for the 'show' button
|
||||
*/
|
||||
$scope.showTraining = function (training) { $state.go('app.public.training_show', { id: training.slug }) }
|
||||
}])
|
||||
$scope.showTraining = function (training) { $state.go('app.public.training_show', { id: training.slug }); };
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Public view of a specific training
|
||||
@ -39,7 +39,7 @@ Application.Controllers.controller('TrainingsController', ['$scope', '$state', '
|
||||
Application.Controllers.controller('ShowTrainingController', ['$scope', '$state', 'trainingPromise', 'growl', '_t', 'dialogs',
|
||||
function ($scope, $state, trainingPromise, growl, _t, dialogs) {
|
||||
// Current training
|
||||
$scope.training = trainingPromise
|
||||
$scope.training = trainingPromise;
|
||||
|
||||
/**
|
||||
* Callback to delete the current training (admins only)
|
||||
@ -47,7 +47,7 @@ Application.Controllers.controller('ShowTrainingController', ['$scope', '$state'
|
||||
$scope.delete = function (training) {
|
||||
// check the permissions
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
console.error(_t('unauthorized_operation'))
|
||||
console.error(_t('unauthorized_operation'));
|
||||
} else {
|
||||
dialogs.confirm(
|
||||
{
|
||||
@ -56,34 +56,34 @@ Application.Controllers.controller('ShowTrainingController', ['$scope', '$state'
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_this_training')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // deletion confirmed
|
||||
// delete the training then redirect to the trainings listing
|
||||
training.$delete(
|
||||
function () { $state.go('app.public.trainings_list') },
|
||||
function () { $state.go('app.public.trainings_list'); },
|
||||
function (error) {
|
||||
growl.warning(_t('the_training_cant_be_deleted_because_it_is_already_reserved_by_some_users'))
|
||||
console.error(error)
|
||||
growl.warning(_t('the_training_cant_be_deleted_because_it_is_already_reserved_by_some_users'));
|
||||
console.error(error);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for the 'reserve' button
|
||||
*/
|
||||
$scope.reserveTraining = function (training, event) { $state.go('app.logged.trainings_reserve', { id: training.id }) }
|
||||
$scope.reserveTraining = function (training, event) { $state.go('app.logged.trainings_reserve', { id: training.id }); };
|
||||
|
||||
/**
|
||||
* Revert view to the full list of trainings ("<-" button)
|
||||
*/
|
||||
$scope.cancel = function (event) { $state.go('app.public.trainings_list') }
|
||||
}])
|
||||
$scope.cancel = function (event) { $state.go('app.public.trainings_list'); };
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Controller used in the training reservation agenda page.
|
||||
@ -96,28 +96,28 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// Color of the selected event backgound
|
||||
const SELECTED_EVENT_BG_COLOR = '#ffdd00'
|
||||
const SELECTED_EVENT_BG_COLOR = '#ffdd00';
|
||||
|
||||
// Slot free to be booked
|
||||
const FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::TRAINING_COLOR %>'
|
||||
const FREE_SLOT_BORDER_COLOR = '<%= AvailabilityHelper::TRAINING_COLOR %>';
|
||||
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// bind the trainings availabilities with full-Calendar events
|
||||
$scope.eventSources = [ { events: availabilityTrainingsPromise, textColor: 'black' } ]
|
||||
$scope.eventSources = [ { events: availabilityTrainingsPromise, textColor: 'black' } ];
|
||||
|
||||
// the user to deal with, ie. the current user for non-admins
|
||||
$scope.ctrl =
|
||||
{ member: {} }
|
||||
{ member: {} };
|
||||
|
||||
// list of plans, classified by group
|
||||
$scope.plansClassifiedByGroup = []
|
||||
$scope.plansClassifiedByGroup = [];
|
||||
for (let group of Array.from(groupsPromise)) {
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] }
|
||||
const groupObj = { id: group.id, name: group.name, plans: [] };
|
||||
for (let plan of Array.from(plansPromise)) {
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan) }
|
||||
if (plan.group_id === group.id) { groupObj.plans.push(plan); }
|
||||
}
|
||||
$scope.plansClassifiedByGroup.push(groupObj)
|
||||
$scope.plansClassifiedByGroup.push(groupObj);
|
||||
}
|
||||
|
||||
// mapping of fullCalendar events.
|
||||
@ -127,141 +127,141 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
placable: null, // Destination slot for the change
|
||||
paid: [], // Slots that were just booked by the user (transaction ok)
|
||||
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
|
||||
$scope.selectionTime = null
|
||||
$scope.selectionTime = null;
|
||||
|
||||
// the last clicked event in the calender
|
||||
$scope.selectedEvent = null
|
||||
$scope.selectedEvent = null;
|
||||
|
||||
// indicates the state of the current view : calendar or plans information
|
||||
$scope.plansAreShown = false
|
||||
$scope.plansAreShown = false;
|
||||
|
||||
// will store the user's plan if he choosed to buy one
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
|
||||
// the moment when the plan selection changed for the last time, used to trigger changes in the cart
|
||||
$scope.planSelectionTime = null
|
||||
$scope.planSelectionTime = null;
|
||||
|
||||
// Selected training
|
||||
$scope.training = trainingPromise
|
||||
$scope.training = trainingPromise;
|
||||
|
||||
// 'all' OR training's slug
|
||||
$scope.mode = $stateParams.id
|
||||
$scope.mode = $stateParams.id;
|
||||
|
||||
// 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')),
|
||||
eventClick (event, jsEvent, view) {
|
||||
return calendarEventClickCb(event, jsEvent, view)
|
||||
return calendarEventClickCb(event, jsEvent, view);
|
||||
},
|
||||
eventRender (event, element, view) {
|
||||
return eventRenderCb(event, element, view)
|
||||
return eventRenderCb(event, element, view);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Application global settings
|
||||
$scope.settings = settingsPromise
|
||||
$scope.settings = settingsPromise;
|
||||
|
||||
// Global config: message to the end user concerning the subscriptions rules
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert
|
||||
$scope.subscriptionExplicationsAlert = settingsPromise.subscription_explications_alert;
|
||||
|
||||
// Global config: message to the end user concerning the training reservation
|
||||
$scope.trainingExplicationsAlert = settingsPromise.training_explications_alert
|
||||
$scope.trainingExplicationsAlert = settingsPromise.training_explications_alert;
|
||||
|
||||
// Global config: message to the end user giving advice about the training reservation
|
||||
$scope.trainingInformationMessage = settingsPromise.training_information_message
|
||||
$scope.trainingInformationMessage = settingsPromise.training_information_message;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
$scope.selectedEvent.backgroundColor = SELECTED_EVENT_BG_COLOR;
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
slot.id = null
|
||||
slot.isValid = false
|
||||
slot.is_reserved = false
|
||||
slot.can_modify = false
|
||||
slot.offered = false
|
||||
if (slot.is_completed) { slot.is_completed = false }
|
||||
return updateCalendar()
|
||||
}
|
||||
slot.backgroundColor = 'white';
|
||||
slot.title = slot.training.name;
|
||||
slot.borderColor = FREE_SLOT_BORDER_COLOR;
|
||||
slot.id = null;
|
||||
slot.isValid = false;
|
||||
slot.is_reserved = false;
|
||||
slot.can_modify = false;
|
||||
slot.offered = false;
|
||||
if (slot.is_completed) { slot.is_completed = false; }
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback when a slot was successfully cancelled. Reset the slot style as 'ready to book'
|
||||
*/
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent) }
|
||||
$scope.slotCancelled = function () { $scope.markSlotAsRemoved($scope.selectedEvent); };
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
$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'
|
||||
*/
|
||||
$scope.changeModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
$scope.events.placable.title = $scope.events.placable.training.name
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = $scope.events.placable.training.name;
|
||||
}
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.selectedEvent._id)) {
|
||||
$scope.selectedEvent.backgroundColor = '#bbb'
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('i_shift')
|
||||
$scope.selectedEvent.backgroundColor = '#bbb';
|
||||
$scope.selectedEvent.title = $scope.selectedEvent.training.name + ' - ' + _t('i_shift');
|
||||
}
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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'
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor
|
||||
$scope.events.placable.id = $scope.events.modifiable.id
|
||||
$scope.events.placable.is_reserved = true
|
||||
$scope.events.placable.can_modify = true
|
||||
$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';
|
||||
$scope.events.placable.borderColor = $scope.events.modifiable.borderColor;
|
||||
$scope.events.placable.id = $scope.events.modifiable.id;
|
||||
$scope.events.placable.is_reserved = true;
|
||||
$scope.events.placable.can_modify = true;
|
||||
|
||||
$scope.events.modifiable.backgroundColor = 'white'
|
||||
$scope.events.modifiable.title = $scope.events.modifiable.training.name
|
||||
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR
|
||||
$scope.events.modifiable.id = null
|
||||
$scope.events.modifiable.is_reserved = false
|
||||
$scope.events.modifiable.can_modify = false
|
||||
if ($scope.events.modifiable.is_completed) { $scope.events.modifiable.is_completed = false }
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
$scope.events.modifiable.title = $scope.events.modifiable.training.name;
|
||||
$scope.events.modifiable.borderColor = FREE_SLOT_BORDER_COLOR;
|
||||
$scope.events.modifiable.id = null;
|
||||
$scope.events.modifiable.is_reserved = false;
|
||||
$scope.events.modifiable.can_modify = false;
|
||||
if ($scope.events.modifiable.is_completed) { $scope.events.modifiable.is_completed = false; }
|
||||
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the current booking modification, reseting the whole process
|
||||
*/
|
||||
$scope.cancelModifyTrainingSlot = function () {
|
||||
if ($scope.events.placable) {
|
||||
$scope.events.placable.backgroundColor = 'white'
|
||||
$scope.events.placable.title = $scope.events.placable.training.name
|
||||
$scope.events.placable.backgroundColor = 'white';
|
||||
$scope.events.placable.title = $scope.events.placable.training.name;
|
||||
}
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? $scope.events.modifiable.training.name + ' - ' + _t('i_ve_reserved') : $scope.events.modifiable.training.name
|
||||
$scope.events.modifiable.backgroundColor = 'white'
|
||||
$scope.events.modifiable.title = $scope.currentUser.role !== 'admin' ? $scope.events.modifiable.training.name + ' - ' + _t('i_ve_reserved') : $scope.events.modifiable.training.name;
|
||||
$scope.events.modifiable.backgroundColor = 'white';
|
||||
|
||||
return updateCalendar()
|
||||
}
|
||||
return updateCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to deal with the reservations of the user selected in the dropdown list instead of the current user's
|
||||
@ -270,23 +270,23 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
$scope.updateMember = function () {
|
||||
if ($scope.ctrl.member) {
|
||||
Member.get({ id: $scope.ctrl.member.id }, function (member) {
|
||||
$scope.ctrl.member = member
|
||||
const id = $stateParams.id === 'all' ? $stateParams.id : $scope.training.id
|
||||
$scope.ctrl.member = member;
|
||||
const id = $stateParams.id === 'all' ? $stateParams.id : $scope.training.id;
|
||||
return Availability.trainings({ trainingId: id, member_id: $scope.ctrl.member.id }, function (trainings) {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents')
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('removeEvents');
|
||||
return $scope.eventSources.splice(0, 1, {
|
||||
events: trainings,
|
||||
textColor: 'black'
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
// as the events are re-fetched for the new user, we must re-init the cart
|
||||
$scope.events.reserved = []
|
||||
$scope.selectedPlan = null
|
||||
return $scope.plansAreShown = false
|
||||
}
|
||||
$scope.events.reserved = [];
|
||||
$scope.selectedPlan = null;
|
||||
return $scope.plansAreShown = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the provided plan to the current shopping cart
|
||||
@ -295,28 +295,28 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
$scope.selectPlan = function (plan) {
|
||||
// toggle selected plan
|
||||
if ($scope.selectedPlan !== plan) {
|
||||
$scope.selectedPlan = plan
|
||||
$scope.selectedPlan = plan;
|
||||
} else {
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
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-
|
||||
*/
|
||||
$scope.doNotSubscribePlan = function (e) {
|
||||
e.preventDefault()
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
return $scope.planSelectionTime = new Date()
|
||||
}
|
||||
e.preventDefault();
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectedPlan = null;
|
||||
return $scope.planSelectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
*/
|
||||
$scope.showPlans = function () { $scope.plansAreShown = true }
|
||||
$scope.showPlans = function () { $scope.plansAreShown = true; };
|
||||
|
||||
/**
|
||||
* Once the reservation is booked (payment process successfully completed), change the event style
|
||||
@ -324,31 +324,31 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
* @param reservation {Object}
|
||||
*/
|
||||
$scope.afterPayment = function (reservation) {
|
||||
$scope.events.paid[0].backgroundColor = 'white'
|
||||
$scope.events.paid[0].is_reserved = true
|
||||
$scope.events.paid[0].can_modify = true
|
||||
updateTrainingSlotId($scope.events.paid[0], reservation)
|
||||
$scope.events.paid[0].borderColor = '#b2e774'
|
||||
$scope.events.paid[0].title = $scope.events.paid[0].training.name + ' - ' + _t('i_ve_reserved')
|
||||
$scope.events.paid[0].backgroundColor = 'white';
|
||||
$scope.events.paid[0].is_reserved = true;
|
||||
$scope.events.paid[0].can_modify = true;
|
||||
updateTrainingSlotId($scope.events.paid[0], reservation);
|
||||
$scope.events.paid[0].borderColor = '#b2e774';
|
||||
$scope.events.paid[0].title = $scope.events.paid[0].training.name + ' - ' + _t('i_ve_reserved');
|
||||
|
||||
if ($scope.selectedPlan) {
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan)
|
||||
$scope.plansAreShown = false
|
||||
$scope.selectedPlan = null
|
||||
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
|
||||
$scope.plansAreShown = false;
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
$scope.ctrl.member.training_credits = angular.copy(reservation.user.training_credits)
|
||||
$scope.ctrl.member.machine_credits = angular.copy(reservation.user.machine_credits)
|
||||
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits)
|
||||
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits)
|
||||
$scope.ctrl.member.training_credits = angular.copy(reservation.user.training_credits);
|
||||
$scope.ctrl.member.machine_credits = angular.copy(reservation.user.machine_credits);
|
||||
Auth._currentUser.training_credits = angular.copy(reservation.user.training_credits);
|
||||
Auth._currentUser.machine_credits = angular.copy(reservation.user.machine_credits);
|
||||
|
||||
return refetchCalendar()
|
||||
}
|
||||
return refetchCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* To use as callback in Array.prototype.filter to get only enabled plans
|
||||
*/
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled }
|
||||
$scope.filterDisabledPlans = function (plan) { return !plan.disabled; };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -357,9 +357,9 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
*/
|
||||
const initialize = function () {
|
||||
if ($scope.currentUser.role !== 'admin') {
|
||||
return Member.get({ id: $scope.currentUser.id }, function (member) { $scope.ctrl.member = member })
|
||||
return Member.get({ id: $scope.currentUser.id }, function (member) { $scope.ctrl.member = member; });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when the user clicks on a reservation slot in the agenda.
|
||||
@ -369,12 +369,12 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
* @see http://fullcalendar.io/docs/mouse/eventClick/
|
||||
*/
|
||||
var calendarEventClickCb = function (event, jsEvent, view) {
|
||||
$scope.selectedEvent = event
|
||||
$scope.selectedEvent = event;
|
||||
if ($stateParams.id === 'all') {
|
||||
$scope.training = event.training
|
||||
$scope.training = event.training;
|
||||
}
|
||||
return $scope.selectionTime = new Date()
|
||||
}
|
||||
return $scope.selectionTime = new Date();
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggered when fullCalendar tries to graphicaly render an event block.
|
||||
@ -383,13 +383,13 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
*/
|
||||
var eventRenderCb = function (event, element, view) {
|
||||
if (($scope.currentUser.role === 'admin') && (event.tags.length > 0)) {
|
||||
let html = ''
|
||||
let html = '';
|
||||
for (let tag of Array.from(event.tags)) {
|
||||
html += `<span class='label label-success text-white' title='${tag.name}'>${tag.name}</span>`
|
||||
html += `<span class='label label-success text-white' title='${tag.name}'>${tag.name}</span>`;
|
||||
}
|
||||
element.find('.fc-time').append(html)
|
||||
element.find('.fc-time').append(html);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* After payment, update the id of the newly reserved slot with the id returned by the server.
|
||||
@ -400,28 +400,28 @@ Application.Controllers.controller('ReserveTrainingController', ['$scope', '$sta
|
||||
var updateTrainingSlotId = function (slot, reservation) {
|
||||
angular.forEach(reservation.slots, function (s) {
|
||||
if (slot.start_at === slot.start_at) {
|
||||
return slot.id = s.id
|
||||
return slot.id = s.id;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the calendar's display to render the new attributes of the events
|
||||
*/
|
||||
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents') }
|
||||
var updateCalendar = function () { uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents'); };
|
||||
|
||||
/**
|
||||
* Asynchronously fetch the events from the API and refresh the calendar's view with these new events
|
||||
*/
|
||||
var refetchCalendar = function () {
|
||||
$timeout(function () {
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents')
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents')
|
||||
})
|
||||
}
|
||||
uiCalendarConfig.calendars.calendar.fullCalendar('refetchEvents');
|
||||
return uiCalendarConfig.calendars.calendar.fullCalendar('rerenderEvents');
|
||||
});
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -9,16 +9,16 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('WalletController', ['$scope', 'walletPromise', 'transactionsPromise',
|
||||
function ($scope, walletPromise, transactionsPromise) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// current user wallet
|
||||
$scope.wallet = walletPromise
|
||||
$scope.wallet = walletPromise;
|
||||
|
||||
// current wallet transactions
|
||||
return $scope.transactions = transactionsPromise
|
||||
return $scope.transactions = transactionsPromise;
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -1,34 +1,34 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Directives.directive('bsJasnyFileinput', [function () {
|
||||
return {
|
||||
require: ['ngModel'],
|
||||
link: function ($scope, elm, attrs, requiredCtrls) {
|
||||
var ngModelCtrl = requiredCtrls[0]
|
||||
var fileinput = elm.parents('[data-provides=fileinput]')
|
||||
var filetypeRegex = attrs.bsJasnyFileinput
|
||||
var ngModelCtrl = requiredCtrls[0];
|
||||
var fileinput = elm.parents('[data-provides=fileinput]');
|
||||
var filetypeRegex = attrs.bsJasnyFileinput;
|
||||
fileinput.on('clear.bs.fileinput', function (e) {
|
||||
if (ngModelCtrl) {
|
||||
ngModelCtrl.$setViewValue(null)
|
||||
ngModelCtrl.$setPristine()
|
||||
$scope.$apply()
|
||||
ngModelCtrl.$setViewValue(null);
|
||||
ngModelCtrl.$setPristine();
|
||||
$scope.$apply();
|
||||
}
|
||||
})
|
||||
});
|
||||
fileinput.on('change.bs.fileinput', function (e, files) {
|
||||
if (ngModelCtrl) {
|
||||
if (files) {
|
||||
ngModelCtrl.$setViewValue(files.result)
|
||||
ngModelCtrl.$setViewValue(files.result);
|
||||
} else {
|
||||
ngModelCtrl.$setPristine()
|
||||
ngModelCtrl.$setPristine();
|
||||
}
|
||||
|
||||
// TODO: ne marche pas pour filetype
|
||||
if (filetypeRegex) {
|
||||
if (files && typeof files.type !== 'undefined' && files.type.match(new RegExp(filetypeRegex))) { ngModelCtrl.$setValidity('filetype', true) } else { ngModelCtrl.$setValidity('filetype', false) }
|
||||
if (files && typeof files.type !== 'undefined' && files.type.match(new RegExp(filetypeRegex))) { ngModelCtrl.$setValidity('filetype', true); } else { ngModelCtrl.$setValidity('filetype', false); }
|
||||
};
|
||||
}
|
||||
$scope.$apply()
|
||||
})
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
}
|
||||
}])
|
||||
};
|
||||
}]);
|
||||
|
@ -40,28 +40,28 @@ 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
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
|
||||
// total amount of the bill to pay
|
||||
$scope.amountTotal = 0
|
||||
$scope.amountTotal = 0;
|
||||
|
||||
// total amount of the elements in the cart, without considering any coupon
|
||||
$scope.totalNoCoupon = 0
|
||||
$scope.totalNoCoupon = 0;
|
||||
|
||||
// Discount coupon to apply to the basket, if any
|
||||
$scope.coupon = { applied: null }
|
||||
$scope.coupon = { applied: null };
|
||||
|
||||
// Global config: is the user authorized to change his bookings slots?
|
||||
$scope.enableBookingMove = ($scope.settings.booking_move_enable === 'true')
|
||||
$scope.enableBookingMove = ($scope.settings.booking_move_enable === 'true');
|
||||
|
||||
// Global config: delay in hours before a booking while changing the booking slot is forbidden
|
||||
$scope.moveBookingDelay = parseInt($scope.settings.booking_move_delay)
|
||||
$scope.moveBookingDelay = parseInt($scope.settings.booking_move_delay);
|
||||
|
||||
// Global config: is the user authorized to cancel his bookings?
|
||||
$scope.enableBookingCancel = ($scope.settings.booking_cancel_enable === 'true')
|
||||
$scope.enableBookingCancel = ($scope.settings.booking_cancel_enable === 'true');
|
||||
|
||||
// Global config: delay in hours before a booking while the cancellation is forbidden
|
||||
$scope.cancelBookingDelay = parseInt($scope.settings.booking_cancel_delay)
|
||||
$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')
|
||||
@ -69,9 +69,9 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
* @param slot {Object} fullCalendar event object
|
||||
*/
|
||||
$scope.validateSlot = function (slot) {
|
||||
slot.isValid = true
|
||||
return updateCartPrice()
|
||||
}
|
||||
slot.isValid = true;
|
||||
return updateCartPrice();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the provided slot from the shopping cart (state transition from 'about to be reserved' to free)
|
||||
@ -81,29 +81,29 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
* @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)
|
||||
if (event) { event.preventDefault(); }
|
||||
$scope.events.reserved.splice(index, 1);
|
||||
// if is was the last slot, we remove any plan from the cart
|
||||
if ($scope.events.reserved.length === 0) {
|
||||
$scope.selectedPlan = null
|
||||
$scope.plan = null
|
||||
$scope.modePlans = false
|
||||
$scope.selectedPlan = null;
|
||||
$scope.plan = null;
|
||||
$scope.modePlans = false;
|
||||
}
|
||||
if (typeof $scope.onSlotRemovedFromCart === 'function') { $scope.onSlotRemovedFromCart(slot) }
|
||||
return updateCartPrice()
|
||||
}
|
||||
if (typeof $scope.onSlotRemovedFromCart === 'function') { $scope.onSlotRemovedFromCart(slot); }
|
||||
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.
|
||||
*/
|
||||
$scope.isSlotsValid = function () {
|
||||
let isValid = true
|
||||
let isValid = true;
|
||||
angular.forEach($scope.events.reserved, function (m) {
|
||||
if (!m.isValid) { return isValid = false }
|
||||
})
|
||||
return isValid
|
||||
}
|
||||
if (!m.isValid) { return isValid = false; }
|
||||
});
|
||||
return isValid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Switch the user's view from the reservation agenda to the plan subscription
|
||||
@ -111,12 +111,12 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
$scope.showPlans = function () {
|
||||
// first, we ensure that a user was selected (admin) or logged (member)
|
||||
if (Object.keys($scope.user).length > 0) {
|
||||
return $scope.modePlans = true
|
||||
return $scope.modePlans = true;
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user hasn't the admin role
|
||||
return growl.error(_t('cart.please_select_a_member_first'))
|
||||
return growl.error(_t('cart.please_select_a_member_first'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the shopping chart and redirect the user to the payment step
|
||||
@ -124,23 +124,23 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
$scope.payCart = function () {
|
||||
// first, we check that a user was selected
|
||||
if (Object.keys($scope.user).length > 0) {
|
||||
const reservation = mkReservation($scope.user, $scope.events.reserved, $scope.selectedPlan)
|
||||
const reservation = mkReservation($scope.user, $scope.events.reserved, $scope.selectedPlan);
|
||||
|
||||
return Wallet.getWalletByUser({ user_id: $scope.user.id }, function (wallet) {
|
||||
const amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount)
|
||||
const amountToPay = helpers.getAmountToPay($scope.amountTotal, wallet.amount);
|
||||
if (!$scope.isAdmin() && (amountToPay > 0)) {
|
||||
return payByStripe(reservation)
|
||||
return payByStripe(reservation);
|
||||
} else {
|
||||
if ($scope.isAdmin() || (amountToPay === 0)) {
|
||||
return payOnSite(reservation)
|
||||
return payOnSite(reservation);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user is not admin
|
||||
return growl.error(_t('cart.please_select_a_member_first'))
|
||||
return growl.error(_t('cart.please_select_a_member_first'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* When modifying an already booked reservation, confirm the modification.
|
||||
@ -155,62 +155,62 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
, function () { // success
|
||||
// -> run the callback
|
||||
if (typeof $scope.onSlotModifySuccess === 'function') { $scope.onSlotModifySuccess() }
|
||||
if (typeof $scope.onSlotModifySuccess === 'function') { $scope.onSlotModifySuccess(); }
|
||||
// -> set the events as successfully moved (to display a summary)
|
||||
$scope.events.moved = {
|
||||
newSlot: $scope.events.placable,
|
||||
oldSlot: $scope.events.modifiable
|
||||
}
|
||||
};
|
||||
// -> reset the 'moving' status
|
||||
$scope.events.placable = null
|
||||
return $scope.events.modifiable = null
|
||||
$scope.events.placable = null;
|
||||
return $scope.events.modifiable = null;
|
||||
}
|
||||
, function (err) { // failure
|
||||
growl.error(_t('cart.unable_to_change_the_reservation'))
|
||||
return console.error(err)
|
||||
})
|
||||
}
|
||||
growl.error(_t('cart.unable_to_change_the_reservation'));
|
||||
return console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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() }
|
||||
$scope.events.placable = null
|
||||
return $scope.events.modifiable = null
|
||||
}
|
||||
if (event) { event.preventDefault(); }
|
||||
if (typeof $scope.onSlotModifyCancel === 'function') { $scope.onSlotModifyCancel(); }
|
||||
$scope.events.placable = null;
|
||||
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-
|
||||
*/
|
||||
$scope.removeSlotToPlace = function (e) {
|
||||
e.preventDefault()
|
||||
if (typeof $scope.onSlotModifyUnselect === 'function') { $scope.onSlotModifyUnselect() }
|
||||
return $scope.events.placable = null
|
||||
}
|
||||
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
|
||||
*/
|
||||
$scope.tagMissmatch = function () {
|
||||
if ($scope.events.placable.tag_ids.length === 0) { return false }
|
||||
if ($scope.events.placable.tag_ids.length === 0) { return false; }
|
||||
for (let tag of Array.from($scope.events.modifiable.tags)) {
|
||||
if (!Array.from($scope.events.placable.tag_ids).includes(tag.id)) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the currently logged user has teh 'admin' role?
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$scope.isAdmin = function () { return $rootScope.currentUser && ($rootScope.currentUser.role === 'admin') }
|
||||
$scope.isAdmin = function () { return $rootScope.currentUser && ($rootScope.currentUser.role === 'admin'); };
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -221,27 +221,27 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
// What the bound slot
|
||||
$scope.$watch('slotSelectionTime', function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
return slotSelectionChanged()
|
||||
return slotSelectionChanged();
|
||||
}
|
||||
})
|
||||
});
|
||||
$scope.$watch('user', function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
resetCartState()
|
||||
return updateCartPrice()
|
||||
resetCartState();
|
||||
return updateCartPrice();
|
||||
}
|
||||
})
|
||||
});
|
||||
$scope.$watch('planSelectionTime', function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
return planSelectionChanged()
|
||||
return planSelectionChanged();
|
||||
}
|
||||
})
|
||||
});
|
||||
// watch when a coupon is applied to re-compute the total price
|
||||
return $scope.$watch('coupon.applied', function (newValue, oldValue) {
|
||||
if ((newValue !== null) || (oldValue !== null)) {
|
||||
return updateCartPrice()
|
||||
return updateCartPrice();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when the selected slot changed
|
||||
@ -251,57 +251,57 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
if (!$scope.slot.is_reserved && !$scope.events.modifiable && !$scope.slot.is_completed) {
|
||||
// slot is not reserved and we are not currently modifying a slot
|
||||
// -> can be added to cart or removed if already present
|
||||
const index = $scope.events.reserved.indexOf($scope.slot)
|
||||
const index = $scope.events.reserved.indexOf($scope.slot);
|
||||
if (index === -1) {
|
||||
if (($scope.limitToOneSlot === 'true') && $scope.events.reserved[0]) {
|
||||
// if we limit the number of slots in the cart to 1, and there is already
|
||||
// a slot in the cart, we remove it before adding the new one
|
||||
$scope.removeSlot($scope.events.reserved[0], 0)
|
||||
$scope.removeSlot($scope.events.reserved[0], 0);
|
||||
}
|
||||
// slot is not in the cart, so we add it
|
||||
$scope.events.reserved.push($scope.slot)
|
||||
if (typeof $scope.onSlotAddedToCart === 'function') { $scope.onSlotAddedToCart() }
|
||||
$scope.events.reserved.push($scope.slot);
|
||||
if (typeof $scope.onSlotAddedToCart === 'function') { $scope.onSlotAddedToCart(); }
|
||||
} else {
|
||||
// slot is in the cart, remove it
|
||||
$scope.removeSlot($scope.slot, index)
|
||||
$scope.removeSlot($scope.slot, index);
|
||||
}
|
||||
// in every cases, because a new reservation has started, we reset the cart content
|
||||
resetCartState()
|
||||
resetCartState();
|
||||
// finally, we update the prices
|
||||
return updateCartPrice()
|
||||
return updateCartPrice();
|
||||
} else if (!$scope.slot.is_reserved && !$scope.slot.is_completed && $scope.events.modifiable) {
|
||||
// slot is not reserved but we are currently modifying a slot
|
||||
// -> we request the calender to change the rendering
|
||||
if (typeof $scope.onSlotModifyUnselect === 'function') { $scope.onSlotModifyUnselect() }
|
||||
if (typeof $scope.onSlotModifyUnselect === 'function') { $scope.onSlotModifyUnselect(); }
|
||||
// -> then, we re-affect the destination slot
|
||||
if (!$scope.events.placable || ($scope.events.placable._id !== $scope.slot._id)) {
|
||||
return $scope.events.placable = $scope.slot
|
||||
return $scope.events.placable = $scope.slot;
|
||||
} else {
|
||||
return $scope.events.placable = null
|
||||
return $scope.events.placable = null;
|
||||
}
|
||||
} else if ($scope.slot.is_reserved && $scope.events.modifiable && ($scope.slot.is_reserved._id === $scope.events.modifiable._id)) {
|
||||
// slot is reserved and currently modified
|
||||
// -> we cancel the modification
|
||||
return $scope.cancelModifySlot()
|
||||
return $scope.cancelModifySlot();
|
||||
} else if ($scope.slot.is_reserved && (slotCanBeModified($scope.slot) || slotCanBeCanceled($scope.slot)) && !$scope.events.modifiable && ($scope.events.reserved.length === 0)) {
|
||||
// slot is reserved and is ok to be modified or cancelled
|
||||
// but we are not currently running a modification or having any slots in the cart
|
||||
// -> first the affect the modification/cancellation rights attributes to the current slot
|
||||
resetCartState()
|
||||
$scope.slot.movable = slotCanBeModified($scope.slot)
|
||||
$scope.slot.cancelable = slotCanBeCanceled($scope.slot)
|
||||
resetCartState();
|
||||
$scope.slot.movable = slotCanBeModified($scope.slot);
|
||||
$scope.slot.cancelable = slotCanBeCanceled($scope.slot);
|
||||
// -> then, we open a dialog to ask to the user to choose an action
|
||||
return dialogs.confirm({
|
||||
templateUrl: '<%= asset_path "shared/confirm_modify_slot_modal.html" %>',
|
||||
resolve: {
|
||||
object () { return $scope.slot }
|
||||
object () { return $scope.slot; }
|
||||
}
|
||||
}
|
||||
, function (type) {
|
||||
// the user has choosen an action, so we proceed
|
||||
if (type === 'move') {
|
||||
if (typeof $scope.onSlotStartToModify === 'function') { $scope.onSlotStartToModify() }
|
||||
return $scope.events.modifiable = $scope.slot
|
||||
if (typeof $scope.onSlotStartToModify === 'function') { $scope.onSlotStartToModify(); }
|
||||
return $scope.events.modifiable = $scope.slot;
|
||||
} else if (type === 'cancel') {
|
||||
return dialogs.confirm(
|
||||
{
|
||||
@ -310,67 +310,67 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return {
|
||||
title: _t('cart.confirmation_required'),
|
||||
msg: _t('cart.do_you_really_want_to_cancel_this_reservation')
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
function () { // cancel confirmed
|
||||
Slot.cancel({ id: $scope.slot.id }, function () { // successfully canceled
|
||||
growl.success(_t('cart.reservation_was_cancelled_successfully'))
|
||||
if (typeof $scope.onSlotCancelSuccess === 'function') { return $scope.onSlotCancelSuccess() }
|
||||
growl.success(_t('cart.reservation_was_cancelled_successfully'));
|
||||
if (typeof $scope.onSlotCancelSuccess === 'function') { return $scope.onSlotCancelSuccess(); }
|
||||
}
|
||||
, function () { // error while canceling
|
||||
growl.error(_t('cart.cancellation_failed'))
|
||||
})
|
||||
growl.error(_t('cart.cancellation_failed'));
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
$scope.events.moved = null
|
||||
$scope.events.paid = []
|
||||
$scope.events.modifiable = null
|
||||
return $scope.events.placable = null
|
||||
}
|
||||
$scope.selectedPlan = null;
|
||||
$scope.coupon.applied = null;
|
||||
$scope.events.moved = null;
|
||||
$scope.events.paid = [];
|
||||
$scope.events.modifiable = null;
|
||||
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
|
||||
*/
|
||||
var slotCanBeModified = function (slot) {
|
||||
if ($scope.isAdmin()) { return true }
|
||||
const slotStart = moment(slot.start)
|
||||
const now = moment()
|
||||
if ($scope.isAdmin()) { return true; }
|
||||
const slotStart = moment(slot.start);
|
||||
const now = moment();
|
||||
if (slot.can_modify && $scope.enableBookingMove && (slotStart.diff(now, 'hours') >= $scope.moveBookingDelay)) {
|
||||
return true
|
||||
return true;
|
||||
} else {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
const now = moment()
|
||||
if ($scope.isAdmin()) { return true; }
|
||||
const slotStart = moment(slot.start);
|
||||
const now = moment();
|
||||
if (slot.can_modify && $scope.enableBookingCancel && (slotStart.diff(now, 'hours') >= $scope.cancelBookingDelay)) {
|
||||
return true
|
||||
return true;
|
||||
} else {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when the selected slot changed
|
||||
@ -378,47 +378,47 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
var planSelectionChanged = function () {
|
||||
if (Auth.isAuthenticated()) {
|
||||
if ($scope.selectedPlan !== $scope.plan) {
|
||||
$scope.selectedPlan = $scope.plan
|
||||
$scope.selectedPlan = $scope.plan;
|
||||
} else {
|
||||
$scope.selectedPlan = null
|
||||
$scope.selectedPlan = null;
|
||||
}
|
||||
return updateCartPrice()
|
||||
return updateCartPrice();
|
||||
} else {
|
||||
return $rootScope.login(null, function () {
|
||||
$scope.selectedPlan = $scope.plan
|
||||
return updateCartPrice()
|
||||
})
|
||||
$scope.selectedPlan = $scope.plan;
|
||||
return updateCartPrice();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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)
|
||||
const r = mkReservation($scope.user, $scope.events.reserved, $scope.selectedPlan);
|
||||
return Price.compute(mkRequestParams(r, $scope.coupon.applied), function (res) {
|
||||
$scope.amountTotal = res.price
|
||||
$scope.totalNoCoupon = res.price_without_coupon
|
||||
return setSlotsDetails(res.details)
|
||||
})
|
||||
$scope.amountTotal = res.price;
|
||||
$scope.totalNoCoupon = res.price_without_coupon;
|
||||
return setSlotsDetails(res.details);
|
||||
});
|
||||
} else {
|
||||
// otherwise we alert, this error musn't occur when the current user is not admin
|
||||
growl.warning(_t('cart.please_select_a_member_first'))
|
||||
return $scope.amountTotal = null
|
||||
growl.warning(_t('cart.please_select_a_member_first'));
|
||||
return $scope.amountTotal = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setSlotsDetails = function (details) {
|
||||
angular.forEach($scope.events.reserved, function (slot) {
|
||||
angular.forEach(details.slots, function (s) {
|
||||
if (moment(s.start_at).isSame(slot.start)) {
|
||||
slot.promo = s.promo
|
||||
return slot.price = s.price
|
||||
slot.promo = s.promo;
|
||||
return slot.price = s.price;
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Format the parameters expected by /api/prices/compute or /api/reservations and return the resulting object
|
||||
@ -430,8 +430,8 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
return {
|
||||
reservation,
|
||||
coupon_code: ((coupon ? coupon.code : undefined))
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an hash map implementing the Reservation specs
|
||||
@ -447,18 +447,18 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
reservable_type: $scope.reservableType,
|
||||
slots_attributes: [],
|
||||
plan_id: ((plan ? plan.id : undefined))
|
||||
}
|
||||
};
|
||||
angular.forEach(slots, function (slot, key) {
|
||||
reservation.slots_attributes.push({
|
||||
start_at: slot.start,
|
||||
end_at: slot.end,
|
||||
availability_id: slot.availability_id,
|
||||
offered: slot.offered || false
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
return reservation
|
||||
}
|
||||
return reservation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal window that allows the user to process a credit card payment for his current shopping cart.
|
||||
@ -469,79 +469,79 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
size: 'md',
|
||||
resolve: {
|
||||
reservation () {
|
||||
return reservation
|
||||
return reservation;
|
||||
},
|
||||
price () {
|
||||
return Price.compute(mkRequestParams(reservation, $scope.coupon.applied)).$promise
|
||||
return Price.compute(mkRequestParams(reservation, $scope.coupon.applied)).$promise;
|
||||
},
|
||||
wallet () {
|
||||
return Wallet.getWalletByUser({ user_id: reservation.user_id }).$promise
|
||||
return Wallet.getWalletByUser({ user_id: reservation.user_id }).$promise;
|
||||
},
|
||||
cgv () {
|
||||
return CustomAsset.get({ name: 'cgv-file' }).$promise
|
||||
return CustomAsset.get({ name: 'cgv-file' }).$promise;
|
||||
},
|
||||
coupon () {
|
||||
return $scope.coupon.applied
|
||||
return $scope.coupon.applied;
|
||||
}
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'cgv', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon',
|
||||
function ($scope, $uibModalInstance, $state, reservation, price, cgv, Auth, Reservation, wallet, helpers, $filter, coupon) {
|
||||
// user wallet amount
|
||||
$scope.walletAmount = wallet.amount
|
||||
$scope.walletAmount = wallet.amount;
|
||||
|
||||
// Price
|
||||
$scope.amount = helpers.getAmountToPay(price.price, wallet.amount)
|
||||
$scope.amount = helpers.getAmountToPay(price.price, wallet.amount);
|
||||
|
||||
// CGV
|
||||
$scope.cgv = cgv.custom_asset
|
||||
$scope.cgv = cgv.custom_asset;
|
||||
|
||||
// Reservation
|
||||
$scope.reservation = reservation
|
||||
$scope.reservation = reservation;
|
||||
|
||||
// Used in wallet info template to interpolate some translations
|
||||
$scope.numberFilter = $filter('number')
|
||||
$scope.numberFilter = $filter('number');
|
||||
|
||||
/**
|
||||
* Callback to process the payment with Stripe, triggered on button click
|
||||
*/
|
||||
$scope.payment = function (status, response) {
|
||||
if (response.error) {
|
||||
growl.error(response.error.message)
|
||||
growl.error(response.error.message);
|
||||
} else {
|
||||
$scope.attempting = true
|
||||
$scope.reservation.card_token = response.id
|
||||
$scope.attempting = true;
|
||||
$scope.reservation.card_token = response.id;
|
||||
Reservation.save(
|
||||
mkRequestParams($scope.reservation, coupon),
|
||||
function (reservation) { $uibModalInstance.close(reservation) },
|
||||
function (reservation) { $uibModalInstance.close(reservation); },
|
||||
function (response) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts = [];
|
||||
if (response.status === 500) {
|
||||
$scope.alerts.push({
|
||||
msg: response.statusText,
|
||||
type: 'danger'
|
||||
})
|
||||
});
|
||||
} else {
|
||||
if (response.data.card && (response.data.card.join('').length > 0)) {
|
||||
$scope.alerts.push({
|
||||
msg: response.data.card.join('. '),
|
||||
type: 'danger'
|
||||
})
|
||||
});
|
||||
} else if (response.data.payment && (response.data.payment.join('').length > 0)) {
|
||||
$scope.alerts.push({
|
||||
msg: response.data.payment.join('. '),
|
||||
type: 'danger'
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
return $scope.attempting = false
|
||||
return $scope.attempting = false;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
]
|
||||
}).result['finally'](null).then(function (reservation) { afterPayment(reservation) })
|
||||
}
|
||||
}).result['finally'](null).then(function (reservation) { afterPayment(reservation); });
|
||||
};
|
||||
/**
|
||||
* Open a modal window that allows the user to process a local payment for his current shopping cart (admin only).
|
||||
*/
|
||||
@ -551,43 +551,43 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
size: 'sm',
|
||||
resolve: {
|
||||
reservation () {
|
||||
return reservation
|
||||
return reservation;
|
||||
},
|
||||
price () {
|
||||
return Price.compute(mkRequestParams(reservation, $scope.coupon.applied)).$promise
|
||||
return Price.compute(mkRequestParams(reservation, $scope.coupon.applied)).$promise;
|
||||
},
|
||||
wallet () {
|
||||
return Wallet.getWalletByUser({ user_id: reservation.user_id }).$promise
|
||||
return Wallet.getWalletByUser({ user_id: reservation.user_id }).$promise;
|
||||
},
|
||||
coupon () {
|
||||
return $scope.coupon.applied
|
||||
return $scope.coupon.applied;
|
||||
}
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon',
|
||||
function ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation, wallet, helpers, $filter, coupon) {
|
||||
// user wallet amount
|
||||
$scope.walletAmount = wallet.amount
|
||||
$scope.walletAmount = wallet.amount;
|
||||
|
||||
// Global price (total of all items)
|
||||
$scope.price = price.price
|
||||
$scope.price = price.price;
|
||||
|
||||
// Price to pay (wallet deducted)
|
||||
$scope.amount = helpers.getAmountToPay(price.price, wallet.amount)
|
||||
$scope.amount = helpers.getAmountToPay(price.price, wallet.amount);
|
||||
|
||||
// Reservation
|
||||
$scope.reservation = reservation
|
||||
$scope.reservation = reservation;
|
||||
|
||||
// Used in wallet info template to interpolate some translations
|
||||
$scope.numberFilter = $filter('number')
|
||||
$scope.numberFilter = $filter('number');
|
||||
|
||||
// Button label
|
||||
if ($scope.amount > 0) {
|
||||
$scope.validButtonName = _t('cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat')
|
||||
$scope.validButtonName = _t('cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')($scope.amount) }, 'messageformat');
|
||||
} else {
|
||||
if ((price.price > 0) && ($scope.walletAmount === 0)) {
|
||||
$scope.validButtonName = _t('cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat')
|
||||
$scope.validButtonName = _t('cart.confirm_payment_of_html', { ROLE: $rootScope.currentUser.role, AMOUNT: $filter('currency')(price.price) }, 'messageformat');
|
||||
} else {
|
||||
$scope.validButtonName = _t('confirm')
|
||||
$scope.validButtonName = _t('confirm');
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,40 +595,40 @@ Application.Directives.directive('cart', [ '$rootScope', '$uibModal', 'dialogs',
|
||||
* Callback to process the local payment, triggered on button click
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$scope.attempting = true
|
||||
$scope.attempting = true;
|
||||
return Reservation.save(mkRequestParams($scope.reservation, coupon), function (reservation) {
|
||||
$uibModalInstance.close(reservation)
|
||||
return $scope.attempting = true
|
||||
$uibModalInstance.close(reservation);
|
||||
return $scope.attempting = true;
|
||||
}
|
||||
, function (response) {
|
||||
$scope.alerts = []
|
||||
$scope.alerts.push({ msg: _t('cart.a_problem_occured_during_the_payment_process_please_try_again_later'), type: 'danger' })
|
||||
return $scope.attempting = false
|
||||
})
|
||||
}
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.alerts = [];
|
||||
$scope.alerts.push({ msg: _t('cart.a_problem_occured_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
return $scope.attempting = false;
|
||||
});
|
||||
};
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}
|
||||
]
|
||||
}).result['finally'](null).then(function (reservation) { afterPayment(reservation) })
|
||||
}
|
||||
}).result['finally'](null).then(function (reservation) { afterPayment(reservation); });
|
||||
};
|
||||
/**
|
||||
* 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
|
||||
$scope.events.paid = $scope.events.reserved;
|
||||
// we call the external callback if present
|
||||
if (typeof $scope.afterPayment === 'function') { $scope.afterPayment(reservation) }
|
||||
if (typeof $scope.afterPayment === 'function') { $scope.afterPayment(reservation); }
|
||||
// we reset the coupon and the cart content and we unselect the slot
|
||||
$scope.events.reserved = []
|
||||
$scope.coupon.applied = null
|
||||
$scope.slot = null
|
||||
return $scope.selectedPlan = null
|
||||
}
|
||||
$scope.events.reserved = [];
|
||||
$scope.coupon.applied = null;
|
||||
$scope.slot = null;
|
||||
return $scope.selectedPlan = null;
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize()
|
||||
return initialize();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -14,25 +14,25 @@ Application.Directives.directive('confirmationNeeded', [() =>
|
||||
priority: 1,
|
||||
terminal: true,
|
||||
link (scope, element, attrs) {
|
||||
const msg = attrs.confirmationNeeded || 'Are you sure?'
|
||||
const clickAction = attrs.ngClick
|
||||
const msg = attrs.confirmationNeeded || 'Are you sure?';
|
||||
const clickAction = attrs.ngClick;
|
||||
return element.bind('click', function () {
|
||||
if (attrs.confirmationNeededIf != null) {
|
||||
const confirmNeededIf = scope.$eval(attrs.confirmationNeededIf)
|
||||
const confirmNeededIf = scope.$eval(attrs.confirmationNeededIf);
|
||||
if (confirmNeededIf === true) {
|
||||
if (window.confirm(msg)) {
|
||||
return scope.$eval(clickAction)
|
||||
return scope.$eval(clickAction);
|
||||
}
|
||||
} else {
|
||||
return scope.$eval(clickAction)
|
||||
return scope.$eval(clickAction);
|
||||
}
|
||||
} else {
|
||||
if (window.confirm(msg)) {
|
||||
return scope.$eval(clickAction)
|
||||
return scope.$eval(clickAction);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -22,54 +22,54 @@ Application.Directives.directive('coupon', [ '$rootScope', 'Coupon', '_t', funct
|
||||
link ($scope, element, attributes) {
|
||||
// Whether code input is shown or not (ie. the link 'I have a coupon' is shown)
|
||||
$scope.code =
|
||||
{ input: false }
|
||||
{ input: false };
|
||||
|
||||
// Available status are: 'pending', 'valid', 'invalid'
|
||||
$scope.status = 'pending'
|
||||
$scope.status = 'pending';
|
||||
|
||||
// Binding for the code inputed (see the attached template)
|
||||
$scope.couponCode = null
|
||||
$scope.couponCode = null;
|
||||
|
||||
// Code validation messages
|
||||
$scope.messages = []
|
||||
$scope.messages = [];
|
||||
|
||||
// Re-compute if the code can be applied when the total of the cart changes
|
||||
$scope.$watch('total', function (newValue, oldValue) {
|
||||
if (newValue && (newValue !== oldValue) && $scope.couponCode) {
|
||||
return $scope.validateCode()
|
||||
return $scope.validateCode();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* Callback to validate the code
|
||||
*/
|
||||
$scope.validateCode = function () {
|
||||
$scope.messages = []
|
||||
$scope.messages = [];
|
||||
if ($scope.couponCode === '') {
|
||||
$scope.status = 'pending'
|
||||
return $scope.coupon = null
|
||||
$scope.status = 'pending';
|
||||
return $scope.coupon = null;
|
||||
} else {
|
||||
return Coupon.validate({ code: $scope.couponCode, user_id: $scope.userId, amount: $scope.total }, function (res) {
|
||||
$scope.status = 'valid'
|
||||
$scope.coupon = res
|
||||
$scope.status = 'valid';
|
||||
$scope.coupon = res;
|
||||
if (res.type === 'percent_off') {
|
||||
return $scope.messages.push({ type: 'success', message: _t('the_coupon_has_been_applied_you_get_PERCENT_discount', { PERCENT: res.percent_off }) })
|
||||
return $scope.messages.push({ type: 'success', message: _t('the_coupon_has_been_applied_you_get_PERCENT_discount', { PERCENT: res.percent_off }) });
|
||||
} else {
|
||||
return $scope.messages.push({ type: 'success', message: _t('the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY', { AMOUNT: res.amount_off, CURRENCY: $rootScope.currencySymbol }) })
|
||||
return $scope.messages.push({ type: 'success', message: _t('the_coupon_has_been_applied_you_get_AMOUNT_CURRENCY', { AMOUNT: res.amount_off, CURRENCY: $rootScope.currencySymbol }) });
|
||||
}
|
||||
}
|
||||
, function (err) {
|
||||
$scope.status = 'invalid'
|
||||
$scope.coupon = null
|
||||
return $scope.messages.push({ type: 'danger', message: _t(`unable_to_apply_the_coupon_because_${err.data.status}`) })
|
||||
})
|
||||
$scope.status = 'invalid';
|
||||
$scope.coupon = null;
|
||||
return $scope.messages.push({ type: 'danger', message: _t(`unable_to_apply_the_coupon_because_${err.data.status}`) });
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to remove the message at provided index from the displayed list
|
||||
*/
|
||||
$scope.closeMessage = function (index) { $scope.messages.splice(index, 1) }
|
||||
$scope.closeMessage = function (index) { $scope.messages.splice(index, 1); };
|
||||
}
|
||||
})
|
||||
}])
|
||||
});
|
||||
}]);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Directives.directive('fileread', [ () =>
|
||||
({
|
||||
@ -20,11 +20,11 @@ Application.Directives.directive('fileread', [ () =>
|
||||
link (scope, element, attributes) {
|
||||
return element.bind('change', changeEvent =>
|
||||
scope.$apply(() => scope.fileread = changeEvent.target.files[0])
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
// This `bsHolder` angular directive is a workaround for
|
||||
// an incompatability between angular and the holder.js
|
||||
@ -38,11 +38,11 @@ Application.Directives.directive('bsHolder', [ () =>
|
||||
.addTheme('icon-xs', { background: 'white', foreground: '#e0e0e0', size: 20, font: 'FontAwesome' })
|
||||
.addTheme('icon-black-xs', { background: 'black', foreground: 'white', size: 20, font: 'FontAwesome' })
|
||||
.addTheme('avatar', { background: '#eeeeee', foreground: '#555555', size: 16, font: 'FontAwesome' })
|
||||
.run(element[0])
|
||||
.run(element[0]);
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Directives.directive('match', [ () =>
|
||||
({
|
||||
@ -53,11 +53,11 @@ Application.Directives.directive('match', [ () =>
|
||||
},
|
||||
link (scope, elem, attrs, ctrl) {
|
||||
return scope.$watch(() => (ctrl.$pristine && angular.isUndefined(ctrl.$modelValue)) || (scope.match === ctrl.$modelValue)
|
||||
, currentValue => ctrl.$setValidity('match', currentValue))
|
||||
, currentValue => ctrl.$setValidity('match', currentValue));
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Directives.directive('publishProject', [ () =>
|
||||
({
|
||||
@ -65,30 +65,30 @@ Application.Directives.directive('publishProject', [ () =>
|
||||
link (scope, elem, attrs, ctrl) {
|
||||
return elem.bind('click', function ($event) {
|
||||
if ($event) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
if (elem.attr('disabled')) { return }
|
||||
const input = angular.element('<input name="project[state]" type="hidden" value="published">')
|
||||
const form = angular.element('form')
|
||||
form.append(input)
|
||||
form.triggerHandler('submit')
|
||||
return form[0].submit()
|
||||
})
|
||||
if (elem.attr('disabled')) { return; }
|
||||
const input = angular.element('<input name="project[state]" type="hidden" value="published">');
|
||||
const form = angular.element('form');
|
||||
form.append(input);
|
||||
form.triggerHandler('submit');
|
||||
return form[0].submit();
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Directives.directive('disableAnimation', ['$animate', ($animate) =>
|
||||
({
|
||||
restrict: 'A',
|
||||
link (scope, elem, attrs) {
|
||||
return attrs.$observe('disableAnimation', value => $animate.enabled(!value, elem))
|
||||
return attrs.$observe('disableAnimation', value => $animate.enabled(!value, elem));
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* Isolate a form's scope from its parent : no nested validation
|
||||
@ -98,34 +98,34 @@ Application.Directives.directive('isolateForm', [ () =>
|
||||
restrict: 'A',
|
||||
require: '?form',
|
||||
link (scope, elm, attrs, ctrl) {
|
||||
if (!ctrl) { return }
|
||||
if (!ctrl) { return; }
|
||||
|
||||
// Do a copy of the controller
|
||||
const ctrlCopy = {}
|
||||
angular.copy(ctrl, ctrlCopy)
|
||||
const ctrlCopy = {};
|
||||
angular.copy(ctrl, ctrlCopy);
|
||||
|
||||
// Get the form's parent
|
||||
const parent = elm.parent().controller('form')
|
||||
const parent = elm.parent().controller('form');
|
||||
// Remove parent link to the controller
|
||||
parent.$removeControl(ctrl)
|
||||
parent.$removeControl(ctrl);
|
||||
|
||||
// Replace form controller with a "isolated form"
|
||||
const isolatedFormCtrl = {
|
||||
$setValidity (validationToken, isValid, control) {
|
||||
ctrlCopy.$setValidity(validationToken, isValid, control)
|
||||
return parent.$setValidity(validationToken, true, ctrl)
|
||||
ctrlCopy.$setValidity(validationToken, isValid, control);
|
||||
return parent.$setValidity(validationToken, true, ctrl);
|
||||
},
|
||||
|
||||
$setDirty () {
|
||||
elm.removeClass('ng-pristine').addClass('ng-dirty')
|
||||
ctrl.$dirty = true
|
||||
return ctrl.$pristine = false
|
||||
elm.removeClass('ng-pristine').addClass('ng-dirty');
|
||||
ctrl.$dirty = true;
|
||||
return ctrl.$pristine = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return angular.extend(ctrl, isolatedFormCtrl)
|
||||
return angular.extend(ctrl, isolatedFormCtrl);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -16,5 +16,5 @@ Application.Directives.directive('fabUserAvatar', [ function () {
|
||||
avatarClass: '@'
|
||||
},
|
||||
templateUrl: '<%= asset_path "shared/_user_avatar.html" %>'
|
||||
})
|
||||
}])
|
||||
});
|
||||
}]);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* This directive will allow to select a member.
|
||||
@ -26,23 +26,23 @@ Application.Directives.directive('selectMember', [ 'Diacritics', 'Member', funct
|
||||
link (scope, element, attributes) {
|
||||
return scope.autoCompleteName = function (nameLookup) {
|
||||
if (!nameLookup) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
scope.isLoadingMembers = true
|
||||
const asciiName = Diacritics.remove(nameLookup)
|
||||
scope.isLoadingMembers = true;
|
||||
const asciiName = Diacritics.remove(nameLookup);
|
||||
|
||||
const q = { query: asciiName }
|
||||
const q = { query: asciiName };
|
||||
if (attributes.subscription) {
|
||||
q['subscription'] = attributes.subscription
|
||||
q['subscription'] = attributes.subscription;
|
||||
}
|
||||
|
||||
return Member.search(q, function (users) {
|
||||
scope.matchingMembers = users
|
||||
return scope.isLoadingMembers = false
|
||||
scope.matchingMembers = users;
|
||||
return scope.isLoadingMembers = false;
|
||||
}
|
||||
, function (error) { console.error(error) })
|
||||
}
|
||||
, function (error) { console.error(error); });
|
||||
};
|
||||
}
|
||||
|
||||
})
|
||||
}])
|
||||
});
|
||||
}]);
|
||||
|
@ -19,18 +19,18 @@ Application.Directives.directive('socialLink', [ function () {
|
||||
templateUrl: '<%= asset_path "shared/_social_link.html" %>',
|
||||
link (scope, element, attributes) {
|
||||
if (scope.network === 'dailymotion') {
|
||||
scope.image = "<%= asset_path('social/dailymotion.png') %>"
|
||||
return scope.altText = 'd'
|
||||
scope.image = "<%= asset_path('social/dailymotion.png') %>";
|
||||
return scope.altText = 'd';
|
||||
} else if (scope.network === 'echosciences') {
|
||||
scope.image = "<%= asset_path('social/echosciences.png') %>"
|
||||
return scope.altText = 'E)'
|
||||
scope.image = "<%= asset_path('social/echosciences.png') %>";
|
||||
return scope.altText = 'E)';
|
||||
} else {
|
||||
if (scope.network === 'website') {
|
||||
return scope.faClass = 'fa-globe'
|
||||
return scope.faClass = 'fa-globe';
|
||||
} else {
|
||||
return scope.faClass = `fa-${scope.network.replace('_', '-')}`
|
||||
return scope.faClass = `fa-${scope.network.replace('_', '-')}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}])
|
||||
});
|
||||
}]);
|
||||
|
@ -1,23 +1,23 @@
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
// https://github.com/gtramontina/stripe-angular
|
||||
|
||||
Application.Directives.directive('stripeForm', ['$window',
|
||||
function ($window) {
|
||||
var directive = { restrict: 'A' }
|
||||
var directive = { restrict: 'A' };
|
||||
directive.link = function (scope, element, attributes) {
|
||||
var form = angular.element(element)
|
||||
var form = angular.element(element);
|
||||
form.bind('submit', function () {
|
||||
var button = form.find('button')
|
||||
button.prop('disabled', true)
|
||||
var button = form.find('button');
|
||||
button.prop('disabled', true);
|
||||
$window.Stripe.createToken(form[0], function () {
|
||||
var args = arguments
|
||||
var args = arguments;
|
||||
scope.$apply(function () {
|
||||
scope[attributes.stripeForm].apply(scope, args)
|
||||
})
|
||||
scope[attributes.stripeForm].apply(scope, args);
|
||||
});
|
||||
// button.prop('disabled', false);
|
||||
})
|
||||
})
|
||||
}
|
||||
return directive
|
||||
}])
|
||||
});
|
||||
});
|
||||
};
|
||||
return directive;
|
||||
}]);
|
||||
|
@ -10,46 +10,46 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Directives.directive('url', [ function () {
|
||||
const URL_REGEXP = /^(https?:\/\/)([\da-z\.-]+)\.([-a-z0-9\.]{2,30})([\/\w \.-]*)*\/?$/
|
||||
const URL_REGEXP = /^(https?:\/\/)([\da-z\.-]+)\.([-a-z0-9\.]{2,30})([\/\w \.-]*)*\/?$/;
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link (scope, element, attributes, ctrl) {
|
||||
return ctrl.$validators.url = function (modelValue, viewValue) {
|
||||
if (ctrl.$isEmpty(modelValue)) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
if (URL_REGEXP.test(viewValue)) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise, this is invalid
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Directives.directive('endpoint', [ function () {
|
||||
const ENDPOINT_REGEXP = /^\/?([-._~:?#\[\]@!$&'()*+,;=%\w]+\/?)*$/
|
||||
const ENDPOINT_REGEXP = /^\/?([-._~:?#\[\]@!$&'()*+,;=%\w]+\/?)*$/;
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link (scope, element, attributes, ctrl) {
|
||||
return ctrl.$validators.endpoint = function (modelValue, viewValue) {
|
||||
if (ctrl.$isEmpty(modelValue)) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
if (ENDPOINT_REGEXP.test(viewValue)) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise, this is invalid
|
||||
return false
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -11,142 +11,142 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Filters.filter('array', [ () =>
|
||||
function (arrayLength) {
|
||||
if (arrayLength) {
|
||||
arrayLength = Math.ceil(arrayLength)
|
||||
const arr = new Array(arrayLength)
|
||||
arrayLength = Math.ceil(arrayLength);
|
||||
const arr = new Array(arrayLength);
|
||||
|
||||
for (let i = 0, end = arrayLength, asc = end >= 0; asc ? i < end : i > end; asc ? i++ : i--) {
|
||||
arr[i] = i
|
||||
arr[i] = i;
|
||||
}
|
||||
|
||||
return arr
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
// filter for projects and trainings
|
||||
Application.Filters.filter('machineFilter', [ () =>
|
||||
function (elements, selectedMachine) {
|
||||
if (!angular.isUndefined(elements) && !angular.isUndefined(selectedMachine) && (elements != null) && (selectedMachine != null)) {
|
||||
const filteredElements = []
|
||||
const filteredElements = [];
|
||||
angular.forEach(elements, function (element) {
|
||||
if (element.machine_ids.indexOf(selectedMachine) !== -1) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
})
|
||||
return filteredElements
|
||||
});
|
||||
return filteredElements;
|
||||
} else {
|
||||
return elements
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('projectMemberFilter', [ 'Auth', Auth =>
|
||||
function (projects, selectedMember) {
|
||||
if (!angular.isUndefined(projects) && angular.isDefined(selectedMember) && (projects != null) && (selectedMember != null) && (selectedMember !== '')) {
|
||||
const filteredProject = []
|
||||
const filteredProject = [];
|
||||
// Mes projets
|
||||
if (selectedMember === '0') {
|
||||
angular.forEach(projects, function (project) {
|
||||
if (project.author_id === Auth._currentUser.id) {
|
||||
return filteredProject.push(project)
|
||||
return filteredProject.push(project);
|
||||
}
|
||||
})
|
||||
});
|
||||
// les projets auxquels je collabore
|
||||
} else {
|
||||
angular.forEach(projects, function (project) {
|
||||
if (project.user_ids.indexOf(Auth._currentUser.id) !== -1) {
|
||||
return filteredProject.push(project)
|
||||
return filteredProject.push(project);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
return filteredProject
|
||||
return filteredProject;
|
||||
} else {
|
||||
return projects
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('themeFilter', [ () =>
|
||||
function (projects, selectedTheme) {
|
||||
if (!angular.isUndefined(projects) && !angular.isUndefined(selectedTheme) && (projects != null) && (selectedTheme != null)) {
|
||||
const filteredProjects = []
|
||||
const filteredProjects = [];
|
||||
angular.forEach(projects, function (project) {
|
||||
if (project.theme_ids.indexOf(selectedTheme) !== -1) {
|
||||
return filteredProjects.push(project)
|
||||
return filteredProjects.push(project);
|
||||
}
|
||||
})
|
||||
return filteredProjects
|
||||
});
|
||||
return filteredProjects;
|
||||
} else {
|
||||
return projects
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('componentFilter', [ () =>
|
||||
function (projects, selectedComponent) {
|
||||
if (!angular.isUndefined(projects) && !angular.isUndefined(selectedComponent) && (projects != null) && (selectedComponent != null)) {
|
||||
const filteredProjects = []
|
||||
const filteredProjects = [];
|
||||
angular.forEach(projects, function (project) {
|
||||
if (project.component_ids.indexOf(selectedComponent) !== -1) {
|
||||
return filteredProjects.push(project)
|
||||
return filteredProjects.push(project);
|
||||
}
|
||||
})
|
||||
return filteredProjects
|
||||
});
|
||||
return filteredProjects;
|
||||
} else {
|
||||
return projects
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('projectsByAuthor', [ () =>
|
||||
function (projects, authorId) {
|
||||
if (!angular.isUndefined(projects) && angular.isDefined(authorId) && (projects != null) && (authorId != null) && (authorId !== '')) {
|
||||
const filteredProject = []
|
||||
const filteredProject = [];
|
||||
angular.forEach(projects, function (project) {
|
||||
if (project.author_id === authorId) {
|
||||
return filteredProject.push(project)
|
||||
return filteredProject.push(project);
|
||||
}
|
||||
})
|
||||
return filteredProject
|
||||
});
|
||||
return filteredProject;
|
||||
} else {
|
||||
return projects
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('projectsCollabored', [ () =>
|
||||
function (projects, memberId) {
|
||||
if (!angular.isUndefined(projects) && angular.isDefined(memberId) && (projects != null) && (memberId != null) && (memberId !== '')) {
|
||||
const filteredProject = []
|
||||
const filteredProject = [];
|
||||
angular.forEach(projects, function (project) {
|
||||
if (project.user_ids.indexOf(memberId) !== -1) {
|
||||
return filteredProject.push(project)
|
||||
return filteredProject.push(project);
|
||||
}
|
||||
})
|
||||
return filteredProject
|
||||
});
|
||||
return filteredProject;
|
||||
} else {
|
||||
return projects
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
// depend on humanize.js lib in /vendor
|
||||
Application.Filters.filter('humanize', [ () =>
|
||||
(element, param) => Humanize.truncate(element, param, null)
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* This filter will convert ASCII carriage-return character to the HTML break-line tag
|
||||
@ -154,11 +154,11 @@ Application.Filters.filter('humanize', [ () =>
|
||||
Application.Filters.filter('breakFilter', [ () =>
|
||||
function (text) {
|
||||
if (text != null) {
|
||||
return text.replace(/\n+/g, '<br />')
|
||||
return text.replace(/\n+/g, '<br />');
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* This filter will take a HTML text as input and will return it without the html tags
|
||||
@ -166,224 +166,224 @@ Application.Filters.filter('breakFilter', [ () =>
|
||||
Application.Filters.filter('simpleText', [ () =>
|
||||
function (text) {
|
||||
if (text != null) {
|
||||
text = text.replace(/<br\s*\/?>/g, '\n')
|
||||
return text.replace(/<\/?\w+[^>]*>/g, '')
|
||||
text = text.replace(/<br\s*\/?>/g, '\n');
|
||||
return text.replace(/<\/?\w+[^>]*>/g, '');
|
||||
} else {
|
||||
return ''
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('toTrusted', [ '$sce', $sce =>
|
||||
text => $sce.trustAsHtml(text)
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('planIntervalFilter', [ () =>
|
||||
(interval, intervalCount) => moment.duration(intervalCount, interval).humanize()
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('humanReadablePlanName', ['$filter', $filter =>
|
||||
function (plan, groups, short) {
|
||||
if (plan != null) {
|
||||
let result = plan.base_name
|
||||
let result = plan.base_name;
|
||||
if (groups != null) {
|
||||
for (let group of Array.from(groups)) {
|
||||
if (group.id === plan.group_id) {
|
||||
if (short != null) {
|
||||
result += ` - ${group.slug}`
|
||||
result += ` - ${group.slug}`;
|
||||
} else {
|
||||
result += ` - ${group.name}`
|
||||
result += ` - ${group.name}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result += ` - ${$filter('planIntervalFilter')(plan.interval, plan.interval_count)}`
|
||||
return result
|
||||
result += ` - ${$filter('planIntervalFilter')(plan.interval, plan.interval_count)}`;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('trainingReservationsFilter', [ () =>
|
||||
function (elements, selectedScope) {
|
||||
if (!angular.isUndefined(elements) && !angular.isUndefined(selectedScope) && (elements != null) && (selectedScope != null)) {
|
||||
const filteredElements = []
|
||||
const filteredElements = [];
|
||||
angular.forEach(elements, function (element) {
|
||||
switch (selectedScope) {
|
||||
case 'future':
|
||||
if (new Date(element.start_at) > new Date()) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
break
|
||||
break;
|
||||
case 'passed':
|
||||
if ((new Date(element.start_at) <= new Date()) && !element.is_valid) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
break
|
||||
break;
|
||||
case 'valided':
|
||||
if ((new Date(element.start_at) <= new Date()) && element.is_valid) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
})
|
||||
return filteredElements
|
||||
});
|
||||
return filteredElements;
|
||||
} else {
|
||||
return elements
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('eventsReservationsFilter', [ () =>
|
||||
function (elements, selectedScope) {
|
||||
if (!angular.isUndefined(elements) && !angular.isUndefined(selectedScope) && (elements != null) && (selectedScope != null) && (selectedScope !== '')) {
|
||||
const filteredElements = []
|
||||
const filteredElements = [];
|
||||
angular.forEach(elements, function (element) {
|
||||
if (angular.isUndefined(element.start_at)) { element.start_at = element.availability.start_at }
|
||||
if (angular.isUndefined(element.end_at)) { element.end_at = element.availability.end_at }
|
||||
if (angular.isUndefined(element.start_at)) { element.start_at = element.availability.start_at; }
|
||||
if (angular.isUndefined(element.end_at)) { element.end_at = element.availability.end_at; }
|
||||
switch (selectedScope) {
|
||||
case 'future':
|
||||
if (new Date(element.end_at) >= new Date()) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
break
|
||||
break;
|
||||
case 'future_asc':
|
||||
if (new Date(element.end_at) >= new Date()) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
break
|
||||
break;
|
||||
case 'passed':
|
||||
if (new Date(element.end_at) <= new Date()) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
break
|
||||
break;
|
||||
default:
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
})
|
||||
});
|
||||
switch (selectedScope) {
|
||||
case 'future_asc':
|
||||
return filteredElements.reverse()
|
||||
return filteredElements.reverse();
|
||||
default:
|
||||
return filteredElements
|
||||
return filteredElements;
|
||||
}
|
||||
} else {
|
||||
return elements
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('groupFilter', [ () =>
|
||||
function (elements, member) {
|
||||
if (!angular.isUndefined(elements) && !angular.isUndefined(member) && (elements != null) && (member != null)) {
|
||||
const filteredElements = []
|
||||
const filteredElements = [];
|
||||
angular.forEach(elements, function (element) {
|
||||
if (member.group_id === element.id) {
|
||||
return filteredElements.push(element)
|
||||
return filteredElements.push(element);
|
||||
}
|
||||
})
|
||||
return filteredElements
|
||||
});
|
||||
return filteredElements;
|
||||
} else {
|
||||
return elements
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('groupByFilter', [ () =>
|
||||
_.memoize((elements, field) => _.groupBy(elements, field))
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('capitalize', [() =>
|
||||
text => `${text.charAt(0).toUpperCase()}${text.slice(1).toLowerCase()}`
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('reverse', [ () =>
|
||||
function (items) {
|
||||
if (!angular.isArray(items)) {
|
||||
return items
|
||||
return items;
|
||||
}
|
||||
|
||||
return items.slice().reverse()
|
||||
return items.slice().reverse();
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('toArray', [ () =>
|
||||
function (obj) {
|
||||
if (!(obj instanceof Object)) { return obj }
|
||||
if (!(obj instanceof Object)) { return obj; }
|
||||
return _.map(obj, function (val, key) {
|
||||
if (angular.isObject(val)) {
|
||||
return Object.defineProperty(val, '$key', { __proto__: null, value: key })
|
||||
return Object.defineProperty(val, '$key', { __proto__: null, value: key });
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('toIsoDate', [ () =>
|
||||
function (date) {
|
||||
if (!(date instanceof Date) && !moment.isMoment(date)) { return date }
|
||||
return moment(date).format('YYYY-MM-DD')
|
||||
if (!(date instanceof Date) && !moment.isMoment(date)) { return date; }
|
||||
return moment(date).format('YYYY-MM-DD');
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('booleanFormat', [ '_t', _t =>
|
||||
function (boolean) {
|
||||
if (boolean || (boolean === 'true')) {
|
||||
return _t('yes')
|
||||
return _t('yes');
|
||||
} else {
|
||||
return _t('no')
|
||||
return _t('no');
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('booleanFormat', [ '_t', _t =>
|
||||
function (boolean) {
|
||||
if (((typeof boolean === 'boolean') && boolean) || ((typeof boolean === 'string') && (boolean === 'true'))) {
|
||||
return _t('yes')
|
||||
return _t('yes');
|
||||
} else {
|
||||
return _t('no')
|
||||
return _t('no');
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('maxCount', [ '_t', _t =>
|
||||
function (max) {
|
||||
if ((typeof max === 'undefined') || (max === null) || ((typeof max === 'number') && (max === 0))) {
|
||||
return _t('unlimited')
|
||||
return _t('unlimited');
|
||||
} else {
|
||||
return max
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
||||
Application.Filters.filter('filterDisabled', [ () =>
|
||||
function (list, filter) {
|
||||
if (angular.isArray(list)) {
|
||||
return list.filter(function (e) {
|
||||
switch (filter) {
|
||||
case 'disabled': return e.disabled
|
||||
case 'enabled': return !e.disabled
|
||||
default: return true
|
||||
case 'disabled': return e.disabled;
|
||||
case 'enabled': return !e.disabled;
|
||||
default: return true;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
return list
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -11,8 +11,8 @@
|
||||
*/
|
||||
angular.module('application.router', ['ui.router'])
|
||||
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $locationProvider) {
|
||||
$locationProvider.hashPrefix('!')
|
||||
$urlRouterProvider.otherwise('/')
|
||||
$locationProvider.hashPrefix('!');
|
||||
$urlRouterProvider.otherwise('/');
|
||||
|
||||
// abstract root parents states
|
||||
// these states controls the access rights to the various routes inherited from them
|
||||
@ -30,14 +30,14 @@ angular.module('application.router', ['ui.router'])
|
||||
'main': {}
|
||||
},
|
||||
resolve: {
|
||||
logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise }],
|
||||
logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise }],
|
||||
commonTranslations: [ 'Translations', function (Translations) { return Translations.query(['app.public.common', 'app.shared.buttons', 'app.shared.elements']).$promise }]
|
||||
logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise; }],
|
||||
logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }],
|
||||
commonTranslations: [ 'Translations', function (Translations) { return Translations.query(['app.public.common', 'app.shared.buttons', 'app.shared.elements']).$promise; }]
|
||||
},
|
||||
onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', function ($rootScope, logoFile, logoBlackFile) {
|
||||
// Application logo
|
||||
$rootScope.logo = logoFile.custom_asset
|
||||
return $rootScope.logoBlack = logoBlackFile.custom_asset
|
||||
$rootScope.logo = logoFile.custom_asset;
|
||||
return $rootScope.logoBlack = logoBlackFile.custom_asset;
|
||||
}]
|
||||
})
|
||||
.state('app.public', {
|
||||
@ -49,10 +49,10 @@ angular.module('application.router', ['ui.router'])
|
||||
authorizedRoles: ['member', 'admin']
|
||||
},
|
||||
resolve: {
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser() }]
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser(); }]
|
||||
},
|
||||
onEnter: ['$state', '$timeout', 'currentUser', '$rootScope', function ($state, $timeout, currentUser, $rootScope) {
|
||||
$rootScope.currentUser = currentUser
|
||||
$rootScope.currentUser = currentUser;
|
||||
}]
|
||||
})
|
||||
.state('app.admin', {
|
||||
@ -61,10 +61,10 @@ angular.module('application.router', ['ui.router'])
|
||||
authorizedRoles: ['admin']
|
||||
},
|
||||
resolve: {
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser() }]
|
||||
currentUser: ['Auth', function (Auth) { return Auth.currentUser(); }]
|
||||
},
|
||||
onEnter: ['$state', '$timeout', 'currentUser', '$rootScope', function ($state, $timeout, currentUser, $rootScope) {
|
||||
$rootScope.currentUser = currentUser
|
||||
$rootScope.currentUser = currentUser;
|
||||
}]
|
||||
})
|
||||
|
||||
@ -78,7 +78,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.about').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.about').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.home', {
|
||||
@ -90,12 +90,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
lastMembersPromise: ['Member', function (Member) { return Member.lastSubscribed({ limit: 4 }).$promise }],
|
||||
lastProjectsPromise: ['Project', function (Project) { return Project.lastPublished().$promise }],
|
||||
upcomingEventsPromise: ['Event', function (Event) { return Event.upcoming({ limit: 3 }).$promise }],
|
||||
homeBlogpostPromise: ['Setting', function (Setting) { return Setting.get({ name: 'home_blogpost' }).$promise }],
|
||||
twitterNamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'twitter_name' }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.home').$promise }]
|
||||
lastMembersPromise: ['Member', function (Member) { return Member.lastSubscribed({ limit: 4 }).$promise; }],
|
||||
lastProjectsPromise: ['Project', function (Project) { return Project.lastPublished().$promise; }],
|
||||
upcomingEventsPromise: ['Event', function (Event) { return Event.upcoming({ limit: 3 }).$promise; }],
|
||||
homeBlogpostPromise: ['Setting', function (Setting) { return Setting.get({ name: 'home_blogpost' }).$promise; }],
|
||||
twitterNamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'twitter_name' }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.home').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -109,12 +109,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['fablab_name', 'name_genre']" }).$promise }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise }],
|
||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise }],
|
||||
memberPromise: ['Member', 'currentUser', function (Member, currentUser) { return Member.get({ id: currentUser.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.profileCompletion', 'app.shared.user']).$promise }]
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['fablab_name', 'name_genre']" }).$promise; }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
||||
memberPromise: ['Member', 'currentUser', function (Member, currentUser) { return Member.get({ id: currentUser.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.profileCompletion', 'app.shared.user']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -123,7 +123,7 @@ angular.module('application.router', ['ui.router'])
|
||||
abstract: true,
|
||||
url: '/dashboard',
|
||||
resolve: {
|
||||
memberPromise: ['Member', 'currentUser', function (Member, currentUser) { return Member.get({ id: currentUser.id }).$promise }]
|
||||
memberPromise: ['Member', 'currentUser', function (Member, currentUser) { return Member.get({ id: currentUser.id }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.profile', {
|
||||
@ -135,7 +135,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.dashboard.profile', 'app.shared.public_profile']).$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.dashboard.profile', 'app.shared.public_profile']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.settings', {
|
||||
@ -147,9 +147,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
groups: ['Group', function (Group) { return Group.query().$promise }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.dashboard.settings', 'app.shared.user']).$promise }]
|
||||
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.dashboard.settings', 'app.shared.user']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.projects', {
|
||||
@ -161,7 +161,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.projects').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.projects').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.trainings', {
|
||||
@ -173,7 +173,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.trainings').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.trainings').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.events', {
|
||||
@ -185,7 +185,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.events').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.events').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.invoices', {
|
||||
@ -197,7 +197,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.invoices').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.dashboard.invoices').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.dashboard.wallet', {
|
||||
@ -209,9 +209,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
walletPromise: ['Wallet', 'currentUser', function (Wallet, currentUser) { return Wallet.getWalletByUser({ user_id: currentUser.id }).$promise }],
|
||||
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.shared.wallet']).$promise }]
|
||||
walletPromise: ['Wallet', 'currentUser', function (Wallet, currentUser) { return Wallet.getWalletByUser({ user_id: currentUser.id }).$promise; }],
|
||||
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.shared.wallet']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -225,8 +225,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
memberPromise: ['$stateParams', 'Member', function ($stateParams, Member) { return Member.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.members_show', 'app.shared.public_profile']).$promise }]
|
||||
memberPromise: ['$stateParams', 'Member', function ($stateParams, Member) { return Member.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.members_show', 'app.shared.public_profile']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.members', {
|
||||
@ -238,8 +238,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
membersPromise: ['Member', function (Member) { return Member.query({ requested_attributes: '[profile]', page: 1, size: 10 }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.members').$promise }]
|
||||
membersPromise: ['Member', function (Member) { return Member.query({ requested_attributes: '[profile]', page: 1, size: 10 }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.members').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -253,10 +253,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise }],
|
||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.projects_list').$promise }]
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.projects_list').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.projects_new', {
|
||||
@ -268,8 +268,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.projects_new', 'app.shared.project']).$promise }]
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.projects_new', 'app.shared.project']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.projects_show', {
|
||||
@ -281,8 +281,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.projects_show').$promise }]
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.projects_show').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.projects_edit', {
|
||||
@ -294,9 +294,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise }],
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.projects_edit', 'app.shared.project']).$promise }]
|
||||
projectPromise: ['$stateParams', 'Project', function ($stateParams, Project) { return Project.get({ id: $stateParams.id }).$promise; }],
|
||||
allowedExtensions: ['Project', function (Project) { return Project.allowedExtensions().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.logged.projects_edit', 'app.shared.project']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -310,8 +310,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.machines_list', 'app.shared.training_reservation_modal', 'app.shared.request_training_modal']).$promise }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.machines_list', 'app.shared.training_reservation_modal', 'app.shared.request_training_modal']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.machines_new', {
|
||||
@ -323,7 +323,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.machines_new', 'app.shared.machine']).$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.machines_new', 'app.shared.machine']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.machines_show', {
|
||||
@ -335,8 +335,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.machines_show', 'app.shared.training_reservation_modal', 'app.shared.request_training_modal']).$promise }]
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.machines_show', 'app.shared.training_reservation_modal', 'app.shared.request_training_modal']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.machines_reserve', {
|
||||
@ -348,9 +348,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise }],
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
||||
settingsPromise: ['Setting', function (Setting) {
|
||||
return Setting.query({
|
||||
names: `['machine_explications_alert', \
|
||||
@ -361,12 +361,12 @@ angular.module('application.router', ['ui.router'])
|
||||
'booking_cancel_enable', \
|
||||
'booking_cancel_delay', \
|
||||
'subscription_explications_alert']`
|
||||
}).$promise
|
||||
}).$promise;
|
||||
}],
|
||||
translations: [ 'Translations', function (Translations) {
|
||||
return Translations.query(['app.logged.machines_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select',
|
||||
'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal',
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -379,8 +379,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.machines_edit', 'app.shared.machine']).$promise }]
|
||||
machinePromise: ['Machine', '$stateParams', function (Machine, $stateParams) { return Machine.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.machines_edit', 'app.shared.machine']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -395,8 +395,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.spaces_list']).$promise }]
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.spaces_list']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.space_new', {
|
||||
@ -409,7 +409,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.space_new', 'app.shared.space']).$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.space_new', 'app.shared.space']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.space_show', {
|
||||
@ -422,8 +422,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.space_show']).$promise }]
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.space_show']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.space_edit', {
|
||||
@ -436,8 +436,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.space_edit', 'app.shared.space']).$promise }]
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.space_edit', 'app.shared.space']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.space_reserve', {
|
||||
@ -450,10 +450,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise }],
|
||||
availabilitySpacesPromise: ['Availability', '$stateParams', function (Availability, $stateParams) { return Availability.spaces({ spaceId: $stateParams.id }).$promise }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise }],
|
||||
spacePromise: ['Space', '$stateParams', function (Space, $stateParams) { return Space.get({ id: $stateParams.id }).$promise; }],
|
||||
availabilitySpacesPromise: ['Availability', '$stateParams', function (Availability, $stateParams) { return Availability.spaces({ spaceId: $stateParams.id }).$promise; }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
settingsPromise: ['Setting', function (Setting) {
|
||||
return Setting.query({
|
||||
names: `['booking_window_start', \
|
||||
@ -463,12 +463,12 @@ angular.module('application.router', ['ui.router'])
|
||||
'booking_cancel_enable', \
|
||||
'booking_cancel_delay', \
|
||||
'subscription_explications_alert', \
|
||||
'space_explications_alert']` }).$promise
|
||||
'space_explications_alert']` }).$promise;
|
||||
}],
|
||||
translations: [ 'Translations', function (Translations) {
|
||||
return Translations.query(['app.logged.space_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select',
|
||||
'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal',
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -483,8 +483,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query({ public_page: true }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.trainings_list']).$promise }]
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query({ public_page: true }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.trainings_list']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.training_show', {
|
||||
@ -496,8 +496,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.training_show']).$promise }]
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.training_show']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.logged.trainings_reserve', {
|
||||
@ -509,12 +509,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
explicationAlertPromise: ['Setting', function (Setting) { return Setting.get({ name: 'training_explications_alert' }).$promise }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise }],
|
||||
availabilityTrainingsPromise: ['Availability', '$stateParams', function (Availability, $stateParams) { return Availability.trainings({ trainingId: $stateParams.id }).$promise }],
|
||||
explicationAlertPromise: ['Setting', function (Setting) { return Setting.get({ name: 'training_explications_alert' }).$promise; }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
availabilityTrainingsPromise: ['Availability', '$stateParams', function (Availability, $stateParams) { return Availability.trainings({ trainingId: $stateParams.id }).$promise; }],
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) {
|
||||
if ($stateParams.id !== 'all') { return Training.get({ id: $stateParams.id }).$promise }
|
||||
if ($stateParams.id !== 'all') { return Training.get({ id: $stateParams.id }).$promise; }
|
||||
}],
|
||||
settingsPromise: ['Setting', function (Setting) {
|
||||
return Setting.query({
|
||||
@ -526,12 +526,12 @@ angular.module('application.router', ['ui.router'])
|
||||
'booking_cancel_delay', \
|
||||
'subscription_explications_alert', \
|
||||
'training_explications_alert', \
|
||||
'training_information_message']` }).$promise
|
||||
'training_information_message']` }).$promise;
|
||||
}],
|
||||
translations: [ 'Translations', function (Translations) {
|
||||
return Translations.query(['app.logged.trainings_reserve', 'app.shared.plan_subscribe', 'app.shared.member_select',
|
||||
'app.shared.stripe', 'app.shared.valid_reservation_modal', 'app.shared.confirm_modify_slot_modal',
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise
|
||||
'app.shared.wallet', 'app.shared.coupon_input', 'app.shared.cart']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -545,7 +545,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.notifications').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.logged.notifications').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -560,12 +560,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_explications_alert' }).$promise }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise }],
|
||||
subscriptionExplicationsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'subscription_explications_alert' }).$promise; }],
|
||||
plansPromise: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) {
|
||||
return Translations.query(['app.public.plans', 'app.shared.member_select', 'app.shared.stripe', 'app.shared.wallet',
|
||||
'app.shared.coupon_input']).$promise
|
||||
'app.shared.coupon_input']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -580,10 +580,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.events_list').$promise }]
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.public.events_list').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.events_show', {
|
||||
@ -595,12 +595,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise }],
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['booking_move_enable', 'booking_move_delay', 'event_explications_alert']" }).$promise }],
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['booking_move_enable', 'booking_move_delay', 'event_explications_alert']" }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) {
|
||||
return Translations.query(['app.public.events_show', 'app.shared.member_select', 'app.shared.stripe',
|
||||
'app.shared.valid_reservation_modal', 'app.shared.wallet', 'app.shared.coupon_input']).$promise
|
||||
'app.shared.valid_reservation_modal', 'app.shared.wallet', 'app.shared.coupon_input']).$promise;
|
||||
}]
|
||||
}
|
||||
})
|
||||
@ -615,12 +615,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
bookingWindowStart: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_start' }).$promise }],
|
||||
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.calendar']).$promise }]
|
||||
bookingWindowStart: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_start' }).$promise; }],
|
||||
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise; }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.public.calendar']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -635,10 +635,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
bookingWindowStart: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_start' }).$promise }],
|
||||
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.calendar').$promise }]
|
||||
bookingWindowStart: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_start' }).$promise; }],
|
||||
bookingWindowEnd: ['Setting', function (Setting) { return Setting.get({ name: 'booking_window_end' }).$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.calendar').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -652,10 +652,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise }],
|
||||
licencesPromise: ['Licence', function (Licence) { return Licence.query().$promise }],
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.project_elements').$promise }]
|
||||
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
|
||||
licencesPromise: ['Licence', function (Licence) { return Licence.query().$promise; }],
|
||||
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.project_elements').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -669,9 +669,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.trainings', 'app.shared.trainings']).$promise }]
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.trainings', 'app.shared.trainings']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.trainings_new', {
|
||||
@ -683,8 +683,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.trainings_new', 'app.shared.trainings']).$promise }]
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.trainings_new', 'app.shared.trainings']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.trainings_edit', {
|
||||
@ -696,9 +696,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.shared.trainings').$promise }]
|
||||
trainingPromise: ['Training', '$stateParams', function (Training, $stateParams) { return Training.get({ id: $stateParams.id }).$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.shared.trainings').$promise; }]
|
||||
}
|
||||
})
|
||||
// events
|
||||
@ -711,12 +711,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
eventsPromise: ['Event', function (Event) { return Event.query({ page: 1 }).$promise }],
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.events').$promise }]
|
||||
eventsPromise: ['Event', function (Event) { return Event.query({ page: 1 }).$promise; }],
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.events').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.events_new', {
|
||||
@ -728,11 +728,11 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.events_new', 'app.shared.event']).$promise }]
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.events_new', 'app.shared.event']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.events_edit', {
|
||||
@ -744,12 +744,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise }],
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.events_edit', 'app.shared.event']).$promise }]
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }],
|
||||
categoriesPromise: ['Category', function (Category) { return Category.query().$promise; }],
|
||||
themesPromise: ['EventTheme', function (EventTheme) { return EventTheme.query().$promise; }],
|
||||
ageRangesPromise: ['AgeRange', function (AgeRange) { return AgeRange.query().$promise; }],
|
||||
priceCategoriesPromise: ['PriceCategory', function (PriceCategory) { return PriceCategory.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.events_edit', 'app.shared.event']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.event_reservations', {
|
||||
@ -761,9 +761,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise }],
|
||||
reservationsPromise: ['Reservation', '$stateParams', function (Reservation, $stateParams) { return Reservation.query({ reservable_id: $stateParams.id, reservable_type: 'Event' }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.event_reservations').$promise }]
|
||||
eventPromise: ['Event', '$stateParams', function (Event, $stateParams) { return Event.get({ id: $stateParams.id }).$promise; }],
|
||||
reservationsPromise: ['Reservation', '$stateParams', function (Reservation, $stateParams) { return Reservation.query({ reservable_id: $stateParams.id, reservable_type: 'Event' }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.event_reservations').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -777,19 +777,19 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
plans: ['Plan', function (Plan) { return Plan.query().$promise }],
|
||||
groups: ['Group', function (Group) { return Group.query().$promise }],
|
||||
machinesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Machine', plan_id: 'null' }).$promise }],
|
||||
trainingsPricingsPromise: ['TrainingsPricing', function (TrainingsPricing) { return TrainingsPricing.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.pricing', 'app.shared.member_select', 'app.shared.coupon']).$promise }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise }],
|
||||
machineCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Machine' }).$promise }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
trainingCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Training' }).$promise }],
|
||||
couponsPromise: ['Coupon', function (Coupon) { return Coupon.query().$promise }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise }],
|
||||
spacesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Space', plan_id: 'null' }).$promise }],
|
||||
spacesCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Space' }).$promise }]
|
||||
plans: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
machinesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Machine', plan_id: 'null' }).$promise; }],
|
||||
trainingsPricingsPromise: ['TrainingsPricing', function (TrainingsPricing) { return TrainingsPricing.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.pricing', 'app.shared.member_select', 'app.shared.coupon']).$promise; }],
|
||||
trainingsPromise: ['Training', function (Training) { return Training.query().$promise; }],
|
||||
machineCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Machine' }).$promise; }],
|
||||
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
trainingCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Training' }).$promise; }],
|
||||
couponsPromise: ['Coupon', function (Coupon) { return Coupon.query().$promise; }],
|
||||
spacesPromise: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
spacesPricesPromise: ['Price', function (Price) { return Price.query({ priceable_type: 'Space', plan_id: 'null' }).$promise; }],
|
||||
spacesCreditsPromise: ['Credit', function (Credit) { return Credit.query({ creditable_type: 'Space' }).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -797,9 +797,9 @@ angular.module('application.router', ['ui.router'])
|
||||
.state('app.admin.plans', {
|
||||
abstract: true,
|
||||
resolve: {
|
||||
prices: ['Pricing', function (Pricing) { return Pricing.query().$promise }],
|
||||
groups: ['Group', function (Group) { return Group.query().$promise }],
|
||||
partners: ['User', function (User) { return User.query({ role: 'partner' }).$promise }]
|
||||
prices: ['Pricing', function (Pricing) { return Pricing.query().$promise; }],
|
||||
groups: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
partners: ['User', function (User) { return User.query({ role: 'partner' }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.plans.new', {
|
||||
@ -811,7 +811,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.plans.new', 'app.shared.plan']).$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.plans.new', 'app.shared.plan']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.plans.edit', {
|
||||
@ -823,11 +823,11 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
spaces: ['Space', function (Space) { return Space.query().$promise }],
|
||||
machines: ['Machine', function (Machine) { return Machine.query().$promise }],
|
||||
plans: ['Plan', function (Plan) { return Plan.query().$promise }],
|
||||
planPromise: ['Plan', '$stateParams', function (Plan, $stateParams) { return Plan.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.plans.edit', 'app.shared.plan']).$promise }]
|
||||
spaces: ['Space', function (Space) { return Space.query().$promise; }],
|
||||
machines: ['Machine', function (Machine) { return Machine.query().$promise; }],
|
||||
plans: ['Plan', function (Plan) { return Plan.query().$promise; }],
|
||||
planPromise: ['Plan', '$stateParams', function (Plan, $stateParams) { return Plan.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.plans.edit', 'app.shared.plan']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -841,7 +841,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.coupons_new', 'app.shared.coupon']).$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.coupons_new', 'app.shared.coupon']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.coupons_edit', {
|
||||
@ -853,8 +853,8 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
couponPromise: ['Coupon', '$stateParams', function (Coupon, $stateParams) { return Coupon.get({ id: $stateParams.id }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.coupons_edit', 'app.shared.coupon']).$promise }]
|
||||
couponPromise: ['Coupon', '$stateParams', function (Coupon, $stateParams) { return Coupon.get({ id: $stateParams.id }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.coupons_edit', 'app.shared.coupon']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -878,14 +878,14 @@ angular.module('application.router', ['ui.router'])
|
||||
'invoice_code-value', \
|
||||
'invoice_code-active', \
|
||||
'invoice_reference', \
|
||||
'invoice_logo']` }).$promise
|
||||
'invoice_logo']` }).$promise;
|
||||
}],
|
||||
invoices: [ 'Invoice', function (Invoice) {
|
||||
return Invoice.list({
|
||||
query: { number: '', customer: '', date: null, order_by: '-reference', page: 1, size: 20 }
|
||||
}).$promise
|
||||
}).$promise;
|
||||
}],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.invoices').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.invoices').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -911,12 +911,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
membersPromise: ['Member', function (Member) { return Member.list({ query: { search: '', order_by: 'id', page: 1, size: 20 } }).$promise }],
|
||||
adminsPromise: ['Admin', function (Admin) { return Admin.query().$promise }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise }],
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.members').$promise }]
|
||||
membersPromise: ['Member', function (Member) { return Member.list({ query: { search: '', order_by: 'id', page: 1, size: 20 } }).$promise; }],
|
||||
adminsPromise: ['Admin', function (Admin) { return Admin.query().$promise; }],
|
||||
groupsPromise: ['Group', function (Group) { return Group.query().$promise; }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.members').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.members_new', {
|
||||
@ -928,7 +928,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.members_new', 'app.shared.user', 'app.shared.user_admin']).$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.members_new', 'app.shared.user', 'app.shared.user_admin']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.members_edit', {
|
||||
@ -940,12 +940,12 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
memberPromise: ['Member', '$stateParams', function (Member, $stateParams) { return Member.get({ id: $stateParams.id }).$promise }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise }],
|
||||
walletPromise: ['Wallet', '$stateParams', function (Wallet, $stateParams) { return Wallet.getWalletByUser({ user_id: $stateParams.id }).$promise }],
|
||||
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.members_edit', 'app.shared.user', 'app.shared.user_admin', 'app.shared.wallet']).$promise }]
|
||||
memberPromise: ['Member', '$stateParams', function (Member, $stateParams) { return Member.get({ id: $stateParams.id }).$promise; }],
|
||||
activeProviderPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.active().$promise; }],
|
||||
walletPromise: ['Wallet', '$stateParams', function (Wallet, $stateParams) { return Wallet.getWalletByUser({ user_id: $stateParams.id }).$promise; }],
|
||||
transactionsPromise: ['Wallet', 'walletPromise', function (Wallet, walletPromise) { return Wallet.transactions({ id: walletPromise.id }).$promise; }],
|
||||
tagsPromise: ['Tag', function (Tag) { return Tag.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.members_edit', 'app.shared.user', 'app.shared.user_admin', 'app.shared.wallet']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.admins_new', {
|
||||
@ -957,7 +957,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.admins_new').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.admins_new').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -971,9 +971,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise }],
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.authentication_new', 'app.shared.authentication', 'app.shared.oauth2']).$promise }]
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }],
|
||||
authProvidersPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.authentication_new', 'app.shared.authentication', 'app.shared.oauth2']).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.authentication_edit', {
|
||||
@ -985,9 +985,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
providerPromise: ['AuthProvider', '$stateParams', function (AuthProvider, $stateParams) { return AuthProvider.get({ id: $stateParams.id }).$promise }],
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.authentication_edit', 'app.shared.authentication', 'app.shared.oauth2']).$promise }]
|
||||
providerPromise: ['AuthProvider', '$stateParams', function (AuthProvider, $stateParams) { return AuthProvider.get({ id: $stateParams.id }).$promise; }],
|
||||
mappingFieldsPromise: ['AuthProvider', function (AuthProvider) { return AuthProvider.mapping_fields().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query(['app.admin.authentication_edit', 'app.shared.authentication', 'app.shared.oauth2']).$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1001,9 +1001,9 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
membersPromise: ['Member', function (Member) { return Member.mapping().$promise }],
|
||||
statisticsPromise: ['Statistics', function (Statistics) { return Statistics.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.statistics').$promise }]
|
||||
membersPromise: ['Member', function (Member) { return Member.mapping().$promise; }],
|
||||
statisticsPromise: ['Statistics', function (Statistics) { return Statistics.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.statistics').$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.admin.stats_graphs', {
|
||||
@ -1015,7 +1015,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.stats_graphs').$promise }]
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.stats_graphs').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1057,13 +1057,13 @@ angular.module('application.router', ['ui.router'])
|
||||
'visibility_yearly', \
|
||||
'visibility_others', \
|
||||
'display_name_enable', \
|
||||
'machines_sort_by']` }).$promise
|
||||
'machines_sort_by']` }).$promise;
|
||||
}],
|
||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise }],
|
||||
cgvFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgv-file' }).$promise }],
|
||||
faviconFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'favicon-file' }).$promise }],
|
||||
profileImageFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'profile-image-file' }).$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.settings').$promise }]
|
||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
||||
cgvFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgv-file' }).$promise; }],
|
||||
faviconFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'favicon-file' }).$promise; }],
|
||||
profileImageFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'profile-image-file' }).$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.settings').$promise; }]
|
||||
}
|
||||
})
|
||||
|
||||
@ -1077,10 +1077,10 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
clientsPromise: ['OpenAPIClient', function (OpenAPIClient) { return OpenAPIClient.query().$promise }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.open_api_clients').$promise }]
|
||||
clientsPromise: ['OpenAPIClient', function (OpenAPIClient) { return OpenAPIClient.query().$promise; }],
|
||||
translations: [ 'Translations', function (Translations) { return Translations.query('app.admin.open_api_clients').$promise; }]
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -9,13 +9,13 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('_t', ['$filter', $filter =>
|
||||
function (key, interpolation, options) {
|
||||
if (interpolation == null) { interpolation = undefined }
|
||||
if (options == null) { options = undefined }
|
||||
return $filter('translate')(key, interpolation, options)
|
||||
if (interpolation == null) { interpolation = undefined; }
|
||||
if (options == null) { options = undefined; }
|
||||
return $filter('translate')(key, interpolation, options);
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Abuse', ['$resource', $resource =>
|
||||
$resource('/api/abuses/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Abuse', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Admin', ['$resource', $resource =>
|
||||
$resource('/api/admins/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Admin', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('AgeRange', ['$resource', $resource =>
|
||||
$resource('/api/age_ranges/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('AgeRange', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -9,21 +9,21 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('AuthService', ['Session', function (Session) {
|
||||
return {
|
||||
isAuthenticated () {
|
||||
return (Session.currentUser != null) && (Session.currentUser.id != null)
|
||||
return (Session.currentUser != null) && (Session.currentUser.id != null);
|
||||
},
|
||||
|
||||
isAuthorized (authorizedRoles) {
|
||||
if (!angular.isArray(authorizedRoles)) {
|
||||
authorizedRoles = [authorizedRoles]
|
||||
authorizedRoles = [authorizedRoles];
|
||||
}
|
||||
|
||||
return this.isAuthenticated() && (authorizedRoles.indexOf(Session.currentUser.role) !== -1)
|
||||
return this.isAuthenticated() && (authorizedRoles.indexOf(Session.currentUser.role) !== -1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('AuthProvider', ['$resource', $resource =>
|
||||
$resource('/api/auth_providers/:id',
|
||||
@ -31,4 +31,4 @@ Application.Services.factory('AuthProvider', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Availability', ['$resource', $resource =>
|
||||
$resource('/api/availabilities/:id',
|
||||
@ -46,4 +46,4 @@ Application.Services.factory('Availability', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -9,16 +9,16 @@
|
||||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('CalendarConfig', [() =>
|
||||
function (options) {
|
||||
// The calendar is divided in slots of 1 hour
|
||||
if (options == null) { options = {} }
|
||||
const BASE_SLOT = '01:00:00'
|
||||
if (options == null) { options = {}; }
|
||||
const BASE_SLOT = '01:00:00';
|
||||
|
||||
// The calendar will be initialized positioned under 9:00 AM
|
||||
const DEFAULT_CALENDAR_POSITION = '09:00:00'
|
||||
const DEFAULT_CALENDAR_POSITION = '09:00:00';
|
||||
|
||||
const defaultOptions = {
|
||||
timezone: Fablab.timezone,
|
||||
@ -48,9 +48,9 @@ Application.Services.factory('CalendarConfig', [() =>
|
||||
allDaySlot: false,
|
||||
defaultView: 'agendaWeek',
|
||||
editable: false
|
||||
}
|
||||
};
|
||||
|
||||
return Object.assign({}, defaultOptions, options)
|
||||
return Object.assign({}, defaultOptions, options);
|
||||
}
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Category', ['$resource', $resource =>
|
||||
$resource('/api/categories/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Category', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Component', ['$resource', $resource =>
|
||||
$resource('/api/components/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Component', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Coupon', ['$resource', $resource =>
|
||||
$resource('/api/coupons/:id',
|
||||
@ -27,4 +27,4 @@ Application.Services.factory('Coupon', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Credit', ['$resource', $resource =>
|
||||
$resource('/api/credits/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Credit', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -4,19 +4,19 @@
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.service('CSRF', ['$cookies',
|
||||
$cookies =>
|
||||
({
|
||||
setMetaTags () {
|
||||
if (angular.element('meta[name="csrf-param"]').length === 0) {
|
||||
angular.element('head').append('<meta name="csrf-param" content="authenticity_token">')
|
||||
angular.element('head').append(`<meta name=\"csrf-token\" content=\"${$cookies['XSRF-TOKEN']}\">`)
|
||||
angular.element('head').append('<meta name="csrf-param" content="authenticity_token">');
|
||||
angular.element('head').append(`<meta name=\"csrf-token\" content=\"${$cookies['XSRF-TOKEN']}\">`);
|
||||
} else {
|
||||
angular.element('meta[name="csrf-token"]').replaceWith(`<meta name=\"csrf-token\" content=\"${$cookies['XSRF-TOKEN']}\">`)
|
||||
angular.element('meta[name="csrf-token"]').replaceWith(`<meta name=\"csrf-token\" content=\"${$cookies['XSRF-TOKEN']}\">`);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,10 +8,10 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('CustomAsset', ['$resource', $resource =>
|
||||
$resource('/api/custom_assets/:name',
|
||||
{ name: '@name' })
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -101,21 +101,21 @@ Application.Services.service('Diacritics', [
|
||||
{ 'base': 'x', 'letters': '\u0078\u24E7\uFF58\u1E8B\u1E8D' },
|
||||
{ 'base': 'y', 'letters': '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF' },
|
||||
{ 'base': 'z', 'letters': '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763' }
|
||||
]
|
||||
];
|
||||
|
||||
var diacriticsMap = {}
|
||||
var diacriticsMap = {};
|
||||
for (var i = 0; i < defaultDiacriticsRemovalap.length; i++) {
|
||||
var letters = defaultDiacriticsRemovalap[i].letters.split('')
|
||||
var letters = defaultDiacriticsRemovalap[i].letters.split('');
|
||||
for (var j = 0; j < letters.length; j++) {
|
||||
diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base
|
||||
diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base;
|
||||
}
|
||||
}
|
||||
|
||||
return str.replace(/[^\u0000-\u007E]/g, function (a) {
|
||||
return diacriticsMap[a] || a
|
||||
})
|
||||
return diacriticsMap[a] || a;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('dialogs', ['$uibModal', function ($uibModal) {
|
||||
return ({
|
||||
@ -22,27 +22,27 @@ Application.Services.factory('dialogs', ['$uibModal', function ($uibModal) {
|
||||
return {
|
||||
title: 'Titre de confirmation',
|
||||
msg: 'Message de confirmation'
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'object', function ($scope, $uibModalInstance, $state, object) {
|
||||
$scope.object = object
|
||||
$scope.ok = function (info) { $uibModalInstance.close(info) }
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel') }
|
||||
$scope.object = object;
|
||||
$scope.ok = function (info) { $uibModalInstance.close(info); };
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
}
|
||||
if (angular.isObject(options)) { angular.extend(defaultOpts, options) }
|
||||
};
|
||||
if (angular.isObject(options)) { angular.extend(defaultOpts, options); }
|
||||
return $uibModal.open(defaultOpts)
|
||||
.result['finally'](null).then(function (info) {
|
||||
if (angular.isFunction(success)) {
|
||||
return success(info)
|
||||
return success(info);
|
||||
}
|
||||
}
|
||||
, function (reason) {
|
||||
if (angular.isFunction(error)) {
|
||||
return error(reason)
|
||||
return error(reason);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
}])
|
||||
});
|
||||
}]);
|
||||
|
@ -1,3 +1,3 @@
|
||||
Application.Services.service('es', function (esFactory) {
|
||||
return esFactory({ host: window.location.origin })
|
||||
})
|
||||
return esFactory({ host: window.location.origin });
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Event', ['$resource', $resource =>
|
||||
$resource('/api/events/:id',
|
||||
@ -25,4 +25,4 @@ Application.Services.factory('Event', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('EventTheme', ['$resource', $resource =>
|
||||
$resource('/api/event_themes/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('EventTheme', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,13 +8,13 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Export', ['$http', $http =>
|
||||
({
|
||||
status (query) {
|
||||
return $http.post('/api/exports/status', query)
|
||||
return $http.post('/api/exports/status', query);
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Group', ['$resource', $resource =>
|
||||
$resource('/api/groups/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Group', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,13 +8,13 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('helpers', [() =>
|
||||
({
|
||||
getAmountToPay (price, walletAmount) {
|
||||
if (walletAmount > price) { return 0 } else { return price - walletAmount }
|
||||
if (walletAmount > price) { return 0; } else { return price - walletAmount; }
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Invoice', ['$resource', $resource =>
|
||||
$resource('/api/invoices/:id',
|
||||
@ -24,4 +24,4 @@ Application.Services.factory('Invoice', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Licence', ['$resource', $resource =>
|
||||
$resource('/api/licences/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Licence', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Machine', ['$resource', $resource =>
|
||||
$resource('/api/machines/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Machine', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Member', ['$resource', $resource =>
|
||||
$resource('/api/members/:id',
|
||||
@ -44,4 +44,4 @@ Application.Services.factory('Member', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Notification', ['$resource', $resource =>
|
||||
$resource('/api/notifications/:id',
|
||||
@ -30,4 +30,4 @@ Application.Services.factory('Notification', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('OpenAPIClient', ['$resource', $resource =>
|
||||
$resource('/api/open_api_clients/:id',
|
||||
@ -23,4 +23,4 @@ Application.Services.factory('OpenAPIClient', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('OpenlabProject', ['$resource', $resource =>
|
||||
$resource('/api/openlab_projects/:id',
|
||||
@ -20,4 +20,4 @@ Application.Services.factory('OpenlabProject', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -9,62 +9,62 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('paginationService', [function () {
|
||||
const helpers = {}
|
||||
const helpers = {};
|
||||
|
||||
helpers.pageCount = (totalCount, perPage) => Math.ceil(totalCount / perPage)
|
||||
helpers.pageCount = (totalCount, perPage) => Math.ceil(totalCount / perPage);
|
||||
|
||||
helpers.hasNextPage = function (currentPage, totalCount, perPage) {
|
||||
const _pageCount = helpers.pageCount(totalCount, perPage)
|
||||
return (_pageCount !== currentPage) && (_pageCount !== 0)
|
||||
}
|
||||
const _pageCount = helpers.pageCount(totalCount, perPage);
|
||||
return (_pageCount !== currentPage) && (_pageCount !== 0);
|
||||
};
|
||||
|
||||
const Instance = function (resourceService, currentPage, perPage, totalCount, defaultQueryParams, callback, functionName) {
|
||||
this.resourceService = resourceService
|
||||
this.currentPage = currentPage
|
||||
this.perPage = perPage
|
||||
this.totalCount = totalCount
|
||||
this.defaultQueryParams = defaultQueryParams
|
||||
this.callback = callback
|
||||
this.functionName = functionName || 'query'
|
||||
this.loading = false
|
||||
this.resourceService = resourceService;
|
||||
this.currentPage = currentPage;
|
||||
this.perPage = perPage;
|
||||
this.totalCount = totalCount;
|
||||
this.defaultQueryParams = defaultQueryParams;
|
||||
this.callback = callback;
|
||||
this.functionName = functionName || 'query';
|
||||
this.loading = false;
|
||||
|
||||
this.pageCount = function () {
|
||||
return helpers.pageCount(this.totalCount, this.perPage)
|
||||
}
|
||||
return helpers.pageCount(this.totalCount, this.perPage);
|
||||
};
|
||||
|
||||
this.hasNextPage = function () {
|
||||
return helpers.hasNextPage(this.currentPage, this.totalCount, this.perPage)
|
||||
}
|
||||
return helpers.hasNextPage(this.currentPage, this.totalCount, this.perPage);
|
||||
};
|
||||
|
||||
this.loadMore = function (queryParams) {
|
||||
let k, v
|
||||
this.currentPage += 1
|
||||
this.loading = true
|
||||
let k, v;
|
||||
this.currentPage += 1;
|
||||
this.loading = true;
|
||||
|
||||
const _queryParams = { page: this.currentPage, per_page: this.perPage }
|
||||
const _queryParams = { page: this.currentPage, per_page: this.perPage };
|
||||
|
||||
if (queryParams) {
|
||||
for (k in queryParams) {
|
||||
v = queryParams[k]
|
||||
_queryParams[k] = v
|
||||
v = queryParams[k];
|
||||
_queryParams[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
for (k in this.defaultQueryParams) {
|
||||
v = this.defaultQueryParams[k]
|
||||
_queryParams[k] = v
|
||||
v = this.defaultQueryParams[k];
|
||||
_queryParams[k] = v;
|
||||
}
|
||||
|
||||
return this.resourceService[this.functionName](_queryParams, dataPromise => {
|
||||
this.callback(dataPromise)
|
||||
return this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
this.callback(dataPromise);
|
||||
return this.loading = false;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
return { Instance }
|
||||
return { Instance };
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Plan', ['$resource', $resource =>
|
||||
$resource('/api/plans/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Plan', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Price', ['$resource', $resource =>
|
||||
$resource('/api/prices/:id',
|
||||
@ -27,4 +27,4 @@ Application.Services.factory('Price', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('PriceCategory', ['$resource', $resource =>
|
||||
$resource('/api/price_categories/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('PriceCategory', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Pricing', ['$resource', $resource =>
|
||||
$resource('/api/pricing',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Pricing', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Project', ['$resource', $resource =>
|
||||
$resource('/api/projects/:id',
|
||||
@ -31,4 +31,4 @@ Application.Services.factory('Project', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Reservation', ['$resource', $resource =>
|
||||
$resource('/api/reservations/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Reservation', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -9,17 +9,17 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.service('Session', [ function () {
|
||||
this.create = function (user) {
|
||||
return this.currentUser = user
|
||||
}
|
||||
return this.currentUser = user;
|
||||
};
|
||||
|
||||
this.destroy = function () {
|
||||
return this.currentUser = null
|
||||
}
|
||||
return this.currentUser = null;
|
||||
};
|
||||
|
||||
return this
|
||||
return this;
|
||||
}
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Setting', ['$resource', $resource =>
|
||||
$resource('/api/settings/:name',
|
||||
@ -22,4 +22,4 @@ Application.Services.factory('Setting', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Slot', ['$resource', $resource =>
|
||||
$resource('/api/slots/:id',
|
||||
@ -23,4 +23,4 @@ Application.Services.factory('Slot', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,8 +8,8 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
// list the social networks supported in the user's profiles
|
||||
Application.Services.factory('SocialNetworks', [ () => ['facebook', 'twitter', 'google_plus', 'viadeo', 'linkedin', 'instagram', 'youtube', 'vimeo', 'dailymotion', 'github', 'echosciences', 'website', 'pinterest', 'lastfm', 'flickr']
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Space', ['$resource', $resource =>
|
||||
$resource('/api/spaces/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Space', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Statistics', ['$resource', $resource => $resource('/api/statistics')
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Subscription', ['$resource', $resource =>
|
||||
$resource('/api/subscriptions/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Subscription', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Tag', ['$resource', $resource =>
|
||||
$resource('/api/tags/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Tag', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Theme', ['$resource', $resource =>
|
||||
$resource('/api/themes/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('Theme', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Training', ['$resource', $resource =>
|
||||
$resource('/api/trainings/:id',
|
||||
@ -23,4 +23,4 @@ Application.Services.factory('Training', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('TrainingsPricing', ['$resource', $resource =>
|
||||
$resource('/api/trainings_pricings/:id',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('TrainingsPricing', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,18 +8,18 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Translations', ['$translatePartialLoader', '$translate', ($translatePartialLoader, $translate) =>
|
||||
({
|
||||
query (stateName) {
|
||||
if (angular.isArray((stateName))) {
|
||||
angular.forEach(stateName, state => $translatePartialLoader.addPart(state))
|
||||
angular.forEach(stateName, state => $translatePartialLoader.addPart(state));
|
||||
} else {
|
||||
$translatePartialLoader.addPart(stateName)
|
||||
$translatePartialLoader.addPart(stateName);
|
||||
}
|
||||
return $translate.refresh()
|
||||
return $translate.refresh();
|
||||
}
|
||||
})
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Twitter', ['$resource', $resource => $resource('/api/feeds/twitter_timelines')
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('User', ['$resource', $resource =>
|
||||
$resource('/api/users',
|
||||
@ -19,4 +19,4 @@ Application.Services.factory('User', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Version', ['$resource', $resource => $resource('/api/version')
|
||||
])
|
||||
]);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict'
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('Wallet', ['$resource', $resource =>
|
||||
$resource('/api/wallet',
|
||||
@ -31,4 +31,4 @@ Application.Services.factory('Wallet', ['$resource', $resource =>
|
||||
}
|
||||
)
|
||||
|
||||
])
|
||||
]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user