Add new permissions management ui (role overrides)
When editing permissions for an account, course or admin section the UI has changed to use drop downs instead of a 6 state check box. It has also been switched to use 100% backbonejs to handle creating and editing roles. This works with the roles api and allows you to create custom roles for courses. fixes #CNVS-1165 Test Plan Apply this test in two places. The Site Admin and a custom university. 1. Go to the "permissions" tab 2. Notice permissions are available per role in a table. ------------ Adding/Removing Roles -------------- 1. When under the "Account Role" tab click "Add Role" 2. Enter a role name and click "Create/Add" 3. A new role should appear automatically. 4. You should be able to delete this role by clicking the x next to it's name. ------------ Editing Permissions ---------------- 1. Go to a role in the permissions tab. 2. Try to edit one of it's permissions. It should have a drop down with options to select permissions. You should be able to enable/disable or set to default and lock the permission. Read only permissions cannot be clicked on. 3. Buttons with default set should have a special "default" class added to the button representing its permission. ------------ Organization of Roles -------------- 1. In the course role tab, add a few roles with different base types (use the dropwdown) 2. Roles should be grouped together by base role type. ------------ Automatic Saving ------------------ 1. Change a permission on a role 2. The role should automatically save the the permission after selecting the option you want Change-Id: I343afc36b85183e5913c8eef6111ea2c5ae62726 Reviewed-on: https://gerrit.instructure.com/16323 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Bracken Mosbacker <bracken@instructure.com> QA-Review: Adam Phillipps <adam@instructure.com>
This commit is contained in:
parent
14f6a92c0b
commit
f3d8cdd94c
|
@ -72,7 +72,9 @@ define [
|
|||
# in charge of getting variables ready to pass to handlebars during render
|
||||
# override with your own logic to do something fancy.
|
||||
toJSON: ->
|
||||
(@model ? @collection)?.toJSON arguments...
|
||||
json = ((@model ? @collection)?.toJSON arguments...) || {}
|
||||
json.cid = @cid
|
||||
json
|
||||
|
||||
##
|
||||
# Renders all child views
|
||||
|
@ -83,13 +85,15 @@ define [
|
|||
|
||||
##
|
||||
# Renders a single child view and appends its designated element
|
||||
# Use ids in your view, not classes. This
|
||||
#
|
||||
# @api private
|
||||
renderView: (view, className) =>
|
||||
target = @$('.' + className).first()
|
||||
renderView: (view, selector) =>
|
||||
target = @$("##{selector}")
|
||||
target = @$(".#{selector}") unless target.length
|
||||
view.setElement target
|
||||
view.render()
|
||||
@[className] ?= view
|
||||
@[selector] ?= view
|
||||
|
||||
##
|
||||
# Binds a `@model` data to the element's html. Whenever the data changes
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
require [
|
||||
'jquery',
|
||||
'underscore'
|
||||
'compiled/models/Role'
|
||||
'compiled/models/Account'
|
||||
'compiled/collections/RolesCollection'
|
||||
'compiled/views/roles/RolesOverrideIndexView'
|
||||
'compiled/views/roles/AccountRolesView'
|
||||
'compiled/views/roles/CourseRolesView'
|
||||
'compiled/views/roles/ManageRolesView'
|
||||
'compiled/views/roles/NewRoleView'
|
||||
], ($, _, Role, Account, RolesCollection, RolesOverrideIndexView, AccountRolesView, CourseRolesView, ManageRolesView, NewRoleView) ->
|
||||
account_roles = new RolesCollection ENV.ACCOUNT_ROLES
|
||||
course_roles = new RolesCollection ENV.COURSE_ROLES
|
||||
|
||||
course_permissions = ENV.COURSE_PERMISSIONS
|
||||
account_permissions = ENV.ACCOUNT_PERMISSIONS
|
||||
course_role_types = []
|
||||
_.each ENV.COURSE_ROLES, (role) ->
|
||||
if role.role == role.base_role_type
|
||||
course_role_types.push
|
||||
value : role.base_role_type
|
||||
label : role.label
|
||||
|
||||
# They will both use the same collection.
|
||||
rolesOverrideIndexView = new RolesOverrideIndexView
|
||||
el: '#content'
|
||||
views:
|
||||
'account-roles': new AccountRolesView
|
||||
views:
|
||||
'#account_roles' : new ManageRolesView
|
||||
collection: account_roles
|
||||
permission_groups: account_permissions
|
||||
'new-role' : new NewRoleView
|
||||
base_role_types: [{value:'AccountMembership', label:'AccountMembership'}]
|
||||
admin_roles: true
|
||||
collection: account_roles
|
||||
|
||||
'course-roles': new CourseRolesView
|
||||
views:
|
||||
'#course_roles' : new ManageRolesView
|
||||
collection: course_roles
|
||||
permission_groups: course_permissions
|
||||
'new-role' : new NewRoleView
|
||||
base_role_types: course_role_types
|
||||
collection: course_roles
|
||||
|
||||
rolesOverrideIndexView.render()
|
||||
|
||||
# Make sure the left navigation permissions is highlighted.
|
||||
$('#section-tabs .permissions').addClass 'active'
|
||||
|
||||
# This is not the right way to do this and is just a hack until
|
||||
# something offical in canvas is built.
|
||||
# Adds toggle functionality to the menu buttons.
|
||||
# Yes, it's ugly but works :) Sorry.
|
||||
# ============================================================
|
||||
# DELETE ME SOMEDAY!
|
||||
# ============================================================
|
||||
$(document).on 'click', (event) ->
|
||||
container = $('.btn-group')
|
||||
if (container.has(event.target).length is 0 and !$(event.target).hasClass('.btn'))
|
||||
container.removeClass 'open'
|
||||
|
||||
$(document).on 'click', '.btn', (event) ->
|
||||
event.preventDefault()
|
||||
previous_state = $(this).parent().hasClass 'open'
|
||||
$('.btn-group').removeClass 'open'
|
||||
|
||||
if (previous_state == false && !$(this).attr('disabled') )
|
||||
$(this).parent().addClass('open')
|
||||
$(this).siblings('.dropdown-menu').find('input').first().focus()
|
||||
|
||||
$(document).on 'keyup', (event) =>
|
||||
if (event.keyCode == 27)
|
||||
$('.btn-group').removeClass 'open'
|
||||
$(this).focus()
|
||||
|
||||
|
||||
##################################################################
|
|
@ -0,0 +1,32 @@
|
|||
define [
|
||||
'Backbone'
|
||||
'underscore'
|
||||
'compiled/models/Role'
|
||||
], (Backbone, _, Role) ->
|
||||
class RolesCollection extends Backbone.Collection
|
||||
model: Role
|
||||
|
||||
sortOrder: [
|
||||
"NoPermissions"
|
||||
"AccountMembership"
|
||||
"StudentEnrollment"
|
||||
"TaEnrollment"
|
||||
"TeacherEnrollment"
|
||||
"DesignerEnrollment"
|
||||
"ObserverEnrollment"
|
||||
]
|
||||
|
||||
# Method Summary
|
||||
# make a comment
|
||||
# @api backbone override
|
||||
comparator: (role) ->
|
||||
base_role_type= role.get 'base_role_type'
|
||||
|
||||
index = _.indexOf @sortOrder, base_role_type
|
||||
if base_role_type == role.get 'role'
|
||||
return "#{index}_#{base_role_type}"
|
||||
else if role.get "role" == "AccountAdmin"
|
||||
return "0_#{base_role_type}"
|
||||
else
|
||||
return "#{index}_#{base_role_type}_#{role}"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
define [
|
||||
'Backbone'
|
||||
'underscore'
|
||||
], (Backbone, _) ->
|
||||
class Account extends Backbone.Model
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
define [
|
||||
'Backbone'
|
||||
'underscore'
|
||||
'compiled/models/Account'
|
||||
], (Backbone, _, Account) ->
|
||||
class Role extends Backbone.Model
|
||||
# Method Summary
|
||||
# Each role has an Account model nested in it. When creating
|
||||
# a new role, run it through and makes sure attributes have
|
||||
# and account model nested in model.account. It's NOT using
|
||||
# parse because parse sets the id to role in parse (because roles
|
||||
# have 'fake' ids so backbone will work) and when an id is set
|
||||
# when you try to save, it assumes it was all ready created and
|
||||
# does a PUT instead of a POST request. Thus, we don't call parse
|
||||
# we call nestAccountModel.
|
||||
# @api backbone override
|
||||
initialize: (attributes, options) ->
|
||||
super
|
||||
|
||||
if attributes
|
||||
parsedAttributes = @nestAccountModel attributes
|
||||
@set parsedAttributes
|
||||
|
||||
# Method Summary
|
||||
# urlRoot is used in url to generate the a restful url. Because
|
||||
# the "id" is set to the roles name (see parse function), the
|
||||
# url uses the role name in place of the :id attribute in the url
|
||||
#
|
||||
# ie:
|
||||
# /accounts/:account_id/roles
|
||||
# /accounts/:account_id/roles/:some_role_name
|
||||
#
|
||||
# produces
|
||||
# /accounts/1/roles
|
||||
# /accounts/1/roles/StudentAssistant
|
||||
#
|
||||
# @api override backbone
|
||||
urlRoot: -> "/api/v1/accounts/#{@get('account').get('id')}/roles"
|
||||
|
||||
# Method Summary
|
||||
# ResourceName is used by a collection to help determin the url
|
||||
# that should be generated for the resource.
|
||||
# @api custom backbone override
|
||||
resourceName: 'roles'
|
||||
|
||||
# Method Summary
|
||||
# Expects data to have data.account object that will be used to
|
||||
# create a new model. The new model replaces the old account
|
||||
# object.
|
||||
# @api private
|
||||
nestAccountModel: (data) ->
|
||||
data.account = new Account data.account
|
||||
data
|
||||
|
||||
# Method Summary
|
||||
# Parse is called when data is set via attributes to the model.
|
||||
# Because roles might not always have a unique id, we are
|
||||
# setting the id to be the role name. This takes care of checks
|
||||
# for "isNew()" as well as issues with generating a correct url.
|
||||
# Also, ensure that account is wrapped in a backbone model since
|
||||
# the url relies on it being a backbone model.
|
||||
# @api override backbone
|
||||
parse: (data) ->
|
||||
data.id = data.role if data.role
|
||||
data = @nestAccountModel(data)
|
||||
data
|
||||
|
||||
# Method Summary
|
||||
# See backbones explaination of a validate method for in depth
|
||||
# details but in short, if your return something from validate
|
||||
# there is an error, if you don't, there are no errors. Throw
|
||||
# in the error object to any validation function you make. It's
|
||||
# passed by reference dawg.
|
||||
# @api override backbone
|
||||
validate: (attrs) ->
|
||||
errors = {}
|
||||
errors unless _.isEmpty errors
|
|
@ -0,0 +1,9 @@
|
|||
define [], ->
|
||||
BASE_ROLE_TYPES = [
|
||||
'AccountMembership'
|
||||
'StudentEnrollment'
|
||||
'TeacherEnrollment'
|
||||
'TaEnrollment'
|
||||
'ObserverEnrollment'
|
||||
'DesignerEnrollment'
|
||||
]
|
|
@ -0,0 +1,8 @@
|
|||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/accountRoles'
|
||||
], ($, _, Backbone, template) ->
|
||||
class AccountRolesView extends Backbone.View
|
||||
template: template
|
|
@ -0,0 +1,8 @@
|
|||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/courseRoles'
|
||||
], ($, _, Backbone, template) ->
|
||||
class CourseRolesView extends Backbone.View
|
||||
template: template
|
|
@ -0,0 +1,120 @@
|
|||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/manageRoles'
|
||||
'compiled/views/roles/PermissionButtonView'
|
||||
'compiled/views/roles/RoleHeaderView'
|
||||
], ($, _, Backbone, template, PermissionButtonView, RoleHeaderView) ->
|
||||
class ManageRolesView extends Backbone.View
|
||||
template: template
|
||||
className: 'manage-roles-table'
|
||||
|
||||
# Method Summary
|
||||
# When a new Role is added/removed from the collection, re-draw the table.
|
||||
initialize: ->
|
||||
super
|
||||
@permission_groups = @options.permission_groups if @options.permission_groups
|
||||
@collection.on 'add', @renderTable
|
||||
@collection.on 'remove', @renderTable
|
||||
|
||||
# Method Summary
|
||||
# Gets called after this backbone view has
|
||||
# been rendered. For each permission in the
|
||||
# permission list, it will add a new
|
||||
# permission select box for each role in the roles
|
||||
# collection. In this way, we are drawing the
|
||||
# whole table row by row since html doesn't
|
||||
# support drawing column by column.
|
||||
# @api custom backbone
|
||||
filter: ->
|
||||
@renderTable()
|
||||
|
||||
# Method Summary
|
||||
# The table has two parts. A header and the tbody part. The header
|
||||
# has some functionality to do with deleting a role so contains its
|
||||
# own logic. renderHeader gets called when renderTable gets
|
||||
# called, which should get called when role is added or removed.
|
||||
# @api private
|
||||
renderHeader: ->
|
||||
@$el.find('thead tr').html "<th>Permissions</th>"
|
||||
|
||||
@collection.each (role) =>
|
||||
roleHeaderView = new RoleHeaderView
|
||||
model: role
|
||||
|
||||
@$el.find('thead tr').append roleHeaderView.render().el
|
||||
|
||||
# Method Summary
|
||||
# Creates the permission table by drawing it all at once.
|
||||
# This is necessary because html tables only support
|
||||
# drawing a table via rows instead of columns and we are
|
||||
# representing our data in coloumns. works by bring in
|
||||
# permission_groups, drawing the main group headers then
|
||||
# for each main group of permissions, drawing each one of
|
||||
# those permissions rows by iterating over each role in the
|
||||
# collection and drawing a select box for each role. The
|
||||
# permissions_group object looks like this.
|
||||
#
|
||||
# permission_groups = [
|
||||
# {
|
||||
# group_name:"Parent label"
|
||||
# group_permissions: [
|
||||
# {
|
||||
# label: "title"
|
||||
# permission_name: "some_property"
|
||||
# }
|
||||
# {
|
||||
# label: "title again"
|
||||
# permission_name: "some_property_again"
|
||||
# }
|
||||
#
|
||||
# ]
|
||||
# }
|
||||
# {
|
||||
# group_name:"Parent label 2"
|
||||
# group_permissions: [
|
||||
# label: "title 2"
|
||||
# permission_name: "some_other_property_2"
|
||||
# ]
|
||||
# }
|
||||
# ]
|
||||
#
|
||||
# Steps: 1. Draw group header
|
||||
# 2. Draw permission label
|
||||
# 3. Draw each select box from the collection of roles.
|
||||
# @api private
|
||||
renderTable: =>
|
||||
@renderHeader()
|
||||
@$el.find('tbody').html '' # Clear tbody in case it gets re-drawing.
|
||||
|
||||
_.each @permission_groups, (permission_group) =>
|
||||
# Add the headers to the group
|
||||
permission_group_header = """
|
||||
<tr class="toolbar">
|
||||
<th>#{permission_group.group_name.toUpperCase()}</th>
|
||||
<td colspan="#{@collection.length}"></td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
@$el.find('tbody').append permission_group_header
|
||||
|
||||
# Add each permission item.
|
||||
_.each permission_group.group_permissions, (permission_row) =>
|
||||
|
||||
permission_row_html = """
|
||||
<tr>
|
||||
<th role="rowheader">#{permission_row.label}</th>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
@$el.find('tbody').append permission_row_html
|
||||
|
||||
@collection.each (role) =>
|
||||
permissionButtonView = new PermissionButtonView
|
||||
model: role
|
||||
permission_name: permission_row.permission_name
|
||||
|
||||
@$el.find("tr")
|
||||
.last()
|
||||
.append permissionButtonView.render().el
|
|
@ -0,0 +1,74 @@
|
|||
define [
|
||||
'i18n!editor'
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/newRole'
|
||||
'compiled/models/Role'
|
||||
'compiled/models/Account'
|
||||
], (I18n, $, _, Backbone, template, Role, Account) ->
|
||||
class NewRoleView extends Backbone.View
|
||||
template: template
|
||||
|
||||
els:
|
||||
"input[type=text]" : "$role_name"
|
||||
"select" : "$base_role_type"
|
||||
|
||||
events:
|
||||
"click button" : "createRole"
|
||||
"submit form" : "createRole"
|
||||
|
||||
# Method Summary
|
||||
# We need base role types so we know what types the user can
|
||||
# select from. We also need to know if this is for admin roles.
|
||||
# If it is, the user can only select one type of base_role_type
|
||||
# which is "AccountMembership" See the template for better
|
||||
# understanding.
|
||||
# @api backbone override
|
||||
initialize: ->
|
||||
super
|
||||
@base_role_types = @options?.base_role_types
|
||||
@adminRoles = @options?.admin_roles
|
||||
|
||||
# Method Summary
|
||||
# JSON is dumped into the template so we are adding some logic
|
||||
# checks we can use to display certain information.
|
||||
# @api backbone override
|
||||
toJSON: ->
|
||||
json = super
|
||||
json['base_role_types'] = @base_role_types
|
||||
json['adminRoles'] = @adminRoles
|
||||
json
|
||||
|
||||
# Method Summary
|
||||
# This will grab values out of the newRole view and save them
|
||||
# as attributes when creating a new role. @collection.create
|
||||
# will create a new role and if it is successful, add it to
|
||||
# the collection. We also clear the form apon success. We
|
||||
# wait: true which means, wait until the request comes back
|
||||
# before adding the role to the collection.
|
||||
# @api private
|
||||
createRole: (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
role_name = @$role_name.val()
|
||||
base_role_type = @$base_role_type.val()
|
||||
|
||||
attributes =
|
||||
base_role_type: base_role_type
|
||||
role: role_name
|
||||
account: ENV.CURRENT_ACCOUNT.account
|
||||
|
||||
@collection.create attributes,
|
||||
success: (model) =>
|
||||
@clearForm()
|
||||
error: ->
|
||||
alert I18n.t "role.duplicate_role_error", "Could not create this role because a role with this name already exists. Please try a different name"
|
||||
wait: true
|
||||
|
||||
# Method Summary
|
||||
# Clear all variables in the form.
|
||||
# @api private
|
||||
clearForm: ->
|
||||
@$role_name.val('')
|
||||
@$base_role_type.val('')
|
|
@ -0,0 +1,362 @@
|
|||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/permissionButton'
|
||||
], ($, _, Backbone, template) ->
|
||||
class PermissionButtonView extends Backbone.View
|
||||
template: template
|
||||
tagName: 'td'
|
||||
className: 'permissionButtonView'
|
||||
|
||||
events:
|
||||
"change input[type=radio]" : "updateRole"
|
||||
|
||||
# Method Summary:
|
||||
# Set the permission_name attribute.
|
||||
#
|
||||
# ============================================================================
|
||||
# !!! NOTE permission_name This must be passed in for this view to work !!!
|
||||
# ============================================================================
|
||||
#
|
||||
# @api backbone override
|
||||
initialize: ->
|
||||
super
|
||||
@permission_name = @options.permission_name if @options.permission_name
|
||||
|
||||
# Method Summary
|
||||
# We add a few values to the json being passed into the template so we can determine which item
|
||||
# should be selected on the initial page load. We didn't create a helper for handlebars because
|
||||
# this is very specific to this class. We have some logic here that checks to see what the
|
||||
# permissions value is given it's key, the permission_name for some of the properties. Permissions
|
||||
# object might look like this.
|
||||
#
|
||||
# ie:
|
||||
# "enabled": true,
|
||||
# "locked": true,
|
||||
# "readonly": false,
|
||||
# "explicit": true,
|
||||
# "prior_default": false
|
||||
#
|
||||
# @api custom backbone override
|
||||
toJSON: ->
|
||||
json = super
|
||||
|
||||
json['enableChecked'] = @isEnabled()
|
||||
json['enableAndLockChecked'] = @isEnabledAndLocked()
|
||||
json['disableChecked'] = @isDisabled()
|
||||
json['disableAndLockChecked'] = @isDisabledAndLocked()
|
||||
json['systemDefaultChecked'] = @isDefault()
|
||||
json['systemDefaultLockedChecked'] = @isDefaultAndLocked()
|
||||
json['readOnly'] = @isReadOnly()
|
||||
json['default'] = @isDefault() || @isDefaultAndLocked() # Any kind of default. Used for setting a css class
|
||||
|
||||
json
|
||||
|
||||
# Method Summary
|
||||
# Make sure all initial icons are shown correctly. Puts the correct
|
||||
# set of icons into the button by cloning the icons in the dropdown
|
||||
# list. :) I'm a smarty pants. Also, add accessibility attributes.
|
||||
# Each button has data about it's role and permission name. This
|
||||
# makes testing easier.
|
||||
# @api custom backbone override
|
||||
filter: ->
|
||||
@setPreviewIcons()
|
||||
@$el.attr 'data-role_name', @model.id
|
||||
@$el.attr 'data-permission_name', @permission_name
|
||||
|
||||
# Method Summary
|
||||
# Preview Icons are set based on the model attributes, not what is
|
||||
# selected; however model attributes should always be in sync with
|
||||
# what is selected so it will have the same effect. There are only
|
||||
# 6 possiblities.
|
||||
# @api private
|
||||
setPreviewIcons: ->
|
||||
if @isEnabled() then @setEnabledIcon()
|
||||
else if @isEnabledAndLocked() then @setEnabledLockedIcon()
|
||||
else if @isDisabled() then @setDisabledIcon()
|
||||
else if @isDisabledAndLocked() then @setDisabledLockedIcon()
|
||||
else if @isDefault() then @setDefaultIcon()
|
||||
else if @isDefaultAndLocked() then @setDefaultAndLockedIcon()
|
||||
|
||||
# Method Summary:
|
||||
# We are checking the ides of each changed radio element because we
|
||||
# can't get access to @cid inside of the "events" object. If somone
|
||||
# can figure out how to do this feel free to remove this switch
|
||||
# statement.
|
||||
#
|
||||
# TODO Remove the 'default_permission' its ugly
|
||||
# @api private
|
||||
updateRole: (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
switch $(event.target).attr('id')
|
||||
when "button-#{@cid}-0"
|
||||
@$el.find('a.btn').removeClass 'default_permission'
|
||||
@enable()
|
||||
break
|
||||
when "button-#{@cid}-1"
|
||||
@$el.find('a.btn').removeClass 'default_permission'
|
||||
@enableAndLock()
|
||||
break
|
||||
when "button-#{@cid}-2"
|
||||
@$el.find('a.btn').removeClass 'default_permission'
|
||||
@disable()
|
||||
break
|
||||
when "button-#{@cid}-3"
|
||||
@$el.find('a.btn').removeClass 'default_permission'
|
||||
@disableAndLock()
|
||||
break
|
||||
when "button-#{@cid}-4"
|
||||
@$el.find('a.btn').addClass 'default_permission'
|
||||
@setSystemDefault()
|
||||
break
|
||||
when "button-#{@cid}-5"
|
||||
@$el.find('a.btn').addClass 'default_permission'
|
||||
@setSystemDefaultAndLocked()
|
||||
break
|
||||
|
||||
@setPreviewIcons()
|
||||
@closeMenu()
|
||||
@saveModel()
|
||||
|
||||
# Method Summary
|
||||
# Save the current role by calling .save.
|
||||
# @api private
|
||||
saveModel: ->
|
||||
@model.save {},
|
||||
failure: ->
|
||||
alert 'Permission was not be saved!'
|
||||
|
||||
# Method Summary
|
||||
# Close the menu by removing the 'open' class on it's parent btn-group
|
||||
# @api private
|
||||
closeMenu: ->
|
||||
@$el.children('.btn-group').removeClass 'open'
|
||||
|
||||
# Method Summary for enable, enableAndLock, disable, disableAndLock
|
||||
# When called, this enables the given role for this buttons property.
|
||||
# Enabling a property should look like the following
|
||||
#
|
||||
# some_property:
|
||||
# "enabled": true
|
||||
# "locked" : false
|
||||
# "explicit" : true
|
||||
# @api private
|
||||
enable: ->
|
||||
@model.get('permissions')[@permission_name].enabled = true
|
||||
@model.get('permissions')[@permission_name].explicit = true
|
||||
@model.get('permissions')[@permission_name].locked = false
|
||||
|
||||
enableAndLock: ->
|
||||
@model.get('permissions')[@permission_name].enabled = true
|
||||
@model.get('permissions')[@permission_name].explicit = true
|
||||
@model.get('permissions')[@permission_name].locked = true
|
||||
|
||||
disable: ->
|
||||
@model.get('permissions')[@permission_name].enabled = false
|
||||
@model.get('permissions')[@permission_name].explicit = true
|
||||
@model.get('permissions')[@permission_name].locked = false
|
||||
|
||||
disableAndLock: ->
|
||||
@model.get('permissions')[@permission_name].enabled = false
|
||||
@model.get('permissions')[@permission_name].explicit = true
|
||||
@model.get('permissions')[@permission_name].locked = true
|
||||
|
||||
# Method Summary
|
||||
# This is the edge case for setting properties. This does care what
|
||||
# the other properties were set to because when you set explict to
|
||||
# false and save it, the request comming back will tell you what
|
||||
# the prior default (either enabled or disabled) is. If no prior
|
||||
# default is set, then you can assume what the permission is based
|
||||
# on the properites sent back. For example, just use the enabled
|
||||
# field.
|
||||
#
|
||||
# Example of the response that will be generated from setting
|
||||
# explicit to false:
|
||||
#
|
||||
# ie:
|
||||
# "enabled": true,
|
||||
# "locked": true,
|
||||
# "readonly": false,
|
||||
# "explicit": true,
|
||||
# "prior_default": false
|
||||
#
|
||||
# @api private
|
||||
setSystemDefault: ->
|
||||
@model.get('permissions')[@permission_name].locked = false
|
||||
@model.get('permissions')[@permission_name].explicit = false
|
||||
|
||||
# Method Summary
|
||||
# Same as systemDefault except locked is true.
|
||||
# @api private
|
||||
setSystemDefaultAndLocked: ->
|
||||
@model.get('permissions')[@permission_name].locked = true
|
||||
@model.get('permissions')[@permission_name].explicit = false
|
||||
|
||||
# Method Summary
|
||||
# Check to see if this role is enabled.
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# enabled : true
|
||||
# locked : false
|
||||
# explicit : true
|
||||
#
|
||||
# returns Boolean
|
||||
# @api private
|
||||
isEnabled: ->
|
||||
@model.get('permissions')[@permission_name].enabled && !@isLocked() && @isExplicit()
|
||||
|
||||
# Method Summary
|
||||
# Check to see if this role is enabled and locked.
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# enabled : true
|
||||
# locked : true
|
||||
# explicit : true
|
||||
#
|
||||
# returns Boolean
|
||||
# @api private
|
||||
isEnabledAndLocked: ->
|
||||
@model.get('permissions')[@permission_name].enabled && @isLocked() && @isExplicit()
|
||||
|
||||
# Method Summary
|
||||
# Check to see if this role is disabled.
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# enabled : false
|
||||
# locked : false
|
||||
# explicit : true
|
||||
#
|
||||
# returns Boolean
|
||||
# @api private
|
||||
isDisabled: ->
|
||||
!@model.get('permissions')[@permission_name].enabled && !@isLocked() && @isExplicit()
|
||||
|
||||
# Method Summary
|
||||
# Check to see if this role is disabled and locked.
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# enabled : false
|
||||
# locked : true
|
||||
# explicit : true
|
||||
#
|
||||
# returns Boolean
|
||||
# @api private
|
||||
isDisabledAndLocked: ->
|
||||
!@model.get('permissions')[@permission_name].enabled && @isLocked() && @isExplicit()
|
||||
|
||||
# Method Summary
|
||||
# All default means is explicit is set to false and lock is false.
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# enabled : 'don't care about this value :/'
|
||||
# locked : false
|
||||
# explicit : false
|
||||
#
|
||||
# @api private
|
||||
isDefault: ->
|
||||
!@isExplicit() && !@isLocked()
|
||||
|
||||
# Method Summary
|
||||
# Default and lock does is make sure explicit is set to false and lock is true
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# enabled : 'don't care about this value :/'
|
||||
# locked : true
|
||||
# explicit : false
|
||||
#
|
||||
# @api private
|
||||
isDefaultAndLocked: ->
|
||||
!@isExplicit() && @isLocked()
|
||||
|
||||
# Method Summary
|
||||
# Read only attribute is set means you cannot change this permission.
|
||||
#
|
||||
# This means
|
||||
#
|
||||
# readonly : true
|
||||
#
|
||||
# @api private
|
||||
isReadOnly: ->
|
||||
@model.get('permissions')[@permission_name].readonly
|
||||
|
||||
# Method Summary
|
||||
# Checks to see if the permission is explicit. Doesn't care about any other permissions.
|
||||
# ie:
|
||||
# explicit : true | false
|
||||
#
|
||||
# @api private
|
||||
isExplicit: ->
|
||||
@model.get('permissions')[@permission_name].explicit
|
||||
|
||||
# Method Summary
|
||||
# Checks to see if the permission is locked. Doesn't care about any other permissions
|
||||
#
|
||||
# ie:
|
||||
# locked : true | false
|
||||
# @api private
|
||||
isLocked: ->
|
||||
@model.get('permissions')[@permission_name].locked
|
||||
|
||||
# Method Summary
|
||||
# Set icon button for preview. In order to do this we just clone the radio buttons
|
||||
# images into the buttons preview section. Takes in a string. The string can have these options
|
||||
# 0 = "enabled"
|
||||
# 1 = "enabledLocked"
|
||||
# 2 = "disabled"
|
||||
# 3 = "disabledLocked"
|
||||
# @api private
|
||||
setButtonPreview: (selected_radio) ->
|
||||
icons = @$el.find("label[for=button-#{@cid}-#{selected_radio}] i").clone()
|
||||
@$el.find('a.dropdown-toggle').html icons
|
||||
|
||||
# Method Summary
|
||||
# Sets the button preview for an dropdown button to the enabled icons
|
||||
# @api private
|
||||
setEnabledIcon: ->
|
||||
@setButtonPreview 0
|
||||
|
||||
# Method Summary
|
||||
# Sets the button preview for an dropdown button to the enabled and locked icons
|
||||
# @api private
|
||||
setEnabledLockedIcon: ->
|
||||
@setButtonPreview 1
|
||||
|
||||
# Method Summary
|
||||
# Sets the button preview for an dropdown button to the disabled
|
||||
# @api private
|
||||
setDisabledIcon: ->
|
||||
@setButtonPreview 2
|
||||
|
||||
# Method Summary
|
||||
# Sets the button preview for an dropdown button to the disabled
|
||||
# @api private
|
||||
setDisabledLockedIcon: ->
|
||||
@setButtonPreview 3
|
||||
|
||||
# Method Summary
|
||||
# Check to see if there is a prior_set because if there is one set, we should always
|
||||
# use that setting to show what the default is. If that setting is not set, we can
|
||||
# assume its just the enabled value.
|
||||
# @api private
|
||||
setDefaultIcon: ->
|
||||
if _.isUndefined @model.get('permissions')[@permission_name].prior_default
|
||||
if @model.get('permissions')[@permission_name].enabled then @setEnabledIcon() else @setDisabledIcon()
|
||||
else
|
||||
if @model.get('permissions')[@permission_name].prior_default then @setEnabledIcon() else @setDisabledIcon()
|
||||
|
||||
# Method Summary
|
||||
# Same as setDefaultIcon except everything has a lock applied to it.
|
||||
# @api private
|
||||
setDefaultAndLockedIcon: ->
|
||||
if _.isUndefined @model.get('permissions')[@permission_name].prior_default
|
||||
if @model.get('permissions')[@permission_name].enabled then @setEnabledLockedIcon() else @setDisabledLockedIcon()
|
||||
else
|
||||
if @model.get('permissions')[@permission_name].prior_default then @setEnabledLockedIcon() else @setDisabledLockedIcon()
|
|
@ -0,0 +1,79 @@
|
|||
define [
|
||||
'i18n!editor'
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/roleHeader'
|
||||
], (I18n, $, _, Backbone, template) ->
|
||||
class RoleHeaderView extends Backbone.View
|
||||
template: template
|
||||
tagName: 'th'
|
||||
className: 'roleHeader'
|
||||
|
||||
# Static roles are role's that cannot be deleted.
|
||||
# The delete link will not show up next to their
|
||||
# name.
|
||||
staticRoles: [
|
||||
'AccountAdmin'
|
||||
'AccountMembership'
|
||||
'StudentEnrollment'
|
||||
'TeacherEnrollment'
|
||||
'TaEnrollment'
|
||||
'ObserverEnrollment'
|
||||
'DesignerEnrollment'
|
||||
]
|
||||
|
||||
events:
|
||||
"click a" : "removeRole"
|
||||
|
||||
# Method Summary
|
||||
# Are you abled to delete this role? You can delete
|
||||
# a role if it's not one of the static roles.
|
||||
# @api private
|
||||
deletable: ->
|
||||
!_.contains @staticRoles, @model.get('role')
|
||||
|
||||
# Method Summary
|
||||
# We add attributes to JSON that gets passed into the
|
||||
# handlebars template so we can manipulate the template.
|
||||
# @api backbone override
|
||||
toJSON: ->
|
||||
json = super
|
||||
json['deletable'] = @deletable()
|
||||
json['showBaseRoleType'] = @showBaseRoleType()
|
||||
json
|
||||
|
||||
# Method Summary
|
||||
# Destroys the model. This will send a DELETE request to the model.
|
||||
# If this role is in a collection (most likely is) it will automatically
|
||||
# be removed from the collection and the collections remove event will
|
||||
# be triggered.
|
||||
#
|
||||
# Make sure the user knows that if there are any enrollments on this role
|
||||
# it will be frozen.
|
||||
# @api private
|
||||
removeRole: ->
|
||||
if confirm I18n.t "role.remove_role_confirmation", "If there are any users with this role, they will keep the current permissions but you will not be able to create new users with this role. Click ok to continue deleting this role."
|
||||
@model.destroy
|
||||
error: (model, response) ->
|
||||
alert "#{model.role} could not be remove, contact your site admin if this continues."
|
||||
wait: true
|
||||
|
||||
# Method Summary
|
||||
# Under the actual role name we display the base role type. We don't do
|
||||
# this for every type of base_role_type however. These base_role_types
|
||||
# we hide because it's implied. This gets used in the template to determin
|
||||
# what should be shown.
|
||||
# @api private
|
||||
showBaseRoleType: ->
|
||||
!_.contains ["AccountAdmin", "NoPermissions", "AccountMembership"], @model.get('base_role_type')
|
||||
|
||||
# Method Summary
|
||||
# This is called after render to ensure column header is set for accessiblity.
|
||||
# @api custom backbone override
|
||||
filter: ->
|
||||
@$el.attr('role', 'columnheader')
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
define [
|
||||
'jquery'
|
||||
'underscore'
|
||||
'Backbone'
|
||||
'jst/roles/rolesOverrideIndex'
|
||||
], ($, _, Backbone, template) ->
|
||||
class RolesOverrideIndexView extends Backbone.View
|
||||
template: template
|
||||
els:
|
||||
"#role_tabs": "$roleTabs"
|
||||
|
||||
# Method Summary
|
||||
# Enable tabs for account/course roles.
|
||||
# @api custom backbone override
|
||||
filter: ->
|
||||
@$roleTabs.tabs()
|
|
@ -87,6 +87,7 @@
|
|||
class RoleOverridesController < ApplicationController
|
||||
before_filter :require_context
|
||||
before_filter :require_role, :only => [:activate_role, :add_role, :remove_role, :update, :show]
|
||||
before_filter :set_js_env_for_current_account
|
||||
|
||||
# @API List roles
|
||||
# List the roles available to an account.
|
||||
|
@ -111,17 +112,36 @@ class RoleOverridesController < ApplicationController
|
|||
|
||||
def index
|
||||
if authorized_action(@context, @current_user, :manage_role_overrides)
|
||||
@managing_account_roles = @context.is_a?(Account) && (params[:account_roles] || @context.site_admin?)
|
||||
account_role_data = []
|
||||
|
||||
if @managing_account_roles
|
||||
@role_types = RoleOverride.account_membership_types(@context)
|
||||
else
|
||||
@role_types = RoleOverride.enrollment_types
|
||||
role = Role.built_in_role("AccountAdmin")
|
||||
account_role_data << role_json(@context, role, @current_user, session)
|
||||
account_role_data[0][:id] = role.name
|
||||
@context.available_custom_account_roles.each do |role|
|
||||
json = role_json(@context, role, @current_user, session)
|
||||
json[:id] = role.name
|
||||
account_role_data << json
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
course_role_data = []
|
||||
custom_roles = @context.available_course_roles_by_name.values
|
||||
RoleOverride::ENROLLMENT_TYPES.map do |role_hash|
|
||||
role = Role.built_in_role(role_hash[:name])
|
||||
json = role_json(@context, role, @current_user, session)
|
||||
json[:id] = role.name
|
||||
course_role_data << json
|
||||
|
||||
custom_roles.select { |cr| cr.base_role_type == role_hash[:base_role_name] }.map do |cr|
|
||||
json = role_json(@context, cr, @current_user, session)
|
||||
json[:id] = cr.name
|
||||
course_role_data << json
|
||||
end
|
||||
end
|
||||
|
||||
js_env :ACCOUNT_ROLES => account_role_data
|
||||
js_env :COURSE_ROLES => course_role_data
|
||||
js_env :ACCOUNT_PERMISSIONS => account_permissions(@context)
|
||||
js_env :COURSE_PERMISSIONS => course_permissions(@context)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -380,6 +400,12 @@ class RoleOverridesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Summary:
|
||||
# Adds ENV.CURRENT_ACCOUNT with the account we are working with.
|
||||
def set_js_env_for_current_account
|
||||
js_env :CURRENT_ACCOUNT => @context
|
||||
end
|
||||
|
||||
# Internal: Get role from params or return error. Used as before filter.
|
||||
#
|
||||
# Returns found role or false (to halt execution).
|
||||
|
@ -422,15 +448,85 @@ class RoleOverridesController < ApplicationController
|
|||
|
||||
manageable_permissions.keys.each do |permission|
|
||||
if settings = permissions[permission]
|
||||
if settings.has_key?(:enabled) && value_to_boolean(settings[:explicit])
|
||||
override = value_to_boolean(settings[:enabled])
|
||||
end
|
||||
locked = value_to_boolean(settings[:locked]) if settings.has_key?(:locked)
|
||||
if !value_to_boolean(settings[:readonly])
|
||||
if settings.has_key?(:enabled) && value_to_boolean(settings[:explicit])
|
||||
override = value_to_boolean(settings[:enabled])
|
||||
end
|
||||
locked = value_to_boolean(settings[:locked]) if settings.has_key?(:locked)
|
||||
|
||||
RoleOverride.manage_role_override(context, role, permission.to_s,
|
||||
:override => override, :locked => locked)
|
||||
RoleOverride.manage_role_override(context, role, permission.to_s,
|
||||
:override => override, :locked => locked)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
protected :set_permissions_for
|
||||
|
||||
private
|
||||
|
||||
def course_permissions(context)
|
||||
site_admin = {:group_name => t('site_admin_permissions', "Site Admin Permissions"), :group_permissions => []}
|
||||
account = {:group_name => t('account_permissions', "Account Permissions"), :group_permissions => []}
|
||||
course = {:group_name => t('course_permissions', "Course & Account Permissions"), :group_permissions => []}
|
||||
|
||||
base_role_names = RoleOverride.enrollment_types.map do |enrollment_type|
|
||||
enrollment_type[:base_role_name]
|
||||
end
|
||||
|
||||
RoleOverride.manageable_permissions(context).each do |p|
|
||||
hash = {:label => p[1][:label].call, :permission_name => p[0]}
|
||||
|
||||
# Check to see if the base role name is in the list of other base role names in p[1]
|
||||
is_course_permission = !(base_role_names & p[1][:available_to]).empty?
|
||||
|
||||
if p[1][:account_only]
|
||||
if p[1][:account_only] == :site_admin
|
||||
site_admin[:group_permissions] << hash if is_course_permission
|
||||
else
|
||||
account[:group_permissions] << hash if is_course_permission
|
||||
end
|
||||
else
|
||||
course[:group_permissions] << hash if is_course_permission
|
||||
end
|
||||
end
|
||||
|
||||
res = []
|
||||
res << site_admin if site_admin[:group_permissions].any?
|
||||
res << account if account[:group_permissions].any?
|
||||
res << course if course[:group_permissions].any?
|
||||
|
||||
res.each{|pg| pg[:group_permissions] = pg[:group_permissions].sort_by{|p|p[:label]} }
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
# Returns a hash with the avalible permissions grouped by groups of permissions.
|
||||
# context - the current context
|
||||
def account_permissions(context)
|
||||
site_admin = {:group_name => t('site_admin_permissions', "Site Admin Permissions"), :group_permissions => []}
|
||||
account = {:group_name => t('account_permissions', "Account Permissions"), :group_permissions => []}
|
||||
course = {:group_name => t('course_permissions', "Course & Account Permissions"), :group_permissions => []}
|
||||
|
||||
RoleOverride.manageable_permissions(context).each do |p|
|
||||
hash = {:label => p[1][:label].call, :permission_name => p[0]}
|
||||
if p[1][:account_only]
|
||||
if p[1][:account_only] == :site_admin
|
||||
site_admin[:group_permissions] << hash
|
||||
else
|
||||
account[:group_permissions] << hash
|
||||
end
|
||||
else
|
||||
course[:group_permissions] << hash
|
||||
end
|
||||
end
|
||||
|
||||
res = []
|
||||
res << site_admin if site_admin[:group_permissions].any?
|
||||
res << account if account[:group_permissions].any?
|
||||
res << course if course[:group_permissions].any?
|
||||
|
||||
res.each{|pg| pg[:group_permissions] = pg[:group_permissions].sort_by{|p|p[:label]} }
|
||||
|
||||
res
|
||||
end
|
||||
end
|
||||
|
|
|
@ -506,6 +506,12 @@ class Account < ActiveRecord::Base
|
|||
self.account_users.find_by_user_id(user && user.id)
|
||||
end
|
||||
|
||||
def available_custom_account_roles
|
||||
account_roles = roles.for_accounts.active
|
||||
account_roles |= self.parent_account.available_custom_account_roles if self.parent_account
|
||||
account_roles
|
||||
end
|
||||
|
||||
def available_account_roles
|
||||
account_roles = roles.for_accounts.active.map(&:name)
|
||||
account_roles |= ['AccountAdmin']
|
||||
|
|
|
@ -60,6 +60,10 @@ class Role < ActiveRecord::Base
|
|||
!account_role?
|
||||
end
|
||||
|
||||
def label
|
||||
self.name
|
||||
end
|
||||
|
||||
alias_method :destroy!, :destroy
|
||||
def destroy
|
||||
self.workflow_state = 'deleted'
|
||||
|
@ -132,11 +136,19 @@ class Role < ActiveRecord::Base
|
|||
class BuiltInRole
|
||||
attr_accessor :name
|
||||
|
||||
def initialize(name)
|
||||
@name = name
|
||||
if @name == 'AccountAdmin'
|
||||
@label = I18n.t('roles.account_admin', "Account Admin")
|
||||
else
|
||||
er = RoleOverride.enrollment_types.find{|er|er[:name] == @name}
|
||||
@label = er[:label].call
|
||||
end
|
||||
end
|
||||
|
||||
def self.create(name)
|
||||
return nil unless Role.built_in_role_names.include?(name)
|
||||
r = BuiltInRole.new
|
||||
r.name = name
|
||||
r
|
||||
BuiltInRole.new(name)
|
||||
end
|
||||
|
||||
def base_role_type
|
||||
|
@ -146,6 +158,10 @@ class Role < ActiveRecord::Base
|
|||
def workflow_state
|
||||
'active'
|
||||
end
|
||||
|
||||
def label
|
||||
@label
|
||||
end
|
||||
end
|
||||
|
||||
# returns a BuiltInRole for the role with the given name, or nil
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
div.dropdown-menu.new-role {
|
||||
top: 0px !important;
|
||||
padding: 20px;
|
||||
|
||||
select[disabled], select:disabled {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
.table td.permissionButtonView {
|
||||
position: relative;
|
||||
|
||||
.default_permission {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.icon-x {
|
||||
color: #9B0000;
|
||||
}
|
||||
|
||||
.icon-check {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.btn-group{
|
||||
margin: 0 auto;
|
||||
width: 40px;
|
||||
position: relative;
|
||||
|
||||
.btn.dropdown-toggle{
|
||||
position: relative;
|
||||
min-width: 35px;
|
||||
|
||||
&:disabled, &[disabled] {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
& .icon-lock {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
text-align: left;
|
||||
/*left: 30%;*/
|
||||
|
||||
input[type=radio] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label{
|
||||
display: block;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
span.text{
|
||||
float: right;
|
||||
text-align: left !important;
|
||||
width: 110px;
|
||||
|
||||
&:last{
|
||||
float: none;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
label:hover, label:focus, input:checked+label {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
background-color: #08C;
|
||||
background-color: #0081C2;
|
||||
background-image: -moz-linear-gradient(top, #08C, #0077B3);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08C), to(#0077B3));
|
||||
background-image: -webkit-linear-gradient(top, #08C, #0077B3);
|
||||
background-image: -o-linear-gradient(top, #08C, #0077B3);
|
||||
background-image: linear-gradient(to bottom, #08C, #0077B3);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF0088CC', endColorstr='#FF0077B3', GradientType=0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,870 @@
|
|||
/* line 9, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
table {
|
||||
max-width: 100%;
|
||||
background-color: transparent;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0; }
|
||||
|
||||
/* line 19, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table {
|
||||
width: 100%;
|
||||
margin-bottom: 20px; }
|
||||
/* line 24, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
border-top: 1px solid #dddddd; }
|
||||
/* line 31, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table th {
|
||||
font-weight: bold; }
|
||||
/* line 35, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table thead th {
|
||||
vertical-align: bottom; }
|
||||
/* line 44, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table caption + thead tr:first-child th,
|
||||
.table caption + thead tr:first-child td,
|
||||
.table colgroup + thead tr:first-child th,
|
||||
.table colgroup + thead tr:first-child td,
|
||||
.table thead:first-child tr:first-child th,
|
||||
.table thead:first-child tr:first-child td {
|
||||
border-top: 0; }
|
||||
/* line 48, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table tbody + tbody {
|
||||
border-top: 2px solid #dddddd; }
|
||||
|
||||
/* line 60, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-condensed th,
|
||||
.table-condensed td {
|
||||
padding: 4px 5px; }
|
||||
|
||||
/* line 69, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered {
|
||||
border: 1px solid #dddddd;
|
||||
border-collapse: separate;
|
||||
*border-collapse: collapse;
|
||||
border-left: 0;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px; }
|
||||
/* line 76, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered th,
|
||||
.table-bordered td {
|
||||
border-left: 1px solid #dddddd; }
|
||||
/* line 88, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered caption + thead tr:first-child th,
|
||||
.table-bordered caption + tbody tr:first-child th,
|
||||
.table-bordered caption + tbody tr:first-child td,
|
||||
.table-bordered colgroup + thead tr:first-child th,
|
||||
.table-bordered colgroup + tbody tr:first-child th,
|
||||
.table-bordered colgroup + tbody tr:first-child td,
|
||||
.table-bordered thead:first-child tr:first-child th,
|
||||
.table-bordered tbody:first-child tr:first-child th,
|
||||
.table-bordered tbody:first-child tr:first-child td {
|
||||
border-top: 0; }
|
||||
/* line 93, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered thead:first-child tr:first-child th:first-child,
|
||||
.table-bordered tbody:first-child tr:first-child td:first-child {
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
-moz-border-radius-topleft: 4px; }
|
||||
/* line 99, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered thead:first-child tr:first-child th:last-child,
|
||||
.table-bordered tbody:first-child tr:first-child td:last-child {
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-moz-border-radius-topright: 4px; }
|
||||
/* line 107, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered thead:last-child tr:last-child th:first-child,
|
||||
.table-bordered tbody:last-child tr:last-child td:first-child,
|
||||
.table-bordered tfoot:last-child tr:last-child td:first-child {
|
||||
-webkit-border-radius: 0 0 0 4px;
|
||||
-moz-border-radius: 0 0 0 4px;
|
||||
border-radius: 0 0 0 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
-moz-border-radius-bottomleft: 4px; }
|
||||
/* line 115, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered thead:last-child tr:last-child th:last-child,
|
||||
.table-bordered tbody:last-child tr:last-child td:last-child,
|
||||
.table-bordered tfoot:last-child tr:last-child td:last-child {
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
-moz-border-radius-bottomright: 4px; }
|
||||
/* line 125, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered caption + thead tr:first-child th:first-child,
|
||||
.table-bordered caption + tbody tr:first-child td:first-child,
|
||||
.table-bordered colgroup + thead tr:first-child th:first-child,
|
||||
.table-bordered colgroup + tbody tr:first-child td:first-child {
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
-moz-border-radius-topleft: 4px; }
|
||||
/* line 133, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-bordered caption + thead tr:first-child th:last-child,
|
||||
.table-bordered caption + tbody tr:first-child td:last-child,
|
||||
.table-bordered colgroup + thead tr:first-child th:last-child,
|
||||
.table-bordered colgroup + tbody tr:first-child td:last-child {
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-moz-border-radius-topright: 4px; }
|
||||
|
||||
/* line 151, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-striped tbody tr:nth-child(odd) td,
|
||||
.table-striped tbody tr:nth-child(odd) th {
|
||||
background-color: #f9f9f9; }
|
||||
|
||||
/* line 164, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-hover tbody tr:hover td,
|
||||
.table-hover tbody tr:hover th {
|
||||
background-color: whitesmoke; }
|
||||
|
||||
/* line 178, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
table td[class*="span"],
|
||||
table th[class*="span"],
|
||||
.row-fluid table td[class*="span"],
|
||||
.row-fluid table th[class*="span"] {
|
||||
display: table-cell;
|
||||
float: none;
|
||||
margin-left: 0; }
|
||||
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span1,
|
||||
.table th.span1 {
|
||||
float: none;
|
||||
width: 44px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span2,
|
||||
.table th.span2 {
|
||||
float: none;
|
||||
width: 124px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span3,
|
||||
.table th.span3 {
|
||||
float: none;
|
||||
width: 204px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span4,
|
||||
.table th.span4 {
|
||||
float: none;
|
||||
width: 284px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span5,
|
||||
.table th.span5 {
|
||||
float: none;
|
||||
width: 364px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span6,
|
||||
.table th.span6 {
|
||||
float: none;
|
||||
width: 444px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span7,
|
||||
.table th.span7 {
|
||||
float: none;
|
||||
width: 524px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span8,
|
||||
.table th.span8 {
|
||||
float: none;
|
||||
width: 604px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span9,
|
||||
.table th.span9 {
|
||||
float: none;
|
||||
width: 684px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span10,
|
||||
.table th.span10 {
|
||||
float: none;
|
||||
width: 764px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span11,
|
||||
.table th.span11 {
|
||||
float: none;
|
||||
width: 844px;
|
||||
margin-left: 0; }
|
||||
/* line 188, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table td.span12,
|
||||
.table th.span12 {
|
||||
float: none;
|
||||
width: 924px;
|
||||
margin-left: 0; }
|
||||
|
||||
/* line 199, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table tbody tr.success td {
|
||||
background-color: #dff0d8; }
|
||||
/* line 202, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table tbody tr.error td {
|
||||
background-color: #f2dede; }
|
||||
/* line 205, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table tbody tr.warning td {
|
||||
background-color: #fcf8e3; }
|
||||
/* line 208, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table tbody tr.info td {
|
||||
background-color: #d9edf7; }
|
||||
|
||||
/* line 215, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-hover tbody tr.success:hover td {
|
||||
background-color: #d0e9c6; }
|
||||
/* line 218, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-hover tbody tr.error:hover td {
|
||||
background-color: #ebcccc; }
|
||||
/* line 221, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-hover tbody tr.warning:hover td {
|
||||
background-color: #faf2cc; }
|
||||
/* line 224, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_tables.scss */
|
||||
.table-hover tbody tr.info:hover td {
|
||||
background-color: #c4e3f3; }
|
||||
|
||||
/* line 8, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropup,
|
||||
.dropdown {
|
||||
position: relative; }
|
||||
|
||||
/* line 11, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-toggle {
|
||||
*margin-bottom: -3px; }
|
||||
|
||||
/* line 16, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-toggle:active,
|
||||
.open .dropdown-toggle {
|
||||
outline: 0; }
|
||||
|
||||
/* line 22, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.caret {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
vertical-align: top;
|
||||
border-top: 4px solid black;
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
content: ""; }
|
||||
|
||||
/* line 34, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown .caret {
|
||||
margin-top: 8px;
|
||||
margin-left: 2px; }
|
||||
|
||||
/* line 41, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
float: left;
|
||||
min-width: 160px;
|
||||
padding: 5px 0;
|
||||
margin: 2px 0 0;
|
||||
list-style: none;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
*border-right-width: 2px;
|
||||
*border-bottom-width: 2px;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
-webkit-background-clip: padding-box;
|
||||
-moz-background-clip: padding;
|
||||
background-clip: padding-box; }
|
||||
/* line 64, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu.pull-right {
|
||||
right: 0;
|
||||
left: auto; }
|
||||
/* line 70, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu .divider {
|
||||
*width: 100%;
|
||||
height: 1px;
|
||||
margin: 9px 1px;
|
||||
*margin: -5px 0 5px;
|
||||
overflow: hidden;
|
||||
background-color: #e5e5e5;
|
||||
border-bottom: 1px solid white; }
|
||||
/* line 75, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu li > a {
|
||||
display: block;
|
||||
padding: 3px 20px;
|
||||
clear: both;
|
||||
font-weight: normal;
|
||||
line-height: 20px;
|
||||
color: #333333;
|
||||
white-space: nowrap; }
|
||||
|
||||
/* line 90, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu li > a:hover,
|
||||
.dropdown-menu li > a:focus,
|
||||
.dropdown-submenu:hover > a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
background-color: #0081c2;
|
||||
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
|
||||
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
|
||||
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
|
||||
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF0088CC', endColorstr='#FF0077B3', GradientType=0); }
|
||||
|
||||
/* line 99, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu .active > a,
|
||||
.dropdown-menu .active > a:hover {
|
||||
color: #333333;
|
||||
text-decoration: none;
|
||||
outline: 0;
|
||||
background-color: #0081c2;
|
||||
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
|
||||
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
|
||||
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
|
||||
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF0088CC', endColorstr='#FF0077B3', GradientType=0); }
|
||||
|
||||
/* line 110, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu .disabled > a,
|
||||
.dropdown-menu .disabled > a:hover {
|
||||
color: #999999; }
|
||||
|
||||
/* line 114, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-menu .disabled > a:hover {
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
cursor: default; }
|
||||
|
||||
/* line 123, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.open {
|
||||
*z-index: 1000; }
|
||||
/* line 128, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.open > .dropdown-menu {
|
||||
display: block; }
|
||||
|
||||
/* line 135, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.pull-right > .dropdown-menu {
|
||||
right: 0;
|
||||
left: auto; }
|
||||
|
||||
/* line 147, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropup .caret,
|
||||
.navbar-fixed-bottom .dropdown .caret {
|
||||
border-top: 0;
|
||||
border-bottom: 4px solid black;
|
||||
content: ""; }
|
||||
/* line 153, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropup .dropdown-menu,
|
||||
.navbar-fixed-bottom .dropdown .dropdown-menu {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
margin-bottom: 1px; }
|
||||
|
||||
/* line 162, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu {
|
||||
position: relative; }
|
||||
|
||||
/* line 166, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu > .dropdown-menu {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px; }
|
||||
|
||||
/* line 175, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu:hover > .dropdown-menu {
|
||||
display: block; }
|
||||
|
||||
/* line 180, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropup .dropdown-submenu > .dropdown-menu {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: -2px;
|
||||
-webkit-border-radius: 5px 5px 5px 0;
|
||||
-moz-border-radius: 5px 5px 5px 0;
|
||||
border-radius: 5px 5px 5px 0; }
|
||||
|
||||
/* line 191, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu > a:after {
|
||||
display: block;
|
||||
content: " ";
|
||||
float: right;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 0 5px 5px;
|
||||
border-left-color: #cccccc;
|
||||
margin-top: 5px;
|
||||
margin-right: -10px; }
|
||||
|
||||
/* line 204, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu:hover > a:after {
|
||||
border-left-color: white; }
|
||||
|
||||
/* line 209, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu.pull-left {
|
||||
float: none; }
|
||||
/* line 215, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown-submenu.pull-left > .dropdown-menu {
|
||||
left: -100%;
|
||||
margin-left: 10px;
|
||||
-webkit-border-radius: 6px 0 6px 6px;
|
||||
-moz-border-radius: 6px 0 6px 6px;
|
||||
border-radius: 6px 0 6px 6px; }
|
||||
|
||||
/* line 227, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.dropdown .dropdown-menu .nav-header {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px; }
|
||||
|
||||
/* line 234, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_dropdowns.scss */
|
||||
.typeahead {
|
||||
margin-top: 2px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px; }
|
||||
|
||||
/* line 9, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav {
|
||||
margin-left: 0;
|
||||
margin-bottom: 20px;
|
||||
list-style: none; }
|
||||
|
||||
/* line 16, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav > li > a {
|
||||
display: block; }
|
||||
|
||||
/* line 19, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav > li > a:hover {
|
||||
text-decoration: none;
|
||||
background-color: #eeeeee; }
|
||||
|
||||
/* line 25, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav > .pull-right {
|
||||
float: right; }
|
||||
|
||||
/* line 30, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-header {
|
||||
display: block;
|
||||
padding: 3px 15px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
color: #999999;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
text-transform: uppercase; }
|
||||
|
||||
/* line 41, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav li + .nav-header {
|
||||
margin-top: 9px; }
|
||||
|
||||
/* line 50, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-list {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
margin-bottom: 0; }
|
||||
|
||||
/* line 56, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-list > li > a,
|
||||
.nav-list .nav-header {
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); }
|
||||
|
||||
/* line 61, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-list > li > a {
|
||||
padding: 3px 15px; }
|
||||
|
||||
/* line 65, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-list > .active > a,
|
||||
.nav-list > .active > a:hover {
|
||||
color: white;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
|
||||
background-color: #0088cc; }
|
||||
|
||||
/* line 71, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-list [class^="icon-"],
|
||||
.nav-list [class*=" icon-"] {
|
||||
margin-right: 2px; }
|
||||
|
||||
/* line 75, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-list .divider {
|
||||
*width: 100%;
|
||||
height: 1px;
|
||||
margin: 9px 1px;
|
||||
*margin: -5px 0 5px;
|
||||
overflow: hidden;
|
||||
background-color: #e5e5e5;
|
||||
border-bottom: 1px solid white; }
|
||||
|
||||
/* line 86, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs,
|
||||
.nav-pills {
|
||||
*zoom: 1; }
|
||||
/* line 15, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_mixins.scss */
|
||||
.nav-tabs:before, .nav-tabs:after,
|
||||
.nav-pills:before,
|
||||
.nav-pills:after {
|
||||
display: table;
|
||||
content: "";
|
||||
line-height: 0; }
|
||||
/* line 22, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_mixins.scss */
|
||||
.nav-tabs:after,
|
||||
.nav-pills:after {
|
||||
clear: both; }
|
||||
|
||||
/* line 90, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs > li,
|
||||
.nav-pills > li {
|
||||
float: left; }
|
||||
|
||||
/* line 94, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs > li > a,
|
||||
.nav-pills > li > a {
|
||||
padding-right: 12px;
|
||||
padding-left: 12px;
|
||||
margin-right: 2px;
|
||||
line-height: 14px; }
|
||||
|
||||
/* line 105, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs {
|
||||
border-bottom: 1px solid #ddd; }
|
||||
|
||||
/* line 109, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs > li {
|
||||
margin-bottom: -1px; }
|
||||
|
||||
/* line 113, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs > li > a {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
line-height: 20px;
|
||||
border: 1px solid transparent;
|
||||
-webkit-border-radius: 4px 4px 0 0;
|
||||
-moz-border-radius: 4px 4px 0 0;
|
||||
border-radius: 4px 4px 0 0; }
|
||||
/* line 119, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs > li > a:hover {
|
||||
border-color: #eeeeee #eeeeee #dddddd; }
|
||||
|
||||
/* line 125, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs > .active > a,
|
||||
.nav-tabs > .active > a:hover {
|
||||
color: #555555;
|
||||
background-color: white;
|
||||
border: 1px solid #ddd;
|
||||
border-bottom-color: transparent;
|
||||
cursor: default; }
|
||||
|
||||
/* line 138, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-pills > li > a {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px; }
|
||||
|
||||
/* line 148, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-pills > .active > a,
|
||||
.nav-pills > .active > a:hover {
|
||||
color: white;
|
||||
background-color: #0088cc; }
|
||||
|
||||
/* line 159, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-stacked > li {
|
||||
float: none; }
|
||||
|
||||
/* line 162, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-stacked > li > a {
|
||||
margin-right: 0; }
|
||||
|
||||
/* line 167, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs.nav-stacked {
|
||||
border-bottom: 0; }
|
||||
|
||||
/* line 170, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs.nav-stacked > li > a {
|
||||
border: 1px solid #ddd;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0; }
|
||||
|
||||
/* line 174, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs.nav-stacked > li:first-child > a {
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
-moz-border-radius-topright: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-moz-border-radius-topleft: 4px;
|
||||
border-top-left-radius: 4px; }
|
||||
|
||||
/* line 177, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs.nav-stacked > li:last-child > a {
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
-moz-border-radius-bottomright: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
-moz-border-radius-bottomleft: 4px;
|
||||
border-bottom-left-radius: 4px; }
|
||||
|
||||
/* line 180, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs.nav-stacked > li > a:hover {
|
||||
border-color: #ddd;
|
||||
z-index: 2; }
|
||||
|
||||
/* line 186, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-pills.nav-stacked > li > a {
|
||||
margin-bottom: 3px; }
|
||||
|
||||
/* line 189, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-pills.nav-stacked > li:last-child > a {
|
||||
margin-bottom: 1px; }
|
||||
|
||||
/* line 198, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs .dropdown-menu {
|
||||
-webkit-border-radius: 0 0 6px 6px;
|
||||
-moz-border-radius: 0 0 6px 6px;
|
||||
border-radius: 0 0 6px 6px; }
|
||||
|
||||
/* line 201, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-pills .dropdown-menu {
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px; }
|
||||
|
||||
/* line 208, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav .dropdown-toggle .caret {
|
||||
border-top-color: #0088cc;
|
||||
border-bottom-color: #0088cc;
|
||||
margin-top: 6px; }
|
||||
|
||||
/* line 213, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav .dropdown-toggle:hover .caret {
|
||||
border-top-color: #005580;
|
||||
border-bottom-color: #005580; }
|
||||
|
||||
/* move down carets for tabs */
|
||||
/* line 218, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs .dropdown-toggle .caret {
|
||||
margin-top: 8px; }
|
||||
|
||||
/* line 224, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav .active .dropdown-toggle .caret {
|
||||
border-top-color: #fff;
|
||||
border-bottom-color: #fff; }
|
||||
|
||||
/* line 228, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs .active .dropdown-toggle .caret {
|
||||
border-top-color: #555555;
|
||||
border-bottom-color: #555555; }
|
||||
|
||||
/* line 235, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav > .dropdown.active > a:hover {
|
||||
cursor: pointer; }
|
||||
|
||||
/* line 243, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav-tabs .open .dropdown-toggle,
|
||||
.nav-pills .open .dropdown-toggle,
|
||||
.nav > li.dropdown.open.active > a:hover {
|
||||
color: white;
|
||||
background-color: #999999;
|
||||
border-color: #999999; }
|
||||
|
||||
/* line 250, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav li.dropdown.open .caret,
|
||||
.nav li.dropdown.open.active .caret,
|
||||
.nav li.dropdown.open a:hover .caret {
|
||||
border-top-color: white;
|
||||
border-bottom-color: white;
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100); }
|
||||
|
||||
/* line 257, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-stacked .open > a:hover {
|
||||
border-color: #999999; }
|
||||
|
||||
/* line 271, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabbable {
|
||||
*zoom: 1; }
|
||||
/* line 15, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_mixins.scss */
|
||||
.tabbable:before, .tabbable:after {
|
||||
display: table;
|
||||
content: "";
|
||||
line-height: 0; }
|
||||
/* line 22, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_mixins.scss */
|
||||
.tabbable:after {
|
||||
clear: both; }
|
||||
|
||||
/* line 274, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tab-content {
|
||||
overflow: auto; }
|
||||
|
||||
/* line 281, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-below > .nav-tabs,
|
||||
.tabs-right > .nav-tabs,
|
||||
.tabs-left > .nav-tabs {
|
||||
border-bottom: 0; }
|
||||
|
||||
/* line 287, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tab-content > .tab-pane,
|
||||
.pill-content > .pill-pane {
|
||||
display: none; }
|
||||
|
||||
/* line 291, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tab-content > .active,
|
||||
.pill-content > .active {
|
||||
display: block; }
|
||||
|
||||
/* line 299, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-below > .nav-tabs {
|
||||
border-top: 1px solid #ddd; }
|
||||
|
||||
/* line 302, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-below > .nav-tabs > li {
|
||||
margin-top: -1px;
|
||||
margin-bottom: 0; }
|
||||
|
||||
/* line 306, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-below > .nav-tabs > li > a {
|
||||
-webkit-border-radius: 0 0 4px 4px;
|
||||
-moz-border-radius: 0 0 4px 4px;
|
||||
border-radius: 0 0 4px 4px; }
|
||||
/* line 308, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-below > .nav-tabs > li > a:hover {
|
||||
border-bottom-color: transparent;
|
||||
border-top-color: #ddd; }
|
||||
|
||||
/* line 314, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-below > .nav-tabs > .active > a,
|
||||
.tabs-below > .nav-tabs > .active > a:hover {
|
||||
border-color: transparent #ddd #ddd #ddd; }
|
||||
|
||||
/* line 323, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-left > .nav-tabs > li,
|
||||
.tabs-right > .nav-tabs > li {
|
||||
float: none; }
|
||||
|
||||
/* line 327, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-left > .nav-tabs > li > a,
|
||||
.tabs-right > .nav-tabs > li > a {
|
||||
min-width: 74px;
|
||||
margin-right: 0;
|
||||
margin-bottom: 3px; }
|
||||
|
||||
/* line 334, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-left > .nav-tabs {
|
||||
float: left;
|
||||
margin-right: 19px;
|
||||
border-right: 1px solid #ddd; }
|
||||
|
||||
/* line 339, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-left > .nav-tabs > li > a {
|
||||
margin-right: -1px;
|
||||
-webkit-border-radius: 4px 0 0 4px;
|
||||
-moz-border-radius: 4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px; }
|
||||
|
||||
/* line 343, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-left > .nav-tabs > li > a:hover {
|
||||
border-color: #eeeeee #dddddd #eeeeee #eeeeee; }
|
||||
|
||||
/* line 347, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-left > .nav-tabs .active > a,
|
||||
.tabs-left > .nav-tabs .active > a:hover {
|
||||
border-color: #ddd transparent #ddd #ddd;
|
||||
*border-right-color: white; }
|
||||
|
||||
/* line 353, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-right > .nav-tabs {
|
||||
float: right;
|
||||
margin-left: 19px;
|
||||
border-left: 1px solid #ddd; }
|
||||
|
||||
/* line 358, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-right > .nav-tabs > li > a {
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 4px 4px 0;
|
||||
-moz-border-radius: 0 4px 4px 0;
|
||||
border-radius: 0 4px 4px 0; }
|
||||
|
||||
/* line 362, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-right > .nav-tabs > li > a:hover {
|
||||
border-color: #eeeeee #eeeeee #eeeeee #dddddd; }
|
||||
|
||||
/* line 366, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.tabs-right > .nav-tabs .active > a,
|
||||
.tabs-right > .nav-tabs .active > a:hover {
|
||||
border-color: #ddd #ddd #ddd transparent;
|
||||
*border-left-color: white; }
|
||||
|
||||
/* line 377, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav > .disabled > a {
|
||||
color: #999999; }
|
||||
|
||||
/* line 381, ../../../../../../../.rbenv/versions/1.9.3-p286/lib/ruby/gems/1.9.1/gems/bootstrap-sass-2.2.1.1/vendor/assets/stylesheets/bootstrap/_navs.scss */
|
||||
.nav > .disabled > a:hover {
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
cursor: default; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.role-tab {
|
||||
padding-bottom: 200px !important;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.manage-permissions{
|
||||
thead th{
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
th{
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
&.toolbar{
|
||||
th, td {
|
||||
background-color:transparent !important;
|
||||
&:hover{
|
||||
background-color:transparent !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
<div class="new-role"></div>
|
||||
<table id="account_roles" class='table table-striped table-hover table-condensed'></table>
|
|
@ -0,0 +1,2 @@
|
|||
<div class="new-role"></div>
|
||||
<table id="course_roles" class='table table-striped table-hover table-condensed'></table>
|
|
@ -0,0 +1,5 @@
|
|||
<thead>
|
||||
<tr></tr>
|
||||
</thead>
|
||||
|
||||
<tbody></tbody>
|
|
@ -0,0 +1,14 @@
|
|||
<div class="btn-group">
|
||||
<a class="btn btn-success dropdown-toggle" aria-role="link" href="#" data-toggle="dropdown" aria-haspopup="true">Add Role</a>
|
||||
<div class="dropdown-menu bootstrap-form new-role" aria-hidden="true">
|
||||
<form>
|
||||
<input type='text' aria-label="Role Name" tabindex=1 placeholder="Role name"></input>
|
||||
<select aria-label="Role Basetype" tabindex=2 {{#if adminRoles }}disabled{{/if}}>
|
||||
{{#each base_role_types}}
|
||||
<option role="menuitem" value="{{value}}">{{ label }}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
<button type="submit" class="btn btn-success" aria-label="Add Role" tabindex=3>Add</button>
|
||||
<form>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,25 @@
|
|||
<div class="btn-group">
|
||||
<a class="btn btn-small dropdown-toggle {{#if default }}default_permission{{/if}}" href="#" data-toggle="dropdown" {{#if readOnly }}disabled="disabled" data-tooltip title="You do not have permission to change this" {{/if}}><i class="icon-check"></i><i class="icon-lock"></i></a>
|
||||
|
||||
<div class="dropdown-menu" role="radiogroup">
|
||||
<input type="radio" name="permission-for-{{cid}}" value="0" role="radio" id="button-{{cid}}-0" {{#if enableChecked }}checked="checked"{{/if}} >
|
||||
<label tabindex="0" for="button-{{cid}}-0"><i class="icon-check"></i></i><span class="text">{{#t "rolebutton.enable"}}Enable{{/t}}</span></label>
|
||||
|
||||
<input type="radio" name="permission-for-{{cid}}" value="0" role="radio" id="button-{{cid}}-1" {{#if enableAndLockChecked }}checked="checked"{{/if}}>
|
||||
<label tabindex=1 for="button-{{cid}}-1"><i class="icon-check"></i><i class="icon-lock"></i><span class="text">{{#t "rolebutton.enable_and_lock"}}Enable and Lock{{/t}}</span></label>
|
||||
|
||||
<input type="radio" name="permission-for-{{cid}}" value="0" role="radio" id="button-{{cid}}-2" {{#if disableChecked }}checked="checked"{{/if}}>
|
||||
<label tabindex=2 for="button-{{cid}}-2"><i class="icon-x"></i><span class="text">{{#t "rolebutton.disable"}}Disable{{/t}}</span></label>
|
||||
|
||||
<input type="radio" name="permission-for-{{cid}}" value="0" role="radio" id="button-{{cid}}-3" {{#if disableAndLockChecked }}checked="checked"{{/if}}>
|
||||
<label tabindex=3 for="button-{{cid}}-3"><i class="icon-x"></i><i class="icon-lock"></i><span class="text">{{#t "rolebutton.disable_and_lock"}}Disable and Lock{{/t}}</span></label>
|
||||
<li class="divider"></li>
|
||||
|
||||
<input type="radio" name="permission-for-{{cid}}" value="0" role="radio" id="button-{{cid}}-4" {{#if systemDefaultChecked }}checked="checked"{{/if}}>
|
||||
<label tabindex=4 for="button-{{cid}}-4" class="clearfix"><span class="text">{{#t "rolebutton.use_default"}}Use Default{{/t}}</span></label>
|
||||
|
||||
<input type="radio" name="permission-for-{{cid}}" value="0" role="radio" id="button-{{cid}}-5" {{#if systemDefaultLockedChecked }}checked="checked"{{/if}}>
|
||||
<label tabindex=5 for="button-{{cid}}-5" class="clearfix"><i class="icon-lock"></i><span class="text">{{#t "rolebutton.use_default"}}Use Default{{/t}}</span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<em data-tooltip title="Based on {{base_role_type}}">{{label}}</em>
|
||||
{{#if deletable}}<a href="#" aria-label="Delete role {{role}}"><i class="icon-end standalone-icon" ></i></a>{{/if}}
|
|
@ -0,0 +1,9 @@
|
|||
<div id="role_tabs" class="ui-tabs-minimal manage-permissions">
|
||||
<ul>
|
||||
<li><a href="#course-roles-tab" id="course_role_link">Course Roles</a></li>
|
||||
<li><a href="#account-roles-tab" id="account_role_link">Account Roles</a></li>
|
||||
</ul>
|
||||
|
||||
<div id="course-roles-tab" class="course-roles role-tab"></div>
|
||||
<div id="account-roles-tab" class="account-roles role-tab"></div>
|
||||
</div>
|
|
@ -1,224 +1,7 @@
|
|||
<% @active_tab = "permissions" %>
|
||||
<% add_crumb t 'crumbs.permissions', "Permissions" %>
|
||||
<% content_for :page_title do %><%= t :page_title, "Manage Permissions for %{account}", :account => @context.name %><% end %>
|
||||
<% content_for :page_header do %>
|
||||
<h1><%= t 'titles.manage_permissions', "Manage Permissions" %></h1>
|
||||
<% end %>
|
||||
<%
|
||||
@body_classes << "full-width"
|
||||
add_crumb t 'crumbs.permissions', "Permissions"
|
||||
content_for :page_title, t(:page_title, "Manage Permissions for %{account}", :account => @context.name)
|
||||
js_bundle :roles
|
||||
%>
|
||||
|
||||
<% content_for :page_subhead do %>
|
||||
<h2><%= t 'titles.subhead', "Set what users are allowed to do based on their role in the course." %></h2>
|
||||
<% end %>
|
||||
<style type="text/css" media="screen">
|
||||
|
||||
|
||||
#permissions-table thead th{
|
||||
padding: 4px 10px;
|
||||
font-size: 1.0em;
|
||||
min-width: 75px;
|
||||
text-align: center;
|
||||
}
|
||||
#permissions-table tbody th {
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
}
|
||||
#permissions-table tbody td {
|
||||
text-align: center;
|
||||
}
|
||||
.lock{
|
||||
height: 16px;
|
||||
opacity: 0;
|
||||
-moz-opacity: 0;
|
||||
filter:alpha(opacity=0);
|
||||
}
|
||||
td:hover .lock{
|
||||
opacity: 0.4;
|
||||
-moz-opacity: 0.4;
|
||||
filter:alpha(opacity=40);
|
||||
cursor: pointer;
|
||||
}
|
||||
img.lock.locked{
|
||||
opacity: 1;
|
||||
-moz-opacity: 1;
|
||||
filter:alpha(opacity=1);
|
||||
}
|
||||
img.lock.disabled{
|
||||
opacity: 0;
|
||||
-moz-opacity: 0;
|
||||
filter:alpha(opacity=0);
|
||||
cursor: auto;
|
||||
}
|
||||
#permissions-table.zebra-stripes tbody tr:hover {
|
||||
background: #DCEFFB
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2><%= @context.class.to_s %> <%= t('titles.permissions', 'Permissions') %></h2>
|
||||
<div style="margin:1em;">
|
||||
<div class="ui-widget ui-widget-content ui-corner-all" style="margin-bottom:1em; padding: 1em">
|
||||
<h3><%= t 'titles.explanation', "Explanation:" %></h3>
|
||||
<%= t :explanation_defaults, "The partially transparent checkboxes (%{default_checked} and %{default_unchecked}) indicate the system default.",
|
||||
:default_checked => '<span class="six-checkbox six-checkbox-default-checked"></span>'.html_safe, :default_unchecked => '<span class="six-checkbox six-checkbox-default-unchecked"></span>'.html_safe %><br />
|
||||
<%= mt :explanation_normal, "You can click to override the default and explicitly **allow** (%{normal_checked}) or **deny** (%{normal_unchecked}) this action.",
|
||||
:normal_checked => '<span class="six-checkbox six-checkbox-checked"></span>'.html_safe, :normal_unchecked => '<span class="six-checkbox six-checkbox-unchecked"></span>'.html_safe %><br />
|
||||
<%= t :explanation_disabled, "A grayed out box (%{disabled_checked} or %{disabled_unchecked}) means you are not allowed to change it.",
|
||||
:disabled_checked => '<span class="six-checkbox six-checkbox-disabled-checked"></span>'.html_safe, :disabled_unchecked => '<span class="six-checkbox six-checkbox-disabled-unchecked"></span>'.html_safe %><br />
|
||||
<%= t :explanation_locked, "If you would like to prevent anyone from overriding this in any sub-accounts, click the lock (%{lock}) icon.",
|
||||
:lock => image_tag("locked_small.png", :class => 'lock locked') %>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<% if !@context.site_admin? %>
|
||||
<% if @managing_account_roles %>
|
||||
<a href="<%= context_url(@context, :context_permissions_url) %>"><%= t 'links.manage_course_roles', "Manage Course-Level Roles" %></a>
|
||||
<% else %>
|
||||
<a id="course_level_roles" href="<%= context_url(@context, :context_permissions_url, :account_roles => 1) %>"><%= t 'links.manage_accoiunt_roles', "Manage Account-Level Roles" %></a>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if @managing_account_roles %>
|
||||
<table id="account_roles" style="margin-bottom: 10px;" class='ui-widget ui-widget-content ui-corner-all zebra-stripes'>
|
||||
<thead class="ui-widget-header">
|
||||
<tr>
|
||||
<th><%= t 'headers.account_role_type', "Account Role Type" %></th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @context.available_account_roles.each do |type| %>
|
||||
<tr class="<%= cycle("even", "odd") %>">
|
||||
<td style="padding: 1px 3px;"><%= AccountUser.readable_type type %></td>
|
||||
<td style="padding: 1px 3px; text-align: right;">
|
||||
<%= link_to("<i class='icon-end standalone-icon'></i>".html_safe, context_url(@context, :remove_role_context_permissions_url, :role => type, :account_roles => params[:account_roles]), :class => "no-hover remove_role_link", :method => :delete, :confirm => t('prompts.delete_role_type', "Are you sure you want to delete this role type?")) unless type == 'AccountAdmin' %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<tr>
|
||||
<td colspan="2" style="padding: 2px 3px;">
|
||||
<%form_tag(context_url(@context, :add_role_context_permissions_url)) do %>
|
||||
<input type="hidden" name="account_roles" value="1"/>
|
||||
<%= before_label :new_role_type, "New Role Type" %>
|
||||
<input class= "add_new_role" type="text" name="role_type"/>
|
||||
<button id="add_new_role_button" class="btn btn-small" type="submit"><i class="icon-add"></i> <%= t '#buttons.add', "Add" %></button>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<% end %>
|
||||
|
||||
<% form_tag(context_url(@context, :context_permissions_url, :account_roles => params[:account_roles])) do %>
|
||||
<table cellspacing="0" id="permissions-table" class='ui-widget ui-widget-content ui-corner-all zebra-stripes'>
|
||||
<thead class='ui-widget-header'>
|
||||
<tr>
|
||||
<th></th>
|
||||
<% @role_types.each do |enrollment_type| %>
|
||||
<th><%= enrollment_type[:label].respond_to?(:call) ? enrollment_type[:label].call() : enrollment_type[:label] %></th>
|
||||
<% end %>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% permissions = RoleOverride.manageable_permissions(@context) %>
|
||||
<% permissions.reject! { |k, p| (p[:available_to] & RoleOverride.enrollment_types.map { |role| role[:name] }).empty? unless @managing_account_roles } %>
|
||||
<% permissions.to_a.sort { |a, b| a.last[:label].call() <=> b.last[:label].call() } %>
|
||||
<% site_admin_permissions, permissions = permissions.partition { |(k, p)| p[:account_only] == :site_admin } %>
|
||||
<% account_permissions, permissions = permissions.partition { |(k, p)| p[:account_only] } %>
|
||||
<% unless site_admin_permissions.empty? -%>
|
||||
<tr class='ui-widget-header'>
|
||||
<td><%= t 'headers.site_admin_permissions', "Site Admin Permissions" %></td>
|
||||
<td colspan='<%= @role_types.size %>'></td>
|
||||
</tr>
|
||||
<%= render :partial => 'permission', :collection => site_admin_permissions %>
|
||||
<% end -%>
|
||||
<% unless account_permissions.empty? -%>
|
||||
<tr class='ui-widget-header'>
|
||||
<td><%= t 'headers.account_permissions', "Account Permissions" %></td>
|
||||
<td colspan='<%= @role_types.size %>'></td>
|
||||
</tr>
|
||||
<%= render :partial => 'permission', :collection => account_permissions %>
|
||||
<% end -%>
|
||||
<tr class='ui-widget-header'>
|
||||
<td><%= t 'headers.course_permissions', "Course & Account Permissions" %></td>
|
||||
<td colspan='<%= @role_types.size %>'></td>
|
||||
</tr>
|
||||
<%= render :partial => 'permission', :collection => permissions %>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="button-container">
|
||||
<a class="btn cancel_button" href="<%= url_for(:back) %>"><%= t '#buttons.cancel', "Cancel" %></a>
|
||||
<button type="submit" class="btn btn-primary save_permissions_changes"><%= t 'buttons.save', "Save Changes" %></button>
|
||||
</div>
|
||||
<% end -%>
|
||||
</div>
|
||||
|
||||
<% js_block do %>
|
||||
<script type="text/javascript">
|
||||
require([
|
||||
'jquery' /* $ */,
|
||||
'jquery.instructure_misc_plugins' /* /\.log\(/ */
|
||||
], function($) {
|
||||
|
||||
$('.six-checkbox').click(function(){
|
||||
var $this = $(this);
|
||||
if (!$this.hasClass('six-checkbox-disabled-checked') && !$this.hasClass('six-checkbox-disabled-unchecked') ) { //if its not disabled
|
||||
if (!$this.hasClass("six-checkbox-checked") && !$this.hasClass("six-checkbox-unchecked")) { //if it is not explicitly set
|
||||
if ( $this.hasClass("six-checkbox-default-checked") || $this.hasClass("six-checkbox-default-unchecked") ) {
|
||||
$this
|
||||
.addClass("six-checkbox-checked")
|
||||
.find("input")
|
||||
.val('checked');
|
||||
} else {
|
||||
$this
|
||||
.addClass("six-checkbox-checked")
|
||||
.find("input")
|
||||
.val('checked');
|
||||
}
|
||||
}
|
||||
else { // it IS explicity set
|
||||
if ($this.hasClass("six-checkbox-checked")) {
|
||||
$this
|
||||
.removeClass("six-checkbox-checked")
|
||||
.addClass("six-checkbox-unchecked")
|
||||
.find("input")
|
||||
.val('unchecked');
|
||||
}
|
||||
else { //if ($this.hasClass("six-checkbox-unchecked")) {
|
||||
$this
|
||||
.removeClass("six-checkbox-unchecked")
|
||||
.find("input")
|
||||
.val('');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
$.fn.setLockTitle = function(){
|
||||
$(this).attr('title',
|
||||
$(this).hasClass('locked') ?
|
||||
<%= t('tooltips.locked', "This permission is locked, no one can override what is set here.").to_json.html_safe %> :
|
||||
<%= t('tooltips.lock', "Click to not allow anyone to override what is set here.").to_json.html_safe %>
|
||||
);
|
||||
return this;
|
||||
};
|
||||
$('#permissions-table .lock:not(".disabled")')
|
||||
.setLockTitle()
|
||||
.click(function(){
|
||||
$(this)
|
||||
.toggleClass('locked')
|
||||
.setLockTitle()
|
||||
.next('input')
|
||||
.val(
|
||||
$(this).hasClass('locked')
|
||||
);
|
||||
|
||||
// // uncomment this part if you want it to automatically check boxes that are left at the default if they are locked
|
||||
// var $checkbox = $(this).parent().find('.six-checkbox');
|
||||
// $.each(['checked', 'unchecked'], function(){
|
||||
// console.log(this)
|
||||
// if ( $checkbox.hasClass('six-checkbox-default-' + this) ) {
|
||||
// $checkbox.addClass("six-checkbox-" + this)
|
||||
// .find("input")
|
||||
// .val(this);
|
||||
// }
|
||||
// });
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<% end %>
|
||||
|
|
|
@ -20,10 +20,11 @@ module Api::V1::Role
|
|||
include Api::V1::Json
|
||||
include Api::V1::Account
|
||||
|
||||
def role_json(account, role, current_user, session)
|
||||
def role_json(account, role, current_user, session, opts={})
|
||||
json = {
|
||||
:account => account_json(account, current_user, session, []),
|
||||
:role => role.name,
|
||||
:label => role.label,
|
||||
:base_role_type => role.base_role_type,
|
||||
:workflow_state => role.workflow_state,
|
||||
:permissions => {}
|
||||
|
|
|
@ -394,7 +394,7 @@ describe "Roles API", :type => :integration do
|
|||
describe "json response" do
|
||||
it "should return the expected json format" do
|
||||
json = api_call_with_settings
|
||||
json.keys.sort.should == ["account", "base_role_type", "permissions", "role", "workflow_state"]
|
||||
json.keys.sort.should == ["account", "base_role_type", "label", "permissions", "role", "workflow_state"]
|
||||
json["account"].should == {
|
||||
"name" => @account.name,
|
||||
"root_account_id" => @account.root_account_id,
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
define [
|
||||
'Backbone'
|
||||
'underscore'
|
||||
'compiled/models/Role'
|
||||
'compiled/collections/RolesCollection'
|
||||
'compiled/util/BaseRoleTypes'
|
||||
], (Backbone,_, Role, RolesCollection) ->
|
||||
module 'RolesCollection',
|
||||
setup: ->
|
||||
@account_id = 2
|
||||
teardown: ->
|
||||
@account_id = null
|
||||
|
||||
test "generate the correct url for a collection of roles", 1, ->
|
||||
roles_collection = new RolesCollection null
|
||||
contextAssetString: "account_#{@account_id}"
|
||||
|
||||
equal roles_collection.url(), "/api/v1/accounts/#{@account_id}/roles", "roles collection url"
|
||||
|
||||
test "fetches a collection of roles", 1, ->
|
||||
server = sinon.fakeServer.create()
|
||||
|
||||
role1 = new Role
|
||||
role2 = new Role
|
||||
|
||||
roles_collection = new RolesCollection null
|
||||
contextAssetString: "account_#{@account_id}"
|
||||
|
||||
roles_collection.fetch success: =>
|
||||
equal roles_collection.size(), 2, "Adds all of the roles to the collection"
|
||||
|
||||
server.respond 'GET', roles_collection.url(), [200, {
|
||||
'Content-Type': 'application/json'
|
||||
}, JSON.stringify([role1, role2])]
|
||||
|
||||
server.restore()
|
||||
|
||||
test "keeps roles in order based on sort order", 3, ->
|
||||
RolesCollection.sortOrder = [
|
||||
"AccountMembership"
|
||||
"StudentEnrollment"
|
||||
"TaEnrollment"
|
||||
]
|
||||
|
||||
roleFirst = new Role base_role_type : "AccountMembership"
|
||||
roleSecond = new Role base_role_type : "StudentEnrollment"
|
||||
roleThird = new Role base_role_type : "TaEnrollment"
|
||||
|
||||
roleCollection = new RolesCollection([roleThird, roleFirst, roleSecond])
|
||||
|
||||
equal roleCollection.models[0], roleFirst, "First role is in order"
|
||||
equal roleCollection.models[1], roleSecond, "Second role is in order"
|
||||
equal roleCollection.models[2], roleThird, "Third role is in order"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
define [
|
||||
'Backbone'
|
||||
'underscore'
|
||||
'compiled/models/Role'
|
||||
'compiled/models/Account'
|
||||
'compiled/util/BaseRoleTypes'
|
||||
], (Backbone,_, Role, Account, BASE_ROLE_TYPES) ->
|
||||
module 'RoleModel',
|
||||
setup: ->
|
||||
@account = new Account id: 4
|
||||
@role = new Role account: @account
|
||||
@server = sinon.fakeServer.create()
|
||||
|
||||
teardown: ->
|
||||
@server.restore()
|
||||
@role = null
|
||||
@account_id = null
|
||||
|
||||
test 'the id gets set to the role name when role is created', 1, ->
|
||||
@role.fetch success: =>
|
||||
equal @role.get('id'), "existingRole", "Role id should equal the roles name"
|
||||
|
||||
@server.respond 'GET', @role.url(), [200, {
|
||||
'Content-Type': 'application/json'
|
||||
}, JSON.stringify({"role": "existingRole"})]
|
||||
|
||||
test 'generates the correct url for existing and non-existing roles', 2, ->
|
||||
equal @role.url(), "/api/v1/accounts/#{@account.get('id')}/roles", "non-existing role url"
|
||||
|
||||
@role.fetch success: =>
|
||||
equal @role.url(), "/api/v1/accounts/#{@account.get('id')}/roles/existingRole", "existing role url"
|
||||
|
||||
@server.respond 'GET', @role.url(), [200, {
|
||||
'Content-Type': 'application/json'
|
||||
}, JSON.stringify({"role": "existingRole", "account" : @account})]
|
||||
|
|
@ -96,11 +96,13 @@ describe RoleOverridesController do
|
|||
@existing_override.locked.should be_true
|
||||
end
|
||||
|
||||
it "should only update the parts that are specified" do
|
||||
it "only updates unchecked" do
|
||||
post_with_settings(:override => 'unchecked')
|
||||
@existing_override.reload
|
||||
@existing_override.locked.should be_false
|
||||
|
||||
end
|
||||
|
||||
it "only updates enabled" do
|
||||
@existing_override.enabled = true
|
||||
@existing_override.save
|
||||
|
||||
|
@ -142,14 +144,16 @@ describe RoleOverridesController do
|
|||
override.locked.should be_true
|
||||
end
|
||||
|
||||
it "should only set the parts that are specified" do
|
||||
it "sets override as false when override is unchecked" do
|
||||
post_with_settings(:override => 'unchecked')
|
||||
override = @account.role_overrides(true).find_by_permission_and_enrollment_type(@permission, @role)
|
||||
override.should_not be_nil
|
||||
override.enabled.should be_false
|
||||
override.locked.should be_nil
|
||||
override.destroy
|
||||
end
|
||||
|
||||
it "sets the override to locked when specifiying locked" do
|
||||
post_with_settings(:locked => 'true')
|
||||
override = @account.role_overrides(true).find_by_permission_and_enrollment_type(@permission, @role)
|
||||
override.should_not be_nil
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Copyright (C) 2012 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
||||
|
||||
describe RoleOverridesHelper do
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
(function() {
|
||||
|
||||
define(['Backbone', 'underscore', 'compiled/models/Role', 'compiled/collections/RolesCollection', 'compiled/util/BaseRoleTypes'], function(Backbone, _, Role, RolesCollection, BASE_ROLE_TYPES) {
|
||||
module('RolesCollection', {
|
||||
setup: function() {
|
||||
return this.account_id = 2;
|
||||
},
|
||||
teardown: function() {
|
||||
return this.account_id = null;
|
||||
}
|
||||
});
|
||||
return test("generate the correct url for a collection of roles", 1, function() {
|
||||
var roles_collection;
|
||||
roles_collection = new RolesCollection;
|
||||
return equal(roles_collection.url(), "/accounts/" + this.account_id + "/roles", "roles collection url");
|
||||
});
|
||||
});
|
||||
|
||||
}).call(this);
|
|
@ -5,123 +5,215 @@ shared_examples_for "permission tests" do
|
|||
course_with_admin_logged_in
|
||||
end
|
||||
|
||||
def has_default_permission?(permission, enrollment_type)
|
||||
default_permissions = Permissions.retrieve
|
||||
default_permissions[permission][:true_for].include?(enrollment_type)
|
||||
def select_enable(permission_name, role_name)
|
||||
permission_button = fj("[data-permission_name='#{permission_name}'].[data-role_name='#{role_name}']")
|
||||
permission_button.find_element(:css, "a").click
|
||||
options = permission_button.find_elements(:css, ".dropdown-menu label")
|
||||
options[0].click # 0 is Enable
|
||||
|
||||
wait_for_ajax_requests #Every select needs to wait for for the request to finish
|
||||
end
|
||||
|
||||
def get_updated_role(permission, enrollment_type)
|
||||
RoleOverride.first(:conditions => {:permission => permission.to_s, :enrollment_type => enrollment_type})
|
||||
end
|
||||
def select_enable_and_lock(permission_name, role_name)
|
||||
permission_button = fj("[data-permission_name='#{permission_name}'].[data-role_name='#{role_name}']")
|
||||
permission_button.find_element(:css, "a").click
|
||||
options = permission_button.find_elements(:css, ".dropdown-menu label")
|
||||
options[1].click # 1 is enabled and locked
|
||||
|
||||
def get_checkbox(permission, selector, enrollment_type)
|
||||
row = nil
|
||||
permissions = ff("#permissions-table tr > th")
|
||||
permissions.each do |elem|
|
||||
if (elem.text.include? permission)
|
||||
row = elem.find_element(:xpath, "..")
|
||||
break
|
||||
end
|
||||
end
|
||||
#enrollment type is the number corresponding to the role i.e. Student = 0, Ta = 1, Teacher = 2...
|
||||
row.find_elements(:css, selector)[enrollment_type]
|
||||
end
|
||||
|
||||
def checkbox_verifier(permission, enrollment_type, disable_permission = false, locked = false)
|
||||
selector = locked ? ".lock" : ".six-checkbox"
|
||||
#get the element we need
|
||||
check_box = get_checkbox(permission, selector, enrollment_type)
|
||||
#we iterate according to the permission event
|
||||
iterate = disable_permission ? 2 : 1
|
||||
iterate.times { check_box.click }
|
||||
f(".save_permissions_changes").click
|
||||
wait_for_ajax_requests
|
||||
check_box = get_checkbox(permission, selector, enrollment_type)
|
||||
if (locked)
|
||||
check_box.find_element(:xpath, "..").find_element(:css, "input").should have_value("true")
|
||||
else
|
||||
if (disable_permission)
|
||||
check_box.find_element(:css, "input").should have_value("unchecked")
|
||||
else
|
||||
check_box.find_element(:css, "input").should have_value("checked")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def permissions_verifier(opts, default_permitted = false, disable_permission = false, locked = false)
|
||||
if (default_permitted)
|
||||
has_default_permission?(opts.keys[0], opts.values[0]).should be_true
|
||||
else
|
||||
has_default_permission?(opts.keys[0], opts.values[0]).should be_false
|
||||
end
|
||||
role = get_updated_role(opts.keys[0], opts.values[0])
|
||||
role.should be_present
|
||||
if (disable_permission)
|
||||
role.enabled.should be_false
|
||||
else
|
||||
if (!locked)
|
||||
role.enabled.should be_true
|
||||
end
|
||||
end
|
||||
if (locked)
|
||||
role.locked.should be_true
|
||||
else
|
||||
role.locked.should be_false
|
||||
end
|
||||
def select_disable(permission_name, role_name)
|
||||
permission_button = fj("[data-permission_name='#{permission_name}'].[data-role_name='#{role_name}']")
|
||||
permission_button.find_element(:css, "a").click
|
||||
options = permission_button.find_elements(:css, ".dropdown-menu label")
|
||||
options[2].click # 2 is Disabled
|
||||
|
||||
wait_for_ajax_requests
|
||||
end
|
||||
|
||||
describe "new role permissions" do
|
||||
before (:each) do
|
||||
def select_disable_and_lock(permission_name, role_name)
|
||||
permission_button = fj("[data-permission_name='#{permission_name}'].[data-role_name='#{role_name}']")
|
||||
permission_button.find_element(:css, "a").click
|
||||
options = permission_button.find_elements(:css, ".dropdown-menu label")
|
||||
options[3].click # 3 is Disabled and locked
|
||||
|
||||
wait_for_ajax_requests
|
||||
end
|
||||
|
||||
def add_new_account_role(role_name)
|
||||
role = account.roles.build name: role_name
|
||||
role.base_role_type = "AccountMembership"
|
||||
role.save!
|
||||
role
|
||||
end
|
||||
|
||||
def add_new_course_role(role_name, role_type = "StudentEnrollment")
|
||||
role = account.roles.build name: role_name
|
||||
role.base_role_type = role_type
|
||||
role.save!
|
||||
role
|
||||
end
|
||||
|
||||
describe "Adding new roles" do
|
||||
before do
|
||||
get url
|
||||
end
|
||||
|
||||
def add_new_role(role)
|
||||
f(".add_new_role").send_keys(role)
|
||||
f("#add_new_role_button").click
|
||||
it "adds a new account role" do
|
||||
role_name = "an account role"
|
||||
|
||||
f("#account_role_link").click
|
||||
f('#account-roles-tab .new-role a.dropdown-toggle').click
|
||||
f('#account-roles-tab .new-role form input').send_keys(role_name)
|
||||
f('#account-roles-tab .new-role button').click
|
||||
wait_for_ajax_requests
|
||||
account.reload
|
||||
account.available_account_roles.should include(role)
|
||||
f("#permissions-table tr").should include_text(role)
|
||||
|
||||
f('#account-roles-tab').should include_text(role_name)
|
||||
end
|
||||
|
||||
it "should add a new account role type" do
|
||||
role = "New Role"
|
||||
add_new_role(role)
|
||||
end
|
||||
it "adds a new course role" do
|
||||
role_name = "a course role"
|
||||
|
||||
it "should delete an added role" do
|
||||
role = "New Role"
|
||||
add_new_role(role)
|
||||
f(".remove_role_link").click
|
||||
driver.switch_to.alert.accept
|
||||
f("#course_role_link").click
|
||||
f('#course-roles-tab .new-role a.dropdown-toggle').click
|
||||
f('#course-roles-tab .new-role form input').send_keys(role_name)
|
||||
f('#course-roles-tab .new-role button').click
|
||||
wait_for_ajax_requests
|
||||
account.reload
|
||||
account.roles.active.find_by_name(role).should be_nil
|
||||
f("#permissions-table tr").should_not include_text(role)
|
||||
end
|
||||
|
||||
it "should enable manage permissions of new role" do
|
||||
role = "New Role"
|
||||
add_new_role(role)
|
||||
checkbox_verifier("Manage permissions", 1)
|
||||
opts = {:manage_role_overrides => role}
|
||||
permissions_verifier(opts)
|
||||
end
|
||||
|
||||
it "should disable manage permissions of new role" do
|
||||
role = "New Role"
|
||||
add_new_role(role)
|
||||
checkbox_verifier("Manage permissions", 1, true)
|
||||
opts = {:manage_role_overrides => role}
|
||||
permissions_verifier(opts, false, true)
|
||||
end
|
||||
|
||||
it "should lock manage permissions of new role" do
|
||||
role = "New Role"
|
||||
add_new_role(role)
|
||||
checkbox_verifier("Manage permissions", 1, false, true)
|
||||
opts = {:manage_role_overrides => role}
|
||||
permissions_verifier(opts, false, false, true)
|
||||
f('#course-roles-tab').should include_text(role_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Removing roles" do
|
||||
context "when deleting account roles" do
|
||||
let!(:role_name) {"delete this account role"}
|
||||
|
||||
before do
|
||||
add_new_account_role role_name
|
||||
get url
|
||||
end
|
||||
|
||||
it "deletes a role" do
|
||||
f("#account_role_link").click
|
||||
f(".roleHeader a").click
|
||||
driver.switch_to.alert.accept
|
||||
wait_for_ajax_requests
|
||||
|
||||
f('#account-roles-tab').should_not include_text(role_name)
|
||||
end
|
||||
end
|
||||
|
||||
context "when deleting course roles" do
|
||||
let!(:role_name) {"delete this course role"}
|
||||
|
||||
before do
|
||||
add_new_course_role role_name
|
||||
get url
|
||||
end
|
||||
|
||||
it "deletes a role" do
|
||||
f("#course_role_link").click
|
||||
f(".roleHeader a").click
|
||||
driver.switch_to.alert.accept
|
||||
wait_for_ajax_requests
|
||||
|
||||
f('#course-roles-tab').should_not include_text(role_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Managing roles" do
|
||||
context "when managing account roles" do
|
||||
let!(:role_name) {"TestAcccountRole"}
|
||||
let!(:permission_name) {"read_sis"} # Everyone should have this permission
|
||||
let!(:role) { add_new_account_role role_name }
|
||||
|
||||
before do
|
||||
get url
|
||||
f("#account_role_link").click
|
||||
end
|
||||
|
||||
it "enables a permission" do
|
||||
select_enable(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_true
|
||||
role_override.locked.should be_false
|
||||
end
|
||||
|
||||
it "locks and enables a permission" do
|
||||
select_enable_and_lock(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_true
|
||||
role_override.locked.should be_true
|
||||
end
|
||||
|
||||
it "disables a permission" do
|
||||
select_disable(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_false
|
||||
role_override.locked.should be_false
|
||||
end
|
||||
|
||||
it "locks and disables a permission" do
|
||||
select_disable_and_lock(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_false
|
||||
role_override.locked.should be_true
|
||||
end
|
||||
|
||||
it "sets a permission to default"
|
||||
it "sets a permission to default and locked"
|
||||
end
|
||||
|
||||
context "when managing course roles" do
|
||||
let!(:role_name) {"TestCourseRole"}
|
||||
let!(:permission_name) {"read_sis"} # Everyone should have this permission
|
||||
let!(:role) { add_new_course_role role_name }
|
||||
|
||||
before do
|
||||
f("#course_role_link").click
|
||||
get url
|
||||
end
|
||||
|
||||
it "enables a permission" do
|
||||
select_enable(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_true
|
||||
role_override.locked.should be_false
|
||||
end
|
||||
|
||||
it "locks and enables a permission" do
|
||||
select_enable_and_lock(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_true
|
||||
role_override.locked.should be_true
|
||||
end
|
||||
|
||||
it "disables a permission" do
|
||||
select_disable(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_false
|
||||
role_override.locked.should be_false
|
||||
end
|
||||
|
||||
it "locks and disables a permission" do
|
||||
select_disable_and_lock(permission_name, role_name)
|
||||
|
||||
role_override = RoleOverride.find_by_enrollment_type(role.name)
|
||||
role_override.enabled.should be_false
|
||||
role_override.locked.should be_true
|
||||
end
|
||||
|
||||
it "sets a permission to default"
|
||||
it "sets a permission to default and locked"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue