def post(self): course = self.request.get('course') try: data = json.loads(self.request.get('data')) except ValueError: data = None if not course or not data: return self.response.set_status(202) # Create Evals if data['instructor']: for ta in data['tas']: Eval.create(course, ta, data['instructor']) data['instructor'] = None # Create Invites tas = [ta['name'] for ta in data['tas']] for student in data['students'][:]: try: EvalInvite.create(course, student, tas) except DeadlineExceededError: # Need to test this data = json.dumps(data) taskqueue.add(url='/admin/init', params={'course': course, 'data': data}) return self.response.set_status(200) data['students'].remove(student) return self.response.set_status(201)
def get(self, key, ta='', responses=None, success=None, errors=None): invite = EvalInvite.get_by_key_name(key) if not invite: return self.redirect('/') settings = Settings.get_by_key_name('settings') invite.expired = datetime.datetime.now() > settings.expire_date success = success or [] errors = errors or [] remaining = invite.remaining_evals() if not remaining and not invite.tas: if settings.send_completed_email: body = const.COMPLETED_EMAIL_TEMPLATE.format(invite.name) try: to_email = '{} <{}>'.format(invite.name, invite.email) mail.send_mail(settings.admin_email, to_email, const.COMPLETED_EMAIL_SUBJECT, body) except apiproxy_errors.OverQuotaError as message: logging.error(message) completed = Completed(name=invite.name, email=invite.email) completed.put() invite.delete() questions = None else: if not responses: responses = [''] * len(const.QUESTIONS) questions = zip(const.QUESTIONS, responses) values = {'invite': invite, 'success': success, 'errors': errors, 'sel_ta': ta, 'questions': questions, 'remaining': remaining} template = jinja_environment.get_template('eval.html') self.response.out.write(template.render(values))
def reset(self): if self.request.get('confirm') != '0xDEADBEEF': self.get(errors=['Invalid confirmation']) else: keys = [x for x in EvalInvite.all(keys_only=True)] keys.extend([x for x in Eval.all(keys_only=True)]) keys.extend([x for x in Completed.all(keys_only=True)]) for i in range(int(math.ceil(len(keys) * 1. / MAX_DELETES))): db.delete(keys[i * MAX_DELETES:(i + 1) * MAX_DELETES]) self.get(successes=['Reset Database'])
def get(self, successes=None, warnings=None, errors=None): courses = {} # Remaining Evaluations for invite in EvalInvite.all(): if invite.course not in courses: courses[invite.course] = {} for ta in invite.tas: if ta in courses[invite.course]: courses[invite.course][ta].remaining += 1 else: courses[invite.course][ta] = helpers.Dummy( remaining=1, completed=0, sent_results=None) # Completed Evaluations for evaluation in Eval.all(): completed = sum(evaluation.get_responses()[0]) tas = courses[evaluation.course] if evaluation.ta in tas: tas[evaluation.ta].completed = completed tas[evaluation.ta].sent_results = evaluation.sent_results else: tas[evaluation.ta] = helpers.Dummy( completed=completed, remaining=0, sent_results=evaluation.sent_results) form_token, cookie = helpers.generate_validation_token() self.response.headers.add_header('Set-Cookie', cookie) successes = helpers.nsorted(successes) if successes else [] warnings = helpers.nsorted(warnings) if warnings else [] errors = helpers.nsorted(errors) if errors else [] courses = [(x, sorted(courses[x].items())) for x in helpers.nsorted(courses)] # Initialize settings if not already set user = users.get_current_user() admin_email = 'Computer Science Lead TA <{}>'.format(user.email()) now = datetime.datetime.now() expire_date = now + datetime.timedelta(days=5) settings = Settings.get_or_insert('settings', admin_email=admin_email, expire_date=expire_date) if settings.expire_date < now: remaining_time = str(datetime.timedelta()) else: remaining_time = str(settings.expire_date - now) values = {'successes': successes, 'warnings': warnings, 'errors': errors, 'courses': courses, 'form_token': form_token, 'eval_time': remaining_time} template = jinja_environment.get_template('admin.html') self.response.out.write(template.render(values))
def post(self, key): invite = EvalInvite.get_by_key_name(key) if not invite: return self.redirect('/') settings = Settings.get_by_key_name('settings') if datetime.datetime.now() > settings.expire_date: return self.get(key) ta = self.request.get('ta') if ta not in invite.tas: return self.get(key, errors=('Must select a TA to evaluate',)) if self.request.get('not_applicable'): success = 'Not Applicable: {}'.format(ta) else: errors = [] responses = self.get_responses() for i in range(len(const.QUESTIONS)): if i >= len(responses): responses.append('') continue if const.QUESTIONS[i][1] in [0, 1]: if responses[i] not in ['0', '1', '2', '3', '4', '5']: responses[i] = '' errors.append('Must provide an answer for {!r}'.format( const.QUESTIONS[i][0])) if errors: return self.get(key, ta, responses, errors=errors) try: db.run_in_transaction(Eval.update, invite.course, ta, responses) except apiproxy_errors.RequestTooLargeError: return self.get(key, ta, responses, errors=('Your response is too long',)) success = 'Evaluated: {}'.format(ta) # Remove TA from list of TAs student can evaluate invite.tas.remove(ta) invite.put() self.get(key, success=success)