diff options
-rw-r--r-- | extensions/MyDashboard/lib/WebService.pm | 87 | ||||
-rw-r--r-- | extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl | 5 | ||||
-rw-r--r-- | extensions/MyDashboard/web/js/query.js | 180 |
3 files changed, 171 insertions, 101 deletions
diff --git a/extensions/MyDashboard/lib/WebService.pm b/extensions/MyDashboard/lib/WebService.pm index c98525429..87061eabe 100644 --- a/extensions/MyDashboard/lib/WebService.pm +++ b/extensions/MyDashboard/lib/WebService.pm @@ -23,6 +23,55 @@ use constant READ_ONLY => qw( run_flag_query ); +sub run_last_changes { + my ($self, $params) = @_; + + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->login(LOGIN_REQUIRED); + + trick_taint($params->{changeddate_api}); + trick_taint($params->{bug_id}); + + my $last_comment_sql = " + SELECT comment_id + FROM longdescs + WHERE bug_id = ? AND bug_when > ?"; + if (!$user->is_insider) { + $last_comment_sql .= " AND isprivate = 0"; + } + $last_comment_sql .= " LIMIT 1"; + my $last_comment_sth = $dbh->prepare($last_comment_sql); + + my $last_changes = {}; + my $activity = $self->history({ ids => [ $params->{bug_id} ], + new_since => $params->{changeddate_api} }); + if (@{$activity->{bugs}[0]{history}}) { + my $change_set = $activity->{bugs}[0]{history}[0]; + $last_changes->{activity} = $change_set->{changes}; + foreach my $change (@{ $last_changes->{activity} }) { + $change->{field_desc} + = template_var('field_descs')->{$change->{field_name}} || $change->{field_name}; + } + $last_changes->{email} = $change_set->{who}; + my $datetime = datetime_from($change_set->{when}); + $datetime->set_time_zone($user->timezone); + $last_changes->{when} = $datetime->strftime('%Y-%m-%d %T %Z'); + } + my $last_comment_id = $dbh->selectrow_array( + $last_comment_sth, undef, $params->{bug_id}, $params->{changeddate_api}); + if ($last_comment_id) { + my $comments = $self->comments({ comment_ids => [ $last_comment_id ] }); + my $comment = $comments->{comments}{$last_comment_id}; + $last_changes->{comment} = $comment->{text}; + $last_changes->{email} = $comment->{creator} if !$last_changes->{email}; + my $datetime = datetime_from($comment->{creation_time}); + $datetime->set_time_zone($user->timezone); + $last_changes->{when} = $datetime->strftime('%Y-%m-%d %T %Z'); + } + + return { results => [ {last_changes => $last_changes } ] }; +} + sub run_bug_query { my($self, $params) = @_; my $dbh = Bugzilla->dbh; @@ -38,46 +87,8 @@ sub run_bug_query { next if $qdef->{name} ne $params->{query}; my ($bugs, $query_string) = query_bugs($qdef); - my $last_comment_sql = " - SELECT comment_id - FROM longdescs - WHERE bug_id = ? AND bug_when > ?"; - if (!$user->is_insider) { - $last_comment_sql .= " AND isprivate = 0"; - } - $last_comment_sql .= " LIMIT 1"; - my $last_comment_sth = $dbh->prepare($last_comment_sql); - # Add last changes to each bug foreach my $b (@$bugs) { - my $last_changes = {}; - my $activity = $self->history({ ids => [ $b->{bug_id} ], - new_since => $b->{changeddate_api} }); - if (@{$activity->{bugs}[0]{history}}) { - my $change_set = $activity->{bugs}[0]{history}[0]; - $last_changes->{activity} = $change_set->{changes}; - foreach my $change (@{ $last_changes->{activity} }) { - $change->{field_desc} - = template_var('field_descs')->{$change->{field_name}} || $change->{field_name}; - } - $last_changes->{email} = $change_set->{who}; - my $datetime = datetime_from($change_set->{when}); - $datetime->set_time_zone($user->timezone); - $last_changes->{when} = $datetime->strftime('%Y-%m-%d %T %Z'); - } - my $last_comment_id = $dbh->selectrow_array( - $last_comment_sth, undef, $b->{bug_id}, $b->{changeddate_api}); - if ($last_comment_id) { - my $comments = $self->comments({ comment_ids => [ $last_comment_id ] }); - my $comment = $comments->{comments}{$last_comment_id}; - $last_changes->{comment} = $comment->{text}; - $last_changes->{email} = $comment->{creator} if !$last_changes->{email}; - my $datetime = datetime_from($comment->{creation_time}); - $datetime->set_time_zone($user->timezone); - $last_changes->{when} = $datetime->strftime('%Y-%m-%d %T %Z'); - } - $b->{last_changes} = $last_changes; - # Set the data type properly for webservice clients # for non-string values. $b->{bug_id} = $self->type('int', $b->{bug_id}); diff --git a/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl b/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl index 3f5f45f1d..023de290c 100644 --- a/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl +++ b/extensions/MyDashboard/template/en/default/pages/mydashboard.html.tmpl @@ -25,8 +25,11 @@ [% saved_queries.push(q) IF q.saved %] [% END %] +<script id="last-changes-stub" type="text/x-handlebars-template"> + <div id="last_changes_stub_{{bug_id}}">Loading...</div> +</script> <script id="last-changes-template" type="text/x-handlebars-template"> - <div id="last_changes"> + <div id="last_changes_{{bug_id}}"> {{#if email}} <div id="last_changes_header"> Last Changes :: {{email}} :: {{when}} diff --git a/extensions/MyDashboard/web/js/query.js b/extensions/MyDashboard/web/js/query.js index fe7c00b17..82e2a531b 100644 --- a/extensions/MyDashboard/web/js/query.js +++ b/extensions/MyDashboard/web/js/query.js @@ -24,10 +24,12 @@ YUI({ }).use("node", "datatable", "datatable-sort", "datatable-message", "json-stringify", "datatable-datasource", "datasource-io", "datasource-jsonschema", "cookie", "gallery-datatable-row-expansion-bmo", "handlebars", "escape", function(Y) { - var counter = 0, - dataSource = null, - dataTable = null, - default_query = "assignedbugs"; + var counter = 0, + bugQueryTable = null, + bugQuery = null, + lastChangesQuery = null, + lastChangesCache = {}, + default_query = "assignedbugs"; // Grab last used query name from cookie or use default var query_cookie = Y.Cookie.get("my_dashboard_query"); @@ -45,54 +47,77 @@ YUI({ } } + var bugQuery = new Y.DataSource.IO({ source: 'jsonrpc.cgi' }); + + bugQuery.plug(Y.Plugin.DataSourceJSONSchema, { + schema: { + resultListLocator: "result.result.bugs", + resultFields: ["bug_id", "changeddate", "changeddate_fancy", + "bug_status", "short_desc", "changeddate_api" ], + metaFields: { + description: "result.result.description", + heading: "result.result.heading", + buffer: "result.result.buffer" + } + } + }); + + bugQuery.on('error', function(e) { + try { + var response = Y.JSON.parse(e.data.responseText); + if (response.error) + e.error.message = response.error.message; + } catch(ex) { + // ignore + } + }); + + var bugQueryCallback = { + success: function(e) { + if (e.response) { + Y.one('#query_count_refresh').removeClass('bz_default_hidden'); + Y.one("#query_container .query_description").setHTML(e.response.meta.description); + Y.one("#query_container .query_heading").setHTML(e.response.meta.heading); + Y.one("#query_bugs_found").setHTML( + '<a href="buglist.cgi?' + e.response.meta.buffer + + '" target="_blank">' + e.response.results.length + ' bugs found</a>'); + bugQueryTable.set('data', e.response.results); + } + }, + failure: function(o) { + if (o.error) { + alert("Failed to load bug list from Bugzilla:\n\n" + o.error.message); + } else { + alert("Failed to load bug list from Bugzilla."); + } + } + }; + var updateQueryTable = function(query_name) { if (!query_name) return; counter = counter + 1; + lastChangesCache = {}; - var callback = { - success: function(e) { - if (e.response) { - Y.one('#query_count_refresh').removeClass('bz_default_hidden'); - Y.one("#query_container .query_description").setHTML(e.response.meta.description); - Y.one("#query_container .query_heading").setHTML(e.response.meta.heading); - Y.one("#query_bugs_found").setHTML( - '<a href="buglist.cgi?' + e.response.meta.buffer + - '" target="_blank">' + e.response.results.length + ' bugs found</a>'); - dataTable.set('data', e.response.results); - } - }, - failure: function(o) { - if (o.error) { - alert("Failed to load bug list from Bugzilla:\n\n" + o.error.message); - } else { - alert("Failed to load bug list from Bugzilla."); - } - } - }; + Y.one('#query_count_refresh').addClass('bz_default_hidden'); + bugQueryTable.set('data', []); + bugQueryTable.render("#query_table"); + bugQueryTable.showMessage('loadingMessage'); - var json_object = { + var bugQueryParams = { version: "1.1", method: "MyDashboard.run_bug_query", id: counter, params: { query : query_name } }; - var stringified = Y.JSON.stringify(json_object); - - Y.one('#query_count_refresh').addClass('bz_default_hidden'); - - dataTable.set('data', []); - dataTable.render("#query_table"); - dataTable.showMessage('loadingMessage'); - - dataSource.sendRequest({ - request: stringified, + bugQuery.sendRequest({ + request: Y.JSON.stringify(bugQueryParams), cfg: { method: "POST", headers: { 'Content-Type': 'application/json' } }, - callback: callback + callback: bugQueryCallback }); }; @@ -101,22 +126,17 @@ YUI({ Y.Escape.html(o.data.changeddate_fancy) + '</span>'; }; - dataSource = new Y.DataSource.IO({ source: 'jsonrpc.cgi' }); - dataSource.plug(Y.Plugin.DataSourceJSONSchema, { + lastChangesQuery = new Y.DataSource.IO({ source: 'jsonrpc.cgi' }); + + lastChangesQuery.plug(Y.Plugin.DataSourceJSONSchema, { schema: { - resultListLocator: "result.result.bugs", - resultFields: ["bug_id", "changeddate", "changeddate_fancy", - "bug_status", "short_desc", "last_changes"], - metaFields: { - description: "result.result.description", - heading: "result.result.heading", - buffer: "result.result.buffer" - } + resultListLocator: "result.results", + resultFields: ["last_changes"], } }); - dataSource.on('error', function(e) { + lastChangesQuery.on('error', function(e) { try { var response = Y.JSON.parse(e.data.responseText); if (response.error) @@ -126,7 +146,7 @@ YUI({ } }); - dataTable = new Y.DataTable({ + bugQueryTable = new Y.DataTable({ columns: [ { key: Y.Plugin.DataTableRowExpansion.column_key, label: ' ', sortable: false }, { key: "bug_id", label: "Bug", allowHTML: true, sortable: true, @@ -138,29 +158,65 @@ YUI({ ], }); - var last_changes_source = Y.one('#last-changes-template').getHTML(), + var last_changes_source = Y.one('#last-changes-template').getHTML(), last_changes_template = Y.Handlebars.compile(last_changes_source); - dataTable.plug(Y.Plugin.DataTableRowExpansion, { + var stub_source = Y.one('#last-changes-stub').getHTML(), + stub_template = Y.Handlebars.compile(stub_source); + + + bugQueryTable.plug(Y.Plugin.DataTableRowExpansion, { uniqueIdKey: 'bug_id', template: function(data) { - var last_changes = {}; - if (data.last_changes.email) { - last_changes = { - activity: data.last_changes.activity, - email: data.last_changes.email, - when: data.last_changes.when, - comment: data.last_changes.comment, + var bug_id = data.bug_id; + + var lastChangesCallback = { + success: function(e) { + if (e.response) { + var last_changes = e.response.results[0].last_changes; + last_changes['bug_id'] = bug_id; + lastChangesCache[bug_id] = last_changes; + Y.one('#last_changes_stub_' + bug_id).setHTML(last_changes_template(last_changes)); + } + }, + failure: function(o) { + if (o.error) { + alert("Failed to load last changes from Bugzilla:\n\n" + o.error.message); + } else { + alert("Failed to load last changes from Bugzilla."); + } + } + }; + + if (!lastChangesCache[bug_id]) { + var lastChangesParams = { + version: "1.1", + method: "MyDashboard.run_last_changes", + params: { bug_id: data.bug_id, changeddate_api: data.changeddate_api } }; + + lastChangesQuery.sendRequest({ + request: Y.JSON.stringify(lastChangesParams), + cfg: { + method: "POST", + headers: { 'Content-Type': 'application/json' } + }, + callback: lastChangesCallback + }); + + return stub_template({bug_id: bug_id}); + } + else { + return last_changes_template(lastChangesCache[bug_id]); } - return last_changes_template(last_changes); + } }); - dataTable.plug(Y.Plugin.DataTableSort); + bugQueryTable.plug(Y.Plugin.DataTableSort); - dataTable.plug(Y.Plugin.DataTableDataSource, { - datasource: dataSource + bugQueryTable.plug(Y.Plugin.DataTableDataSource, { + datasource: bugQuery }); // Initial load @@ -183,7 +239,7 @@ YUI({ }); Y.one('#query_buglist').on('click', function(e) { - var data = dataTable.data; + var data = bugQueryTable.data; var ids = []; for (var i = 0, l = data.size(); i < l; i++) { ids.push(data.item(i).get('bug_id')); |