Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
c78b84ca
Commit
c78b84ca
authored
Jul 12, 2017
by
Albert (AJ) St. Aubin
Committed by
GitHub
Jul 12, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #15480 from edx/staubina/ed-592
Staubina/ed 592
parents
1f6a4f22
b8b0110d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
131 additions
and
41 deletions
+131
-41
common/static/common/js/discussion/content.js
+1
-1
common/static/common/js/discussion/utils.js
+11
-1
common/static/common/js/discussion/views/discussion_content_view.js
+2
-1
lms/djangoapps/instructor/views/api.py
+14
-1
lms/static/js/instructor_dashboard/membership.js
+92
-25
lms/templates/instructor/instructor_dashboard_2/membership.html
+11
-12
No files found.
common/static/common/js/discussion/content.js
View file @
c78b84ca
...
...
@@ -122,7 +122,7 @@
userId
=
this
.
get
(
'user_id'
);
if
(
userId
)
{
this
.
set
(
'staff_authored'
,
DiscussionUtil
.
isStaff
(
userId
));
this
.
set
(
'community_ta_authored'
,
DiscussionUtil
.
isTA
(
userId
));
this
.
set
(
'community_ta_authored'
,
DiscussionUtil
.
isTA
(
userId
)
||
DiscussionUtil
.
isGroupTA
(
userId
)
);
}
else
{
this
.
set
(
'staff_authored'
,
false
);
this
.
set
(
'community_ta_authored'
,
false
);
...
...
common/static/common/js/discussion/utils.js
View file @
c78b84ca
/* globals $$course_id, Content, Markdown, MathJax, URI */
/* globals $$course_id, Content, Markdown, MathJax, URI
, _
*/
(
function
()
{
'use strict'
;
this
.
DiscussionUtil
=
(
function
()
{
...
...
@@ -41,6 +41,16 @@
return
_
.
include
(
ta
,
parseInt
(
userId
));
};
DiscussionUtil
.
isGroupTA
=
function
(
userId
)
{
var
groupTa
,
localUserId
=
userId
;
if
(
_
.
isUndefined
(
userId
))
{
localUserId
=
this
.
user
?
this
.
user
.
id
:
void
0
;
}
groupTa
=
_
.
union
(
this
.
roleIds
[
'Group Moderator'
]);
return
_
.
include
(
groupTa
,
parseInt
(
localUserId
,
10
));
};
DiscussionUtil
.
isPrivilegedUser
=
function
(
userId
)
{
return
this
.
isStaff
(
userId
)
||
this
.
isTA
(
userId
);
};
...
...
common/static/common/js/discussion/views/discussion_content_view.js
View file @
c78b84ca
...
...
@@ -508,7 +508,8 @@
return
_
.
template
(
$
(
'#post-user-display-template'
).
html
())({
username
:
endorsement
.
username
,
user_url
:
DiscussionUtil
.
urlFor
(
'user_profile'
,
endorsement
.
user_id
),
is_community_ta
:
DiscussionUtil
.
isTA
(
endorsement
.
user_id
),
is_community_ta
:
DiscussionUtil
.
isTA
(
endorsement
.
user_id
)
||
DiscussionUtil
.
isGroupTA
(
endorsement
.
user_id
),
is_staff
:
DiscussionUtil
.
isStaff
(
endorsement
.
user_id
)
});
}
else
{
...
...
lms/djangoapps/instructor/views/api.py
View file @
c78b84ca
...
...
@@ -45,7 +45,12 @@ from certificates.models import CertificateInvalidation, CertificateStatuses, Ce
from
courseware.access
import
has_access
from
courseware.courses
import
get_course_by_id
,
get_course_with_access
from
courseware.models
import
StudentModule
from
django_comment_client.utils
import
has_forum_access
from
django_comment_client.utils
import
(
has_forum_access
,
get_course_discussion_settings
,
get_group_name
,
get_group_id_for_user
)
from
django_comment_common.models
import
(
Role
,
FORUM_ROLE_ADMINISTRATOR
,
...
...
@@ -933,6 +938,7 @@ def list_course_role_members(request, course_id):
def
extract_user_info
(
user
):
""" convert user into dicts for json view """
return
{
'username'
:
user
.
username
,
'email'
:
user
.
email
,
...
...
@@ -2505,18 +2511,25 @@ def list_forum_members(request, course_id):
except
Role
.
DoesNotExist
:
users
=
[]
course_discussion_settings
=
get_course_discussion_settings
(
course_id
)
def
extract_user_info
(
user
):
""" Convert user to dict for json rendering. """
group_id
=
get_group_id_for_user
(
user
,
course_discussion_settings
)
group_name
=
get_group_name
(
group_id
,
course_discussion_settings
)
return
{
'username'
:
user
.
username
,
'email'
:
user
.
email
,
'first_name'
:
user
.
first_name
,
'last_name'
:
user
.
last_name
,
'group_name'
:
group_name
,
}
response_payload
=
{
'course_id'
:
course_id
.
to_deprecated_string
(),
rolename
:
map
(
extract_user_info
,
users
),
'division_scheme'
:
course_discussion_settings
.
division_scheme
,
}
return
JsonResponse
(
response_payload
)
...
...
lms/static/js/instructor_dashboard/membership.js
View file @
c78b84ca
...
...
@@ -12,7 +12,7 @@ such that the value can be defined later than this assignment (file load order).
(
function
()
{
'use strict'
;
var
AuthListWidget
,
BatchEnrollment
,
BetaTesterBulkAddition
,
MemberListWidget
,
Membership
,
emailStudents
,
plantTimeout
,
statusAjaxError
,
MemberListWidget
,
Membership
,
emailStudents
,
plantTimeout
,
statusAjaxError
,
enableAddButton
,
/* eslint-disable */
__hasProp
=
{}.
hasOwnProperty
,
__extends
=
function
(
child
,
parent
)
{
for
(
var
key
in
parent
)
{
if
(
__hasProp
.
call
(
parent
,
key
))
child
[
key
]
=
parent
[
key
];
}
function
ctor
()
{
this
.
constructor
=
child
;
}
ctor
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
ctor
();
child
.
__super__
=
parent
.
prototype
;
return
child
;
};
...
...
@@ -26,6 +26,18 @@ such that the value can be defined later than this assignment (file load order).
return
window
.
InstructorDashboard
.
util
.
statusAjaxError
.
apply
(
this
,
arguments
);
};
enableAddButton
=
function
(
enable
,
parent
)
{
var
$addButton
=
parent
.
$
(
'input[type="button"].add'
);
var
$addField
=
parent
.
$
(
'input[type="text"].add-field'
);
if
(
enable
)
{
$addButton
.
removeAttr
(
'disabled'
);
$addField
.
removeAttr
(
'disabled'
);
}
else
{
$addButton
.
attr
(
'disabled'
,
true
);
$addField
.
attr
(
'disabled'
,
true
);
}
};
emailStudents
=
false
;
MemberListWidget
=
(
function
()
{
...
...
@@ -92,17 +104,22 @@ such that the value can be defined later than this assignment (file load order).
__extends
(
AuthListWidget
,
_super
);
// eslint-disable-line no-use-before-define
function
AuthListWidget
(
$container
,
rolename
,
$errorSection
)
{
// eslint-disable-line no-shadow
var
msg
,
authlistwidget
=
this
;
authListWidget
=
this
,
labelsList
=
[
gettext
(
'Username'
),
gettext
(
'Email'
),
gettext
(
'Revoke access'
)];
this
.
rolename
=
rolename
;
this
.
$errorSection
=
$errorSection
;
this
.
list_enabled
=
true
;
if
(
this
.
rolename
===
'Group Moderator'
)
{
labelsList
=
[
gettext
(
'Username'
),
gettext
(
'Email'
),
gettext
(
'Group'
),
gettext
(
'Revoke access'
)];
}
AuthListWidget
.
__super__
.
constructor
.
call
(
this
,
$container
,
{
// eslint-disable-line no-underscore-dangle
title
:
$container
.
data
(
'display-name'
),
info
:
$container
.
data
(
'info-text'
),
labels
:
[
gettext
(
'Username'
),
gettext
(
'Email'
),
gettext
(
'Revoke access'
)]
,
labels
:
labelsList
,
add_placeholder
:
gettext
(
'Enter username or email'
),
add_btn_label
:
$container
.
data
(
'add-button-label'
),
add_handler
:
function
(
input
)
{
return
auth
listw
idget
.
add_handler
(
input
);
return
auth
ListW
idget
.
add_handler
(
input
);
}
});
this
.
debug
=
true
;
...
...
@@ -122,15 +139,15 @@ such that the value can be defined later than this assignment (file load order).
};
AuthListWidget
.
prototype
.
add_handler
=
function
(
input
)
{
var
auth
listwidgetaddh
andler
=
this
;
var
auth
ListWidgetAddH
andler
=
this
;
if
((
input
!=
null
)
&&
input
!==
''
)
{
return
this
.
modify_member_access
(
input
,
'allow'
,
function
(
error
)
{
if
(
error
!==
null
)
{
return
auth
listwidgetaddh
andler
.
show_errors
(
error
);
return
auth
ListWidgetAddH
andler
.
show_errors
(
error
);
}
auth
listwidgetaddh
andler
.
clear_errors
();
auth
listwidgetaddh
andler
.
clear_input
();
return
auth
listwidgetaddh
andler
.
reload_list
();
auth
ListWidgetAddH
andler
.
clear_errors
();
auth
ListWidgetAddH
andler
.
clear_input
();
return
auth
ListWidgetAddH
andler
.
reload_list
();
});
}
else
{
return
this
.
show_errors
(
gettext
(
'Please enter a username or email.'
));
...
...
@@ -138,43 +155,69 @@ such that the value can be defined later than this assignment (file load order).
};
AuthListWidget
.
prototype
.
reload_list
=
function
()
{
var
authlistwidgetreloadlist
=
this
;
return
this
.
get_member_list
(
function
(
error
,
memberList
)
{
var
authListWidgetReloadList
=
this
,
$selectedOption
;
return
this
.
get_member_list
(
function
(
error
,
memberList
,
divisionScheme
)
{
if
(
error
!==
null
)
{
return
authlistwidgetreloadlist
.
show_errors
(
error
);
authListWidgetReloadList
.
show_errors
(
error
);
return
;
}
authlistwidgetreloadlist
.
clear_rows
();
return
_
.
each
(
memberList
,
function
(
member
)
{
authListWidgetReloadList
.
clear_rows
();
_
.
each
(
memberList
,
function
(
member
)
{
var
$revokeBtn
,
labelTrans
;
labelTrans
=
gettext
(
'Revoke access'
);
$revokeBtn
=
$
(
_
.
template
(
'<div class="revoke"><span class="icon fa fa-times-circle" aria-hidden="true"></span> <%- label %></div>'
)({
// eslint-disable-line max-len
label
:
labelTrans
}),
{
class
:
'revoke'
});
$revokeBtn
.
click
(
function
()
{
return
authlistwidgetreloadl
ist
.
modify_member_access
(
member
.
email
,
'revoke'
,
function
(
err
)
{
authListWidgetReloadL
ist
.
modify_member_access
(
member
.
email
,
'revoke'
,
function
(
err
)
{
if
(
err
!==
null
)
{
return
authlistwidgetreloadlist
.
show_errors
(
err
);
authListWidgetReloadList
.
show_errors
(
err
);
return
;
}
auth
listwidgetreloadl
ist
.
clear_errors
();
return
authlistwidgetreloadl
ist
.
reload_list
();
auth
ListWidgetReloadL
ist
.
clear_errors
();
authListWidgetReloadL
ist
.
reload_list
();
});
});
return
authlistwidgetreloadlist
.
add_row
([
member
.
username
,
member
.
email
,
$revokeBtn
]);
if
(
authListWidgetReloadList
.
rolename
===
'Group Moderator'
)
{
if
(
divisionScheme
!==
undefined
&&
divisionScheme
===
'none'
)
{
// There is No discussion division scheme selected so the Group Moderator role
// should be disabled
authListWidgetReloadList
.
list_enabled
=
false
;
$selectedOption
=
$
(
'select#member-lists-selector'
).
children
(
'option:selected'
);
if
(
$selectedOption
[
0
].
value
===
authListWidgetReloadList
.
rolename
)
{
authListWidgetReloadList
.
show_errors
(
gettext
(
'This role requires a divided discussions scheme.'
)
);
enableAddButton
(
false
,
authListWidgetReloadList
);
}
}
else
{
authListWidgetReloadList
.
list_enabled
=
true
;
enableAddButton
(
true
,
authListWidgetReloadList
);
authListWidgetReloadList
.
add_row
([
member
.
username
,
member
.
email
,
member
.
group_name
,
$revokeBtn
]
);
}
}
else
{
authListWidgetReloadList
.
add_row
([
member
.
username
,
member
.
email
,
$revokeBtn
]);
}
});
});
};
AuthListWidget
.
prototype
.
clear_errors
=
function
()
{
var
re
f
,
re
sult
;
result
=
(
this
.
$error_section
)
!=
null
?
ref
.
text
(
''
)
:
undefined
;
var
result
;
result
=
this
.
$errorSection
!==
undefined
?
this
.
$errorSection
.
text
(
''
)
:
undefined
;
return
result
;
};
AuthListWidget
.
prototype
.
show_errors
=
function
(
msg
)
{
var
re
f
,
re
sult
;
result
=
(
this
.
$error_section
)
!=
null
?
ref
.
text
(
msg
)
:
undefined
;
var
result
;
result
=
this
.
$errorSection
!==
undefined
?
this
.
$errorSection
.
text
(
msg
)
:
undefined
;
return
result
;
};
...
...
@@ -188,7 +231,11 @@ such that the value can be defined later than this assignment (file load order).
rolename
:
this
.
rolename
},
success
:
function
(
data
)
{
return
typeof
cb
===
'function'
?
cb
(
null
,
data
[
authlistwidgetgetmemberlist
.
rolename
])
:
undefined
;
return
typeof
cb
===
'function'
?
cb
(
null
,
data
[
authlistwidgetgetmemberlist
.
rolename
],
data
.
division_scheme
)
:
undefined
;
}
});
};
...
...
@@ -933,6 +980,7 @@ such that the value can be defined later than this assignment (file load order).
this.$list_selector = this.$section.find('select#member-lists-selector');
this.$auth_list_containers = this.$section.find('.auth-list-container');
this.$auth_list_errors = this.$section.find('.member-lists-management .request-response-error');
this.auth_lists = _.map(this.$auth_list_containers, function(authListContainer) {
var rolename;
rolename = $(authListContainer).data('rolename');
...
...
@@ -944,6 +992,7 @@ such that the value can be defined later than this assignment (file load order).
authList = ref[i];
this.$list_selector.append($('<option/>', {
text: authList.$container.data('display-name'),
value: authList.rolename,
data: {
auth_list: authList
}
...
...
@@ -955,6 +1004,7 @@ such that the value can be defined later than this assignment (file load order).
this.$list_selector.change(function() {
var $opt, j, len1, ref1;
$opt = thismembership.$list_selector.children('option:selected');
if (!($opt.length > 0)) {
return;
}
...
...
@@ -966,11 +1016,28 @@ such that the value can be defined later than this assignment (file load order).
authList = $opt.data('auth_list');
authList.$container.addClass('active');
authList.re_view();
// On Change update the Group Moderation list
if ($opt[0].value === 'Group Moderator') {
if (!authList.list_enabled) {
authList.show_errors(gettext('This role requires a divided discussions scheme.'));
enableAddButton(false, authList);
} else {
enableAddButton(true, authList);
}
}
});
this.$list_selector.change();
}
membership.prototype.onClickTitle = function() {};
membership.prototype.onClickTitle = function() {
var list;
// When the title is clicked refresh all the authorization lists as the member list
// may have changed since render.
for (list = 0; list < this.auth_lists.length; list++) {
this.auth_lists[list].re_view();
}
};
return membership;
}());
...
...
lms/templates/instructor/instructor_dashboard_2/membership.html
View file @
c78b84ca
...
...
@@ -223,26 +223,25 @@ from openedx.core.djangolib.markup import HTML, Text
<div
class=
"auth-list-container"
data-rolename=
"Group Moderator"
data-display-name=
"${_("
Discussion
Group
Moderators
")}"
data-display-name=
"${_("
Group
Community
TA
")}"
data-info-text=
"
${_("
Discussion
Group
Moderators
can
edit
or
delete
any
post
,
clear
misuse
flags
,
close
"
"
and
re-open
threads
,
endorse
responses
,
and
see
posts
from
all
groups
.
"
"
Their
posts
are
marked
as
'
staff
'.
They
cannot
manage
course
team
membership
by
"
"
adding
or
removing
discussion
moderation
roles
.
Only
enrolled
users
can
be
"
"
added
as
Discussion
Moderator
s
.")}"
${_("
Group
Community
TAs
are
members
of
the
community
who
help
course
teams
moderate
discussions
.
Group
"
"
Community
TAs
see
only
posts
by
learners
in
their
assigned
group
.
They
can
edit
or
delete
posts
,
"
"
clear
flags
,
close
and
re-open
threads
,
and
endorse
responses
,
but
only
for
posts
by
learners
in
"
"
their
group
.
Their
posts
are
marked
as
'
Community
TA
'.
Only
enrolled
learners
can
be
added
as
Group
"
"
Community
TA
s
.")}"
data-list-endpoint=
"${ section_data['list_forum_members_url'] }"
data-modify-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
data-add-button-label=
"${_("
Add
Group
Moderator
")}"
data-add-button-label=
"${_("
Add
Group
Community
TA
")}"
></div>
<div
class=
"auth-list-container"
data-rolename=
"Community TA"
data-display-name=
"${_("
Discussion
Community
TAs
")}"
data-display-name=
"${_("
Community
TA
")}"
data-info-text=
"
${_("
Community
TAs
are
members
of
the
community
whom
you
deem
particularly
"
"
helpful
on
the
discussion
boards
.
They
can
edit
or
delete
any
post
,
clear
"
"
misuse
flags
,
close
and
re-open
threads
,
endorse
responses
,
and
see
posts
from
"
"
all
groups
.
Their
posts
are
marked
as
'
Community
TA
'.
Only
enrolled
users
can
"
${_("
Community
TAs
are
members
of
the
community
who
help
course
teams
moderate
discussions
.
"
"
They
can
see
posts
by
all
learners
,
and
can
edit
or
delete
posts
,
clear
flags
,
close
or
re-open
"
"
threads
,
and
endorse
responses
.
Their
posts
are
marked
as
'
Community
TA
'.
Only
enrolled
learners
can
"
"
be
added
as
Community
TAs
.")}"
data-list-endpoint=
"${ section_data['list_forum_members_url'] }"
data-modify-endpoint=
"${ section_data['update_forum_role_membership_url'] }"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment