Exemplo n.º 1
0
def remove(request, group_id, set_id):
    item_is_staff('group', request.user, group_id)

    tg_set = get_object_or_404(TaskGroupSet, task_group_id=group_id, pk=set_id)

    if tg_set.task_set.exists():
        messages.error(request, 'Task set can be deleted only if empty')
    else:
        messages.success(request, 'Task set deleted successfully')
        tg_set.delete()

    return redirect('staff_group_tasks', group_id=group_id)
Exemplo n.º 2
0
def publish_all(request, group_id, set_id):
    group, role = item_is_staff('group', request.user, group_id)

    rd = redirect('staff_group_tasks', group_id=group_id)

    if group.archived:
        messages.warning(request, 'Unable to publish tasks in archived group')
        return rd

    tg = get_object_or_404(TaskGroupSet, task_group_id=group_id, pk=set_id)
    tasks = tg.task_set.filter(published=False)

    if not tasks:
        messages.warning(request, 'There are no unpublished tasks in the set')
        return rd

    if request.POST:
        for task in tasks:
            task.published = True
            task.save()
        return rd

    context = {
        'title': 'Bulk publish',
        'bulk': True,
        'group': group,
        'tasks': tasks,
        'set_name': tg.name
    }

    return render(request, 'webapp/admin/task/publish.html', context)
Exemplo n.º 3
0
def create(request, group_id):
    group, role = item_is_staff('group', request.user, group_id)

    rd = redirect('staff_group_tasks', group_id=group_id)

    if group.archived:
        messages.warning(request, 'Set cannot be created in archived group')
        return rd

    if request.POST:
        instance = TaskGroupSet(task_group_id=group_id)
        form = TaskGroupSetForm(request.POST, instance=instance)
        if form.is_valid:
            form.save()
            messages.success(request, 'Task set is created successfully')
            return rd
        else:
            messages.error(request, 'Form was filled incorrectly')

    context = {
        'title': 'Create task set in {}'.format(group.name),
        'group': group,
        'form': TaskGroupSetForm()
    }
    return render(request, 'webapp/admin/group/taskset/actions.html', context)
Exemplo n.º 4
0
def edit(request, group_id, set_id):
    group, role = item_is_staff('group', request.user, group_id)

    rd = redirect('staff_group_tasks', group_id=group_id)

    if group.archived:
        messages.warning(request, 'Set in the archived group cannot be edited')
        return rd

    task_set = get_object_or_404(TaskGroupSet,
                                 task_group_id=group_id,
                                 pk=set_id)

    form = TaskGroupSetForm(instance=task_set)

    if request.POST:
        form = TaskGroupSetForm(request.POST, instance=task_set)
        if form.is_valid:
            form.save()
            messages.success(request, 'Changes saved')
            return rd
        else:
            messages.error(request, 'Form was filled incorrectly')

    context = {
        'group': group,
        'set': task_set,
        'title': 'Edit task set {}'.format(task_set.name),
        'form': form
    }
    return render(request, 'webapp/admin/group/taskset/actions.html', context)
    pass
Exemplo n.º 5
0
def create(request, group_id, set_id):
    group, role = item_is_staff('group', request.user, group_id)

    rd = redirect('staff_group_tasks', group_id=group_id)

    if group.archived:
        messages.warning(request, 'Task cannot be added to archived group.')
        return rd

    try:
        task_set = TaskGroupSet.objects.get(pk=set_id)
    except TaskGroupSet.DoesNotExist:
        messages.warning(request,
                         'Task cannot be added to nonexistent task set.')
        return rd

    if request.method == 'POST':
        instance = Task(owner=request.user, task_group=group, tg_set=task_set)
        form = TaskForm(request.POST, request.FILES, instance=instance)
        if form.is_valid():
            form.save()
            return rd
        messages.error(request, 'Form was filled incorrectly')
    else:
        form = TaskForm()

    context = {
        'form': form,
        'group': group,
        'set': task_set,
        'title': 'Create task'
    }
    return render(request, 'webapp/admin/task/actions.html', context)
Exemplo n.º 6
0
def list_user(request, task_id, user_id):
    task, role = item_is_staff('task', request.user, task_id)
    user = get_object_or_404(User, pk=user_id)

    evaluations = SubmissionEvaluation.objects.select_related(
        'submission').filter(
            submission__user_id=user_id,
            submission__task_id=task_id).order_by('submission__submitted')

    context = {
        'title':
        'Submissions of {} {} on {}'.format(short_name(user.first_name),
                                            user.last_name, task.name),
        'task':
        task,
        'group':
        task.task_group,
        'user':
        user,
        'evaluations':
        evaluations
    }

    return render(request, 'webapp/admin/submission/list_user_task.html',
                  context)
Exemplo n.º 7
0
def publish(request, task_id):
    task, role = item_is_staff('task', request.user, task_id)

    if task.published:
        messages.warning(request, 'This task is already published')

    elif task.task_group.archived:
        messages.warning(
            request,
            'The group, to which this task belongs is archived. Task cannot be published'
        )

    elif request.method == 'POST':
        task.published = True
        task.save()
        messages.success(request, 'Task was published successfully.')

    else:
        return render(
            request, 'webapp/admin/task/publish.html', {
                'task': task,
                'group': task.task_group,
                'title': 'Publish ' + task.name
            })

    return redirect('staff_task_details', task_id=task.id)
Exemplo n.º 8
0
def copy(request, group_id):
    group, role = item_is_staff('group', request.user, group_id)

    if request.POST:
        form = CopyTaskGroup(request.POST)
        if form.is_valid():
            new_group = TaskGroup.objects.create(
                name=form.cleaned_data['name'],
                description=form.cleaned_data['description'])
            new_group.save()
            # creating access to the new group
            try:
                provider_id = request.user.casusermeta.ext_id
            except CASUserMeta.DoesNotExist:
                provider_id = None

            access = TaskGroupAccess(user=request.user,
                                     role='owner',
                                     task_group=new_group,
                                     provider_id=provider_id)
            access.save()

            for tg_set in TaskGroupSet.objects.filter(task_group=group):
                tasks = Task.objects.filter(task_group=group, tg_set=tg_set)
                tg_set.pk = None  # reset pk so that insert will be performed instead of update
                tg_set.task_group = new_group
                tg_set.save()
                for task in tasks:
                    task.pk = None  # reset pk
                    task.deadline = None
                    task.published = False
                    task.archived = False
                    task.task_group = new_group
                    task.tg_set = tg_set  # new TaskGroupSet
                    task.save()

            messages.success(request, 'Group was copied successfully')
            return redirect('staff_group_tasks', group_id=new_group.pk)
        else:
            messages.error(request, 'Please fill in the new group name')
            return redirect('staff_group_copy', group_id=group_id)

    context = {
        'group':
        group,
        'tasks':
        Task.objects.filter(task_group=group),
        'title':
        group.name + ' copy',
        'form':
        CopyTaskGroup(initial={
            'name': group.name,
            'description': group.description
        })
    }

    return render(request, 'webapp/admin/group/copy.html', context)
Exemplo n.º 9
0
def deadlines(request, group_id):
    group, role = item_is_staff('group', request.user, group_id)

    if group.archived:
        messages.warning(
            request,
            'Group is archived, setting bulk deadlines is not possible.')
        return redirect('staff_group_tasks', group_id=group_id)

    formset = formset_factory(TaskGroupBulkDeadlines, extra=0)

    if request.POST:
        forms = formset(request.POST)
        if forms.is_valid():
            filled = False
            for data in forms.cleaned_data:
                if data['deadline']:
                    filled = True
                    for task in Task.objects.filter(tg_set=data['set_id']):
                        task.deadline = data['deadline']
                        task.save()
            if filled:
                messages.success(request, 'Changes applied')
                return redirect('staff_group_tasks', group_id=group_id)
            else:
                messages.warning(request, 'No changes were made')
                return redirect('staff_group_deadlines', group_id=group_id)
    else:
        initial_data = []

        for item in [
                st for st in TaskGroupSet.objects.filter(task_group=group)
                if st.task_set.exists()
        ]:
            initial_data.append({
                'set_id':
                item.id,
                'set_name':
                item.name[:20] + (item.name[20:] and '...')
            })

        forms = formset(initial=initial_data)

    context = {
        'group': group,
        'forms': forms,
        'title': 'Set bulk deadlines for {}'.format(group.name)
    }

    return render(request, 'webapp/admin/group/deadlines.html', context)
Exemplo n.º 10
0
def item_archive(request, item_name, item_id):
    item, role = item_is_staff(item_name, request.user, item_id)

    if request.method == 'POST':
        item.archived = not item.archived
        item.save()
        return redirect('staff_task_details', task_id=item_id) \
            if item_name == 'task' else redirect('staff_group_tasks', group_id=item_id)

    return render(request, 'webapp/admin/item_archive.html', {
        'item_name': item_name,
        'item': item,
        'title': 'Unarchive ' if item.archived else 'Archive ' + item.name
    })
Exemplo n.º 11
0
def perform_action(request, s_uuid, action):
    try:
        submission = Submission.objects.get(uuid=s_uuid)
        task, role = item_is_staff('task', request.user, submission.task_id)
    except (Submission.DoesNotExist, ValueError):
        messages.warning(request, 'Unable to find submission with given uuid.')
        return redirect('staff_dashboard')

    # pass redirect argument if existent
    redirect_to = request.GET.get('next') if request.GET.get('next') else \
        reverse('staff_submission_report', args=[submission.uuid])

    if action not in ['reevaluate', 'validate', 'invalidate']:
        messages.warning(request, 'Invalid action')
        return redirect(redirect_to)

    return submission_operation_create(request.user, action, [s_uuid], task.id,
                                       redirect_to, False)
Exemplo n.º 12
0
def task_list(request, group_id):
    group, role = item_is_staff('group', request.user, group_id)

    context = {
        'user_role':
        role,
        'group':
        group,
        'sets': [
            dict(id=tg_set.id,
                 name=tg_set.name,
                 description=tg_set.description,
                 tasks=tg_set.task_set.filter(task_group=group),
                 has_unpublished=tg_set.task_set.filter(
                     task_group=group, published=False).exists())
            for tg_set in TaskGroupSet.objects.filter(task_group=group)
        ],
        'title':
        group.name + ' task list'
    }
    return render(request, 'webapp/admin/group/index.html', context)
Exemplo n.º 13
0
def item_edit(request, item_name, item_id):
    item, role = item_is_staff(item_name, request.user, item_id)

    context = {
        'title': 'Edit ' + item.name
    }

    if item_name == 'group':
        form_object = TaskGroupForm
        context['group'] = item
        rd = redirect('staff_group_tasks', group_id=item_id)
    else:
        form_object = TaskForm
        context['group'] = item.task_group
        context['task'] = item
        rd = redirect('staff_task_details', task_id=item_id)

    if item.archived or (item.task_group.archived if hasattr(item, 'task_group') else False):
        messages.warning(request, 'Archived {} cannot be edited'.format(item_name))
        return rd

    if request.method == 'POST':
        if item_name == 'group':
            form = form_object(request.POST, instance=item)
        else:
            form = form_object(request.POST, request.FILES, edit=1, instance=item)

        if form.is_valid():
            form.save()
            messages.success(request, 'Changes saved successfully')
            return rd
        else:
            messages.error(request, 'Form was filled incorrectly')
    else:
        form = form_object(instance=item, edit=1)

    context['form'] = form

    return render(request, 'webapp/admin/{}/actions.html'.format(item_name), context)
Exemplo n.º 14
0
def list_all(request, task_id):
    task, role = item_is_staff('task', request.user, task_id)

    evaluations = SubmissionEvaluation.objects.select_related(
        'submission',
        'submission__user').filter(submission__task_id=task_id).annotate(
            best=RawSQL(
                '''dense_rank() over(partition by webapp_submission.user_id
        order by webapp_submissionevaluation.score desc, webapp_submission.submitted desc)''',
                []),
            latest=RawSQL(
                '''dense_rank() over(partition by webapp_submission.user_id
        order by webapp_submission.submitted desc)''',
                [])).order_by('-submission__submitted')

    context = {
        'title': 'Submissions to {}'.format(task.name),
        'task': task,
        'group': task.task_group,
        'evaluations': evaluations
    }

    if request.POST:
        s_ids = []
        action = request.POST.get('action')
        if action and action in ['reevaluate', 'invalidate', 'validate']:
            objects = build_http_array(request.POST, 'submission')
            for index in objects:
                s_ids.append(objects[index]['uuid'])

            redirect_to = reverse('staff_task_submissions_all', args=[task_id])
            return submission_operation_create(request.user, action, s_ids,
                                               task_id, redirect_to)
        else:
            messages.warning(
                request, 'Action parameter was not received or is invalid')

    return render(request, 'webapp/admin/submission/list_all.html', context)
Exemplo n.º 15
0
def user_reports(request, group_id, user_id):
    group, role = item_is_staff('group', request.user, group_id)

    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        messages.warning(request, 'User with given ID does not exist')
        return redirect('staff_group_tasks', group_id=group_id)

    evaluations = SubmissionEvaluation.objects.filter(
        submission__user=user,
        submission__task__task_group_id=group_id).select_related(
            'submission', ).annotate(
                task_name=F('submission__task__name'),
                set_name=F('submission__task__tg_set__name'),
                best=RawSQL(
                    '''dense_rank() over(partition by webapp_submission.task_id
        order by webapp_submissionevaluation.score desc, webapp_submission.submitted desc)''',
                    []),
                latest=RawSQL(
                    '''dense_rank() over(partition by webapp_submission.task_id
        order by webapp_submission.submitted desc)''',
                    [])).order_by('-submission__submitted')

    context = {
        'title':
        'Submissions from {} to group {}'.format(user.last_name, group.name),
        'group':
        group,
        'user':
        user,
        'evaluations':
        evaluations
    }

    return render(request, 'webapp/admin/submission/list_user_group.html',
                  context)
Exemplo n.º 16
0
def details(request, task_id):
    task, role = item_is_staff('task', request.user, task_id)

    ids = SubmissionEvaluation.objects.annotate(rank=RawSQL(
        '''dense_rank() over(partition by webapp_submission.user_id
        order by {}webapp_submission.submitted desc)'''.format(
            'webapp_submissionevaluation.score desc, ' if task.result_type ==
            'best' else ''), [])).values(
                'id', 'rank', 'status', 'received', 'worker_took_time',
                'submission__submitted').filter(submission__task_id=task_id,
                                                is_invalid=False)

    results = SubmissionEvaluation.objects.select_related(
        'submission',
        'submission__user').filter(pk__in=(pk['id'] for pk in ids
                                           if pk['rank'] == 1)).order_by(
                                               '-score',
                                               'submission__submitted')

    # separating staff and user submissions
    staff_members = task.task_group.taskgroupaccess_set.filter(~Q(
        role='user')).values_list('user_id', flat=True)
    d_results = []
    s_results = []

    for r in results:
        if r.submission.user_id in staff_members:
            d_results.append(r)
        else:
            s_results.append(r)

    # gathering stats
    stats = {
        'avg_check_time': 'n/a',
        'avg_wait_time': 'n/a',
        'avg_score': '0.0',
        'sbm_count': 0
    }

    total_check = 0
    total_wait = 0
    index = 0
    for i in ids:
        try:
            if i['status'] == 'ok' and i['worker_took_time'] is not None:
                worker_took = i[
                    'worker_took_time'] / 1000  # ms to seconds without loosing precision
                total_check += worker_took
                # wait time is calculated by subtracting submit unix time and worker_took_time assuming remaining
                # time gap to be the time spent in queue
                total_wait += (i['received'] - i['submission__submitted']
                               ).total_seconds() - worker_took
                index += 1
        except KeyError:
            pass

    if index > 0:
        stats['avg_check_time'] = format_int(round(total_check / index))
        stats['avg_wait_time'] = format_int(round(total_wait / index))

    if s_results:
        stats.update(
            SubmissionEvaluation.objects.filter(
                pk__in=(pk.id for pk in s_results)).aggregate(
                    avg_score=Avg(F('score')), sbm_count=Count(F('score'))))

    context = {
        'title': 'Task: ' + task.name,
        'task': task,
        'group': task.task_group,
        'pack_url': get_package_link(task),
        'are_results': len(ids) > 0,
        's_results': s_results,
        'd_results': d_results,
        'stats': stats,
    }
    return render(request, 'webapp/admin/task/index.html', context)
Exemplo n.º 17
0
def operation_handle(request, task_id, sop_uuid):
    task, role = item_is_staff('task', request.user, task_id)

    # set redirect targets
    redirect_to = request.GET.get('next')
    self_rd = redirect('staff_task_operation_handle',
                       sop_uuid=sop_uuid,
                       task_id=task_id)

    if redirect_to:
        rd = HttpResponseRedirect(redirect_to)
        self_rd['Location'] += '?next={}'.format(redirect_to)
    else:
        rd = redirect('staff_task_submissions_all', task_id=task_id)

    # SubmissionOperation's task_id must correspond to the given task_id
    try:
        op = SubmissionOperation.objects.get(pk=sop_uuid, task_id=task_id)
    except (SubmissionOperation.DoesNotExist, ValueError):
        messages.error(request, 'The operation cannot be found')
        return rd

    # here we also select only submissions with evaluations and those which belong to the task
    try:
        evaluations = SubmissionEvaluation.objects.filter(
            submission__pk__in=json.loads(op.submission_list),
            submission__task_id=task_id).select_related(
                'submission', 'submission__user')
    except ValueError:
        messages.error(request, 'The operation is invalid')
        op.delete()
        return rd

    if not evaluations:
        if op.is_bulk:
            message = 'You have to select at least one submission in order to perform any action.'
        else:
            message = 'The operation cannot be performed. (no submission received)'

        messages.warning(request, message)
        op.delete()
        return rd

    if op.has_started:
        if op.action == 'reevaluate':
            extra = json.loads(op.extra)
            if not len(extra):
                messages.error(
                    request,
                    'The operation cannot be performed. (no pending submissions received)'
                )
                op.delete()
                return rd

            try:
                pending_submissions = Submission.objects.select_related(
                    'user').filter(pk__in=extra)
            except ValueError:
                messages.error(
                    request,
                    'The operation cannot be performed. (no valid pending submissions received)'
                )
                op.delete()
                return rd

            context = {
                'task':
                task,
                'group':
                task.task_group,
                'role':
                role,
                'submissions':
                pending_submissions,
                'title':
                'Re-evaluating submission{}'.format('s' if op.is_bulk else ''),
                'tokens': {},
                'old_scores': {},
                'bulk':
                op.is_bulk
            }

            for e in evaluations:
                context['old_scores'][e.submission_id] = e.score

            signer = TimestampSigner()

            for ps in pending_submissions:
                context['tokens'][ps.uuid] = signer.sign(ps.uuid)

            return render(request, 'webapp/admin/submission/reevaluation.html',
                          context)

        elif op.action == 'invalidate' or op.action == 'validate':
            messages.warning(request,
                             'This operation has already been invoked.')
            return rd
        else:
            messages.error(
                request, 'The operation cannot be performed. (invalid action)')
            op.delete()
            return rd
    else:
        if request.POST:
            if request.POST.get('cancel-action') == '1':  # action cancelled
                op.delete()
                return rd
            # confirmation received:
            if op.action == 'reevaluate':
                pending = []
                for evaluation in evaluations:
                    old_submission = evaluation.submission
                    files = SubmissionFile.objects.filter(
                        submission=old_submission)

                    new_s = Submission.objects.create(
                        uuid=str(uuid.uuid4()),
                        user=evaluation.submission.user,
                        task=task,
                        reevaluated=True,
                        copy_of=old_submission,
                        invoked_by=request.user,
                        queue_priority="low")

                    pending.append(str(new_s.uuid))

                    for file in files:
                        SubmissionFile.objects.create(submission=new_s,
                                                      name=file.name,
                                                      contents=file.contents)

                    try:
                        upload_submission(new_s)
                    except redis.exceptions.RedisError:
                        new_s.delete()
                        op.delete()
                        return render(request, 'webapp/submit_fail.html',
                                      {'task': task})

                op.has_started = True
                op.extra = json.dumps(pending)
                op.save()

                return self_rd

            elif op.action == 'invalidate':
                form = InvalidateSubmissionForm(request.POST)
                if form.is_valid():
                    evaluation_set_validity(evaluations, False,
                                            form.cleaned_data['comment'],
                                            request.user.id)
                else:
                    messages.error(
                        request, 'Please fill in the reason of invalidation.')
                    return self_rd

            elif op.action == 'validate':
                evaluation_set_validity(evaluations, True)
            else:
                messages.error(
                    request,
                    'The operation cannot be performed. (invalid action)')
                op.delete()
                return rd

            op.has_started = True
            op.save()
            return rd
        else:  # ask for a confirmation
            if op.action == 'invalidate' or op.action == 'validate':
                evaluations = evaluations.filter(
                    is_invalid=False if op.action == 'invalidate' else True)
                if not evaluations:
                    messages.warning(
                        request, '{} submission{} already {}'.format(
                            'Selected' if op.is_bulk else 'This',
                            's are' if op.is_bulk else ' is', 'invalid'
                            if op.action == 'invalidate' else 'valid'))
                    op.delete()
                    return rd

            context = {
                'title': 'Confirm operation',
                'evaluations': evaluations,
                'task': task,
                'group': task.task_group,
                'op': op,
                'form': InvalidateSubmissionForm()
            }

            return render(request, 'webapp/admin/task/confirm_operation.html',
                          context)