mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
[ongoing] change user role
This commit is contained in:
parent
3319e68526
commit
06a5bff084
@ -265,6 +265,47 @@ Application.Controllers.controller('AdminMembersController', ['$scope', '$sce',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a modal dialog asking for confirmation to change the role of the given user
|
||||
* @param userId {number} id of the user to "promote"
|
||||
* @returns {*}
|
||||
*/
|
||||
$scope.changeUserRole = function(userId) {
|
||||
const modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: '<%= asset_path "admin/members/change_role_modal.html" %>',
|
||||
size: 'lg',
|
||||
resolve: {
|
||||
userPromise: ['Member', function (Member) { return Member.get({ id: userId }).$promise; }]
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', 'Member', 'userPromise', function ($scope, $uibModalInstance, Member, userPromise) {
|
||||
$scope.user = userPromise;
|
||||
|
||||
$scope.role = userPromise.role;
|
||||
|
||||
$scope.roles = ['admin', 'manager', 'member'];
|
||||
|
||||
$scope.ok = function () {
|
||||
Member.updateRole(
|
||||
{ id: $scope.user.id },
|
||||
{ role: $scope.role },
|
||||
function (_res) {
|
||||
growl.success(_t('app.admin.members_edit.role_changed'));
|
||||
return $uibModalInstance.close(_res);
|
||||
},
|
||||
function (error) { growl.error(_t('app.admin.members_edit.error_while_changing_role')); }
|
||||
);
|
||||
};
|
||||
|
||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||
}]
|
||||
});
|
||||
// once the form was validated successfully ...
|
||||
return modalInstance.result.then(function (user) {
|
||||
// remove the user for the old list add to the new
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ask for confirmation then delete the specified user
|
||||
|
@ -44,6 +44,10 @@ Application.Services.factory('Member', ['$resource', '$q', function ($resource,
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
},
|
||||
updateRole: {
|
||||
method: 'PATCH',
|
||||
url: '/api/members/:id/update_role'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
4
app/assets/stylesheets/modules/members.scss
Normal file
4
app/assets/stylesheets/modules/members.scss
Normal file
@ -0,0 +1,4 @@
|
||||
.promote-member img {
|
||||
width: 16px;
|
||||
height: 21px;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{logoBlack.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="modal-logo"/>
|
||||
<h1 translate>{{ 'app.admin.members_edit.change_role' }}</h1>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="alert alert-warning" translate>{{ 'app.admin.members_edit.warning_role_change' }}</p>
|
||||
<select ng-model="role" class="form-control" ng-options="r in roles"></select>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-info" ng-click="ok()" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||
</div>
|
@ -41,9 +41,9 @@
|
||||
<th style="width:15%"><a href="" ng-click="setOrderMember('first_name')">{{ 'app.admin.members.first_name' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='first_name', 'fa fa-sort-alpha-desc': member.order=='-first_name', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs"><a href="" ng-click="setOrderMember('email')">{{ 'app.admin.members.email' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='email', 'fa fa-sort-alpha-desc': member.order=='-email', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:10%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('phone')">{{ 'app.admin.members.phone' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-numeric-asc': member.order=='phone', 'fa fa-sort-numeric-desc': member.order=='-phone', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:20%" class="hidden-xs hidden-sm"><a href="" ng-click="setOrderMember('group')">{{ 'app.admin.members.user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs hidden-sm"><a href="" ng-click="setOrderMember('group')">{{ 'app.admin.members.user_type' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='group', 'fa fa-sort-alpha-desc': member.order=='-group', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:15%" class="hidden-xs hidden-sm hidden-md"><a href="" ng-click="setOrderMember('plan')">{{ 'app.admin.members.subscription' | translate }} <i class="fa fa-arrows-v" ng-class="{'fa fa-sort-alpha-asc': member.order=='plan', 'fa fa-sort-alpha-desc': member.order=='-plan', 'fa fa-arrows-v': member.order }"></i></a></th>
|
||||
<th style="width:10%" class="buttons-col"></th>
|
||||
<th style="width:15%" class="buttons-col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -59,6 +59,9 @@
|
||||
<button class="btn btn-default edit-member" ui-sref="app.admin.members_edit({id: m.id})">
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>
|
||||
<button class="btn btn-default promote-member">
|
||||
<img src="/rank-icon.svg" alt="promote member" ng-click="changeUserRole(m.id)" ng-show="isAuthorized('admin')"/>
|
||||
</button>
|
||||
<button class="btn btn-danger delete-member" ng-click="deleteMember(m.id)" ng-show="isAuthorized('admin')">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
|
@ -3,7 +3,7 @@
|
||||
# API Controller for resources of type User with role 'member'
|
||||
class API::MembersController < API::ApiController
|
||||
before_action :authenticate_user!, except: [:last_subscribed]
|
||||
before_action :set_member, only: %i[update destroy merge complete_tour]
|
||||
before_action :set_member, only: %i[update destroy merge complete_tour update_role]
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
@ -202,6 +202,15 @@ class API::MembersController < API::ApiController
|
||||
end
|
||||
end
|
||||
|
||||
def update_role
|
||||
authorize @member
|
||||
|
||||
user.remove_role @member.role.to_sym
|
||||
user.add_role params[:role]
|
||||
|
||||
render json: @member
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_member
|
||||
|
@ -160,6 +160,8 @@ class User < ApplicationRecord
|
||||
'admin'
|
||||
elsif manager?
|
||||
'manager'
|
||||
elsif member?
|
||||
'member'
|
||||
else
|
||||
'other'
|
||||
end
|
||||
|
@ -39,7 +39,7 @@ class UserPolicy < ApplicationPolicy
|
||||
end
|
||||
end
|
||||
|
||||
%w[create mapping].each do |action|
|
||||
%w[create mapping update_role].each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.admin?
|
||||
end
|
||||
|
@ -55,6 +55,7 @@ Rails.application.routes.draw do
|
||||
get 'search/:query', action: 'search', on: :collection
|
||||
get 'mapping', action: 'mapping', on: :collection
|
||||
patch ':id/complete_tour', action: 'complete_tour', on: :collection
|
||||
patch ':id/update_role', action: 'update_role', on: :collection
|
||||
end
|
||||
resources :reservations, only: %i[show create index update]
|
||||
resources :notifications, only: %i[index show update] do
|
||||
|
61
public/rank-icon.svg
Normal file
61
public/rank-icon.svg
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
height="74.5"
|
||||
width="56"
|
||||
sodipodi:docname="rank-icon.svg"
|
||||
version="1.1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 56 74.499999"
|
||||
enable-background="new 0 0 100 100"
|
||||
xml:space="preserve"
|
||||
id="svg102"><sodipodi:namedview
|
||||
inkscape:current-layer="svg102"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-x="0"
|
||||
inkscape:cy="60.2"
|
||||
inkscape:cx="27.8"
|
||||
inkscape:zoom="6.744"
|
||||
lock-margins="false"
|
||||
fit-margin-bottom="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-top="0"
|
||||
showgrid="false"
|
||||
id="namedview11"
|
||||
inkscape:window-height="1007"
|
||||
inkscape:window-width="1374"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
inkscape:document-rotation="0" /><metadata
|
||||
id="metadata108"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs106" /><g
|
||||
style="stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
transform="translate(-22.2,-2.3)"
|
||||
id="g92"><path
|
||||
style="stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 50.2,75.8 c -0.2,0 -0.3,0 -0.5,-0.1 L 23.7,60.8 C 23.4,60.6 23.2,60.3 23.2,59.9 V 45.1 c 0,-0.4 0.2,-0.7 0.5,-0.9 0.3,-0.2 0.7,-0.2 1,0 L 50.2,58.8 75.7,44.2 c 0.3,-0.2 0.7,-0.2 1,0 0.3,0.2 0.5,0.5 0.5,0.9 V 60 c 0,0.4 -0.2,0.7 -0.5,0.9 l -26,14.9 c -0.1,0 -0.3,0 -0.5,0 z m -25,-16.4 25,14.3 25,-14.3 V 46.9 l -24.5,14 c -0.3,0.2 -0.7,0.2 -1,0 l -24.5,-14 z"
|
||||
id="path90" /></g><g
|
||||
style="stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="translate(-22.2,-2.3)"
|
||||
id="g96"><path
|
||||
style="stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 62.5,45.1 c -0.3,0 -0.7,-0.1 -1,-0.2 L 50.3,39 39,44.8 C 38.1,45.3 37,45 36.4,44.3 36,43.8 35.8,43.2 35.9,42.6 L 38,30.1 29,21.2 c -0.6,-0.6 -0.8,-1.4 -0.5,-2.1 0.3,-0.7 0.9,-1.3 1.7,-1.4 L 42.7,15.9 48.4,4.5 c 0.4,-0.7 1.1,-1.2 1.9,-1.2 0.8,0 1.5,0.4 1.9,1.2 l 5.6,11.3 12.6,1.9 c 0.8,0.1 1.4,0.7 1.7,1.4 0.2,0.8 0,1.6 -0.5,2.1 l -9.1,8.8 2.1,12.5 c 0.1,0.6 -0.1,1.2 -0.5,1.7 -0.4,0.6 -1,0.9 -1.6,0.9 z M 50.2,36.9 c 0.3,0 0.7,0.1 1,0.2 L 62.4,43 c 0,0 0.1,0 0.1,0 L 60.4,30.5 c -0.1,-0.7 0.1,-1.4 0.6,-1.9 l 9.1,-8.8 c 0,0 0,0 0,-0.1 0,-0.1 -0.1,-0.1 -0.1,-0.1 L 57.5,17.8 C 56.8,17.7 56.2,17.3 55.9,16.7 L 50.3,5.3 c 0,0 -0.2,0 -0.2,0 l -5.6,11.3 c -0.3,0.6 -0.9,1 -1.6,1.1 l -12.5,1.8 c 0,0 -0.1,0 -0.1,0.1 0,0.1 0,0.1 0,0.1 l 9.1,8.8 c 0.5,0.5 0.7,1.2 0.6,1.9 L 37.9,42.9 38,43 49.2,37.1 c 0.4,-0.1 0.7,-0.2 1,-0.2 z"
|
||||
id="path94" /></g></svg>
|
After Width: | Height: | Size: 3.3 KiB |
Loading…
Reference in New Issue
Block a user