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
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)

Subscribers

People subscribed via source and target branches