Merge lp:~stevanr/lava-dashboard/image-report-editor-frontend into lp:lava-dashboard
- image-report-editor-frontend
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 422 |
Proposed branch: | lp:~stevanr/lava-dashboard/image-report-editor-frontend |
Merge into: | lp:lava-dashboard |
Diff against target: |
1948 lines (+1720/-95) 16 files modified
dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py (+388/-0) dashboard_app/models.py (+134/-95) dashboard_app/static/dashboard_app/css/image-charts.css (+82/-0) dashboard_app/static/dashboard_app/js/image-report-editor.js (+221/-0) dashboard_app/templates/dashboard_app/image_chart_filter_form.html (+109/-0) dashboard_app/templates/dashboard_app/image_report_chart_detail.html (+86/-0) dashboard_app/templates/dashboard_app/image_report_chart_form.html (+62/-0) dashboard_app/templates/dashboard_app/image_report_detail.html (+80/-0) dashboard_app/templates/dashboard_app/image_report_form.html (+45/-0) dashboard_app/templates/dashboard_app/image_report_list.html (+37/-0) dashboard_app/urls.py (+14/-0) dashboard_app/views/filters/tables.py (+9/-0) dashboard_app/views/filters/views.py (+20/-0) dashboard_app/views/image_reports/__init__.py (+17/-0) dashboard_app/views/image_reports/forms.py (+91/-0) dashboard_app/views/image_reports/views.py (+325/-0) |
To merge this branch: | bzr merge lp:~stevanr/lava-dashboard/image-report-editor-frontend |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Antonio Terceiro | Approve | ||
Review via email: mp+185255@code.launchpad.net |
Commit message
Description of the change
GUI for Image Report Editor. For details, see:
https:/
and
https:/
- 432. By Stevan Radaković
-
Fix ordering in aliases bug.
- 433. By Stevan Radaković
-
Small makeup changes.
- 434. By Stevan Radaković
-
Add comments to js file.
- 435. By Stevan Radaković
-
Remove empty options from select boxes.
- 436. By Stevan Radaković
-
Set redirect for image report chart add/edit view.
- 437. By Stevan Radaković
-
Chart type not editable when filters are present.
- 438. By Stevan Radaković
-
Fix aliases for test cases.
- 439. By Stevan Radaković
-
Revert migration delete. Add new migration step.
Stevan Radaković (stevanr) wrote : | # |
Of course you can, the only thing you have to do is something like:
"lava-server manage migrate dashboard_app 0029"
before the migration.
I realize our scripts on staging and production are not that sophisticated, so I reverted the deleted migration and created new one based on that migration step and my changes to the model.
- 440. By Stevan Radaković
-
Change database yet again.
- 441. By Stevan Radaković
-
Better way to update tests/test cases within filter.
- 442. By Stevan Radaković
-
Remove item menu for now.
Antonio Terceiro (terceiro) wrote : | # |
On Fri, Sep 13, 2013 at 10:19:41AM -0000, Stevan Radaković wrote:
> Of course you can, the only thing you have to do is something like:
> "lava-server manage migrate dashboard_app 0029" before the migration.
Sure, but that defeats the point of using migrations since it will not
require specific manual steps on a specific upgrade.
> I realize our scripts on staging and production are not that
> sophisticated, so I reverted the deleted migration and created new one
> based on that migration step and my changes to the model.
The point of migrations is to have your database evolve without manual
intervention other than "upgrade my database", and having this "upgrade
my datavase" action always to the right thing.
review approve
Preview Diff
1 | === added file 'dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py' |
2 | --- dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py 1970-01-01 00:00:00 +0000 |
3 | +++ dashboard_app/migrations/0031_auto__del_imagecharttestrun__add_imagecharttest__add_unique_imagechart.py 2013-09-13 13:13:49 +0000 |
4 | @@ -0,0 +1,388 @@ |
5 | +# -*- coding: utf-8 -*- |
6 | +import datetime |
7 | +from south.db import db |
8 | +from south.v2 import SchemaMigration |
9 | +from django.db import models |
10 | + |
11 | + |
12 | +class Migration(SchemaMigration): |
13 | + |
14 | + def forwards(self, orm): |
15 | + # Deleting model 'ImageChartTestRun' |
16 | + db.delete_table('dashboard_app_imagecharttestrun') |
17 | + |
18 | + # Adding model 'ImageChartTest' |
19 | + db.create_table('dashboard_app_imagecharttest', ( |
20 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
21 | + ('image_chart_filter', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.ImageChartFilter'])), |
22 | + ('test', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.Test'])), |
23 | + ('name', self.gf('django.db.models.fields.CharField')(max_length=200)), |
24 | + )) |
25 | + db.send_create_signal('dashboard_app', ['ImageChartTest']) |
26 | + |
27 | + # Adding unique constraint on 'ImageChartTest', fields ['image_chart_filter', 'test'] |
28 | + db.create_unique('dashboard_app_imagecharttest', ['image_chart_filter_id', 'test_id']) |
29 | + |
30 | + # Adding model 'ImageChartFilter' |
31 | + db.create_table('dashboard_app_imagechartfilter', ( |
32 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
33 | + ('image_chart', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.ImageReportChart'])), |
34 | + ('filter', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.TestRunFilter'], null=True, on_delete=models.SET_NULL)), |
35 | + ('representation', self.gf('django.db.models.fields.CharField')(default='lines', max_length=20)), |
36 | + )) |
37 | + db.send_create_signal('dashboard_app', ['ImageChartFilter']) |
38 | + |
39 | + # Deleting field 'ImageChartTestCase.image_chart' |
40 | + db.delete_column('dashboard_app_imagecharttestcase', 'image_chart_id') |
41 | + |
42 | + # Adding field 'ImageChartTestCase.image_chart_filter' |
43 | + db.add_column('dashboard_app_imagecharttestcase', 'image_chart_filter', |
44 | + self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['dashboard_app.ImageChartFilter']), |
45 | + keep_default=False) |
46 | + |
47 | + # Adding unique constraint on 'ImageChartTestCase', fields ['image_chart_filter', 'test_case'] |
48 | + db.create_unique('dashboard_app_imagecharttestcase', ['image_chart_filter_id', 'test_case_id']) |
49 | + |
50 | + # Adding field 'ImageReport.is_published' |
51 | + db.add_column('dashboard_app_imagereport', 'is_published', |
52 | + self.gf('django.db.models.fields.BooleanField')(default=False), |
53 | + keep_default=False) |
54 | + |
55 | + # Deleting field 'ImageReportChart.representation' |
56 | + db.delete_column('dashboard_app_imagereportchart', 'representation') |
57 | + |
58 | + # Adding field 'ImageReportChart.description' |
59 | + db.add_column('dashboard_app_imagereportchart', 'description', |
60 | + self.gf('django.db.models.fields.TextField')(null=True, blank=True), |
61 | + keep_default=False) |
62 | + |
63 | + |
64 | + def backwards(self, orm): |
65 | + # Removing unique constraint on 'ImageChartTestCase', fields ['image_chart_filter', 'test_case'] |
66 | + db.delete_unique('dashboard_app_imagecharttestcase', ['image_chart_filter_id', 'test_case_id']) |
67 | + |
68 | + # Removing unique constraint on 'ImageChartTest', fields ['image_chart_filter', 'test'] |
69 | + db.delete_unique('dashboard_app_imagecharttest', ['image_chart_filter_id', 'test_id']) |
70 | + |
71 | + # Adding model 'ImageChartTestRun' |
72 | + db.create_table('dashboard_app_imagecharttestrun', ( |
73 | + ('test_run', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.TestRun'])), |
74 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
75 | + ('name', self.gf('django.db.models.fields.CharField')(max_length=200)), |
76 | + ('image_chart', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dashboard_app.ImageReportChart'])), |
77 | + )) |
78 | + db.send_create_signal('dashboard_app', ['ImageChartTestRun']) |
79 | + |
80 | + # Deleting model 'ImageChartTest' |
81 | + db.delete_table('dashboard_app_imagecharttest') |
82 | + |
83 | + # Deleting model 'ImageChartFilter' |
84 | + db.delete_table('dashboard_app_imagechartfilter') |
85 | + |
86 | + # Adding field 'ImageChartTestCase.image_chart' |
87 | + db.add_column('dashboard_app_imagecharttestcase', 'image_chart', |
88 | + self.gf('django.db.models.fields.related.ForeignKey')(default=0, to=orm['dashboard_app.ImageReportChart']), |
89 | + keep_default=False) |
90 | + |
91 | + # Deleting field 'ImageChartTestCase.image_chart_filter' |
92 | + db.delete_column('dashboard_app_imagecharttestcase', 'image_chart_filter_id') |
93 | + |
94 | + # Deleting field 'ImageReport.is_published' |
95 | + db.delete_column('dashboard_app_imagereport', 'is_published') |
96 | + |
97 | + # Adding field 'ImageReportChart.representation' |
98 | + db.add_column('dashboard_app_imagereportchart', 'representation', |
99 | + self.gf('django.db.models.fields.CharField')(default='pass/fail', max_length=20), |
100 | + keep_default=False) |
101 | + |
102 | + # Deleting field 'ImageReportChart.description' |
103 | + db.delete_column('dashboard_app_imagereportchart', 'description') |
104 | + |
105 | + |
106 | + models = { |
107 | + 'auth.group': { |
108 | + 'Meta': {'object_name': 'Group'}, |
109 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
110 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
111 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
112 | + }, |
113 | + 'auth.permission': { |
114 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, |
115 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
116 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), |
117 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
118 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
119 | + }, |
120 | + 'auth.user': { |
121 | + 'Meta': {'object_name': 'User'}, |
122 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
123 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), |
124 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
125 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), |
126 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
127 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
128 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
129 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
130 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
131 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
132 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
133 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), |
134 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
135 | + }, |
136 | + 'contenttypes.contenttype': { |
137 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
138 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
139 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
140 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
141 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
142 | + }, |
143 | + 'dashboard_app.attachment': { |
144 | + 'Meta': {'object_name': 'Attachment'}, |
145 | + 'content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True'}), |
146 | + 'content_filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}), |
147 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), |
148 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
149 | + 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), |
150 | + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), |
151 | + 'public_url': ('django.db.models.fields.URLField', [], {'max_length': '512', 'blank': 'True'}) |
152 | + }, |
153 | + 'dashboard_app.bundle': { |
154 | + 'Meta': {'ordering': "['-uploaded_on']", 'object_name': 'Bundle'}, |
155 | + '_gz_content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'db_column': "'gz_content'"}), |
156 | + '_raw_content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'db_column': "'content'"}), |
157 | + 'bundle_stream': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bundles'", 'to': "orm['dashboard_app.BundleStream']"}), |
158 | + 'content_filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}), |
159 | + 'content_sha1': ('django.db.models.fields.CharField', [], {'max_length': '40', 'unique': 'True', 'null': 'True'}), |
160 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
161 | + 'is_deserialized': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
162 | + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'uploaded_bundles'", 'null': 'True', 'to': "orm['auth.User']"}), |
163 | + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}) |
164 | + }, |
165 | + 'dashboard_app.bundledeserializationerror': { |
166 | + 'Meta': {'object_name': 'BundleDeserializationError'}, |
167 | + 'bundle': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'deserialization_error'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['dashboard_app.Bundle']"}), |
168 | + 'error_message': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), |
169 | + 'traceback': ('django.db.models.fields.TextField', [], {'max_length': '32768'}) |
170 | + }, |
171 | + 'dashboard_app.bundlestream': { |
172 | + 'Meta': {'object_name': 'BundleStream'}, |
173 | + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), |
174 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
175 | + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
176 | + 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
177 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), |
178 | + 'pathname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), |
179 | + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), |
180 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) |
181 | + }, |
182 | + 'dashboard_app.hardwaredevice': { |
183 | + 'Meta': {'object_name': 'HardwareDevice'}, |
184 | + 'description': ('django.db.models.fields.CharField', [], {'max_length': '256'}), |
185 | + 'device_type': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
186 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) |
187 | + }, |
188 | + 'dashboard_app.image': { |
189 | + 'Meta': {'object_name': 'Image'}, |
190 | + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'null': 'True', 'to': "orm['dashboard_app.TestRunFilter']"}), |
191 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
192 | + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '1024'}) |
193 | + }, |
194 | + 'dashboard_app.imagechartfilter': { |
195 | + 'Meta': {'object_name': 'ImageChartFilter'}, |
196 | + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.TestRunFilter']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), |
197 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
198 | + 'image_chart': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.ImageReportChart']"}), |
199 | + 'representation': ('django.db.models.fields.CharField', [], {'default': "'lines'", 'max_length': '20'}) |
200 | + }, |
201 | + 'dashboard_app.imagecharttest': { |
202 | + 'Meta': {'unique_together': "(('image_chart_filter', 'test'),)", 'object_name': 'ImageChartTest'}, |
203 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
204 | + 'image_chart_filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.ImageChartFilter']"}), |
205 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), |
206 | + 'test': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.Test']"}) |
207 | + }, |
208 | + 'dashboard_app.imagecharttestcase': { |
209 | + 'Meta': {'unique_together': "(('image_chart_filter', 'test_case'),)", 'object_name': 'ImageChartTestCase'}, |
210 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
211 | + 'image_chart_filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.ImageChartFilter']"}), |
212 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), |
213 | + 'test_case': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.TestCase']"}) |
214 | + }, |
215 | + 'dashboard_app.imagereport': { |
216 | + 'Meta': {'object_name': 'ImageReport'}, |
217 | + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), |
218 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
219 | + 'is_published': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
220 | + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '1024'}) |
221 | + }, |
222 | + 'dashboard_app.imagereportchart': { |
223 | + 'Meta': {'object_name': 'ImageReportChart'}, |
224 | + 'chart_type': ('django.db.models.fields.CharField', [], {'default': "'pass/fail'", 'max_length': '20'}), |
225 | + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), |
226 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
227 | + 'image_report': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dashboard_app.ImageReport']"}), |
228 | + 'is_data_table_visible': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
229 | + 'is_interactive': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
230 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
231 | + 'target_goal': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '10', 'decimal_places': '5', 'blank': 'True'}) |
232 | + }, |
233 | + 'dashboard_app.imageset': { |
234 | + 'Meta': {'object_name': 'ImageSet'}, |
235 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
236 | + 'images': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dashboard_app.Image']", 'symmetrical': 'False'}), |
237 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}) |
238 | + }, |
239 | + 'dashboard_app.launchpadbug': { |
240 | + 'Meta': {'object_name': 'LaunchpadBug'}, |
241 | + 'bug_id': ('django.db.models.fields.PositiveIntegerField', [], {'unique': 'True'}), |
242 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
243 | + 'test_runs': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'launchpad_bugs'", 'symmetrical': 'False', 'to': "orm['dashboard_app.TestRun']"}) |
244 | + }, |
245 | + 'dashboard_app.namedattribute': { |
246 | + 'Meta': {'unique_together': "(('object_id', 'name'),)", 'object_name': 'NamedAttribute'}, |
247 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), |
248 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
249 | + 'name': ('django.db.models.fields.TextField', [], {}), |
250 | + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), |
251 | + 'value': ('django.db.models.fields.TextField', [], {}) |
252 | + }, |
253 | + 'dashboard_app.pmqabundlestream': { |
254 | + 'Meta': {'object_name': 'PMQABundleStream'}, |
255 | + 'bundle_stream': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['dashboard_app.BundleStream']"}), |
256 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) |
257 | + }, |
258 | + 'dashboard_app.softwarepackage': { |
259 | + 'Meta': {'unique_together': "(('name', 'version'),)", 'object_name': 'SoftwarePackage'}, |
260 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
261 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
262 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '128'}) |
263 | + }, |
264 | + 'dashboard_app.softwarepackagescratch': { |
265 | + 'Meta': {'object_name': 'SoftwarePackageScratch'}, |
266 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
267 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
268 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '128'}) |
269 | + }, |
270 | + 'dashboard_app.softwaresource': { |
271 | + 'Meta': {'object_name': 'SoftwareSource'}, |
272 | + 'branch_revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
273 | + 'branch_url': ('django.db.models.fields.CharField', [], {'max_length': '256'}), |
274 | + 'branch_vcs': ('django.db.models.fields.CharField', [], {'max_length': '10'}), |
275 | + 'commit_timestamp': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
276 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
277 | + 'project_name': ('django.db.models.fields.CharField', [], {'max_length': '32'}) |
278 | + }, |
279 | + 'dashboard_app.tag': { |
280 | + 'Meta': {'object_name': 'Tag'}, |
281 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
282 | + 'name': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '256'}) |
283 | + }, |
284 | + 'dashboard_app.test': { |
285 | + 'Meta': {'object_name': 'Test'}, |
286 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
287 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), |
288 | + 'test_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '1024'}) |
289 | + }, |
290 | + 'dashboard_app.testcase': { |
291 | + 'Meta': {'unique_together': "(('test', 'test_case_id'),)", 'object_name': 'TestCase'}, |
292 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
293 | + 'name': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
294 | + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_cases'", 'to': "orm['dashboard_app.Test']"}), |
295 | + 'test_case_id': ('django.db.models.fields.TextField', [], {}), |
296 | + 'units': ('django.db.models.fields.TextField', [], {'blank': 'True'}) |
297 | + }, |
298 | + 'dashboard_app.testdefinition': { |
299 | + 'Meta': {'object_name': 'TestDefinition'}, |
300 | + 'content': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), |
301 | + 'description': ('django.db.models.fields.TextField', [], {}), |
302 | + 'environment': ('django.db.models.fields.CharField', [], {'max_length': '256'}), |
303 | + 'format': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
304 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
305 | + 'location': ('django.db.models.fields.CharField', [], {'default': "'LOCAL'", 'max_length': '64'}), |
306 | + 'mime_type': ('django.db.models.fields.CharField', [], {'default': "'text/plain'", 'max_length': '64'}), |
307 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), |
308 | + 'target_dev_types': ('django.db.models.fields.CharField', [], {'max_length': '512'}), |
309 | + 'target_os': ('django.db.models.fields.CharField', [], {'max_length': '512'}), |
310 | + 'url': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), |
311 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '256'}) |
312 | + }, |
313 | + 'dashboard_app.testresult': { |
314 | + 'Meta': {'ordering': "('_order',)", 'object_name': 'TestResult'}, |
315 | + '_order': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
316 | + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), |
317 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
318 | + 'lineno': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), |
319 | + 'measurement': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '20', 'decimal_places': '10', 'blank': 'True'}), |
320 | + 'message': ('django.db.models.fields.TextField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), |
321 | + 'microseconds': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), |
322 | + 'relative_index': ('django.db.models.fields.PositiveIntegerField', [], {}), |
323 | + 'result': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), |
324 | + 'test_case': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'test_results'", 'null': 'True', 'to': "orm['dashboard_app.TestCase']"}), |
325 | + 'test_run': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_results'", 'to': "orm['dashboard_app.TestRun']"}), |
326 | + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) |
327 | + }, |
328 | + 'dashboard_app.testrun': { |
329 | + 'Meta': {'ordering': "['-import_assigned_date']", 'object_name': 'TestRun'}, |
330 | + 'analyzer_assigned_date': ('django.db.models.fields.DateTimeField', [], {}), |
331 | + 'analyzer_assigned_uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}), |
332 | + 'bundle': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_runs'", 'to': "orm['dashboard_app.Bundle']"}), |
333 | + 'devices': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.HardwareDevice']"}), |
334 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
335 | + 'import_assigned_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
336 | + 'microseconds': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), |
337 | + 'packages': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.SoftwarePackage']"}), |
338 | + 'sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.SoftwareSource']"}), |
339 | + 'sw_image_desc': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), |
340 | + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'test_runs'", 'blank': 'True', 'to': "orm['dashboard_app.Tag']"}), |
341 | + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'test_runs'", 'to': "orm['dashboard_app.Test']"}), |
342 | + 'time_check_performed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) |
343 | + }, |
344 | + 'dashboard_app.testrundenormalization': { |
345 | + 'Meta': {'object_name': 'TestRunDenormalization'}, |
346 | + 'count_fail': ('django.db.models.fields.PositiveIntegerField', [], {}), |
347 | + 'count_pass': ('django.db.models.fields.PositiveIntegerField', [], {}), |
348 | + 'count_skip': ('django.db.models.fields.PositiveIntegerField', [], {}), |
349 | + 'count_unknown': ('django.db.models.fields.PositiveIntegerField', [], {}), |
350 | + 'test_run': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'denormalization'", 'unique': 'True', 'primary_key': 'True', 'to': "orm['dashboard_app.TestRun']"}) |
351 | + }, |
352 | + 'dashboard_app.testrunfilter': { |
353 | + 'Meta': {'unique_together': "(('owner', 'name'),)", 'object_name': 'TestRunFilter'}, |
354 | + 'build_number_attribute': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), |
355 | + 'bundle_streams': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dashboard_app.BundleStream']", 'symmetrical': 'False'}), |
356 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
357 | + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '1024'}), |
358 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), |
359 | + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
360 | + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['auth.User']"}) |
361 | + }, |
362 | + 'dashboard_app.testrunfilterattribute': { |
363 | + 'Meta': {'object_name': 'TestRunFilterAttribute'}, |
364 | + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attributes'", 'to': "orm['dashboard_app.TestRunFilter']"}), |
365 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
366 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), |
367 | + 'value': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) |
368 | + }, |
369 | + 'dashboard_app.testrunfiltersubscription': { |
370 | + 'Meta': {'unique_together': "(('user', 'filter'),)", 'object_name': 'TestRunFilterSubscription'}, |
371 | + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dashboard_app.TestRunFilter']"}), |
372 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
373 | + 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
374 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) |
375 | + }, |
376 | + 'dashboard_app.testrunfiltertest': { |
377 | + 'Meta': {'object_name': 'TestRunFilterTest'}, |
378 | + 'filter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tests'", 'to': "orm['dashboard_app.TestRunFilter']"}), |
379 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
380 | + 'index': ('django.db.models.fields.PositiveIntegerField', [], {}), |
381 | + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['dashboard_app.Test']"}) |
382 | + }, |
383 | + 'dashboard_app.testrunfiltertestcase': { |
384 | + 'Meta': {'object_name': 'TestRunFilterTestCase'}, |
385 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
386 | + 'index': ('django.db.models.fields.PositiveIntegerField', [], {}), |
387 | + 'test': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'cases'", 'to': "orm['dashboard_app.TestRunFilterTest']"}), |
388 | + 'test_case': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['dashboard_app.TestCase']"}) |
389 | + } |
390 | + } |
391 | + |
392 | + complete_apps = ['dashboard_app'] |
393 | \ No newline at end of file |
394 | |
395 | === modified file 'dashboard_app/models.py' |
396 | --- dashboard_app/models.py 2013-09-05 16:00:38 +0000 |
397 | +++ dashboard_app/models.py 2013-09-13 13:13:49 +0000 |
398 | @@ -1540,101 +1540,6 @@ |
399 | return self.name |
400 | |
401 | |
402 | -class ImageReport(models.Model): |
403 | - |
404 | - name = models.SlugField(max_length=1024, unique=True) |
405 | - |
406 | - description = models.TextField(blank=True, null=True) |
407 | - |
408 | - def __unicode__(self): |
409 | - return self.name |
410 | - |
411 | - |
412 | -# Chart types |
413 | -CHART_TYPES = ((r'pass/fail', 'Pass/Fail'), |
414 | - (r'measurement', 'Measurement')) |
415 | -# Chart representation |
416 | -REPRESENTATION_TYPES = ((r'lines', 'Lines'), |
417 | - (r'bars', 'Bars')) |
418 | - |
419 | - |
420 | -class ImageReportChart(models.Model): |
421 | - |
422 | - name = models.CharField(max_length=100) |
423 | - |
424 | - image_report = models.ForeignKey( |
425 | - ImageReport, |
426 | - default=None, |
427 | - null=False, |
428 | - on_delete=models.CASCADE) |
429 | - |
430 | - test_runs = models.ManyToManyField( |
431 | - TestRun, |
432 | - through='ImageChartTestRun') |
433 | - |
434 | - test_cases = models.ManyToManyField( |
435 | - TestCase, |
436 | - through='ImageChartTestCase') |
437 | - |
438 | - chart_type = models.CharField( |
439 | - max_length=20, |
440 | - choices=CHART_TYPES, |
441 | - verbose_name='Chart type') |
442 | - |
443 | - representation = models.CharField( |
444 | - max_length=20, |
445 | - choices=REPRESENTATION_TYPES, |
446 | - verbose_name='Representation type') |
447 | - |
448 | - target_goal = models.DecimalField( |
449 | - blank = True, |
450 | - decimal_places = 5, |
451 | - max_digits = 10, |
452 | - null = True, |
453 | - verbose_name = 'Target goal') |
454 | - |
455 | - is_interactive = models.BooleanField( |
456 | - default=False, |
457 | - verbose_name='Chart is interactive') |
458 | - |
459 | - is_data_table_visible = models.BooleanField( |
460 | - default=False, |
461 | - verbose_name='Data table is visible') |
462 | - |
463 | - def __unicode__(self): |
464 | - return self.name |
465 | - |
466 | - |
467 | -class ImageChartTestRun(models.Model): |
468 | - |
469 | - image_chart = models.ForeignKey( |
470 | - ImageReportChart, |
471 | - null=False, |
472 | - on_delete=models.CASCADE) |
473 | - |
474 | - test_run = models.ForeignKey( |
475 | - TestRun, |
476 | - null=False, |
477 | - on_delete=models.CASCADE) |
478 | - |
479 | - name = models.CharField(max_length=200) |
480 | - |
481 | - |
482 | -class ImageChartTestCase(models.Model): |
483 | - |
484 | - image_chart = models.ForeignKey( |
485 | - ImageReportChart, |
486 | - null=False, |
487 | - on_delete=models.CASCADE) |
488 | - |
489 | - test_case = models.ForeignKey( |
490 | - TestCase, |
491 | - null=False, |
492 | - on_delete=models.CASCADE) |
493 | - |
494 | - name = models.CharField(max_length=200) |
495 | - |
496 | - |
497 | class LaunchpadBug(models.Model): |
498 | |
499 | bug_id = models.PositiveIntegerField(unique=True) |
500 | @@ -1923,3 +1828,137 @@ |
501 | class PMQABundleStream(models.Model): |
502 | |
503 | bundle_stream = models.ForeignKey(BundleStream, related_name='+') |
504 | + |
505 | + |
506 | +class ImageReport(models.Model): |
507 | + |
508 | + name = models.SlugField(max_length=1024, unique=True) |
509 | + |
510 | + description = models.TextField(blank=True, null=True) |
511 | + |
512 | + is_published = models.BooleanField( |
513 | + default=False, |
514 | + verbose_name='Published') |
515 | + |
516 | + def __unicode__(self): |
517 | + return self.name |
518 | + |
519 | + @models.permalink |
520 | + def get_absolute_url(self): |
521 | + return ("dashboard_app.views.image_reports.views.image_report_detail", |
522 | + (), dict(name=self.name)) |
523 | + |
524 | +# Chart types |
525 | +CHART_TYPES = ((r'pass/fail', 'Pass/Fail'), |
526 | + (r'measurement', 'Measurement')) |
527 | +# Chart representation |
528 | +REPRESENTATION_TYPES = ((r'lines', 'Lines'), |
529 | + (r'bars', 'Bars')) |
530 | + |
531 | + |
532 | +class ImageReportChart(models.Model): |
533 | + |
534 | + name = models.CharField(max_length=100) |
535 | + |
536 | + description = models.TextField(blank=True, null=True) |
537 | + |
538 | + image_report = models.ForeignKey( |
539 | + ImageReport, |
540 | + default=None, |
541 | + null=False, |
542 | + on_delete=models.CASCADE) |
543 | + |
544 | + chart_type = models.CharField( |
545 | + max_length=20, |
546 | + choices=CHART_TYPES, |
547 | + verbose_name='Chart type', |
548 | + blank=False, |
549 | + default="pass/fail", |
550 | + ) |
551 | + |
552 | + target_goal = models.DecimalField( |
553 | + blank = True, |
554 | + decimal_places = 5, |
555 | + max_digits = 10, |
556 | + null = True, |
557 | + verbose_name = 'Target goal') |
558 | + |
559 | + is_interactive = models.BooleanField( |
560 | + default=False, |
561 | + verbose_name='Chart is interactive') |
562 | + |
563 | + is_data_table_visible = models.BooleanField( |
564 | + default=False, |
565 | + verbose_name='Data table is visible') |
566 | + |
567 | + def __unicode__(self): |
568 | + return self.name |
569 | + |
570 | + @models.permalink |
571 | + def get_absolute_url(self): |
572 | + return ("dashboard_app.views.image_reports.views.image_chart_detail", |
573 | + (), dict(id=self.id)) |
574 | + |
575 | + |
576 | +class ImageChartFilter(models.Model): |
577 | + |
578 | + image_chart = models.ForeignKey( |
579 | + ImageReportChart, |
580 | + null=False, |
581 | + on_delete=models.CASCADE) |
582 | + |
583 | + filter = models.ForeignKey( |
584 | + TestRunFilter, |
585 | + null=True, |
586 | + on_delete=models.SET_NULL) |
587 | + |
588 | + representation = models.CharField( |
589 | + max_length=20, |
590 | + choices=REPRESENTATION_TYPES, |
591 | + verbose_name='Representation', |
592 | + blank=False, |
593 | + default="lines", |
594 | + ) |
595 | + |
596 | + @models.permalink |
597 | + def get_absolute_url(self): |
598 | + return ( |
599 | + "dashboard_app.views.image_reports.views.image_chart_filter_edit", |
600 | + (), dict(id=self.id)) |
601 | + |
602 | + |
603 | +class ImageChartTest(models.Model): |
604 | + |
605 | + class Meta: |
606 | + unique_together = ("image_chart_filter", "test") |
607 | + |
608 | + image_chart_filter = models.ForeignKey( |
609 | + ImageChartFilter, |
610 | + null=False, |
611 | + on_delete=models.CASCADE) |
612 | + |
613 | + test = models.ForeignKey( |
614 | + Test, |
615 | + null=False, |
616 | + on_delete=models.CASCADE) |
617 | + |
618 | + name = models.CharField(max_length=200) |
619 | + |
620 | + |
621 | +class ImageChartTestCase(models.Model): |
622 | + |
623 | + class Meta: |
624 | + unique_together = ("image_chart_filter", "test_case") |
625 | + |
626 | + image_chart_filter = models.ForeignKey( |
627 | + ImageChartFilter, |
628 | + null=False, |
629 | + on_delete=models.CASCADE) |
630 | + |
631 | + test_case = models.ForeignKey( |
632 | + TestCase, |
633 | + null=False, |
634 | + on_delete=models.CASCADE) |
635 | + |
636 | + name = models.CharField(max_length=200) |
637 | + |
638 | |
639 | === added file 'dashboard_app/static/dashboard_app/css/image-charts.css' |
640 | --- dashboard_app/static/dashboard_app/css/image-charts.css 1970-01-01 00:00:00 +0000 |
641 | +++ dashboard_app/static/dashboard_app/css/image-charts.css 2013-09-13 13:13:49 +0000 |
642 | @@ -0,0 +1,82 @@ |
643 | +@import url("../../admin/css/widgets.css"); |
644 | + |
645 | +div.selector { clear: both; } |
646 | +div.selector span.helptext { display: none; } |
647 | +div.selector h2 { margin: 0; font-size: 11pt; } |
648 | +div.selector a { text-decoration: none; } |
649 | +div.selector select { height: 10em; } |
650 | +div.selector ul.selector-chooser { margin-top: 5.5em; } |
651 | +div.selector .selector-chosen select { |
652 | + border: 1px solid rgb(204, 204, 204); |
653 | + border-top: none; |
654 | +} |
655 | + |
656 | +.list-container { |
657 | + border: 1px solid #000000; |
658 | + clear: both; |
659 | + margin: 10px 10px 10px 10px; |
660 | + padding: 10px; |
661 | + width: 50%; |
662 | +} |
663 | + |
664 | +.form-field { |
665 | + margin-bottom: 5px; |
666 | + vertical-align: top; |
667 | +} |
668 | + |
669 | +.form-field label { |
670 | + vertical-align: top; |
671 | + width: 100px; |
672 | + display: inline-block; |
673 | + margin-left: 10px; |
674 | +} |
675 | + |
676 | +.submit-button { |
677 | + margin-top: 20px; |
678 | + margin-left: 10px; |
679 | +} |
680 | + |
681 | +.filter-headline { |
682 | + font-weight: bold; |
683 | + font-size: 16px; |
684 | +} |
685 | + |
686 | +.filter-container { |
687 | + margin-bottom: 10px; |
688 | + clear: both; |
689 | +} |
690 | + |
691 | +.filter-title { |
692 | + font-weight: bold; |
693 | + font-size: 15px; |
694 | + margin-bottom: 10px; |
695 | +} |
696 | + |
697 | +.chart-title { |
698 | + font-weight: bold; |
699 | + font-size: 15px; |
700 | + margin-bottom: 10px; |
701 | +} |
702 | + |
703 | +.errors { |
704 | + color: red; |
705 | +} |
706 | + |
707 | +.fields-container { |
708 | + margin-left: 10px; |
709 | +} |
710 | + |
711 | +#filters_div { |
712 | + margin: 10px 0 0 10px; |
713 | + border: 1px solid #000000; |
714 | + clear: both; |
715 | + width: 75%; |
716 | + padding: 5px 0 10px 10px; |
717 | + overflow: auto; |
718 | +} |
719 | + |
720 | +#alias_container { |
721 | + font-weight: bold; |
722 | + float: left; |
723 | + display: none; |
724 | +} |
725 | \ No newline at end of file |
726 | |
727 | === added file 'dashboard_app/static/dashboard_app/images/ajax-progress.gif' |
728 | 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-13 13:13:49 +0000 differ |
729 | === added file 'dashboard_app/static/dashboard_app/js/image-report-editor.js' |
730 | --- dashboard_app/static/dashboard_app/js/image-report-editor.js 1970-01-01 00:00:00 +0000 |
731 | +++ dashboard_app/static/dashboard_app/js/image-report-editor.js 2013-09-13 13:13:49 +0000 |
732 | @@ -0,0 +1,221 @@ |
733 | +select_filter = function() { |
734 | + // Open the filter select dialog. |
735 | + $('#filter_select_dialog').dialog('open'); |
736 | +} |
737 | + |
738 | +filters_callback = function(id, name) { |
739 | + // Function which will be called when a filter is selected from the dialog. |
740 | + |
741 | + if ($('#id_chart_type').val() == "pass/fail") { |
742 | + url = "/dashboard/filters/+get-tests-json"; |
743 | + } else { |
744 | + url = "/dashboard/filters/+get-test-cases-json"; |
745 | + } |
746 | + |
747 | + $.ajax({ |
748 | + url: url, |
749 | + async: false, |
750 | + data: {"id": id}, |
751 | + beforeSend: function () { |
752 | + $('#filter-container').remove(); |
753 | + $('#filter_select_dialog').dialog('close'); |
754 | + $('#loading_dialog').dialog('open'); |
755 | + }, |
756 | + success: function (data) { |
757 | + $('#loading_dialog').dialog('close'); |
758 | + $("#id_filter").val(id); |
759 | + add_filter_container(data, name); |
760 | + }, |
761 | + error: function(data, status, error) { |
762 | + $('#loading_dialog').dialog('close'); |
763 | + alert('Filter could not be loaded, please try again.'); |
764 | + } |
765 | + }); |
766 | +} |
767 | + |
768 | +add_filter_container = function(data, title) { |
769 | + // Adds elements which contain tests or test cases from the previously |
770 | + // selected filter. |
771 | + |
772 | + content = '<hr><div class="filter-title">' + title + '</div>'; |
773 | + |
774 | + if ($('#id_chart_type').val() == "pass/fail") { |
775 | + test_label = "Tests"; |
776 | + } else { |
777 | + test_label = "Test Cases"; |
778 | + } |
779 | + |
780 | + content += '<div class="selector"><div class="selector-available"><h2>' + |
781 | + 'Select ' + test_label + '</h2>'; |
782 | + |
783 | + content += '<select id="available_tests" multiple class="filtered">'; |
784 | + for (i in data) { |
785 | + if ($('#id_chart_type').val() == "pass/fail") { |
786 | + content += '<option value="' + data[i].pk + '">' + |
787 | + data[i].fields.test_id + '</option>'; |
788 | + } else { |
789 | + content += '<option value="' + data[i].pk + '">' + |
790 | + data[i].fields.test_case_id + '</option>'; |
791 | + } |
792 | + } |
793 | + content += '</select>'; |
794 | + |
795 | + content += '<a id="add_all_link" href="javascript: void(0)">' + |
796 | + 'Choose All</a>'; |
797 | + content += '</div>'; |
798 | + |
799 | + content += '<ul class="selector-chooser">' + |
800 | + '<li><a href="javascript: void(0)" id="add_link"' + |
801 | + 'class="selector-add active"></a></li>' + |
802 | + '<li><a href="javascript: void(0)" id="remove_link"' + |
803 | + 'class="selector-remove active"></a></li>' + |
804 | + '</ul>'; |
805 | + |
806 | + content += '<div class="selector-chosen"><h2>' + |
807 | + 'Choosen ' + test_label + '</h2>'; |
808 | + |
809 | + content += '<select id="chosen_tests" onchange="toggle_alias()" multiple class="filtered"></select>'; |
810 | + content += '<a id="remove_all_link" href="javascript: void(0)">' + |
811 | + 'Remove All</a>'; |
812 | + content += '</div></div>'; |
813 | + |
814 | + content += '<div id="alias_container">Alias<br/>'; |
815 | + content += '<input type="text" onkeyup="copy_alias(this);" id="alias" />'; |
816 | + content += '</div>'; |
817 | + |
818 | + $('<div id="filter-container"></div>').html( |
819 | + content).appendTo($('#filters_div')); |
820 | + |
821 | + update_events(); |
822 | +} |
823 | + |
824 | +update_events = function() { |
825 | + // Add onclick events to the links controlling the select boxes. |
826 | + |
827 | + $('#add_link').click(function() { |
828 | + move_options('available_tests', 'chosen_tests'); |
829 | + }); |
830 | + $('#remove_link').click(function() { |
831 | + move_options('chosen_tests', 'available_tests'); |
832 | + }); |
833 | + $('#add_all_link').click(function() { |
834 | + $('#available_tests option').each(function() { |
835 | + $(this).attr('selected', 'selected'); |
836 | + }); |
837 | + move_options('available_tests', 'chosen_tests'); |
838 | + }); |
839 | + $('#remove_all_link').click(function() { |
840 | + $('#chosen_tests option').each(function() { |
841 | + $(this).attr('selected', 'selected'); |
842 | + }); |
843 | + move_options('chosen_tests', 'available_tests'); |
844 | + }); |
845 | +} |
846 | + |
847 | +move_options = function(from_element, to_element) { |
848 | + var options = $("#" + from_element + " option:selected"); |
849 | + $("#" + to_element).append(options.clone()); |
850 | + $(options).remove(); |
851 | + |
852 | + update_aliases(); |
853 | + toggle_alias(); |
854 | +} |
855 | + |
856 | +add_selected_options = function() { |
857 | + // Adds options from chosen tests select box as hidden fields. |
858 | + |
859 | + $('#chosen_tests option').each(function() { |
860 | + if ($('#id_chart_type').val() == "pass/fail") { |
861 | + field_name = "image_chart_tests"; |
862 | + } else { |
863 | + field_name = "image_chart_test_cases"; |
864 | + } |
865 | + $('<input type="hidden" name="' + field_name + |
866 | + '" value="'+ $(this).val() + '" />').appendTo($('#add_filter_link')); |
867 | + }); |
868 | +} |
869 | + |
870 | +update_aliases = function() { |
871 | + // Update hidden aliases inputs based on chosen tests. |
872 | + |
873 | + $('#chosen_tests option').each(function() { |
874 | + if ($('#alias_' + $(this).val()).length == 0) { |
875 | + $('<input type="hidden" class="alias" data-sid="' + $(this).val() + |
876 | + '" name="aliases" id="alias_' + $(this).val() + |
877 | + '" />').appendTo($('#aliases_div')); |
878 | + } |
879 | + }); |
880 | + chosen_tests = $.map($('#chosen_tests option'), function(e) { |
881 | + return e.value; |
882 | + }); |
883 | + $('.alias').each(function(index, value) { |
884 | + test_id = value.id.split('_')[1]; |
885 | + |
886 | + if (chosen_tests.indexOf(test_id) == -1) { |
887 | + $('#alias_' + test_id).remove(); |
888 | + } |
889 | + }); |
890 | +} |
891 | + |
892 | +toggle_alias = function() { |
893 | + // Show/hide alias input field. |
894 | + |
895 | + if ($('#chosen_tests option:selected').length == 1) { |
896 | + $('#alias_container').show(); |
897 | + test_id = $('#chosen_tests option:selected').val(); |
898 | + $('#alias').val($('#alias_' + test_id).val()); |
899 | + } else { |
900 | + $('#alias_container').hide(); |
901 | + } |
902 | +} |
903 | + |
904 | +copy_alias = function(e) { |
905 | + // Populate alias input based on the selected test. |
906 | + |
907 | + if ($('#chosen_tests option:selected').length == 1) { |
908 | + test_id = $('#chosen_tests option:selected').val(); |
909 | + $('#alias_' + test_id).val(e.value); |
910 | + } |
911 | +} |
912 | + |
913 | +sort_aliases = function() { |
914 | + // Pre submit function. Sort the aliases hidden inputs. |
915 | + |
916 | + $('#aliases_div input').sort(function(a,b) { |
917 | + return a.dataset.sid > b.dataset.sid; |
918 | + }).appendTo('#aliases_div'); |
919 | +} |
920 | + |
921 | +init_filter_dialog = function() { |
922 | + // Setup the filter table dialog. |
923 | + |
924 | + var filter_dialog = $('<div id="filter_select_dialog"></div>'); |
925 | + $('#all-filters_wrapper').wrapAll(filter_dialog); |
926 | + |
927 | + $('#filter_select_dialog').dialog({ |
928 | + autoOpen: false, |
929 | + title: 'Select Filter', |
930 | + draggable: false, |
931 | + height: 280, |
932 | + width: 420, |
933 | + modal: true, |
934 | + resizable: false |
935 | + }); |
936 | +} |
937 | + |
938 | +init_loading_dialog = function() { |
939 | + // Setup the loading image dialog. |
940 | + |
941 | + $('#loading_dialog').dialog({ |
942 | + autoOpen: false, |
943 | + title: '', |
944 | + draggable: false, |
945 | + height: 35, |
946 | + width: 250, |
947 | + modal: true, |
948 | + resizable: false, |
949 | + dialogClass: 'loading-dialog' |
950 | + }); |
951 | + |
952 | + $('.loading-dialog div.ui-dialog-titlebar').hide(); |
953 | +} |
954 | |
955 | === added file 'dashboard_app/templates/dashboard_app/image_chart_filter_form.html' |
956 | --- dashboard_app/templates/dashboard_app/image_chart_filter_form.html 1970-01-01 00:00:00 +0000 |
957 | +++ dashboard_app/templates/dashboard_app/image_chart_filter_form.html 2013-09-13 13:13:49 +0000 |
958 | @@ -0,0 +1,109 @@ |
959 | +{% extends "dashboard_app/_content.html" %} |
960 | +{% load i18n %} |
961 | +{% load django_tables2 %} |
962 | + |
963 | +{% block extrahead %} |
964 | +{{ block.super }} |
965 | +<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/> |
966 | +<script type="text/javascript" src="{{ STATIC_URL }}dashboard_app/js/image-report-editor.js"></script> |
967 | + |
968 | +{% endblock %} |
969 | + |
970 | + |
971 | +{% block content %} |
972 | +<h1>Image Chart Filter</h1> |
973 | + |
974 | +{% block content_form %} |
975 | +<form action="" method="post">{% csrf_token %} |
976 | + |
977 | + {% if form.errors %} |
978 | + <div class="errors"> |
979 | + <div> |
980 | + {{ form.non_field_errors }} |
981 | + <ul> |
982 | + {% for field in form %} |
983 | + {% if field.errors %} |
984 | + <li>{{ field.label }}: {{ field.errors|striptags }}</li> |
985 | + {% endif %} |
986 | + {% endfor %} |
987 | + </ul> |
988 | + </div> |
989 | + </div> |
990 | + {% endif %} |
991 | + |
992 | + <div id="filters_div"> |
993 | + <div id="add_filter_link"> |
994 | + <a href="#" onclick="select_filter()">Select filter</a> |
995 | + {{ form.filter }} |
996 | + {{ form.image_chart }} |
997 | + <input type="hidden" id="id_chart_type" value="{{ image_chart.chart_type }}"/> |
998 | + {{ form.image_chart_tests }} |
999 | + {{ form.image_chart_test_cases }} |
1000 | + </div> |
1001 | + |
1002 | + <div> |
1003 | + {{ form.representation.label_tag }} |
1004 | + {{ form.representation }} |
1005 | + </div> |
1006 | + </div> |
1007 | + |
1008 | + <div id="aliases_div"> |
1009 | + </div> |
1010 | + |
1011 | + <div class="submit-button"> |
1012 | + <input type="submit" value="Save" /> |
1013 | + </div> |
1014 | +</form> |
1015 | + |
1016 | +{% endblock content_form %} |
1017 | + |
1018 | +{% render_table filters_table %} |
1019 | + |
1020 | +<div id="loading_dialog"> |
1021 | +<img src="{{ STATIC_URL }}dashboard_app/images/ajax-progress.gif" alt="Loading..." /> |
1022 | +</div> |
1023 | + |
1024 | +<script type="text/javascript"> |
1025 | + $().ready(function () { |
1026 | + |
1027 | + init_filter_dialog(); |
1028 | + init_loading_dialog(); |
1029 | + |
1030 | + $('form').submit(function() { |
1031 | + add_selected_options(); |
1032 | + sort_aliases(); |
1033 | + }); |
1034 | + |
1035 | + {% if form.filter.value %} |
1036 | + filters_callback('{{ instance.filter.id }}', |
1037 | + '{{ instance.filter.name }}'); |
1038 | + |
1039 | + if ($('#id_chart_type').val() == "pass/fail") { |
1040 | + {% for test in instance.imagecharttest_set.all %} |
1041 | + $('#available_tests option[value="{{ test.test_id }}"]').attr('selected', 'selected'); |
1042 | + {% endfor %} |
1043 | + } else { |
1044 | + {% for test in instance.imagecharttestcase_set.all %} |
1045 | + $('#available_tests option[value="{{ test.test_case_id }}"]').attr('selected', 'selected'); |
1046 | + {% endfor %} |
1047 | + } |
1048 | + |
1049 | + move_options('available_tests', 'chosen_tests'); |
1050 | + |
1051 | + if ($('#id_chart_type').val() == "pass/fail") { |
1052 | + {% for test in instance.imagecharttest_set.all %} |
1053 | + $('#alias_{{ test.test_id }}').val('{{ test.name }}'); |
1054 | + {% endfor %} |
1055 | + } else { |
1056 | + {% for test in instance.imagecharttestcase_set.all %} |
1057 | + |
1058 | + $('#alias_{{ test.test_case_id }}').val('{{ test.name }}'); |
1059 | + {% endfor %} |
1060 | + } |
1061 | + |
1062 | + {% endif %} |
1063 | +}); |
1064 | + |
1065 | +</script> |
1066 | + |
1067 | +{% endblock %} |
1068 | |
1069 | === added file 'dashboard_app/templates/dashboard_app/image_report_chart_detail.html' |
1070 | --- dashboard_app/templates/dashboard_app/image_report_chart_detail.html 1970-01-01 00:00:00 +0000 |
1071 | +++ dashboard_app/templates/dashboard_app/image_report_chart_detail.html 2013-09-13 13:13:49 +0000 |
1072 | @@ -0,0 +1,86 @@ |
1073 | +{% extends "dashboard_app/_content.html" %} |
1074 | +{% load i18n %} |
1075 | + |
1076 | +{% block extrahead %} |
1077 | +{{ block.super }} |
1078 | +<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/> |
1079 | +{% endblock %} |
1080 | + |
1081 | +{% block content %} |
1082 | + |
1083 | +<h1>Image Chart {{ image_chart.name }}</h1> |
1084 | + |
1085 | + |
1086 | +<div class="fields-container"> |
1087 | + <div class="form-field"> |
1088 | + <a href="{{ image_chart.get_absolute_url }}/+edit">Edit</a> this chart. |
1089 | + </div> |
1090 | + <div class="form-field"> |
1091 | + Description: {{ image_chart.description }} |
1092 | + </div> |
1093 | + <div class="form-field"> |
1094 | + Chart type: {{ image_chart.chart_type }} |
1095 | + </div> |
1096 | + <div class="form-field"> |
1097 | + Data table visible: {{ image_chart.is_data_table_visible }} |
1098 | + </div> |
1099 | + <div class="form-field"> |
1100 | + Target goal: {{ image_chart.target_goal|floatformat:"-2" }} |
1101 | + </div> |
1102 | +</div> |
1103 | + |
1104 | + |
1105 | +<h3>Filters</h3> |
1106 | + |
1107 | +<div class="fields-container"> |
1108 | + <div id="add_filter_link"> |
1109 | + <a href="{{ image_chart.get_absolute_url }}/+add-filter">Add filter</a> |
1110 | + </div> |
1111 | +</div> |
1112 | + |
1113 | +<div class="list-container"> |
1114 | + {% for chart_filter in image_chart.imagechartfilter_set.all %} |
1115 | + <div class="chart-title"> |
1116 | + {{ chart_filter.filter.name }} |
1117 | + <a style="font-size: 13px;" href="{{ chart_filter.get_absolute_url }}"> |
1118 | + edit |
1119 | + </a> |
1120 | + <a style="font-size: 13px;" href="{{ chart_filter.get_absolute_url }}/+delete"> |
1121 | + remove |
1122 | + </a> |
1123 | + </div> |
1124 | + <div> |
1125 | + {% if image_chart.chart_type == "pass/fail" %} |
1126 | + Tests: |
1127 | + {% for chart_test in chart_filter.imagecharttest_set.all %} |
1128 | + {% if forloop.last %} |
1129 | + {{ chart_test.test.test_id }} |
1130 | + {% else %} |
1131 | + {{ chart_test.test.test_id }}, |
1132 | + {% endif %} |
1133 | + {% endfor %} |
1134 | + {% else %} |
1135 | + Test Cases:  |
1136 | + {% for chart_test in chart_filter.imagecharttestcase_set.all %} |
1137 | + {% if forloop.last %} |
1138 | + {{ chart_test.test_case.test_case_id }} |
1139 | + {% else %} |
1140 | + {{ chart_test.test_case.test_case_id }}, |
1141 | + {% endif %} |
1142 | + {% endfor %} |
1143 | + {% endif %} |
1144 | + </div> |
1145 | + <div> |
1146 | + Representation: {{ chart_filter.representation }} |
1147 | + </div> |
1148 | + |
1149 | + <hr/> |
1150 | + {% empty %} |
1151 | + <div> |
1152 | + <li>No filters added yet.</li> |
1153 | + </div> |
1154 | + {% endfor %} |
1155 | +</div> |
1156 | + |
1157 | + |
1158 | +{% endblock %} |
1159 | |
1160 | === added file 'dashboard_app/templates/dashboard_app/image_report_chart_form.html' |
1161 | --- dashboard_app/templates/dashboard_app/image_report_chart_form.html 1970-01-01 00:00:00 +0000 |
1162 | +++ dashboard_app/templates/dashboard_app/image_report_chart_form.html 2013-09-13 13:13:49 +0000 |
1163 | @@ -0,0 +1,62 @@ |
1164 | +{% extends "dashboard_app/_content.html" %} |
1165 | +{% load i18n %} |
1166 | +{% load django_tables2 %} |
1167 | + |
1168 | +{% block extrahead %} |
1169 | +{{ block.super }} |
1170 | +<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/> |
1171 | + |
1172 | +{% endblock %} |
1173 | + |
1174 | + |
1175 | +{% block content %} |
1176 | +<h1>Add Image Charts 2.0</h1> |
1177 | + |
1178 | +{% block content_form %} |
1179 | +<form action="" method="post">{% csrf_token %} |
1180 | + |
1181 | + {% if form.errors %} |
1182 | + <div class="errors"> |
1183 | + <div> |
1184 | + {{ form.non_field_errors }} |
1185 | + <ul> |
1186 | + {% for field in form %} |
1187 | + {% if field.errors %} |
1188 | + <li>{{ field.label }}: {{ field.errors|striptags }}</li> |
1189 | + {% endif %} |
1190 | + {% endfor %} |
1191 | + </ul> |
1192 | + </div> |
1193 | + </div> |
1194 | + {% endif %} |
1195 | + |
1196 | + <div class="form-field"> |
1197 | + {{ form.name.label_tag }} |
1198 | + {{ form.name }} |
1199 | + <input type="hidden" id="id_image_report" name="image_report" value="{{ image_report_id }}"/> |
1200 | + </div> |
1201 | + <div class="form-field"> |
1202 | + {{ form.description.label_tag }} |
1203 | + {{ form.description }} |
1204 | + </div> |
1205 | + <div class="form-field"> |
1206 | + {{ form.chart_type.label_tag }} |
1207 | + {{ form.chart_type }} |
1208 | + </div> |
1209 | + <div class="form-field"> |
1210 | + {{ form.is_data_table_visible.label_tag }} |
1211 | + {{ form.is_data_table_visible }} |
1212 | + </div> |
1213 | + <div class="form-field"> |
1214 | + {{ form.target_goal.label_tag }} |
1215 | + {{ form.target_goal }} |
1216 | + </div> |
1217 | + |
1218 | + <div class="submit-button"> |
1219 | + <input type="submit" value="Save" /> |
1220 | + </div> |
1221 | +</form> |
1222 | + |
1223 | +{% endblock content_form %} |
1224 | + |
1225 | +{% endblock %} |
1226 | |
1227 | === added file 'dashboard_app/templates/dashboard_app/image_report_detail.html' |
1228 | --- dashboard_app/templates/dashboard_app/image_report_detail.html 1970-01-01 00:00:00 +0000 |
1229 | +++ dashboard_app/templates/dashboard_app/image_report_detail.html 2013-09-13 13:13:49 +0000 |
1230 | @@ -0,0 +1,80 @@ |
1231 | +{% extends "dashboard_app/_content.html" %} |
1232 | +{% load i18n %} |
1233 | + |
1234 | +{% block extrahead %} |
1235 | +{{ block.super }} |
1236 | +<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/> |
1237 | +{% endblock %} |
1238 | + |
1239 | +{% block content %} |
1240 | + |
1241 | +<h1>Image Report {{ image_report.name }}</h1> |
1242 | + |
1243 | +<div class="fields-container"> |
1244 | + <div class="form-field"> |
1245 | + Status: |
1246 | + {% if image_report.is_published %} |
1247 | + <span style="font-weight: bold; color: green;"> |
1248 | + Published |
1249 | + </span> |
1250 | + {% else %} |
1251 | + <span style="font-weight: bold; color: orange;"> |
1252 | + Not Published |
1253 | + </span> |
1254 | + {% endif %} |
1255 | + </div> |
1256 | + <div class="form-field"> |
1257 | + Description: {{ image_report.description }} |
1258 | + </div> |
1259 | + <div class="form-field"> |
1260 | + <a href="{{ image_report.get_absolute_url }}/+edit">Edit</a> this image report. |
1261 | + </div> |
1262 | + <div class="form-field"> |
1263 | + {% if image_report.is_published %} |
1264 | + <a href="{{ image_report.get_absolute_url }}/+unpublish">Unpublish</a> this image report. |
1265 | + {% else %} |
1266 | + <a href="{{ image_report.get_absolute_url }}/+publish">Publish</a> this image report. |
1267 | +{% endif %} |
1268 | + </div> |
1269 | +</div> |
1270 | + |
1271 | +<h3>Charts</h3> |
1272 | + |
1273 | +<div class="fields-container"> |
1274 | + <a href="{% url dashboard_app.views.image_reports.views.image_chart_add %}?image_report_id={{ image_report.id }}"> |
1275 | + Add new chart |
1276 | + </a> |
1277 | +</div> |
1278 | + |
1279 | +<div class="list-container"> |
1280 | + {% for image_chart in image_report.imagereportchart_set.all %} |
1281 | + <div class="chart-title"> |
1282 | + {{ image_chart.name }} |
1283 | + <a style="font-size: 13px;" href="{{ image_chart.get_absolute_url }}"> |
1284 | + details |
1285 | + </a> |
1286 | + <a style="font-size: 13px;" href="{{ image_chart.get_absolute_url }}"> |
1287 | + preview |
1288 | + </a> |
1289 | + </div> |
1290 | + <div> |
1291 | + Description: {{ image_chart.description }} |
1292 | + </div> |
1293 | + <div> |
1294 | + Chart type: {{ image_chart.chart_type }} |
1295 | + </div> |
1296 | + <div> |
1297 | + Data table visible: {{ image_chart.is_data_table_visible }} |
1298 | + </div> |
1299 | + <div> |
1300 | + Target goal: {{ image_chart.target_goal|floatformat:"-2" }} |
1301 | + </div> |
1302 | + <hr/> |
1303 | + {% empty %} |
1304 | + <div> |
1305 | + <li>No charts added yet.</li> |
1306 | + </div> |
1307 | + {% endfor %} |
1308 | +</div> |
1309 | + |
1310 | +{% endblock %} |
1311 | |
1312 | === added file 'dashboard_app/templates/dashboard_app/image_report_form.html' |
1313 | --- dashboard_app/templates/dashboard_app/image_report_form.html 1970-01-01 00:00:00 +0000 |
1314 | +++ dashboard_app/templates/dashboard_app/image_report_form.html 2013-09-13 13:13:49 +0000 |
1315 | @@ -0,0 +1,45 @@ |
1316 | +{% extends "dashboard_app/_content.html" %} |
1317 | + |
1318 | +{% block extrahead %} |
1319 | +{{ block.super }} |
1320 | +<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/> |
1321 | +{% endblock %} |
1322 | + |
1323 | +{% block content %} |
1324 | +<h1>Image Reports 2.0</h1> |
1325 | + |
1326 | +{% block content_form %} |
1327 | +<form action="" method="post">{% csrf_token %} |
1328 | + |
1329 | + {% if form.errors %} |
1330 | + <div class="errors"> |
1331 | + <div> |
1332 | + {{ form.non_field_errors }} |
1333 | + <ul> |
1334 | + {% for field in form %} |
1335 | + {% if field.errors %} |
1336 | + <li>{{ field.label }}: {{ field.errors|striptags }}</li> |
1337 | + {% endif %} |
1338 | + {% endfor %} |
1339 | + </ul> |
1340 | + </div> |
1341 | + </div> |
1342 | + {% endif %} |
1343 | + |
1344 | +<div class="form-field"> |
1345 | + {{ form.name.label_tag }} |
1346 | + {{ form.name }} |
1347 | +</div> |
1348 | +<div class="form-field"> |
1349 | + {{ form.description.label_tag }} |
1350 | + {{ form.description }} |
1351 | +</div> |
1352 | + |
1353 | +<div class="submit-button"> |
1354 | +<input type="submit" value="Save" /> |
1355 | +</div> |
1356 | +</form> |
1357 | + |
1358 | +{% endblock content_form %} |
1359 | + |
1360 | +{% endblock %} |
1361 | |
1362 | === added file 'dashboard_app/templates/dashboard_app/image_report_list.html' |
1363 | --- dashboard_app/templates/dashboard_app/image_report_list.html 1970-01-01 00:00:00 +0000 |
1364 | +++ dashboard_app/templates/dashboard_app/image_report_list.html 2013-09-13 13:13:49 +0000 |
1365 | @@ -0,0 +1,37 @@ |
1366 | +{% extends "dashboard_app/_content.html" %} |
1367 | + |
1368 | +{% block extrahead %} |
1369 | +{{ block.super }} |
1370 | +<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}dashboard_app/css/image-charts.css"/> |
1371 | +{% endblock %} |
1372 | + |
1373 | +{% block content %} |
1374 | +<h1>Image Reports 2.0</h1> |
1375 | + |
1376 | +<p style="margin-left: 10px;"> |
1377 | + <a href="{% url dashboard_app.views.image_reports.views.image_report_add %}"> |
1378 | + Add new Image Report |
1379 | + </a> |
1380 | +</p> |
1381 | + |
1382 | +{% for image_report in image_reports %} |
1383 | +<div class="list-container"> |
1384 | + <div style="float: left;"> |
1385 | + <a href="{{ image_report.get_absolute_url }}">{{ image_report.name }}</a> |
1386 | + |
1387 | + </div> |
1388 | + {% if image_report.is_published %} |
1389 | + <div style="font-weight: bold; float: right; color: green;"> |
1390 | + Published |
1391 | + </div> |
1392 | + {% else %} |
1393 | + <div style="font-weight: bold; float: right; color: orange;"> |
1394 | + Not Published |
1395 | + </div> |
1396 | + {% endif %} |
1397 | + <div style="clear: both;"> |
1398 | + {{ image_report.description }} |
1399 | + </div> |
1400 | +</div> |
1401 | +{% endfor %} |
1402 | +{% endblock %} |
1403 | |
1404 | === modified file 'dashboard_app/urls.py' |
1405 | --- dashboard_app/urls.py 2013-09-05 11:27:15 +0000 |
1406 | +++ dashboard_app/urls.py 2013-09-13 13:13:49 +0000 |
1407 | @@ -33,6 +33,8 @@ |
1408 | url(r'^filters/\+add$', 'filters.views.filter_add'), |
1409 | url(r'^filters/\+add-preview-json$', 'filters.views.filter_preview_json'), |
1410 | url(r'^filters/\+add-cases-for-test-json$', 'filters.views.filter_add_cases_for_test_json'), |
1411 | + url(r'^filters/\+get-tests-json$', 'filters.views.get_tests_json'), |
1412 | + url(r'^filters/\+get-test-cases-json$', 'filters.views.get_test_cases_json'), |
1413 | url(r'^filters/\+attribute-name-completion-json$', 'filters.views.filter_attr_name_completion_json'), |
1414 | url(r'^filters/\+attribute-value-completion-json$', 'filters.views.filter_attr_value_completion_json'), |
1415 | url(r'^filters/~(?P<username>[^/]+)/(?P<name>[a-zA-Z0-9-_]+)$', 'filters.views.filter_detail'), |
1416 | @@ -63,6 +65,18 @@ |
1417 | url(r'^permalink/bundle/(?P<content_sha1>[0-9a-z]+)/$', 'redirect_to_bundle'), |
1418 | url(r'^permalink/bundle/(?P<content_sha1>[0-9a-z]+)/(?P<trailing>.*)$', 'redirect_to_bundle'), |
1419 | url(r'^image-reports/$', 'images.image_report_list'), |
1420 | + url(r'^image-charts/$', 'image_reports.views.image_report_list'), |
1421 | + url(r'^image-charts/(?P<name>[a-zA-Z0-9-_]+)$', 'image_reports.views.image_report_detail'), |
1422 | + url(r'^image-charts/\+add$', 'image_reports.views.image_report_add'), |
1423 | + url(r'^image-charts/(?P<name>[a-zA-Z0-9-_]+)/\+edit$', 'image_reports.views.image_report_edit'), |
1424 | + url(r'^image-charts/(?P<name>[a-zA-Z0-9-_]+)/\+publish$', 'image_reports.views.image_report_publish'), |
1425 | + url(r'^image-charts/(?P<name>[a-zA-Z0-9-_]+)/\+unpublish$', 'image_reports.views.image_report_unpublish'), |
1426 | + url(r'^image-chart/(?P<id>[a-zA-Z0-9-_]+)$', 'image_reports.views.image_chart_detail'), |
1427 | + url(r'^image-chart/\+add$', 'image_reports.views.image_chart_add'), |
1428 | + url(r'^image-chart/(?P<id>[a-zA-Z0-9-_]+)/\+edit$', 'image_reports.views.image_chart_edit'), |
1429 | + url(r'^image-chart/(?P<id>[a-zA-Z0-9-_]+)/\+add-filter$', 'image_reports.views.image_chart_filter_add'), |
1430 | + url(r'^image-chart-filter/(?P<id>[a-zA-Z0-9-_]+)$', 'image_reports.views.image_chart_filter_edit'), |
1431 | + url(r'^image-chart-filter/(?P<id>[a-zA-Z0-9-_]+)/\+delete$', 'image_reports.views.image_chart_filter_delete'), |
1432 | url(r'^pmqa$', 'pmqa.pmqa_view'), |
1433 | url(r'^pmqa(?P<pathname>/[a-zA-Z0-9/._-]+/)(?P<device_type>[a-zA-Z0-9-_]+)$', 'pmqa.pmqa_filter_view'), |
1434 | url(r'^pmqa(?P<pathname>/[a-zA-Z0-9/._-]+/)(?P<device_type>[a-zA-Z0-9-_]+)/json$', 'pmqa.pmqa_filter_view_json'), |
1435 | |
1436 | === modified file 'dashboard_app/views/filters/tables.py' |
1437 | --- dashboard_app/views/filters/tables.py 2013-01-10 01:56:51 +0000 |
1438 | +++ dashboard_app/views/filters/tables.py 2013-09-13 13:13:49 +0000 |
1439 | @@ -109,6 +109,15 @@ |
1440 | return TestRunFilter.objects.filter(public=True) |
1441 | |
1442 | |
1443 | +class AllFiltersSimpleTable(DataTablesTable): |
1444 | + |
1445 | + name = TemplateColumn(''' |
1446 | + <a href="#" onclick="filters_callback('{{ record.id }}', '{{ record.name }}');">{{ record.name }}</a> |
1447 | + ''') |
1448 | + |
1449 | + def get_queryset(self): |
1450 | + return TestRunFilter.objects.all() |
1451 | + |
1452 | |
1453 | class TestRunColumn(Column): |
1454 | def render(self, record): |
1455 | |
1456 | === modified file 'dashboard_app/views/filters/views.py' |
1457 | --- dashboard_app/views/filters/views.py 2013-01-10 01:56:51 +0000 |
1458 | +++ dashboard_app/views/filters/views.py 2013-09-13 13:13:49 +0000 |
1459 | @@ -20,6 +20,7 @@ |
1460 | |
1461 | from django.contrib.auth.decorators import login_required |
1462 | from django.contrib.contenttypes.models import ContentType |
1463 | +from django.core import serializers |
1464 | from django.core.exceptions import PermissionDenied, ValidationError |
1465 | from django.core.urlresolvers import reverse |
1466 | from django.http import HttpResponse, HttpResponseRedirect |
1467 | @@ -37,6 +38,7 @@ |
1468 | evaluate_filter, |
1469 | ) |
1470 | from dashboard_app.models import ( |
1471 | + Bundle, |
1472 | NamedAttribute, |
1473 | Test, |
1474 | TestCase, |
1475 | @@ -234,6 +236,24 @@ |
1476 | mimetype='application/json') |
1477 | |
1478 | |
1479 | +def get_tests_json(request): |
1480 | + |
1481 | + tests = Test.objects.filter( |
1482 | + test_runs__bundle__bundle_stream__testrunfilter__id=request.GET['id']).distinct() |
1483 | + |
1484 | + data = serializers.serialize('json', tests) |
1485 | + return HttpResponse(data, mimetype='application/json') |
1486 | + |
1487 | + |
1488 | +def get_test_cases_json(request): |
1489 | + |
1490 | + test_cases = TestCase.objects.filter( |
1491 | + test__test_runs__bundle__bundle_stream__testrunfilter__id=request.GET['id']).distinct() |
1492 | + |
1493 | + data = serializers.serialize('json', test_cases) |
1494 | + return HttpResponse(data, mimetype='application/json') |
1495 | + |
1496 | + |
1497 | def filter_attr_name_completion_json(request): |
1498 | term = request.GET['term'] |
1499 | content_type_id = ContentType.objects.get_for_model(TestRun).id |
1500 | |
1501 | === added directory 'dashboard_app/views/image_reports' |
1502 | === added file 'dashboard_app/views/image_reports/__init__.py' |
1503 | --- dashboard_app/views/image_reports/__init__.py 1970-01-01 00:00:00 +0000 |
1504 | +++ dashboard_app/views/image_reports/__init__.py 2013-09-13 13:13:49 +0000 |
1505 | @@ -0,0 +1,17 @@ |
1506 | +# Copyright (C) 2010-2013 Linaro Limited |
1507 | +# |
1508 | +# Author: Stevan Radakovic <stevan.radakovic@linaro.org> |
1509 | +# |
1510 | +# This file is part of Launch Control. |
1511 | +# |
1512 | +# Launch Control is free software: you can redistribute it and/or modify |
1513 | +# it under the terms of the GNU Affero General Public License version 3 |
1514 | +# as published by the Free Software Foundation |
1515 | +# |
1516 | +# Launch Control is distributed in the hope that it will be useful, |
1517 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1518 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1519 | +# GNU General Public License for more details. |
1520 | +# |
1521 | +# You should have received a copy of the GNU Affero General Public License |
1522 | +# along with Launch Control. If not, see <http://www.gnu.org/licenses/>. |
1523 | |
1524 | === added file 'dashboard_app/views/image_reports/forms.py' |
1525 | --- dashboard_app/views/image_reports/forms.py 1970-01-01 00:00:00 +0000 |
1526 | +++ dashboard_app/views/image_reports/forms.py 2013-09-13 13:13:49 +0000 |
1527 | @@ -0,0 +1,91 @@ |
1528 | +# Copyright (C) 2010-2013 Linaro Limited |
1529 | +# |
1530 | +# Author: Stevan Radakovic <stevan.radakovic@linaro.org> |
1531 | +# |
1532 | +# This file is part of Launch Control. |
1533 | +# |
1534 | +# Launch Control is free software: you can redistribute it and/or modify |
1535 | +# it under the terms of the GNU Affero General Public License version 3 |
1536 | +# as published by the Free Software Foundation |
1537 | +# |
1538 | +# Launch Control is distributed in the hope that it will be useful, |
1539 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1540 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1541 | +# GNU General Public License for more details. |
1542 | +# |
1543 | +# You should have received a copy of the GNU Affero General Public License |
1544 | +# along with Launch Control. If not, see <http://www.gnu.org/licenses/>. |
1545 | + |
1546 | +from django import forms |
1547 | + |
1548 | +from dashboard_app.models import ( |
1549 | + ImageReport, |
1550 | + ImageReportChart, |
1551 | + ImageChartFilter, |
1552 | + ImageChartTest, |
1553 | + ImageChartTestCase, |
1554 | + Test, |
1555 | + TestCase, |
1556 | +) |
1557 | + |
1558 | + |
1559 | +class ImageReportEditorForm(forms.ModelForm): |
1560 | + class Meta: |
1561 | + model = ImageReport |
1562 | + exclude = ('owner', 'is_published',) |
1563 | + |
1564 | + def save(self, commit=True, **kwargs): |
1565 | + instance = super(ImageReportEditorForm, |
1566 | + self).save(commit=commit, **kwargs) |
1567 | + return instance |
1568 | + |
1569 | + def is_valid(self): |
1570 | + return super(ImageReportEditorForm, self).is_valid() |
1571 | + |
1572 | + def full_clean(self): |
1573 | + super(ImageReportEditorForm, self).full_clean() |
1574 | + |
1575 | + def __init__(self, user, *args, **kwargs): |
1576 | + super(ImageReportEditorForm, self).__init__(*args, **kwargs) |
1577 | + |
1578 | + |
1579 | +class ImageReportChartForm(forms.ModelForm): |
1580 | + class Meta: |
1581 | + model = ImageReportChart |
1582 | + widgets = {'image_report': forms.HiddenInput} |
1583 | + |
1584 | + def __init__(self, user, *args, **kwargs): |
1585 | + super(ImageReportChartForm, self).__init__(*args, **kwargs) |
1586 | + if len(self.instance.imagechartfilter_set.all()) != 0: |
1587 | + self.fields['chart_type'].label = "" |
1588 | + self.fields['chart_type'].widget = forms.HiddenInput() |
1589 | + |
1590 | + def save(self, commit=True, **kwargs): |
1591 | + instance = super(ImageReportChartForm, |
1592 | + self).save(commit=commit, **kwargs) |
1593 | + return instance |
1594 | + |
1595 | + |
1596 | +class ImageChartFilterForm(forms.ModelForm): |
1597 | + |
1598 | + image_chart_tests = forms.ModelMultipleChoiceField( |
1599 | + widget=forms.MultipleHiddenInput, |
1600 | + queryset=Test.objects.all().order_by("id"), |
1601 | + required=False) |
1602 | + image_chart_test_cases = forms.ModelMultipleChoiceField( |
1603 | + widget=forms.MultipleHiddenInput, |
1604 | + queryset=TestCase.objects.all().order_by("id"), |
1605 | + required=False) |
1606 | + |
1607 | + class Meta: |
1608 | + model = ImageChartFilter |
1609 | + widgets = {'filter': forms.HiddenInput, |
1610 | + 'image_chart': forms.HiddenInput,} |
1611 | + |
1612 | + def __init__(self, user, *args, **kwargs): |
1613 | + super(ImageChartFilterForm, self).__init__(*args, **kwargs) |
1614 | + |
1615 | + def save(self, commit=True, **kwargs): |
1616 | + instance = super(ImageChartFilterForm, |
1617 | + self).save(commit=commit, **kwargs) |
1618 | + return instance |
1619 | |
1620 | === added file 'dashboard_app/views/image_reports/views.py' |
1621 | --- dashboard_app/views/image_reports/views.py 1970-01-01 00:00:00 +0000 |
1622 | +++ dashboard_app/views/image_reports/views.py 2013-09-13 13:13:49 +0000 |
1623 | @@ -0,0 +1,325 @@ |
1624 | +# Copyright (C) 2010-2013 Linaro Limited |
1625 | +# |
1626 | +# Author: Stevan Radakovic <stevan.radakovic@linaro.org> |
1627 | +# |
1628 | +# This file is part of Launch Control. |
1629 | +# |
1630 | +# Launch Control is free software: you can redistribute it and/or modify |
1631 | +# it under the terms of the GNU Affero General Public License version 3 |
1632 | +# as published by the Free Software Foundation |
1633 | +# |
1634 | +# Launch Control is distributed in the hope that it will be useful, |
1635 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1636 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1637 | +# GNU General Public License for more details. |
1638 | +# |
1639 | +# You should have received a copy of the GNU Affero General Public License |
1640 | +# along with Launch Control. If not, see <http://www.gnu.org/licenses/>. |
1641 | + |
1642 | +import json |
1643 | + |
1644 | +from django.contrib.auth.decorators import login_required |
1645 | +from django.core.exceptions import PermissionDenied, ValidationError |
1646 | +from django.http import HttpResponse, HttpResponseRedirect |
1647 | +from django.shortcuts import render_to_response |
1648 | +from django.template import RequestContext |
1649 | +from django.utils.safestring import mark_safe |
1650 | + |
1651 | +from lava_server.bread_crumbs import ( |
1652 | + BreadCrumb, |
1653 | + BreadCrumbTrail, |
1654 | +) |
1655 | + |
1656 | +from dashboard_app.views import index |
1657 | + |
1658 | +from dashboard_app.views.image_reports.forms import ( |
1659 | + ImageReportEditorForm, |
1660 | + ImageReportChartForm, |
1661 | + ImageChartFilterForm, |
1662 | + ) |
1663 | + |
1664 | +from dashboard_app.models import ( |
1665 | + ImageReport, |
1666 | + ImageReportChart, |
1667 | + ImageChartFilter, |
1668 | + ImageChartTest, |
1669 | + ImageChartTestCase, |
1670 | + Test, |
1671 | + TestCase, |
1672 | + TestRunFilter, |
1673 | + ) |
1674 | + |
1675 | +from dashboard_app.views.filters.tables import AllFiltersSimpleTable |
1676 | + |
1677 | + |
1678 | + |
1679 | +@BreadCrumb("Image reports", parent=index) |
1680 | +def image_report_list(request): |
1681 | + |
1682 | + if request.user.is_authenticated(): |
1683 | + image_reports = ImageReport.objects.all() |
1684 | + else: |
1685 | + image_reports = None |
1686 | + |
1687 | + return render_to_response( |
1688 | + 'dashboard_app/image_report_list.html', { |
1689 | + "image_reports": image_reports, |
1690 | + }, RequestContext(request) |
1691 | + ) |
1692 | + |
1693 | +@BreadCrumb("Image report {name}", parent=image_report_list, needs=['name']) |
1694 | +def image_report_detail(request, name): |
1695 | + image_report = ImageReport.objects.get(name=name) |
1696 | + |
1697 | + return render_to_response( |
1698 | + 'dashboard_app/image_report_detail.html', { |
1699 | + 'image_report': image_report, |
1700 | + 'bread_crumb_trail': BreadCrumbTrail.leading_to( |
1701 | + image_report_detail, name=name), |
1702 | + }, RequestContext(request) |
1703 | + ) |
1704 | + |
1705 | +@BreadCrumb("Add new image report", parent=image_report_list) |
1706 | +@login_required |
1707 | +def image_report_add(request): |
1708 | + return image_report_form( |
1709 | + request, |
1710 | + BreadCrumbTrail.leading_to(image_report_add)) |
1711 | + |
1712 | +@BreadCrumb("Update image report {name}", parent=image_report_list, |
1713 | + needs=['name']) |
1714 | +@login_required |
1715 | +def image_report_edit(request, name): |
1716 | + image_report = ImageReport.objects.get(name=name) |
1717 | + return image_report_form( |
1718 | + request, |
1719 | + BreadCrumbTrail.leading_to(image_report_edit, |
1720 | + name=name), |
1721 | + instance=image_report) |
1722 | + |
1723 | +@BreadCrumb("Publish image report {name}", parent=image_report_list, |
1724 | + needs=['name']) |
1725 | +@login_required |
1726 | +def image_report_publish(request, name): |
1727 | + image_report = ImageReport.objects.get(name=name) |
1728 | + image_report.is_published = True |
1729 | + image_report.save() |
1730 | + |
1731 | + return render_to_response( |
1732 | + 'dashboard_app/image_report_detail.html', { |
1733 | + 'image_report': image_report, |
1734 | + 'bread_crumb_trail': BreadCrumbTrail.leading_to( |
1735 | + image_report_detail, name=name), |
1736 | + }, RequestContext(request) |
1737 | + ) |
1738 | + |
1739 | +@BreadCrumb("Unpublish image report {name}", parent=image_report_list, |
1740 | + needs=['name']) |
1741 | +@login_required |
1742 | +def image_report_unpublish(request, name): |
1743 | + image_report = ImageReport.objects.get(name=name) |
1744 | + image_report.is_published = False |
1745 | + image_report.save() |
1746 | + |
1747 | + return render_to_response( |
1748 | + 'dashboard_app/image_report_detail.html', { |
1749 | + 'image_report': image_report, |
1750 | + 'bread_crumb_trail': BreadCrumbTrail.leading_to( |
1751 | + image_report_detail, name=name), |
1752 | + }, RequestContext(request) |
1753 | + ) |
1754 | + |
1755 | +def image_report_form(request, bread_crumb_trail, instance=None): |
1756 | + |
1757 | + if request.method == 'POST': |
1758 | + |
1759 | + form = ImageReportEditorForm(request.user, request.POST, |
1760 | + instance=instance) |
1761 | + if form.is_valid(): |
1762 | + image_report = form.save() |
1763 | + return HttpResponseRedirect(image_report.get_absolute_url()) |
1764 | + |
1765 | + else: |
1766 | + form = ImageReportEditorForm(request.user, instance=instance) |
1767 | + |
1768 | + return render_to_response( |
1769 | + 'dashboard_app/image_report_form.html', { |
1770 | + 'bread_crumb_trail': bread_crumb_trail, |
1771 | + 'form': form, |
1772 | + }, RequestContext(request)) |
1773 | + |
1774 | +@BreadCrumb("Image chart details", parent=image_report_list) |
1775 | +def image_chart_detail(request, id): |
1776 | + image_chart = ImageReportChart.objects.get(id=id) |
1777 | + |
1778 | + return render_to_response( |
1779 | + 'dashboard_app/image_report_chart_detail.html', { |
1780 | + 'image_chart': image_chart, |
1781 | + 'bread_crumb_trail': BreadCrumbTrail.leading_to( |
1782 | + image_chart_detail, id=id), |
1783 | + }, RequestContext(request) |
1784 | + ) |
1785 | + |
1786 | +@BreadCrumb("Add new image chart", parent=image_report_list) |
1787 | +@login_required |
1788 | +def image_chart_add(request): |
1789 | + return image_chart_form( |
1790 | + request, |
1791 | + BreadCrumbTrail.leading_to(image_chart_add)) |
1792 | + |
1793 | +@BreadCrumb("Update image chart", parent=image_report_list) |
1794 | +@login_required |
1795 | +def image_chart_edit(request, id): |
1796 | + image_chart = ImageReportChart.objects.get(id=id) |
1797 | + return image_chart_form( |
1798 | + request, |
1799 | + BreadCrumbTrail.leading_to(image_chart_edit, |
1800 | + id=id), |
1801 | + instance=image_chart) |
1802 | + |
1803 | +def image_chart_form(request, bread_crumb_trail, instance=None): |
1804 | + |
1805 | + if request.method == 'POST': |
1806 | + |
1807 | + form = ImageReportChartForm(request.user, request.POST, |
1808 | + instance=instance) |
1809 | + if form.is_valid(): |
1810 | + image_chart = form.save() |
1811 | + return HttpResponseRedirect( |
1812 | + image_chart.get_absolute_url()) |
1813 | + |
1814 | + else: |
1815 | + form = ImageReportChartForm(request.user, instance=instance) |
1816 | + |
1817 | + if not instance: |
1818 | + image_report_id = request.GET.get('image_report_id', None) |
1819 | + else: |
1820 | + image_report_id = instance.image_report.id |
1821 | + |
1822 | + filters_table = AllFiltersSimpleTable("all-filters", None) |
1823 | + |
1824 | + return render_to_response( |
1825 | + 'dashboard_app/image_report_chart_form.html', { |
1826 | + 'bread_crumb_trail': bread_crumb_trail, |
1827 | + 'form': form, |
1828 | + 'filters_table': filters_table, |
1829 | + 'image_report_id': image_report_id, |
1830 | + }, RequestContext(request)) |
1831 | + |
1832 | +@BreadCrumb("Image chart add filter", parent=image_report_list) |
1833 | +def image_chart_filter_add(request, id): |
1834 | + image_chart = ImageReportChart.objects.get(id=id) |
1835 | + return image_chart_filter_form( |
1836 | + request, |
1837 | + BreadCrumbTrail.leading_to(image_chart_filter_add), |
1838 | + chart_instance=image_chart) |
1839 | + |
1840 | +@BreadCrumb("Update image chart filter", parent=image_report_list) |
1841 | +@login_required |
1842 | +def image_chart_filter_edit(request, id): |
1843 | + image_chart_filter = ImageChartFilter.objects.get(id=id) |
1844 | + return image_chart_filter_form( |
1845 | + request, |
1846 | + BreadCrumbTrail.leading_to(image_chart_filter_edit, id=id), |
1847 | + instance=image_chart_filter) |
1848 | + |
1849 | +@BreadCrumb("Image chart add filter", parent=image_report_list) |
1850 | +def image_chart_filter_delete(request, id): |
1851 | + image_chart_filter = ImageChartFilter.objects.get(id=id) |
1852 | + url = image_chart_filter.image_chart.get_absolute_url() |
1853 | + image_chart_filter.delete() |
1854 | + return HttpResponseRedirect(url) |
1855 | + |
1856 | +def image_chart_filter_form(request, bread_crumb_trail, chart_instance=None, |
1857 | + instance=None): |
1858 | + |
1859 | + if instance: |
1860 | + chart_instance = instance.image_chart |
1861 | + |
1862 | + if request.method == 'POST': |
1863 | + |
1864 | + form = ImageChartFilterForm(request.user, request.POST, |
1865 | + instance=instance) |
1866 | + |
1867 | + if form.is_valid(): |
1868 | + |
1869 | + chart_filter = form.save() |
1870 | + aliases = request.POST.getlist('aliases') |
1871 | + |
1872 | + |
1873 | + if chart_filter.image_chart.chart_type == 'pass/fail': |
1874 | + |
1875 | + image_chart_tests = Test.objects.filter( |
1876 | + imagecharttest__image_chart_filter=chart_filter).order_by( |
1877 | + 'id') |
1878 | + |
1879 | + tests = form.cleaned_data['image_chart_tests'] |
1880 | + |
1881 | + for index, test in enumerate(tests): |
1882 | + if test in image_chart_tests: |
1883 | + chart_test = ImageChartTest.objects.get( |
1884 | + image_chart_filter=chart_filter, test=test) |
1885 | + chart_test.name = aliases[index] |
1886 | + chart_test.save() |
1887 | + else: |
1888 | + chart_test = ImageChartTest() |
1889 | + chart_test.image_chart_filter = chart_filter |
1890 | + chart_test.test = test |
1891 | + chart_test.name = aliases[index] |
1892 | + chart_test.save() |
1893 | + |
1894 | + for index, chart_test in enumerate(image_chart_tests): |
1895 | + if chart_test not in tests: |
1896 | + ImageChartTest.objects.get( |
1897 | + image_chart_filter=chart_filter, |
1898 | + test=chart_test).delete() |
1899 | + |
1900 | + return HttpResponseRedirect( |
1901 | + chart_filter.image_chart.get_absolute_url()) |
1902 | + |
1903 | + else: |
1904 | + |
1905 | + image_chart_test_cases = TestCase.objects.filter( |
1906 | + imagecharttestcase__image_chart_filter= |
1907 | + chart_filter).order_by('id') |
1908 | + |
1909 | + test_cases = form.cleaned_data['image_chart_test_cases'] |
1910 | + |
1911 | + for index, test_case in enumerate(test_cases): |
1912 | + if test_case in image_chart_test_cases: |
1913 | + chart_test_case = ImageChartTestCase.objects.get( |
1914 | + image_chart_filter=chart_filter, |
1915 | + test_case=test_case) |
1916 | + chart_test_case.name = aliases[index] |
1917 | + chart_test_case.save() |
1918 | + else: |
1919 | + chart_test_case = ImageChartTestCase() |
1920 | + chart_test_case.image_chart_filter = chart_filter |
1921 | + chart_test_case.test_case = test_case |
1922 | + chart_test_case.name = aliases[index] |
1923 | + chart_test_case.save() |
1924 | + |
1925 | + for index, chart_test_case in enumerate( |
1926 | + image_chart_test_cases): |
1927 | + if chart_test_case not in test_cases: |
1928 | + ImageChartTestCase.objects.get( |
1929 | + image_chart_filter=chart_filter, |
1930 | + test_case=chart_test_case).delete() |
1931 | + |
1932 | + return HttpResponseRedirect( |
1933 | + chart_filter.image_chart.get_absolute_url()) |
1934 | + |
1935 | + else: |
1936 | + form = ImageChartFilterForm(request.user, instance=instance, |
1937 | + initial={'image_chart': chart_instance}) |
1938 | + |
1939 | + filters_table = AllFiltersSimpleTable("all-filters", None) |
1940 | + |
1941 | + return render_to_response( |
1942 | + 'dashboard_app/image_chart_filter_form.html', { |
1943 | + 'bread_crumb_trail': bread_crumb_trail, |
1944 | + 'filters_table': filters_table, |
1945 | + 'image_chart': chart_instance, |
1946 | + 'instance': instance, |
1947 | + 'form': form, |
1948 | + }, RequestContext(request)) |
> === added file 'dashboard_ app/migrations/ 0030_auto_ _add_imagechart test__add_ imagereport_ _add_imagechart testcase_ _add.py' app/migrations/ 0030_auto_ _add_imagechart testcase_ _add_imagerepor t__add_ imagecharttestr un__.py'
> === removed file 'dashboard_
AFAICT you cannot remove migrations that were already added and were already
run, only add new migrations. I think you have to put the old one back, remove
the new one, and generate one that will record just the changes since the
previous.
Did you test upgrading from trunk code to your new version?
review needs-fixing