manage_users.html 13.4 KB
Newer Older
1
<%! import json %>
David Baumgold committed
2
<%! from django.utils.translation import ugettext as _ %>
3
<%! from django.core.urlresolvers import reverse %>
4
<%! from student.roles import CourseInstructorRole %>
5
<%inherit file="base.html" />
Mark Hoeber committed
6
<%def name="online_help_token()"><% return "team" %></%def>
David Baumgold committed
7
<%block name="title">${_("Course Team Settings")}</%block>
8
<%block name="bodyclass">is-signedin course users view-team</%block>
9

10
<%block name="content">
11

12
<div class="wrapper-mast wrapper">
13
  <header class="mast has-actions has-subtitle">
Brian Talbot committed
14
    <h1 class="page-header">
Mark L. Chang committed
15
      <small class="subtitle">${_("Settings")}</small>
David Baumgold committed
16
      <span class="sr">&gt; </span>${_("Course Team")}
Brian Talbot committed
17
    </h1>
18 19

    <nav class="nav-actions">
David Baumgold committed
20
      <h3 class="sr">${_("Page Actions")}</h3>
21 22 23
      <ul>
        %if allow_actions:
        <li class="nav-item">
24
          <a href="#" class="button new-button create-user-button"><i class="icon-plus"></i> ${_("New Team Member")}</a>
25 26 27 28 29 30 31
        </li>
        %endif
      </ul>
    </nav>
  </header>
</div>

32 33 34
<div class="wrapper-content wrapper">
  <section class="content">
    <article class="content-primary" role="main">
35
      %if allow_actions:
36
      <div class="wrapper-create-element animate wrapper-create-user">
Mathew Peterson committed
37
        <form class="form-create create-user" id="create-user-form" name="create-user-form">
38 39 40 41
          <div class="wrapper-form">
            <h3 class="title">${_("Add a User to Your Course's Team")}</h3>

            <fieldset class="form-fields">
42
              <legend class="sr">${_("New Team Member Information")}</legend>
43

44 45 46
                <ol class="list-input">
                  <li class="field text required create-user-email">
                    <label for="user-email-input">${_("User's Email Address")}</label>
47
                    <input id="user-email-input" name="user-email" type="text" placeholder="${_('example: username@domain.com')}" value="">
48 49 50 51 52
                    <span class="tip tip-stacked">${_("Please provide the email address of the course staff member you'd like to add")}</span>
                  </li>
                </ol>
            </fieldset>
          </div>
53

54 55 56 57 58 59
          <div class="actions">
            <button class="action action-primary" type="submit">${_("Add User")}</button>
            <button class="action action-secondary action-cancel">${_("Cancel")}</button>
          </div>
        </form>
      </div>
60
      %endif
61 62 63

      <ol class="user-list">
        % for user in staff:
64 65 66 67 68
          <% course_team_url = reverse(
             'contentstore.views.course_team_handler',
             kwargs={'course_key_string': unicode(context_course.id), 'email': user.email}
          )
          %>
69

70
        <li class="user-item" data-email="${user.email}" data-url="${course_team_url}">
71

72
        <% is_instuctor = CourseInstructorRole(context_course.id).has_user(user) %>
73
          % if is_instuctor:
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
          <span class="wrapper-ui-badge">
            <span class="flag flag-role flag-role-admin is-hanging">
              <span class="label sr">${_("Current Role:")}</span>
              <span class="value">
                ${_("Admin")}
                % if request.user.id == user.id:
                    <span class="msg-you">${_("You!")}</span>
                % endif
              </span>
            </span>
          </span>
          % else:
          <span class="wrapper-ui-badge">
            <span class="flag flag-role flag-role-staff is-hanging">
              <span class="label sr">${_("Current Role:")}</span>
              <span class="value">
                ${_("Staff")}
                % if request.user.id == user.id:
                    <span class="msg-you">${_("You!")}</span>
                % endif
              </span>
            </span>
          </span>
          % endif

          <div class="item-metadata">
            <h3 class="user-name">
              <span class="user-username">${user.username}</span>
              <span class="user-email">
David Baumgold committed
103
                <a class="action action-email" href="mailto:${user.email}" title="${_("send an email message to {email}").format(email=user.email)}">${user.email}</a>
104 105 106 107 108 109 110
              </span>
            </h3>
          </div>

          % if allow_actions:
          <ul  class="item-actions user-actions">
            <li class="action action-role">
111
              % if is_instuctor and len(instructors) == 1:
Mark L. Chang committed
112
                <span class="admin-role notoggleforyou">${_("Promote another member to Admin to remove your admin rights")}</span>
113
              % else:
114
                <a href="#" class="admin-role toggle-admin-role ${'remove' if is_instuctor else 'add'}-admin-role">${_("Remove Admin Access") if is_instuctor else _("Add Admin Access")}</a>
115
              % endif
116
            </li>
117
            <li class="action action-delete ${"is-disabled" if request.user.id == user.id else ""}">
David Baumgold committed
118
                <a href="#" class="delete remove-user action-icon" data-id="${user.email}"><i class="icon-trash"></i><span class="sr">${_("Delete the user, {username}").format(username=user.username)}</span></a>
119 120 121 122 123 124 125
            </li>
          </ul>
          % endif

        </li>
        % endfor
      </ol>
126

127
      <% user_is_instuctor = CourseInstructorRole(context_course.id).has_user(request.user) %>
128
      % if user_is_instuctor and len(staff) == 1:
129 130 131 132
      <div class="notice notice-incontext notice-create has-actions">
        <div class="msg">
          <h3 class="title">${_('Add Team Members to This Course')}</h3>
          <div class="copy">
Mark L. Chang committed
133
            <p>${_('Adding team members makes course authoring collaborative. Users must be signed up for Studio and have an active account. ')}</p>
134 135 136 137 138 139 140 141 142 143
          </div>
        </div>

        <ul class="list-actions">
          <li class="action-item">
            <a href="#" class="action action-primary button new-button create-user-button"><i class="icon-plus icon-inline"></i> ${_('Add a New Team Member')}</a>
          </li>
        </ul>
      </div>
      %endif
144
    </article>
145 146 147

    <aside class="content-supplementary" role="complimentary">
      <div class="bit">
148 149
        <h3 class="title-3">${_("Course Team Roles")}</h3>
        <p>${_("Course team members, or staff, are course co-authors. They have full writing and editing privileges on all course content.")}</p>
Mathew Peterson committed
150
        <p>${_("Admins are course team members who can add and remove other course team members.")}</p>
151 152
      </div>

153
      % if user_is_instuctor and len(instructors) == 1:
154
      <div class="bit">
155 156
        <h3 class="title-3">${_("Transferring Ownership")}</h3>
        <p>${_("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.")}</p>
157 158 159 160
      </div>
      % endif
    </aside>
  </section>
161
</div>
162
</%block>
163 164 165

<%block name="jsextra">
<script type="text/javascript">
166 167 168
require(["jquery", "underscore", "gettext", "js/views/feedback_prompt"],
    function($, _, gettext, PromptView) {

169
  var staffEmails = ${json.dumps([user.email for user in staff])};
170
  var tplUserURL = "${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': unicode(context_course.id), 'email': '@@EMAIL@@'})}"
171 172

  var unknownErrorMessage = gettext("Unknown");
173

David Baumgold committed
174
  $(document).ready(function() {
175 176 177
    var $createUserForm = $('#create-user-form');
    var $createUserFormWrapper = $createUserForm.closest('.wrapper-create-user');
    $createUserForm.bind('submit', function(e) {
David Baumgold committed
178
      e.preventDefault();
179 180
      var email = $('#user-email-input').val().trim();
      if(!email) {
181
        var msg = new PromptView.Error({
182 183
          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"),
184 185
          actions: {
            primary: {
186
              text: gettext("Return and add email address"),
187 188 189 190 191 192 193 194 195 196 197
              click: function(view) {
                view.hide();
                $("#user-email-input").focus();
              }
            }
          }
        })
        msg.show();
        return;
      }
      if(_.contains(staffEmails, email)) {
198
        var msg = new PromptView.Warning({
199
          title: gettext("Already a course team member"),
200
          message: _.template(gettext("{email} is already on the “{course}” team. If you're trying to add a new member, please double-check the email address you provided."), {email: email, course: course.escape('name')}, {interpolate: /\{(.+?)\}/g}),
201 202
          actions: {
            primary: {
203
              text: gettext("Return to team listing"),
204 205 206 207 208 209 210 211 212 213
              click: function(view) {
                view.hide();
                $("#user-email-input").focus();
              }
            }
          }
        })
        msg.show();
        return;
      }
214
      var url = tplUserURL.replace("@@EMAIL@@", $('#user-email-input').val().trim())
David Baumgold committed
215
      $.ajax({
216
        url: url,
David Baumgold committed
217 218 219
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
220
        data: JSON.stringify({
221
          role: 'staff',
222
        }),
David Baumgold committed
223 224 225 226 227
        success: function(data) {
          location.reload();
        },
        notifyOnError: false,
        error: function(jqXHR, textStatus, errorThrown) {
228 229
          var message;
          try {
230
            message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage;
231
          } catch (e) {
232
            message = unknownErrorMessage
233
          }
234
          var prompt = new PromptView.Error({
235 236 237 238 239 240 241 242 243 244 245 246 247
            title: gettext("Error adding user"),
            message: message,
            actions: {
              primary: {
                text: gettext("OK"),
                click: function(view) {
                  view.hide();
                  $("#user-email-input").focus()
                }
              }
            }
          })
          prompt.show();
David Baumgold committed
248 249 250
        }
      });
    });
251

252
    var $cancelButton = $createUserForm.find('.action-cancel');
David Baumgold committed
253 254
    $cancelButton.bind('click', function(e) {
      e.preventDefault();
255
      $('.create-user-button').toggleClass('is-disabled');
256
      $createUserFormWrapper.toggleClass('is-shown');
257
      $('#user-email-input').val('');
David Baumgold committed
258
    });
259

260
    $('.create-user-button').bind('click', function(e) {
David Baumgold committed
261
      e.preventDefault();
262
      $('.create-user-button').toggleClass('is-disabled');
263 264
      $createUserFormWrapper.toggleClass('is-shown');
      $createUserForm.find('#user-email-input').focus();
David Baumgold committed
265
    });
266

David Baumgold committed
267 268 269
    $('body').bind('keyup', function(e) {
      if(e.which == 27) {
        $cancelButton.click();
270
      }
271
    });
272

273
    $('.remove-user').click(function() {
274
      var email = $(this).data('id');
275
      var msg = new PromptView.Warning({
276
        title: gettext("Are you sure?"),
277
        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}),
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
        actions: {
          primary: {
            text: gettext("Delete"),
            click: function(view) {
              view.hide();
              var url = tplUserURL.replace("@@EMAIL@@", email)
              $.ajax({
                url: url,
                type: 'DELETE',
                dataType: 'json',
                contentType: 'application/json',
                success: function(data) {
                  location.reload();
                },
                notifyOnError: false,
                error: function(jqXHR, textStatus, errorThrown) {
                  var message;
                  try {
296
                    message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage;
297
                  } catch (e) {
298
                    message = unknownErrorMessage;
299
                  }
300
                  var prompt = new PromptView.Error({
301 302 303 304 305 306 307 308 309 310 311 312
                    title: gettext("Error removing user"),
                    message: message,
                    actions: {
                      primary: {
                        text: gettext("OK"),
                        click: function(view) {
                          view.hide();
                        }
                      }
                    }
                  })
                  prompt.show();
313
                }
314
              });
315
            }
316 317 318 319 320 321 322
          },
          secondary: {
            text: gettext("Cancel"),
            click: function(view) {
              view.hide();
            }
          }
David Baumgold committed
323 324
        }
      });
325
      msg.show();
326
    });
327

328
    $(".toggle-admin-role").click(function(e) {
329 330
      e.preventDefault()
      var type;
331
      if($(this).hasClass("add-admin-role")) {
332
        role = 'instructor';
333
      } else {
334
        role = 'staff';
335
      }
336
      var url = $(this).closest("li[data-url]").data("url");
337 338
      $.ajax({
        url: url,
339
        type: 'POST',
340 341 342
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify({
343
          role: role
344
        }),
345
        success: function(data) {
346
          location.reload();
347 348 349 350 351
        },
        notifyOnError: false,
        error: function(jqXHR, textStatus, errorThrown) {
          var message;
          try {
352
            message = JSON.parse(jqXHR.responseText).error || unknownErrorMessage;
353
          } catch (e) {
354
            message = unknownErrorMessage;
355
          }
356
          var prompt = new PromptView.Error({
357
            title: gettext("There was an error changing the user's role"),
358 359 360
            message: message,
            actions: {
              primary: {
361
                text: gettext("Try Again"),
362 363 364 365 366 367 368
                click: function(view) {
                  view.hide();
                }
              }
            }
          })
          prompt.show();
369 370 371 372
        }
      })
    })

373
  });
374
});
375
</script>
Lyla Fischer committed
376
</%block>