Beispiel #1
0
def new_user(get, guts):
    if get:
        template = get_template("new_user.html")
        return TemplateResponse(template, {"form": NewUserForm()})
    else:
        if not guts.user.is_superuser:
            return ForbiddenResponse(
                "Only administrators may create new accounts.")
        f = NewUserForm(guts.parameters)
        if f.is_valid():
            frm = settings.EMAIL_FROM
            current_site = Site.objects.get_current()
            subject = "New %s Account Created" % current_site.name
            base = "https://%s" % current_site.domain

            cleaned = f.cleaned_data
            password = User.objects.make_random_password()
            if cleaned["username"]:
                username = cleaned["username"]
            else:
                ## peel off the part before the @
                ## and then translate non-alpha-numeric characters to underscores
                username = re.sub(r'\W', '_', cleaned["email"].split("@",
                                                                     1)[0])
            u = User.objects.create_user(username, cleaned["email"], password)
            u.first_name = cleaned["first_name"]
            u.last_name = cleaned["last_name"]
            u.save()

            send_mail(
                subject,
                """An account has been created for you on the %s system.

Login information:

    Username: %s
    Password: %s

Login to change your password:

    %s/user_management/

If you have any problems logging in, please email us for assistance at:

  %s

    """ % (current_site.name, username, password, base, frm),
                frm,
                [cleaned['email']],
            )

            u.save()
            template = get_template("new_user_created.html")
            return TemplateResponse(template, {
                'username': username,
                'password': password
            })
        else:
            template = get_template("new_user.html")
            return TemplateResponse("new_user.html", {'form': NewUserForm()})
Beispiel #2
0
def track_page_visit(get, guts):
    if get:
        form = PageTrackForm()
        return TemplateResponse(page_track_template, {"form": form})
    else:
        if guts.user.is_superuser:
            form = PageTrackForm(guts.parameters)
            if form.is_valid():
                url = form.cleaned_data["url"]
                view, view_args, view_kwargs = resolve(urlparse(url).path)
                print(repr(form.cleaned_data), file=sys.stderr)
                pt = PageTrack(
                    user=form.cleaned_data["user"],
                    view_name=view.__name__,
                    view_args=repr(view_args),
                    view_kwargs=repr(view_kwargs),
                    focus_time=form.cleaned_data["focus_time"],
                )
                if "blur_time" in form.cleaned_data:
                    pt.blur_time = form.cleaned_data["blur_time"]
                pt.full_clean()
                pt.save()
                new_form = PageTrackForm()
                return TemplateResponse(page_track_template, {
                    "form": new_form,
                    "pt": pt
                })
            else:
                return TemplateResponse(page_track_template, {"form": form})
        else:
            return ForbiddenResponse("Only superusers may use this form.")
Beispiel #3
0
def timesheet(guts):
    """Generate a TimeChart object from the given spec parameters and
    then translate it into a viewable format."""
    if guts.user.is_staff:
        template = get_template("timesheet.html")
        if all([
                p in guts.parameters
                for p in ("resolution", "periods", "ending_date")
        ]):
            form = TimesheetForm(guts.parameters)
        else:
            form = TimesheetForm()
        if form.is_bound and form.is_valid():
            resolution = form.cleaned_data["resolution"]
            periods = form.cleaned_data["periods"]
            spec = TimeBlockSpec(resolution, periods,
                                 form.cleaned_data["ending_date"])
            users = set(form.cleaned_data["users"])
            for group in form.cleaned_data["groups"]:
                for user in group.user_set.all():
                    users.add(user)
            chart = TimeChart(spec, users)
            rows = []
            for (uid, bins_by_block) in six.iteritems(chart.report):
                user = User.objects.get(pk=uid)
                cells = []
                for block in spec:
                    if block in bins_by_block:
                        cells.append(bins_by_block[block].as_dict())
                    else:
                        cells.append({"data_sets": [], "work_time": 0})
                rows.append({"user": user.username, "cells": cells})
            headers = [str(block) for block in spec]
            return TemplateResponse(
                template,
                {
                    "form": form,
                    "headers": headers,
                    "rows": sorted(rows, key=lambda r: r["user"]),
                    "resolution": resolution,
                    "periods": periods,
                },
            )
        else:
            return TemplateResponse(template, {"form": form})
    else:
        return ForbiddenResponse(
            "The timesheet pages are only accessible to staff.")
Beispiel #4
0
def home(guts):
    """Manage the display of the homepage. Currently returns a count for
       the number of resolvable tasks.
       
       Template data should include the counts of tasks the user can
       annotate or merge.
       """
    site_messages = Announcement.objects.filter(enabled=True)
    respondable_tasks = Task.objects.can_annotate(guts.user)
    resolvable_tasks = Task.objects.can_merge(guts.user)
    recent_responses = Response.objects.filter(
        user=guts.user).order_by('-end_time')[0:5]
    recent_results = Result.objects.filter(
        user=guts.user).order_by('-end_time')[0:5]
    reviews = Review.objects.filter(complete=False, response__user=guts.user)
    if "visitable_pages" not in guts.session:
        guts.session["visitable_pages"] = visitable(guts.user)
    template = get_template("home.html")
    return TemplateResponse(
        template,
        {
            'respondable_tasks': respondable_tasks,
            'respondable_task_count': respondable_tasks.count(),
            'resolvable_tasks': resolvable_tasks,
            'resolvable_task_count': resolvable_tasks.count(),
            'recent_responses': recent_responses,
            'recent_results': recent_results,
            'reviews': reviews,
            "pages": guts.session["visitable_pages"],
            "messages": site_messages,
        },
    )
Beispiel #5
0
def one_group(guts, group_id):
    """Summarize information about one group."""
    if guts.user.is_superuser:
        group = get_object_or_404(Group, pk=group_id)
        users = [
            u.username for u in group.user_set.order_by("username")
            if u.is_active
        ]
        emails = [
            u.email for u in group.user_set.order_by("username") if u.is_active
        ]
        annotates = [{
            "title": p.title,
            "id": p.id
        } for p in group.annotator_for.order_by("title")]
        merges = [{
            "title": p.title,
            "id": p.id
        } for p in group.merger_for.order_by("title")]
        template = get_template("group.html")
        return TemplateResponse(
            template,
            {
                "id": group_id,
                "name": group.name,
                "users": users,
                "annotates": annotates,
                "merges": merges,
                "emails": emails,
            },
        )
    else:
        return ForbiddenResponse("Only administrators can see this page.")
Beispiel #6
0
def task_adhoc_review(get, guts):
    if get:
        response_id = guts.parameters['response']
        response = Response.objects.get(pk=response_id)
        reviews = Review.objects.filter(response=response)
        if reviews.count() == 1:
            review = reviews[0]
        else:
            review = Review(response=response, comment="")
        task = response.task
        result = task.result
        # Tagger or merger can both view, as well as super-user
        if ((response.user != guts.user) and not (guts.user.is_superuser)
                and (result.user != guts.user)):
            return ForbiddenResponse(
                "You are not authorized to see this review.")
        project_type = get_project_type(task.project)
        task = project_type.cast(task)
        try:
            template = get_template(review.review_template)
        except NotImplementedError:
            template = task.template()
        template_data = task.template_data(review=review)
        return TemplateResponse(template, template_data)
    else:
        return ViewResponse('main:next-review')
Beispiel #7
0
def task_review(get, guts, review_id):
    """Present an interface to request the user to review 
       a given task."""
    review = get_object_or_404(Review, pk=review_id)
    response = review.response
    ## NOTE: an earlier version of this code would throw a Review.DoesNotExist exception
    ## if the Review object with the right id and user had complete=True.  I don't see
    ## the harm in re-reviewing so I am not checking for that here.
    if (response.user != guts.user) and not (guts.user.is_superuser or get):
        return ForbiddenResponse("You are not authorized to see this review.")
    if get:
        task = response.task
        project_type = get_project_type(task.project)
        task = project_type.cast(task)
        try:
            template = get_template(review.review_template)
        except NotImplementedError:
            template = task.template()
        template_data = task.template_data(review=review)
        return TemplateResponse(template, template_data)
    else:
        review.complete = True
        review.full_clean()
        review.save()
        return ViewResponse('main:next-review')
Beispiel #8
0
def all_projects_brief(guts):
    """Summarize the active projects, whose tags match the filters in
    the query parameter, more succinctly."""
    def extended_dict(project):
        d = project.as_dict()
        d["priority_display"] = project.get_priority_display()
        d["remaining_to_tag"] = project.task_set.filter(
            completed=False).count()
        d["remaining_to_merge"] = project.task_set.filter(
            completed=True, result__isnull=True).count()
        d["merged"] = project.task_set.filter(completed=True,
                                              result__isnull=False).count()
        return d

    if guts.user.is_superuser:
        filter_tags = guts.parameters.getlist("filter")
        qs = projects_query_set(filter_tags)
        data = {
            "project_list": [extended_dict(p) for p in qs],
            "available_tags": [tag for tag in ProjectTag.objects.all()],
            "selected_tags": filter_tags,
        }
        template = get_template("brief-overview.html")
        return TemplateResponse(template, data)
    else:
        return ForbiddenResponse("Only administrators can see this page.")
Beispiel #9
0
def wip_review(get, guts):
    if guts.user.is_superuser:
        wips = WorkInProgress.objects.all()
    elif Project.objects.filter(admin=guts.user).count():
        wips = WorkInProgress.objects.filter(task__project__admin=guts.user)
    else:
        return ForbiddenResponse(
            "Only project administrators and superusers may see this page.")
    if get:
        wip_list = [{
            "id": wip.id,
            "user": wip.user.username,
            "task_id": wip.task.id,
            "task_url": wip.task.get_absolute_url(),
            "project_id": wip.task.project.id,
            "project_name": wip.task.project.title,
            "project_url": wip.task.project.get_absolute_url(),
            "start_time": wip.start_time,
        } for wip in wips.order_by("-start_time")]
        template_data = {"wips": wip_list}
        template = get_template("wip-review.html")
        return TemplateResponse(template, template_data)
    else:
        try:
            wips_to_delete = [
                wips.get(pk=pk)
                for pk in guts.parameters.getlist("wips_to_delete")
            ]
            for wip in wips_to_delete:
                wip.delete()
            return ViewResponse('main:wip-list')
        except WorkInProgress.DoesNotExist:
            return ForbiddenResponse("You can only delete a project "
                                     "that you are an admin for.")
Beispiel #10
0
def project_upload(get, guts, project):
    """Take an upload, and queue it for running through the task processor.
    
    # TODO: Testing
    # TODO: Return something better than the current Upload complete response. (template)
    # TODO: fix allowing user to select project form a dropdown (project is in the URL).
    # TODO: only allow certain users to upload projects
    """
    ptype = get_project_type(project)
    project = ptype.cast(project)
    if get:
        template = get_template("project/upload_form.html")
        return TemplateResponse(template, {"form": UploadForm()})
    else:
        action = guts.parameters["action"]
        if action == "Upload":
            pu = ProjectUpload(project=project)
            item = UploadForm(guts.parameters, guts.files, instance=pu)
            if item.is_valid():
                item.save()
                if not hasattr(settings,
                               "PROCESS_INLINE") or settings.PROCESS_INLINE:
                    project.handle_input(pu)
                    if project.auto_review:
                        project.add_auto_reviews()
                    pu.complete = True
                    pu.save()
                    message = (
                        "Upload complete to project %s, tasks processed" %
                        project.id)
                else:
                    message = "Upload complete, queued as %s" % pu.id
                guts.log_info(message)
                return DefaultResponse(message)
            else:
                ## re-present the page with input errors marked
                template = get_template("project/upload_form.html")
                return TemplateResponse(template, {"form": item})
        elif action == "Empty":
            ## NOTE: if subclasses have customized the delete() method,
            ## this bulk-delete will not call it.
            Task.objects.filter(project=project).delete()
            return ViewResponse('main:view-project', project.id)
        else:
            return ErrorResponse("Bad form",
                                 "Action parameter %s not understood" % action)
Beispiel #11
0
def project_stats(guts, project):
    user_response_counts = (Response.objects.filter(
        task__project=project).values("user__username").annotate(Count("id")))
    template = get_template("project/stats.html")
    return TemplateResponse(template, {
        'user_response_counts': user_response_counts,
        'project': project
    })
Beispiel #12
0
def abandon_wip(get, guts):
    """A view to abandon a WIP. When GETting this page, the user sees
    the \"are you sure?\" page.  When POSTing, the first WIP that the
    user has is deleted.
    """
    if get:
        wips = WorkInProgress.objects.filter(user=guts.user)
        template = get_template("abandon_wip.html")
        return TemplateResponse(template, {'wips': wips})
    else:
        wips = WorkInProgress.objects.filter(user=guts.user)
        if wips.count():
            wip = wips[0]
            wip.delete()
            return ViewResponse('main:home')
        else:
            template = get_template("abandon_wip.html")
            return TemplateResponse(template, {"wips": wips})
Beispiel #13
0
def all_users(guts):
    """Summarize information about all users."""
    if guts.user.is_superuser:
        users = [{
            "name": u.username,
            "is_superuser": u.is_superuser,
            "annotated": u.response_set.count(),
            "merged": u.result_set.count(),
        } for u in User.objects.order_by("username") if u.is_active]
        template = get_template("users.html")
        return TemplateResponse(template, {"users": users})
    else:
        return ForbiddenResponse("Only administrators can see this page.")
Beispiel #14
0
def all_projects(guts):
    """Summarize the status of the active projects whose tags match
    the filters in the query parameter."""
    if guts.user.is_superuser:
        qs = projects_query_set(guts.parameters.getlist("filter"))
        cache = dict([(g.id,
                       [u.username for u in g.user_set.all() if u.is_active])
                      for g in Group.objects.all()])
        result = {"project_list": [project_info(p, cache) for p in qs]}
        template = get_template("overview.html")
        return TemplateResponse(template, result)
    else:
        return ForbiddenResponse("Only administrators can see this page.")
Beispiel #15
0
def project_agreement(guts, project):
    ptype = get_project_type(project)
    if not hasattr(ptype, 'test_agreement'):
        return DefaultResponse("Project doesn't support testing agreement.")

    same_counts = {}
    tasks = project.task_set.filter(completed=True).all()
    for t in tasks:
        responses = t.response_set.all()
        same = ptype.test_agreement(responses)
        same_counts[same] = same_counts.setdefault(same, 0) + 1
    template = get_template('project/agreement.html')
    print(same_counts)  ## TODO: is this leftover debugging code?
    return TemplateResponse(template, {
        'counts': same_counts,
        'task_count': tasks.count()
    })
Beispiel #16
0
def all_groups(guts):
    """Summarize information about all the groups in the database."""
    if guts.user.is_superuser:
        groups_info = [{
            "id":
            g.id,
            "name":
            g.name,
            "users": [
                u.username for u in g.user_set.order_by("username")
                if u.is_active
            ],
        } for g in Group.objects.order_by("name")]
        template = get_template("groups.html")
        return TemplateResponse(template, {"groups": groups_info})
    else:
        return ForbiddenResponse("Only administrators can see this page.")
Beispiel #17
0
def recent_results(guts, username):
    """Show a list of recent results."""
    skip = int(guts.parameters.get("skip", 0))
    user = get_object_or_404(User, username=username)

    def contextlet(result):
        ptype = get_project_type(result.task.project)
        return {
            "result": result,
            "result_summary": ptype.cast(result).summary(),
            "project_type": result.task.project.type,
            "responses": [
                {
                    "response": response,
                    "response_summary": ptype.cast(response).summary(),
                    "match": ptype.cast(result).summary()
                    == ptype.cast(response).summary(),
                }
                for response in result.task.response_set.all()
            ],
        }

    if guts.user.is_superuser or guts.user == user:
        recent_results = Result.objects.filter(user=user).order_by("-end_time")[
            skip : skip + 50
        ]
        skips = {"current": "%s - %s" % (skip + 1, skip + len(recent_results))}
        if skip >= 50:
            skips['forward'] = (skip - 50) or "0"
        if len(recent_results) == 50:
            skips['backward'] = skip + 50
        template = get_template("recent_results.html")
        template_context = {
            "results": [contextlet(result) for result in recent_results],
            "skips": skips,
            "username": username,
        }
        return TemplateResponse(template, template_context)
    else:
        return ForbiddenResponse(
            "Only the user %s, or an administrator, may see this page." % username
        )
Beispiel #18
0
def recent_responses(guts, username):
    """Show a list of recent responses"""
    skip = int(guts.parameters.get("skip", 0))
    user = get_object_or_404(User, username=username)
    if guts.user.is_superuser or guts.user == user:
        recent_responses = Response.objects.filter(
            user=user, task__result__id__isnull=False
        ).order_by("-task__result__end_time")[skip : skip + 50]
        responses = []
        for response in recent_responses:
            res = {'response': response}
            res['project_type'] = response.task.project.type
            ptype = get_project_type(response.task.project)
            res['task_summary'] = ptype.cast(response.task).summary()
            res['response_summary'] = ptype.cast(response).summary()
            res['result_summary'] = ptype.cast(response.task.result).summary()
            if (
                res["response_summary"] is not None
                and res["result_summary"] is not None
            ):
                res['match'] = res['response_summary'] == res['result_summary']
            responses.append(res)
        template = get_template("recent_responses.html")
        skips = {}
        skips['current'] = "%s - %s" % (skip + 1, skip + len(responses))
        if skip >= 50:
            skips['forward'] = (skip - 50) or "0"
        if len(responses) == 50:
            skips['backward'] = skip + 50

        return TemplateResponse(
            template,
            {'responses': responses, 'skips': skips, 'username': user.username},
        )

    else:
        return ForbiddenResponse(
            "Only the user %s, or an administrator, may see this page." % username
        )
Beispiel #19
0
def change_password(get, guts):
    message = ""
    if get:
        f = ChangePassForm()
    else:
        f = ChangePassForm(guts.parameters)
        if f.is_valid():
            cleaned = f.cleaned_data
            if (guts.user.check_password(cleaned['old_pass'])
                    and cleaned['pass1'] == cleaned['pass2']):
                guts.user.set_password(cleaned['pass1'])
                guts.user.save()
                return ViewResponse('main:home')
            elif not guts.user.check_password(cleaned['old_pass']):
                message = "You did not enter your current password correctly"
            else:
                message = "Passwords didn't match."
    template = get_template("change_password.html")
    return TemplateResponse(template, {
        'form': f,
        'user': guts.user,
        'message': message
    })
Beispiel #20
0
def one_user(guts, username):
    """Summarize information about one user."""
    user = get_object_or_404(User, username=username)
    if guts.user.is_superuser or guts.user == user:
        groups = [{"name": g.name, "id": g.id} for g in user.groups.all()]
        recent_responses = [
            r.task.id for r in Response.objects.filter(
                user=user).order_by("-end_time")[0:20]
        ]
        recent_results = [
            r.task.id for r in Result.objects.filter(
                user=user).order_by("-end_time")[0:20]
        ]
        recent_reviews = [
            r.id for r in Review.objects.filter(
                response__user=user).order_by("-creation_time")[0:20]
        ]
        template = get_template("user.html")
        return TemplateResponse(
            template,
            {
                "name": username,
                "is_superuser": user.is_superuser,
                "groups": groups,
                "respondable_task_count":
                Task.objects.can_annotate(user).count(),
                "resolvable_task_count": Task.objects.can_merge(user).count(),
                "recent_responses": recent_responses,
                "recent_results": recent_results,
                "recent_reviews": recent_reviews,
            },
        )
    else:
        return ForbiddenResponse(
            "Only the user %s, or an administrator, may see this page." %
            username)
Beispiel #21
0
def task_view(get, guts, task_id):
    """View a given task ID or submit a response to it; in either
    case, this should dispatch appropriately based on the task's
    type."""
    import main.views.base

    task = Task.objects.get(pk=task_id)
    project_type = type_list[task.project.type]
    task = project_type.cast(task)
    try:
        wip = WorkInProgress.objects.get(task=task, user=guts.user)
    except WorkInProgress.DoesNotExist:
        if task.project.auto_review:
            try:
                ## Tasks in auto-review projects have a kludgey workflow:
                ## the task is responsible for noticing that it is in an
                ## auto-review project and adjusting the output of template()
                ## and template_data accordingly.
                ## When GETting the page, if a Response object already exists, then
                ## the output should be appropriate for displaying a review.
                auto_review = AutoReview.objects.get(task=task, user=guts.user)
                if get:
                    ## If the Task subclass has not been retrofitted to handle
                    ## auto-review projects, then this line will throw an exception
                    ## "TypeError: ... unexpected keyword argument 'auto_review_user'"
                    return TemplateResponse(
                        task.template(),
                        task.template_data(auto_review_user=guts.user))
                else:
                    ## NOTE: does the downcasting of task screw this query up?
                    response_query = Response.objects.filter(user=guts.user,
                                                             task=task)
                    if not response_query.exists():
                        ## No response?  Ask the task to make one!
                        kwargs = {
                            "user": guts.user,
                            "task": task,
                            "start_time": auto_review.start_time,
                        }
                        task.handle_response(guts, **kwargs)
                        ## (Note that this code path does NOT update the task's
                        ## completed_assignments field, because auto-review projects
                        ## do not have a limit on how many responses they can have.)
                        ##
                        ## And then GET this page again, so the user can see the review.
                        return ViewResponse('main:view-task', task_id)
                    else:
                        ## The user must have clicked the "I read this review" button.
                        auto_review.end_time = timezone.now()
                        auto_review.full_clean()
                        auto_review.save()
                        return ViewResponse('main:next-task')
            except AutoReview.DoesNotExist:
                ## fall through to the case below, since an admin is allowed to
                ## look at someone else's auto-review
                pass
        ## an admin can look at any task, but not even an admin
        ## can submit a response or result to a task without getting a WIP first
        if not (task.viewable_by(guts.user) and get):
            return ForbiddenResponse("You are not allowed to view %s." %
                                     six.text_type(task))
    if get:
        return TemplateResponse(task.template(), task.template_data())
    else:
        ## TODO: if we successfully make handle_response a method of the task,
        ## then we don't have to pass the task in kwargs
        kwargs = {
            "user": guts.user,
            "task": task,
            "start_time": wip.start_time
        }
        try:
            task.handle_response(guts, **kwargs)
            if task.completed:
                if 'review_user' in guts.parameters:
                    users = guts.parameters.getlist('review_user')
                    for user in users:
                        user_obj = User.objects.get(pk=user)
                        comment = guts.parameters.get("comment_%s" % user, "")
                        rev = Review(
                            response=task.response_set.get(user=user_obj),
                            comment=comment,
                        )
                        rev.full_clean()
                        rev.save()
            else:
                task.completed_assignments = task.completed_assignments + 1
                task.full_clean()
                task.save()
            wip.delete()
            if 'stop_working' in guts.parameters:
                return ViewResponse('main:home')
            else:
                return ViewResponse('main:next-task')
        except MultiValueDictKeyError:
            ## translate the MultiValueDict into a list of (key, list) pairs
            params = guts.parameters.lists()
            exc_type, exc_value, exc_traceback = sys.exc_info()
            tb_info = traceback.extract_tb(exc_traceback)
            template = get_template("parameter-error-in-task.html")
            context = {
                "task": str(task),
                "params": params,
                "exc_value": exc_value,
                "traceback": tb_info,
            }
            guts.log_error("Bad form? " + repr(context))
            return TemplateResponse(template, context, status=500)
Beispiel #22
0
def one_project(guts, project_id):
    """Summarize information about a single project."""
    project = get_object_or_404(Project, pk=project_id)
    if guts.user.is_superuser or guts.user == project.admin:
        ## Generate assignment counts.  When a project has 5000 or more tasks,
        ## the join-group-and-count operation using the Django QuerySet API
        ## is painfully slow, so we are dropping back to raw SQL here.
        query = """SELECT completed_assignments, COUNT(t.id) AS howmany
                   FROM main_task AS t LEFT JOIN main_result AS r ON (r.task_id = t.id)
                   WHERE project_id = %s AND (r.id IS NULL OR NOT completed)
                   GROUP BY completed_assignments"""
        cursor = connection.cursor()
        cursor.execute(query, [project.id])
        assignments = [{
            "completed_assignments": completed_assignments,
            "howmany": howmany
        } for completed_assignments, howmany in cursor.fetchall()]
        tasks = project.task_set
        needs_merging = tasks.filter(completed=True, result__isnull=True)
        if needs_merging.count():
            assignments.append({
                'completed_assignments': 'Needs Merging',
                'howmany': needs_merging.count(),
            })
        finished = tasks.filter(result__isnull=False)
        if finished.count():
            assignments.append({
                'completed_assignments': 'Finished',
                'howmany': finished.count()
            })

        # Project overview info
        pi = project_info(project)

        # Uploaded files
        uploads = ProjectUpload.objects.filter(project=project)

        # Task info
        MAXIMUM_TASKS_TO_LINK = 1500
        if tasks.count() <= MAXIMUM_TASKS_TO_LINK:
            ti = [{
                "id": t.id,
                "url": t.get_absolute_url(),
                "completed": t.completed,
                "merged": t.merged,
            } for t in tasks.order_by("id")]
            show_tasks = True
        else:
            ti = None
            show_tasks = False
        template = get_template("project.html")
        return TemplateResponse(
            template,
            {
                "project": pi,
                "show_tasks": show_tasks,
                "tasks": ti,
                'assignments': assignments,
                'uploads': uploads,
            },
        )
    else:
        return ForbiddenResponse(
            "Only project owners or administrators may see this page.")
Beispiel #23
0
def about(guts):
    """Manage the display of the homepage"""
    template = get_template("about.html")
    return TemplateResponse(template, {})