Merge lp:~cprov/uci-engine/webui-create-ticket into lp:uci-engine

Proposed by Celso Providelo
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
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).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:794
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1433/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1433/rebuild

review: Approve (continuous-integration)
Revision history for this message
Evan (ev) wrote :

Comments inline. Are we going to handle form validation in a follow up MP?

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:795
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1441/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1441/rebuild

review: Approve (continuous-integration)
Revision history for this message
Celso Providelo (cprov) wrote :
Download full text (3.7 KiB)

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('create-button').on('click', function(e) {
>> + e.halt();
>> + if (!f._runValidation()) {
>> + return 1;
>> + }
>> +
>> + // XXX cprov 20140922: extend the form data with appropriate
>> + // 'status' and 'current_workflow_step'.
>> + var form_data = f.toJSON();
>> +
>> + Y.io(f.get('action'), {
>> + method: f.get('method'),
>> + sync: true,
>> + data: Y.JSON.stringify(form_data),
>> + headers: {
>> + 'Content-Type': 'application/json;',
>> + },
>> + on: {
>> + success: function(tx, r) {
>> + var location = r.getResponseHeader('Location');
>> + Y.log('SUCCESS: ' + location);
>
> Leftover from debugging?

Yes, removed.

>> + Y.config.win.location.href = location.replace(
>> + '/api/v1', '');
>> + },
>> + failure: function (tx, r) {
>> + Y.log('FA...

Read more...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:796
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1442/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1442/rebuild

review: Approve (continuous-integration)
Revision history for this message
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-ci-engineering)
>
> For more details, see:
> https://code.launchpad.net/~cprov/uci-engine/webui-create-ticket/+merge/235554
>
> 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?

Revision history for this message
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-ci-engineering)
>>
>> For more details, see:
>> https://code.launchpad.net/~cprov/uci-engine/webui-create-ticket/+merge/235554
>>
>> 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://code.launchpad.net/~cprov/uci-engine/webui-create-ticket/+merge/235554
> You are the owner of lp:~cprov/uci-engine/webui-create-ticket.

--
Celso Providelo
<email address hidden>

Revision history for this message
Evan (ev) wrote :

Looks good. Thanks for the updates.

review: Approve
Revision history for this message
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?

Revision history for this message
Celso Providelo (cprov) wrote :

Joe,

Tastypie allows shallow schema introspection via <API>/schema (e.g /api/v1/ticket/schema/) but it doesn't look very appealing atm (lack of documentation on the model/field level and not precise information for validation since we have many CharFields).

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.

Revision history for this message
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/ticket/schema/) but it doesn't look very appealing atm (lack of documentation on the model/field level and not precise information for validation since we have many CharFields).
>
> 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.

Revision history for this message
Ubuntu CI Bot (uci-bot) wrote :

Attempt to merge into lp:uci-engine failed due to conflicts:

text conflict in webui/common/static/common/webui.css

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:797
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1460/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1460/rebuild

review: Approve (continuous-integration)
801. By Celso Providelo

[r=PS Jenkins bot, Evan Dandrea] Implements a ticket creation form in the webui.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'webui/common/static/common/webui.css'
--- webui/common/static/common/webui.css 2014-09-22 17:32:23 +0000
+++ webui/common/static/common/webui.css 2014-09-24 20:14:57 +0000
@@ -209,3 +209,39 @@
209 height: 1em;209 height: 1em;
210 vertical-align: middle;210 vertical-align: middle;
211}211}
212
213div.form-error {
214 display: block;
215 -moz-border-radius: 4px;
216 -webkit-border-radius: 4px;
217 border-radius: 4px;
218 -webkit-box-shadow: 0 2px 2px 0 #C2C2C2;
219 box-shadow: 0 2px 2px 0 #C2C2C2;
220 padding: 10px 0px 10px 0px;
221 margin: 10px;
222 background-color: #DD4040;
223 color: white;
224 text-align: left;
225 text-indent: 10px;
226 font-weight: bold;
227}
228
229form .error {
230 color: #FF0000;
231 font-weight: bold;
232 float: right;
233}
234
235.yui3-form {
236 width: 60%;
237 padding-left: 10px;
238}
239
240.field {
241 width: 100%;
242}
243
244input[type="submit"] {
245 margin-top: 1em !important;
246 width: auto;
247}
212248
=== modified file 'webui/tickets/static/tickets/webui.js'
--- webui/tickets/static/tickets/webui.js 2014-09-22 17:32:23 +0000
+++ webui/tickets/static/tickets/webui.js 2014-09-24 20:14:57 +0000
@@ -748,7 +748,7 @@
748 * 'type' can be one of 'open', 'complete', 'failed', otherwise748 * 'type' can be one of 'open', 'complete', 'failed', otherwise
749 * all tickets will be listed.749 * all tickets will be listed.
750 *750 *
751 * @method update_ticket751 * @method setup_ticket_datatable
752 */752 */
753 setup_ticket_datatable: function (container, type) {753 setup_ticket_datatable: function (container, type) {
754 var itemsPerPage = 10;754 var itemsPerPage = 10;
755755
=== added file 'webui/tickets/static/tickets/webui_create_ticket.js'
--- webui/tickets/static/tickets/webui_create_ticket.js 1970-01-01 00:00:00 +0000
+++ webui/tickets/static/tickets/webui_create_ticket.js 2014-09-24 20:14:57 +0000
@@ -0,0 +1,5 @@
1YUI().use('webuiforms', function(Y) {
2
3 Y.webuiforms.setupCreateForm('#form-content');
4
5});
06
=== added file 'webui/tickets/static/tickets/webuiforms.js'
--- webui/tickets/static/tickets/webuiforms.js 1970-01-01 00:00:00 +0000
+++ webui/tickets/static/tickets/webuiforms.js 2014-09-24 20:14:57 +0000
@@ -0,0 +1,105 @@
1"use strict";
2
3// Make jslint happy
4var YUI;
5
6YUI.add('webuiforms', function (Y) {
7
8 /**
9 * Overriding Y.SelectField to properly rendering '<label>'s.
10 */
11 Y.WebUISelectField = Y.Base.create(
12 'select-field', Y.SelectField, [Y.WidgetParent, Y.WidgetChild], {
13
14 _renderLabelNode : function () {
15 var contentBox = this.get('contentBox'),
16 titleNode = Y.Node.create('<label></label>');
17 titleNode.set('innerHTML', this.get('label'));
18 contentBox.appendChild(titleNode);
19 this._labelNode = titleNode;
20 }
21 });
22
23 Y.webuiforms = {
24
25 /**
26 * Hardcoded array of series choices, must be kept in sync with
27 * the supported options in Ticket-System.
28 */
29 seriesChoices: [
30 {label : 'Utopic - 14.10', value : 'utopic'},
31 {label : 'Trusty - 14.04', value : 'trusty'},
32 {label : 'Precise - 12.04', value : 'precise'}
33 ],
34
35 /**
36 * Setup a form for creating a new ticket.
37 *
38 * Uses Y.Form() to build and render the form dynamically and
39 * re-implements its submission to POST JSON data (instead of
40 * 'urlencoded'). Opens the just-created ticket on success.
41 *
42 * @method setupCreateForm
43 */
44 setupCreateForm: function (container) {
45 var form_message = Y.Node.create('<div>');
46 Y.one(container).appendChild(form_message);
47
48 // Build and render a form for creating a new Ticket.
49 var f = new Y.Form({
50 boundingBox: container,
51 action : '/api/v1/ticket/',
52 method : 'post',
53 children : [
54 {name: 'title', required: true, label: 'Title:'},
55 {name: 'description', label: 'Description:',
56 type: 'TextareaField'},
57 {name: 'owner', required: true, label: 'Owner:',
58 validator: Y.FormField.VALIDATE_EMAIL_ADDRESS},
59 {name: 'series', required: true, label: 'Series:',
60 type: 'WebUISelectField', useDefaultOption: false,
61 choices: this.seriesChoices},
62 {name: 'create-button', type: 'SubmitButton',
63 value: 'Create!'}
64 ]
65 });
66 f.render();
67
68 // Hijack the default (www-urlencoded) form submission and
69 // submit its content as JSON.
70 f.getField('create-button').on('click', function(e) {
71 e.halt();
72 if (!f._runValidation()) {
73 return 1;
74 }
75
76 // XXX cprov 20140922: extend the form data with appropriate
77 // 'status' and 'current_workflow_step'.
78 var form_data = f.toJSON();
79
80 Y.io(f.get('action'), {
81 method: f.get('method'),
82 sync: true,
83 data: Y.JSON.stringify(form_data),
84 headers: {
85 'Content-Type': 'application/json;',
86 },
87 on: {
88 success: function(tx, r) {
89 var location = r.getResponseHeader('Location');
90 Y.config.win.location.href = location.replace(
91 '/api/v1', '');
92 },
93 failure: function (tx, r) {
94 Y.log('FAILURE: ' + r.responseText);
95 form_message.addClass('form-error')
96 form_message.set(
97 'text', 'Ticket creation failed!')
98 }
99 }
100 });
101 });
102 }
103 };
104}, '0.0.1', {requires: ['io', 'node', 'json-parse', 'json-stringify',
105 'gallery-form']});
0106
=== added file 'webui/tickets/templates/tickets/create.html'
--- webui/tickets/templates/tickets/create.html 1970-01-01 00:00:00 +0000
+++ webui/tickets/templates/tickets/create.html 2014-09-24 20:14:57 +0000
@@ -0,0 +1,23 @@
1{% extends "common/base.html" %}
2{% load staticfiles %}
3
4{% block extra_headers %}
5 <script type="text/javascript" src="{% static 'tickets/webuiforms.js' %}"></script>
6 <script type="text/javascript" src="{% static 'tickets/webui_create_ticket.js' %}"></script>
7{% endblock extra_headers %}
8
9{% block second_nav %}
10<nav role="navigation" class="nav-secondary clearfix">
11 <ul class="breadcrumb">
12 <li><a href="/">Open tickets</a></li>
13 <li><a href="/complete/">Completed tickets</a></li>
14 <li><a href="/failed/">Failed tickets</a></li>
15 </ul>
16</nav>
17{% endblock second_nav %}
18
19{% block content %}
20
21 <div id="form-content" class="yui3-skin-sam"></div>
22
23{% endblock content %}
024
=== modified file 'webui/tickets/urls.py'
--- webui/tickets/urls.py 2014-08-27 21:04:07 +0000
+++ webui/tickets/urls.py 2014-09-24 20:14:57 +0000
@@ -14,4 +14,5 @@
14 'tickets.views.review', name='ticket_review'),14 'tickets.views.review', name='ticket_review'),
15 url(r'^complete/$', 'tickets.views.complete', name='ticket_complete'),15 url(r'^complete/$', 'tickets.views.complete', name='ticket_complete'),
16 url(r'^failed/$', 'tickets.views.failed', name='ticket_failed'),16 url(r'^failed/$', 'tickets.views.failed', name='ticket_failed'),
17 url(r'^create$', 'tickets.views.create', name='create'),
17)18)
1819
=== modified file 'webui/tickets/views.py'
--- webui/tickets/views.py 2014-06-30 12:07:54 +0000
+++ webui/tickets/views.py 2014-09-24 20:14:57 +0000
@@ -34,3 +34,7 @@
3434
35def status(request):35def status(request):
36 return render_to_response('tickets/status.html', base_data)36 return render_to_response('tickets/status.html', base_data)
37
38
39def create(request):
40 return render_to_response('tickets/create.html', base_data)

Subscribers

People subscribed via source and target branches