diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py
index 02a91e7d84de..89bbd95b728c 100644
--- a/lms/djangoapps/instructor/views/api.py
+++ b/lms/djangoapps/instructor/views/api.py
@@ -2308,6 +2308,7 @@ def _list_instructor_tasks(request, course_id):
Internal function with common code for both DRF and and tradition views.
"""
+ include_canvas = request.GET.get('include_canvas') is not None
course_id = CourseKey.from_string(course_id)
params = getattr(request, 'query_params', request.POST)
problem_location_str = strip_if_string(params.get('problem_location_str', False))
@@ -2331,6 +2332,11 @@ def _list_instructor_tasks(request, course_id):
else:
# Specifying for single problem's history
tasks = task_api.get_instructor_task_history(course_id, module_state_key)
+ elif include_canvas:
+ tasks = task_api.get_running_instructor_canvas_tasks(
+ course_id,
+ user=request.user
+ )
else:
# If no problem or student, just get currently running tasks
tasks = task_api.get_running_instructor_tasks(course_id)
diff --git a/lms/djangoapps/instructor_task/api.py b/lms/djangoapps/instructor_task/api.py
index 62095c3ae3aa..f66995eb8b0e 100644
--- a/lms/djangoapps/instructor_task/api.py
+++ b/lms/djangoapps/instructor_task/api.py
@@ -75,6 +75,34 @@ def get_running_instructor_tasks(course_id):
return instructor_tasks.order_by('-id')
+def _get_filtered_instructor_tasks(course_id, user, task_types):
+ """
+ Returns a filtered query of InstructorTasks based on the course, user, and desired task types
+ """
+ instructor_tasks = get_running_instructor_tasks(course_id)
+ now = datetime.datetime.now(pytz.utc)
+ filtered_tasks = InstructorTask.objects.filter(
+ course_id=course_id,
+ task_type__in=task_types,
+ updated__lte=now,
+ updated__gte=now - datetime.timedelta(days=2),
+ requester=user
+ ).order_by('-updated')
+
+ return (instructor_tasks | filtered_tasks).distinct()[0:3]
+
+
+def get_running_instructor_canvas_tasks(course_id, user):
+ """
+ Returns a query of InstructorTask objects of running tasks for a given course
+ including canvas-specific tasks.
+ """
+ # Inline import because we will install the plugin separately
+ from ol_openedx_canvas_integration.constants import CANVAS_TASK_TYPES # pylint: disable=import-error
+
+ return _get_filtered_instructor_tasks(course_id, user, CANVAS_TASK_TYPES)
+
+
def get_instructor_task_history(course_id, usage_key=None, student=None, task_type=None):
"""
Returns a query of InstructorTask objects of historical tasks for a given course,
diff --git a/lms/djangoapps/instructor_task/views.py b/lms/djangoapps/instructor_task/views.py
index 51e2812577fe..f21f21d4a631 100644
--- a/lms/djangoapps/instructor_task/views.py
+++ b/lms/djangoapps/instructor_task/views.py
@@ -138,7 +138,9 @@ def get_task_completion_info(instructor_task): # lint-amnesty, pylint: disable=
student = None
problem_url = None
+ entrance_exam_url = None
email_id = None
+ course_id = None
try:
task_input = json.loads(instructor_task.task_input)
except ValueError:
@@ -149,6 +151,7 @@ def get_task_completion_info(instructor_task): # lint-amnesty, pylint: disable=
problem_url = task_input.get('problem_url')
entrance_exam_url = task_input.get('entrance_exam_url')
email_id = task_input.get('email_id')
+ course_id = task_input.get('course_key')
if instructor_task.task_state == PROGRESS:
# special message for providing progress updates:
@@ -192,6 +195,17 @@ def get_task_completion_info(instructor_task): # lint-amnesty, pylint: disable=
else: # num_succeeded < num_attempted
# Translators: {action} is a past-tense verb that is localized separately. {succeeded} and {attempted} are counts. # lint-amnesty, pylint: disable=line-too-long
msg_format = _("Problem {action} for {succeeded} of {attempted} students")
+ elif course_id is not None:
+ # this reports on actions for a course as a whole
+ results = task_output.get('results', {})
+ assignments_count = results.get("assignments", 0)
+ grades_count = results.get("grades", 0)
+
+ msg_format = _("{grades_count} grades and {assignments_count} assignments updated or created").format(
+ grades_count=grades_count,
+ assignments_count=assignments_count,
+ )
+ succeeded = True
elif email_id is not None:
# this reports on actions on bulk emails
if num_attempted == 0:
diff --git a/lms/static/js/instructor_dashboard/instructor_dashboard.js b/lms/static/js/instructor_dashboard/instructor_dashboard.js
index 02972a93b6c4..d1dbb4f5183a 100644
--- a/lms/static/js/instructor_dashboard/instructor_dashboard.js
+++ b/lms/static/js/instructor_dashboard/instructor_dashboard.js
@@ -170,6 +170,9 @@ such that the value can be defined later than this assignment (file load order).
}, {
constructor: window.InstructorDashboard.sections.ECommerce,
$element: idashContent.find('.' + CSS_IDASH_SECTION + '#e-commerce')
+ }, {
+ constructor: window.InstructorDashboard.sections.CanvasIntegration,
+ $element: idashContent.find('.' + CSS_IDASH_SECTION + '#canvas_integration')
}, {
constructor: window.InstructorDashboard.sections.Membership,
$element: idashContent.find('.' + CSS_IDASH_SECTION + '#membership')
diff --git a/lms/static/js/instructor_dashboard/util.js b/lms/static/js/instructor_dashboard/util.js
index 8e39f4d03e66..1c8d4e00c1e5 100644
--- a/lms/static/js/instructor_dashboard/util.js
+++ b/lms/static/js/instructor_dashboard/util.js
@@ -51,7 +51,8 @@
enableColumnReorder: false,
autoHeight: true,
rowHeight: 100,
- forceFitColumns: true
+ forceFitColumns: true,
+ enableTextSelectionOnCells: true
};
columns = [
{
@@ -98,7 +99,14 @@
*/
name: gettext('Submitted'),
- minWidth: 120
+ minWidth: 120,
+ formatter: function(row, cell, value) {
+ if (!value) {
+ return value
+ }
+ var fromNow = moment(value).fromNow()
+ return value.concat("
(", fromNow, ")")
+ }
}, {
id: 'duration_sec',
field: 'duration_sec',
@@ -492,7 +500,8 @@
enableCellNavigation: true,
enableColumnReorder: false,
rowHeight: 30,
- forceFitColumns: true
+ forceFitColumns: true,
+ enableTextSelectionOnCells: true
};
columns = [
{
diff --git a/lms/templates/instructor/instructor_dashboard_2/html-datatable.underscore b/lms/templates/instructor/instructor_dashboard_2/html-datatable.underscore
new file mode 100644
index 000000000000..89da91b17881
--- /dev/null
+++ b/lms/templates/instructor/instructor_dashboard_2/html-datatable.underscore
@@ -0,0 +1,16 @@
+
+
<%- h %> | + <%})%> +
---|
<%- value %> | + <%})%> +