diff --git a/cms/djangoapps/contentstore/features/course-team.feature b/cms/djangoapps/contentstore/features/course-team.feature deleted file mode 100644 index 05a59002f5..0000000000 --- a/cms/djangoapps/contentstore/features/course-team.feature +++ /dev/null @@ -1,89 +0,0 @@ -@shard_2 -Feature: CMS.Course Team - As a course author, I want to be able to add others to my team - - Scenario: Admins can add other users - Given I have opened a new course in Studio - And the user "alice" exists - And I am viewing the course team settings - When I add "alice" to the course team - And "alice" logs in - Then she does see the course on her page - - Scenario: Added admins cannot delete or add other users - Given I have opened a new course in Studio - And the user "bob" exists - And I am viewing the course team settings - When I add "bob" to the course team - And "bob" logs in - And he selects the new course - And he views the course team settings - Then he cannot delete users - And he cannot add users - - Scenario: Admins can delete other users - Given I have opened a new course in Studio - And the user "carol" exists - And I am viewing the course team settings - When I add "carol" to the course team - And I delete "carol" from the course team - And "carol" logs in - Then she does not see the course on her page - - Scenario: Admins cannot add users that do not exist - Given I have opened a new course in Studio - And I am viewing the course team settings - When I add "dennis" to the course team - Then I should see "Could not find user by email address" somewhere on the page - - Scenario: Admins should be able to make other people into admins - Given I have opened a new course in Studio - And the user "emily" exists - And I am viewing the course team settings - And I add "emily" to the course team - When I make "emily" a course team admin - And "emily" logs in - And she selects the new course - And she views the course team settings - Then "emily" should be marked as an admin - And she can add users - And she can delete users - - Scenario: Admins should be able to remove other admins - Given I have opened a new course in Studio - And the user "frank" exists as a course admin - And I am viewing the course team settings - When I remove admin rights from "frank" - And "frank" logs in - And he selects the new course - And he views the course team settings - Then "frank" should not be marked as an admin - And he cannot add users - And he cannot delete users - - Scenario: Admins should be able to give course ownership to someone else - Given I have opened a new course in Studio - And the user "gina" exists - And I am viewing the course team settings - When I add "gina" to the course team - And I make "gina" a course team admin - And I remove admin rights from myself - And "gina" logs in - And she selects the new course - And she views the course team settings - And she deletes me from the course team - And I am logged into studio - Then I do not see the course on my page - - Scenario: Admins should be able to remove their own admin rights - Given I have opened a new course in Studio - And the user "harry" exists as a course admin - And I am viewing the course team settings - Then I should be marked as an admin - And I can add users - And I can delete users - When I remove admin rights from myself - Then I should not be marked as an admin - And I cannot add users - And I cannot delete users - And I cannot make myself a course team admin diff --git a/cms/djangoapps/contentstore/features/course-team.py b/cms/djangoapps/contentstore/features/course-team.py deleted file mode 100644 index 130f05b0f5..0000000000 --- a/cms/djangoapps/contentstore/features/course-team.py +++ /dev/null @@ -1,124 +0,0 @@ -# pylint: disable=missing-docstring -# pylint: disable=redefined-outer-name - -from lettuce import world, step -from nose.tools import assert_in # pylint: disable=no-name-in-module - - -@step(u'(I am viewing|s?he views) the course team settings$') -def view_grading_settings(_step, whom): - world.click_course_settings() - link_css = 'li.nav-course-settings-team a' - world.css_click(link_css) - - -@step(u'I add "([^"]*)" to the course team$') -def add_other_user(_step, name): - new_user_css = 'a.create-user-button' - world.css_click(new_user_css) - - # Wait for the css animation to apply the is-shown class - shown_css = 'div.wrapper-create-user.is-shown' - world.wait_for_present(shown_css) - - email_css = 'input#user-email-input' - world.css_fill(email_css, name + '@edx.org') - if world.is_firefox(): - world.trigger_event(email_css) - confirm_css = 'form.create-user button.action-primary' - world.css_click(confirm_css) - - -@step(u'I delete "([^"]*)" from the course team$') -def delete_other_user(_step, name): - to_delete_css = '.user-item .item-actions a.remove-user[data-id="{email}"]'.format( - email="{0}{1}".format(name, '@edx.org')) - world.css_click(to_delete_css) - world.confirm_studio_prompt() - - -@step(u's?he deletes me from the course team$') -def other_delete_self(_step): - to_delete_css = '.user-item .item-actions a.remove-user[data-id="{email}"]'.format( - email="robot+studio@edx.org") - world.css_click(to_delete_css) - world.confirm_studio_prompt() - - -@step(u'I make "([^"]*)" a course team admin$') -def make_course_team_admin(_step, name): - admin_btn_css = '.user-item[data-email="{name}@edx.org"] .user-actions .add-admin-role'.format( - name=name) - world.css_click(admin_btn_css) - - -@step(u'I remove admin rights from ("([^"]*)"|myself)$') -def remove_course_team_admin(_step, outer_capture, name): - if outer_capture == "myself": - email = world.scenario_dict["USER"].email - else: - email = name + '@edx.org' - admin_btn_css = '.user-item[data-email="{email}"] .user-actions .remove-admin-role'.format( - email=email) - world.css_click(admin_btn_css) - - -@step(u'I( do not)? see the course on my page$') -@step(u's?he does( not)? see the course on (his|her) page$') -def see_course(_step, do_not_see, gender='self'): - class_css = 'h3.course-title' - if do_not_see: - assert world.is_css_not_present(class_css) - else: - all_courses = world.css_find(class_css) - all_names = [item.html for item in all_courses] - assert_in(world.scenario_dict['COURSE'].display_name, all_names) - - -@step(u'"([^"]*)" should( not)? be marked as an admin$') -def marked_as_admin(_step, name, not_marked_admin): - flag_css = '.user-item[data-email="{name}@edx.org"] .flag-role.flag-role-admin'.format( - name=name) - if not_marked_admin: - assert world.is_css_not_present(flag_css) - else: - assert world.is_css_present(flag_css) - - -@step(u'I should( not)? be marked as an admin$') -def self_marked_as_admin(_step, not_marked_admin): - return marked_as_admin(_step, "robot+studio", not_marked_admin) - - -@step(u'I can(not)? delete users$') -@step(u's?he can(not)? delete users$') -def can_delete_users(_step, can_not_delete): - to_delete_css = 'a.remove-user' - if can_not_delete: - assert world.is_css_not_present(to_delete_css) - else: - assert world.is_css_present(to_delete_css) - - -@step(u'I can(not)? add users$') -@step(u's?he can(not)? add users$') -def can_add_users(_step, can_not_add): - add_css = 'a.create-user-button' - if can_not_add: - assert world.is_css_not_present(add_css) - else: - assert world.is_css_present(add_css) - - -@step(u'I can(not)? make ("([^"]*)"|myself) a course team admin$') -@step(u's?he can(not)? make ("([^"]*)"|me) a course team admin$') -def can_make_course_admin(_step, can_not_make_admin, outer_capture, name): - if outer_capture == "myself": - email = world.scenario_dict["USER"].email - else: - email = name + '@edx.org' - add_button_css = '.user-item[data-email="{email}"] .add-admin-role'.format(email=email) - if can_not_make_admin: - assert world.is_css_not_present(add_button_css) - else: - assert world.is_css_present(add_button_css) diff --git a/cms/djangoapps/contentstore/views/library.py b/cms/djangoapps/contentstore/views/library.py index 0a7a0e2504..a5aa09a6f0 100644 --- a/cms/djangoapps/contentstore/views/library.py +++ b/cms/djangoapps/contentstore/views/library.py @@ -24,6 +24,7 @@ from opaque_keys.edx.locator import LibraryLocator, LibraryUsageLocator from xmodule.modulestore.exceptions import DuplicateCourseError from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore +from .user import user_with_role from .component import get_component_templates, CONTAINER_TEMPATES from student.auth import ( @@ -220,14 +221,18 @@ def manage_library_users(request, library_key_string): instructors = set(CourseInstructorRole(library_key).users_with_role()) staff = set(CourseStaffRole(library_key).users_with_role()) - instructors users = set(LibraryUserRole(library_key).users_with_role()) - instructors - staff - all_users = instructors | staff | users + + formatted_users = [] + for user in instructors: + formatted_users.append(user_with_role(user, 'instructor')) + for user in staff: + formatted_users.append(user_with_role(user, 'staff')) + for user in users: + formatted_users.append(user_with_role(user, 'library_user')) return render_to_response('manage_users_lib.html', { 'context_library': library, - 'staff': staff, - 'instructors': instructors, - 'users': users, - 'all_users': all_users, + 'users': formatted_users, 'allow_actions': bool(user_perms & STUDIO_EDIT_ROLES), 'library_key': unicode(library_key), 'lib_users_url': reverse_library_url('manage_library_users', library_key_string), diff --git a/cms/djangoapps/contentstore/views/tests/test_checklists.py b/cms/djangoapps/contentstore/views/tests/test_checklists.py index b86a78ce9c..17ce2e889a 100644 --- a/cms/djangoapps/contentstore/views/tests/test_checklists.py +++ b/cms/djangoapps/contentstore/views/tests/test_checklists.py @@ -136,7 +136,7 @@ class ChecklistTestCase(CourseTestCase): # Verify no side effect in the original list. self.assertEqual(get_action_url(checklist, index), stored) - test_expansion(self.course.checklists[0], 0, 'ManageUsers', '/course_team/mitX/333/Checklists_Course/') + test_expansion(self.course.checklists[0], 0, 'ManageUsers', '/course_team/mitX/333/Checklists_Course') test_expansion(self.course.checklists[1], 1, 'CourseOutline', '/course/mitX/333/Checklists_Course') test_expansion(self.course.checklists[2], 0, 'http://help.edge.edx.org/', 'http://help.edge.edx.org/') diff --git a/cms/djangoapps/contentstore/views/user.py b/cms/djangoapps/contentstore/views/user.py index 93a7c66a77..10373a8dc6 100644 --- a/cms/djangoapps/contentstore/views/user.py +++ b/cms/djangoapps/contentstore/views/user.py @@ -61,6 +61,16 @@ def course_team_handler(request, course_key_string=None, email=None): return HttpResponseNotFound() +def user_with_role(user, role): + """ Build user representation with attached role """ + return { + 'id': user.id, + 'username': user.username, + 'email': user.email, + 'role': role + } + + def _manage_users(request, course_key): """ This view will return all CMS users who are editors for the specified course @@ -71,14 +81,20 @@ def _manage_users(request, course_key): raise PermissionDenied() course_module = modulestore().get_course(course_key) - instructors = CourseInstructorRole(course_key).users_with_role() + instructors = set(CourseInstructorRole(course_key).users_with_role()) # the page only lists staff and assumes they're a superset of instructors. Do a union to ensure. staff = set(CourseStaffRole(course_key).users_with_role()).union(instructors) + formatted_users = [] + for user in instructors: + formatted_users.append(user_with_role(user, 'instructor')) + for user in staff - instructors: + formatted_users.append(user_with_role(user, 'staff')) + return render_to_response('manage_users.html', { 'context_course': course_module, - 'staff': staff, - 'instructors': instructors, + 'show_transfer_ownership_hint': request.user in instructors and len(instructors) == 1, + 'users': formatted_users, 'allow_actions': bool(user_perms & STUDIO_EDIT_ROLES), }) diff --git a/cms/static/js/factories/manage_users.js b/cms/static/js/factories/manage_users.js index 2f4e5b406f..d15979e16d 100644 --- a/cms/static/js/factories/manage_users.js +++ b/cms/static/js/factories/manage_users.js @@ -1,203 +1,35 @@ -define(['jquery', 'underscore', 'gettext', 'js/views/feedback_prompt'], function($, _, gettext, PromptView) { +/* + Code for editing users and assigning roles within a course team context. +*/ +define(['underscore', 'gettext', 'js/views/manage_users_and_roles'], +function(_, gettext, ManageUsersAndRoles) { 'use strict'; - return function (staffEmails, tplUserURL) { - var unknownErrorMessage = gettext('Unknown'), - $createUserForm = $('#create-user-form'), - $createUserFormWrapper = $createUserForm.closest('.wrapper-create-user'), - $cancelButton; + return function (containerName, users, tplUserURL, current_user_id, allow_actions) { + function updateMessages(messages) { + var local_messages = _.extend({}, messages); + local_messages.alreadyMember.title = gettext('Already a course team member'); + local_messages.deleteUser.messageTpl = gettext( + 'Are you sure you want to delete {email} from the course team for “{container}”?' + ); + return local_messages; + } + // Roles order are important: first role is considered initial role (the role added to user when (s)he's added + // Last role is considered an admin role (unrestricted access + ability to manage other users' permissions) + // Changing roles is performed in promote-demote fashion, so moves only to adjacent roles is allowed + var roles = [{key:'staff', name:gettext('Staff')}, {key:'instructor', 'name': gettext("Admin")}]; - $createUserForm.bind('submit', function(event) { - event.preventDefault(); - var email = $('#user-email-input').val().trim(), - url, msg; + var options = { + el: $("#content"), + containerName: containerName, + tplUserURL: tplUserURL, + roles: roles, + users: users, + messages_modifier: updateMessages, + current_user_id: current_user_id, + allow_actions: allow_actions + }; - if(!email) { - msg = new PromptView.Error({ - title: gettext('A valid email address is required'), - message: gettext('You must enter a valid email address in order to add a new team member'), - actions: { - primary: { - text: gettext('Return and add email address'), - click: function(view) { - view.hide(); - $('#user-email-input').focus(); - } - } - } - }); - msg.show(); - } - - if(_.contains(staffEmails, email)) { - msg = new PromptView.Warning({ - title: gettext('Already a course team member'), - message: _.template( - gettext("{email} is already on the {course} team. Recheck the email address if you want to add a new member."), { - email: email, - course: course.escape('name') - }, {interpolate: /\{(.+?)\}/g} - ), - actions: { - primary: { - text: gettext('Return to team listing'), - click: function(view) { - view.hide(); - $('#user-email-input').focus(); - } - } - } - }); - msg.show(); - } - - url = tplUserURL.replace('@@EMAIL@@', $('#user-email-input').val().trim()); - $.ajax({ - url: url, - type: 'POST', - dataType: 'json', - contentType: 'application/json', - notifyOnError: false, - data: JSON.stringify({role: 'staff'}), - success: function(data) {location.reload();}, - error: function(jqXHR, textStatus, errorThrown) { - var message, prompt; - try { - message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage; - } catch (e) { - message = unknownErrorMessage; - } - prompt = new PromptView.Error({ - title: gettext('Error adding user'), - message: message, - actions: { - primary: { - text: gettext('OK'), - click: function(view) { - view.hide(); - $('#user-email-input').focus(); - } - } - } - }); - prompt.show(); - } - }); - }); - - $cancelButton = $createUserForm.find('.action-cancel'); - $cancelButton.bind('click', function(event) { - event.preventDefault(); - $('.create-user-button').toggleClass('is-disabled').attr('aria-disabled', $('.create-user-button').hasClass('is-disabled')); - $createUserFormWrapper.toggleClass('is-shown'); - $('#user-email-input').val(''); - }); - - $('.create-user-button').bind('click', function(event) { - event.preventDefault(); - $('.create-user-button').toggleClass('is-disabled').attr('aria-disabled', $('.create-user-button').hasClass('is-disabled')); - $createUserFormWrapper.toggleClass('is-shown'); - $createUserForm.find('#user-email-input').focus(); - }); - - $('body').bind('keyup', function(event) { - if(event.which == 27) { - $cancelButton.click(); - } - }); - - $('.remove-user').click(function() { - var email = $(this).data('id'), - msg = new PromptView.Warning({ - title: gettext('Are you sure?'), - message: _.template(gettext('Are you sure you want to delete {email} from the course team for “{course}”?'), {email: email, course: course.get('name')}, {interpolate: /\{(.+?)\}/g}), - actions: { - primary: { - text: gettext('Delete'), - click: function(view) { - var url = tplUserURL.replace('@@EMAIL@@', email); - view.hide(); - $.ajax({ - url: url, - type: 'DELETE', - dataType: 'json', - contentType: 'application/json', - notifyOnError: false, - success: function(data) {location.reload();}, - error: function(jqXHR, textStatus, errorThrown) { - var message; - try { - message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage; - } catch (e) { - message = unknownErrorMessage; - } - var prompt = new PromptView.Error({ - title: gettext('Error removing user'), - message: message, - actions: { - primary: { - text: gettext('OK'), - click: function(view) { - view.hide(); - } - } - } - }); - prompt.show(); - } - }); - } - }, - secondary: { - text: gettext('Cancel'), - click: function(view) { - view.hide(); - } - } - } - }); - msg.show(); - }); - - $('.toggle-admin-role').click(function(event) { - event.preventDefault(); - var type, url, role; - if($(this).hasClass('add-admin-role')) { - role = 'instructor'; - } else { - role = 'staff'; - } - - url = $(this).closest('li[data-url]').data('url'); - $.ajax({ - url: url, - type: 'POST', - dataType: 'json', - contentType: 'application/json', - notifyOnError: false, - data: JSON.stringify({role: role}), - success: function(data) {location.reload();}, - error: function(jqXHR, textStatus, errorThrown) { - var message, prompt; - try { - message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage; - } catch (e) { - message = unknownErrorMessage; - } - prompt = new PromptView.Error({ - title: gettext("There was an error changing the user's role"), - message: message, - actions: { - primary: { - text: gettext('Try Again'), - click: function(view) { - view.hide(); - } - } - } - }); - prompt.show(); - } - }); - }); + var view = new ManageUsersAndRoles(options); + view.render(); }; }); diff --git a/cms/static/js/factories/manage_users_lib.js b/cms/static/js/factories/manage_users_lib.js index 388ec56c73..f25bf8b131 100644 --- a/cms/static/js/factories/manage_users_lib.js +++ b/cms/static/js/factories/manage_users_lib.js @@ -1,159 +1,39 @@ /* Code for editing users and assigning roles within a library context. */ -define(['jquery', 'underscore', 'gettext', 'js/views/feedback_prompt', 'js/views/utils/view_utils'], -function($, _, gettext, PromptView, ViewUtils) { +define(['underscore', 'gettext', 'js/views/manage_users_and_roles'], +function(_, gettext, ManageUsersAndRoles) { 'use strict'; - return function (libraryName, allUserEmails, tplUserURL) { - var unknownErrorMessage = gettext('Unknown'), - $createUserForm = $('#create-user-form'), - $createUserFormWrapper = $createUserForm.closest('.wrapper-create-user'), - $cancelButton; + return function (containerName, users, tplUserURL, current_user_id, allow_actions) { + function updateMessages(messages) { + var local_messages = _.extend({}, messages); + local_messages.alreadyMember.title = gettext('Already a library team member'); + local_messages.deleteUser.messageTpl = gettext( + 'Are you sure you want to delete {email} from the library “{container}”?' + ); + return local_messages; + } + // Roles order are important: first role is considered initial role (the role added to user when (s)he's added + // Last role is considered an admin role (unrestricted access + ability to manage other users' permissions) + // Changing roles is performed in promote-demote fashion, so moves only to adjacent roles is allowed + var roles = [ + {key:'library_user', name:gettext('Library User')}, + {key:'staff', name:gettext('Staff')}, + {key:'instructor', 'name': gettext("Admin")} + ]; - // Our helper method that calls the RESTful API to add/remove/change user roles: - var changeRole = function(email, newRole, opts) { - var url = tplUserURL.replace('@@EMAIL@@', email); - var errMessage = opts.errMessage || gettext("There was an error changing the user's role"); - var onSuccess = opts.onSuccess || function(data){ ViewUtils.reload(); }; - var onError = opts.onError || function(){}; - $.ajax({ - url: url, - type: newRole ? 'POST' : 'DELETE', - dataType: 'json', - contentType: 'application/json', - notifyOnError: false, - data: JSON.stringify({role: newRole}), - success: onSuccess, - error: function(jqXHR, textStatus, errorThrown) { - var message, prompt; - try { - message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage; - } catch (e) { - message = unknownErrorMessage; - } - prompt = new PromptView.Error({ - title: errMessage, - message: message, - actions: { - primary: { text: gettext('OK'), click: function(view) { view.hide(); onError(); } } - } - }); - prompt.show(); - } - }); + var options = { + el: $("#content"), + containerName: containerName, + tplUserURL: tplUserURL, + roles: roles, + users: users, + messages_modifier: updateMessages, + current_user_id: current_user_id, + allow_actions: allow_actions }; - $createUserForm.bind('submit', function(event) { - event.preventDefault(); - var email = $('#user-email-input').val().trim(); - var msg; - - if(!email) { - msg = new PromptView.Error({ - title: gettext('A valid email address is required'), - message: gettext('You must enter a valid email address in order to add an instructor'), - actions: { - primary: { - text: gettext('Return and add email address'), - click: function(view) { view.hide(); $('#user-email-input').focus(); } - } - } - }); - msg.show(); - return; - } - - if(_.contains(allUserEmails, email)) { - msg = new PromptView.Warning({ - title: gettext('Already a library team member'), - message: _.template( - gettext("{email} is already on the {course} team. Recheck the email address if you want to add a new member."), { - email: email, - course: libraryName - }, {interpolate: /\{(.+?)\}/g} - ), - actions: { - primary: { - text: gettext('Return to team listing'), - click: function(view) { view.hide(); $('#user-email-input').focus(); } - } - } - }); - msg.show(); - return; - } - - // Use the REST API to create the user, giving them a role of "library_user" for now: - changeRole( - $('#user-email-input').val().trim(), - 'library_user', - { - errMessage: gettext('Error adding user'), - onError: function() { $('#user-email-input').focus(); } - } - ); - }); - - $cancelButton = $createUserForm.find('.action-cancel'); - $cancelButton.on('click', function(event) { - event.preventDefault(); - $('.create-user-button').toggleClass('is-disabled'); - $createUserFormWrapper.toggleClass('is-shown'); - $('#user-email-input').val(''); - }); - - $('.create-user-button').on('click', function(event) { - event.preventDefault(); - $('.create-user-button').toggleClass('is-disabled'); - $createUserFormWrapper.toggleClass('is-shown'); - $createUserForm.find('#user-email-input').focus(); - }); - - $('body').on('keyup', function(event) { - if(event.which == jQuery.ui.keyCode.ESCAPE && $createUserFormWrapper.is('.is-shown')) { - $cancelButton.click(); - } - }); - - $('.remove-user').click(function() { - var email = $(this).closest('li[data-email]').data('email'), - msg = new PromptView.Warning({ - title: gettext('Are you sure?'), - message: _.template(gettext('Are you sure you want to delete {email} from the library “{library}”?'), {email: email, library: libraryName}, {interpolate: /\{(.+?)\}/g}), - actions: { - primary: { - text: gettext('Delete'), - click: function(view) { - // User the REST API to delete the user: - changeRole(email, null, { errMessage: gettext('Error removing user') }); - } - }, - secondary: { - text: gettext('Cancel'), - click: function(view) { view.hide(); } - } - } - }); - msg.show(); - }); - - $('.user-actions .make-instructor').click(function(event) { - event.preventDefault(); - var email = $(this).closest('li[data-email]').data('email'); - changeRole(email, 'instructor', {}); - }); - - $('.user-actions .make-staff').click(function(event) { - event.preventDefault(); - var email = $(this).closest('li[data-email]').data('email'); - changeRole(email, 'staff', {}); - }); - - $('.user-actions .make-user').click(function(event) { - event.preventDefault(); - var email = $(this).closest('li[data-email]').data('email'); - changeRole(email, 'library_user', {}); - }); - + var view = new ManageUsersAndRoles(options); + view.render(); }; }); diff --git a/cms/static/js/spec/views/pages/library_users_spec.js b/cms/static/js/spec/views/pages/library_users_spec.js index 8ec8721747..bf31d00144 100644 --- a/cms/static/js/spec/views/pages/library_users_spec.js +++ b/cms/static/js/spec/views/pages/library_users_spec.js @@ -5,76 +5,149 @@ define([ function ($, AjaxHelpers, ViewHelpers, ManageUsersFactory, ViewUtils) { "use strict"; describe("Library Instructor Access Page", function () { - var mockHTML = readFixtures('mock/mock-manage-users-lib.underscore'); + const changeRoleUrl = "dummy_change_role_url/@@EMAIL@@"; + var team_member_fixture = readFixtures("team-member.underscore"); + var systemFeedbackFixture = readFixtures("system-feedback.underscore"); - beforeEach(function () { - ViewHelpers.installMockAnalytics(); - appendSetFixtures(mockHTML); - ManageUsersFactory( - "Mock Library", - ["honor@example.com", "audit@example.com", "staff@example.com"], - "dummy_change_role_url" - ); + function setRole(email, role){ + var user_li = $("li.user-item[data-email="+ email + "]"); + var role_action = $("li.action-role a.make-"+role, user_li); + expect(role_action).toBeVisible(); + role_action.click(); + } + + function getUrl(email) { + return changeRoleUrl.replace('@@EMAIL@@', email); + } + + describe("read-write access", function() { + var mockHTML = readFixtures('mock/mock-manage-users-lib.underscore'); + + beforeEach(function () { + ViewHelpers.installMockAnalytics(); + setFixtures(mockHTML); + appendSetFixtures($(" +%block> <%block name="content"> @@ -44,7 +50,7 @@
Loading
+${_("Admins are course team members who can add and remove other course team members.")}
${_("Every course must have an Admin. If you're the Admin and you want transfer ownership of the course, click Add admin access to make another user the Admin, then ask that user to remove you from the Course Team list.")}
@@ -162,7 +108,13 @@ %block> <%block name="requirejs"> - require(["js/factories/manage_users"], function(ManageUsersFactory) { - ManageUsersFactory(${json.dumps([user.email for user in staff])}, "${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': unicode(context_course.id), 'email': '@@EMAIL@@'})}"); + require(["js/factories/manage_users"], function(ManageCourseUsersFactory) { + ManageCourseUsersFactory( + "${context_course.display_name | h}", + ${json.dumps(users)}, + "${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': unicode(context_course.id), 'email': '@@EMAIL@@'})}", + ${ request.user.id }, + ${str(allow_actions).lower()} + ); }); %block> diff --git a/cms/templates/manage_users_lib.html b/cms/templates/manage_users_lib.html index 8a4bb264be..2d40585775 100644 --- a/cms/templates/manage_users_lib.html +++ b/cms/templates/manage_users_lib.html @@ -5,6 +5,13 @@ <%def name="online_help_token()"><% return "team_library" %>%def> <%block name="title">${_("Library User Access")}%block> <%block name="bodyclass">is-signedin course users view-team%block> +<%namespace name='static' file='static_content.html'/> + +<%block name="header_extras"> + +%block> <%block name="content"> @@ -58,77 +65,13 @@Loading
+