|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
A reimplementation of emblemsHere's a stab at implementing emblems. I don't really know how to
send things around with bzr; the attached is a bundle from 'bzr send -o', but that doesn't contain my log message apparently??? The log message was: === Add support for Emblems An emblem is an icon displayed along side the search results to draw attention to a particular result. Two types of emblems are added here: The singleton "patch" emblem which is used for bugs with (non-obsolete) patches in a configurable set of states. Keyword emblems are associated with a particular keyword. * An 'emblems' table is added to the database schema; this holds all configured emblems including the patch emblem. Each emblem has a 'definition' column which is either 'patch:<status>,<status>' or 'keyword:<keyword>'. * checksetup.py adds a default value for the patch emblem if it doesn't already exist. * An editing UI is added to the admin section; this allows adding and removing keyword emblems, changing the statuses for the patch emblem, and editing the image URLs for all emblems. * A Bugzilla::Emblem object is added to represent rows in the emblem table. * A hidden open_patches column is defined in Search.pm that indicates whether the result has open patches according to the patch emblem statuses. * buglist.cgi adds 'open_patches' and 'keywords' to the set of selected columns if necessary. * list/table.html.tmpl is modified to add the emblems to the first table column. The concept (but not the code) is based on original implementation by Thomas Thurman and Olav Vittters. === Notes, future enhancements, etc. ================================ * I tried to do this clean but I haven't written any significant Perl code since 2001/2002 so I'm pretty rusty on good style. (Also, I didn't check that the POD docs in Bugzilla::Emblem parse correctly.) * The editing UI was largely a cut-paste-and-modify job from the keyword editing, which made things a lot easier; a lot of the new lines in the patch are actually from that. * This isn't made optional in any way; as soon as you install this and run checksetup.py, you'll start getting patch emblems. Things that could be done here: * The automatically added patch emblem could start off with a an empty default set of statuses. If that was the case, then there would be no user interface appearance of emblems and no change to the search queries. There would be a small amount of overhead from buglist.cgi and template additions. * Emblems could be controlled globally with a 'useemblems' parameter. * Emblems could maybe be done as an extension. See below. * With mod_perl, if you change the statuses for the patch emblem, it's going to take a web server restart to have that picked up, since COLUMNS is cached. I don't know any easy way to fix that. It might be worth adding a note to that effect in the message that is displayed when the statuses are changed. * It would seem nice to allow more than one patch emblem; you might want different emblems for statuses of "accepted-commit-now" and "none" (haven't looked at yet.) This would, however, up the complexity of implementation quite a bit, since you'd have to dynamically add a variable number of 'open_patch' columns on the fly. * Emblems can be added through the web interface, but there's no way to upload the icon, so either an absolute URL to some other server is used, or the images have to separately be loaded into /images/emblems. * I didn't put any effort into CSS or prettification, so emblems push over the bug numbers, which looks a bit ugly. 1 2 <heart> 3 4 <patch> 5 6 We may have CSS that can be stolen from our old templates. * There's a + print STDERR join("|", @sql_fields), "\n"; leftover in the patch I just saw. Could it be an extension? ========================= Most of the additions could be done easily through the extension mechanism. Some of it is existing hooks: Schema.pm addition: db_schema-abstract_schema Search.pm addition: buglist-columns Install/DB.pm addition: install-update_db editemblems.cgi: Could be done with page-before_template hook A few things would need new hooks: buglist.cgi addition: would need a new hook or hooks to update @selectcolumns and the page vars. admin.html.tmpl addition: needs a new template hook How to do the messages and user error additions wasn't that clear, but presumably something could be figured out, or just fall back to hardcoding. But the thing that really stumped me was how to do the table.html.tmpl addition. As I read the template hook mechanism, it's just not going to perform acceptably to have a hook called for each row. (It seems to do a look up through all the extension directories each time the hook is invoked.) - Owen # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: otaylor@...-\ # j3ku6q352hwx29ec # target_branch: /home/otaylor/Source/bugzilla-mkanat/ # testament_sha1: 0440277d5a1e9fec23182107ddf132da834ba6ec # timestamp: 2009-08-23 15:40:46 -0400 # base_revision_id: mkanat@...-\ # u4m8c53n3nb3ci4b # # Begin patch === modified file 'Bugzilla/DB/Schema.pm' --- Bugzilla/DB/Schema.pm 2009-07-29 05:01:49 +0000 +++ Bugzilla/DB/Schema.pm 2009-08-23 19:23:00 +0000 @@ -550,6 +550,19 @@ ], }, + # Emblems + # -------- + + emblems => { + FIELDS => [ + id => {TYPE => 'SMALLSERIAL', NOTNULL => 1, + PRIMARYKEY => 1}, + definition => {TYPE => 'varchar(200)', NOTNULL => 1}, + description => {TYPE => 'MEDIUMTEXT'}, + image_url => {TYPE => 'varchar(200)', NOTNULL => 1}, + ] + }, + # Flags # ----- === added file 'Bugzilla/Emblem.pm' --- Bugzilla/Emblem.pm 1970-01-01 00:00:00 +0000 +++ Bugzilla/Emblem.pm 2009-08-23 19:23:00 +0000 @@ -0,0 +1,272 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# Contributor(s): Max Kanat-Alexander <mkanat@...> +# Owen Taylor <otaylor@...> + +use strict; + +package Bugzilla::Emblem; + +use base qw(Bugzilla::Object); + +use Bugzilla::Error; +use Bugzilla::Util; + +############################### +#### Initialization #### +############################### + +use constant DB_COLUMNS => qw( + emblems.id + emblems.definition + emblems.description + emblems.image_url +); + +use constant DB_TABLE => 'emblems'; + +use constant REQUIRED_CREATE_FIELDS => qw(definition image_url description); + +use constant VALIDATORS => { + definition => \&_check_definition, + image_url => \&_check_image_url, + description => \&_check_description, +}; + +use constant UPDATE_COLUMNS => qw( + definition + image_url + description +); + +############################### +#### Accessors ###### +############################### + +sub image_url { return $_[0]->{'image_url'}; } +sub description { return $_[0]->{'description'}; } + +sub ispatch { + my ($self) = @_; + + return $self->{'definition'} =~ /^patch:/; +} + +sub keyword { + my ($self) = @_; + + return undef unless ($self->{'definition'} =~ /^keyword:(.*)/); + + return $1; +} + +sub statuses { + my ($self) = @_; + + return () unless $self->{'definition'} =~ /^patch:(.*)/; + + return split(',', $1) +} + +############################### +#### Mutators ##### +############################### + +sub set_definition { $_[0]->set('definition', $_[1]); } +sub set_image_url { $_[0]->set('image_url', $_[1]); } +sub set_description { $_[0]->set('description', $_[1]); } + +############################### +#### Subroutines ###### +############################### + +sub get_keyword_emblems { + my $class = shift; + my $dbh = Bugzilla->dbh; + my $emblems = + $dbh->selectall_arrayref('SELECT ' . join(', ', DB_COLUMNS) . ' + FROM emblems + WHERE emblems.definition like \'keyword:%\'', + {'Slice' => {}}); + + if (!$emblems) { + return []; + } + + foreach my $emblem (@$emblems) { + bless($emblem, $class); + } + return $emblems; +} + +sub get_all_emblems { + my $class = shift; + my $dbh = Bugzilla->dbh; + my $emblems = + $dbh->selectall_arrayref('SELECT ' . join(', ', DB_COLUMNS) . ' + FROM emblems', + {'Slice' => {}}); + + if (!$emblems) { + return []; + } + + foreach my $emblem (@$emblems) { + bless($emblem, $class); + } + return $emblems; +} + +sub get_patch_emblem { + my $class = shift; + my $dbh = Bugzilla->dbh; + my $emblem = + $dbh->selectall_arrayref('SELECT ' . join(', ', DB_COLUMNS) . ' + FROM emblems + WHERE emblems.definition like \'patch:%\' + LIMIT 1', + {'Slice' => {}}); + + if (!$emblem || @$emblem != 1) { + return undef; + } + + bless($emblem->[0], $class); + return $emblem->[0]; +} + +############################### +### Validators ### +############################### + +sub _check_definition { + my ($self, $definition) = @_; + + $definition = trim($definition); + + # We don't actually validate here, since we can't return a meaningful + # erorr message; it's up to the caller to validate the specific + # definition type: + # keyword:<keyword> + # patch:<status>,<status>,<status> + + return $definition; +} + +sub _check_description { + my ($self, $desc) = @_; + $desc = trim($desc); + $desc eq '' && ThrowUserError("emblem_blank_description"); + return $desc; +} + +sub _check_image_url { + my ($self, $image_url) = @_; + $image_url = trim($image_url); + $image_url eq '' && ThrowUserError("emblem_blank_image_url"); + return $image_url; +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::Emblem - An emblem displayed with search results + +=head1 SYNOPSIS + + use Bugzilla::Emblem + + my $description = $keyword->description; + + my $keywords = Bugzilla::Keyword->get_keyword_emblems(); + + my $keyword = Bugzilla::Keyword->get_patch_emblem(); + +=head1 DESCRIPTION + +Bugzilla::Emblem represents an an emblem displayed with search results + +This implements all standard C<Bugzilla::Object> methods. See +L<Bugzilla::Object> for more details. + +=head1 METHODS + +This is only a list of methods specific to C<Bugzilla::Emblem>. +See L<Bugzilla::Object> for more methods that this object +implements. + +=item C<ispatch()> + + Description: Determine if this is the singleton patch emblem + Params: none + Returns: C<1> if this is the singleton patch emblem, C<0> otherwise + +=item C<keyword()> + + Description: Return the keyword for a keyword emblem + Params: none + Returns: The keyword for this emblem if it's a keyword emblem, + C<undef> if it's the patch emblem + +=item C<statuses()> + + Description: Return the statuses for the patch emblem + Params: none + Returns: The statuses that count as an open patch if the emblem is + the patch emblem. An empty list if it's a keyword emblem + +=item C<ispatch()> + + Description: Determine if this is the singleton patch emblem + Params: none + Returns: <1> if this is the singleton patch emblem, <0> otherwise + +=head1 SUBROUTINES + +This is only a list of subroutines specific to C<Bugzilla::Emblem>. +See L<Bugzilla::Object> for more subroutines that this object +implements. + +=over + +=item C<get_all_emblems()> + + Description: Returns all defined emblems. + Params: none + Returns: A reference to an array of Emblem objects, or an empty + arrayref if there are no emblems. This includes both + the keyword emblems and the signleton patch emblem. + +=item C<get_keyword_emblems()> + + Description: Returns defined keyword emblems. + Params: none + Returns: A reference to an array of Emblem objects, or an empty + arrayref if there are no emblems. + +=item C<get_patch_emblem()> + + Description: Returns the singleton patch emblem. + Params: none + Returns: the Emblem object for the patch emblem. This will nevern + be undefined except in the error-case when there is no + patch emblem in the database. + +=back + +=cut === modified file 'Bugzilla/Install/DB.pm' --- Bugzilla/Install/DB.pm 2009-08-14 02:07:41 +0000 +++ Bugzilla/Install/DB.pm 2009-08-23 19:23:00 +0000 @@ -632,6 +632,8 @@ _fix_saved_searches(); + _create_patch_emblem(); + ################################################################ # New --TABLE-- changes should go *** A B O V E *** this point # ################################################################ @@ -3521,6 +3523,15 @@ $dbh->bz_commit_transaction(); } +sub _create_patch_emblem { + my $dbh = Bugzilla->dbh; + + if (!$dbh->selectrow_arrayref("SELECT 1 FROM emblems WHERE definition like 'patch:%' LIMIT 1")) { + $dbh->do("INSERT INTO emblems (definition, image_url, description) + VALUES ('patch:none', '/images/emblems/patch.png', 'Patch needs attention')"); + } +} + 1; __END__ === modified file 'Bugzilla/Search.pm' --- Bugzilla/Search.pm 2009-07-10 20:37:42 +0000 +++ Bugzilla/Search.pm 2009-08-23 19:23:00 +0000 @@ -49,6 +49,7 @@ use Bugzilla::Field; use Bugzilla::Status; use Bugzilla::Keyword; +use Bugzilla::Emblem; use Date::Format; use Date::Parse; @@ -167,6 +168,29 @@ # The short_short_desc column is identical to short_desc $columns{'short_short_desc'} = $columns{'short_desc'}; + # The open_patches column is used to flag results that need the patch emblem, + # but should be otherwise hidden, so we add it in directly here rather than + # adding it to the field definitions. + $columns{'open_patches'} = { title => 'Open Patches' }; + + my @open_patch_statuses; + my $patch_emblem = Bugzilla::Emblem->get_patch_emblem(); + if ($patch_emblem) { + @open_patch_statuses = map { $dbh->quote($_) } $patch_emblem->statuses; + } + + if (@open_patch_statuses) { + my $open_patch = $dbh->sql_in('attachments.status', \@open_patch_statuses); + $columns{'open_patches'}->{'name'} = + "EXISTS (SELECT * FROM attachments" + . " WHERE attachments.bug_id = bugs.bug_id" + . " AND attachments.ispatch = 1" + . " AND attachments.isobsolete = 0" + . " AND $open_patch)"; + } else { + $columns{'open_patches'}->{'name'} = '0'; + }; + Bugzilla::Hook::process("buglist-columns", { columns => \%columns }); $cache->{search_columns} = \%columns; @@ -938,6 +962,7 @@ my @sql_fields = map { $_ eq EMPTY_COLUMN ? EMPTY_COLUMN : COLUMNS->{$_}->{name} . ' AS ' . $_ } @fields; + print STDERR join("|", @sql_fields), "\n"; my $query = "SELECT " . join(', ', @sql_fields) . " FROM $suppstring" . " LEFT JOIN bug_group_map " . === modified file 'buglist.cgi' --- buglist.cgi 2009-08-12 03:28:01 +0000 +++ buglist.cgi 2009-08-23 19:23:00 +0000 @@ -45,6 +45,7 @@ use Bugzilla::Bug; use Bugzilla::Product; use Bugzilla::Keyword; +use Bugzilla::Emblem; use Bugzilla::Field; use Bugzilla::Status; use Bugzilla::Token; @@ -796,6 +797,22 @@ } } +my $need_open_patches = 0; +my $need_keywords = 0; +$vars->{'emblems'} = {}; +foreach my $emblem (@{Bugzilla::Emblem->get_all_emblems()}) { + if ($emblem->ispatch && $emblem->statuses) { + $vars->{'emblems'}->{'PATCH'} = $emblem->image_url; + $need_open_patches = 1; + } else { + $vars->{'emblems'}->{$emblem->keyword} = $emblem->image_url; + $need_keywords = 1; + } +} + +push(@selectcolumns, "open_patches") if $need_open_patches; +push(@selectcolumns, "keywords") if $need_keywords; + ################################################################################ # Sort Order Determination ################################################################################ === added file 'editemblems.cgi' --- editemblems.cgi 1970-01-01 00:00:00 +0000 +++ editemblems.cgi 2009-08-23 19:23:00 +0000 @@ -0,0 +1,208 @@ +#!/usr/bin/perl -wT +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Terry Weissman. +# Portions created by Terry Weissman are +# Copyright (C) 2000 Terry Weissman. All +# Rights Reserved. +# +# Contributor(s): Terry Weissman <terry@...> +# Owen Taylor <otaylor@...> + +use strict; +use lib qw(. lib); + +use Bugzilla; +use Bugzilla::Constants; +use Bugzilla::Emblem; +use Bugzilla::Error; +use Bugzilla::Util; +use Bugzilla::Token; + +my $cgi = Bugzilla->cgi; +my $dbh = Bugzilla->dbh; +my $template = Bugzilla->template; +my $vars = {}; + +# +# Preliminary checks: +# + +my $user = Bugzilla->login(LOGIN_REQUIRED); + +print $cgi->header(); + +$user->in_group('editkeywords') + || ThrowUserError("auth_failure", {group => "editkeywords", + action => "edit", + object => "emblems"}); + +my $action = trim($cgi->param('action') || ''); +my $key_id = $cgi->param('id'); +my $token = $cgi->param('token'); + +$vars->{'action'} = $action; + +if ($action eq "") { + ProcessList(); + exit; +} + +if ($action eq 'add') { + $vars->{'token'} = issue_session_token('add_emblem'); + + print $cgi->header(); + + $template->process("admin/emblems/create.html.tmpl", $vars) + || ThrowTemplateError($template->error()); + + exit; +} + +# +# action='new' -> add keyword entered in the 'action=add' screen +# +if ($action eq 'new') { + check_token_data($token, 'add_emblem'); + my $keyword = CheckKeyword(scalar $cgi->param('keyword')); + my $image_url = $cgi->param('image_url') || ''; + my $desc = $cgi->param('description') || ''; + + my $emblem = Bugzilla::Emblem->create( + { definition => "keyword:$keyword", + image_url => $image_url, + description => $desc }); + + delete_token($token); + + $vars->{'emblem_keyword'} = $emblem->keyword; + ProcessList('emblem_created'); + + exit; +} + + +if ($action eq 'edit') { + my $emblem = new Bugzilla::Emblem($key_id) + || ThrowCodeError('invalid_emblem_id', { id => $key_id }); + + $vars->{'emblem'} = $emblem; + $vars->{'token'} = issue_session_token('edit_emblem'); + + print $cgi->header(); + $template->process("admin/emblems/edit.html.tmpl", $vars) + || ThrowTemplateError($template->error()); + exit; +} + +# +# action='update' -> update the emblem with changes from the 'action=edit' screen +# +if ($action eq 'update') { + check_token_data($token, 'edit_emblem'); + my $emblem = new Bugzilla::Emblem($key_id) + || ThrowCodeError('invalid_emblem_id', { id => $key_id }); + + my $definition; + if ($emblem->ispatch) { + my $statuses_string = trim(scalar $cgi->param('statuses')); + my @statuses; + foreach my $status (split(",", $statuses_string)) { + push @statuses, trim($status); + } + $definition = "patch:" . join(",", @statuses); + } else { + my $keyword = CheckKeyword(scalar $cgi->param('keyword')); + $definition = "keyword:$keyword", + } + + $emblem->set_all({ + definition => $definition, + image_url => scalar $cgi->param('image_url'), + description => scalar $cgi->param('description'), + }); + my $changes = $emblem->update(); + + delete_token($token); + + print $cgi->header(); + + $vars->{'emblem'} = $emblem; + $vars->{'changes'} = $changes; + ProcessList('emblem_updated'); + + exit; +} + +if ($action eq 'del') { + my $emblem = new Bugzilla::Emblem($key_id) + || ThrowCodeError('invalid_emblem_id', { id => $key_id }); + + $vars->{'emblem'} = $emblem; + $vars->{'token'} = issue_session_token('delete_emblem'); + + print $cgi->header(); + $template->process("admin/emblems/confirm-delete.html.tmpl", $vars) + || ThrowTemplateError($template->error()); + exit; +} + +# +# action='delete' -> delete the emblem after confirmation at 'action=del' screen +# +if ($action eq 'delete') { + check_token_data($token, 'delete_emblem'); + my $emblem = new Bugzilla::Emblem($key_id) + || ThrowCodeError('invalid_emblem_id', { id => $key_id }); + + $dbh->do('DELETE FROM emblems WHERE id = ?', undef, $emblem->id); + + delete_token($token); + + $vars->{'emblem_keyword'} = $emblem->keyword; + ProcessList('emblem_deleted'); + exit; +} + +ThrowCodeError("action_unrecognized", $vars); + +################################################################################ +# Utilities +################################################################################ + +sub CheckKeyword { + my ($keyword) = @_; + + $keyword = trim($keyword || ''); + $keyword eq "" && ThrowUserError("emblem_blank_keyword"); + if ($keyword =~ /[\s,]/) { + ThrowUserError("emblem_invalid_keyword"); + } + + return $keyword; +} + +sub ProcessList { + my ($message) = @_; + + print $cgi->header(); + + $vars->{'patch_emblem'} = Bugzilla::Emblem->get_patch_emblem(); + $vars->{'keyword_emblems'} = Bugzilla::Emblem->get_keyword_emblems(); + $vars->{'message'} = $message if defined $message; + + $template->process("admin/emblems/list.html.tmpl", $vars) + || ThrowTemplateError($template->error()); +} === added directory 'images/emblems' === added file 'images/emblems/patch.png' Binary files images/emblems/patch.png 1970-01-01 00:00:00 +0000 and images/emblems/patch.png 2009-08-23 19:23:00 +0000 differ === modified file 'template/en/default/admin/admin.html.tmpl' --- template/en/default/admin/admin.html.tmpl 2008-08-08 06:26:33 +0000 +++ template/en/default/admin/admin.html.tmpl 2009-08-23 19:23:00 +0000 @@ -118,6 +118,11 @@ <dd class="[% class %]">Set keywords to be used with [% terms.bugs %]. Keywords are an easy way to "tag" [% terms.bugs %] to let you find them more easily later.</dd> + [% class = user.in_group('editkeywords') ? "" : "forbidden" %] + <dt class="[% class %]"><a href="editemblems.cgi">Emblems</a></dt> + <dd class="[% class %]">Set icons to be displayed next to the search result list. Emblems + allow highlighting bugs with particular keywords or that have patches that need attention.</dd> + [% class = user.in_group('bz_canusewhines') ? "" : "forbidden" %] <dt class="[% class %]"><a href="editwhines.cgi">Whining</a></dt> <dd class="[% class %]">Set queries which will be run at some specified date === added directory 'template/en/default/admin/emblems' === added file 'template/en/default/admin/emblems/confirm-delete.html.tmpl' --- template/en/default/admin/emblems/confirm-delete.html.tmpl 1970-01-01 00:00:00 +0000 +++ template/en/default/admin/emblems/confirm-delete.html.tmpl 2009-08-23 19:23:00 +0000 @@ -0,0 +1,47 @@ +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Terry Weissman <terry@...> + # Vlad Dascalu <jocuri@...> + # Max Kanat-Alexander <mkanat@...> + # Owen Taylor <otaylor@...> + #%] + +[%# INTERFACE: + # emblem: A Bugzilla::Emblem object. + #%] + +[% PROCESS global/header.html.tmpl + title = "Delete Emblem" +%] + +<p> + Are you <b>sure</b> you want to delete + the <code>[% emblem.keyword FILTER html %]</code> emblem? +</p> + +<form method="post" action="editemblems.cgi"> + <input type="hidden" name="id" value="[% emblem.id FILTER html %]"> + <input type="hidden" name="action" value="delete"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + <input type="submit" id="delete" + value="Yes, really delete the emblem"> +</form> + +<p><a href="editemblems.cgi">Edit other emblems</a>.</p> + +[% PROCESS global/footer.html.tmpl %] === added file 'template/en/default/admin/emblems/create.html.tmpl' --- template/en/default/admin/emblems/create.html.tmpl 1970-01-01 00:00:00 +0000 +++ template/en/default/admin/emblems/create.html.tmpl 2009-08-23 19:23:00 +0000 @@ -0,0 +1,63 @@ +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Terry Weissman <terry@...> + # Vlad Dascalu <jocuri@...> + # Owen Taylor <otaylor@...> + #%] + +[%# INTERFACE: + # none + #%] + +[% PROCESS global/header.html.tmpl + title = "Add emblem" + subheader = "This page allows you to add a new emblem." +%] + +<form method="post" action="editemblems.cgi"> + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <th align="right">Keyword:</th> + <td><input size="64" maxlength="64" name="keyword" value=""></td> + </tr> + <tr> + <th align="right">Image URL:</th> + <td><input size="64" maxlength="64" name="image_url" value=""></td> + </tr> + <tr> + <th align="right">Description:</th> + <td> + [% INCLUDE global/textarea.html.tmpl + name = 'description' + minrows = 4 + cols = 64 + wrap = 'virtual' + %] + </td> + </tr> + </table> + <hr> + <input type="hidden" name="id" value="-1"> + <input type="submit" id="create" value="Add"> + <input type="hidden" name="action" value="new"> + <input type="hidden" name="token" value="[% token FILTER html %]"> +</form> + +<p><a href="editemblems.cgi">Edit other emblems</a>.</p> + +[% PROCESS global/footer.html.tmpl %] === added file 'template/en/default/admin/emblems/edit.html.tmpl' --- template/en/default/admin/emblems/edit.html.tmpl 1970-01-01 00:00:00 +0000 +++ template/en/default/admin/emblems/edit.html.tmpl 2009-08-23 19:23:00 +0000 @@ -0,0 +1,74 @@ +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Terry Weissman <terry@...> + # Vlad Dascalu <jocuri@...> + # Max Kanat-Alexander <mkanat@...> + # Owen Taylor <otaylor@...> + #%] + +[%# INTERFACE: + # emblem: A Bugzilla::Emblem object. + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Edit emblem" +%] + +<form method="post" action="editemblems.cgi"> + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + [% IF emblem.ispatch %] + <th align="right">Statuses:</th> + <td><input size="64" maxlength="64" name="statuses" + value="[% emblem.statuses.join(',') FILTER html %]"></td> + [% ELSE %] + <th align="right">Keyword:</th> + <td><input size="64" maxlength="64" name="keyword" + value="[% emblem.keyword FILTER html %]"></td> + [% END %] + </tr> + <tr> + <th align="right">Image URL:</th> + <td><input size="64" maxlength="64" name="image_url" + value="[% emblem.image_url FILTER html %]"></td> + </tr> + <tr> + <th align="right">Description:</th> + <td> + [% INCLUDE global/textarea.html.tmpl + name = 'description' + minrows = 4 + cols = 64 + wrap = 'virtual' + defaultcontent = emblem.description + %] + </td> + </tr> + </table> + + <input type="submit" id="update" value="Save Changes"> + <input type="hidden" name="action" value="update"> + <input type="hidden" name="id" value="[% emblem.id FILTER html %]"> + <input type="hidden" name="token" value="[% token FILTER html %]"> +</form> + +<p><a href="editemblems.cgi">Edit other emblems</a>.</p> + +[% PROCESS global/footer.html.tmpl %] === added file 'template/en/default/admin/emblems/list.html.tmpl' --- template/en/default/admin/emblems/list.html.tmpl 1970-01-01 00:00:00 +0000 +++ template/en/default/admin/emblems/list.html.tmpl 2009-08-23 19:23:00 +0000 @@ -0,0 +1,88 @@ +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Terry Weissman <terry@...> + # Vlad Dascalu <jocuri@...> + # Jouni Heikniemi <jouni@...> + # Owen Taylor <otaylor@...> + #%] + +[%# INTERFACE: + # patch_emblem: emblems object having the properties: + # - id: number. The ID of the emblem. + # - statuses: string. The attachment statuses that trigger the emblem + # - image_url: string. The URL for the image of the keyword + # keyword_emblems: array of emblems objects having the properties: + # - id: number. The ID of the emblem. + # - keyword: string. The keyword the emblem corresponds to. + # - image_url: string. The URL for the image of the keyword + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Select emblem" +%] + +<h2>Patch Emblem</h2> + +<p> + The patch emblem shows when a bug has a (non-obsolete) patch with one of the + specified statuses. <a href="editemblems.cgi?action=edit&id=[% patch_emblem.id %]">Edit</a> +</p> +<table border="0" cellpadding="4" cellspacing="0"> + <tr> + <th align="right">Statuses:</th> + <td>[% patch_emblem.statuses.join(",") FILTER html %]</td> + </tr> + <tr> + <th align="right">Image URL:</th> + <td>[% patch_emblem.image_url FILTER html %]</td> + </tr> +</table> + +<hr> + +<h2>Keyword Emblems</h2> + +[% columns = [ + { + name => "keyword" + heading => "Edit emblem..." + contentlink => "editemblems.cgi?action=edit&id=%%id%%" + }, + { + name => "image_url" + heading => "Image URL" + }, + { + heading => "Action" + content => "Delete" + contentlink => "editemblems.cgi?action=del&id=%%id%%" + } + ] +%] + +[% PROCESS admin/table.html.tmpl + columns = columns + data = keyword_emblems + footer = footer_row +%] + +<p><a href="editemblems.cgi?action=add">Add a new emblem</a></p> + +[% PROCESS global/footer.html.tmpl %] === modified file 'template/en/default/global/messages.html.tmpl' --- template/en/default/global/messages.html.tmpl 2009-08-07 22:10:52 +0000 +++ template/en/default/global/messages.html.tmpl 2009-08-23 19:23:00 +0000 @@ -289,6 +289,40 @@ [%+ new_email FILTER html %] has been canceled. Your old account settings have been reinstated. + [% ELSIF message_tag == "emblem_created" %] + [% title = "New Emblem Created" %] + The <em>[% emblem_keyword FILTER html %]</em> emblem has been created. + + [% ELSIF message_tag == "emblem_deleted" %] + [% title = "Emblem Deleted" %] + The <em>[% emblem_keyword FILTER html %]</em> emblem has been deleted. + + [% ELSIF message_tag == "emblem_updated" %] + [% title = "Emblem Updated" %] + [% IF changes.keys.size %] + Changes to the <em>[% emblem.keyword FILTER html %]</em> emblem have + been saved: + <ul> + [% IF changes.definition.defined %] + <li> + [% IF emblem.ispatch %] + Statuses updated to <em>[% emblem.statuses.join(",") FILTER html %]</em>. + [% ELSE %] + Keyword updated to <em>[% emblem.keyword FILTER html %]</em>. + [% END %] + </li> + [% END %] + [% IF changes.image_url.defined %] + <li>Image Url updated to <em>[% emblem.image_url FILTER html %]</em></li> + [% END %] + [% IF changes.description.defined %] + <li>Description updated to <em>[% emblem.description FILTER html %]</em></li> + [% END %] + </ul> + [% ELSE %] + No changes made. + [% END %] + [% ELSIF message_tag == "field_value_created" %] [% title = "New Field Value Created" %] The value <em>[% value.name FILTER html %]</em> has been added as a === modified file 'template/en/default/global/user-error.html.tmpl' --- template/en/default/global/user-error.html.tmpl 2009-08-06 03:34:58 +0000 +++ template/en/default/global/user-error.html.tmpl 2009-08-23 19:23:00 +0000 @@ -408,6 +408,22 @@ Your message did not contain any text.[% terms.Bugzilla %] does not accept HTML-only email, or HTML email with attachments. + [% ELSIF error == "emblem_blank_description" %] + [% title = "Blank Emblem Description Not Allowed" %] + You must enter a non-blank description for the emblem. + + [% ELSIF error == "emblem_blank_image_url" %] + [% title = "Blank Emblem Image Url Not Allowed" %] + You must enter a non-blank image url for the emblem. + + [% ELSIF error == "emblem_blank_keyword" %] + [% title = "Blank Emblem Keyword Not Allowed" %] + You must enter a non-blank keyword for the emblem. + + [% ELSIF error == "emblem_invalid_keyword" %] + [% title = "Invalid Emblem Keyword" %] + The keyword for an emblem must not contain commas or whitespace. + [% ELSIF error == "empty_group_description" %] [% title = "The group description can not be empty" %] You must enter a description for the group. === modified file 'template/en/default/list/table.html.tmpl' --- template/en/default/list/table.html.tmpl 2009-08-06 03:34:58 +0000 +++ template/en/default/list/table.html.tmpl 2009-08-23 19:23:00 +0000 @@ -173,6 +173,15 @@ </td> [% END %] <td class="first-child"> + [% FOREACH keyword = bug.keywords.split(", ") %] + [% IF emblems.${keyword}.defined %] + <img src="[% emblems.${keyword} FILTER html %]" width="16" height="16" alt=""> + [% END %] + [% END %] + [% IF bug.open_patches == 1 %] + <img src="[% emblems.PATCH FILTER html %]" width="16" height="16" alt=""> + [% END %] + <a name="b[% bug.bug_id %]" href="show_bug.cgi?id=[% bug.bug_id %]">[% bug.bug_id %]</a> <span style="display: none">[%+ '[SEC]' IF bug.secure_mode %]</span> # Begin bundle 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 cKEgIRZO0g== _______________________________________________ Gnome-bugsquad mailing list Gnome-bugsquad@... http://mail.gnome.org/mailman/listinfo/gnome-bugsquad |
| Free embeddable forum powered by Nabble | Forum Help |