mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 11:20:39 -03:30
clean up of ui rbac code
This commit is contained in:
parent
433ba95add
commit
56364617fd
@ -1,15 +1,39 @@
|
||||
@import "../../shared/branding/colors.default.less";
|
||||
|
||||
/** @define AddPermissions */
|
||||
.AddPermissions {
|
||||
position: absolute;
|
||||
|
||||
.AddPermissions-backDrop {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
z-index: 1041;
|
||||
opacity: 0;
|
||||
transition: 0.5s opacity;
|
||||
background: @login-backdrop;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.AddPermissions-dialog {
|
||||
margin: 30px auto;
|
||||
margin-top: 95px;
|
||||
}
|
||||
|
||||
.AddPermissions-content {
|
||||
max-width: 750px !important;
|
||||
max-width: 750px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background-color: @login-bg;
|
||||
border-radius: 4px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s;
|
||||
z-index: 1042;
|
||||
position: relative;
|
||||
opacity: 1;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
.AddPermissions-header {
|
||||
@ -19,13 +43,20 @@
|
||||
}
|
||||
|
||||
.AddPermissions-body {
|
||||
padding-top: 0px !important;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-top: 0px;
|
||||
max-height: 70vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.AddPermissions-footer {
|
||||
padding-top: 20px !important;
|
||||
display: flex;
|
||||
flex-wrap: wrap-reverse;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
padding-bottom: 0px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.AddPermissions-list .List-searchRow {
|
||||
@ -64,7 +95,7 @@
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
border-radius: 50%;
|
||||
background-color: #ebebeb;
|
||||
background-color: @default-list-header-bg;
|
||||
padding-left: 6px;
|
||||
padding-right: 1px;
|
||||
padding-bottom: 3px;
|
||||
@ -75,7 +106,7 @@
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
border-bottom: 1px solid @default-second-border;
|
||||
}
|
||||
|
||||
.AddPermissions-roleRow {
|
||||
@ -102,11 +133,11 @@
|
||||
.AddPermissions-roleType {
|
||||
border-radius: 5px;
|
||||
padding: 0px 6px;
|
||||
border: 1px solid #e1e1e1;
|
||||
border: 1px solid @default-second-border;
|
||||
font-size: 10px;
|
||||
color: #848992;
|
||||
color: @default-interface-txt;
|
||||
text-transform: uppercase;
|
||||
background-color: #fff;
|
||||
background-color: @default-bg;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
@ -125,14 +156,14 @@
|
||||
line-height: 11px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
color: #b7b7b7;
|
||||
background-color: #fafafa;
|
||||
color: @default-icon;
|
||||
background-color: @default-tertiary-bg;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.AddPermissions-roleRemove:hover {
|
||||
background-color: #ff5850;
|
||||
color: #fff;
|
||||
background-color: @default-err;
|
||||
color: @default-bg;
|
||||
}
|
||||
|
||||
.AddPermissions-selectHide {
|
||||
|
||||
@ -6,55 +6,22 @@
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name controllers.function:Authentication
|
||||
* @name controllers.function:Access
|
||||
* @description
|
||||
* Controller for handling /#/login and /#/logout routes.
|
||||
*
|
||||
* Tower (app.js) verifies the user is authenticated and that the user session is not expired. If either condition is not true,
|
||||
* the user is redirected to /#/login and the Authentication controller.
|
||||
*
|
||||
* Methods for checking the session state are found in [js/shared/AuthService.js](/static/docs/api/shared.function:AuthService), which is referenced here as Authorization.
|
||||
*
|
||||
* #Login Modal Dialog
|
||||
*
|
||||
* The modal dialog prompting for username and password is found in templates/ui/index.html.
|
||||
*```
|
||||
* <!-- login modal -->
|
||||
* <div id="login-modal" class="modal fade">
|
||||
* <div class="modal-dialog">
|
||||
* <div class="modal-content" id="login-modal-content">
|
||||
* </div><!-- modal-content -->
|
||||
* </div><!-- modal-dialog -->
|
||||
* </div><!-- modal -->
|
||||
*```
|
||||
* HTML for the login form is generated, compiled and injected into <div id="login-modal-content"></div> by the controller. This is done to associate the form with the controller's scope. Because
|
||||
* <div id="login-modal"></div> is outside of the ng-view container, it gets associated with $rootScope by default. In the controller we create a new scope using $rootScope.$new() and associate
|
||||
* that with the login form. Doing this each time the controller is instantiated insures the form is clean and not pre-populated with a prior user's username and password.
|
||||
*
|
||||
* Just before the release of 2.0 a bug was discovered where clicking logout and then immediately clicking login without providing a username and password would successfully log
|
||||
* the user back into Tower. Implementing the above approach fixed this, forcing a new username/password to be entered each time the login dialog appears.
|
||||
*
|
||||
* #Login Workflow
|
||||
*
|
||||
* When the the login button is clicked, the following occurs:
|
||||
*
|
||||
* - Call Authorization.retrieveToken(username, password) - sends a POST request to /api/v1/authtoken to get a new token value.
|
||||
* - Call Authorization.setToken(token, expires) to store the token and exipration time in a session cookie.
|
||||
* - Start the expiration timer by calling the init() method of [js/shared/Timer.js](/static/docs/api/shared.function:Timer)
|
||||
* - Get user informaton by calling Authorization.getUser() - sends a GET request to /api/v1/me
|
||||
* - Store user information in the session cookie by calling Authorization.setUser().
|
||||
* - Get the Tower license by calling Authorization.getLicense() - sends a GET request to /api/vi/config
|
||||
* - Stores the license object in local storage by calling Authorization.setLicense(). This adds the Tower version and a tested flag to the license object. The tested flag is initially set to false.
|
||||
*
|
||||
* Note that there is a session timer kept on the server side as well as the client side. Each time an API request is made, Tower (in app.js) calls
|
||||
* Timer.isExpired(). This verifies the UI does not think the session is expired, and if not, moves the expiration time into the future. The number of
|
||||
* seconds between API calls before a session is considered expired is set in config.js as session_timeout.
|
||||
*
|
||||
* @Usage
|
||||
* This is usage information.
|
||||
* Controller for handling permissions adding
|
||||
*/
|
||||
|
||||
export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (rootScope, scope, GetBasePath, Rest, $q) {
|
||||
var manuallyUpdateChecklists = function(list, id, isSelected) {
|
||||
var elemScope = angular
|
||||
.element("#" +
|
||||
list + "s_table #" + id + ".List-tableRow input")
|
||||
.scope();
|
||||
if (elemScope) {
|
||||
elemScope.isSelected = !!isSelected;
|
||||
}
|
||||
};
|
||||
|
||||
scope.allSelected = [];
|
||||
|
||||
// the object permissions are being added to
|
||||
@ -72,6 +39,8 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (r
|
||||
.roles[key].name };
|
||||
});
|
||||
|
||||
// TODO: get working with api
|
||||
// array w roles and descriptions for key
|
||||
scope.roleKey = Object
|
||||
.keys(scope.object.summary_fields.roles)
|
||||
.map(function(key) {
|
||||
@ -82,35 +51,36 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (r
|
||||
.roles[key].description };
|
||||
});
|
||||
|
||||
// handle form tabs
|
||||
// handle form tab changes
|
||||
scope.toggleFormTabs = function(list) {
|
||||
scope.usersSelected = (list === 'users');
|
||||
scope.teamsSelected = !scope.usersSelected;
|
||||
};
|
||||
|
||||
// TODO: manually handle selection/deselection
|
||||
// of user/team checkboxes
|
||||
// manually handle selection/deselection of user/team checkboxes
|
||||
scope.$on("selectedOrDeselected", function(e, val) {
|
||||
val = val.value;
|
||||
if (val.isSelected) {
|
||||
// deselected, so remove from the allSelected list
|
||||
scope.allSelected = scope.allSelected.filter(function(i) {
|
||||
// return all but the object who has the id and type
|
||||
// of the element to deselect
|
||||
return (!(val.id === i.id && val.type === i.type));
|
||||
});
|
||||
} else {
|
||||
var name;
|
||||
|
||||
if (val.type === "user") {
|
||||
name = (val.first_name &&
|
||||
val.last_name) ?
|
||||
val.first_name + " " +
|
||||
val.last_name :
|
||||
val.username;
|
||||
} else {
|
||||
name = val.name;
|
||||
}
|
||||
|
||||
// selected, so add to the allSelected list
|
||||
scope.allSelected.push({
|
||||
name: name,
|
||||
name: function() {
|
||||
if (val.type === "user") {
|
||||
return (val.first_name &&
|
||||
val.last_name) ?
|
||||
val.first_name + " " +
|
||||
val.last_name :
|
||||
val.username;
|
||||
} else {
|
||||
return val .name;
|
||||
}
|
||||
},
|
||||
type: val.type,
|
||||
roles: [],
|
||||
id: val.id
|
||||
@ -118,10 +88,16 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (r
|
||||
}
|
||||
});
|
||||
|
||||
// used to handle changes to the itemsSelected scope var on "next page",
|
||||
// "sorting etc."
|
||||
scope.$on("itemsSelected", function(e, inList) {
|
||||
// compile a list of objects that needed to be checked in the lists
|
||||
scope.updateLists = scope.allSelected.filter(function(inMemory) {
|
||||
var notInList = true;
|
||||
inList.forEach(function(val) {
|
||||
// if the object is part of the allSelected list and is
|
||||
// selected,
|
||||
// you don't need to add it updateLists
|
||||
if (inMemory.id === val.id &&
|
||||
inMemory.type === val.type) {
|
||||
notInList = false;
|
||||
@ -131,61 +107,19 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (r
|
||||
});
|
||||
});
|
||||
|
||||
// handle changes to the updatedLists by manually selected those values in
|
||||
// the UI
|
||||
scope.$watch("updateLists", function(toUpdate) {
|
||||
(toUpdate || []).forEach(function(obj) {
|
||||
var elemScope = angular
|
||||
.element("#" +
|
||||
obj.type + "s_table #" + obj.id +
|
||||
".List-tableRow input")
|
||||
.scope()
|
||||
if (elemScope) {
|
||||
elemScope.isSelected = true;
|
||||
}
|
||||
manuallyUpdateChecklists(obj.type, obj.id, true);
|
||||
});
|
||||
|
||||
delete scope.updateLists;
|
||||
});
|
||||
|
||||
// create array of users/teams
|
||||
// scope.$watchGroup(['selectedUsers', 'selectedTeams'],
|
||||
// function(val) {
|
||||
// scope.allSelected = (val[0] || [])
|
||||
// .map(function(i) {
|
||||
// var roles = i.roles || [];
|
||||
// var name = (i.first_name &&
|
||||
// i.last_name) ?
|
||||
// i.first_name + " " +
|
||||
// i.last_name :
|
||||
// i.username;
|
||||
//
|
||||
// return {
|
||||
// name: name,
|
||||
// type: "user",
|
||||
// roles: roles,
|
||||
// id: i.id
|
||||
// };
|
||||
// }).concat((val[1] || [])
|
||||
// .map(function(i) {
|
||||
// var roles = i.roles || [];
|
||||
//
|
||||
// return {
|
||||
// name: i.name,
|
||||
// type: "team",
|
||||
// roles: roles,
|
||||
// id: i.id
|
||||
// };
|
||||
// }));
|
||||
// });
|
||||
|
||||
// remove selected user/team
|
||||
scope.removeObject = function(obj) {
|
||||
var elemScope = angular
|
||||
.element("#" +
|
||||
obj.type + "s_table #" + obj.id + ".List-tableRow input")
|
||||
.scope()
|
||||
if (elemScope) {
|
||||
elemScope.isSelected = false;
|
||||
}
|
||||
manuallyUpdateChecklists(obj.type, obj.id, false);
|
||||
|
||||
scope.allSelected = scope.allSelected.filter(function(i) {
|
||||
return (!(obj.id === i.id && obj.type === i.type));
|
||||
@ -197,7 +131,7 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (r
|
||||
scope.posts = _
|
||||
.flatten((val || [])
|
||||
.map(function (owner) {
|
||||
var url = GetBasePath(owner.type + "s") + "/" + owner.id +
|
||||
var url = GetBasePath(owner.type + "s") + owner.id +
|
||||
"/roles/";
|
||||
|
||||
return (owner.roles || [])
|
||||
@ -217,7 +151,7 @@ export default ['$rootScope', '$scope', 'GetBasePath', 'Rest', '$q', function (r
|
||||
});
|
||||
|
||||
$q.all(requests)
|
||||
.then(function (responses) {
|
||||
.then(function () {
|
||||
rootScope.$broadcast("refreshList", "permission");
|
||||
scope.closeModal();
|
||||
}, function (error) {
|
||||
|
||||
@ -17,7 +17,7 @@ export default
|
||||
templateUrl: templateUrl('access/addPermissions/addPermissions'),
|
||||
link: function(scope, element, attrs, ctrl) {
|
||||
scope.toggleFormTabs('users');
|
||||
|
||||
|
||||
$("body").append(element);
|
||||
|
||||
Wait('start');
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div id="add-permissions-modal" class="LoginModal modal fade">
|
||||
<div class="LoginModal-backDrop is-loggedOut"></div>
|
||||
<div class="LoginModal-dialog">
|
||||
<div class="LoginModal-content is-loggedOut AddPermissions-content">
|
||||
<div id="add-permissions-modal" class="AddPermissions modal fade">
|
||||
<div class="AddPermissions-backDrop is-loggedOut"></div>
|
||||
<div class="AddPermissions-dialog">
|
||||
<div class="AddPermissions-content is-loggedOut">
|
||||
<div class="AddPermissions-header">
|
||||
<div class="List-header">
|
||||
<div class="List-title">
|
||||
@ -18,7 +18,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="LoginModal-body AddPermissions-body">
|
||||
<div class="AddPermissions-body">
|
||||
<div class="AddPermissions-directions">
|
||||
<span class="AddPermissions-directionNumber">
|
||||
1.
|
||||
@ -41,14 +41,12 @@
|
||||
</div>
|
||||
|
||||
<div class="AddPermissions-list" ng-show="usersSelected">
|
||||
<add-permissions-users
|
||||
selected="selectedUsers">
|
||||
</add-permissions-users>
|
||||
<add-permissions-list type="users">
|
||||
</add-permissions-list>
|
||||
</div>
|
||||
<div class="AddPermissions-list" ng-show="teamsSelected">
|
||||
<add-permissions-teams
|
||||
selected="selectedTeams">
|
||||
</add-permissions-teams>
|
||||
<add-permissions-list type="teams">
|
||||
</add-permissions-list>
|
||||
</div>
|
||||
|
||||
<div class="AddPermissions-separator"
|
||||
@ -83,7 +81,7 @@
|
||||
</ng-form>
|
||||
</form>
|
||||
</div>
|
||||
<div class="LoginModal-footer AddPermissions-footer">
|
||||
<div class="AddPermissions-footer">
|
||||
{{ post }}
|
||||
<div class="buttons Form-buttons AddPermissions-buttons">
|
||||
<button type="button"
|
||||
|
||||
@ -6,16 +6,17 @@
|
||||
|
||||
/* jshint unused: vars */
|
||||
export default
|
||||
['addPermissionsTeamsList', 'generateList', 'GetBasePath', 'SelectionInit', 'SearchInit',
|
||||
'PaginateInit', function(addPermissionsTeamsList, generateList,
|
||||
['addPermissionsTeamsList', 'addPermissionsUsersList', 'generateList', 'GetBasePath', 'SelectionInit', 'SearchInit',
|
||||
'PaginateInit', function(addPermissionsTeamsList,
|
||||
addPermissionsUsersList, generateList,
|
||||
GetBasePath, SelectionInit, SearchInit, PaginateInit) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
},
|
||||
template: "<div id='addPermissionsTeamsList'></div>",
|
||||
template: "<div class='addPermissionsList-inner'></div>",
|
||||
link: function(scope, element, attrs, ctrl) {
|
||||
scope.$on("linkLists", function() {
|
||||
scope.$on("linkLists", function(e) {
|
||||
var generator = generateList,
|
||||
list = addPermissionsTeamsList,
|
||||
url = GetBasePath("teams"),
|
||||
@ -23,10 +24,23 @@ export default
|
||||
id = "addPermissionsTeamsList",
|
||||
mode = "edit";
|
||||
|
||||
if (attrs.type === 'users') {
|
||||
list = addPermissionsUsersList;
|
||||
url = GetBasePath("users") + "?is_superuser=false";
|
||||
set = "users";
|
||||
id = "addPermissionsUsersList";
|
||||
mode = "edit";
|
||||
}
|
||||
|
||||
scope.id = id;
|
||||
|
||||
scope.$watch("selectedItems", function() {
|
||||
scope.$emit("itemsSelected", scope.selectedItems);
|
||||
});
|
||||
|
||||
element.find(".addPermissionsList-inner")
|
||||
.attr("id", id);
|
||||
|
||||
generator.inject(list, { id: id,
|
||||
title: false, mode: mode, scope: scope });
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import addPermissionsListDirective from './addPermissionsList.directive';
|
||||
import teamsList from './permissionsTeams.list';
|
||||
import usersList from './permissionsUsers.list';
|
||||
|
||||
export default
|
||||
angular.module('addPermissionsListModule', [])
|
||||
.directive('addPermissionsList', addPermissionsListDirective)
|
||||
.factory('addPermissionsTeamsList', teamsList)
|
||||
.factory('addPermissionsUsersList', usersList);
|
||||
@ -6,10 +6,9 @@
|
||||
|
||||
import addPermissionsDirective from './addPermissions.directive';
|
||||
import roleSelect from './roleSelect.directive';
|
||||
import teamsPermissions from './teams/main';
|
||||
import usersPermissions from './users/main';
|
||||
import addPermissionsList from './addPermissionsList/main';
|
||||
|
||||
export default
|
||||
angular.module('AddPermissions', [teamsPermissions.name, usersPermissions.name])
|
||||
angular.module('AddPermissions', [addPermissionsList.name])
|
||||
.directive('addPermissions', addPermissionsDirective)
|
||||
.directive('roleSelect', roleSelect);
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import teamsDirective from './permissionsTeams.directive';
|
||||
import teamsList from './permissionsTeams.list';
|
||||
|
||||
export default
|
||||
angular.module('PermissionsTeams', [])
|
||||
.directive('addPermissionsTeams', teamsDirective)
|
||||
.factory('addPermissionsTeamsList', teamsList);
|
||||
@ -1,13 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import usersDirective from './permissionsUsers.directive';
|
||||
import usersList from './permissionsUsers.list';
|
||||
|
||||
export default
|
||||
angular.module('PermissionsUsers', [])
|
||||
.directive('addPermissionsUsers', usersDirective)
|
||||
.factory('addPermissionsUsersList', usersList);
|
||||
@ -1,44 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
/* jshint unused: vars */
|
||||
export default
|
||||
['addPermissionsUsersList', 'generateList', 'GetBasePath', 'SelectionInit', 'SearchInit',
|
||||
'PaginateInit', function(addPermissionsUsersList, generateList,
|
||||
GetBasePath, SelectionInit, SearchInit, PaginateInit) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
},
|
||||
template: "<div id='addPermissionsUsersList'></div>",
|
||||
link: function(scope, element, attrs, ctrl) {
|
||||
scope.$on("linkLists", function() {
|
||||
var generator = generateList,
|
||||
list = addPermissionsUsersList,
|
||||
url = GetBasePath("users") + "?is_superuser=false",
|
||||
set = "users",
|
||||
id = "addPermissionsUsersList",
|
||||
mode = "edit";
|
||||
|
||||
scope.$watch("selectedItems", function() {
|
||||
scope.$emit("itemsSelected", scope.selectedItems);
|
||||
});
|
||||
|
||||
generator.inject(list, { id: id,
|
||||
title: false, mode: mode, scope: scope });
|
||||
|
||||
SearchInit({ scope: scope, set: set,
|
||||
list: list, url: url });
|
||||
|
||||
PaginateInit({ scope: scope,
|
||||
list: list, url: url, pageSize: 5 });
|
||||
|
||||
scope.search(list.iterator);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
];
|
||||
@ -1,4 +1,5 @@
|
||||
/** @define RoleList */
|
||||
@import "../shared/branding/colors.default.less";
|
||||
|
||||
.RoleList {
|
||||
display: flex;
|
||||
@ -15,11 +16,11 @@
|
||||
border-radius: 5px;
|
||||
padding: 2px 10px;
|
||||
margin: 4px 0px;
|
||||
border: 1px solid #e1e1e1;
|
||||
border: 1px solid @default-second-border;
|
||||
font-size: 12px;
|
||||
color: #848992;
|
||||
color: @default-interface-txt;
|
||||
text-transform: uppercase;
|
||||
background-color: #fff;
|
||||
background-color: @default-bg;
|
||||
margin-right: 5px;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
@ -36,7 +37,7 @@
|
||||
}
|
||||
|
||||
.RoleList-deleteContainer {
|
||||
border: 1px solid #e1e1e1;
|
||||
border: 1px solid @default-second-border;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
padding: 0 5px;
|
||||
@ -49,7 +50,7 @@
|
||||
|
||||
.RoleList-tagDelete {
|
||||
font-size: 13px;
|
||||
color: #b7b7b7;
|
||||
color: @default-icon;
|
||||
}
|
||||
|
||||
.RoleList-name {
|
||||
@ -62,10 +63,10 @@
|
||||
}
|
||||
|
||||
.RoleList-deleteContainer:hover, {
|
||||
border-color: #ff5850;
|
||||
background-color: #ff5850;
|
||||
border-color: @default-err;
|
||||
background-color: @default-err;
|
||||
}
|
||||
|
||||
.RoleList-deleteContainer:hover > .RoleList-tagDelete {
|
||||
color: #fff;
|
||||
color: @default-bg;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user