From 4f6724b0f86ccffa091ca33c04e237b9dd5d4c4a Mon Sep 17 00:00:00 2001 From: Byron Jones Date: Wed, 23 Oct 2013 15:25:27 +0800 Subject: Bug 895687: add UserStory extension --- Bugzilla/Bug.pm | 4 + Bugzilla/Template.pm | 8 ++ extensions/InlineHistory/Extension.pm | 3 + extensions/UserStory/Config.pm | 21 ++++++ extensions/UserStory/Extension.pm | 88 ++++++++++++++++++++++ extensions/UserStory/lib/Constants.pm | 22 ++++++ .../hook/bug/comments-comment_banner.html.tmpl | 51 +++++++++++++ .../default/hook/bug/edit-custom_field.html.tmpl | 9 +++ .../en/default/hook/bug/show-header-end.html.tmpl | 9 +++ extensions/UserStory/web/style/user_story.css | 26 +++++++ t/008filter.t | 2 +- template/en/default/bug/activity/table.html.tmpl | 2 +- 12 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 extensions/UserStory/Config.pm create mode 100644 extensions/UserStory/Extension.pm create mode 100644 extensions/UserStory/lib/Constants.pm create mode 100644 extensions/UserStory/template/en/default/hook/bug/comments-comment_banner.html.tmpl create mode 100644 extensions/UserStory/template/en/default/hook/bug/edit-custom_field.html.tmpl create mode 100644 extensions/UserStory/template/en/default/hook/bug/show-header-end.html.tmpl create mode 100644 extensions/UserStory/web/style/user_story.css diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 0b17a02e6..9aa34b090 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -997,6 +997,10 @@ sub update { $_->update foreach @{ $self->{_update_ref_bugs} || [] }; delete $self->{_update_ref_bugs}; + # BMO - allow extensions to alter what is logged into bugs_activity + Bugzilla::Hook::process('bug_update_before_logging', + { bug => $self, timestamp => $delta_ts, changes => $changes, old_bug => $old_bug }); + # Log bugs_activity items # XXX Eventually, when bugs_activity is able to track the dupe_id, # this code should go below the duplicates-table-updating code below. diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index 434e49da5..b529caf89 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -682,6 +682,14 @@ sub create { return $var; }, + # preserve newline by converting them to
+ html_br => sub { + my ($var) = @_; + $var = html_quote($var); + $var =~ s/\n/
/g; + return $var; + }, + # Prevents line break on hyphens and whitespaces. no_break => sub { my ($var) = @_; diff --git a/extensions/InlineHistory/Extension.pm b/extensions/InlineHistory/Extension.pm index cb83fcf1d..9e6bdee92 100644 --- a/extensions/InlineHistory/Extension.pm +++ b/extensions/InlineHistory/Extension.pm @@ -57,6 +57,9 @@ sub template_before_process { return; } + # allow other extensions to alter history + Bugzilla::Hook::process('inline_history_activtiy', { activity => $activity }); + # prime caches with objects already loaded my %user_cache; foreach my $comment (@{$bug->comments}) { diff --git a/extensions/UserStory/Config.pm b/extensions/UserStory/Config.pm new file mode 100644 index 000000000..8649c71cf --- /dev/null +++ b/extensions/UserStory/Config.pm @@ -0,0 +1,21 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::UserStory; +use strict; + +use constant NAME => 'UserStory'; +use constant REQUIRED_MODULES => [ + { + package => 'Text-Diff', + module => 'Text::Diff', + version => 0, + }, +]; +use constant OPTIONAL_MODULES => []; + +__PACKAGE__->NAME; diff --git a/extensions/UserStory/Extension.pm b/extensions/UserStory/Extension.pm new file mode 100644 index 000000000..26f2c6bab --- /dev/null +++ b/extensions/UserStory/Extension.pm @@ -0,0 +1,88 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::UserStory; +use strict; +use warnings; + +use base qw(Bugzilla::Extension); +our $VERSION = '1'; + +use Bugzilla; +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::Extension::UserStory::Constants; +use Text::Diff; + +BEGIN { + *Bugzilla::Product::user_story_group = \&_product_user_story_group; +} + +sub _product_user_story_group { + my ($self) = @_; + return USER_STORY_PRODUCTS->{$self->name}; +} + +# ensure user is allowed to edit the story +sub bug_check_can_change_field { + my ($self, $args) = @_; + my ($bug, $field, $priv_results) = @$args{qw(bug field priv_results)}; + return unless $field eq 'cf_user_story'; + + my $user = Bugzilla->user; + my $group = $bug->product_obj->user_story_group() + || return; + if (!$user->in_group($group)) { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } +} + +# store just a diff of the changes in the bugs_activity table +sub bug_update_before_logging { + my ($self, $args) = @_; + my $changes = $args->{changes}; + return unless exists $changes->{cf_user_story}; + my $diff = diff( + \$changes->{cf_user_story}->[0], + \$changes->{cf_user_story}->[1], + { + CONTEXT => 0, + }, + ); + $changes->{cf_user_story} = [ '', $diff ]; +} + +# stop inline-history from displaying changes to the user story +sub inline_history_activtiy { + my ($self, $args) = @_; + foreach my $activity (@{ $args->{activity} }) { + foreach my $change (@{ $activity->{changes} }) { + if ($change->{fieldname} eq 'cf_user_story') { + $change->{removed} = ''; + $change->{added} = '(updated)'; + } + } + } +} + +# create cf_user_story field +sub install_update_db { + my ($self, $args) = @_; + return if Bugzilla::Field->new({ name => 'cf_user_story'}); + Bugzilla::Field->create({ + name => 'cf_user_story', + description => 'User Story', + type => FIELD_TYPE_TEXTAREA, + mailhead => 0, + enter_bug => 0, + obsolete => 0, + custom => 1, + buglist => 0, + }); +} + +__PACKAGE__->NAME; diff --git a/extensions/UserStory/lib/Constants.pm b/extensions/UserStory/lib/Constants.pm new file mode 100644 index 000000000..dca38154c --- /dev/null +++ b/extensions/UserStory/lib/Constants.pm @@ -0,0 +1,22 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::UserStory::Constants; + +use strict; +use warnings; + +use base qw(Exporter); + +our @EXPORT = qw( USER_STORY_PRODUCTS ); + +use constant USER_STORY_PRODUCTS => { + # product group required to edit + Tracking => 'editbugs', +}; + +1; diff --git a/extensions/UserStory/template/en/default/hook/bug/comments-comment_banner.html.tmpl b/extensions/UserStory/template/en/default/hook/bug/comments-comment_banner.html.tmpl new file mode 100644 index 000000000..f58c2fb8b --- /dev/null +++ b/extensions/UserStory/template/en/default/hook/bug/comments-comment_banner.html.tmpl @@ -0,0 +1,51 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% RETURN UNLESS bug.product_obj.user_story_group %] +[% can_edit_story = bug.check_can_change_field('cf_user_story', 0, 1) %] + +
+
+ User Story + [% IF can_edit_story %] + + (edit) + + [% END %] +
+ + [% IF bug.cf_user_story != "" %] +
+
+        [%- bug.cf_user_story FILTER quoteUrls(bug) -%]
+      
+
+ [% ELSE %] +
+ [% END %] + + [% IF can_edit_story %] +
+ [% INCLUDE global/textarea.html.tmpl + name = 'cf_user_story' + id = 'user_story' + minrows = 10 + maxrows = 10 + cols = constants.COMMENT_COLS + defaultcontent = bug.cf_user_story %] +
+ + [% END %] +
diff --git a/extensions/UserStory/template/en/default/hook/bug/edit-custom_field.html.tmpl b/extensions/UserStory/template/en/default/hook/bug/edit-custom_field.html.tmpl new file mode 100644 index 000000000..2f0f758a4 --- /dev/null +++ b/extensions/UserStory/template/en/default/hook/bug/edit-custom_field.html.tmpl @@ -0,0 +1,9 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% field.hidden = field.name == 'cf_user_story' %] diff --git a/extensions/UserStory/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/UserStory/template/en/default/hook/bug/show-header-end.html.tmpl new file mode 100644 index 000000000..abdbe865e --- /dev/null +++ b/extensions/UserStory/template/en/default/hook/bug/show-header-end.html.tmpl @@ -0,0 +1,9 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% style_urls.push("extensions/UserStory/web/style/user_story.css") %] diff --git a/extensions/UserStory/web/style/user_story.css b/extensions/UserStory/web/style/user_story.css new file mode 100644 index 000000000..51affd359 --- /dev/null +++ b/extensions/UserStory/web/style/user_story.css @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This Source Code Form is "Incompatible With Secondary Licenses", as + * defined by the Mozilla Public License, v. 2.0. */ + + +#user_story_readonly { + border: 1px solid black; + border-radius: 4px; +} + +.skin-standard #user_story_readonly { + padding: 2px; +} + +.skin-Mozilla #user_story_readonly { + border: none; + border-radius: 0px; +} + +.skin-Mozilla #user_story_readonly .bz_comment_text { + border: 1px solid darkgrey; + border-radius: 4px; +} diff --git a/t/008filter.t b/t/008filter.t index d0c0311f6..9b6a2dad6 100644 --- a/t/008filter.t +++ b/t/008filter.t @@ -225,7 +225,7 @@ sub directive_ok { return 1 if $directive =~ /FILTER\ (html|csv|js|base64|css_class_quote|ics| quoteUrls|time|uri|xml|lower|html_light| obsolete|inactive|closed|unitconvert| - txt|html_linebreak|none|json)\b/x; + txt|html_linebreak|html_br|none|json)\b/x; return 0; } diff --git a/template/en/default/bug/activity/table.html.tmpl b/template/en/default/bug/activity/table.html.tmpl index a9aca0a64..86a89297b 100644 --- a/template/en/default/bug/activity/table.html.tmpl +++ b/template/en/default/bug/activity/table.html.tmpl @@ -110,7 +110,7 @@ change.fieldname == 'flagtypes.name' %] [% display_value(change.fieldname, change_type) FILTER email FILTER html %] [% ELSE %] - [% display_value(change.fieldname, change_type) FILTER html %] + [% display_value(change.fieldname, change_type) FILTER html_br %] [% END %] [% ELSE %]   -- cgit v1.2.3-24-g4f1b