summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2014-06-30 15:58:36 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-07-14 14:10:03 +0100
commite7fa0c325d59811c272b7dad671225fea8c29609 (patch)
tree599e0c75cef2d37fc1573d7ff91b9f3ce7b6f180
parentd19b784c1a2a4380c63947690ae6f7fa393c1ebc (diff)
downloadpoky-e7fa0c325d59811c272b7dad671225fea8c29609.tar.gz
bitbake: toaster: new project page implementation
We add the logic to create a new project. This page also serves as user registration and silent login for users. Once the project is added, the main project page is displayed. (Bitbake rev: 8855daebe55917c4f5855413d02ae1f3f7f76571) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py257
-rw-r--r--bitbake/lib/toaster/orm/models.py38
-rw-r--r--bitbake/lib/toaster/toastergui/templates/newproject.html13
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py2
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py48
5 files changed, 338 insertions, 20 deletions
diff --git a/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py b/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py
new file mode 100644
index 0000000000..aa1ce1f4ac
--- /dev/null
+++ b/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py
@@ -0,0 +1,257 @@
1# -*- coding: utf-8 -*-
2from south.utils import datetime_utils as datetime
3from south.db import db
4from south.v2 import SchemaMigration
5from django.db import models
6
7
8class Migration(SchemaMigration):
9
10 def forwards(self, orm):
11 # Adding field 'Project.branch'
12 db.add_column(u'orm_project', 'branch',
13 self.gf('django.db.models.fields.CharField')(default='master', max_length=50),
14 keep_default=False)
15
16 # Adding field 'Project.short_description'
17 db.add_column(u'orm_project', 'short_description',
18 self.gf('django.db.models.fields.CharField')(default='', max_length=50, blank=True),
19 keep_default=False)
20
21 # Adding field 'Project.user_id'
22 db.add_column(u'orm_project', 'user_id',
23 self.gf('django.db.models.fields.IntegerField')(null=True),
24 keep_default=False)
25
26
27 def backwards(self, orm):
28 # Deleting field 'Project.branch'
29 db.delete_column(u'orm_project', 'branch')
30
31 # Deleting field 'Project.short_description'
32 db.delete_column(u'orm_project', 'short_description')
33
34 # Deleting field 'Project.user_id'
35 db.delete_column(u'orm_project', 'user_id')
36
37
38 models = {
39 u'orm.build': {
40 'Meta': {'object_name': 'Build'},
41 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
42 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
43 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
44 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
45 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
46 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
47 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
48 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
49 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
50 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
51 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
52 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
53 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
54 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
55 },
56 u'orm.helptext': {
57 'Meta': {'object_name': 'HelpText'},
58 'area': ('django.db.models.fields.IntegerField', [], {}),
59 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
60 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
61 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
62 'text': ('django.db.models.fields.TextField', [], {})
63 },
64 u'orm.layer': {
65 'Meta': {'object_name': 'Layer'},
66 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
67 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
68 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
69 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
70 },
71 u'orm.layer_version': {
72 'Meta': {'object_name': 'Layer_Version'},
73 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
74 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
75 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
76 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
77 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
78 'priority': ('django.db.models.fields.IntegerField', [], {})
79 },
80 u'orm.logmessage': {
81 'Meta': {'object_name': 'LogMessage'},
82 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
83 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
84 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
85 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
86 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
87 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
88 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
89 },
90 u'orm.package': {
91 'Meta': {'object_name': 'Package'},
92 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
93 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
94 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
95 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
96 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
97 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
98 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
99 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
100 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
101 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
102 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
103 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
104 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
105 },
106 u'orm.package_dependency': {
107 'Meta': {'object_name': 'Package_Dependency'},
108 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
109 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
110 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
111 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
112 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
113 },
114 u'orm.package_file': {
115 'Meta': {'object_name': 'Package_File'},
116 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
117 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
118 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
119 'size': ('django.db.models.fields.IntegerField', [], {})
120 },
121 u'orm.project': {
122 'Meta': {'object_name': 'Project'},
123 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
124 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
125 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
126 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
127 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
128 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
129 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
130 },
131 u'orm.projectlayer': {
132 'Meta': {'object_name': 'ProjectLayer'},
133 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
134 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
135 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
136 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
137 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
138 },
139 u'orm.projecttarget': {
140 'Meta': {'object_name': 'ProjectTarget'},
141 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
142 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
143 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
144 },
145 u'orm.projectvariable': {
146 'Meta': {'object_name': 'ProjectVariable'},
147 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
148 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
149 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
150 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
151 },
152 u'orm.recipe': {
153 'Meta': {'object_name': 'Recipe'},
154 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
155 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
156 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
157 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
158 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
159 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
160 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
161 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
162 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
163 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
164 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
165 },
166 u'orm.recipe_dependency': {
167 'Meta': {'object_name': 'Recipe_Dependency'},
168 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
169 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
170 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
171 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
172 },
173 u'orm.target': {
174 'Meta': {'object_name': 'Target'},
175 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
176 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
177 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
178 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
179 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
180 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
181 },
182 u'orm.target_file': {
183 'Meta': {'object_name': 'Target_File'},
184 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
185 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
186 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
187 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
188 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
189 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
190 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
191 'size': ('django.db.models.fields.IntegerField', [], {}),
192 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
193 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
194 },
195 u'orm.target_image_file': {
196 'Meta': {'object_name': 'Target_Image_File'},
197 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
198 'file_size': ('django.db.models.fields.IntegerField', [], {}),
199 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
200 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
201 },
202 u'orm.target_installed_package': {
203 'Meta': {'object_name': 'Target_Installed_Package'},
204 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
205 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
206 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
207 },
208 u'orm.task': {
209 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
210 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
211 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
212 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
213 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
214 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
215 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
216 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
217 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
218 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
219 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
220 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
221 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
222 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
223 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
224 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
225 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
226 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
227 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
228 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
229 },
230 u'orm.task_dependency': {
231 'Meta': {'object_name': 'Task_Dependency'},
232 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
233 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
234 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
235 },
236 u'orm.variable': {
237 'Meta': {'object_name': 'Variable'},
238 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
239 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
240 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
241 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
242 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
243 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
244 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
245 },
246 u'orm.variablehistory': {
247 'Meta': {'object_name': 'VariableHistory'},
248 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
249 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
250 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
251 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
252 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
253 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
254 }
255 }
256
257 complete_apps = ['orm'] \ No newline at end of file
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index b67afe139c..f4064296bc 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -23,10 +23,48 @@ from django.db import models
23from django.db.models import F 23from django.db.models import F
24from django.utils.encoding import python_2_unicode_compatible 24from django.utils.encoding import python_2_unicode_compatible
25 25
26class ProjectManager(models.Manager):
27 def create_project(self, name, branch, short_description):
28 prj = self.model(name = name, branch = branch, short_description = short_description)
29 prj.save()
30
31 # create default variables
32 ProjectVariable.objects.create(project = prj, name = "MACHINE", value = "qemux86")
33 ProjectVariable.objects.create(project = prj, name = "DISTRO", value = "poky")
34
35 # create default layers
36 ProjectLayer.objects.create(project = prj,
37 name = "meta",
38 giturl = "git://git.yoctoproject.org/poky",
39 commit = branch,
40 treepath = "meta")
41
42 ProjectLayer.objects.create(project = prj,
43 name = "meta-yocto",
44 giturl = "git://git.yoctoproject.org/poky",
45 commit = branch,
46 treepath = "meta-yocto")
47
48 return prj
49
50 def create(self, *args, **kwargs):
51 raise Exception("Invalid call to Project.objects.create. Use Project.objects.create_project() to create a project")
52
53 def get_or_create(self, *args, **kwargs):
54 raise Exception("Invalid call to Project.objects.get_or_create. Use Project.objects.create_project() to create a project")
55
26class Project(models.Model): 56class Project(models.Model):
27 name = models.CharField(max_length=100) 57 name = models.CharField(max_length=100)
58 branch = models.CharField(max_length=50)
59 short_description = models.CharField(max_length=50, blank=True)
28 created = models.DateTimeField(auto_now_add = True) 60 created = models.DateTimeField(auto_now_add = True)
29 updated = models.DateTimeField(auto_now = True) 61 updated = models.DateTimeField(auto_now = True)
62 # This is a horrible hack; since Toaster has no "User" model available when
63 # running in interactive mode, we can't reference the field here directly
64 # Instead, we keep a possible null reference to the User id, as not to force
65 # hard links to possibly missing models
66 user_id = models.IntegerField(null = True)
67 objects = ProjectManager()
30 68
31class Build(models.Model): 69class Build(models.Model):
32 SUCCEEDED = 0 70 SUCCEEDED = 0
diff --git a/bitbake/lib/toaster/toastergui/templates/newproject.html b/bitbake/lib/toaster/toastergui/templates/newproject.html
index ce01800e08..8f1867a94f 100644
--- a/bitbake/lib/toaster/toastergui/templates/newproject.html
+++ b/bitbake/lib/toaster/toastergui/templates/newproject.html
@@ -8,9 +8,9 @@
8 <h1>Create a new project</h1> 8 <h1>Create a new project</h1>
9 </div> 9 </div>
10 <div class="container-fluid"> 10 <div class="container-fluid">
11 {% for a in alerts %} 11 {% if alert %}
12 <div class="alert alert-error row-fluid" role="alert">{{a}}</div> 12 <div class="alert alert-error row-fluid" role="alert">{{alert}}</div>
13 {% endfor %} 13 {% endif %}
14 </div> 14 </div>
15 <form method="POST">{% csrf_token %} 15 <form method="POST">{% csrf_token %}
16 <fieldset> 16 <fieldset>
@@ -27,10 +27,9 @@
27 Yocto Project version 27 Yocto Project version
28 <i class="icon-question-sign get-help" title="This sets the branch for the Yocto Project core layers (meta, meta-yocto and meta-yocto-bsp), and for the layers you use from the OpenEmbedded Metadata Index"></i> 28 <i class="icon-question-sign get-help" title="This sets the branch for the Yocto Project core layers (meta, meta-yocto and meta-yocto-bsp), and for the layers you use from the OpenEmbedded Metadata Index"></i>
29 </label> 29 </label>
30 <select name="projectversion"> 30 <select name="projectversion" id="projectversion">
31 <option value="1.7" {%if projectversion == "1.7" %}selected{%endif%}>Yocto Project 1.7 "D?"</option> 31 <!-- TODO: XHR data from http://layers.openembedded.org/layerindex/branch/master/layers/ -->
32 <option value="1.6" {%if projectversion == "1.6" %}selected{%endif%}>Yocto Project 1.6 "Daisy"</option> 32 <option value="master" {%if projectversion == "master" %}selected{%endif%}>master</option>
33 <option value="1.5" {%if projectversion == "1.5" %}selected{%endif%}>Yocto Project 1.5 "Dora"</option>
34 </select> 33 </select>
35 </fieldset> 34 </fieldset>
36 35
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index bba4fda074..0d7a4c35fa 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -68,7 +68,7 @@ urlpatterns = patterns('toastergui.views',
68 68
69 # project URLs 69 # project URLs
70 url(r'^newproject/$', 'newproject', name='newproject'), 70 url(r'^newproject/$', 'newproject', name='newproject'),
71 url(r'^project/$', 'project', name='project'), 71 url(r'^project/(?P<pid>\d+)/$', 'project', name='project'),
72 72
73 # default redirection 73 # default redirection
74 url(r'^$', RedirectView.as_view( url= 'builds/')), 74 url(r'^$', RedirectView.as_view( url= 'builds/')),
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index a57f001459..8fbe8a3640 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -22,11 +22,13 @@
22import operator,re 22import operator,re
23 23
24from django.db.models import Q, Sum 24from django.db.models import Q, Sum
25from django.db import IntegrityError
25from django.shortcuts import render, redirect 26from django.shortcuts import render, redirect
26from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable 27from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
27from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency 28from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
28from orm.models import Target_Installed_Package, Target_File, Target_Image_File 29from orm.models import Target_Installed_Package, Target_File, Target_Image_File
29from django.views.decorators.cache import cache_control 30from django.views.decorators.cache import cache_control
31from django.core.urlresolvers import reverse
30from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 32from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
31from django.http import HttpResponseBadRequest 33from django.http import HttpResponseBadRequest
32from django.utils import timezone 34from django.utils import timezone
@@ -68,7 +70,6 @@ def _verify_parameters(g, mandatory_parameters):
68 70
69def _redirect_parameters(view, g, mandatory_parameters, *args, **kwargs): 71def _redirect_parameters(view, g, mandatory_parameters, *args, **kwargs):
70 import urllib 72 import urllib
71 from django.core.urlresolvers import reverse
72 url = reverse(view, kwargs=kwargs) 73 url = reverse(view, kwargs=kwargs)
73 params = {} 74 params = {}
74 for i in g: 75 for i in g:
@@ -1772,6 +1773,16 @@ if toastermain.settings.MANAGED:
1772 from django.contrib.auth import authenticate, login 1773 from django.contrib.auth import authenticate, login
1773 from django.contrib.auth.decorators import login_required 1774 from django.contrib.auth.decorators import login_required
1774 1775
1776 import traceback
1777
1778 class BadParameterException(Exception): pass # error thrown on invalid POST requests
1779
1780 # the context processor that supplies data used across all the pages
1781 def managedcontextprocessor(request):
1782 return {
1783 "projects": Project.objects.all(),
1784 "MANAGED" : toastermain.settings.MANAGED
1785 }
1775 1786
1776 # new project 1787 # new project
1777 def newproject(request): 1788 def newproject(request):
@@ -1787,28 +1798,41 @@ if toastermain.settings.MANAGED:
1787 return render(request, template, context) 1798 return render(request, template, context)
1788 elif request.method == "POST": 1799 elif request.method == "POST":
1789 mandatory_fields = ['projectname', 'email', 'username', 'projectversion'] 1800 mandatory_fields = ['projectname', 'email', 'username', 'projectversion']
1790 if reduce( lambda x, y: x and y, map(lambda x: x in request.POST and len(request.POST[x]) > 0, mandatory_fields)): 1801 try:
1802 # make sure we have values for all mandatory_fields
1803 if reduce( lambda x, y: x or y, map(lambda x: len(request.POST.get(x, '')) == 0, mandatory_fields)):
1804 # set alert for missing fields
1805 raise BadParameterException("Fields missing: " +
1806 ", ".join([x for x in mandatory_fields if len(request.POST.get(x, '')) == 0 ]))
1807
1791 if not request.user.is_authenticated(): 1808 if not request.user.is_authenticated():
1792 user = authenticate(username = request.POST['username'], password = 'nopass') 1809 user = authenticate(username = request.POST['username'], password = 'nopass')
1793 if user is None: 1810 if user is None:
1794 user = User.objects.create_user(username = request.POST['username'], email = request.POST['email'], password = "nopass") 1811 user = User.objects.create_user(username = request.POST['username'], email = request.POST['email'], password = "nopass")
1795 raise Exception("User cannot be authed, creating") 1812
1796 user = authenticate(username = request.POST['username'], password = '') 1813 user = authenticate(username = user.username, password = 'nopass')
1797 login(request, user) 1814 login(request, user)
1798 1815
1799 return redirect(project) 1816 # save the project
1800 else: 1817 prj = Project.objects.create_project(name = request.POST['projectname'],
1801 alerts = [] 1818 branch = request.POST['projectversion'].split(" ")[0],
1802 # set alerts for missing fields 1819 short_description=request.POST['projectversion'].split(" ")[1:])
1803 map(lambda x: alerts.append('Field '+ x + ' not filled in') if not x in request.POST or len(request.POST[x]) == 0 else None, mandatory_fields) 1820 prj.user_id = request.user.pk
1804 # fill in new page with already submitted values 1821 prj.save()
1822 return redirect(reverse(project, args = (prj.pk,)))
1823
1824 except (IntegrityError, BadParameterException) as e:
1825 # fill in page with previously submitted values
1805 map(lambda x: context.__setitem__(x, request.POST[x]), mandatory_fields) 1826 map(lambda x: context.__setitem__(x, request.POST[x]), mandatory_fields)
1806 context['alerts'] = alerts 1827 if isinstance(e, IntegrityError) and "username" in str(e):
1828 context['alert'] = "Your chosen username is already used"
1829 else:
1830 context['alert'] = str(e)
1807 return render(request, template, context) 1831 return render(request, template, context)
1808 raise Exception("Invalid HTTP method for this page") 1832 raise Exception("Invalid HTTP method for this page")
1809 1833
1810 # Shows the edit project page 1834 # Shows the edit project page
1811 def project(request): 1835 def project(request, pid):
1812 template = "project.html" 1836 template = "project.html"
1813 context = {} 1837 context = {}
1814 return render(request, template, context) 1838 return render(request, template, context)