Merge lp:~cprov/uci-engine/webui-create-ticket into lp:uci-engine
- webui-create-ticket
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Celso Providelo |
Approved revision: | no longer in the source branch. |
Merged at revision: | 801 |
Proposed branch: | lp:~cprov/uci-engine/webui-create-ticket |
Merge into: | lp:uci-engine |
Diff against target: |
226 lines (+175/-1) 7 files modified
webui/common/static/common/webui.css (+36/-0) webui/tickets/static/tickets/webui.js (+1/-1) webui/tickets/static/tickets/webui_create_ticket.js (+5/-0) webui/tickets/static/tickets/webuiforms.js (+105/-0) webui/tickets/templates/tickets/create.html (+23/-0) webui/tickets/urls.py (+1/-0) webui/tickets/views.py (+4/-0) |
To merge this branch: | bzr merge lp:~cprov/uci-engine/webui-create-ticket |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Evan (community) | Approve | ||
Joe Talbott | Pending | ||
Review via email: mp+235554@code.launchpad.net |
Commit message
Implements a ticket creation form in the webui.
Description of the change
Implements a ticket creation form in the webui.
This form will be used during the ci-train transition (where the CLI is not part of the workflow).
It uses Y.form to build, render and validate the new form and implements a custom form submission function to submit data as JSON to the Ticket-System.
The form is not yet linked from the other pages, the current navbar/breadcrumb is not a good place for it (IMHO).
PS Jenkins bot (ps-jenkins) wrote : | # |
Comments inline. Are we going to handle form validation in a follow up MP?
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:795
http://
Executed test runs:
Click here to trigger a rebuild:
http://
Celso Providelo (cprov) wrote : | # |
On Tue, Sep 23, 2014 at 8:14 AM, Evan Dandrea
<email address hidden> wrote:
> Review: Needs Fixing
>
> Comments inline. Are we going to handle form validation in a follow up MP?
Basic validation were already in place (required fields). I've added
an email-address validation for the current owner field for now, but
once authentication is in place that field will be removed/hidden.
> Title, description, and owner end up as clickable links that focus on the title input box. Series is plain text. This looks odd.
I've extended and fixed Y.SelectField() which was being stupid when
rendering the label.
>> + {name: 'title', required: true, label: 'Title'},
>> + {name: 'description', label: 'Description',
>> + type: 'TextareaField'},
>> + {name: 'owner', required: true, label: 'Owner'},
>> + {name : 'series', required: true, label : 'Series',
>> + type : 'SelectField',
>> + choices : [
>> + {label : 'Utopic', value : 'utopic'},
>> + {label : 'Trusty', value : 'trusty'},
>> + {label : 'Precise', value : 'precise'},
>
> Must we hardcode this? If so, I think we should follow up with an MP to put this in a separate js file that can be pulled in from any code that needs it.
I've split the 'webuiform' module as an experiment, overall loading
performance is faster. 'webuiforms' also host 'seriesChoices', so it's
easier to maintain the hardcoded bits until there is a better
solution.
>> + ]},
>> + {name: 'create-button', type: 'SubmitButton',
>> + value: 'Create!'}
>> + ]
>> + });
>> + f.render();
>> +
>> + // Hijack the default (www-urlencoded) form submission and
>> + // submit its content as JSON.
>> + f.getField(
>> + e.halt();
>> + if (!f._runValidat
>> + return 1;
>> + }
>> +
>> + // XXX cprov 20140922: extend the form data with appropriate
>> + // 'status' and 'current_
>> + var form_data = f.toJSON();
>> +
>> + Y.io(f.
>> + method: f.get('method'),
>> + sync: true,
>> + data: Y.JSON.
>> + headers: {
>> + 'Content-Type': 'application/
>> + },
>> + on: {
>> + success: function(tx, r) {
>> + var location = r.getResponseHe
>> + Y.log('SUCCESS: ' + location);
>
> Leftover from debugging?
Yes, removed.
>> + Y.config.
>> + '/api/v1', '');
>> + },
>> + failure: function (tx, r) {
>> + Y.log('FA...
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:796
http://
Executed test runs:
Click here to trigger a rebuild:
http://
Joe Talbott (joetalbott) wrote : | # |
On Tue, Sep 23, 2014 at 02:46:22AM -0000, Celso Providelo wrote:
> Celso Providelo has proposed merging lp:~cprov/uci-engine/webui-create-ticket into lp:uci-engine.
>
> Commit message:
> Implements a ticket creation form in the webui.
>
> Requested reviews:
> Joe Talbott (joetalbott)
> Canonical CI Engineering (canonical-
>
> For more details, see:
> https:/
>
> Implements a ticket creation form in the webui.
>
> This form will be used during the ci-train transition (where the CLI is not part of the workflow).
>
> It uses Y.form to build, render and validate the new form and implements a custom form submission function to submit data as JSON to the Ticket-System.
>
> The form is not yet linked from the other pages, the current navbar/breadcrumb is not a good place for it (IMHO).
I thought we were going to have the TS generate the form?
Celso Providelo (cprov) wrote : | # |
Joe,
I've experimented with this idea and realize that the form generation
is not part of the API provider, it already offer us REST primitives
and it is good at it.
The forms are related to the way the UI is layed and users want to use
it, a single form will probably involve data from many models and will
be executed via multiple REST posts.
Long story short, building forms on TS would be going in the wrong
direction by artificially coupling UI to Models (not APIs), to not
mention the additional django view + forms which would tie us even
more to django for a simple REST wsgi app.
The way it's is done, the form is built and validated client-side in
terms of the information users want to provide and submitted according
to what our API allows us to do.
Do you see it differently ?
[]
On Tue, Sep 23, 2014 at 12:15 PM, Joe Talbott <email address hidden> wrote:
> On Tue, Sep 23, 2014 at 02:46:22AM -0000, Celso Providelo wrote:
>> Celso Providelo has proposed merging lp:~cprov/uci-engine/webui-create-ticket into lp:uci-engine.
>>
>> Commit message:
>> Implements a ticket creation form in the webui.
>>
>> Requested reviews:
>> Joe Talbott (joetalbott)
>> Canonical CI Engineering (canonical-
>>
>> For more details, see:
>> https:/
>>
>> Implements a ticket creation form in the webui.
>>
>> This form will be used during the ci-train transition (where the CLI is not part of the workflow).
>>
>> It uses Y.form to build, render and validate the new form and implements a custom form submission function to submit data as JSON to the Ticket-System.
>>
>> The form is not yet linked from the other pages, the current navbar/breadcrumb is not a good place for it (IMHO).
>
>
> I thought we were going to have the TS generate the form?
>
>
> --
> https:/
> You are the owner of lp:~cprov/uci-engine/webui-create-ticket.
--
Celso Providelo
<email address hidden>
Looks good. Thanks for the updates.
Joe Talbott (joetalbott) wrote : | # |
On Tue, Sep 23, 2014 at 03:30:48PM -0000, Celso Providelo wrote:
> Joe,
>
> I've experimented with this idea and realize that the form generation
> is not part of the API provider, it already offer us REST primitives
> and it is good at it.
>
> The forms are related to the way the UI is layed and users want to use
> it, a single form will probably involve data from many models and will
> be executed via multiple REST posts.
>
> Long story short, building forms on TS would be going in the wrong
> direction by artificially coupling UI to Models (not APIs), to not
> mention the additional django view + forms which would tie us even
> more to django for a simple REST wsgi app.
>
> The way it's is done, the form is built and validated client-side in
> terms of the information users want to provide and submitted according
> to what our API allows us to do.
>
> Do you see it differently ?
If having the TS generate the forms is not optimal then I'm fine with
that. Are we able to utilize the API schema on the client-side so that
the TS can communicate its data requirements?
Celso Providelo (cprov) wrote : | # |
Joe,
Tastypie allows shallow schema introspection via <API>/schema (e.g /api/v1/
I can try to investigate some good way for using it, but the benefits get quickly consumed when we have to compose forms for multiple models.
Joe Talbott (joetalbott) wrote : | # |
On Tue, Sep 23, 2014 at 06:38:08PM -0000, Celso Providelo wrote:
> Joe,
>
> Tastypie allows shallow schema introspection via <API>/schema (e.g /api/v1/
>
> I can try to investigate some good way for using it, but the benefits get quickly consumed when we have to compose forms for multiple models.
No worries. We can sort it out later on. I'm okay with your approach
here.
Ubuntu CI Bot (uci-bot) wrote : | # |
Attempt to merge into lp:uci-engine failed due to conflicts:
text conflict in webui/common/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:797
http://
Executed test runs:
Click here to trigger a rebuild:
http://
- 801. By Celso Providelo
-
[r=PS Jenkins bot, Evan Dandrea] Implements a ticket creation form in the webui.
Preview Diff
1 | === modified file 'webui/common/static/common/webui.css' |
2 | --- webui/common/static/common/webui.css 2014-09-22 17:32:23 +0000 |
3 | +++ webui/common/static/common/webui.css 2014-09-24 20:14:57 +0000 |
4 | @@ -209,3 +209,39 @@ |
5 | height: 1em; |
6 | vertical-align: middle; |
7 | } |
8 | + |
9 | +div.form-error { |
10 | + display: block; |
11 | + -moz-border-radius: 4px; |
12 | + -webkit-border-radius: 4px; |
13 | + border-radius: 4px; |
14 | + -webkit-box-shadow: 0 2px 2px 0 #C2C2C2; |
15 | + box-shadow: 0 2px 2px 0 #C2C2C2; |
16 | + padding: 10px 0px 10px 0px; |
17 | + margin: 10px; |
18 | + background-color: #DD4040; |
19 | + color: white; |
20 | + text-align: left; |
21 | + text-indent: 10px; |
22 | + font-weight: bold; |
23 | +} |
24 | + |
25 | +form .error { |
26 | + color: #FF0000; |
27 | + font-weight: bold; |
28 | + float: right; |
29 | +} |
30 | + |
31 | +.yui3-form { |
32 | + width: 60%; |
33 | + padding-left: 10px; |
34 | +} |
35 | + |
36 | +.field { |
37 | + width: 100%; |
38 | +} |
39 | + |
40 | +input[type="submit"] { |
41 | + margin-top: 1em !important; |
42 | + width: auto; |
43 | +} |
44 | |
45 | === modified file 'webui/tickets/static/tickets/webui.js' |
46 | --- webui/tickets/static/tickets/webui.js 2014-09-22 17:32:23 +0000 |
47 | +++ webui/tickets/static/tickets/webui.js 2014-09-24 20:14:57 +0000 |
48 | @@ -748,7 +748,7 @@ |
49 | * 'type' can be one of 'open', 'complete', 'failed', otherwise |
50 | * all tickets will be listed. |
51 | * |
52 | - * @method update_ticket |
53 | + * @method setup_ticket_datatable |
54 | */ |
55 | setup_ticket_datatable: function (container, type) { |
56 | var itemsPerPage = 10; |
57 | |
58 | === added file 'webui/tickets/static/tickets/webui_create_ticket.js' |
59 | --- webui/tickets/static/tickets/webui_create_ticket.js 1970-01-01 00:00:00 +0000 |
60 | +++ webui/tickets/static/tickets/webui_create_ticket.js 2014-09-24 20:14:57 +0000 |
61 | @@ -0,0 +1,5 @@ |
62 | +YUI().use('webuiforms', function(Y) { |
63 | + |
64 | + Y.webuiforms.setupCreateForm('#form-content'); |
65 | + |
66 | +}); |
67 | |
68 | === added file 'webui/tickets/static/tickets/webuiforms.js' |
69 | --- webui/tickets/static/tickets/webuiforms.js 1970-01-01 00:00:00 +0000 |
70 | +++ webui/tickets/static/tickets/webuiforms.js 2014-09-24 20:14:57 +0000 |
71 | @@ -0,0 +1,105 @@ |
72 | +"use strict"; |
73 | + |
74 | +// Make jslint happy |
75 | +var YUI; |
76 | + |
77 | +YUI.add('webuiforms', function (Y) { |
78 | + |
79 | + /** |
80 | + * Overriding Y.SelectField to properly rendering '<label>'s. |
81 | + */ |
82 | + Y.WebUISelectField = Y.Base.create( |
83 | + 'select-field', Y.SelectField, [Y.WidgetParent, Y.WidgetChild], { |
84 | + |
85 | + _renderLabelNode : function () { |
86 | + var contentBox = this.get('contentBox'), |
87 | + titleNode = Y.Node.create('<label></label>'); |
88 | + titleNode.set('innerHTML', this.get('label')); |
89 | + contentBox.appendChild(titleNode); |
90 | + this._labelNode = titleNode; |
91 | + } |
92 | + }); |
93 | + |
94 | + Y.webuiforms = { |
95 | + |
96 | + /** |
97 | + * Hardcoded array of series choices, must be kept in sync with |
98 | + * the supported options in Ticket-System. |
99 | + */ |
100 | + seriesChoices: [ |
101 | + {label : 'Utopic - 14.10', value : 'utopic'}, |
102 | + {label : 'Trusty - 14.04', value : 'trusty'}, |
103 | + {label : 'Precise - 12.04', value : 'precise'} |
104 | + ], |
105 | + |
106 | + /** |
107 | + * Setup a form for creating a new ticket. |
108 | + * |
109 | + * Uses Y.Form() to build and render the form dynamically and |
110 | + * re-implements its submission to POST JSON data (instead of |
111 | + * 'urlencoded'). Opens the just-created ticket on success. |
112 | + * |
113 | + * @method setupCreateForm |
114 | + */ |
115 | + setupCreateForm: function (container) { |
116 | + var form_message = Y.Node.create('<div>'); |
117 | + Y.one(container).appendChild(form_message); |
118 | + |
119 | + // Build and render a form for creating a new Ticket. |
120 | + var f = new Y.Form({ |
121 | + boundingBox: container, |
122 | + action : '/api/v1/ticket/', |
123 | + method : 'post', |
124 | + children : [ |
125 | + {name: 'title', required: true, label: 'Title:'}, |
126 | + {name: 'description', label: 'Description:', |
127 | + type: 'TextareaField'}, |
128 | + {name: 'owner', required: true, label: 'Owner:', |
129 | + validator: Y.FormField.VALIDATE_EMAIL_ADDRESS}, |
130 | + {name: 'series', required: true, label: 'Series:', |
131 | + type: 'WebUISelectField', useDefaultOption: false, |
132 | + choices: this.seriesChoices}, |
133 | + {name: 'create-button', type: 'SubmitButton', |
134 | + value: 'Create!'} |
135 | + ] |
136 | + }); |
137 | + f.render(); |
138 | + |
139 | + // Hijack the default (www-urlencoded) form submission and |
140 | + // submit its content as JSON. |
141 | + f.getField('create-button').on('click', function(e) { |
142 | + e.halt(); |
143 | + if (!f._runValidation()) { |
144 | + return 1; |
145 | + } |
146 | + |
147 | + // XXX cprov 20140922: extend the form data with appropriate |
148 | + // 'status' and 'current_workflow_step'. |
149 | + var form_data = f.toJSON(); |
150 | + |
151 | + Y.io(f.get('action'), { |
152 | + method: f.get('method'), |
153 | + sync: true, |
154 | + data: Y.JSON.stringify(form_data), |
155 | + headers: { |
156 | + 'Content-Type': 'application/json;', |
157 | + }, |
158 | + on: { |
159 | + success: function(tx, r) { |
160 | + var location = r.getResponseHeader('Location'); |
161 | + Y.config.win.location.href = location.replace( |
162 | + '/api/v1', ''); |
163 | + }, |
164 | + failure: function (tx, r) { |
165 | + Y.log('FAILURE: ' + r.responseText); |
166 | + form_message.addClass('form-error') |
167 | + form_message.set( |
168 | + 'text', 'Ticket creation failed!') |
169 | + } |
170 | + } |
171 | + }); |
172 | + }); |
173 | + } |
174 | + }; |
175 | +}, '0.0.1', {requires: ['io', 'node', 'json-parse', 'json-stringify', |
176 | + 'gallery-form']}); |
177 | |
178 | === added file 'webui/tickets/templates/tickets/create.html' |
179 | --- webui/tickets/templates/tickets/create.html 1970-01-01 00:00:00 +0000 |
180 | +++ webui/tickets/templates/tickets/create.html 2014-09-24 20:14:57 +0000 |
181 | @@ -0,0 +1,23 @@ |
182 | +{% extends "common/base.html" %} |
183 | +{% load staticfiles %} |
184 | + |
185 | +{% block extra_headers %} |
186 | + <script type="text/javascript" src="{% static 'tickets/webuiforms.js' %}"></script> |
187 | + <script type="text/javascript" src="{% static 'tickets/webui_create_ticket.js' %}"></script> |
188 | +{% endblock extra_headers %} |
189 | + |
190 | +{% block second_nav %} |
191 | +<nav role="navigation" class="nav-secondary clearfix"> |
192 | + <ul class="breadcrumb"> |
193 | + <li><a href="/">Open tickets</a></li> |
194 | + <li><a href="/complete/">Completed tickets</a></li> |
195 | + <li><a href="/failed/">Failed tickets</a></li> |
196 | + </ul> |
197 | +</nav> |
198 | +{% endblock second_nav %} |
199 | + |
200 | +{% block content %} |
201 | + |
202 | + <div id="form-content" class="yui3-skin-sam"></div> |
203 | + |
204 | +{% endblock content %} |
205 | |
206 | === modified file 'webui/tickets/urls.py' |
207 | --- webui/tickets/urls.py 2014-08-27 21:04:07 +0000 |
208 | +++ webui/tickets/urls.py 2014-09-24 20:14:57 +0000 |
209 | @@ -14,4 +14,5 @@ |
210 | 'tickets.views.review', name='ticket_review'), |
211 | url(r'^complete/$', 'tickets.views.complete', name='ticket_complete'), |
212 | url(r'^failed/$', 'tickets.views.failed', name='ticket_failed'), |
213 | + url(r'^create$', 'tickets.views.create', name='create'), |
214 | ) |
215 | |
216 | === modified file 'webui/tickets/views.py' |
217 | --- webui/tickets/views.py 2014-06-30 12:07:54 +0000 |
218 | +++ webui/tickets/views.py 2014-09-24 20:14:57 +0000 |
219 | @@ -34,3 +34,7 @@ |
220 | |
221 | def status(request): |
222 | return render_to_response('tickets/status.html', base_data) |
223 | + |
224 | + |
225 | +def create(request): |
226 | + return render_to_response('tickets/create.html', base_data) |
PASSED: Continuous integration, rev:794 s-jenkins. ubuntu- ci:8080/ job/uci- engine- ci/1433/
http://
Executed test runs:
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/uci- engine- ci/1433/ rebuild
http://