From patchwork Tue Oct 11 11:25:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zygmunt Krynicki X-Patchwork-Id: 4627 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id E16A323E0B for ; Tue, 11 Oct 2011 11:25:17 +0000 (UTC) Received: from mail-ey0-f180.google.com (mail-ey0-f180.google.com [209.85.215.180]) by fiordland.canonical.com (Postfix) with ESMTP id CC0E5A18337 for ; Tue, 11 Oct 2011 11:25:17 +0000 (UTC) Received: by eyg5 with SMTP id 5so2002880eyg.11 for ; Tue, 11 Oct 2011 04:25:17 -0700 (PDT) Received: by 10.223.77.71 with SMTP id f7mr17155566fak.33.1318332317567; Tue, 11 Oct 2011 04:25:17 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.24.41 with SMTP id r9cs154047laf; Tue, 11 Oct 2011 04:25:17 -0700 (PDT) Received: by 10.216.229.86 with SMTP id g64mr692475weq.42.1318332316124; Tue, 11 Oct 2011 04:25:16 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id fv20si15918905wbb.5.2011.10.11.04.25.15 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 11 Oct 2011 04:25:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1RDaSR-0007xT-I7 for ; Tue, 11 Oct 2011 11:25:15 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 7EEDBE09FA for ; Tue, 11 Oct 2011 11:25:15 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: lava-dashboard X-Launchpad-Branch: ~linaro-validation/lava-dashboard/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 272 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-validation/lava-dashboard/trunk] Rev 272: Add test effort create/update views Message-Id: <20111011112515.2591.32038.launchpad@ackee.canonical.com> Date: Tue, 11 Oct 2011 11:25:15 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14124"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 96e3c1cdf579f8adbe998a166f1e0d010c756403 ------------------------------------------------------------ revno: 272 committer: Zygmunt Krynicki branch nick: trunk timestamp: Thu 2011-10-06 14:03:00 +0200 message: Add test effort create/update views added: dashboard_app/forms.py dashboard_app/templates/dashboard_app/testing_effort_form.html modified: dashboard_app/templates/dashboard_app/testing_effort_detail.html dashboard_app/urls.py dashboard_app/views.py --- lp:lava-dashboard https://code.launchpad.net/~linaro-validation/lava-dashboard/trunk You are subscribed to branch lp:lava-dashboard. To unsubscribe from this branch go to https://code.launchpad.net/~linaro-validation/lava-dashboard/trunk/+edit-subscription === added file 'dashboard_app/forms.py' --- dashboard_app/forms.py 1970-01-01 00:00:00 +0000 +++ dashboard_app/forms.py 2011-10-06 12:03:00 +0000 @@ -0,0 +1,26 @@ +from django import forms +from django.contrib.auth.models import Group +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext as _ + +from lava_projects.models import Project +from dashboard_app.models import TestingEffort + + +class TestingEffortForm(forms.Form): + + name = forms.CharField( + label=_(u"Name"), + max_length=100) + + description = forms.CharField( + required=False, + widget=forms.widgets.Textarea(), + label=_(u"Description"), + help_text=_(u"Description of this testing effort")) + + tags = forms.CharField( + required=False, + label=_(u"Tags"), + max_length=1024, + help_text=_(u"Tags, separated by whitespace or commas")) === modified file 'dashboard_app/templates/dashboard_app/testing_effort_detail.html' --- dashboard_app/templates/dashboard_app/testing_effort_detail.html 2011-09-28 02:30:30 +0000 +++ dashboard_app/templates/dashboard_app/testing_effort_detail.html 2011-10-06 12:03:00 +0000 @@ -14,8 +14,17 @@ {% block sidebar %} -

{{ effort }}

-{{ effort.description|markdown }} +

Administration

+{% if belongs_to_user %} + +{% else %} +

You cannot make any changes to this testing effort. Only the owner of the +{{ effort.project }} can do +this.

+{% endif %} +

Tags

The concept of testing efforts is based on using tags to associate test runs with a common goal or task. This testing effort @@ -67,6 +76,10 @@ padding: 2pt; } +

About {{ effort.name }}

+{{ effort.description|markdown }} +

Tests related to this effort

+

The following tests contain one of the tags associated with this effort

{% regroup test_run_list|dictsortreversed:"analyzer_assigned_date" by analyzer_assigned_date|date:"Y-m-d" as test_run_cluster_list %} {% for test_run_cluster in test_run_cluster_list %} === added file 'dashboard_app/templates/dashboard_app/testing_effort_form.html' --- dashboard_app/templates/dashboard_app/testing_effort_form.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/testing_effort_form.html 2011-10-06 12:03:00 +0000 @@ -0,0 +1,61 @@ +{% extends "dashboard_app/_content_with_sidebar.html" %} +{% comment %} +This template is a candidate for lava-server/form.html (generic form template) +To make it work sensibly we need to move javascript and theme code to widgets +and start using proper widget media references +{% endcomment %} +{% load humanize %} +{% load markup %} +{% load i18n %} + + +{% block extrahead %} +{{ block.super }} + + + + +{% endblock %} + + +{% block content %} + + + {% block form_header %} + {% endblock %} + {% csrf_token %} +
+ {% for field in form %} + {% block form_field %} + + + + + {% endblock %} + {% endfor %} +
+ {% if field.errors %} +
+ {{ field.errors }} + {{ field }} +
+ {% else %} + {{ field }} + {% endif %} +

{{ field.help_text }}

+
+ {% block form_footer %} +

Continue

+ + {% endblock %} + + +{% endblock %} === modified file 'dashboard_app/urls.py' --- dashboard_app/urls.py 2011-09-29 13:06:54 +0000 +++ dashboard_app/urls.py 2011-10-06 12:03:00 +0000 @@ -67,4 +67,6 @@ url(r'^image_status/(?P[a-zA-Z0-9_-]+)\+(?P[a-zA-Z0-9_-]+)/test-history/(?P[^/]+)/$', 'image_test_history'), url(r'^efforts/$', 'testing_effort_list'), url(r'^efforts/(?P[0-9]+)/$', 'testing_effort_detail'), + url(r'^efforts/(?P[0-9]+)/update/$', 'testing_effort_update'), + url(r'^efforts/(?P[a-z0-9-]+)/\+new/$', 'testing_effort_create'), ) === modified file 'dashboard_app/views.py' --- dashboard_app/views.py 2011-09-28 02:30:30 +0000 +++ dashboard_app/views.py 2011-10-06 12:03:00 +0000 @@ -20,14 +20,17 @@ Views for the Dashboard application """ +import re import json +from django.contrib.auth.decorators import login_required from django.contrib.sites.models import Site from django.db.models.manager import Manager from django.db.models.query import QuerySet -from django.http import Http404, HttpResponse +from django.http import Http404, HttpResponse, HttpResponseRedirect from django.shortcuts import render_to_response, redirect, get_object_or_404 -from django.template import RequestContext +from django.template import RequestContext, loader +from django.views.generic.create_update import create_object from django.views.generic.list_detail import object_list, object_detail from dashboard_app.models import ( @@ -37,12 +40,16 @@ DataReport, DataView, ImageHealth, + Tag, Test, TestResult, TestRun, TestingEffort, ) -from dashboard_app.bread_crumbs import BreadCrumb, BreadCrumbTrail +from lava_server.bread_crumbs import ( + BreadCrumb, + BreadCrumbTrail, +) def _get_queryset(klass): @@ -594,6 +601,7 @@ return render_to_response( "dashboard_app/testing_effort_detail.html", { 'effort': effort, + 'belongs_to_user': effort.project.is_owned_by(request.user), 'test_run_list': effort.get_test_runs( ).select_related( 'denormalization', @@ -606,3 +614,92 @@ effort=effort, pk=pk), }, RequestContext(request)) + + +from lava_projects.models import Project +from lava_projects.views import project_detail +from dashboard_app.forms import TestingEffortForm + + +@BreadCrumb( + "Start a new test effort", + parent=project_detail, + needs=["project_identifier"]) +@login_required +def testing_effort_create(request, project_identifier): + project = get_object_or_404(Project, identifier=project_identifier) + if request.method == 'POST': + form = TestingEffortForm(request.POST) + # Check the form + if form.is_valid(): + # And make a project instance + effort = TestingEffort.objects.create( + name=form.cleaned_data['name'], + description=form.cleaned_data['description'], + project=project) + # Create all the required tags + effort.tags = [ + Tag.objects.get_or_create(name=tag_name)[0] + for tag_name in re.split("[, ]+", form.cleaned_data["tags"]) + if tag_name != ""] + return HttpResponseRedirect(effort.get_absolute_url()) + else: + form = TestingEffortForm() + # Render to template + template_name = "dashboard_app/testing_effort_form.html" + t = loader.get_template(template_name) + c = RequestContext(request, { + 'form': form, + 'bread_crumb_trail': BreadCrumbTrail.leading_to( + testing_effort_create, + project=project, + project_identifier=project.identifier) + }) + return HttpResponse(t.render(c)) + + +@BreadCrumb( + "Update", + parent=testing_effort_detail, + needs=["pk"]) +@login_required +def testing_effort_update(request, pk): + try: + effort = TestingEffort.objects.get(pk=pk) + except TestingEffort.DoesNotExist: + raise Http404() + if not effort.project.is_owned_by(request.user): + return HttpReseponse("not allowed") + if request.method == 'POST': + form = TestingEffortForm(request.POST) + # Check the form + if form.is_valid(): + # And update the effort object + effort.name=form.cleaned_data['name'] + effort.description=form.cleaned_data['description'] + # As well as tags + effort.tags = [ + Tag.objects.get_or_create(name=tag_name)[0] + for tag_name in re.split("[, ]+", form.cleaned_data["tags"]) + if tag_name != ""] + # Save the changes + effort.save() + return HttpResponseRedirect(effort.get_absolute_url()) + else: + form = TestingEffortForm(initial={ + 'name': effort.name, + 'description': effort.description, + 'tags': " ".join([tag.name for tag in effort.tags.order_by('name').all()]) + }) + # Render to template + template_name = "dashboard_app/testing_effort_form.html" + t = loader.get_template(template_name) + c = RequestContext(request, { + 'form': form, + 'effort': effort, + 'bread_crumb_trail': BreadCrumbTrail.leading_to( + testing_effort_update, + effort=effort, + pk=effort.pk) + }) + return HttpResponse(t.render(c))