Merge lp:~cprov/uci-engine/webui-auto-refresh into lp:uci-engine

Proposed by Celso Providelo
Status: Merged
Approved by: Ursula Junque
Approved revision: 626
Merged at revision: 626
Proposed branch: lp:~cprov/uci-engine/webui-auto-refresh
Merge into: lp:uci-engine
Diff against target: 300 lines (+69/-116)
7 files modified
gatekeeper/gatekeeper/resources/tests/test_api.py (+4/-1)
gatekeeper/gatekeeper/resources/v1.py (+5/-1)
webui/tickets/static/tickets/webui.js (+52/-99)
webui/tickets/static/tickets/webui_complete.js (+2/-2)
webui/tickets/static/tickets/webui_failed.js (+2/-2)
webui/tickets/static/tickets/webui_ticket_detail.js (+2/-9)
webui/tickets/static/tickets/webui_ticket_list.js (+2/-2)
To merge this branch: bzr merge lp:~cprov/uci-engine/webui-auto-refresh
Reviewer Review Type Date Requested Status
Ursula Junque (community) Approve
Evan (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+224728@code.launchpad.net

Commit message

Fixing the WebUI auto-refresh feature and preventing tempurls from GK to get cached.

Description of the change

Fixing the WebUI auto-refresh feature and preventing tempurls from GK to get cached.

This branch adds the 'Cache-Control: max-age=0, no-cache' header to the GK response container fresh tempurls for all ticket artifacts. This way it won't be cached in clients browsers and every time the webui refreshes they have access to valid tempurls.

I've completely refactored the the auto-refresh feature in webui.js, so it uses a much simpler and reliable mechanism for periodic tasks (Y.later instead of SetTimeout) which helped to simplify the related code a lot.

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

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

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

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

This looks good, but I'm confused as to why you kept the UI for configuring auto-refresh. I can't imagine a case where we'd want to disable that or tweak the interval. It was good for when the feature first landed, but we've been running with it for a while now and it's just cluttering up the interface.

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

"auto-refresh" section completely removed from the UI now.

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

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

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

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

Looks good.

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

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Revision history for this message
Ursula Junque (ursinha) wrote :

Looks good to me. Thanks for fixing this!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'gatekeeper/gatekeeper/resources/tests/test_api.py'
2--- gatekeeper/gatekeeper/resources/tests/test_api.py 2014-06-16 13:18:53 +0000
3+++ gatekeeper/gatekeeper/resources/tests/test_api.py 2014-06-27 13:46:23 +0000
4@@ -148,9 +148,12 @@
5
6 def test_get_returns_the_list_of_artifacts(self):
7 # GET on a ticket URL returns a list to tempurls for its
8- # artifacts as a dictionary (JSON object).
9+ # artifacts as a dictionary (JSON object). Since tempurls
10+ # expires, this page should not be cached in browsers.
11 resp = self.app.get('/api/v1/ticket/1')
12 self.assertEqual(200, resp.status_code)
13+ self.assertEqual(
14+ 'max-age=0, no-cache', str(resp.cache_control))
15 self.assertEqual('application/json', resp.content_type)
16 self.assertEqual(
17 {'A_ARTIFACT': 'http://ARTIFACT_TEMPURL'},
18
19=== modified file 'gatekeeper/gatekeeper/resources/v1.py'
20--- gatekeeper/gatekeeper/resources/v1.py 2014-06-12 13:26:06 +0000
21+++ gatekeeper/gatekeeper/resources/v1.py 2014-06-27 13:46:23 +0000
22@@ -143,7 +143,11 @@
23 payload = b'{}({})\n'.format(callback, payload)
24 else:
25 payload = b'{}\n'.format(payload)
26- return http.ok([(b'Content-Type', b'application/json')], payload)
27+ headers = [
28+ (b'Cache-Control', 'max-age=0, no-cache'),
29+ (b'Content-Type', b'application/json')
30+ ]
31+ return http.ok(headers, payload)
32
33 @resource.child('sandbox/{sandbox_identifier}')
34 def sandbox_wrapper(self, request, segments, sandbox_identifier):
35
36=== modified file 'webui/tickets/static/tickets/webui.js'
37--- webui/tickets/static/tickets/webui.js 2014-06-26 15:08:17 +0000
38+++ webui/tickets/static/tickets/webui.js 2014-06-27 13:46:23 +0000
39@@ -1,20 +1,24 @@
40 "use strict";
41
42 // Make jslint happy
43-var window;
44 var YUI;
45
46 YUI.add('webui', function (Y) {
47- var json_error_msg = "The ticket system returned data that could not be understood. " +
48- "Please try refreshing, or contact support if this problem persists.",
49- refresh_msg = "Refreshing data...";
50- var default_refresh = 15;
51- var static_prefix = "/static/common/";
52+ var json_error_msg = (
53+ "The ticket system returned data that could not be understood. " +
54+ "Please try refreshing, or contact support if this problem " +
55+ "persists."),
56+ refresh_msg = "Refreshing data...",
57+ default_refresh = 60,
58+ static_prefix = "/static/common/";
59 Y.webui = {
60 url_prefix: "/api/v1/",
61- refresh_interval: (parseInt(Y.one('#refresh_rate'), 10) || default_refresh) * 1000,
62+ refresh_interval: default_refresh * 1000,
63+ refresh_timer: null,
64 done_loading: false,
65- log_prefixes: Y.Array(['package_build', 'image_build', 'image_test', 'package_publish']),
66+ log_prefixes: Y.Array(
67+ ['package_build', 'image_build', 'image_test',
68+ 'package_publish']),
69 log_step_map: {
70 "Image building": "image_build",
71 "Image testing": "image_test",
72@@ -45,54 +49,22 @@
73
74 Y.webui.logs[key].push(log_data);
75 },
76- add_refresh_div: function (callback) {
77- var refresh,
78- refresh_rate,
79- refresh_enabled,
80- onChange;
81-
82- refresh = Y.Node.create('<div id="refresh"></div>');
83-
84- refresh.setHTML('<small>Automatically refresh <input type="checkbox" checked="true"' +
85- 'id="refresh_enabled"></input> every <input type="text"' +
86- 'id="refresh_rate" value="' + default_refresh + '" maxlength="3" size="2"/> seconds.</small>'
87- );
88-
89- Y.one('div#main-content').append(refresh);
90-
91- Y.webui.refresh_timeout = null;
92- refresh_rate = Y.one("#refresh_rate");
93- refresh_enabled = Y.one("#refresh_enabled");
94- Y.webui.refresh_enabled = refresh_enabled.get('checked');
95-
96- onChange = function () {
97- var value = refresh_rate.get('value'),
98- val;
99-
100- val = parseInt(value, 10);
101-
102- if (Y.webui.refresh_timeout) {
103- clearTimeout(Y.webui.refresh_timeout);
104- }
105- if (val !== 0) {
106- Y.webui.refresh_interval = val * 1000;
107- callback();
108- }
109- };
110- refresh_rate.on('change', onChange);
111- refresh_enabled.on('change', function () {
112- if (Y.webui.refresh_timeout) {
113- clearTimeout(Y.webui.refresh_timeout);
114- }
115-
116- Y.webui.refresh_enabled = refresh_enabled.get('checked');
117-
118- if (Y.webui.refresh_enabled) {
119- callback();
120- }
121- });
122- onChange();
123+
124+ /**
125+ * Setup page auto-refresh.
126+ *
127+ * Immediately runs the callback when auto-refresh is set up
128+ * (page is loaded) then use Y.later() for periodically calling
129+ * the 'callback' at the `Y.webui.refresh_interval` rate.
130+ *
131+ * @method setup_auto_refresh
132+ */
133+ setup_auto_refresh: function (callback) {
134+ callback();
135+ Y.webui.refresh_timer = Y.later(
136+ Y.webui.refresh_interval, Y, callback, '', true);
137 },
138+
139 get_workflow_data: function (api_url) {
140 var wf_data = {},
141 wf_str = {},
142@@ -349,7 +321,7 @@
143 },
144 artifact_link: function (data, new_name) {
145 var name = Y.webui.basename(data.name),
146- link = Y.Node.create("<a/>");
147+ link = Y.Node.create('<a/>');
148
149 // Lookup a corresponding tempurl.
150 var tempurl = Y.webui.tempurls[name];
151@@ -671,34 +643,37 @@
152 }
153 }
154 },
155+
156+ /**
157+ * Returns the ticket ID based on the window URL.
158+ *
159+ * Checks the known ticket page path (/ticket/<id>), then match
160+ * a valid integer ID.
161+ *
162+ * @method get_ticket_id
163+ */
164 get_ticket_id: function () {
165- var query = window.location.search.split('?')[1],
166- ticket_id = null,
167- ob;
168-
169- if (query) {
170- ob = Y.QueryString.parse(query);
171- ticket_id = ob.ticket_id;
172- }
173-
174- return ticket_id;
175+ var path = Y.config.win.location.pathname;
176+ if (!path.match(/\/ticket\/\d+\//g)) {
177+ return null;
178+ }
179+ var id_match = path.match(/\d+/g);
180+ if (!id_match) {
181+ return null;
182+ }
183+ return id_match[0];
184 },
185+
186+ /**
187+ * Updates ticket information.
188+ *
189+ * @method update_ticket
190+ */
191 update_ticket: function () {
192 var ticket_id = Y.webui.get_ticket_id();
193-
194 if (ticket_id) {
195 Y.webui.get_ticket(ticket_id, Y.one('#container'));
196 }
197-
198- // we're done so allow more refreshes if needed.
199- if (Y.webui.refresh_timeout) {
200- clearTimeout(Y.webui.refresh_timeout);
201- Y.webui.refresh_timeout = null;
202- }
203-
204- if (Y.webui.refresh_enabled && !Y.webui.refresh_timeout && Y.webui.refresh_interval > 0) {
205- Y.webui.refresh_timeout = setTimeout(Y.webui.update_ticket, Y.webui.refresh_interval);
206- }
207 },
208 has_ticket: function (ticket_ids, id) {
209 return ticket_ids[id] === true;
210@@ -812,31 +787,9 @@
211
212 Y.webui.main_table.set('data', recordset);
213 Y.webui.main_table.render();
214-
215- // we're done so allow more refreshes if needed.
216- if (Y.webui.refresh_timeout) {
217- clearTimeout(Y.webui.refresh_timeout);
218- Y.webui.refresh_timeout = null;
219- }
220- if (Y.webui.refresh_enabled && !Y.webui.refresh_timeout && Y.webui.refresh_interval > 0) {
221- Y.webui.refresh_timeout = setTimeout(status_callback, Y.webui.refresh_interval);
222- }
223 },
224- complete: function () {
225- if (Y.webui.refresh_enabled && !Y.webui.refresh_timeout && Y.webui.refresh_interval > 0) {
226- Y.webui.refresh_timeout = setTimeout(status_callback, Y.webui.refresh_interval);
227- }
228- }
229 }
230 });
231- } else {
232- if (Y.webui.refresh_timeout) {
233- clearTimeout(Y.webui.refresh_timeout);
234- Y.webui.refresh_timeout = null;
235- }
236- if (Y.webui.refresh_enabled && !Y.webui.refresh_timeout && Y.webui.refresh_interval > 0) {
237- Y.webui.refresh_timeout = setTimeout(status_callback, Y.webui.refresh_interval);
238- }
239 }
240 },
241 add_item: function (item) {
242
243=== modified file 'webui/tickets/static/tickets/webui_complete.js'
244--- webui/tickets/static/tickets/webui_complete.js 2014-05-20 14:47:23 +0000
245+++ webui/tickets/static/tickets/webui_complete.js 2014-06-27 13:46:23 +0000
246@@ -1,7 +1,7 @@
247-YUI().use('io', 'jsonp', 'webui', 'datatable-mutable', function(Y) {
248+YUI().use( 'datatable-mutable', 'io', 'jsonp', 'webui', function(Y) {
249
250 Y.webui.make_main_table('#table');
251
252 Y.webui.get_tickets("complete");
253- Y.webui.add_refresh_div(Y.webui.check_complete_statuses);
254+ Y.webui.setup_auto_refresh(Y.webui.check_complete_statuses);
255 });
256
257=== modified file 'webui/tickets/static/tickets/webui_failed.js'
258--- webui/tickets/static/tickets/webui_failed.js 2014-05-20 14:47:23 +0000
259+++ webui/tickets/static/tickets/webui_failed.js 2014-06-27 13:46:23 +0000
260@@ -1,7 +1,7 @@
261-YUI().use('io', 'jsonp', 'webui', 'datatable-mutable', function(Y) {
262+YUI().use('datatable-mutable', 'io', 'jsonp', 'webui', function(Y) {
263
264 Y.webui.make_main_table('#table');
265
266 Y.webui.get_tickets("failed");
267- Y.webui.add_refresh_div(Y.webui.check_failed_statuses);
268+ Y.webui.setup_auto_refresh(Y.webui.check_failed_statuses);
269 });
270
271=== modified file 'webui/tickets/static/tickets/webui_ticket_detail.js'
272--- webui/tickets/static/tickets/webui_ticket_detail.js 2014-05-19 12:40:40 +0000
273+++ webui/tickets/static/tickets/webui_ticket_detail.js 2014-06-27 13:46:23 +0000
274@@ -1,10 +1,3 @@
275-YUI().use('io', 'json-parse', 'querystring', 'node', 'webui', function(Y) {
276-
277- var ticket_id = parseInt(Y.one('#ticket_id').getHTML(), 10);
278-
279- if (ticket_id) {
280- var ticket = Y.webui.get_ticket(ticket_id, Y.one('#container'));
281- }
282-
283- Y.webui.add_refresh_div(Y.webui.update_ticket);
284+YUI().use('io', 'json-parse', 'node', 'webui', function(Y) {
285+ Y.webui.setup_auto_refresh(Y.webui.update_ticket);
286 });
287
288=== modified file 'webui/tickets/static/tickets/webui_ticket_list.js'
289--- webui/tickets/static/tickets/webui_ticket_list.js 2014-05-20 14:47:23 +0000
290+++ webui/tickets/static/tickets/webui_ticket_list.js 2014-06-27 13:46:23 +0000
291@@ -1,7 +1,7 @@
292-YUI().use('event', 'node', 'datatable-mutable', 'webui', function(Y) {
293+YUI().use('datatable-mutable', 'event', 'node', 'webui', function(Y) {
294
295 Y.webui.make_main_table('#table');
296
297 Y.webui.get_tickets("open");
298- Y.webui.add_refresh_div(Y.webui.check_open_statuses);
299+ Y.webui.setup_auto_refresh(Y.webui.check_open_statuses);
300 });

Subscribers

People subscribed via source and target branches