=== added file 'dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py'
@@ -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'
@@ -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'
@@ -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'
@@ -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 = '<hr><div class="filter-title">' + title + '</div>';
+
+ if ($('#id_chart_type').val() == "pass/fail") {
+ test_label = "Tests";
+ } else {
+ test_label = "Test Cases";
+ }
+
+ content += '<div class="selector"><div class="selector-available"><h2>' +
+ 'Select ' + test_label + '</h2>';
+
+ content += '<select id="available_tests" multiple class="filtered">';
+ for (i in data) {
+ if ($('#id_chart_type').val() == "pass/fail") {
+ content += '<option value="' + data[i].pk + '">' +
+ data[i].fields.test_id + '</option>';
+ } else {
+ content += '<option value="' + data[i].pk + '">' +
+ data[i].fields.test_case_id + '</option>';
+ }
+ }
+ content += '</select>';
+
+ content += '<a id="add_all_link" href="javascript: void(0)">' +
+ 'Choose All</a>';
+ content += '</div>';
+
+ content += '<ul class="selector-chooser">' +
+ '<li><a href="javascript: void(0)" id="add_link"' +
+ 'class="selector-add active"></a></li>' +
+ '<li><a href="javascript: void(0)" id="remove_link"' +
+ 'class="selector-remove active"></a></li>' +
+ '</ul>';
+
+ content += '<div class="selector-chosen"><h2>' +
+ 'Choosen ' + test_label + '</h2>';
+
+ content += '<select id="chosen_tests" onchange="toggle_alias()" multiple class="filtered"></select>';
+ content += '<a id="remove_all_link" href="javascript: void(0)">' +
+ 'Remove All</a>';
+ content += '</div></div>';
+
+ content += '<div id="alias_container">Alias<br/>';
+ content += '<input type="text" onkeyup="copy_alias(this);" id="alias" />';
+ content += '</div>';
+
+ $('<div id="filter-container"></div>').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";
+ }
+ $('<input type="hidden" name="' + field_name +
+ '" value="'+ $(this).val() + '" />').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) {
+ $('<input type="hidden" class="alias" data-sid="' + $(this).val() +
+ '" name="aliases" id="alias_' + $(this).val() +
+ '" />').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 = $('<div id="filter_select_dialog"></div>');
+ $('#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'
@@ -0,0 +1,109 @@
+{% extends "dashboard_app/_content.html" %}
+{% load i18n %}
+{% load django_tables2 %}
+
+{% block extrahead %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/>
+<script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/image-report-editor.js"></script>
+
+{% endblock %}
+
+
+{% block content %}
+<h1>Image Chart Filter</h1>
+
+{% block content_form %}
+<form action="" method="post">{% csrf_token %}
+
+ {% if form.errors %}
+ <div class="errors">
+ <div>
+ {{ form.non_field_errors }}
+ <ul>
+ {% for field in form %}
+ {% if field.errors %}
+ <li>{{ field.label }}: {{ field.errors|striptags }}</li>
+ {% endif %}
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
+ {% endif %}
+
+ <div id="filters_div">
+ <div id="add_filter_link">
+ <a href="#" onclick="select_filter()">Select filter</a>
+ {{ form.filter }}
+ {{ form.image_chart }}
+ <input type="hidden" id="id_chart_type" value="{{ image_chart.chart_type }}"/>
+ {{ form.image_chart_tests }}
+ {{ form.image_chart_test_cases }}
+ </div>
+
+ <div>
+ {{ form.representation.label_tag }}
+ {{ form.representation }}
+ </div>
+ </div>
+
+ <div id="aliases_div">
+ </div>
+
+ <div class="submit-button">
+ <input type="submit" value="Save" />
+ </div>
+</form>
+
+{% endblock content_form %}
+
+{% render_table filters_table %}
+
+<div id="loading_dialog">
+<img src="{{ STATIC_URL }}dashboard_app/images/ajax-progress.gif" alt="Loading..." />
+</div>
+
+<script type="text/javascript">
+ $().ready(function () {
+
+ init_filter_dialog();
+ init_loading_dialog();
+
+ $('form').submit(function() {
+ add_selected_options();
+ sort_aliases();
+ });
+
+ {% if form.filter.value %}
+ filters_callback('{{ instance.filter.id }}',
+ '{{ instance.filter.name }}');
+
+ if ($('#id_chart_type').val() == "pass/fail") {
+ {% for test in instance.imagecharttest_set.all %}
+ $('#available_tests option[value="{{ test.test_id }}"]').attr('selected', 'selected');
+ {% endfor %}
+ } else {
+ {% for test in instance.imagecharttestcase_set.all %}
+ $('#available_tests option[value="{{ test.test_case_id }}"]').attr('selected', 'selected');
+ {% endfor %}
+ }
+
+ move_options('available_tests', 'chosen_tests');
+
+ if ($('#id_chart_type').val() == "pass/fail") {
+ {% for test in instance.imagecharttest_set.all %}
+ $('#alias_{{ test.test_id }}').val('{{ test.name }}');
+ {% endfor %}
+ } else {
+ {% for test in instance.imagecharttestcase_set.all %}
+
+ $('#alias_{{ test.test_case_id }}').val('{{ test.name }}');
+ {% endfor %}
+ }
+
+ {% endif %}
+});
+
+</script>
+
+{% endblock %}
=== added file 'dashboard_app/templates/dashboard_app/image_report_chart_detail.html'
@@ -0,0 +1,86 @@
+{% extends "dashboard_app/_content.html" %}
+{% load i18n %}
+
+{% block extrahead %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/>
+{% endblock %}
+
+{% block content %}
+
+<h1>Image Chart {{ image_chart.name }}</h1>
+
+
+<div class="fields-container">
+ <div class="form-field">
+ <a href="{{ image_chart.get_absolute_url }}/+edit">Edit</a> this chart.
+ </div>
+ <div class="form-field">
+ Description: {{ image_chart.description }}
+ </div>
+ <div class="form-field">
+ Chart type: {{ image_chart.chart_type }}
+ </div>
+ <div class="form-field">
+ Data table visible: {{ image_chart.is_data_table_visible }}
+ </div>
+ <div class="form-field">
+ Target goal: {{ image_chart.target_goal|floatformat:"-2" }}
+ </div>
+</div>
+
+
+<h3>Filters</h3>
+
+<div class="fields-container">
+ <div id="add_filter_link">
+ <a href="{{ image_chart.get_absolute_url }}/+add-filter">Add filter</a>
+ </div>
+</div>
+
+<div class="list-container">
+ {% for chart_filter in image_chart.imagechartfilter_set.all %}
+ <div class="chart-title">
+ {{ chart_filter.filter.name }}
+ <a style="font-size: 13px;" href="{{ chart_filter.get_absolute_url }}">
+ edit
+ </a>
+ <a style="font-size: 13px;" href="{{ chart_filter.get_absolute_url }}/+delete">
+ remove
+ </a>
+ </div>
+ <div>
+ {% 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 %}
+ </div>
+ <div>
+ Representation: {{ chart_filter.representation }}
+ </div>
+
+ <hr/>
+ {% empty %}
+ <div>
+ <li>No filters added yet.</li>
+ </div>
+ {% endfor %}
+</div>
+
+
+{% endblock %}
=== added file 'dashboard_app/templates/dashboard_app/image_report_chart_form.html'
@@ -0,0 +1,62 @@
+{% extends "dashboard_app/_content.html" %}
+{% load i18n %}
+{% load django_tables2 %}
+
+{% block extrahead %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/>
+
+{% endblock %}
+
+
+{% block content %}
+<h1>Add Image Charts 2.0</h1>
+
+{% block content_form %}
+<form action="" method="post">{% csrf_token %}
+
+ {% if form.errors %}
+ <div class="errors">
+ <div>
+ {{ form.non_field_errors }}
+ <ul>
+ {% for field in form %}
+ {% if field.errors %}
+ <li>{{ field.label }}: {{ field.errors|striptags }}</li>
+ {% endif %}
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
+ {% endif %}
+
+ <div class="form-field">
+ {{ form.name.label_tag }}
+ {{ form.name }}
+ <input type="hidden" id="id_image_report" name="image_report" value="{{ image_report_id }}"/>
+ </div>
+ <div class="form-field">
+ {{ form.description.label_tag }}
+ {{ form.description }}
+ </div>
+ <div class="form-field">
+ {{ form.chart_type.label_tag }}
+ {{ form.chart_type }}
+ </div>
+ <div class="form-field">
+ {{ form.is_data_table_visible.label_tag }}
+ {{ form.is_data_table_visible }}
+ </div>
+ <div class="form-field">
+ {{ form.target_goal.label_tag }}
+ {{ form.target_goal }}
+ </div>
+
+ <div class="submit-button">
+ <input type="submit" value="Save" />
+ </div>
+</form>
+
+{% endblock content_form %}
+
+{% endblock %}
=== added file 'dashboard_app/templates/dashboard_app/image_report_detail.html'
@@ -0,0 +1,80 @@
+{% extends "dashboard_app/_content.html" %}
+{% load i18n %}
+
+{% block extrahead %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/>
+{% endblock %}
+
+{% block content %}
+
+<h1>Image Report {{ image_report.name }}</h1>
+
+<div class="fields-container">
+ <div class="form-field">
+ Status:
+ {% if image_report.is_published %}
+ <span style="font-weight: bold; color: green;">
+ Published
+ </span>
+ {% else %}
+ <span style="font-weight: bold; color: orange;">
+ Not Published
+ </span>
+ {% endif %}
+ </div>
+ <div class="form-field">
+ Description: {{ image_report.description }}
+ </div>
+ <div class="form-field">
+ <a href="{{ image_report.get_absolute_url }}/+edit">Edit</a> this image report.
+ </div>
+ <div class="form-field">
+ {% if image_report.is_published %}
+ <a href="{{ image_report.get_absolute_url }}/+unpublish">Unpublish</a> this image report.
+ {% else %}
+ <a href="{{ image_report.get_absolute_url }}/+publish">Publish</a> this image report.
+{% endif %}
+ </div>
+</div>
+
+<h3>Charts</h3>
+
+<div class="fields-container">
+ <a href="{% url dashboard_app.views.image_reports.views.image_chart_add %}?image_report_id={{ image_report.id }}">
+ Add new chart
+ </a>
+</div>
+
+<div class="list-container">
+ {% for image_chart in image_report.imagereportchart_set.all %}
+ <div class="chart-title">
+ {{ image_chart.name }}
+ <a style="font-size: 13px;" href="{{ image_chart.get_absolute_url }}">
+ details
+ </a>
+ <a style="font-size: 13px;" href="{{ image_chart.get_absolute_url }}">
+ preview
+ </a>
+ </div>
+ <div>
+ Description: {{ image_chart.description }}
+ </div>
+ <div>
+ Chart type: {{ image_chart.chart_type }}
+ </div>
+ <div>
+ Data table visible: {{ image_chart.is_data_table_visible }}
+ </div>
+ <div>
+ Target goal: {{ image_chart.target_goal|floatformat:"-2" }}
+ </div>
+ <hr/>
+ {% empty %}
+ <div>
+ <li>No charts added yet.</li>
+ </div>
+ {% endfor %}
+</div>
+
+{% endblock %}
=== added file 'dashboard_app/templates/dashboard_app/image_report_form.html'
@@ -0,0 +1,45 @@
+{% extends "dashboard_app/_content.html" %}
+
+{% block extrahead %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/>
+{% endblock %}
+
+{% block content %}
+<h1>Image Reports 2.0</h1>
+
+{% block content_form %}
+<form action="" method="post">{% csrf_token %}
+
+ {% if form.errors %}
+ <div class="errors">
+ <div>
+ {{ form.non_field_errors }}
+ <ul>
+ {% for field in form %}
+ {% if field.errors %}
+ <li>{{ field.label }}: {{ field.errors|striptags }}</li>
+ {% endif %}
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
+ {% endif %}
+
+<div class="form-field">
+ {{ form.name.label_tag }}
+ {{ form.name }}
+</div>
+<div class="form-field">
+ {{ form.description.label_tag }}
+ {{ form.description }}
+</div>
+
+<div class="submit-button">
+<input type="submit" value="Save" />
+</div>
+</form>
+
+{% endblock content_form %}
+
+{% endblock %}
=== added file 'dashboard_app/templates/dashboard_app/image_report_list.html'
@@ -0,0 +1,37 @@
+{% extends "dashboard_app/_content.html" %}
+
+{% block extrahead %}
+{{ block.super }}
+<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/>
+{% endblock %}
+
+{% block content %}
+<h1>Image Reports 2.0</h1>
+
+<p style="margin-left: 10px;">
+ <a href="{% url dashboard_app.views.image_reports.views.image_report_add %}">
+ Add new Image Report
+ </a>
+</p>
+
+{% for image_report in image_reports %}
+<div class="list-container">
+ <div style="float: left;">
+ <a href="{{ image_report.get_absolute_url }}">{{ image_report.name }}</a>
+
+ </div>
+ {% if image_report.is_published %}
+ <div style="font-weight: bold; float: right; color: green;">
+ Published
+ </div>
+ {% else %}
+ <div style="font-weight: bold; float: right; color: orange;">
+ Not Published
+ </div>
+ {% endif %}
+ <div style="clear: both;">
+ {{ image_report.description }}
+ </div>
+</div>
+{% endfor %}
+{% endblock %}
=== modified file 'dashboard_app/urls.py'
@@ -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<username>[^/]+)/(?P<name>[a-zA-Z0-9-_]+)$', 'filters.views.filter_detail'),
@@ -63,6 +65,18 @@
url(r'^permalink/bundle/(?P<content_sha1>[0-9a-z]+)/$', 'redirect_to_bundle'),
url(r'^permalink/bundle/(?P<content_sha1>[0-9a-z]+)/(?P<trailing>.*)$', '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<name>[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<name>[a-zA-Z0-9-_]+)/\+edit$', 'image_reports.views.image_report_edit'),
+ url(r'^image-charts/(?P<name>[a-zA-Z0-9-_]+)/\+publish$', 'image_reports.views.image_report_publish'),
+ url(r'^image-charts/(?P<name>[a-zA-Z0-9-_]+)/\+unpublish$', 'image_reports.views.image_report_unpublish'),
+ url(r'^image-chart/(?P<id>[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<id>[a-zA-Z0-9-_]+)/\+edit$', 'image_reports.views.image_chart_edit'),
+ url(r'^image-chart/(?P<id>[a-zA-Z0-9-_]+)/\+add-filter$', 'image_reports.views.image_chart_filter_add'),
+ url(r'^image-chart-filter/(?P<id>[a-zA-Z0-9-_]+)$', 'image_reports.views.image_chart_filter_edit'),
+ url(r'^image-chart-filter/(?P<id>[a-zA-Z0-9-_]+)/\+delete$', 'image_reports.views.image_chart_filter_delete'),
url(r'^pmqa$', 'pmqa.pmqa_view'),
url(r'^pmqa(?P<pathname>/[a-zA-Z0-9/._-]+/)(?P<device_type>[a-zA-Z0-9-_]+)$', 'pmqa.pmqa_filter_view'),
url(r'^pmqa(?P<pathname>/[a-zA-Z0-9/._-]+/)(?P<device_type>[a-zA-Z0-9-_]+)/json$', 'pmqa.pmqa_filter_view_json'),
=== modified file 'dashboard_app/views/filters/tables.py'
@@ -109,6 +109,15 @@
return TestRunFilter.objects.filter(public=True)
+class AllFiltersSimpleTable(DataTablesTable):
+
+ name = TemplateColumn('''
+ <a href="#" onclick="filters_callback('{{ record.id }}', '{{ record.name }}');">{{ record.name }}</a>
+ ''')
+
+ def get_queryset(self):
+ return TestRunFilter.objects.all()
+
class TestRunColumn(Column):
def render(self, record):
=== modified file 'dashboard_app/views/filters/views.py'
@@ -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'
@@ -0,0 +1,17 @@
+# Copyright (C) 2010-2013 Linaro Limited
+#
+# Author: Stevan Radakovic <stevan.radakovic@linaro.org>
+#
+# 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 <http://www.gnu.org/licenses/>.
=== added file 'dashboard_app/views/image_reports/forms.py'
@@ -0,0 +1,91 @@
+# Copyright (C) 2010-2013 Linaro Limited
+#
+# Author: Stevan Radakovic <stevan.radakovic@linaro.org>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+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'
@@ -0,0 +1,325 @@
+# Copyright (C) 2010-2013 Linaro Limited
+#
+# Author: Stevan Radakovic <stevan.radakovic@linaro.org>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+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))