def test_get_instructor_task_history(self): # when fetching historical tasks, we get all tasks, including running tasks expected_ids = [] for _ in range(1, 5): expected_ids.append(self._create_failure_entry().task_id) expected_ids.append(self._create_success_entry().task_id) expected_ids.append(self._create_progress_entry().task_id) task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history(TEST_COURSE_ID, problem_url=self.problem_url)] self.assertEquals(set(task_ids), set(expected_ids)) # make the same call using explicit task_type: task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history( TEST_COURSE_ID, problem_url=self.problem_url, task_type='rescore_problem' )] self.assertEquals(set(task_ids), set(expected_ids)) # make the same call using a non-existent task_type: task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history( TEST_COURSE_ID, problem_url=self.problem_url, task_type='dummy_type' )] self.assertEquals(set(task_ids), set())
def test_get_instructor_task_history(self): # when fetching historical tasks, we get all tasks, including running tasks expected_ids = [] for _ in range(1, 5): expected_ids.append(self._create_failure_entry().task_id) expected_ids.append(self._create_success_entry().task_id) expected_ids.append(self._create_progress_entry().task_id) task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history(TEST_COURSE_KEY, usage_key=self.problem_url)] self.assertEquals(set(task_ids), set(expected_ids)) # make the same call using explicit task_type: task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history( TEST_COURSE_KEY, usage_key=self.problem_url, task_type='rescore_problem' )] self.assertEquals(set(task_ids), set(expected_ids)) # make the same call using a non-existent task_type: task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history( TEST_COURSE_KEY, usage_key=self.problem_url, task_type='dummy_type' )] self.assertEquals(set(task_ids), set())
def certificate_dashboard(request, course_key_string): """Certificate management dashboard for the support team.""" course_key = get_course_key(course_key_string) course = get_course(course_key_string) if course is None: raise Http404 # generate list of pending background tasks and filter the output task_types = ['certificate-generation', 'verified-certificate-generation'] instructor_tasks = filter_instructor_task( get_running_instructor_tasks(course_key, task_types)) # Get list of tasks sorted by decreasing id instructor_tasks_history = [] for task_type in task_types: instructor_tasks_history += list( filter_instructor_task( get_instructor_task_history(course_key, task_type=task_type, usage_key=None, student=None))) instructor_tasks_history.sort(key=lambda x: -x.id) return render( request, 'backoffice/certificate.html', { 'course': course, 'certificates_directory': settings.CERTIFICATES_DIRECTORY_NAME, 'instructor_tasks': instructor_tasks, 'instructor_tasks_history': instructor_tasks_history, })
def certificate_dashboard(request, course_key_string): """Certificate management dashboard for the support team.""" course_key = get_course_key(course_key_string) course = get_course(course_key_string) if course is None: raise Http404 # generate list of pending background tasks and filter the output task_types = ['certificate-generation', 'verified-certificate-generation'] instructor_tasks = filter_instructor_task( get_running_instructor_tasks(course_key, task_types) ) # Get list of tasks sorted by decreasing id instructor_tasks_history = [] for task_type in task_types: instructor_tasks_history += list(filter_instructor_task( get_instructor_task_history( course_key, task_type=task_type, usage_key=None, student=None) )) instructor_tasks_history.sort(key=lambda x: -x.id) return render(request, 'backoffice/certificate.html', { 'course': course, 'certificate_base_url': settings.CERTIFICATE_BASE_URL, 'instructor_tasks': instructor_tasks, 'instructor_tasks_history': instructor_tasks_history, })
def test_get_instructor_task_history(self): # when fetching historical tasks, we get all tasks, including running tasks expected_ids = [] for _ in range(1, 5): expected_ids.append(self._create_failure_entry().task_id) expected_ids.append(self._create_success_entry().task_id) expected_ids.append(self._create_progress_entry().task_id) task_ids = [instructor_task.task_id for instructor_task in get_instructor_task_history(TEST_COURSE_ID, self.problem_url)] self.assertEquals(set(task_ids), set(expected_ids))
def test_get_instructor_task_history(self): # when fetching historical tasks, we get all tasks, including running tasks expected_ids = [] for _ in range(1, 5): expected_ids.append(self._create_failure_entry().task_id) expected_ids.append(self._create_success_entry().task_id) expected_ids.append(self._create_progress_entry().task_id) task_ids = [ instructor_task.task_id for instructor_task in get_instructor_task_history( TEST_COURSE_ID, self.problem_url) ] self.assertEquals(set(task_ids), set(expected_ids))
def certificate_dashboard(request, course_key_string): """ Will display . Two panels, pending and previous certificate generation tasks. . Two buttons : one two generate a test certificate and the other to trigger a certificate generation task. """ # TODO: only one function that return both the course and the course_key course_key = get_course_key(course_key_string) course = get_course(course_key_string) # generate list of pending background tasks and filter the output instructor_tasks = filter_instructor_task(get_running_instructor_tasks(course_key, task_type='certificate-generation')) instructor_tasks_history = filter_instructor_task(get_instructor_task_history(course_key, task_type='certificate-generation', usage_key=None, student=None)) return render(request, 'backoffice/certificate.html', { 'course': course, 'certificate_base_url' : settings.CERTIFICATE_BASE_URL, 'instructor_tasks' : instructor_tasks, 'instructor_tasks_history' : instructor_tasks_history, })
def get_background_task_table(course_key, problem_url=None, student=None, task_type=None): """ Construct the "datatable" structure to represent background task history. Filters the background task history to the specified course and problem. If a student is provided, filters to only those tasks for which that student was specified. Returns a tuple of (msg, datatable), where the msg is a possible error message, and the datatable is the datatable to be used for display. """ history_entries = get_instructor_task_history(course_key, problem_url, student, task_type) datatable = {} msg = "" # first check to see if there is any history at all # (note that we don't have to check that the arguments are valid; it # just won't find any entries.) if (history_entries.count()) == 0: if problem_url is None: msg += '<font color="red">Failed to find any background tasks for course "{course}".</font>'.format( course=course_key.to_deprecated_string() ) elif student is not None: template = '<font color="red">' + _('Failed to find any background tasks for course "{course}", module "{problem}" and student "{student}".') + '</font>' msg += template.format(course=course_key.to_deprecated_string(), problem=problem_url, student=student.username) else: msg += '<font color="red">' + _('Failed to find any background tasks for course "{course}" and module "{problem}".').format( course=course_key.to_deprecated_string(), problem=problem_url ) + '</font>' else: datatable['header'] = ["Task Type", "Task Id", "Requester", "Submitted", "Duration (sec)", "Task State", "Task Status", "Task Output"] datatable['data'] = [] for instructor_task in history_entries: # get duration info, if known: duration_sec = 'unknown' if hasattr(instructor_task, 'task_output') and instructor_task.task_output is not None: task_output = json.loads(instructor_task.task_output) if 'duration_ms' in task_output: duration_sec = int(task_output['duration_ms'] / 1000.0) # get progress status message: success, task_message = get_task_completion_info(instructor_task) status = "Complete" if success else "Incomplete" # generate row for this task: row = [ str(instructor_task.task_type), str(instructor_task.task_id), str(instructor_task.requester), instructor_task.created.isoformat(' '), duration_sec, str(instructor_task.task_state), status, task_message ] datatable['data'].append(row) if problem_url is None: datatable['title'] = "{course_id}".format(course_id=course_key.to_deprecated_string()) elif student is not None: datatable['title'] = "{course_id} > {location} > {student}".format( course_id=course_key.to_deprecated_string(), location=problem_url, student=student.username ) else: datatable['title'] = "{course_id} > {location}".format( course_id=course_key.to_deprecated_string(), location=problem_url ) return msg, datatable