2018-10-25 16:50:16 +02:00
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS101: Remove unnecessary use of Array.from
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
|
|
|
'use strict';
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Controller used in the members listing page
|
|
|
|
//#
|
|
|
|
Application.Controllers.controller("MembersController", ["$scope", 'Member', 'membersPromise', function($scope, Member, membersPromise) {
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2016-06-16 16:09:22 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
/* PRIVATE STATIC CONSTANTS */
|
2016-06-16 16:09:22 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
// number of invoices loaded each time we click on 'load more...'
|
|
|
|
const MEMBERS_PER_PAGE = 10;
|
2016-06-16 16:09:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
/* PUBLIC SCOPE */
|
2016-10-07 11:11:58 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# currently displayed page of members
|
|
|
|
$scope.page = 1;
|
2016-10-07 11:11:58 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# members list
|
|
|
|
$scope.members = membersPromise;
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
// true when all members are loaded
|
|
|
|
$scope.noMoreResults = false;
|
2016-06-16 16:09:22 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Callback for the 'load more' button.
|
|
|
|
// Will load the next results of the current search, if any
|
|
|
|
//#
|
|
|
|
$scope.showNextMembers = function() {
|
|
|
|
$scope.page += 1;
|
|
|
|
return Member.query({
|
2016-10-07 11:11:58 +02:00
|
|
|
requested_attributes:'[profile]',
|
|
|
|
page: $scope.page,
|
2016-06-16 16:09:22 +02:00
|
|
|
size: MEMBERS_PER_PAGE
|
2018-10-25 16:50:16 +02:00
|
|
|
}, function(members) {
|
|
|
|
$scope.members = $scope.members.concat(members);
|
2016-10-07 11:11:58 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
if (!members[0] || (members[0].maxMembers <= $scope.members.length)) {
|
|
|
|
return $scope.noMoreResults = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2016-06-16 16:09:22 +02:00
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
/* PRIVATE SCOPE */
|
2016-06-16 16:09:22 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Kind of constructor: these actions will be realized first when the controller is loaded
|
|
|
|
//#
|
|
|
|
const initialize = function() {
|
|
|
|
if (!membersPromise[0] || (membersPromise[0].maxMembers <= $scope.members.length)) {
|
|
|
|
return $scope.noMoreResults = true;
|
|
|
|
}
|
|
|
|
};
|
2016-06-16 16:09:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# !!! MUST BE CALLED AT THE END of the controller
|
|
|
|
return initialize();
|
|
|
|
}
|
2016-06-16 16:09:22 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
]);
|
2015-05-05 03:10:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Controller used when editing the current user's profile
|
|
|
|
//#
|
|
|
|
Application.Controllers.controller("EditProfileController", ["$scope", "$rootScope", "$state", "$window", "Member", "Auth", "Session", "activeProviderPromise", 'growl', 'dialogs', 'CSRF', 'memberPromise', 'groups', '_t'
|
|
|
|
, function($scope, $rootScope, $state, $window, Member, Auth, Session, activeProviderPromise, growl, dialogs, CSRF, memberPromise, groups, _t) {
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
/* PUBLIC SCOPE */
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# API URL where the form will be posted
|
|
|
|
$scope.actionUrl = `/api/members/${$scope.currentUser.id}`;
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# list of groups
|
|
|
|
$scope.groups = groups.filter(g => !g.disabled);
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# Form action on the above URL
|
|
|
|
$scope.method = 'patch';
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# Current user's profile
|
|
|
|
$scope.user = memberPromise;
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# default : do not show the group changing form
|
2016-03-23 18:39:41 +01:00
|
|
|
$scope.group =
|
2018-10-25 16:50:16 +02:00
|
|
|
{change: false};
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# group ID of the current/selected user
|
|
|
|
$scope.userGroup = memberPromise.group_id;
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# active authentication provider parameters
|
|
|
|
$scope.activeProvider = activeProviderPromise;
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# allow the user to change his password except if he connect from an SSO
|
|
|
|
$scope.preventPassword = false;
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# mapping of fields to disable
|
|
|
|
$scope.preventField = {};
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# Should the passord be modified?
|
2016-03-24 15:39:24 +01:00
|
|
|
$scope.password =
|
2018-10-25 16:50:16 +02:00
|
|
|
{change: false};
|
2016-03-24 15:39:24 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# Angular-Bootstrap datepicker configuration for birthday
|
|
|
|
$scope.datePicker = {
|
|
|
|
format: Fablab.uibDateFormat,
|
|
|
|
opened: false, // default: datePicker is not shown
|
|
|
|
options: {
|
2016-03-23 18:39:41 +01:00
|
|
|
startingDay: Fablab.weekStartingDay
|
2018-10-25 16:50:16 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#
|
|
|
|
// Return the group object, identified by the ID set in $scope.userGroup
|
|
|
|
//#
|
|
|
|
$scope.getUserGroup = function() {
|
|
|
|
for (let group of Array.from($scope.groups)) {
|
|
|
|
if (group.id === $scope.userGroup) {
|
|
|
|
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'));
|
|
|
|
}
|
|
|
|
, function(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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#
|
|
|
|
// For use with ngUpload (https://github.com/twilson63/ngUpload).
|
|
|
|
// Intended to be the callback when the upload is done: any raised error will be stacked in the
|
|
|
|
// $scope.alerts array. If everything goes fine, the user's profile is updated and the user is
|
|
|
|
// redirected to the home page
|
|
|
|
// @param content {Object} JSON - The upload's result
|
|
|
|
//#
|
|
|
|
$scope.submited = function(content) {
|
|
|
|
if ((content.id == null)) {
|
|
|
|
$scope.alerts = [];
|
|
|
|
return angular.forEach(content, (v, k)=>
|
|
|
|
angular.forEach(v, err=>
|
|
|
|
$scope.alerts.push({
|
2015-05-05 03:10:25 +02:00
|
|
|
msg: k+': '+err,
|
|
|
|
type: 'danger'
|
2018-10-25 16:50:16 +02:00
|
|
|
})
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} 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');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#
|
|
|
|
// Ask for confirmation then delete the current user's account
|
|
|
|
// @param user {Object} the current user (to delete)
|
|
|
|
//#
|
|
|
|
$scope.deleteUser = user=>
|
|
|
|
dialogs.confirm({
|
|
|
|
resolve: {
|
|
|
|
object() {
|
|
|
|
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'));
|
|
|
|
})
|
|
|
|
|
|
|
|
, function(error){
|
|
|
|
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.
|
|
|
|
// The preview may show a placeholder or the content of the file depending on the upload state.
|
|
|
|
// @param v {*} any attribute, will be tested for truthiness (see JS evaluation rules)
|
|
|
|
//#
|
|
|
|
$scope.fileinputClass = function(v){
|
|
|
|
if (v) {
|
|
|
|
return 'fileinput-exists';
|
|
|
|
} else {
|
|
|
|
return 'fileinput-new';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//#
|
|
|
|
// Check if the of the properties editable by the user are linked to the SSO
|
|
|
|
// @return {boolean} true if some editable fields are mapped with the SSO, false otherwise
|
|
|
|
//#
|
|
|
|
$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
|
2016-03-23 18:39:41 +01:00
|
|
|
Object.keys($scope.preventField).length > 1
|
2018-10-25 16:50:16 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
//#
|
|
|
|
// 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;
|
|
|
|
$scope.notifications = {
|
|
|
|
total: 0,
|
2017-01-05 15:06:54 +01:00
|
|
|
unread: 0
|
2018-10-25 16:50:16 +02:00
|
|
|
};
|
|
|
|
return $window.location.href = $scope.activeProvider.link_to_sso_connect;
|
|
|
|
})
|
|
|
|
;
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
/* PRIVATE SCOPE */
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Kind of constructor: these actions will be realized first when the controller is loaded
|
|
|
|
//#
|
|
|
|
const initialize = function() {
|
|
|
|
CSRF.setMetaTags();
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
// init the birth date to JS object
|
|
|
|
$scope.user.profile.birthday = moment($scope.user.profile.birthday).toDate();
|
2016-03-23 18:39:41 +01:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
if ($scope.activeProvider.providable_type !== 'DatabaseProvider') {
|
|
|
|
$scope.preventPassword = true;
|
|
|
|
}
|
|
|
|
// bind fields protection with sso fields
|
|
|
|
return angular.forEach(activeProviderPromise.mapping, map => $scope.preventField[map] = true);
|
|
|
|
};
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# !!! MUST BE CALLED AT THE END of the controller
|
|
|
|
return initialize();
|
|
|
|
}
|
|
|
|
]);
|
2015-05-05 03:10:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// 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) {
|
2015-05-05 03:10:25 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# Selected user's information
|
|
|
|
$scope.user = memberPromise; // DEPENDENCY WITH NAVINUM GAMIFICATION PLUGIN !!!!
|
2016-05-17 16:41:32 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# List of social networks associated with this user and toggle 'show all' state
|
|
|
|
$scope.social = {
|
|
|
|
showAllLinks: false,
|
2016-05-17 16:41:32 +02:00
|
|
|
networks: SocialNetworks
|
2018-10-25 16:50:16 +02:00
|
|
|
};
|
2016-05-17 16:41:32 +02:00
|
|
|
|
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
/* PRIVATE SCOPE */
|
2016-05-17 16:41:32 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Kind of constructor: these actions will be realized first when the controller is loaded
|
|
|
|
//#
|
|
|
|
const initialize = () => $scope.social.networks = filterNetworks();
|
2016-05-17 16:41:32 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//#
|
|
|
|
// Filter social network or website that are associated with the profile of the user provided in promise
|
|
|
|
// and return the filtered networks
|
|
|
|
// @return {Array}
|
|
|
|
//#
|
|
|
|
var filterNetworks = function() {
|
|
|
|
const networks = [];
|
|
|
|
for (let network of Array.from(SocialNetworks)) {
|
|
|
|
if ($scope.user.profile[network] && ($scope.user.profile[network].length > 0)) {
|
2016-05-17 16:41:32 +02:00
|
|
|
networks.push(network);
|
2018-10-25 16:50:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return networks;
|
|
|
|
};
|
2016-05-17 16:41:32 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
//# !!! MUST BE CALLED AT THE END of the controller
|
|
|
|
return initialize();
|
|
|
|
}
|
2016-05-17 16:41:32 +02:00
|
|
|
|
2018-10-25 16:50:16 +02:00
|
|
|
]);
|