From patchwork Fri Sep 13 14:17:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stevan Radakovic X-Patchwork-Id: 20287 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ye0-f200.google.com (mail-ye0-f200.google.com [209.85.213.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1711B20F2F for ; Fri, 13 Sep 2013 15:57:20 +0000 (UTC) Received: by mail-ye0-f200.google.com with SMTP id r3sf1421719yen.7 for ; Fri, 13 Sep 2013 08:57:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:mime-version:to:from:subject :message-id:date:reply-to:sender:errors-to:precedence :x-original-sender:x-original-authentication-results:mailing-list :list-id:list-post:list-help:list-archive:list-unsubscribe :content-type; bh=EhnsLf3fJRmu3pYbKb1UXnAylaZp/su91Z1tfGDsqW0=; b=ZDeC3VnJd4NQjw9FMHN9nmiD4QUkiu65OXHGtT6V2PUWQwwoMXclSBbheaq0LvzZfJ rv5QeItOoPXg0cvj30nRTS/PooYSySjt8ZH5tt6VmG75xNnSZhEW8abVbHnyezxa5DM5 vwslgIldFEM4EiOnR20Fz3YsThec/u+LXbw24+P1uBk9byQj/v2yI98G+zfEvpXxpKQ+ lV1fdNa15motze1EwxRnNGCC3dijj6qW7kdjeKfQokz6CM2Wv8yvrHUYwEU6Dyfu0TZ2 +0hHRzZtR1XxlEGffKzq8JZ8LVfu3UOzLGdJd3UnCVW3ZIdcc7yaMK8IX1Bw/JvXTcfb xYhQ== X-Gm-Message-State: ALoCoQl1t90nuDghNXTLS+rRvgO8qZVbBtg4/TsGZoHFlvqqzJ/RcBiGRnnBkJh15GNMGBdXSqfe X-Received: by 10.236.109.134 with SMTP id s6mr5065071yhg.32.1379081847364; Fri, 13 Sep 2013 07:17:27 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.18.199 with SMTP id y7ls1199111qed.78.gmail; Fri, 13 Sep 2013 07:17:27 -0700 (PDT) X-Received: by 10.52.231.5 with SMTP id tc5mr472450vdc.36.1379081847089; Fri, 13 Sep 2013 07:17:27 -0700 (PDT) Received: from mail-ve0-f170.google.com (mail-ve0-f170.google.com [209.85.128.170]) by mx.google.com with ESMTPS id th8si3206103veb.20.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 13 Sep 2013 07:17:26 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.170 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.170; Received: by mail-ve0-f170.google.com with SMTP id c14so1050255vea.1 for ; Fri, 13 Sep 2013 07:17:26 -0700 (PDT) X-Received: by 10.221.53.74 with SMTP id vp10mr53655vcb.54.1379081846865; Fri, 13 Sep 2013 07:17:26 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp83086vcz; Fri, 13 Sep 2013 07:17:26 -0700 (PDT) X-Received: by 10.194.201.168 with SMTP id kb8mr1164717wjc.63.1379081845725; Fri, 13 Sep 2013 07:17:25 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id n6si1268900wiw.4.1969.12.31.16.00.00 (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 13 Sep 2013 07:17:25 -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; Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1VKUBZ-00049s-1R for ; Fri, 13 Sep 2013 14:17:25 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id F070FE1785 for ; Fri, 13 Sep 2013 14:17:24 +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: 422 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-validation/lava-dashboard/trunk] Rev 422: Add Image report editor feature. Message-Id: <20130913141724.18242.49559.launchpad@ackee.canonical.com> Date: Fri, 13 Sep 2013 14:17:24 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: list X-Generated-By: Launchpad (canonical.com); Revision="16761"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: cab43943a24d35a19407a8e3dc0ca44712b46e6d X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: noreply@launchpad.net X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.170 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Merge authors: Stevan Radaković (stevanr) Related merge proposals: https://code.launchpad.net/~stevanr/lava-dashboard/image-report-editor-frontend/+merge/185255 proposed by: Stevan Radaković (stevanr) review: Approve - Antonio Terceiro (terceiro) ------------------------------------------------------------ revno: 422 [merge] committer: Stevan Radakovic branch nick: trunk timestamp: Fri 2013-09-13 16:16:05 +0200 message: Add Image report editor feature. added: dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py dashboard_app/static/dashboard_app/css/image-charts.css dashboard_app/static/dashboard_app/images/ajax-progress.gif dashboard_app/static/dashboard_app/js/image-report-editor.js dashboard_app/templates/dashboard_app/image_chart_filter_form.html dashboard_app/templates/dashboard_app/image_report_chart_detail.html dashboard_app/templates/dashboard_app/image_report_chart_form.html dashboard_app/templates/dashboard_app/image_report_detail.html dashboard_app/templates/dashboard_app/image_report_form.html dashboard_app/templates/dashboard_app/image_report_list.html dashboard_app/views/image_reports/ dashboard_app/views/image_reports/__init__.py dashboard_app/views/image_reports/forms.py dashboard_app/views/image_reports/views.py modified: dashboard_app/models.py dashboard_app/urls.py dashboard_app/views/filters/tables.py dashboard_app/views/filters/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/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py' --- dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py 1970-01-01 00:00:00 +0000 +++ dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py 2013-09-13 11:45:52 +0000 @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'ImageChartTestRun' + db.delete_table('dashboard_app_imagecharttestrun') + + # Adding model 'ImageChartTest' + db.create_table('dashboard_app_imagecharttest', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('image_chart_filter', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.ImageChartFilter'])), + ('test', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.Test'])), + ('name', self.gf('django.db.models.fields.CharField')(max_length=200)), + )) + db.send_create_signal('dashboard_app', ['ImageChartTest']) + + # Adding unique constraint on 'ImageChartTest', fields ['image_chart_filter', 'test'] + db.create_unique('dashboard_app_imagecharttest', ['image_chart_filter_id', 'test_id']) + + # Adding model 'ImageChartFilter' + db.create_table('dashboard_app_imagechartfilter', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('image_chart', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.ImageReportChart'])), + ('filter', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.TestRunFilter'], null=True, on_delete=models.SET_NULL)), + ('representation', self.gf('django.db.models.fields.CharField')(default='lines', max_length=20)), + )) + db.send_create_signal('dashboard_app', ['ImageChartFilter']) + + # Deleting field 'ImageChartTestCase.image_chart' + db.delete_column('dashboard_app_imagecharttestcase', 'image_chart_id') + + # Adding field 'ImageChartTestCase.image_chart_filter' + db.add_column('dashboard_app_imagecharttestcase', 'image_chart_filter', + self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['dashboard_app.ImageChartFilter']), + keep_default=False) + + # Adding unique constraint on 'ImageChartTestCase', fields ['image_chart_filter', 'test_case'] + db.create_unique('dashboard_app_imagecharttestcase', ['image_chart_filter_id', 'test_case_id']) + + # Adding field 'ImageReport.is_published' + db.add_column('dashboard_app_imagereport', 'is_published', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Deleting field 'ImageReportChart.representation' + db.delete_column('dashboard_app_imagereportchart', 'representation') + + # Adding field 'ImageReportChart.description' + db.add_column('dashboard_app_imagereportchart', 'description', + self.gf('django.db.models.fields.TextField')(null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Removing unique constraint on 'ImageChartTestCase', fields ['image_chart_filter', 'test_case'] + db.delete_unique('dashboard_app_imagecharttestcase', ['image_chart_filter_id', 'test_case_id']) + + # Removing unique constraint on 'ImageChartTest', fields ['image_chart_filter', 'test'] + db.delete_unique('dashboard_app_imagecharttest', ['image_chart_filter_id', 'test_id']) + + # Adding model 'ImageChartTestRun' + db.create_table('dashboard_app_imagecharttestrun', ( + ('test_run', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.TestRun'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=200)), + ('image_chart', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.ImageReportChart'])), + )) + db.send_create_signal('dashboard_app', ['ImageChartTestRun']) + + # Deleting model 'ImageChartTest' + db.delete_table('dashboard_app_imagecharttest') + + # Deleting model 'ImageChartFilter' + db.delete_table('dashboard_app_imagechartfilter') + + # Adding field 'ImageChartTestCase.image_chart' + db.add_column('dashboard_app_imagecharttestcase', 'image_chart', + self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['dashboard_app.ImageReportChart']), + keep_default=False) + + # Deleting field 'ImageChartTestCase.image_chart_filter' + db.delete_column('dashboard_app_imagecharttestcase', 'image_chart_filter_id') + + # Deleting field 'ImageReport.is_published' + db.delete_column('dashboard_app_imagereport', 'is_published') + + # Adding field 'ImageReportChart.representation' + db.add_column('dashboard_app_imagereportchart', 'representation', + self.gf('django.db.models.fields.CharField')(default='pass/fail', max_length=20), + keep_default=False) + + # Deleting field 'ImageReportChart.description' + db.delete_column('dashboard_app_imagereportchart', 'description') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'dashboard_app.attachment': { + 'Meta': {'object_name': 'Attachment'}, + 'content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True'}), + 'content_filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'public_url': ('django.db.models.fields.URLField', [], {'max_length': '512', 'blank': 'True'}) + }, + 'dashboard_app.bundle': { + 'Meta': {'ordering': "['-uploaded_on']", 'object_name': 'Bundle'}, + '_gz_content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'db_column': "'gz_content'"}), + '_raw_content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'db_column': "'content'"}), + 'bundle_stream': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bundles'", 'to': "orm['dashboard_app.BundleStream']"}), + 'content_filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'content_sha1': ('django.db.models.fields.CharField', [], {'max_length': '40', 'unique': 'True', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_deserialized': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'uploaded_bundles'", 'null': 'True', 'to': "orm['auth.User']"}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) + }, + 'dashboard_app.bundledeserializationerror': { + 'Meta': {'object_name': 'BundleDeserializationError'}, + 'bundle': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'deserialization_error'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['dashboard_app.Bundle']"}), + 'error_message': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'traceback': ('django.db.models.fields.TextField', [], {'max_length': '32768'}) + }, + 'dashboard_app.bundlestream': { + 'Meta': {'object_name': 'BundleStream'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'pathname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'dashboard_app.hardwaredevice': { + 'Meta': {'object_name': 'HardwareDevice'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'device_type': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'dashboard_app.image': { + 'Meta': {'object_name': 'Image'}, + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['dashboard_app.TestRunFilter']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '1024'}) + }, + 'dashboard_app.imagechartfilter': { + 'Meta': {'object_name': 'ImageChartFilter'}, + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.TestRunFilter']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image_chart': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.ImageReportChart']"}), + 'representation': ('django.db.models.fields.CharField', [], {'default': "'lines'", 'max_length': '20'}) + }, + 'dashboard_app.imagecharttest': { + 'Meta': {'unique_together': "(('image_chart_filter', 'test'),)", 'object_name': 'ImageChartTest'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image_chart_filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.ImageChartFilter']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'test': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.Test']"}) + }, + 'dashboard_app.imagecharttestcase': { + 'Meta': {'unique_together': "(('image_chart_filter', 'test_case'),)", 'object_name': 'ImageChartTestCase'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image_chart_filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.ImageChartFilter']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'test_case': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.TestCase']"}) + }, + 'dashboard_app.imagereport': { + 'Meta': {'object_name': 'ImageReport'}, + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '1024'}) + }, + 'dashboard_app.imagereportchart': { + 'Meta': {'object_name': 'ImageReportChart'}, + 'chart_type': ('django.db.models.fields.CharField', [], {'default': "'pass/fail'", 'max_length': '20'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image_report': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dashboard_app.ImageReport']"}), + 'is_data_table_visible': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_interactive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'target_goal': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '10', 'decimal_places': '5', 'blank': 'True'}) + }, + 'dashboard_app.imageset': { + 'Meta': {'object_name': 'ImageSet'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'images': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dashboard_app.Image']", 'symmetrical': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}) + }, + 'dashboard_app.launchpadbug': { + 'Meta': {'object_name': 'LaunchpadBug'}, + 'bug_id': ('django.db.models.fields.PositiveIntegerField', [], {'unique': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'test_runs': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'launchpad_bugs'", 'symmetrical': 'False', 'to': "orm['dashboard_app.TestRun']"}) + }, + 'dashboard_app.namedattribute': { + 'Meta': {'unique_together': "(('object_id', 'name'),)", 'object_name': 'NamedAttribute'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.TextField', [], {}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'value': ('django.db.models.fields.TextField', [], {}) + }, + 'dashboard_app.pmqabundlestream': { + 'Meta': {'object_name': 'PMQABundleStream'}, + 'bundle_stream': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['dashboard_app.BundleStream']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'dashboard_app.softwarepackage': { + 'Meta': {'unique_together': "(('name', 'version'),)", 'object_name': 'SoftwarePackage'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'dashboard_app.softwarepackagescratch': { + 'Meta': {'object_name': 'SoftwarePackageScratch'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'dashboard_app.softwaresource': { + 'Meta': {'object_name': 'SoftwareSource'}, + 'branch_revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'branch_url': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'branch_vcs': ('django.db.models.fields.CharField', [], {'max_length': '10'}), + 'commit_timestamp': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project_name': ('django.db.models.fields.CharField', [], {'max_length': '32'}) + }, + 'dashboard_app.tag': { + 'Meta': {'object_name': 'Tag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '256'}) + }, + 'dashboard_app.test': { + 'Meta': {'object_name': 'Test'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'test_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}) + }, + 'dashboard_app.testcase': { + 'Meta': {'unique_together': "(('test', 'test_case_id'),)", 'object_name': 'TestCase'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_cases'", 'to': "orm['dashboard_app.Test']"}), + 'test_case_id': ('django.db.models.fields.TextField', [], {}), + 'units': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + 'dashboard_app.testdefinition': { + 'Meta': {'object_name': 'TestDefinition'}, + 'content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'environment': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'format': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'location': ('django.db.models.fields.CharField', [], {'default': "'LOCAL'", 'max_length': '64'}), + 'mime_type': ('django.db.models.fields.CharField', [], {'default': "'text/plain'", 'max_length': '64'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'target_dev_types': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'target_os': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'version': ('django.db.models.fields.CharField', [], {'max_length': '256'}) + }, + 'dashboard_app.testresult': { + 'Meta': {'ordering': "('_order',)", 'object_name': 'TestResult'}, + '_order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lineno': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'measurement': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '20', 'decimal_places': '10', 'blank': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'microseconds': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'relative_index': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'result': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), + 'test_case': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'test_results'", 'null': 'True', 'to': "orm['dashboard_app.TestCase']"}), + 'test_run': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_results'", 'to': "orm['dashboard_app.TestRun']"}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'dashboard_app.testrun': { + 'Meta': {'ordering': "['-import_assigned_date']", 'object_name': 'TestRun'}, + 'analyzer_assigned_date': ('django.db.models.fields.DateTimeField', [], {}), + 'analyzer_assigned_uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}), + 'bundle': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_runs'", 'to': "orm['dashboard_app.Bundle']"}), + 'devices': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.HardwareDevice']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'import_assigned_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'microseconds': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'packages': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.SoftwarePackage']"}), + 'sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.SoftwareSource']"}), + 'sw_image_desc': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.Tag']"}), + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_runs'", 'to': "orm['dashboard_app.Test']"}), + 'time_check_performed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'dashboard_app.testrundenormalization': { + 'Meta': {'object_name': 'TestRunDenormalization'}, + 'count_fail': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'count_pass': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'count_skip': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'count_unknown': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'test_run': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'denormalization'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['dashboard_app.TestRun']"}) + }, + 'dashboard_app.testrunfilter': { + 'Meta': {'unique_together': "(('owner', 'name'),)", 'object_name': 'TestRunFilter'}, + 'build_number_attribute': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'bundle_streams': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dashboard_app.BundleStream']", 'symmetrical': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '1024'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['auth.User']"}) + }, + 'dashboard_app.testrunfilterattribute': { + 'Meta': {'object_name': 'TestRunFilterAttribute'}, + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attributes'", 'to': "orm['dashboard_app.TestRunFilter']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'value': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'dashboard_app.testrunfiltersubscription': { + 'Meta': {'unique_together': "(('user', 'filter'),)", 'object_name': 'TestRunFilterSubscription'}, + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.TestRunFilter']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'dashboard_app.testrunfiltertest': { + 'Meta': {'object_name': 'TestRunFilterTest'}, + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tests'", 'to': "orm['dashboard_app.TestRunFilter']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['dashboard_app.Test']"}) + }, + 'dashboard_app.testrunfiltertestcase': { + 'Meta': {'object_name': 'TestRunFilterTestCase'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'cases'", 'to': "orm['dashboard_app.TestRunFilterTest']"}), + 'test_case': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['dashboard_app.TestCase']"}) + } + } + + complete_apps = ['dashboard_app'] \ No newline at end of file === modified file 'dashboard_app/models.py' --- dashboard_app/models.py 2013-09-05 16:00:38 +0000 +++ dashboard_app/models.py 2013-09-13 14:16:05 +0000 @@ -1540,101 +1540,6 @@ return self.name -class ImageReport(models.Model): - - name = models.SlugField(max_length=1024, unique=True) - - description = models.TextField(blank=True, null=True) - - def __unicode__(self): - return self.name - - -# Chart types -CHART_TYPES = ((r'pass/fail', 'Pass/Fail'), - (r'measurement', 'Measurement')) -# Chart representation -REPRESENTATION_TYPES = ((r'lines', 'Lines'), - (r'bars', 'Bars')) - - -class ImageReportChart(models.Model): - - name = models.CharField(max_length=100) - - image_report = models.ForeignKey( - ImageReport, - default=None, - null=False, - on_delete=models.CASCADE) - - test_runs = models.ManyToManyField( - TestRun, - through='ImageChartTestRun') - - test_cases = models.ManyToManyField( - TestCase, - through='ImageChartTestCase') - - chart_type = models.CharField( - max_length=20, - choices=CHART_TYPES, - verbose_name='Chart type') - - representation = models.CharField( - max_length=20, - choices=REPRESENTATION_TYPES, - verbose_name='Representation type') - - target_goal = models.DecimalField( - blank = True, - decimal_places = 5, - max_digits = 10, - null = True, - verbose_name = 'Target goal') - - is_interactive = models.BooleanField( - default=False, - verbose_name='Chart is interactive') - - is_data_table_visible = models.BooleanField( - default=False, - verbose_name='Data table is visible') - - def __unicode__(self): - return self.name - - -class ImageChartTestRun(models.Model): - - image_chart = models.ForeignKey( - ImageReportChart, - null=False, - on_delete=models.CASCADE) - - test_run = models.ForeignKey( - TestRun, - null=False, - on_delete=models.CASCADE) - - name = models.CharField(max_length=200) - - -class ImageChartTestCase(models.Model): - - image_chart = models.ForeignKey( - ImageReportChart, - null=False, - on_delete=models.CASCADE) - - test_case = models.ForeignKey( - TestCase, - null=False, - on_delete=models.CASCADE) - - name = models.CharField(max_length=200) - - class LaunchpadBug(models.Model): bug_id = models.PositiveIntegerField(unique=True) @@ -1923,3 +1828,137 @@ class PMQABundleStream(models.Model): bundle_stream = models.ForeignKey(BundleStream, related_name='+') + + +class ImageReport(models.Model): + + name = models.SlugField(max_length=1024, unique=True) + + description = models.TextField(blank=True, null=True) + + is_published = models.BooleanField( + default=False, + verbose_name='Published') + + def __unicode__(self): + return self.name + + @models.permalink + def get_absolute_url(self): + return ("dashboard_app.views.image_reports.views.image_report_detail", + (), dict(name=self.name)) + +# Chart types +CHART_TYPES = ((r'pass/fail', 'Pass/Fail'), + (r'measurement', 'Measurement')) +# Chart representation +REPRESENTATION_TYPES = ((r'lines', 'Lines'), + (r'bars', 'Bars')) + + +class ImageReportChart(models.Model): + + name = models.CharField(max_length=100) + + description = models.TextField(blank=True, null=True) + + image_report = models.ForeignKey( + ImageReport, + default=None, + null=False, + on_delete=models.CASCADE) + + chart_type = models.CharField( + max_length=20, + choices=CHART_TYPES, + verbose_name='Chart type', + blank=False, + default="pass/fail", + ) + + target_goal = models.DecimalField( + blank = True, + decimal_places = 5, + max_digits = 10, + null = True, + verbose_name = 'Target goal') + + is_interactive = models.BooleanField( + default=False, + verbose_name='Chart is interactive') + + is_data_table_visible = models.BooleanField( + default=False, + verbose_name='Data table is visible') + + def __unicode__(self): + return self.name + + @models.permalink + def get_absolute_url(self): + return ("dashboard_app.views.image_reports.views.image_chart_detail", + (), dict(id=self.id)) + + +class ImageChartFilter(models.Model): + + image_chart = models.ForeignKey( + ImageReportChart, + null=False, + on_delete=models.CASCADE) + + filter = models.ForeignKey( + TestRunFilter, + null=True, + on_delete=models.SET_NULL) + + representation = models.CharField( + max_length=20, + choices=REPRESENTATION_TYPES, + verbose_name='Representation', + blank=False, + default="lines", + ) + + @models.permalink + def get_absolute_url(self): + return ( + "dashboard_app.views.image_reports.views.image_chart_filter_edit", + (), dict(id=self.id)) + + +class ImageChartTest(models.Model): + + class Meta: + unique_together = ("image_chart_filter", "test") + + image_chart_filter = models.ForeignKey( + ImageChartFilter, + null=False, + on_delete=models.CASCADE) + + test = models.ForeignKey( + Test, + null=False, + on_delete=models.CASCADE) + + name = models.CharField(max_length=200) + + +class ImageChartTestCase(models.Model): + + class Meta: + unique_together = ("image_chart_filter", "test_case") + + image_chart_filter = models.ForeignKey( + ImageChartFilter, + null=False, + on_delete=models.CASCADE) + + test_case = models.ForeignKey( + TestCase, + null=False, + on_delete=models.CASCADE) + + name = models.CharField(max_length=200) + === added file 'dashboard_app/static/dashboard_app/css/image-charts.css' --- dashboard_app/static/dashboard_app/css/image-charts.css 1970-01-01 00:00:00 +0000 +++ dashboard_app/static/dashboard_app/css/image-charts.css 2013-09-12 14:12:07 +0000 @@ -0,0 +1,82 @@ +@import url("../../admin/css/widgets.css"); + +div.selector { clear: both; } +div.selector span.helptext { display: none; } +div.selector h2 { margin: 0; font-size: 11pt; } +div.selector a { text-decoration: none; } +div.selector select { height: 10em; } +div.selector ul.selector-chooser { margin-top: 5.5em; } +div.selector .selector-chosen select { + border: 1px solid rgb(204, 204, 204); + border-top: none; +} + +.list-container { + border: 1px solid #000000; + clear: both; + margin: 10px 10px 10px 10px; + padding: 10px; + width: 50%; +} + +.form-field { + margin-bottom: 5px; + vertical-align: top; +} + +.form-field label { + vertical-align: top; + width: 100px; + display: inline-block; + margin-left: 10px; +} + +.submit-button { + margin-top: 20px; + margin-left: 10px; +} + +.filter-headline { + font-weight: bold; + font-size: 16px; +} + +.filter-container { + margin-bottom: 10px; + clear: both; +} + +.filter-title { + font-weight: bold; + font-size: 15px; + margin-bottom: 10px; +} + +.chart-title { + font-weight: bold; + font-size: 15px; + margin-bottom: 10px; +} + +.errors { + color: red; +} + +.fields-container { + margin-left: 10px; +} + +#filters_div { + margin: 10px 0 0 10px; + border: 1px solid #000000; + clear: both; + width: 75%; + padding: 5px 0 10px 10px; + overflow: auto; +} + +#alias_container { + font-weight: bold; + float: left; + display: none; +} \ No newline at end of file === added file 'dashboard_app/static/dashboard_app/images/ajax-progress.gif' Binary files dashboard_app/static/dashboard_app/images/ajax-progress.gif 1970-01-01 00:00:00 +0000 and dashboard_app/static/dashboard_app/images/ajax-progress.gif 2013-09-09 11:47:00 +0000 differ === added file 'dashboard_app/static/dashboard_app/js/image-report-editor.js' --- dashboard_app/static/dashboard_app/js/image-report-editor.js 1970-01-01 00:00:00 +0000 +++ dashboard_app/static/dashboard_app/js/image-report-editor.js 2013-09-12 14:24:11 +0000 @@ -0,0 +1,221 @@ +select_filter = function() { + // Open the filter select dialog. + $('#filter_select_dialog').dialog('open'); +} + +filters_callback = function(id, name) { + // Function which will be called when a filter is selected from the dialog. + + if ($('#id_chart_type').val() == "pass/fail") { + url = "/dashboard/filters/+get-tests-json"; + } else { + url = "/dashboard/filters/+get-test-cases-json"; + } + + $.ajax({ + url: url, + async: false, + data: {"id": id}, + beforeSend: function () { + $('#filter-container').remove(); + $('#filter_select_dialog').dialog('close'); + $('#loading_dialog').dialog('open'); + }, + success: function (data) { + $('#loading_dialog').dialog('close'); + $("#id_filter").val(id); + add_filter_container(data, name); + }, + error: function(data, status, error) { + $('#loading_dialog').dialog('close'); + alert('Filter could not be loaded, please try again.'); + } + }); +} + +add_filter_container = function(data, title) { + // Adds elements which contain tests or test cases from the previously + // selected filter. + + content = '
' + title + '
'; + + if ($('#id_chart_type').val() == "pass/fail") { + test_label = "Tests"; + } else { + test_label = "Test Cases"; + } + + content += '

' + + 'Select ' + test_label + '

'; + + content += ''; + + content += '' + + 'Choose All'; + content += '
'; + + content += '
    ' + + '
  • ' + + '
  • ' + + '
'; + + content += '

' + + 'Choosen ' + test_label + '

'; + + content += ''; + content += '' + + 'Remove All'; + content += '
'; + + content += '
Alias
'; + content += ''; + content += '
'; + + $('
').html( + content).appendTo($('#filters_div')); + + update_events(); +} + +update_events = function() { + // Add onclick events to the links controlling the select boxes. + + $('#add_link').click(function() { + move_options('available_tests', 'chosen_tests'); + }); + $('#remove_link').click(function() { + move_options('chosen_tests', 'available_tests'); + }); + $('#add_all_link').click(function() { + $('#available_tests option').each(function() { + $(this).attr('selected', 'selected'); + }); + move_options('available_tests', 'chosen_tests'); + }); + $('#remove_all_link').click(function() { + $('#chosen_tests option').each(function() { + $(this).attr('selected', 'selected'); + }); + move_options('chosen_tests', 'available_tests'); + }); +} + +move_options = function(from_element, to_element) { + var options = $("#" + from_element + " option:selected"); + $("#" + to_element).append(options.clone()); + $(options).remove(); + + update_aliases(); + toggle_alias(); +} + +add_selected_options = function() { + // Adds options from chosen tests select box as hidden fields. + + $('#chosen_tests option').each(function() { + if ($('#id_chart_type').val() == "pass/fail") { + field_name = "image_chart_tests"; + } else { + field_name = "image_chart_test_cases"; + } + $('').appendTo($('#add_filter_link')); + }); +} + +update_aliases = function() { + // Update hidden aliases inputs based on chosen tests. + + $('#chosen_tests option').each(function() { + if ($('#alias_' + $(this).val()).length == 0) { + $('').appendTo($('#aliases_div')); + } + }); + chosen_tests = $.map($('#chosen_tests option'), function(e) { + return e.value; + }); + $('.alias').each(function(index, value) { + test_id = value.id.split('_')[1]; + + if (chosen_tests.indexOf(test_id) == -1) { + $('#alias_' + test_id).remove(); + } + }); +} + +toggle_alias = function() { + // Show/hide alias input field. + + if ($('#chosen_tests option:selected').length == 1) { + $('#alias_container').show(); + test_id = $('#chosen_tests option:selected').val(); + $('#alias').val($('#alias_' + test_id).val()); + } else { + $('#alias_container').hide(); + } +} + +copy_alias = function(e) { + // Populate alias input based on the selected test. + + if ($('#chosen_tests option:selected').length == 1) { + test_id = $('#chosen_tests option:selected').val(); + $('#alias_' + test_id).val(e.value); + } +} + +sort_aliases = function() { + // Pre submit function. Sort the aliases hidden inputs. + + $('#aliases_div input').sort(function(a,b) { + return a.dataset.sid > b.dataset.sid; + }).appendTo('#aliases_div'); +} + +init_filter_dialog = function() { + // Setup the filter table dialog. + + var filter_dialog = $('
'); + $('#all-filters_wrapper').wrapAll(filter_dialog); + + $('#filter_select_dialog').dialog({ + autoOpen: false, + title: 'Select Filter', + draggable: false, + height: 280, + width: 420, + modal: true, + resizable: false + }); +} + +init_loading_dialog = function() { + // Setup the loading image dialog. + + $('#loading_dialog').dialog({ + autoOpen: false, + title: '', + draggable: false, + height: 35, + width: 250, + modal: true, + resizable: false, + dialogClass: 'loading-dialog' + }); + + $('.loading-dialog div.ui-dialog-titlebar').hide(); +} === added file 'dashboard_app/templates/dashboard_app/image_chart_filter_form.html' --- dashboard_app/templates/dashboard_app/image_chart_filter_form.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/image_chart_filter_form.html 2013-09-12 13:30:08 +0000 @@ -0,0 +1,109 @@ +{% extends "dashboard_app/_content.html" %} +{% load i18n %} +{% load django_tables2 %} + +{% block extrahead %} +{{ block.super }} + + + +{% endblock %} + + +{% block content %} +

Image Chart Filter

+ +{% block content_form %} +
{% csrf_token %} + + {% if form.errors %} +
+
+ {{ form.non_field_errors }} +
    + {% for field in form %} + {% if field.errors %} +
  • {{ field.label }}: {{ field.errors|striptags }}
  • + {% endif %} + {% endfor %} +
+
+
+ {% endif %} + +
+ + +
+ {{ form.representation.label_tag }} + {{ form.representation }} +
+
+ +
+
+ +
+ +
+
+ +{% endblock content_form %} + +{% render_table filters_table %} + +
+Loading... +
+ + + +{% endblock %} === added file 'dashboard_app/templates/dashboard_app/image_report_chart_detail.html' --- dashboard_app/templates/dashboard_app/image_report_chart_detail.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/image_report_chart_detail.html 2013-09-12 19:32:47 +0000 @@ -0,0 +1,86 @@ +{% extends "dashboard_app/_content.html" %} +{% load i18n %} + +{% block extrahead %} +{{ block.super }} + +{% endblock %} + +{% block content %} + +

Image Chart {{ image_chart.name }}

+ + +
+
+ Edit this chart. +
+
+ Description: {{ image_chart.description }} +
+
+ Chart type: {{ image_chart.chart_type }} +
+
+ Data table visible: {{ image_chart.is_data_table_visible }} +
+
+ Target goal: {{ image_chart.target_goal|floatformat:"-2" }} +
+
+ + +

Filters

+ +
+ +
+ +
+ {% for chart_filter in image_chart.imagechartfilter_set.all %} +
+ {{ chart_filter.filter.name }}     + + edit +   + + remove + +
+
+ {% if image_chart.chart_type == "pass/fail" %} + Tests:  + {% for chart_test in chart_filter.imagecharttest_set.all %} + {% if forloop.last %} + {{ chart_test.test.test_id }} + {% else %} + {{ chart_test.test.test_id }},  + {% endif %} + {% endfor %} + {% else %} + Test Cases:  + {% for chart_test in chart_filter.imagecharttestcase_set.all %} + {% if forloop.last %} + {{ chart_test.test_case.test_case_id }} + {% else %} + {{ chart_test.test_case.test_case_id }},  + {% endif %} + {% endfor %} + {% endif %} +
+
+ Representation: {{ chart_filter.representation }} +
+ +
+ {% empty %} +
+
  • No filters added yet.
  • +
    + {% endfor %} +
    + + +{% endblock %} === added file 'dashboard_app/templates/dashboard_app/image_report_chart_form.html' --- dashboard_app/templates/dashboard_app/image_report_chart_form.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/image_report_chart_form.html 2013-09-12 14:12:07 +0000 @@ -0,0 +1,62 @@ +{% extends "dashboard_app/_content.html" %} +{% load i18n %} +{% load django_tables2 %} + +{% block extrahead %} +{{ block.super }} + + +{% endblock %} + + +{% block content %} +

    Add Image Charts 2.0

    + +{% block content_form %} +
    {% csrf_token %} + + {% if form.errors %} +
    +
    + {{ form.non_field_errors }} +
      + {% for field in form %} + {% if field.errors %} +
    • {{ field.label }}: {{ field.errors|striptags }}
    • + {% endif %} + {% endfor %} +
    +
    +
    + {% endif %} + +
    + {{ form.name.label_tag }} + {{ form.name }} + +
    +
    + {{ form.description.label_tag }} + {{ form.description }} +
    +
    + {{ form.chart_type.label_tag }} + {{ form.chart_type }} +
    +
    + {{ form.is_data_table_visible.label_tag }} + {{ form.is_data_table_visible }} +
    +
    + {{ form.target_goal.label_tag }} + {{ form.target_goal }} +
    + +
    + +
    +
    + +{% endblock content_form %} + +{% endblock %} === added file 'dashboard_app/templates/dashboard_app/image_report_detail.html' --- dashboard_app/templates/dashboard_app/image_report_detail.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/image_report_detail.html 2013-09-12 14:12:07 +0000 @@ -0,0 +1,80 @@ +{% extends "dashboard_app/_content.html" %} +{% load i18n %} + +{% block extrahead %} +{{ block.super }} + +{% endblock %} + +{% block content %} + +

    Image Report {{ image_report.name }}

    + +
    +
    + Status:  + {% if image_report.is_published %} + + Published + + {% else %} + + Not Published + + {% endif %} +
    +
    + Description: {{ image_report.description }} +
    +
    + Edit this image report. +
    +
    + {% if image_report.is_published %} + Unpublish this image report. + {% else %} + Publish this image report. +{% endif %} +
    +
    + +

    Charts

    + + + +
    + {% for image_chart in image_report.imagereportchart_set.all %} +
    + {{ image_chart.name }}   + + details +   + + preview + +
    +
    + Description: {{ image_chart.description }} +
    +
    + Chart type: {{ image_chart.chart_type }} +
    +
    + Data table visible: {{ image_chart.is_data_table_visible }} +
    +
    + Target goal: {{ image_chart.target_goal|floatformat:"-2" }} +
    +
    + {% empty %} +
    +
  • No charts added yet.
  • +
    + {% endfor %} +
    + +{% endblock %} === added file 'dashboard_app/templates/dashboard_app/image_report_form.html' --- dashboard_app/templates/dashboard_app/image_report_form.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/image_report_form.html 2013-09-12 14:12:07 +0000 @@ -0,0 +1,45 @@ +{% extends "dashboard_app/_content.html" %} + +{% block extrahead %} +{{ block.super }} + +{% endblock %} + +{% block content %} +

    Image Reports 2.0

    + +{% block content_form %} +
    {% csrf_token %} + + {% if form.errors %} +
    +
    + {{ form.non_field_errors }} +
      + {% for field in form %} + {% if field.errors %} +
    • {{ field.label }}: {{ field.errors|striptags }}
    • + {% endif %} + {% endfor %} +
    +
    +
    + {% endif %} + +
    + {{ form.name.label_tag }} + {{ form.name }} +
    +
    + {{ form.description.label_tag }} + {{ form.description }} +
    + +
    + +
    +
    + +{% endblock content_form %} + +{% endblock %} === added file 'dashboard_app/templates/dashboard_app/image_report_list.html' --- dashboard_app/templates/dashboard_app/image_report_list.html 1970-01-01 00:00:00 +0000 +++ dashboard_app/templates/dashboard_app/image_report_list.html 2013-09-11 22:18:16 +0000 @@ -0,0 +1,37 @@ +{% extends "dashboard_app/_content.html" %} + +{% block extrahead %} +{{ block.super }} + +{% endblock %} + +{% block content %} +

    Image Reports 2.0

    + +

    + + Add new Image Report + +

    + +{% for image_report in image_reports %} +
    + + {% if image_report.is_published %} +
    + Published +
    + {% else %} +
    + Not Published +
    + {% endif %} +
    + {{ image_report.description }} +
    +
    +{% endfor %} +{% endblock %} === modified file 'dashboard_app/urls.py' --- dashboard_app/urls.py 2013-09-05 11:27:15 +0000 +++ dashboard_app/urls.py 2013-09-13 14:16:05 +0000 @@ -33,6 +33,8 @@ url(r'^filters/\+add$', 'filters.views.filter_add'), url(r'^filters/\+add-preview-json$', 'filters.views.filter_preview_json'), url(r'^filters/\+add-cases-for-test-json$', 'filters.views.filter_add_cases_for_test_json'), + url(r'^filters/\+get-tests-json$', 'filters.views.get_tests_json'), + url(r'^filters/\+get-test-cases-json$', 'filters.views.get_test_cases_json'), url(r'^filters/\+attribute-name-completion-json$', 'filters.views.filter_attr_name_completion_json'), url(r'^filters/\+attribute-value-completion-json$', 'filters.views.filter_attr_value_completion_json'), url(r'^filters/~(?P[^/]+)/(?P[a-zA-Z0-9-_]+)$', 'filters.views.filter_detail'), @@ -63,6 +65,18 @@ url(r'^permalink/bundle/(?P[0-9a-z]+)/$', 'redirect_to_bundle'), url(r'^permalink/bundle/(?P[0-9a-z]+)/(?P.*)$', 'redirect_to_bundle'), url(r'^image-reports/$', 'images.image_report_list'), + url(r'^image-charts/$', 'image_reports.views.image_report_list'), + url(r'^image-charts/(?P[a-zA-Z0-9-_]+)$', 'image_reports.views.image_report_detail'), + url(r'^image-charts/\+add$', 'image_reports.views.image_report_add'), + url(r'^image-charts/(?P[a-zA-Z0-9-_]+)/\+edit$', 'image_reports.views.image_report_edit'), + url(r'^image-charts/(?P[a-zA-Z0-9-_]+)/\+publish$', 'image_reports.views.image_report_publish'), + url(r'^image-charts/(?P[a-zA-Z0-9-_]+)/\+unpublish$', 'image_reports.views.image_report_unpublish'), + url(r'^image-chart/(?P[a-zA-Z0-9-_]+)$', 'image_reports.views.image_chart_detail'), + url(r'^image-chart/\+add$', 'image_reports.views.image_chart_add'), + url(r'^image-chart/(?P[a-zA-Z0-9-_]+)/\+edit$', 'image_reports.views.image_chart_edit'), + url(r'^image-chart/(?P[a-zA-Z0-9-_]+)/\+add-filter$', 'image_reports.views.image_chart_filter_add'), + url(r'^image-chart-filter/(?P[a-zA-Z0-9-_]+)$', 'image_reports.views.image_chart_filter_edit'), + url(r'^image-chart-filter/(?P[a-zA-Z0-9-_]+)/\+delete$', 'image_reports.views.image_chart_filter_delete'), url(r'^pmqa$', 'pmqa.pmqa_view'), url(r'^pmqa(?P/[a-zA-Z0-9/._-]+/)(?P[a-zA-Z0-9-_]+)$', 'pmqa.pmqa_filter_view'), url(r'^pmqa(?P/[a-zA-Z0-9/._-]+/)(?P[a-zA-Z0-9-_]+)/json$', 'pmqa.pmqa_filter_view_json'), === modified file 'dashboard_app/views/filters/tables.py' --- dashboard_app/views/filters/tables.py 2013-01-10 01:56:51 +0000 +++ dashboard_app/views/filters/tables.py 2013-09-09 11:47:00 +0000 @@ -109,6 +109,15 @@ return TestRunFilter.objects.filter(public=True) +class AllFiltersSimpleTable(DataTablesTable): + + name = TemplateColumn(''' + {{ record.name }} + ''') + + def get_queryset(self): + return TestRunFilter.objects.all() + class TestRunColumn(Column): def render(self, record): === modified file 'dashboard_app/views/filters/views.py' --- dashboard_app/views/filters/views.py 2013-01-10 01:56:51 +0000 +++ dashboard_app/views/filters/views.py 2013-09-09 11:47:00 +0000 @@ -20,6 +20,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.contenttypes.models import ContentType +from django.core import serializers from django.core.exceptions import PermissionDenied, ValidationError from django.core.urlresolvers import reverse from django.http import HttpResponse, HttpResponseRedirect @@ -37,6 +38,7 @@ evaluate_filter, ) from dashboard_app.models import ( + Bundle, NamedAttribute, Test, TestCase, @@ -234,6 +236,24 @@ mimetype='application/json') +def get_tests_json(request): + + tests = Test.objects.filter( + test_runs__bundle__bundle_stream__testrunfilter__id=request.GET['id']).distinct() + + data = serializers.serialize('json', tests) + return HttpResponse(data, mimetype='application/json') + + +def get_test_cases_json(request): + + test_cases = TestCase.objects.filter( + test__test_runs__bundle__bundle_stream__testrunfilter__id=request.GET['id']).distinct() + + data = serializers.serialize('json', test_cases) + return HttpResponse(data, mimetype='application/json') + + def filter_attr_name_completion_json(request): term = request.GET['term'] content_type_id = ContentType.objects.get_for_model(TestRun).id === added directory 'dashboard_app/views/image_reports' === added file 'dashboard_app/views/image_reports/__init__.py' --- dashboard_app/views/image_reports/__init__.py 1970-01-01 00:00:00 +0000 +++ dashboard_app/views/image_reports/__init__.py 2013-09-03 15:03:06 +0000 @@ -0,0 +1,17 @@ +# Copyright (C) 2010-2013 Linaro Limited +# +# Author: Stevan Radakovic +# +# This file is part of Launch Control. +# +# Launch Control is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License version 3 +# as published by the Free Software Foundation +# +# Launch Control is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Launch Control. If not, see . === added file 'dashboard_app/views/image_reports/forms.py' --- dashboard_app/views/image_reports/forms.py 1970-01-01 00:00:00 +0000 +++ dashboard_app/views/image_reports/forms.py 2013-09-13 12:59:23 +0000 @@ -0,0 +1,91 @@ +# Copyright (C) 2010-2013 Linaro Limited +# +# Author: Stevan Radakovic +# +# This file is part of Launch Control. +# +# Launch Control is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License version 3 +# as published by the Free Software Foundation +# +# Launch Control is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Launch Control. If not, see . + +from django import forms + +from dashboard_app.models import ( + ImageReport, + ImageReportChart, + ImageChartFilter, + ImageChartTest, + ImageChartTestCase, + Test, + TestCase, +) + + +class ImageReportEditorForm(forms.ModelForm): + class Meta: + model = ImageReport + exclude = ('owner', 'is_published',) + + def save(self, commit=True, **kwargs): + instance = super(ImageReportEditorForm, + self).save(commit=commit, **kwargs) + return instance + + def is_valid(self): + return super(ImageReportEditorForm, self).is_valid() + + def full_clean(self): + super(ImageReportEditorForm, self).full_clean() + + def __init__(self, user, *args, **kwargs): + super(ImageReportEditorForm, self).__init__(*args, **kwargs) + + +class ImageReportChartForm(forms.ModelForm): + class Meta: + model = ImageReportChart + widgets = {'image_report': forms.HiddenInput} + + def __init__(self, user, *args, **kwargs): + super(ImageReportChartForm, self).__init__(*args, **kwargs) + if len(self.instance.imagechartfilter_set.all()) != 0: + self.fields['chart_type'].label = "" + self.fields['chart_type'].widget = forms.HiddenInput() + + def save(self, commit=True, **kwargs): + instance = super(ImageReportChartForm, + self).save(commit=commit, **kwargs) + return instance + + +class ImageChartFilterForm(forms.ModelForm): + + image_chart_tests = forms.ModelMultipleChoiceField( + widget=forms.MultipleHiddenInput, + queryset=Test.objects.all().order_by("id"), + required=False) + image_chart_test_cases = forms.ModelMultipleChoiceField( + widget=forms.MultipleHiddenInput, + queryset=TestCase.objects.all().order_by("id"), + required=False) + + class Meta: + model = ImageChartFilter + widgets = {'filter': forms.HiddenInput, + 'image_chart': forms.HiddenInput,} + + def __init__(self, user, *args, **kwargs): + super(ImageChartFilterForm, self).__init__(*args, **kwargs) + + def save(self, commit=True, **kwargs): + instance = super(ImageChartFilterForm, + self).save(commit=commit, **kwargs) + return instance === added file 'dashboard_app/views/image_reports/views.py' --- dashboard_app/views/image_reports/views.py 1970-01-01 00:00:00 +0000 +++ dashboard_app/views/image_reports/views.py 2013-09-13 12:59:23 +0000 @@ -0,0 +1,325 @@ +# Copyright (C) 2010-2013 Linaro Limited +# +# Author: Stevan Radakovic +# +# This file is part of Launch Control. +# +# Launch Control is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License version 3 +# as published by the Free Software Foundation +# +# Launch Control is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Launch Control. If not, see . + +import json + +from django.contrib.auth.decorators import login_required +from django.core.exceptions import PermissionDenied, ValidationError +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.utils.safestring import mark_safe + +from lava_server.bread_crumbs import ( + BreadCrumb, + BreadCrumbTrail, +) + +from dashboard_app.views import index + +from dashboard_app.views.image_reports.forms import ( + ImageReportEditorForm, + ImageReportChartForm, + ImageChartFilterForm, + ) + +from dashboard_app.models import ( + ImageReport, + ImageReportChart, + ImageChartFilter, + ImageChartTest, + ImageChartTestCase, + Test, + TestCase, + TestRunFilter, + ) + +from dashboard_app.views.filters.tables import AllFiltersSimpleTable + + + +@BreadCrumb("Image reports", parent=index) +def image_report_list(request): + + if request.user.is_authenticated(): + image_reports = ImageReport.objects.all() + else: + image_reports = None + + return render_to_response( + 'dashboard_app/image_report_list.html', { + "image_reports": image_reports, + }, RequestContext(request) + ) + +@BreadCrumb("Image report {name}", parent=image_report_list, needs=['name']) +def image_report_detail(request, name): + image_report = ImageReport.objects.get(name=name) + + return render_to_response( + 'dashboard_app/image_report_detail.html', { + 'image_report': image_report, + 'bread_crumb_trail': BreadCrumbTrail.leading_to( + image_report_detail, name=name), + }, RequestContext(request) + ) + +@BreadCrumb("Add new image report", parent=image_report_list) +@login_required +def image_report_add(request): + return image_report_form( + request, + BreadCrumbTrail.leading_to(image_report_add)) + +@BreadCrumb("Update image report {name}", parent=image_report_list, + needs=['name']) +@login_required +def image_report_edit(request, name): + image_report = ImageReport.objects.get(name=name) + return image_report_form( + request, + BreadCrumbTrail.leading_to(image_report_edit, + name=name), + instance=image_report) + +@BreadCrumb("Publish image report {name}", parent=image_report_list, + needs=['name']) +@login_required +def image_report_publish(request, name): + image_report = ImageReport.objects.get(name=name) + image_report.is_published = True + image_report.save() + + return render_to_response( + 'dashboard_app/image_report_detail.html', { + 'image_report': image_report, + 'bread_crumb_trail': BreadCrumbTrail.leading_to( + image_report_detail, name=name), + }, RequestContext(request) + ) + +@BreadCrumb("Unpublish image report {name}", parent=image_report_list, + needs=['name']) +@login_required +def image_report_unpublish(request, name): + image_report = ImageReport.objects.get(name=name) + image_report.is_published = False + image_report.save() + + return render_to_response( + 'dashboard_app/image_report_detail.html', { + 'image_report': image_report, + 'bread_crumb_trail': BreadCrumbTrail.leading_to( + image_report_detail, name=name), + }, RequestContext(request) + ) + +def image_report_form(request, bread_crumb_trail, instance=None): + + if request.method == 'POST': + + form = ImageReportEditorForm(request.user, request.POST, + instance=instance) + if form.is_valid(): + image_report = form.save() + return HttpResponseRedirect(image_report.get_absolute_url()) + + else: + form = ImageReportEditorForm(request.user, instance=instance) + + return render_to_response( + 'dashboard_app/image_report_form.html', { + 'bread_crumb_trail': bread_crumb_trail, + 'form': form, + }, RequestContext(request)) + +@BreadCrumb("Image chart details", parent=image_report_list) +def image_chart_detail(request, id): + image_chart = ImageReportChart.objects.get(id=id) + + return render_to_response( + 'dashboard_app/image_report_chart_detail.html', { + 'image_chart': image_chart, + 'bread_crumb_trail': BreadCrumbTrail.leading_to( + image_chart_detail, id=id), + }, RequestContext(request) + ) + +@BreadCrumb("Add new image chart", parent=image_report_list) +@login_required +def image_chart_add(request): + return image_chart_form( + request, + BreadCrumbTrail.leading_to(image_chart_add)) + +@BreadCrumb("Update image chart", parent=image_report_list) +@login_required +def image_chart_edit(request, id): + image_chart = ImageReportChart.objects.get(id=id) + return image_chart_form( + request, + BreadCrumbTrail.leading_to(image_chart_edit, + id=id), + instance=image_chart) + +def image_chart_form(request, bread_crumb_trail, instance=None): + + if request.method == 'POST': + + form = ImageReportChartForm(request.user, request.POST, + instance=instance) + if form.is_valid(): + image_chart = form.save() + return HttpResponseRedirect( + image_chart.get_absolute_url()) + + else: + form = ImageReportChartForm(request.user, instance=instance) + + if not instance: + image_report_id = request.GET.get('image_report_id', None) + else: + image_report_id = instance.image_report.id + + filters_table = AllFiltersSimpleTable("all-filters", None) + + return render_to_response( + 'dashboard_app/image_report_chart_form.html', { + 'bread_crumb_trail': bread_crumb_trail, + 'form': form, + 'filters_table': filters_table, + 'image_report_id': image_report_id, + }, RequestContext(request)) + +@BreadCrumb("Image chart add filter", parent=image_report_list) +def image_chart_filter_add(request, id): + image_chart = ImageReportChart.objects.get(id=id) + return image_chart_filter_form( + request, + BreadCrumbTrail.leading_to(image_chart_filter_add), + chart_instance=image_chart) + +@BreadCrumb("Update image chart filter", parent=image_report_list) +@login_required +def image_chart_filter_edit(request, id): + image_chart_filter = ImageChartFilter.objects.get(id=id) + return image_chart_filter_form( + request, + BreadCrumbTrail.leading_to(image_chart_filter_edit, id=id), + instance=image_chart_filter) + +@BreadCrumb("Image chart add filter", parent=image_report_list) +def image_chart_filter_delete(request, id): + image_chart_filter = ImageChartFilter.objects.get(id=id) + url = image_chart_filter.image_chart.get_absolute_url() + image_chart_filter.delete() + return HttpResponseRedirect(url) + +def image_chart_filter_form(request, bread_crumb_trail, chart_instance=None, + instance=None): + + if instance: + chart_instance = instance.image_chart + + if request.method == 'POST': + + form = ImageChartFilterForm(request.user, request.POST, + instance=instance) + + if form.is_valid(): + + chart_filter = form.save() + aliases = request.POST.getlist('aliases') + + + if chart_filter.image_chart.chart_type == 'pass/fail': + + image_chart_tests = Test.objects.filter( + imagecharttest__image_chart_filter=chart_filter).order_by( + 'id') + + tests = form.cleaned_data['image_chart_tests'] + + for index, test in enumerate(tests): + if test in image_chart_tests: + chart_test = ImageChartTest.objects.get( + image_chart_filter=chart_filter, test=test) + chart_test.name = aliases[index] + chart_test.save() + else: + chart_test = ImageChartTest() + chart_test.image_chart_filter = chart_filter + chart_test.test = test + chart_test.name = aliases[index] + chart_test.save() + + for index, chart_test in enumerate(image_chart_tests): + if chart_test not in tests: + ImageChartTest.objects.get( + image_chart_filter=chart_filter, + test=chart_test).delete() + + return HttpResponseRedirect( + chart_filter.image_chart.get_absolute_url()) + + else: + + image_chart_test_cases = TestCase.objects.filter( + imagecharttestcase__image_chart_filter= + chart_filter).order_by('id') + + test_cases = form.cleaned_data['image_chart_test_cases'] + + for index, test_case in enumerate(test_cases): + if test_case in image_chart_test_cases: + chart_test_case = ImageChartTestCase.objects.get( + image_chart_filter=chart_filter, + test_case=test_case) + chart_test_case.name = aliases[index] + chart_test_case.save() + else: + chart_test_case = ImageChartTestCase() + chart_test_case.image_chart_filter = chart_filter + chart_test_case.test_case = test_case + chart_test_case.name = aliases[index] + chart_test_case.save() + + for index, chart_test_case in enumerate( + image_chart_test_cases): + if chart_test_case not in test_cases: + ImageChartTestCase.objects.get( + image_chart_filter=chart_filter, + test_case=chart_test_case).delete() + + return HttpResponseRedirect( + chart_filter.image_chart.get_absolute_url()) + + else: + form = ImageChartFilterForm(request.user, instance=instance, + initial={'image_chart': chart_instance}) + + filters_table = AllFiltersSimpleTable("all-filters", None) + + return render_to_response( + 'dashboard_app/image_chart_filter_form.html', { + 'bread_crumb_trail': bread_crumb_trail, + 'filters_table': filters_table, + 'image_chart': chart_instance, + 'instance': instance, + 'form': form, + }, RequestContext(request))