diff options
Diffstat (limited to 'extensions/BMO')
105 files changed, 10732 insertions, 0 deletions
diff --git a/extensions/BMO/Config.pm b/extensions/BMO/Config.pm new file mode 100644 index 000000000..0ad817768 --- /dev/null +++ b/extensions/BMO/Config.pm @@ -0,0 +1,38 @@ +# -*- 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 BMO Bugzilla Extension. +# +# The Initial Developer of the Original Code is Gervase Markham +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Gervase Markham <gerv@gerv.net> + +package Bugzilla::Extension::BMO; +use strict; + +use constant NAME => 'BMO'; + +use constant REQUIRED_MODULES => [ + { + package => 'Tie-IxHash', + module => 'Tie::IxHash', + version => 0 + } +]; + +use constant OPTIONAL_MODULES => [ +]; + +__PACKAGE__->NAME; diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm new file mode 100644 index 000000000..4b9a1d2fb --- /dev/null +++ b/extensions/BMO/Extension.pm @@ -0,0 +1,954 @@ +# -*- 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 BMO Bugzilla Extension. +# +# The Initial Developer of the Original Code is Gervase Markham. +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Gervase Markham <gerv@gerv.net> +# David Lawrence <dkl@mozilla.com> +# Byron Jones <glob@mozilla.com> + +package Bugzilla::Extension::BMO; +use strict; +use base qw(Bugzilla::Extension); + +use Bugzilla::Field; +use Bugzilla::Constants; +use Bugzilla::Status; +use Bugzilla::User; +use Bugzilla::User::Setting; +use Bugzilla::Util qw(html_quote trick_taint trim datetime_from detaint_natural); +use Bugzilla::Token; +use Bugzilla::Error; +use Bugzilla::Mailer; +use Bugzilla::Util; + +use Scalar::Util qw(blessed); +use Date::Parse; +use DateTime; +use Encode qw(find_encoding); + +use Bugzilla::Extension::BMO::Constants; +use Bugzilla::Extension::BMO::FakeBug; +use Bugzilla::Extension::BMO::Data qw($cf_visible_in_products + $cf_flags + $cf_project_flags + $cf_disabled_flags + %group_to_cc_map + $blocking_trusted_setters + $blocking_trusted_requesters + $status_trusted_wanters + $status_trusted_setters + $other_setters + %always_fileable_group + %product_sec_groups); +use Bugzilla::Extension::BMO::Reports qw(user_activity_report + triage_reports + group_admins_report + email_queue_report + release_tracking_report + group_membership_report); + +our $VERSION = '0.1'; + +# +# Monkey-patched methods +# + +BEGIN { + *Bugzilla::Bug::last_closed_date = \&_last_closed_date; +} + +sub template_before_process { + my ($self, $args) = @_; + my $file = $args->{'file'}; + my $vars = $args->{'vars'}; + + $vars->{'cf_hidden_in_product'} = \&cf_hidden_in_product; + $vars->{'cf_is_project_flag'} = \&cf_is_project_flag; + $vars->{'cf_flag_disabled'} = \&cf_flag_disabled; + + if ($file =~ /^list\/list/) { + # Purpose: enable correct sorting of list table + # Matched to changes in list/table.html.tmpl + my %db_order_column_name_map = ( + 'map_components.name' => 'component', + 'map_products.name' => 'product', + 'map_reporter.login_name' => 'reporter', + 'map_assigned_to.login_name' => 'assigned_to', + 'delta_ts' => 'opendate', + 'creation_ts' => 'changeddate', + ); + + my @orderstrings = split(/,\s*/, $vars->{'order'}); + + # contains field names of the columns being used to sort the table. + my @order_columns; + foreach my $o (@orderstrings) { + $o =~ s/bugs.//; + $o = $db_order_column_name_map{$o} if + grep($_ eq $o, keys(%db_order_column_name_map)); + next if (grep($_ eq $o, @order_columns)); + push(@order_columns, $o); + } + + $vars->{'order_columns'} = \@order_columns; + + # fields that have a custom sortkey. (So they are correctly sorted + # when using js) + my @sortkey_fields = qw(bug_status resolution bug_severity priority + rep_platform op_sys); + + my %columns_sortkey; + foreach my $field (@sortkey_fields) { + $columns_sortkey{$field} = _get_field_values_sort_key($field); + } + $columns_sortkey{'target_milestone'} = _get_field_values_sort_key('milestones'); + + $vars->{'columns_sortkey'} = \%columns_sortkey; + } + elsif ($file =~ /^bug\/create\/create[\.-]/) { + if (!$vars->{'cloned_bug_id'}) { + # Allow status whiteboard values to be bookmarked + $vars->{'status_whiteboard'} = + Bugzilla->cgi->param('status_whiteboard') || ""; + } + + # Purpose: for pretty product chooser + $vars->{'format'} = Bugzilla->cgi->param('format'); + + # Data needed for "this is a security bug" checkbox + $vars->{'sec_groups'} = \%product_sec_groups; + } + + + if ($file =~ /^list\/list/ || $file =~ /^bug\/create\/create[\.-]/) { + # hack to allow the bug entry templates to use check_can_change_field + # to see if various field values should be available to the current user. + $vars->{'default'} = Bugzilla::Extension::BMO::FakeBug->new($vars->{'default'} || {}); + } + + if ($file =~ /^attachment\/diff-header\./) { + my $attachid = $vars->{attachid} ? $vars->{attachid} : $vars->{newid}; + $vars->{attachment} = Bugzilla::Attachment->new($attachid) if $attachid; + } +} + +sub page_before_template { + my ($self, $args) = @_; + my $page = $args->{'page_id'}; + my $vars = $args->{'vars'}; + + if ($page eq 'user_activity.html') { + user_activity_report($vars); + + } elsif ($page eq 'triage_reports.html') { + triage_reports($vars); + + } elsif ($page eq 'upgrade-3.6.html') { + $vars->{'bzr_history'} = sub { + return `cd /data/www/bugzilla.mozilla.org; /usr/bin/bzr log -n0 -rlast:10..`; + }; + } + elsif ($page eq 'fields.html') { + # Recently global/field-descs.none.tmpl and bug/field-help.none.tmpl + # were changed for better performance and are now only loaded once. + # I have not found an easy way to allow our hook template to check if + # it is called from pages/fields.html.tmpl. So we set a value in request_cache + # that our hook template can see. + Bugzilla->request_cache->{'bmo_fields_page'} = 1; + } + elsif ($page eq 'group_admins.html') { + group_admins_report($vars); + } + elsif ($page eq 'group_membership.html' or $page eq 'group_membership.txt') { + group_membership_report($page, $vars); + } + elsif ($page eq 'email_queue.html') { + email_queue_report($vars); + } + elsif ($page eq 'release_tracking_report.html') { + release_tracking_report($vars); + } +} + +sub _get_field_values_sort_key { + my ($field) = @_; + my $dbh = Bugzilla->dbh; + my $fields = $dbh->selectall_arrayref( + "SELECT value, sortkey FROM $field + ORDER BY sortkey, value"); + + my %field_values; + foreach my $field (@$fields) { + my ($value, $sortkey) = @$field; + $field_values{$value} = $sortkey; + } + return \%field_values; +} + +sub active_custom_fields { + my ($self, $args) = @_; + my $fields = $args->{'fields'}; + my $params = $args->{'params'}; + my $product = $params->{'product'}; + my $component = $params->{'component'}; + + return if !$product; + + my $product_name = blessed $product ? $product->name : $product; + my $component_name = blessed $component ? $component->name : $component; + + my @tmp_fields; + foreach my $field (@$$fields) { + next if cf_hidden_in_product($field->name, $product_name, $component_name, $params->{'type'}); + push(@tmp_fields, $field); + } + $$fields = \@tmp_fields; +} + +sub cf_is_project_flag { + my ($field_name) = @_; + foreach my $flag_re (@$cf_project_flags) { + return 1 if $field_name =~ $flag_re; + } + return 0; +} + +sub cf_hidden_in_product { + my ($field_name, $product_name, $component_name, $custom_flag_mode) = @_; + + # If used in buglist.cgi, we pass in one_product which is a Bugzilla::Product + # elsewhere, we just pass the name of the product. + $product_name = blessed($product_name) ? $product_name->name + : $product_name; + + # Also in buglist.cgi, we pass in a list of components instead + # of a single compoent name everywhere else. + my $component_list = []; + if ($component_name) { + $component_list = ref $component_name ? $component_name + : [ $component_name ]; + } + + if ($custom_flag_mode) { + if ($custom_flag_mode == 1) { + # skip custom flags + foreach my $flag_re (@$cf_flags) { + return 1 if $field_name =~ $flag_re; + } + } elsif ($custom_flag_mode == 2) { + # custom flags only + my $found = 0; + foreach my $flag_re (@$cf_flags) { + if ($field_name =~ $flag_re) { + $found = 1; + last; + } + } + return 1 unless $found; + } + } + + foreach my $field_re (keys %$cf_visible_in_products) { + if ($field_name =~ $field_re) { + # If no product given, for example more than one product + # in buglist.cgi, then hide field by default + return 1 if !$product_name; + + my $products = $cf_visible_in_products->{$field_re}; + foreach my $product (keys %$products) { + my $components = $products->{$product}; + + my $found_component = 0; + if (@$components) { + foreach my $component (@$components) { + if (grep($_ eq $component, @$component_list)) { + $found_component = 1; + last; + } + } + } + + # If product matches and at at least one component matches + # from component_list (if a matching component was required), + # we allow the field to be seen + if ($product eq $product_name && (!@$components || $found_component)) { + return 0; + } + } + + return 1; + } + } + + return 0; +} + +sub cf_flag_disabled { + my ($field_name, $bug) = @_; + return 0 unless grep { $field_name eq $_ } @$cf_disabled_flags; + my $value = $bug->{$field_name}; + return $value eq '---' || $value eq ''; +} + +# Purpose: CC certain email addresses on bugmail when a bug is added or +# removed from a particular group. +sub bugmail_recipients { + my ($self, $args) = @_; + my $bug = $args->{'bug'}; + my $recipients = $args->{'recipients'}; + my $diffs = $args->{'diffs'}; + + if (@$diffs) { + # Changed bug + foreach my $ref (@$diffs) { + my $old = $ref->{old}; + my $new = $ref->{new}; + my $fieldname = $ref->{field_name}; + + if ($fieldname eq "bug_group") { + _cc_if_special_group($old, $recipients); + _cc_if_special_group($new, $recipients); + } + } + } else { + # Determine if it's a new bug, or a comment without a field change + my $comment_count = scalar @{$bug->comments}; + if ($comment_count == 1) { + # New bug + foreach my $group (@{ $bug->groups_in }) { + _cc_if_special_group($group->{'name'}, $recipients); + } + } + } +} + +sub _cc_if_special_group { + my ($group, $recipients) = @_; + + return if !$group; + + if ($group_to_cc_map{$group}) { + my $id = login_to_id($group_to_cc_map{$group}); + $recipients->{$id}->{+REL_CC} = Bugzilla::BugMail::BIT_DIRECT(); + } +} + +sub _check_trusted { + my ($field, $trusted, $priv_results) = @_; + + my $needed_group = $trusted->{'_default'} || ""; + foreach my $dfield (keys %$trusted) { + if ($field =~ $dfield) { + $needed_group = $trusted->{$dfield}; + } + } + if ($needed_group && !Bugzilla->user->in_group($needed_group)) { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } +} + +sub _is_field_set { + my $value = shift; + return $value ne '---' && $value ne '?'; +} + +sub bug_check_can_change_field { + my ($self, $args) = @_; + my $bug = $args->{'bug'}; + my $field = $args->{'field'}; + my $new_value = $args->{'new_value'}; + my $old_value = $args->{'old_value'}; + my $priv_results = $args->{'priv_results'}; + my $user = Bugzilla->user; + + # Only users in the appropriate drivers group can change the + # cf_blocking_* fields or cf_tracking_* fields + + if ($field =~ /^cf_(?:blocking|tracking)_/) { + # 0 -> 1 is used by show_bug, always allow so we skip this whole part + if (!($old_value eq '0' && $new_value eq '1')) { + # require privileged access to set a flag + if (_is_field_set($new_value)) { + _check_trusted($field, $blocking_trusted_setters, $priv_results); + } + + # require editbugs to clear or re-nominate a set flag + elsif (_is_field_set($old_value) + && !$user->in_group('editbugs', $bug->{'product_id'})) + { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } + } + + if ($new_value eq '?') { + _check_trusted($field, $blocking_trusted_requesters, $priv_results); + } + if ($user->id) { + push (@$priv_results, PRIVILEGES_REQUIRED_NONE); + } + + } elsif ($field =~ /^cf_status_/) { + # Only drivers can set wanted. + if ($new_value eq 'wanted') { + _check_trusted($field, $status_trusted_wanters, $priv_results); + } elsif (_is_field_set($new_value)) { + _check_trusted($field, $status_trusted_setters, $priv_results); + } + if ($user->id) { + push (@$priv_results, PRIVILEGES_REQUIRED_NONE); + } + + } elsif ($field =~ /^cf/ && !@$priv_results && $new_value ne '---') { + # "other" custom field setters restrictions + if (exists $other_setters->{$field}) { + my $in_group = 0; + foreach my $group (@{$other_setters->{$field}}) { + if ($user->in_group($group, $bug->product_id)) { + $in_group = 1; + last; + } + } + if (!$in_group) { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } + } + + } elsif ($field eq 'resolution' && $new_value eq 'EXPIRED') { + # The EXPIRED resolution should only be settable by gerv. + if ($user->login ne 'gerv@mozilla.org') { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } + + } elsif ($field eq 'resolution' && $new_value eq 'FIXED') { + # You need at least canconfirm to mark a bug as FIXED + if (!$user->in_group('canconfirm', $bug->{'product_id'})) { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } + + } elsif ( + ($field eq 'bug_status' && $old_value eq 'VERIFIED') + || ($field eq 'dup_id' && $bug->status->name eq 'VERIFIED') + || ($field eq 'resolution' && $bug->status->name eq 'VERIFIED') + ) { + # You need at least editbugs to reopen a resolved/verified bug + if (!$user->in_group('editbugs', $bug->{'product_id'})) { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } + + } elsif ($user->in_group('canconfirm', $bug->{'product_id'})) { + # Canconfirm is really "cantriage"; users with canconfirm can also mark + # bugs as DUPLICATE, WORKSFORME, and INCOMPLETE. + if ($field eq 'bug_status' + && is_open_state($old_value) + && !is_open_state($new_value)) + { + push (@$priv_results, PRIVILEGES_REQUIRED_NONE); + } + elsif ($field eq 'resolution' && + ($new_value eq 'DUPLICATE' || + $new_value eq 'WORKSFORME' || + $new_value eq 'INCOMPLETE')) + { + push (@$priv_results, PRIVILEGES_REQUIRED_NONE); + } + + } elsif ($field eq 'bug_status') { + # Disallow reopening of bugs which have been resolved for > 1 year + if (is_open_state($new_value) + && !is_open_state($old_value) + && $bug->resolution eq 'FIXED') + { + my $days_ago = DateTime->now(time_zone => Bugzilla->local_timezone); + $days_ago->subtract(days => 365); + my $last_closed = datetime_from($bug->last_closed_date); + if ($last_closed lt $days_ago) { + push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED); + } + } + } +} + +# Purpose: link up various Mozilla-specific strings. +sub _link_uuid { + my $args = shift; + my $match = html_quote($args->{matches}->[0]); + + return qq{<a href="https://crash-stats.mozilla.com/report/index/$match">bp-$match</a>}; +} + +sub _link_cve { + my $args = shift; + my $match = html_quote($args->{matches}->[0]); + + return qq{<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=$match">$match</a>}; +} + +sub _link_svn { + my $args = shift; + my $match = html_quote($args->{matches}->[0]); + + return qq{<a href="http://viewvc.svn.mozilla.org/vc?view=rev&revision=$match">r$match</a>}; +} + +sub _link_hg { + my $args = shift; + my $text = html_quote($args->{matches}->[0]); + my $repo = html_quote($args->{matches}->[1]); + my $id = html_quote($args->{matches}->[2]); + + return qq{<a href="https://hg.mozilla.org/$repo/rev/$id">$text</a>}; +} + +sub _link_bzr { + my $args = shift; + my $preamble = html_quote($args->{matches}->[0]); + my $url = html_quote($args->{matches}->[1]); + my $text = html_quote($args->{matches}->[2]); + my $id = html_quote($args->{matches}->[3]); + + $url =~ s/\s+$//; + $url =~ s/\/$//; + + return qq{$preamble<a href="http://$url/revision/$id">$text</a>}; +} + +sub bug_format_comment { + my ($self, $args) = @_; + my $regexes = $args->{'regexes'}; + + # Only match if not already in an URL using the negative lookbehind (?<!\/) + push (@$regexes, { + match => qr/(?<!\/)\b(?:UUID\s+|bp\-)([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\- + [a-f0-9]{4}\-[a-f0-9]{12})\b/x, + replace => \&_link_uuid + }); + + push (@$regexes, { + match => qr/(?<!\/)\b((?:CVE|CAN)-\d{4}-\d{4})\b/, + replace => \&_link_cve + }); + + push (@$regexes, { + match => qr/\br(\d{4,})\b/, + replace => \&_link_svn + }); + + push (@$regexes, { + match => qr/\b(Committing\sto:\sbzr\+ssh:\/\/ + (?:[^\@]+\@)?(bzr\.mozilla\.org[^\n]+)\n.*?\nCommitted\s) + (revision\s(\d+))/sx, + replace => \&_link_bzr + }); + + # Note: for grouping in this regexp, always use non-capturing parentheses. + my $hgrepos = join('|', qw!(?:releases/)?comm-[\w.]+ + (?:releases/)?mozilla-[\w.]+ + (?:releases/)?mobile-[\w.]+ + tracemonkey + tamarin-[\w.]+ + camino!); + + push (@$regexes, { + match => qr/\b(($hgrepos)\s+changeset:?\s+(?:\d+:)?([0-9a-fA-F]{12}))\b/, + replace => \&_link_hg + }); +} + +# Purpose: make it always possible to file bugs in certain groups. +sub bug_check_groups { + my ($self, $args) = @_; + my $group_names = $args->{'group_names'}; + my $add_groups = $args->{'add_groups'}; + + return unless $group_names; + $group_names = ref $group_names + ? $group_names + : [ map { trim($_) } split(',', $group_names) ]; + + foreach my $name (@$group_names) { + if (exists $always_fileable_group{$name}) { + my $group = new Bugzilla::Group({ name => $name }) or next; + $add_groups->{$group->id} = $group; + } + } +} + +# Purpose: generically handle generating pretty blocking/status "flags" from +# custom field names. +sub quicksearch_map { + my ($self, $args) = @_; + my $map = $args->{'map'}; + + foreach my $name (keys %$map) { + if ($name =~ /^cf_(blocking|tracking|status)_([a-z]+)?(\d+)?$/) { + my $type = $1; + my $product = $2; + my $version = $3; + + if ($version) { + $version = join('.', split(//, $version)); + } + + my $pretty_name = $type; + if ($product) { + $pretty_name .= "-" . $product; + } + if ($version) { + $pretty_name .= $version; + } + + $map->{$pretty_name} = $name; + } + elsif ($name =~ /cf_crash_signature$/) { + $map->{'sig'} = $name; + } + } +} + +# Restrict content types attachable by non-privileged people +my @mimetype_whitelist = ('^image\/', 'application\/pdf'); + +sub object_end_of_create_validators { + my ($self, $args) = @_; + my $class = $args->{'class'}; + + if ($class->isa('Bugzilla::Attachment')) { + my $params = $args->{'params'}; + my $bug = $params->{'bug'}; + if (!Bugzilla->user->in_group('editbugs', $bug->product_id)) { + my $mimetype = $params->{'mimetype'}; + if (!grep { $mimetype =~ /$_/ } @mimetype_whitelist ) { + # Need to neuter MIME type to something non-executable + if ($mimetype =~ /^text\//) { + $params->{'mimetype'} = "text/plain"; + } + else { + $params->{'mimetype'} = "application/octet-stream"; + } + } + } + } +} + +sub install_before_final_checks { + my ($self, $args) = @_; + + # Add product chooser setting (although it was added long ago, so add_setting + # will just return every time). + add_setting('product_chooser', + ['pretty_product_chooser', 'full_product_chooser'], + 'pretty_product_chooser'); + + # Migrate from 'gmail_threading' setting to 'bugmail_new_prefix' + my $dbh = Bugzilla->dbh; + if ($dbh->selectrow_array("SELECT 1 FROM setting WHERE name='gmail_threading'")) { + $dbh->bz_start_transaction(); + $dbh->do("UPDATE profile_setting + SET setting_value='on-temp' + WHERE setting_name='gmail_threading' AND setting_value='Off'"); + $dbh->do("UPDATE profile_setting + SET setting_value='off' + WHERE setting_name='gmail_threading' AND setting_value='On'"); + $dbh->do("UPDATE profile_setting + SET setting_value='on' + WHERE setting_name='gmail_threading' AND setting_value='on-temp'"); + $dbh->do("UPDATE profile_setting + SET setting_name='bugmail_new_prefix' + WHERE setting_name='gmail_threading'"); + $dbh->do("DELETE FROM setting WHERE name='gmail_threading'"); + $dbh->bz_commit_transaction(); + } +} + +# Migrate old is_active stuff to new patch (is in core in 4.2), The old column +# name was 'is_active', the new one is 'isactive' (no underscore). +sub install_update_db { + my $dbh = Bugzilla->dbh; + + if ($dbh->bz_column_info('milestones', 'is_active')) { + $dbh->do("UPDATE milestones SET isactive = 0 WHERE is_active = 0;"); + $dbh->bz_drop_column('milestones', 'is_active'); + $dbh->bz_drop_column('milestones', 'is_searchable'); + } +} + +sub _last_closed_date { + my ($self) = @_; + my $dbh = Bugzilla->dbh; + + return $self->{'last_closed_date'} if defined $self->{'last_closed_date'}; + + my $closed_statuses = "'" . join("','", map { $_->name } closed_bug_statuses()) . "'"; + my $status_field_id = get_field_id('bug_status'); + + $self->{'last_closed_date'} = $dbh->selectrow_array(" + SELECT bugs_activity.bug_when + FROM bugs_activity + WHERE bugs_activity.fieldid = ? + AND bugs_activity.added IN ($closed_statuses) + AND bugs_activity.bug_id = ? + ORDER BY bugs_activity.bug_when DESC " . $dbh->sql_limit(1), + undef, $status_field_id, $self->id + ); + + return $self->{'last_closed_date'}; +} + +sub field_end_of_create { + my ($self, $args) = @_; + my $field = $args->{'field'}; + + # email mozilla's DBAs so they can update the grants for metrics + # this really should create a bug in mozilla.org/Server Operations: Database + + if (Bugzilla->params->{'urlbase'} ne 'https://bugzilla.mozilla.org/') { + return; + } + + if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { + print "Emailing notification to infra-dbnotices\@mozilla.com\n"; + } + + my $name = $field->name; + my @message; + push @message, 'To: infra-dbnotices@mozilla.com'; + push @message, "Subject: custom field '$name' added to bugzilla.mozilla.org"; + push @message, 'From: ' . Bugzilla->params->{mailfrom}; + push @message, ''; + push @message, "The custom field '$name' has been added to the BMO database."; + push @message, ''; + push @message, 'Please run the following on tm-bugs01-master01:'; + push @message, " GRANT SELECT ON `bugs`.`$name` TO 'metrics'\@'10.2.70.20_';"; + push @message, " GRANT SELECT ($name) ON `bugs`.`bugs` TO 'metrics'\@'10.2.70.20_';"; + push @message, ''; + MessageToMTA(join("\n", @message)); +} + +sub webservice { + my ($self, $args) = @_; + + my $dispatch = $args->{dispatch}; + $dispatch->{BMO} = "Bugzilla::Extension::BMO::WebService"; +} + +our $search_content_matches; +BEGIN { + $search_content_matches = \&Bugzilla::Search::_content_matches; +} + +sub search_operator_field_override { + my ($self, $args) = @_; + my $search = $args->{'search'}; + my $operators = $args->{'operators'}; + + my $cgi = Bugzilla->cgi; + my @comments = $cgi->param('comments'); + my $exclude_comments = scalar(@comments) && !grep { $_ eq '1' } @comments; + + if ($cgi->param('query_format') + && $cgi->param('query_format') eq 'specific' + && $exclude_comments + ) { + # use the non-comment operator + $operators->{'content'}->{matches} = \&_short_desc_matches; + $operators->{'content'}->{notmatches} = \&_short_desc_matches; + + } else { + # restore default content operator + $operators->{'content'}->{matches} = $search_content_matches; + $operators->{'content'}->{notmatches} = $search_content_matches; + } +} + +sub _short_desc_matches { + # copy of Bugzilla::Search::_content_matches + + my $self = shift; + my %func_args = @_; + my ($chartid, $supptables, $term, $groupby, $fields, $t, $v) = + @func_args{qw(chartid supptables term groupby fields t v)}; + my $dbh = Bugzilla->dbh; + + # Add the fulltext table to the query so we can search on it. + my $table = "bugs_fulltext_$$chartid"; + push(@$supptables, "LEFT JOIN bugs_fulltext AS $table " . + "ON bugs.bug_id = $table.bug_id"); + + # Create search terms to add to the SELECT and WHERE clauses. + my ($term1, $rterm1) = $dbh->sql_fulltext_search("$table.short_desc", $$v, 1); + $rterm1 = $term1 if !$rterm1; + + # The term to use in the WHERE clause. + $$term = $term1; + if ($$t =~ /not/i) { + $$term = "NOT($$term)"; + } + + my $current = Bugzilla::Search::COLUMNS->{'relevance'}->{name}; + $current = $current ? "$current + " : ''; + # For NOT searches, we just add 0 to the relevance. + my $select_term = $$t =~ /not/ ? 0 : "($current$rterm1)"; + Bugzilla::Search::COLUMNS->{'relevance'}->{name} = $select_term; +} + +sub mailer_before_send { + my ($self, $args) = @_; + my $email = $args->{email}; + + # If email is a request for a review, add the attachment itself + # to the email as an attachment. Attachment must be content type + # text/plain and below a certain size. Otherwise the email already + # contain a link to the attachment. + if ($email + && $email->header('X-Bugzilla-Type') eq 'request' + && ($email->header('X-Bugzilla-Flag-Requestee') + && $email->header('X-Bugzilla-Flag-Requestee') eq $email->header('to'))) + { + my $body = $email->body; + + if (my ($attach_id) = $body =~ /Attachment\s+(\d+)\s*:/) { + my $attachment = Bugzilla::Attachment->new($attach_id); + if ($attachment + && $attachment->ispatch + && $attachment->contenttype eq 'text/plain' + && $attachment->linecount + && $attachment->linecount < REQUEST_MAX_ATTACH_LINES) + { + # Don't send a charset header with attachments, as they might + # not be UTF-8, unless we can properly detect it. + my $charset; + if (Bugzilla->feature('detect_charset')) { + my $encoding = detect_encoding($attachment->data); + if ($encoding) { + $charset = find_encoding($encoding)->mime_name; + } + } + + my $attachment_part = Email::MIME->create( + attributes => { + content_type => $attachment->contenttype, + filename => $attachment->filename, + disposition => "attachment", + }, + body => $attachment->data, + ); + $attachment_part->charset_set($charset) if $charset; + + $email->parts_add([ $attachment_part ]); + } + } + } +} + +sub post_bug_after_creation { + my ($self, $args) = @_; + my $vars = $args->{vars}; + my $bug = $vars->{bug}; + + if (Bugzilla->input_params->{format} + && Bugzilla->input_params->{format} eq 'employee-incident' + && $bug->component eq 'Server Operations: Desktop Issues') + { + my $error_mode_cache = Bugzilla->error_mode; + Bugzilla->error_mode(ERROR_MODE_DIE); + + my $template = Bugzilla->template; + my $cgi = Bugzilla->cgi; + + my ($investigate_bug, $ssh_key_bug); + my $old_user = Bugzilla->user; + eval { + Bugzilla->set_user(Bugzilla::User->new({ name => 'nobody@mozilla.org' })); + my $new_user = Bugzilla->user; + + # HACK: User needs to be in the editbugs and primary bug's group to allow + # setting of dependencies. + $new_user->{'groups'} = [ Bugzilla::Group->new({ name => 'editbugs' }), + Bugzilla::Group->new({ name => 'infra' }), + Bugzilla::Group->new({ name => 'infrasec' }) ]; + + my $recipients = { changer => $new_user }; + $vars->{original_reporter} = $old_user; + + my $comment; + $cgi->param('display_action', ''); + $template->process('bug/create/comment-employee-incident.txt.tmpl', $vars, \$comment) + || ThrowTemplateError($template->error()); + + $investigate_bug = Bugzilla::Bug->create({ + short_desc => 'Investigate Lost Device', + product => 'mozilla.org', + component => 'Security Assurance: Incident', + status_whiteboard => '[infrasec:incident]', + bug_severity => 'critical', + cc => [ 'mcoates@mozilla.com', 'jstevensen@mozilla.com' ], + groups => [ 'infrasec' ], + comment => $comment, + op_sys => 'All', + rep_platform => 'All', + version => 'other', + dependson => $bug->bug_id, + }); + $bug->set_all({ blocked => { add => [ $investigate_bug->bug_id ] }}); + Bugzilla::BugMail::Send($investigate_bug->id, $recipients); + + Bugzilla->set_user($old_user); + $vars->{original_reporter} = ''; + $comment = ''; + $cgi->param('display_action', 'ssh'); + $template->process('bug/create/comment-employee-incident.txt.tmpl', $vars, \$comment) + || ThrowTemplateError($template->error()); + + $ssh_key_bug = Bugzilla::Bug->create({ + short_desc => 'Disable/Regenerate SSH Key', + product => $bug->product, + component => $bug->component, + bug_severity => 'critical', + cc => $bug->cc, + groups => [ map { $_->{name} } @{ $bug->groups } ], + comment => $comment, + op_sys => 'All', + rep_platform => 'All', + version => 'other', + dependson => $bug->bug_id, + }); + $bug->set_all({ blocked => { add => [ $ssh_key_bug->bug_id ] }}); + Bugzilla::BugMail::Send($ssh_key_bug->id, $recipients); + }; + my $error = $@; + + Bugzilla->set_user($old_user); + Bugzilla->error_mode($error_mode_cache); + + if ($error || !$investigate_bug || !$ssh_key_bug) { + warn "Failed to create additional employee-incident bug: $error" if $error; + $vars->{'message'} = 'employee_incident_creation_failed'; + } + } +} + +sub buglist_columns { + my ($self, $args) = @_; + my $columns = $args->{columns}; + $columns->{'cc_count'} = { + name => '(SELECT COUNT(*) FROM cc WHERE cc.bug_id = bugs.bug_id)', + title => 'CC Count', + }; +} + +__PACKAGE__->NAME; diff --git a/extensions/BMO/lib/Constants.pm b/extensions/BMO/lib/Constants.pm new file mode 100644 index 000000000..23eaae9cb --- /dev/null +++ b/extensions/BMO/lib/Constants.pm @@ -0,0 +1,33 @@ +# -*- 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 BMO Bugzilla Extension. +# +# The Initial Developer of the Original Code is the Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2007 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# David Lawrence <dkl@mozilla.com> + +package Bugzilla::Extension::BMO::Constants; +use strict; +use base qw(Exporter); +our @EXPORT = qw( + REQUEST_MAX_ATTACH_LINES +); + +# Maximum attachment size in lines that will be sent with a +# requested attachment flag notification. +use constant REQUEST_MAX_ATTACH_LINES => 1000; + +1; diff --git a/extensions/BMO/lib/Data.pm b/extensions/BMO/lib/Data.pm new file mode 100644 index 000000000..b9cb8b385 --- /dev/null +++ b/extensions/BMO/lib/Data.pm @@ -0,0 +1,353 @@ +# -*- 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 BMO Bugzilla Extension. +# +# The Initial Developer of the Original Code is the Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Gervase Markham <gerv@gerv.net> +# Reed Loden <reed@reedloden.com> + +package Bugzilla::Extension::BMO::Data; +use strict; + +use base qw(Exporter); +use Tie::IxHash; + +our @EXPORT_OK = qw($cf_visible_in_products + $cf_flags $cf_project_flags + $cf_disabled_flags + %group_to_cc_map + $blocking_trusted_setters + $blocking_trusted_requesters + $status_trusted_wanters + $status_trusted_setters + $other_setters + %always_fileable_group + %product_sec_groups); + +# Which custom fields are visible in which products and components. +# +# By default, custom fields are visible in all products. However, if the name +# of the field matches any of these regexps, it is only visible if the +# product (and component if necessary) is a member of the attached hash. [] +# for component means "all". +# +# IxHash keeps them in insertion order, and so we get regexp priorities right. +our $cf_visible_in_products; +tie(%$cf_visible_in_products, "Tie::IxHash", + qw/^cf_blocking_kilimanjaro/ => { + "Boot2Gecko" => [], + "Core" => [], + "Fennec" => [], + "Fennec Native" => [], + "Firefox" => [], + "Marketplace" => [], + "mozilla.org" => [], + "Mozilla Services" => [], + "NSPR" => [], + "NSS" => [], + "Testing" => [], + "Thunderbird" => [], + "Toolkit" => [], + "Tracking" => [], + "Web Apps" => [], + }, + qr/^cf_blocking_fennec/ => { + "addons.mozilla.org" => [], + "AUS" => [], + "Core" => [], + "Fennec" => [], + "Fennec Native" => [], + "Marketing" => ["General"], + "mozilla.org" => ["Release Engineering"], + "Mozilla Localizations" => [], + "Mozilla Services" => [], + "NSPR" => [], + "support.mozilla.com" => [], + "Toolkit" => [], + "Tech Evangelism" => [], + "Testing" => ["General"], + }, + qr/^cf_tracking_thunderbird|cf_blocking_thunderbird|cf_status_thunderbird/ => { + "support.mozillamessaging.com" => [], + "Thunderbird" => [], + "MailNews Core" => [], + "Mozilla Messaging" => [], + "Websites" => ["www.mozillamessaging.com"], + }, + qr/^(cf_(blocking|tracking)_seamonkey|cf_status_seamonkey)/ => { + "Composer" => [], + "MailNews Core" => [], + "Mozilla Localizations" => [], + "Other Applications" => [], + "SeaMonkey" => [], + }, + qr/^cf_blocking_|cf_tracking_|cf_status/ => { + "Add-on SDK" => [], + "addons.mozilla.org" => [], + "AUS" => [], + "Core Graveyard" => [], + "Core" => [], + "Directory" => [], + "Fennec" => [], + "Fennec Native" => [], + "Firefox" => [], + "MailNews Core" => [], + "mozilla.org" => ["Release Engineering"], + "Mozilla QA" => ["Mozmill Tests"], + "Mozilla Localizations" => [], + "Mozilla Services" => [], + "NSPR" => [], + "NSS" => [], + "Other Applications" => [], + "SeaMonkey" => [], + "Socorro" => [], + "support.mozilla.com" => [], + "Tech Evangelism" => [], + "Testing" => [], + "Toolkit" => [], + "Websites" => ["getpersonas.com"], + "Webtools" => [], + "Plugins" => [], + }, + qr/^cf_colo_site$/ => { + "mozilla.org" => [ + "Server Operations", + "Server Operations: Projects", + "Server Operations: RelEng", + "Server Operations: Security", + ], + }, + qw/^cf_office$/ => { + "mozilla.org" => ["Server Operations: Desktop Issues"], + }, + qr/^cf_crash_signature$/ => { + "addons.mozilla.org" => [], + "Add-on SDK" => [], + "Calendar" => [], + "Camino" => [], + "Composer" => [], + "Fennec" => [], + "Fennec Native" => [], + "Firefox" => [], + "Mozilla Localizations" => [], + "Mozilla Services" => [], + "Other Applications" => [], + "Penelope" => [], + "SeaMonkey" => [], + "Thunderbird" => [], + "Core" => [], + "Directory" => [], + "JSS" => [], + "MailNews Core" => [], + "NSPR" => [], + "NSS" => [], + "Plugins" => [], + "Rhino" => [], + "Tamarin" => [], + "Testing" => [], + "Toolkit" => [], + "Mozilla Labs" => [], + "mozilla.org" => [], + "Tech Evangelism" => [], + }, + qw/^cf_due_date$/ => { + "Mozilla Reps" => [], + "mozilla.org" => ["Security Assurance: Review Request"], + }, +); + +# Which custom fields are acting as flags (ie. custom flags) +our $cf_flags = [ + qr/^cf_(?:blocking|tracking|status)_/, +]; + +our $cf_project_flags = [ + qr/^cf_blocking_kilimanjaro/, +]; + +# List of disabled fields. +# Temp kludge until custom fields can be disabled correctly upstream. +# Disabled fields are hidden unless they have a value set +our $cf_disabled_flags = [ + 'cf_blocking_20', + 'cf_status_20', + 'cf_tracking_firefox5', + 'cf_status_firefox5', + 'cf_blocking_thunderbird32', + 'cf_status_thunderbird32', + 'cf_blocking_thunderbird30', + 'cf_status_thunderbird30', + 'cf_blocking_seamonkey21', + 'cf_status_seamonkey21', + 'cf_tracking_seamonkey22', + 'cf_status_seamonkey22', + 'cf_tracking_firefox6', + 'cf_status_firefox6', + 'cf_tracking_thunderbird6', + 'cf_status_thunderbird6', + 'cf_tracking_seamonkey23', + 'cf_status_seamonkey23', + 'cf_tracking_firefox7', + 'cf_status_firefox7', + 'cf_tracking_thunderbird7', + 'cf_status_thunderbird7', + 'cf_tracking_seamonkey24', + 'cf_status_seamonkey24', + 'cf_tracking_firefox8', + 'cf_status_firefox8', + 'cf_tracking_thunderbird8', + 'cf_status_thunderbird8', + 'cf_tracking_seamonkey25', + 'cf_status_seamonkey25', + 'cf_blocking_191', + 'cf_status_191', + 'cf_blocking_thunderbird33', + 'cf_status_thunderbird33', + 'cf_tracking_firefox9', + 'cf_status_firefox9', + 'cf_tracking_thunderbird9', + 'cf_status_thunderbird9', + 'cf_tracking_seamonkey26', + 'cf_status_seamonkey26', + 'cf_tracking_firefox10', + 'cf_status_firefox10', + 'cf_tracking_thunderbird10', + 'cf_status_thunderbird10', + 'cf_tracking_seamonkey27', + 'cf_status_seamonkey27', + 'cf_tracking_firefox11', + 'cf_status_firefox11', + 'cf_tracking_thunderbird11', + 'cf_status_thunderbird11', + 'cf_tracking_seamonkey28', + 'cf_status_seamonkey28', +]; + +# Who to CC on particular bugmails when certain groups are added or removed. +our %group_to_cc_map = ( + 'addons-security' => 'amo-editors@mozilla.org', + 'bugzilla-security' => 'security@bugzilla.org', + 'client-services-security' => 'amo-admins@mozilla.org', + 'core-security' => 'security@mozilla.org', + 'tamarin-security' => 'tamarinsecurity@adobe.com', + 'websites-security' => 'website-drivers@mozilla.org', + 'webtools-security' => 'webtools-security@mozilla.org', +); + +# Only users in certain groups can change certain custom fields in +# certain ways. +# +# Who can set cf_blocking_* or cf_tracking_* to +/- +our $blocking_trusted_setters = { + 'cf_blocking_fennec' => 'fennec-drivers', + 'cf_blocking_20' => 'mozilla-next-drivers', + qr/^cf_tracking_firefox/ => 'mozilla-next-drivers', + qr/^cf_blocking_thunderbird/ => 'thunderbird-drivers', + qr/^cf_tracking_thunderbird/ => 'thunderbird-drivers', + qr/^cf_tracking_seamonkey/ => 'seamonkey-council', + qr/^cf_blocking_seamonkey/ => 'seamonkey-council', + qr/^cf_blocking_kilimanjaro/ => 'kilimanjaro-drivers', + '_default' => 'mozilla-stable-branch-drivers', +}; + +# Who can request cf_blocking_* or cf_tracking_* +our $blocking_trusted_requesters = { + qr/^cf_blocking_thunderbird/ => 'thunderbird-trusted-requesters', + '_default' => 'everyone', +}; + +# Who can set cf_status_* to "wanted"? +our $status_trusted_wanters = { + 'cf_status_20' => 'mozilla-next-drivers', + qr/^cf_status_thunderbird/ => 'thunderbird-drivers', + qr/^cf_status_seamonkey/ => 'seamonkey-council', + '_default' => 'mozilla-stable-branch-drivers', +}; + +# Who can set cf_status_* to values other than "wanted"? +our $status_trusted_setters = { + qr/^cf_status_thunderbird/ => 'editbugs', + '_default' => 'canconfirm', +}; + +# Who can set other custom flags (use full field names only, not regex's) +our $other_setters = { + 'cf_colo_site' => ['infra', 'build'], +}; + +# Groups in which you can always file a bug, whoever you are. +our %always_fileable_group = ( + 'addons-security' => 1, + 'bugzilla-security' => 1, + 'client-services-security' => 1, + 'consulting' => 1, + 'core-security' => 1, + 'infra' => 1, + 'infrasec' => 1, + 'marketing-private' => 1, + 'mozilla-confidential' => 1, + 'mozilla-corporation-confidential' => 1, + 'mozilla-foundation-confidential' => 1, + 'mozilla-messaging-confidential' => 1, + 'partner-confidential' => 1, + 'payments-confidential' => 1, + 'tamarin-security' => 1, + 'websites-security' => 1, + 'webtools-security' => 1, +); + +# Mapping of products to their security bits +our %product_sec_groups = ( + "addons.mozilla.org" => 'client-services-security', + "AUS" => 'client-services-security', + "Bugzilla" => 'bugzilla-security', + "bugzilla.mozilla.org" => 'bugzilla-security', + "Community Tools" => 'websites-security', + "Legal" => 'legal', + "Marketing" => 'marketing-private', + "Mozilla Corporation" => 'mozilla-corporation-confidential', + "Mozilla Developer Network" => 'websites-security', + "Mozilla Grants" => 'grants', + "Mozilla Messaging" => 'mozilla-messaging-confidential', + "Mozilla Metrics" => 'metrics-private', + "mozilla.org" => 'mozilla-confidential', + "Mozilla PR" => 'pr-private', + "Mozilla QA" => 'mozilla-corporation-confidential', + "Mozilla Reps" => 'mozilla-reps', + "Mozilla Services" => 'mozilla-services-security', + "mozillaignite" => 'websites-security', + "quality.mozilla.org" => 'websites-security', + "Skywriter" => 'websites-security', + "Socorro" => 'client-services-security', + "support.mozilla.com" => 'websites-security', + "support.mozillamessaging.com" => 'websites-security', + "Talkback" => 'talkback-private', + "Tamarin" => 'tamarin-security', + "Testopia" => 'bugzilla-security', + "Web Apps" => 'webtools-security', + "webmaker.org" => 'websites-security', + "Webpagemaker" => 'websites-security', + "Websites" => 'websites-security', + "Websites Graveyard" => 'websites-security', + "Webtools" => 'webtools-security', + "_default" => 'core-security' +); + +# Default security groups for products should always been fileable +map { $always_fileable_group{$_} = 1 } values %product_sec_groups; + +1; diff --git a/extensions/BMO/lib/FakeBug.pm b/extensions/BMO/lib/FakeBug.pm new file mode 100644 index 000000000..6127cb560 --- /dev/null +++ b/extensions/BMO/lib/FakeBug.pm @@ -0,0 +1,42 @@ +package Bugzilla::Extension::BMO::FakeBug; + +# hack to allow the bug entry templates to use check_can_change_field to see if +# various field values should be available to the current user + +use strict; + +use Bugzilla::Bug; + +our $AUTOLOAD; + +sub new { + my $class = shift; + my $self = shift; + bless $self, $class; + return $self; +} + +sub AUTOLOAD { + my $self = shift; + my $name = $AUTOLOAD; + $name =~ s/.*://; + return exists $self->{$name} ? $self->{$name} : undef; +} + +sub check_can_change_field { + my $self = shift; + return Bugzilla::Bug::check_can_change_field($self, @_) +} + +sub _changes_everconfirmed { + my $self = shift; + return Bugzilla::Bug::_changes_everconfirmed($self, @_) +} + +sub everconfirmed { + my $self = shift; + return ($self->{'status'} == 'UNCONFIRMED') ? 0 : 1; +} + +1; + diff --git a/extensions/BMO/lib/Reports.pm b/extensions/BMO/lib/Reports.pm new file mode 100644 index 000000000..a06d796b5 --- /dev/null +++ b/extensions/BMO/lib/Reports.pm @@ -0,0 +1,1056 @@ +# 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::BMO::Reports; +use strict; + +use Bugzilla::Extension::BMO::Data qw($cf_disabled_flags); + +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::Field; +use Bugzilla::User; +use Bugzilla::Util qw(trim detaint_natural trick_taint correct_urlbase); + +use Date::Parse; +use DateTime; +use JSON qw(-convert_blessed_universally); +use List::MoreUtils qw(uniq); + +use base qw(Exporter); + +our @EXPORT_OK = qw(user_activity_report + triage_reports + group_admins_report + email_queue_report + release_tracking_report + group_membership_report); + +sub user_activity_report { + my ($vars) = @_; + my $dbh = Bugzilla->dbh; + my $input = Bugzilla->input_params; + + my @who = (); + my $from = trim($input->{'from'} || ''); + my $to = trim($input->{'to'} || ''); + my $action = $input->{'action'} || ''; + + # fix non-breaking hyphens + $from =~ s/\N{U+2011}/-/g; + $to =~ s/\N{U+2011}/-/g; + + if ($from eq '') { + my $dt = DateTime->now()->subtract('weeks' => 8); + $from = $dt->ymd('-'); + } + if ($to eq '') { + my $dt = DateTime->now(); + $to = $dt->ymd('-'); + } + + if ($action eq 'run') { + if ($input->{'who'} eq '') { + ThrowUserError('user_activity_missing_username'); + } + Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} }); + + my $from_dt = _string_to_datetime($from); + $from = $from_dt->ymd(); + + my $to_dt = _string_to_datetime($to); + $to = $to_dt->ymd(); + # add one day to include all activity that happened on the 'to' date + $to_dt->add(days => 1); + + my ($activity_joins, $activity_where) = ('', ''); + my ($attachments_joins, $attachments_where) = ('', ''); + if (Bugzilla->params->{"insidergroup"} + && !Bugzilla->user->in_group(Bugzilla->params->{'insidergroup'})) + { + $activity_joins = "LEFT JOIN attachments + ON attachments.attach_id = bugs_activity.attach_id"; + $activity_where = "AND COALESCE(attachments.isprivate, 0) = 0"; + $attachments_where = $activity_where; + } + + my @who_bits; + foreach my $who ( + ref $input->{'who'} + ? @{$input->{'who'}} + : $input->{'who'} + ) { + push @who, $who; + push @who_bits, '?'; + } + my $who_bits = join(',', @who_bits); + + if (!@who) { + my $template = Bugzilla->template; + my $cgi = Bugzilla->cgi; + my $vars = {}; + $vars->{'script'} = $cgi->url(-relative => 1); + $vars->{'fields'} = {}; + $vars->{'matches'} = []; + $vars->{'matchsuccess'} = 0; + $vars->{'matchmultiple'} = 1; + print $cgi->header(); + $template->process("global/confirm-user-match.html.tmpl", $vars) + || ThrowTemplateError($template->error()); + exit; + } + + $from_dt = $from_dt->ymd() . ' 00:00:00'; + $to_dt = $to_dt->ymd() . ' 23:59:59'; + my @params; + for (1..4) { + push @params, @who; + push @params, ($from_dt, $to_dt); + } + + my $order = ($input->{'sort'} && $input->{'sort'} eq 'bug') + ? 'bug_id, bug_when' : 'bug_when'; + + my $comment_filter = ''; + if (!Bugzilla->user->is_insider) { + $comment_filter = 'AND longdescs.isprivate = 0'; + } + + my $query = " + SELECT + fielddefs.name, + bugs_activity.bug_id, + bugs_activity.attach_id, + ".$dbh->sql_date_format('bugs_activity.bug_when', '%Y.%m.%d %H:%i:%s')." AS ts, + bugs_activity.removed, + bugs_activity.added, + profiles.login_name, + bugs_activity.comment_id, + bugs_activity.bug_when + FROM bugs_activity + $activity_joins + LEFT JOIN fielddefs + ON bugs_activity.fieldid = fielddefs.id + INNER JOIN profiles + ON profiles.userid = bugs_activity.who + WHERE profiles.login_name IN ($who_bits) + AND bugs_activity.bug_when >= ? AND bugs_activity.bug_when <= ? + $activity_where + + UNION ALL + + SELECT + 'bug_id' AS name, + bugs.bug_id, + NULL AS attach_id, + ".$dbh->sql_date_format('bugs.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts, + '(new bug)' AS removed, + bugs.short_desc AS added, + profiles.login_name, + NULL AS comment_id, + bugs.creation_ts AS bug_when + FROM bugs + INNER JOIN profiles + ON profiles.userid = bugs.reporter + WHERE profiles.login_name IN ($who_bits) + AND bugs.creation_ts >= ? AND bugs.creation_ts <= ? + + UNION ALL + + SELECT + 'longdesc' AS name, + longdescs.bug_id, + NULL AS attach_id, + DATE_FORMAT(longdescs.bug_when, '%Y.%m.%d %H:%i:%s') AS ts, + '' AS removed, + '' AS added, + profiles.login_name, + longdescs.comment_id AS comment_id, + longdescs.bug_when + FROM longdescs + INNER JOIN profiles + ON profiles.userid = longdescs.who + WHERE profiles.login_name IN ($who_bits) + AND longdescs.bug_when >= ? AND longdescs.bug_when <= ? + $comment_filter + + UNION ALL + + SELECT + 'attachments.description' AS name, + attachments.bug_id, + attachments.attach_id, + ".$dbh->sql_date_format('attachments.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts, + '(new attachment)' AS removed, + attachments.description AS added, + profiles.login_name, + NULL AS comment_id, + attachments.creation_ts AS bug_when + FROM attachments + INNER JOIN profiles + ON profiles.userid = attachments.submitter_id + WHERE profiles.login_name IN ($who_bits) + AND attachments.creation_ts >= ? AND attachments.creation_ts <= ? + $attachments_where + + ORDER BY $order "; + + my $list = $dbh->selectall_arrayref($query, undef, @params); + + my @operations; + my $operation = {}; + my $changes = []; + my $incomplete_data = 0; + my %bug_ids; + + foreach my $entry (@$list) { + my ($fieldname, $bugid, $attachid, $when, $removed, $added, $who, + $comment_id) = @$entry; + my %change; + my $activity_visible = 1; + + next unless Bugzilla->user->can_see_bug($bugid); + + # check if the user should see this field's activity + if ($fieldname eq 'remaining_time' + || $fieldname eq 'estimated_time' + || $fieldname eq 'work_time' + || $fieldname eq 'deadline') + { + $activity_visible = Bugzilla->user->is_timetracker; + } + elsif ($fieldname eq 'longdescs.isprivate' + && !Bugzilla->user->is_insider + && $added) + { + $activity_visible = 0; + } + else { + $activity_visible = 1; + } + + if ($activity_visible) { + # Check for the results of an old Bugzilla data corruption bug + if (($added eq '?' && $removed eq '?') + || ($added =~ /^\? / || $removed =~ /^\? /)) { + $incomplete_data = 1; + } + + # Start a new changeset if required (depends on the sort order) + my $is_new_changeset; + if ($order eq 'bug_when') { + $is_new_changeset = + $operation->{'who'} && + ($who ne $operation->{'who'} || $when ne $operation->{'when'}); + } else { + $is_new_changeset = + $operation->{'bug'} && + $bugid != $operation->{'bug'}; + } + if ($is_new_changeset) { + $operation->{'changes'} = $changes; + push (@operations, $operation); + $operation = {}; + $changes = []; + } + + $bug_ids{$bugid} = 1; + + $operation->{'bug'} = $bugid; + $operation->{'who'} = $who; + $operation->{'when'} = $when; + + $change{'fieldname'} = $fieldname; + $change{'attachid'} = $attachid; + $change{'removed'} = $removed; + $change{'added'} = $added; + $change{'when'} = $when; + + if ($comment_id) { + $change{'comment'} = Bugzilla::Comment->new($comment_id); + next if $change{'comment'}->count == 0; + } + + if ($attachid) { + $change{'attach'} = Bugzilla::Attachment->new($attachid); + } + + push (@$changes, \%change); + } + } + + if ($operation->{'who'}) { + $operation->{'changes'} = $changes; + push (@operations, $operation); + } + + $vars->{'incomplete_data'} = $incomplete_data; + $vars->{'operations'} = \@operations; + + my @bug_ids = sort { $a <=> $b } keys %bug_ids; + $vars->{'bug_ids'} = \@bug_ids; + } + + $vars->{'action'} = $action; + $vars->{'who'} = join(',', @who); + $vars->{'who_count'} = scalar @who; + $vars->{'from'} = $from; + $vars->{'to'} = $to; + $vars->{'sort'} = $input->{'sort'}; +} + +sub _string_to_datetime { + my $input = shift; + my $time = _parse_date($input) + or ThrowUserError('report_invalid_date', { date => $input }); + return _time_to_datetime($time); +} + +sub _time_to_datetime { + my $time = shift; + return DateTime->from_epoch(epoch => $time) + ->set_time_zone('local') + ->truncate(to => 'day'); +} + +sub _parse_date { + my ($str) = @_; + if ($str =~ /^(-|\+)?(\d+)([hHdDwWmMyY])$/) { + # relative date + my ($sign, $amount, $unit, $date) = ($1, $2, lc $3, time); + my ($sec, $min, $hour, $mday, $month, $year, $wday) = localtime($date); + $amount = -$amount if $sign && $sign eq '+'; + if ($unit eq 'w') { + # convert weeks to days + $amount = 7*$amount + $wday; + $unit = 'd'; + } + if ($unit eq 'd') { + $date -= $sec + 60*$min + 3600*$hour + 24*3600*$amount; + return $date; + } + elsif ($unit eq 'y') { + return str2time(sprintf("%4d-01-01 00:00:00", $year+1900-$amount)); + } + elsif ($unit eq 'm') { + $month -= $amount; + while ($month<0) { $year--; $month += 12; } + return str2time(sprintf("%4d-%02d-01 00:00:00", $year+1900, $month+1)); + } + elsif ($unit eq 'h') { + # Special case 0h for 'beginning of this hour' + if ($amount == 0) { + $date -= $sec + 60*$min; + } else { + $date -= 3600*$amount; + } + return $date; + } + return undef; + } + return str2time($str); +} + +sub triage_reports { + my ($vars, $filter) = @_; + my $dbh = Bugzilla->dbh; + my $input = Bugzilla->input_params; + my $user = Bugzilla->user; + + if (exists $input->{'action'} && $input->{'action'} eq 'run' && $input->{'product'}) { + + # load product and components from input + + my $product = Bugzilla::Product->new({ name => $input->{'product'} }) + || ThrowUserError('invalid_object', { object => 'Product', value => $input->{'product'} }); + + my @component_ids; + if ($input->{'component'} ne '') { + my $ra_components = ref($input->{'component'}) + ? $input->{'component'} : [ $input->{'component'} ]; + foreach my $component_name (@$ra_components) { + my $component = Bugzilla::Component->new({ name => $component_name, product => $product }) + || ThrowUserError('invalid_object', { object => 'Component', value => $component_name }); + push @component_ids, $component->id; + } + } + + # determine which comment filters to run + + my $filter_commenter = $input->{'filter_commenter'}; + my $filter_commenter_on = $input->{'commenter'}; + my $filter_last = $input->{'filter_last'}; + my $filter_last_period = $input->{'last'}; + + if (!$filter_commenter || $filter_last) { + $filter_commenter = '1'; + $filter_commenter_on = 'reporter'; + } + + my $filter_commenter_id; + if ($filter_commenter && $filter_commenter_on eq 'is') { + Bugzilla::User::match_field({ 'commenter_is' => {'type' => 'single'} }); + my $user = Bugzilla::User->new({ name => $input->{'commenter_is'} }) + || ThrowUserError('invalid_object', { object => 'User', value => $input->{'commenter_is'} }); + $filter_commenter_id = $user ? $user->id : 0; + } + + my $filter_last_time; + if ($filter_last) { + if ($filter_last_period eq 'is') { + $filter_last_period = -1; + $filter_last_time = str2time($input->{'last_is'} . " 00:00:00") || 0; + } else { + detaint_natural($filter_last_period); + $filter_last_period = 14 if $filter_last_period < 14; + } + } + + # form sql queries + + my $now = (time); + my $bugs_sql = " + SELECT bug_id, short_desc, reporter, creation_ts + FROM bugs + WHERE product_id = ? + AND bug_status = 'UNCONFIRMED'"; + if (@component_ids) { + $bugs_sql .= " AND component_id IN (" . join(',', @component_ids) . ")"; + } + $bugs_sql .= " + ORDER BY creation_ts + "; + + my $comment_count_sql = " + SELECT COUNT(*) + FROM longdescs + WHERE bug_id = ? + "; + + my $comment_sql = " + SELECT who, bug_when, type, thetext, extra_data + FROM longdescs + WHERE bug_id = ? + "; + if (!Bugzilla->user->is_insider) { + $comment_sql .= " AND isprivate = 0 "; + } + $comment_sql .= " + ORDER BY bug_when DESC + LIMIT 1 + "; + + my $attach_sql = " + SELECT description, isprivate + FROM attachments + WHERE attach_id = ? + "; + + # work on an initial list of bugs + + my $list = $dbh->selectall_arrayref($bugs_sql, undef, $product->id); + my @bugs; + + foreach my $entry (@$list) { + my ($bug_id, $summary, $reporter_id, $creation_ts) = @$entry; + + next unless $user->can_see_bug($bug_id); + + # get last comment information + + my ($comment_count) = $dbh->selectrow_array($comment_count_sql, undef, $bug_id); + my ($commenter_id, $comment_ts, $type, $comment, $extra) + = $dbh->selectrow_array($comment_sql, undef, $bug_id); + my $commenter = 0; + + # apply selected filters + + if ($filter_commenter) { + next if $comment_count <= 1; + + if ($filter_commenter_on eq 'reporter') { + next if $commenter_id != $reporter_id; + + } elsif ($filter_commenter_on eq 'noconfirm') { + $commenter = Bugzilla::User->new($commenter_id); + next if $commenter_id != $reporter_id + || $commenter->in_group('canconfirm'); + + } elsif ($filter_commenter_on eq 'is') { + next if $commenter_id != $filter_commenter_id; + } + } else { + $input->{'commenter'} = ''; + $input->{'commenter_is'} = ''; + } + + if ($filter_last) { + my $comment_time = str2time($comment_ts) + or next; + if ($filter_last_period == -1) { + next if $comment_time >= $filter_last_time; + } else { + next if $now - $comment_time <= 60 * 60 * 24 * $filter_last_period; + } + } else { + $input->{'last'} = ''; + $input->{'last_is'} = ''; + } + + # get data for attachment comments + + if ($comment eq '' && $type == CMT_ATTACHMENT_CREATED) { + my ($description, $is_private) = $dbh->selectrow_array($attach_sql, undef, $extra); + next if $is_private && !Bugzilla->user->is_insider; + $comment = "(Attachment) " . $description; + } + + # truncate long comments + + if (length($comment) > 80) { + $comment = substr($comment, 0, 80) . '...'; + } + + # build bug hash for template + + my $bug = {}; + $bug->{id} = $bug_id; + $bug->{summary} = $summary; + $bug->{reporter} = Bugzilla::User->new($reporter_id); + $bug->{creation_ts} = $creation_ts; + $bug->{commenter} = $commenter || Bugzilla::User->new($commenter_id); + $bug->{comment_ts} = $comment_ts; + $bug->{comment} = $comment; + $bug->{comment_count} = $comment_count; + push @bugs, $bug; + } + + @bugs = sort { $b->{comment_ts} cmp $a->{comment_ts} } @bugs; + + $vars->{bugs} = \@bugs; + } else { + $input->{action} = ''; + } + + if (!$input->{filter_commenter} && !$input->{filter_last}) { + $input->{filter_commenter} = 1; + } + + $vars->{'input'} = $input; +} + +sub group_admins_report { + my ($vars) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + + $user->in_group('editusers') + || ThrowUserError('auth_failure', { group => 'editusers', + action => 'run', + object => 'group_admins' }); + + my $query = " + SELECT groups.name, " . + $dbh->sql_group_concat('profiles.login_name', "','", 1) . " + FROM groups + LEFT JOIN user_group_map + ON user_group_map.group_id = groups.id + AND user_group_map.isbless = 1 + AND user_group_map.grant_type = 0 + LEFT JOIN profiles + ON user_group_map.user_id = profiles.userid + WHERE groups.isbuggroup = 1 + GROUP BY groups.name"; + + my @groups; + foreach my $group (@{ $dbh->selectall_arrayref($query) }) { + my @admins; + if ($group->[1]) { + foreach my $admin (split(/,/, $group->[1])) { + push(@admins, Bugzilla::User->new({ name => $admin })); + } + } + push(@groups, { name => $group->[0], admins => \@admins }); + } + + $vars->{'groups'} = \@groups; +} + +sub group_membership_report { + my ($page, $vars) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + my $cgi = Bugzilla->cgi; + + ($user->in_group('editusers') || $user->in_group('infrasec')) + || ThrowUserError('auth_failure', { group => 'editusers', + action => 'run', + object => 'group_admins' }); + + my $who = $cgi->param('who'); + if (!defined($who) || $who eq '') { + if ($page eq 'group_membership.txt') { + print $cgi->redirect("page.cgi?id=group_membership.html&output=txt"); + exit; + } + $vars->{'output'} = $cgi->param('output'); + return; + } + + Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} }); + $who = Bugzilla->input_params->{'who'}; + $who = ref($who) ? $who : [ $who ]; + + my @users; + foreach my $login (@$who) { + my $u = Bugzilla::User->new(login_to_id($login, 1)); + + # this is lifted from $user->groups() + # we need to show which groups are direct and which are inherited + + my $groups_to_check = $dbh->selectcol_arrayref( + q{SELECT DISTINCT group_id + FROM user_group_map + WHERE user_id = ? AND isbless = 0}, undef, $u->id); + + my $rows = $dbh->selectall_arrayref( + "SELECT DISTINCT grantor_id, member_id + FROM group_group_map + WHERE grant_type = " . GROUP_MEMBERSHIP); + + my %group_membership; + foreach my $row (@$rows) { + my ($grantor_id, $member_id) = @$row; + push (@{ $group_membership{$member_id} }, $grantor_id); + } + + my %checked_groups; + my %direct_groups; + my %indirect_groups; + my %groups; + + foreach my $member_id (@$groups_to_check) { + $direct_groups{$member_id} = 1; + } + + while (scalar(@$groups_to_check) > 0) { + my $member_id = shift @$groups_to_check; + if (!$checked_groups{$member_id}) { + $checked_groups{$member_id} = 1; + my $members = $group_membership{$member_id}; + my @new_to_check = grep(!$checked_groups{$_}, @$members); + push(@$groups_to_check, @new_to_check); + foreach my $id (@new_to_check) { + $indirect_groups{$id} = $member_id; + } + $groups{$member_id} = 1; + } + } + + my @groups; + my $ra_groups = Bugzilla::Group->new_from_list([keys %groups]); + foreach my $group (@$ra_groups) { + my $via; + if ($direct_groups{$group->id}) { + $via = ''; + } else { + foreach my $g (@$ra_groups) { + if ($g->id == $indirect_groups{$group->id}) { + $via = $g->name; + last; + } + } + } + push @groups, { + name => $group->name, + desc => $group->description, + via => $via, + }; + } + + push @users, { + user => $u, + groups => \@groups, + }; + } + + $vars->{'who'} = $who; + $vars->{'users'} = \@users; +} + +sub email_queue_report { + my ($vars, $filter) = @_; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + + $user->in_group('admin') || $user->in_group('infra') + || ThrowUserError('auth_failure', { group => 'admin', + action => 'run', + object => 'email_queue' }); + + my $query = " + SELECT j.jobid, + j.insert_time, + j.run_after AS run_time, + COUNT(e.jobid) AS error_count, + MAX(e.error_time) AS error_time, + e.message AS error_message + FROM ts_job j + LEFT JOIN ts_error e ON e.jobid = j.jobid + GROUP BY j.jobid + ORDER BY j.run_after"; + + $vars->{'jobs'} = $dbh->selectall_arrayref($query, { Slice => {} }); + $vars->{'now'} = (time); +} + +sub release_tracking_report { + my ($vars) = @_; + my $dbh = Bugzilla->dbh; + my $input = Bugzilla->input_params; + my $user = Bugzilla->user; + + my @flag_names = qw( + approval-mozilla-release + approval-mozilla-beta + approval-mozilla-aurora + approval-mozilla-central + approval-comm-release + approval-comm-beta + approval-comm-aurora + approval-calendar-release + approval-calendar-beta + approval-calendar-aurora + ); + + my @flags_json; + my @fields_json; + my @products_json; + + # + # tracking flags + # + + my $all_products = $user->get_selectable_products; + my @usable_products; + + # build list of flags and their matching products + + my @invalid_flag_names; + foreach my $flag_name (@flag_names) { + # grab all matching flag_types + my @flag_types = @{Bugzilla::FlagType::match({ name => $flag_name, is_active => 1 })}; + + # remove invalid flags + if (!@flag_types) { + push @invalid_flag_names, $flag_name; + next; + } + + # we need a list of products, based on inclusions/exclusions + my @products; + my %flag_types; + foreach my $flag_type (@flag_types) { + $flag_types{$flag_type->name} = $flag_type->id; + my $has_all = 0; + my @exclusion_ids; + my @inclusion_ids; + foreach my $flag_type (@flag_types) { + if (scalar keys %{$flag_type->inclusions}) { + my $inclusions = $flag_type->inclusions; + foreach my $key (keys %$inclusions) { + push @inclusion_ids, ($inclusions->{$key} =~ /^(\d+)/); + } + } elsif (scalar keys %{$flag_type->exclusions}) { + my $exclusions = $flag_type->exclusions; + foreach my $key (keys %$exclusions) { + push @exclusion_ids, ($exclusions->{$key} =~ /^(\d+)/); + } + } else { + $has_all = 1; + last; + } + } + + if ($has_all) { + push @products, @$all_products; + } elsif (scalar @exclusion_ids) { + push @products, @$all_products; + foreach my $exclude_id (uniq @exclusion_ids) { + @products = grep { $_->id != $exclude_id } @products; + } + } else { + foreach my $include_id (uniq @inclusion_ids) { + push @products, grep { $_->id == $include_id } @$all_products; + } + } + } + @products = uniq @products; + push @usable_products, @products; + my @product_ids = map { $_->id } sort { lc($a->name) cmp lc($b->name) } @products; + + push @flags_json, { + name => $flag_name, + id => $flag_types{$flag_name} || 0, + products => \@product_ids, + fields => [], + }; + } + foreach my $flag_name (@invalid_flag_names) { + @flag_names = grep { $_ ne $flag_name } @flag_names; + } + @usable_products = uniq @usable_products; + + # build a list of tracking flags for each product + # also build the list of all fields + + my @unlink_products; + foreach my $product (@usable_products) { + my @fields = + grep { _is_active_status_field($_->name) } + Bugzilla->active_custom_fields({ product => $product }); + my @field_ids = map { $_->id } @fields; + if (!scalar @fields) { + push @unlink_products, $product; + next; + } + + # product + push @products_json, { + name => $product->name, + id => $product->id, + fields => \@field_ids, + }; + + # add fields to flags + foreach my $rh (@flags_json) { + if (grep { $_ eq $product->id } @{$rh->{products}}) { + push @{$rh->{fields}}, @field_ids; + } + } + + # add fields to fields_json + foreach my $field (@fields) { + my $existing = 0; + foreach my $rh (@fields_json) { + if ($rh->{id} == $field->id) { + $existing = 1; + last; + } + } + if (!$existing) { + push @fields_json, { + name => $field->name, + id => $field->id, + }; + } + } + } + foreach my $rh (@flags_json) { + my @fields = uniq @{$rh->{fields}}; + $rh->{fields} = \@fields; + } + + # remove products which aren't linked with status fields + + foreach my $rh (@flags_json) { + my @product_ids; + foreach my $id (@{$rh->{products}}) { + unless (grep { $_->id == $id } @unlink_products) { + push @product_ids, $id; + } + $rh->{products} = \@product_ids; + } + } + + # + # rapid release dates + # + + my @ranges; + my $start_date = _string_to_datetime('2011-08-16'); + my $end_date = $start_date->clone->add(weeks => 6)->add(days => -1); + my $now_date = _time_to_datetime((time)); + + while ($start_date <= $now_date) { + unshift @ranges, { + value => sprintf("%s-%s", $start_date->ymd(''), $end_date->ymd('')), + label => sprintf("%s and %s", $start_date->ymd('-'), $end_date->ymd('-')), + }; + + $start_date = $end_date->clone;; + $start_date->add(days => 1); + $end_date->add(weeks => 6); + } + push @ranges, { + value => '*', + label => 'Anytime', + }; + + # + # run report + # + + if ($input->{q}) { + my $q = _parse_query($input->{q}); + + my @where; + my @params; + my $query = " + SELECT DISTINCT b.bug_id + FROM bugs b + INNER JOIN flags f ON f.bug_id = b.bug_id "; + + if ($q->{start_date}) { + $query .= "INNER JOIN bugs_activity a ON a.bug_id = b.bug_id "; + } + + $query .= "WHERE "; + + if ($q->{start_date}) { + push @where, "(a.fieldid = ?)"; + push @params, $q->{field_id}; + + push @where, "(a.bug_when >= ?)"; + push @params, $q->{start_date} . ' 00:00:00'; + push @where, "(a.bug_when < ?)"; + push @params, $q->{end_date} . ' 00:00:00'; + + push @where, "(a.added LIKE ?)"; + push @params, '%' . $q->{flag_name} . '?%'; + } + + push @where, "(f.type_id IN (SELECT id FROM flagtypes WHERE name = ?))"; + push @params, $q->{flag_name}; + + push @where, "(f.status = ?)"; + push @params, $q->{flag_status}; + + if ($q->{product_id}) { + push @where, "(b.product_id = ?)"; + push @params, $q->{product_id}; + } + + if (scalar @{$q->{fields}}) { + my @fields; + foreach my $field (@{$q->{fields}}) { + push @fields, + "(" . + ($field->{value} eq '+' ? '' : '!') . + "(b.".$field->{name}." IN ('fixed','verified'))" . + ") "; + } + my $join = uc $q->{join}; + push @where, '(' . join(" $join ", @fields) . ')'; + } + + $query .= join("\nAND ", @where); + + my $bugs = $dbh->selectcol_arrayref($query, undef, @params); + push @$bugs, 0 unless @$bugs; + + my $urlbase = correct_urlbase(); + my $cgi = Bugzilla->cgi; + print $cgi->redirect( + -url => "${urlbase}buglist.cgi?bug_id=" . join(',', @$bugs) + ); + exit; + } + + # + # set template vars + # + + my $json = JSON->new(); + if (0) { + # debugging + $json->shrink(0); + $json->canonical(1); + $vars->{flags_json} = $json->pretty->encode(\@flags_json); + $vars->{products_json} = $json->pretty->encode(\@products_json); + $vars->{fields_json} = $json->pretty->encode(\@fields_json); + } else { + $json->shrink(1); + $vars->{flags_json} = $json->encode(\@flags_json); + $vars->{products_json} = $json->encode(\@products_json); + $vars->{fields_json} = $json->encode(\@fields_json); + } + + $vars->{flag_names} = \@flag_names; + $vars->{ranges} = \@ranges; + $vars->{default_query} = $input->{q}; + foreach my $field (qw(product flags range)) { + $vars->{$field} = $input->{$field}; + } +} + +sub _parse_query { + my $q = shift; + my @query = split(/:/, $q); + my $query; + + # field_id for flag changes + $query->{field_id} = get_field_id('flagtypes.name'); + + # flag_name + my $flag_name = shift @query; + @{Bugzilla::FlagType::match({ name => $flag_name, is_active => 1 })} + or ThrowUserError('report_invalid_parameter', { name => 'flag_name' }); + trick_taint($flag_name); + $query->{flag_name} = $flag_name; + + # flag_status + my $flag_status = shift @query; + $flag_status =~ /^([\?\-\+])$/ + or ThrowUserError('report_invalid_parameter', { name => 'flag_status' }); + $query->{flag_status} = $1; + + # date_range -> from_ymd to_ymd + my $date_range = shift @query; + if ($date_range ne '*') { + $date_range =~ /^(\d\d\d\d)(\d\d)(\d\d)-(\d\d\d\d)(\d\d)(\d\d)$/ + or ThrowUserError('report_invalid_parameter', { name => 'date_range' }); + $query->{start_date} = "$1-$2-$3"; + $query->{end_date} = "$4-$5-$6"; + } + + # product_id + my $product_id = shift @query; + $product_id =~ /^(\d+)$/ + or ThrowUserError('report_invalid_parameter', { name => 'product_id' }); + $query->{product_id} = $1; + + # join + my $join = shift @query; + $join =~ /^(and|or)$/ + or ThrowUserError('report_invalid_parameter', { name => 'join' }); + $query->{join} = $1; + + # fields + my @fields; + foreach my $field (@query) { + $field =~ /^(\d+)([\-\+])$/ + or ThrowUserError('report_invalid_parameter', { name => 'fields' }); + my ($id, $value) = ($1, $2); + my $field_obj = Bugzilla::Field->new($id) + or ThrowUserError('report_invalid_parameter', { name => 'field_id' }); + push @fields, { id => $id, value => $value, name => $field_obj->name }; + } + $query->{fields} = \@fields; + + return $query; +} + +sub _is_active_status_field { + my ($field_name) = @_; + if ($field_name =~ /^cf_status/) { + return !grep { $field_name eq $_ } @$cf_disabled_flags + } + return 0; +} + +1; diff --git a/extensions/BMO/lib/WebService.pm b/extensions/BMO/lib/WebService.pm new file mode 100644 index 000000000..95bdcbdf3 --- /dev/null +++ b/extensions/BMO/lib/WebService.pm @@ -0,0 +1,207 @@ +# -*- 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 BMO Bugzilla Extension. +# +# The Initial Developer of the Original Code is Mozilla Foundation. Portions created +# by the Initial Developer are Copyright (C) 2011 the Mozilla Foundation. All +# Rights Reserved. +# +# Contributor(s): +# Dave Lawrence <dkl@mozilla.com> + +package Bugzilla::Extension::BMO::WebService; + +use strict; +use warnings; + +use base qw(Bugzilla::WebService); + +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::WebService::Util qw(validate); +use Bugzilla::Field; + +sub getBugsConfirmer { + my ($self, $params) = validate(@_, 'names'); + my $dbh = Bugzilla->dbh; + + defined($params->{names}) + || ThrowCodeError('params_required', + { function => 'BMO.getBugsConfirmer', params => ['names'] }); + + my @user_objects = map { Bugzilla::User->check($_) } @{ $params->{names} }; + + # start filtering to remove duplicate user ids + @user_objects = values %{{ map { $_->id => $_ } @user_objects }}; + + my $fieldid = get_field_id('bug_status'); + + my $query = "SELECT DISTINCT bugs_activity.bug_id + FROM bugs_activity + LEFT JOIN bug_group_map + ON bugs_activity.bug_id = bug_group_map.bug_id + WHERE bugs_activity.fieldid = ? + AND bugs_activity.added = 'NEW' + AND bugs_activity.removed = 'UNCONFIRMED' + AND bugs_activity.who = ? + AND bug_group_map.bug_id IS NULL + ORDER BY bugs_activity.bug_id"; + + my %users; + foreach my $user (@user_objects) { + my $bugs = $dbh->selectcol_arrayref($query, undef, $fieldid, $user->id); + $users{$user->login} = $bugs; + } + + return \%users; +} + +sub getBugsVerifier { + my ($self, $params) = validate(@_, 'names'); + my $dbh = Bugzilla->dbh; + + defined($params->{names}) + || ThrowCodeError('params_required', + { function => 'BMO.getBugsVerifier', params => ['names'] }); + + my @user_objects = map { Bugzilla::User->check($_) } @{ $params->{names} }; + + # start filtering to remove duplicate user ids + @user_objects = values %{{ map { $_->id => $_ } @user_objects }}; + + my $fieldid = get_field_id('bug_status'); + + my $query = "SELECT DISTINCT bugs_activity.bug_id + FROM bugs_activity + LEFT JOIN bug_group_map + ON bugs_activity.bug_id = bug_group_map.bug_id + WHERE bugs_activity.fieldid = ? + AND bugs_activity.removed = 'RESOLVED' + AND bugs_activity.added = 'VERIFIED' + AND bugs_activity.who = ? + AND bug_group_map.bug_id IS NULL + ORDER BY bugs_activity.bug_id"; + + my %users; + foreach my $user (@user_objects) { + my $bugs = $dbh->selectcol_arrayref($query, undef, $fieldid, $user->id); + $users{$user->login} = $bugs; + } + + return \%users; +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::Extension::BMO::Webservice - The BMO WebServices API + +=head1 DESCRIPTION + +This module contains API methods that are useful to user's of bugzilla.mozilla.org. + +=head1 METHODS + +See L<Bugzilla::WebService> for a description of how parameters are passed, +and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean. + +=head2 getBugsConfirmer + +B<UNSTABLE> + +=over + +=item B<Description> + +This method returns public bug ids that a given user has confirmed (changed from +C<UNCONFIRMED> to C<NEW>). + +=item B<Params> + +You pass a field called C<names> that is a list of Bugzilla login names to find bugs for. + +=over + +=item C<names> (array) - An array of strings representing Bugzilla login names. + +=back + +=item B<Returns> + +=over + +A hash of Bugzilla login names. Each name points to an array of bug ids that the user has confirmed. + +=back + +=item B<Errors> + +=over + +=back + +=item B<History> + +=over + +=item Added in BMO Bugzilla B<4.0>. + +=back + +=back + +=head2 getBugsVerifier + +B<UNSTABLE> + +=over + +=item B<Description> + +This method returns public bug ids that a given user has verified (changed from +C<RESOLVED> to C<VERIFIED>). + +=item B<Params> + +You pass a field called C<names> that is a list of Bugzilla login names to find bugs for. + +=over + +=item C<names> (array) - An array of strings representing Bugzilla login names. + +=back + +=item B<Returns> + +=over + +A hash of Bugzilla login names. Each name points to an array of bug ids that the user has verified. + +=back + +=item B<Errors> + +=over + +=back + +=item B<History> + +=over + +=item Added in BMO Bugzilla B<4.0>. + +=back + +=back diff --git a/extensions/BMO/template/en/default/account/create.html.tmpl b/extensions/BMO/template/en/default/account/create.html.tmpl new file mode 100644 index 000000000..8bd4a9812 --- /dev/null +++ b/extensions/BMO/template/en/default/account/create.html.tmpl @@ -0,0 +1,184 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + # Byron Jones <glob@mozilla.com> + #%] + +[%# INTERFACE + # none + # + # Param("maintainer") is used to display the maintainer's email. + # Param("emailsuffix") is used to pre-fill the email field. + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% title = BLOCK %] + Create a new [% terms.Bugzilla %] account +[% END %] + +[% PROCESS global/header.html.tmpl + title = title + style_urls = [ 'extensions/BMO/web/styles/create_account.css' ] +%] + +<script type="text/javascript"> +function onSubmit() { + var email = document.getElementById('login').value; + if (email == '') { + alert('You must enter your email address.'); + return false; + } + var isValid = + email.match(/@/) + && email.match(/@.+\./) + && !email.match(/\.$/) + && !email.match(/[\\()&<>,'"\[\]]/) + ; + if (!isValid) { + alert( + "The e-mail address doesn't pass our syntax checking for a legal " + + "email address.\n\nA legal address must contain exactly one '@', and " + + "at least one '.' after the @.\n\nIt must also not contain any of " + + "these special characters: \ ( ) & < > , ; : \" [ ], or any whitespace." + ); + return false; + } + return true; +} +</script> + +<table border="0" id="create-account"> +<tr> + +<td width="50%" id="create-account-left" valign="top"> + + <h2 class="column-header">I need help using a Mozilla Product</h2> + + <table border="0" id="product-list"> + [% INCLUDE product + icon = "firefox" + name = "Firefox Support" + url = "http://support.mozilla.com/" + desc = "Support for the Firefox web browser." + %] + [% INCLUDE product + icon = "firefox" + name = "Firefox for Mobile Support" + url = "http://support.mozilla.com/mobile" + desc = "Support for the Firefox Mobile web browser." + %] + [% INCLUDE product + icon = "thunderbird" + name = "Thunderbird Support" + url = "http://www.mozillamessaging.com/support/" + desc = "Support for Thunderbird email client." + %] + [% INCLUDE product + icon = "other" + name = "Support for other products" + url = "http://www.mozilla.org/projects/" + desc = "Support for products not listed here." + %] + [% INCLUDE product + icon = "input" + name = "Feedback" + url = "http://input.mozilla.com/feedback" + desc = "Report issues with web site you use, or provide quick feedback for Firefox." + %] + [% INCLUDE product + icon = "idea" + name = "Ideas" + url = "http://input.mozilla.com/idea" + desc = "Offer us ideas on how to enhance Firefox." + %] + </table> + +</td> + +<td width="50%" id="create-account-right" valign="top"> + + <h2 class="column-header">I want to help</h2> + + <div id="right-blurb"> + <p> + Great! There are three things to know and do: + </p> + <ol> + <li> + Please consider reading our + <a href="https://developer.mozilla.org/en/Bug_writing_guidelines" target="_blank">[% terms.bug %] writing guidelines</a>. + </li> + <li> + [% terms.Bugzilla %] is a public place, so what you type and your email address will be visible + to all logged-in users. Some people use an + <a href="http://email.about.com/od/freeemailreviews/tp/free_email.htm" target="_blank">alternative email address</a> + for this reason. + </li> + <li> + Please give us an email address you want to use. Once we confirm that it works, + you'll be asked to set a password and then you can start filing [% terms.bugs %] and helping fix them. + </li> + </ol> + </div> + + <h2 class="column-header">Create an account</h2> + + <form method="post" action="createaccount.cgi" onsubmit="return onSubmit()"> + <table id="create-account-form"> + <tr> + <td class="label">Email Address:</td> + <td> + <input size="35" id="login" name="login" placeholder="you@example.com">[% Param('emailsuffix') FILTER html %]</td> + <td> + <input type="hidden" id="token" name="token" value="[% issue_hash_token(['create_account']) FILTER html %]"> + <input type="submit" value="Create Account"> + </td> + </tr> + </table> + </form> + + [% Hook.process('additional_methods') %] + +</td> + +</tr> +</table> + +<p id="bmo-admin"> + If you think there's something wrong with [% terms.Bugzilla %], you can + <a href="mailto:bugzilla-admin@mozilla.org">send an email to the admins</a>, but + remember, they can't file [% terms.bugs %] for you, or solve tech support problems. +</p> + +[% PROCESS global/footer.html.tmpl %] + +[% BLOCK product %] + <tr> + <td valign="top"> + <a href="[% url FILTER none %]"><img + src="extensions/BMO/web/producticons/[% icon FILTER uri %].png" + border="0" width="64" height="64"></a> + </td> + <td valign="top"> + <h2><a href="[% url FILTER none %]">[% name FILTER html %]</a></h2> + <div>[% desc FILTER html %]</div> + </td> + </tr> +[% END %] + diff --git a/extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl new file mode 100644 index 000000000..d9aa35f17 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-brownbag.txt.tmpl @@ -0,0 +1,34 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] + +Topic: [% cgi.param('topic') %] +Presenter: [% cgi.param('presenter') %] +Date: [% cgi.param('date') %] +Time: [% cgi.param('time_hour') %]:[% cgi.param('time_minute') %][% cgi.param('ampm') +%] [%+ cgi.param('time_zone') %] +Duration: [% IF cgi.param('duration') == 'Other' %][% cgi.param('duration_other') %][% ELSE %][% cgi.param('duration') %][% END %] +Audience: [% cgi.param('audience') %] +Air Mozilla: [% IF cgi.param('airmozilla') %]Yes[% ELSE %]No[% END %] +Dial-in: [% IF cgi.param('dialin') %]Yes[% ELSE %]No[% END %] +Archive: [% IF cgi.param('archive') %]Yes[% ELSE %]No[% END %] +Member of IT to help with A/V: [% IF cgi.param('ithelp') %]Yes[% ELSE %]No[% END %] +Description: +[% cgi.param('description') %] diff --git a/extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl new file mode 100644 index 000000000..1b0902d64 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-employee-incident.txt.tmpl @@ -0,0 +1,57 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] + +[% IF cgi.param('incident_type') == 'stolen' %] +[% IF original_reporter -%] +Reporter: [% original_reporter.identity FILTER none %] +[%- END -%] + + [% IF cgi.param('display_action') %] + [% IF cgi.param('display_action') == 'ldap' %] +Action needed: Please immediately reset the LDAP password for this user. + [% ELSIF cgi.param('display_action') == 'ssh' %] +Action needed: Please immediately disable the SSH key for this user. + [% END %] + +The user reported that their mobile or laptop device has been lost or stolen. +This ticket was automatically generated from the employee incident reporting +form. An additional ticket has been filed (see blocker bugs) for InfraSec to +review the impact of this lost device. + [% END %] + +Type of device: [% cgi.param('device') %] +Was the device encrypted?: [% cgi.param('encrypted') %] +Any user data on the device?: [% cgi.param('userdata') %] + [% IF cgi.param('userdata') == 'Yes' %] +Sensitive data on the device: +[%+ cgi.param('sensitivedata') %] + [% END %] +Browser configured to remember passwords?: [% cgi.param('rememberpasswords') %] + [% IF cgi.param('rememberpasswords') == 'Yes' %] +Critical sites: +[%+ cgi.param('criticalsites') %] + [% END %] +[% END %] +[% IF cgi.param('comment') %] +Extra Notes: +[%+ cgi.param('comment') %] +[% END %] diff --git a/extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl new file mode 100644 index 000000000..eb00a88d9 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-legal.txt.tmpl @@ -0,0 +1,39 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] + +Priority for your Team: +[%+ cgi.param('teampriority') %] + +Timeframe for Completion: +[%+ cgi.param('timeframe') %] + +Goal: +[%+ cgi.param('goal') %] + +Business Objective: +[%+ cgi.param('busobj') %] + +Other Party: +[%+ cgi.param('otherparty') %] + +Description: +[%+ cgi.param("comment") %] diff --git a/extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl new file mode 100644 index 000000000..216f2c53a --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl @@ -0,0 +1,48 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + #%] +[%# INTERFACE: + # This template has no interface. + # + # Form variables from a bug submission (i.e. the fields on a template from + # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to + # pull out various custom fields and format an initial Description entry + # from them. + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] +Requester: [% cgi.param('firstname') %] [%+ cgi.param('lastname') %] +Email: [% cgi.param('email') %] +Event Name: [% cgi.param('eventname') %] +Event Date: [% cgi.param("date") %] +Event Location: [% cgi.param("locations") %] +Event Website: [% cgi.param("website") %] +Event Description and Objectives: +[%+ cgi.param("goals") %] + +Attendees: [% IF cgi.param('attendees') != "--Please Select--" %][% cgi.param('attendees') %][% END %] +Target Audience: [% IF cgi.param('audience') != "--Please Select--" %][% cgi.param('audience') %][% END %] + +We'll be doing: [% cgi.param("doing").join(", ") %][% IF cgi.param('doing-other-what') %]: [% cgi.param('doing-other-what') %][% END %] + +Success will be measured by: +[%+ cgi.param('successmeasure') %] + +[%+ cgi.param("comment") IF cgi.param("comment") %] + diff --git a/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl new file mode 100644 index 000000000..c62461d42 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl @@ -0,0 +1,44 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + #%] +[%# INTERFACE: + # This template has no interface. + # + # Form variables from a bug submission (i.e. the fields on a template from + # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to + # pull out various custom fields and format an initial Description entry + # from them. + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] +List Name: [% cgi.param("listName") %] +List Admin: [% cgi.param("listAdmin") %] + +Short Description: +[%+ cgi.param("listShortDesc") %] + +[% IF cgi.param("listType") != "mozilla.com" %] +Long Description: +[%+ cgi.param("listLongDesc") %] +[% END %] + +Justification / Special Instructions: + +[%+ cgi.param("comment") IF cgi.param("comment") %] + diff --git a/extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl new file mode 100644 index 000000000..9a38af7cc --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-recoverykey.txt.tmpl @@ -0,0 +1,28 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] + +Recovery Key: [% cgi.param('recoverykey') %] +Asset Tag Number: [% cgi.param('assettag') %] + +[% IF cgi.param('comment') %] +[%+ cgi.param('comment') %] +[% END %] diff --git a/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl new file mode 100644 index 000000000..0ec7687d4 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl @@ -0,0 +1,48 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + #%] +[%# INTERFACE: + # This template has no interface. + # + # Form variables from a bug submission (i.e. the fields on a template from + # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to + # pull out various custom fields and format an initial Description entry + # from them. + #%] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] +Requester: [% cgi.param('firstname') %] [% cgi.param('lastname') %] +Email: [% cgi.param('email') %] + +Additional Swag: [% cgi.param("additional") %] + +Ship to: +[%+ cgi.param("shiptofirstname") +%] [%+ cgi.param("shiptolastname") +%] +[%+ cgi.param("shiptoaddress") +%] +[%+ cgi.param("shiptoaddress2") +%] +[%+ cgi.param("shiptocity") +%] [%+ cgi.param("shiptostate") +%] [%+ cgi.param("shiptopcode") +%] +[%+ cgi.param("shiptocountry") %] + +Phone: [% cgi.param("shiptophone") %] +[%+ IF cgi.param("shiptoidrut") %]Personal ID/RUT: [% cgi.param("shiptoidrut") %][% END %] + +Additional comments: + +[%+ cgi.param("comment") IF cgi.param("comment") %] + diff --git a/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl new file mode 100644 index 000000000..d0693051c --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl @@ -0,0 +1,292 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Mozilla Corporation. + # Portions created by Mozilla are Copyright (C) 2008 Mozilla + # Corporation. All Rights Reserved. + # + # Contributor(s): Reed Loden <reed@mozilla.com> + # David Tran <dtran@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Corporation Brownbag Requests" + style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }" + style_urls = [ 'skins/standard/enter_bug.css' ] + javascript_urls = [ 'js/attachment.js', 'js/field.js', 'js/util.js' ] + yui = [ 'autocomplete', 'calendar' ] +%] + +[% USE Bugzilla %] + +<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Brownbag Request</div> + +<p><strong>Brownbag Request:</strong> Please use this form if you plan on hosting a brownbag so that IT will be able to properly provide support. </p> + +<p>Process:</p> + +<ol><li>Complete and submit request below.</li> + <li>Your request will be reviewed and assigned to the appropriate person in IT.</li> +</ol> + +<p>These requests will only be visible internally in all cases and only to the +person who submitted the request and any persons designated in the CC line.</p> + +<script type="text/javascript"> +function trySubmit() { + var topic = document.getElementById('topic').value; + var date = document.getElementById('date').value; + var time = document.getElementById('time_hour').value + ':' + + document.getElementById('time_minute').value + + document.getElementById('ampm').value + " " + + document.getElementById('time_zone').value; + var location = document.getElementById('location').value; + var shortdesc = 'Event - (' + date + ' ' + time + ') - ' + location + ' - ' + topic; + document.getElementById('short_desc').value = shortdesc; + + // If intended audience is employees only, add mozilla-corporation-confidential group + var audience = document.getElementById('audience').value; + if (audience == 'Employees Only') { + var brownbagRequestForm = document.getElementById('brownbagRequestForm'); + var groups = document.createElement('input'); + groups.type = 'hidden'; + groups.name = 'groups'; + groups.value = 'mozilla-corporation-confidential'; + brownbagRequestForm.appendChild(groups); + } + + return true; +} +</script> + +<form method="post" action="post_bug.cgi" id="brownbagRequestForm" class="enter_bug_form" + enctype="multipart/form-data" onSubmit="return trySubmit();"> + <input type="hidden" name="format" value="brownbag"> + <input type="hidden" name="product" value="Air Mozilla"> + <input type="hidden" name="component" value="Events"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="version" value="unspecified"> + <input type="hidden" name="bug_severity" id="bug_severity" value="normal"> + <input type="hidden" name="comment" id="comment" value=""> + <input type="hidden" name="short_desc" id="short_desc" value=""> + <input type="hidden" name="token" value="[% token FILTER html %]"> + +<table> + +<tr> + <th class="field_label"> + <label for="presenter">Presenter:</label> + </th> + <td> + <input type="text" name="presenter" id="presenter" value="" size="60" /> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="topic">Topic:</label> + </th> + <td> + <input type="text" name="topic" id="topic" value="" size="60" /> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="date">Date:</label> + </th> + <td> + <input type="text" name="date" size="10" id="date" + align="right" value="" maxlength="10" + onchange="updateCalendarFromField(this)"> + <button type="button" class="calendar_button" id="button_calendar_date" + onclick="showCalendar('date')"><span>Calendar</span> + </button> + <div id="con_calendar_date"></div> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="time_hour">Start Time:</label> + </th> + <td> + <select name="time_hour" id="time_hour"> + <option value="12" selected>12</option> + <option value="1">1</option> + <option value="2">2</option> + <option value="3">3</option> + <option value="4">4</option> + <option value="5">5</option> + <option value="6">6</option> + <option value="7">7</option> + <option value="8">8</option> + <option value="9">9</option> + <option value="10">10</option> + <option value="11">11</option> + </select>: + <select name="time_minute" id="time_minute"> + <option value="00" selected>00</option> + <option value="15">15</option> + <option value="30">30</option> + <option value="45">45</option> + </select> + <select name="ampm" id="ampm"> + <option value="AM">AM</option> + <option value="PM" selected>PM</option> + </select> + <select name="time_zone" id="time_zone"> + <option value="UTC-11">UTC-11</option> + <option value="UTC-10">UTC-10</option> + <option value="UTC-9">UTC-9</option> + <option value="UTC-8" selected>UTC-8</option> + <option value="UTC-7">UTC-7</option> + <option value="UTC-6">UTC-6</option> + <option value="UTC-5">UTC-5</option> + <option value="UTC-4">UTC-4</option> + <option value="UTC-3">UTC-3</option> + <option value="UTC-2">UTC-2</option> + <option value="UTC-1">UTC-1</option> + <option value="UTC+0">UTC+0</option> + <option value="UTC+1">UTC+1</option> + <option value="UTC+2">UTC+2</option> + <option value="UTC+3">UTC+3</option> + <option value="UTC+4">UTC+4</option> + <option value="UTC+5">UTC+5</option> + <option value="UTC+6">UTC+6</option> + <option value="UTC+7">UTC+7</option> + <option value="UTC+8">UTC+8</option> + <option value="UTC+9">UTC+9</option> + <option value="UTC+10">UTC+10</option> + <option value="UTC+11">UTC+11</option> + <option value="UTC+12">UTC+11</option> + </select> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="duration_one_hour_radio">Duration:</label> + </th> + <td> + <input type="radio" name="duration" id="duration_one_hour_radio" value="1 Hour" checked="checked"> + <label for="duration_one_hour_radio">1 Hour</label><br> + <input type="radio" name="duration" id="duration_one_day_radio" value="1 Day"> + <label for="duration_one_day_radio">1 Day</label><br> + <input type="radio" name="duration" id="duration_other_radio" value="Other" + onclick="YAHOO.util.Dom.get('duration_other').focus();"> + <label for="duration_other_radio">Other</label> + <input type="text" name="duration_other" id="duration_other" value=""> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="location">Location:</label> + </th> + <td> + <input type="text" name="location" id="location" + value="[% default.location || 'Ten Forward' FILTER html %]" size="60" /> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="audience">Intended Audience:</label> + </th> + <td> + <select name="audience" id="audience"> + <option value="Public" selected>Open to Public</option> + <option value="Employees Only">Employees Only</option> + <option value="Interns">Interns</option> + </select> + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="airmozilla">Air Mozilla Broadcasting?</label> + </th> + <td align="left"><input type="checkbox" name="airmozilla" id="airmozilla"></td> +</tr> + +<tr> + <th class="field_label"> + <label for="dialin">Dial In?</label> + </th> + <td align="left"><input type="checkbox" name="dialin" id="dialin"></td> +</tr> + +<tr> + <th class="field_label"> + <label for="archive">Archive this?</label> + </th> + <td align="left"><input type="checkbox" name="archive" id="archive" value="yes"></td> +</tr> + +<tr> + <th class="field_label"> + <label for="ithelp">Need IT to help run A/V?</label> + </th> + <td align="left"><input type="checkbox" name="ithelp" id="ithelp" value="yes" checked></td> +</tr> + +<tr> + <th class="field_label"> + <label for="cc">CC (optional):</label> + </th> + <td colspan="3"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 60 + multiple => 5 + %] + </td> +</tr> + +<tr> + <th class="field_label"> + <label for="description">Description</label>: + </th> + <td> + <em>Please briefly describe the brownbag and any specific needs you might have.</em><br> + <textarea id="description" name="description" rows="10" cols="80"></textarea> + </td> +</tr> + +<tr> + <td></td> + <td> + <input type="submit" id="commit" value="Submit Request"> + </td> +</tr> +</table> + +</form> + +<p> + Thanks for contacting us. + You will be notified by email of any progress made in resolving your request. +</p> + +<script type="text/javascript"> + createCalendar('date'); +</script> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl new file mode 100644 index 000000000..2bbacdb12 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-employee-incident.html.tmpl @@ -0,0 +1,288 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Corporation/Foundation Employee Incident" +%] + +[% USE Bugzilla %] + +<script type="text/javascript"> + var type_desc = new Array(); + type_desc['safety'] = "If this is an emergency please immediately call your local police or emergency number."; + type_desc['stolen'] = "Please report a lost Mozilla laptop or any mobile device that was used to access<br> " + + "Mozilla email or contained passwords for Mozilla servers, devices, applications, etc."; + + function validateAndSubmit() { + var alert_text = ''; + var typeSelect = YAHOO.util.Dom.get('incident_type'); + var typeValue = typeSelect.options[typeSelect.selectedIndex].value; + + if (typeValue != 'stolen' && !isFilledOut('short_desc')) { + alert_text += "Please enter a summary.\n"; + } + + var select = YAHOO.util.Dom.get('incident_type'); + var selectValue = select.options[select.selectedIndex].value; + if (selectValue == 'stolen') { + if (!isFilledOut('device')) { + alert_text += "Please provide the type of device.\n"; + } + if (!isFilledOut('encrypted')) { + alert_text += "Please answer whether the device was encrypted.\n"; + } + if (!isFilledOut('userdata')) { + alert_text += "Please answer whether the device had user data.\n"; + } + if (!isFilledOut('rememberpasswords')) { + alert_text += "Please answer whether the browser was configured to remember passwords.\n"; + } + } + + if (alert_text) { + alert(alert_text); + return false; + } + + // Hard code summary if stolen type was chosen + if (typeValue == 'stolen') { + document.getElementById('short_desc').value = '[Lost Device] Change LDAP Password for [% user.name FILTER js %]'; + } + + return true; + } + + function setType (select) { + var selectValue = select.options[select.selectedIndex].value; + + // Set the current description displayed. + document.getElementById('type_desc').innerHTML = type_desc[selectValue]; + + // Display/hide some additional fields based on type selected + if (selectValue == 'stolen') { + YAHOO.util.Dom.removeClass('stolen', 'bz_default_hidden'); + YAHOO.util.Dom.addClass('safety', 'bz_default_hidden'); + } + else { + YAHOO.util.Dom.removeClass('safety', 'bz_default_hidden'); + YAHOO.util.Dom.addClass('stolen', 'bz_default_hidden'); + } + + // Alter the product/component/group based on type selected + if (selectValue == 'stolen') { + document.getElementById('product').value = 'mozilla.org'; + document.getElementById('component').value = 'Server Operations: Desktop Issues'; + document.getElementById('groups').value = 'infra'; + document.getElementById('cc').value = 'mcoates@mozilla.com, jstevensen@mozilla.com, afowler@mozilla.com'; + document.getElementById('bug_severity').value = 'critical'; + document.getElementById('display_action').value = 'ldap'; + } + else { + document.getElementById('product').value = 'Mozilla Corporation'; + document.getElementById('component').value = 'Facilities Management'; + document.getElementById('groups').value = 'hr'; + document.getElementById('cc').value = 'dcohen@mozilla.com, mcoates@mozilla.com, jill@mozilla.com'; + document.getElementById('bug_severity').value = 'normal'; + document.getElementById('display_action').value = ''; + } + } + + function toggleEnabled (source, value, target) { + var sourceElement = YAHOO.util.Dom.get(source); + var targetElement = YAHOO.util.Dom.get(target); + if (sourceElement[sourceElement.selectedIndex].value == value) { + targetElement.disabled = false; + targetElement.focus(); + } + else { + targetElement.disabled = true; + } + } + + function isFilledOut(elem_id) { + var str = document.getElementById(elem_id).value; + return str.length > 0 && str != "noneselected"; + } + + YAHOO.util.Event.onDOMReady(function () { + setType(document.getElementById('incident_type')); + toggleEnabled('userdata', 'Yes', 'sensitivedata'); + toggleEnabled('rememberpasswords', 'Yes', 'criticalsites'); + }); +</script> + +<p><strong>Please use this form for employee incidents only!</strong></p> +<p>If you have a [% terms.bug %] to file, go <a href="enter_bug.cgi">here</a>.</p> +<p><span style="color: red;">*</span> Required Fields</p> +<form method="post" action="post_bug.cgi" id="incidentForm" enctype="multipart/form-data" + onSubmit="return validateAndSubmit();"> + <input type="hidden" id="product" name="product" value=""> + <input type="hidden" id="component" name="component" value=""> + <input type="hidden" id="rep_platform" name="rep_platform" value="All"> + <input type="hidden" id="op_sys" name="op_sys" value="All"> + <input type="hidden" id="priority" name="priority" value="--"> + <input type="hidden" id="version" name="version" value="other"> + <input type="hidden" id="cc" name="cc" value=""> + <input type="hidden" id="groups" name="groups" value=""> + <input type="hidden" id="format" name="format" value="employee-incident"> + <input type="hidden" id="bug_severity" name="bug_severity" value=""> + <input type="hidden" id="display_action" name="display_action" value=""> + <input type="hidden" id="token" name="token" value="[% token FILTER html %]"> + + <table> + <tr> + <td align="right" valign="top"><strong>Incident Type:</strong></td> + <td> + <select id="incident_type" name="incident_type" onchange="setType(this);"> + <option value="safety" selected>Report a Safety Concern</option> + <option value="stolen">My laptop or phone was lost/stolen</option> + </select> + <div id="type_desc" style="color:red;"></div> + </td> + </tr> + <tbody id="safety" class="bz_default_hidden"> + <tr class="safety"> + <td align="right"> + <strong><span style="color: red;">*</span> Summary:</strong> + </td> + <td> + <input name="short_desc" id="short_desc" size="60" + value="[% short_desc FILTER html %]"> + </td> + </tr> + </tbody> + <tbody id="stolen" class="bz_default_hidden"> + <tr> + <td align="right" valign="top"><strong>Stolen Details:</strong></td> + <td> + <table> + <tr> + <td> + <label for="device"> + <strong><span style="color: red;">*</span></strong> + Type of device lost: + </label> + </td> + <td> + <select name="device" id="device"> + <option value="">---</option> + <option value="Mobile Phone">Mobile Phone</option> + <option value="Tablet">Tablet</option> + <option value="Laptop">Laptop</option> + <option value="WorkStation">WorkStation</option> + <option value="Portable Storage Device">Portable Storage Device</option> + <option value="Other">Other (describe in 'Extra Notes')</option> + </select> + </td> + </tr> + <tr> + <td> + <label for="encrypted"> + <strong><span style="color: red;">*</span></strong> + To your knowledge, was your device encrypted? + </label> + </td> + <td> + <select name="encrypted" id="encrypted"> + <option value="">---</option> + <option value="No">No</option> + <option value="Yes">Yes</option> + </select> + </td> + </tr> + <tr> + <td> + <label for="userdata"> + <strong><span style="color: red;">*</span></strong> + Did you have any user data on your device? + </label> + </td> + <td> + <select name="userdata" id="userdata" + onchange="toggleEnabled('userdata', 'Yes', 'sensitivedata');"> + <option value="">---</option> + <option value="No">No</option> + <option value="Yes">Yes</option> + </select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td> </td> + <td>If yes, what sensitive data was stored on your device?</td> + </tr> + <tr> + <td> </td> + <td> + <textarea name="sensitivedata" id="sensitivedata" rows="10" cols="80"></textarea> + </td> + </tr> + <tr> + <td> </td> + <td> + <label for="rememberpasswords"> + <strong><span style="color: red;">*</span></strong> + Was your browser configured to remember passwords + (<a href="http://support.mozilla.com/en-US/kb/make-firefox-remember-usernames-and-passwords">more info</a>)? + </label> + <select name="rememberpasswords" id="rememberpasswords" + onchange="toggleEnabled('rememberpasswords', 'Yes', 'criticalsites');"> + <option value="">---</option> + <option value="No">No</option> + <option value="Yes">Yes</option> + </select> + </td> + </tr> + <tr> + <td> </td> + <td>If yes, which critical sites were included?</td> + </tr> + <tr> + <td> </td> + <td> + <textarea name="criticalsites" id="criticalsites" rows="10" cols="80"></textarea> + </td> + </tr> + </tbody> + <tr> + <td align="right" valign="top"><strong>Extra Notes:</strong></td> + <td> + <textarea name="comment" rows="10" cols="80"> + [% comment FILTER html %]</textarea> + </td> + </tr> + <tr> + <td> </td> + <td> + <input type="submit" id="commit" value="Submit Request"> + </td> + </tr> + </table> +</form> + +<p> + Thanks for contacting us. You will be notified by email of any progress made in resolving your request. +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl new file mode 100644 index 000000000..637eae57a --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl @@ -0,0 +1,188 @@ +[%# 1.0@bugzilla.org %] +[%# 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): Gervase Markham <gerv@gerv.net> + # Ville Skyttä <ville.skytta@iki.fi> + # John Hoogstrate <hoogstrate@zeelandnet.nl> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Corporation/Foundation IT Requests" + javascript_urls = [ 'js/field.js' ] + yui = [ 'autocomplete' ] +%] + +[% USE Bugzilla %] + +<p><strong>Please use this form for IT requests only!</strong></p> +<p>If you have a [% terms.bug %] to file, go <a href="enter_bug.cgi">here</a>.</p> + +<form method="post" action="post_bug.cgi" id="itRequestForm" enctype="multipart/form-data"> + <input type="hidden" name="product" value="mozilla.org"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="version" value="other"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + <script type="text/javascript"> + <!-- + function setsevdesc(theSelect) { + var theValue = theSelect.options[theSelect.selectedIndex].value; + if (theValue == 'blocker') { + document.getElementById('blockerdesc').style.display = 'block'; + document.getElementById('critdesc').style.display = 'none'; + } else if (theValue == 'critical') { + document.getElementById('blockerdesc').style.display = 'none'; + document.getElementById('critdesc').style.display = 'block'; + } else { + document.getElementById('blockerdesc').style.display = 'none'; + document.getElementById('critdesc').style.display = 'none'; + } + } + var compdesc = new Array(); + [% FOREACH comp IN product.components %] + compdesc['[% comp.name FILTER js %]'] = '[% comp.description FILTER js %]'; + [% END %] + compdesc['invalid'] = ''; + function setcompdesc(theRadio) { + var theValue = theRadio.value; + document.getElementById('compdescription').innerHTML = compdesc[theValue]; + } + // --> + </script> + <table> + <tr> + + <td align="right"> + <strong>Urgency:</strong> + </td> + + <td> + <select id="bug_severity" name="bug_severity" onchange="setsevdesc(this)"> + <option value="blocker">All work for IT stops until this is done</option> + <option value="critical">IT should work on it soon as possible (urgent)</option> + <option value="major">IT should get to it within 24 hours</option> + <option value="normal">IT should get to it within the next week</option> + <option value="minor" selected="selected">No rush, but hopefully IT can get to it soon</option> + <option value="trivial">Whenever IT can get around to it</option> + <option value="enhancement">This is just an idea, filing it so we don't forget</option> + </select> + </td> + <td> + <div id="blockerdesc" style="color:red;display:none">This will page the on-call sysadmin if not handled within 30 minutes.</div> + <div id="critdesc" style="color:red;display:none">This will page the on-call sysadmin if not handled within 8 hours.</div> + </td> + + </tr> + <tr> + <td align="right"><strong>Request Type:</strong></td> + <td style="white-space: nowrap;"> + <input type="radio" name="component" id="componentac" onclick="setcompdesc(this)" value="Server Operations: Account Requests"> + <label for="componentac">Request an LDAP/E-mail/etc. account</label><br> + <input type="radio" name="component" id="componentmvd" onclick="setcompdesc(this)" value="Server Operations: Desktop Issues"> + <label for="componentmvd">Desktop/Laptop/Printer/Phone/Tablet/License problem/order/request</label><br> + <input type="radio" name="component" id="componenttbm" onclick="setcompdesc(this)" value="Server Operations: RelEng"> + <label for="componenttbm">Report a problem with a tinderbox machine</label><br> + <input type="radio" name="component" id="componentwcp" onclick="setcompdesc(this)" value="Server Operations: Web Operations"> + <label for="componentwcp">Report a problem with a Mozilla website, or to request a change or push</label><br> + <input type="radio" name="component" id="componentacl" onclick="setcompdesc(this)" value="Server Operations: ACL Request"> + <label for="componentacl">Request a firewall change</label><br> + <input type="radio" name="component" id="componentso" onclick="setcompdesc(this)" value="Server Operations"> + <label for="componentso">Any other issue</label><br> + Mailing list requests should be filed <a href="[% ulrbase FILTER none %]enter_bug.cgi?product=mozilla.org&format=mozlist">here</a> instead. + </td> + <td id="compdescription" align="left" style="color: green; padding-left: 1em"> + </td> + <tr> + <td align="right"><strong>Summary:</strong></td> + <td colspan="3"> + <input name="short_desc" size="60" value="[% short_desc FILTER html %]"> + </td> + </tr> + + <tr> + <td align="right"><strong>CC (optional):</strong></td> + <td colspan="3"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 60 + multiple => 5 + %] + </td> + </tr> + + <tr><td align="right" valign="top"><strong>Description:</strong></td> + <td colspan="3"> + <textarea name="comment" rows="10" cols="80"> + [% comment FILTER html %]</textarea> + <br> + </td> + </tr> + + <tr> + <td align="right"><strong>URL (optional):</strong></td> + <td colspan="3"> + <input name="bug_file_loc" size="60" + value="[% bug_file_loc FILTER html %]"> + </td> + </tr> + + <tr><td colspan="4"> </td></tr> + + <tr> + <td colspan="4"> + <strong>Attachment (optional):</strong> + </td> + </tr> + + <tr> + <td align="right">File:</td> + <td colspan="3"> + <em>Enter the path to the file on your computer.</em><br> + <input type="file" id="data" name="data" size="50"> + <input type="hidden" name="contenttypemethod" value="autodetect" /> + </td> + </tr> + + <tr> + <td align="right">Description:</td> + <td colspan="3"> + <em>Describe the attachment briefly.</em><br> + <input type="text" id="description" name="description" size="60" maxlength="200"> + </td> + </tr> + </table> + + <br> + <!-- infra [% terms.bugs %] --> + <input type="checkbox" name="groups" id="groups" value="infra" checked="checked"><label for="groups"><strong>This is an internal issue which should not be publicly visible.</strong></label><br>(please uncheck this box if it isn't) + <br><br> + + <input type="submit" id="commit" value="Submit Request"> +</form> + +<p>Thanks for contacting us. + You will be notified by email of any progress made in resolving your + request. +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl new file mode 100644 index 000000000..15941c8ab --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl @@ -0,0 +1,220 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Mozilla Corporation. + # Portions created by Mozilla are Copyright (C) 2008 Mozilla + # Corporation. All Rights Reserved. + # + # Contributor(s): Mark Smith <mark@mozilla.com> + # Reed Loden <reed@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Corporation Legal Requests" + style_urls = [ 'skins/standard/attachment.css' ] + javascript_urls = [ 'js/attachment.js', 'js/field.js' ] + yui = [ 'autocomplete' ] +%] + +[% IF user.in_group("mozilla-corporation-confidential") + OR user.in_group("mozilla-messaging-confidential") + OR user.in_group("mozilla-foundation-confidential") %] + +<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>MoLegal</div> + +<p><strong>Welcome to MoLegal.</strong> For legal help please fill in the form below completely.</p> + +<p>Legal [% terms.bugs %] are only visible to the reporter, members of the legal team, and those on the +CC list. This is necessary to maintain attorney-client privilege. Please do not add non- +employees to the cc list.</p> + +<p><strong>All Submissions, And Information Provided In Response To This Request, +Are Confidential And Subject To The Attorney-Client Privilege And Work Product Doctrine.</strong></p> + +<form method="post" action="post_bug.cgi" id="legalRequestForm" enctype="multipart/form-data"> + <input type="hidden" name="product" value="Legal"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="version" value="unspecified"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="bug_severity" value="normal"> + <input type="hidden" name="format" value="legal"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + [% IF user.in_group('canconfirm') %] + <input type="hidden" name="bug_status" value="NEW"> + [% END %] + +<table> + +<tr> + <td align="right" width="170px"><strong>Request Type:</strong></td> + <td> + <select name="component"> + [%- FOREACH c = product.components %] + [% NEXT IF NOT c.is_active %] + <option value="[% c.name FILTER html %]" + [% " selected=\"selected\"" IF c.name == "General" %]> + [% c.name FILTER html -%] + </option> + [%- END %] + </select> + </td> +</tr> + +<tr> + <td align="right" valign="top"> + <strong>Goal:</strong> + </td> + <td colspan="3"> + <em>Identify the company goal this request maps to.</em><br> + <input name="goal" id="goal" size="60" value="[% goal FILTER html %]"> + </td> +</tr> + +<tr> + <td align="right"> + <strong>Priority to your Team:</strong> + </td> + <td> + <select id="teampriority" name="teampriority"> + <option value="High">High</option> + <option value="Medium">Medium</option> + <option value="Low" selected="selected">Low</option> + </select> + </td> +</tr> + +<tr> + <td align="right"> + <strong>Timeframe for Completion:</strong> + </td> + <td> + <select id="timeframe" name="timeframe"> + <option value="2 days">2 days</option> + <option value="a week">a week</option> + <option value="2-4 weeks">2-4 weeks</option> + <option value="this will take a while, but please get started soon"> + this will take a while, but please get started soon</option> + <option value="no rush" selected="selected">no rush</option> + </select> + </td> +</tr> + +<tr> + <td align="right" valign="top"> + <strong>Summary:</strong> + </td> + <td colspan="3"> + <em>Include the name of the vendor, partner, product, or other identifier.</em><br> + <input name="short_desc" size="60" value="[% short_desc FILTER html %]"> + </td> +</tr> + +<tr> + <td align="right"> + <strong>CC (optional):</strong> + </td> + <td colspan="3"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 60 + multiple => 5 + %] + </td> +</tr> + +<tr> + <td align="right" valign="top"> + <strong>Name of Other Party:</strong> + </td> + <td> + <em>If applicable, include full legal entity name, address, and any other relevant contact information.</em><br> + <textarea id="otherparty" name="otherparty" rows="3" cols="80"></textarea> + </td> +</tr> + +<tr> + <td align="right"> + <strong>Business Objective:</strong> + </td> + <td> + <input type="text" name="busobj" id="busobj" value="" size="60" /> + </td> +</tr> + +<tr> + <td align="right" valign="top"> + <strong>Description:</strong> + </td> + <td colspan="3"> + <em>Describe your question, what you want and/or provide any relevant deal terms, restrictions,<br> + or provisions that are applicable. Also provide context and background.</em><br> + <textarea id="comment" name="comment" rows="10" cols="80"> + [% comment FILTER html %]</textarea> + </td> +</tr> + +<tr> + <td align="right"><strong>URL (optional):</strong></td> + <td colspan="3"> + <input name="bug_file_loc" size="60" + value="[% bug_file_loc FILTER html %]"> + </td> +</tr> + +<tr> + <td></td> + <td colspan=2><strong>Attachment (this is optional)</strong></td> +</tr> + +<tr> + <td align="right" valign="top"> + <strong><label for="data">File:</label></strong> + </td> + <td> + <em>Enter the path to the file on your computer.</em><br> + <input type="file" id="data" name="data" size="50"> + <input type="hidden" name="contenttypemethod" value="autodetect" /> + </td> +</tr> + +<tr> + <td align="right" valign="top"> + <strong><label for="description">Description:</label></strong> + </td> + <td> + <em>Describe the attachment briefly.</em><br> + <input type="text" id="description" name="description" size="60" maxlength="200"> + </td> +</tr> + +</table> + +<br> + + <input type="submit" id="commit" value="Submit Request"> +</form> + +<p>Thanks for contacting us. You will be notified by email of any progress made in resolving your request.</p> + +[% ELSE %] + +<p>Sorry, you do not have access to this page.</p> + +[% END %] + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl new file mode 100644 index 000000000..ea60f6c19 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl @@ -0,0 +1,251 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Mozilla Corporation. + # Portions created by Mozilla are Copyright (C) 2008 Mozilla + # Corporation. All Rights Reserved. + # + # Contributor(s): Reed Loden <reed@mozilla.com> + # David Tran <dtran@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Event Request Form" + javascript_urls = [ 'extensions/BMO/web/js/form_validate.js', + 'js/field.js', + 'js/util.js' ] + style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }" + yui = [ 'autocomplete', 'calendar' ] +%] + +<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Event Request Form</div> + +<p><strong>Event Request:</strong> Please use this form to file a request for an event. <b>This form is not a request for swag.</b></p> + +<p>Process:</p> + +<ol> + <li>Complete and submit request below.</li> + <li>Your request will be reviewed by the appropriate person in the Engagement team.</li> +</ol> + +<p>These requests will only be visible to the person who submitted the request, +any persons designated in the CC line, and authorized members of the Mozilla +Engagement team.</p> + +<script language="javascript" type="text/javascript"> +function trySubmit() { + + var date = document.getElementById('date').value; + var eventname = document.getElementById('eventname').value; + var shortdesc = 'Event Request (' + date + ') - ' + eventname; + document.getElementById('short_desc').value = shortdesc; + if(!isChecked('doing-other')) document.getElementById('doing-other-what').value = ''; + return true; +} + +function validateAndSubmit() { + + var alert_text = ''; + if(!isFilledOut('firstname')) alert_text += "Please enter your first name\n"; + if(!isFilledOut('lastname')) alert_text += "Please enter your last name\n"; + if(!isValidEmail(document.getElementById('email').value)) alert_text += "Please enter a valid email address\n"; + if(!isFilledOut('eventname')) alert_text += "Please enter an event name.\n"; + if(!isFilledOut('website')) alert_text += "Please enter an event website.\n"; + if(!isFilledOut('goals')) alert_text += "Please enter the Description and Objectives.\n"; + if(!isFilledOut('date')) alert_text += "Please enter an event date.\n"; + if(!isFilledOut('goals')) alert_text += "Please enter the event goals.\n"; + if(!isFilledOut('successmeasure')) alert_text += "Please enter how you will measure the success of the event.\n"; + + if(!isChecked('doing-booth') && + !isChecked('doing-speaking') && + !isChecked('doing-outreach') && + !isChecked('doing-other') + ) alert_text += "Please indicate what you'll be doing at the event.\n"; + if(isChecked('doing-other') && !isFilledOut('doing-other-what')) alert_text += "Please describe what 'other' thing you'll be doing at the event.\n"; + + //Everything required is filled out..try to submit the form! + if(alert_text == '') { + return trySubmit(); + } + + //alert text, stay here on the pagee + alert(alert_text); + return false; +} + +</script> + +<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data" + onSubmit="return validateAndSubmit();"> + + <input type="hidden" name="format" value="mktgevent"> + <input type="hidden" name="product" value="Marketing"> + <input type="hidden" name="component" value="Event Requests"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="version" value="unspecified"> + <input type="hidden" name="bug_severity" id="bug_severity" value="normal"> + <input type="hidden" name="short_desc" id="short_desc" value=""> + <input type="hidden" name="groups" value="mozilla-corporation-confidential"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + +<table> + +<tr> + <td align="right"><strong>First Name: <span style="color: red;">*</span></strong></td> + <td align="left"> + <input type="text" name="firstname" id="firstname" value="" size="20" maxlength="20" /> + </td> +</tr> +<tr> + <td align="right"><strong>Last Name: <span style="color: red;">*</span></strong></td> + <td align="left"> + <input type="text" name="lastname" id="lastname" value="" size="20" maxlength="20"/> + </td> +</tr> + +<tr> + <td align="right"><strong>Email Address: <span style="color: red;">*</span></strong></td> + <td> + <input type="text" name="email" id="email" value="" size="50" maxlength="50"/> + </td> +</tr> + +<tr> + <td align="right"><strong>CC (optional):</strong></td> + <td colspan="3"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 50 + multiple => 5 + %] + </td> +</tr> + +<tr> + <td><!-- spacer --> </td> +</tr> + +<tr> + <td><!-- spacer --> </td> +</tr> + +<tr> + <td align="right"><strong>Event Name: <span style="color: red;">*</span></strong></td> + <td> + <input type="text" name="eventname" id="eventname" value="" size="50" maxlength="50"/> + </td> +</tr> + +<tr> + <td align="right"><strong>Event Date: <span style="color: red;">*</span></strong></td> + <td> + <input type="text" id="date" name="date" size="10" + onchange="updateCalendarFromField(this)"> + <button type="button" class="calendar_button" id="button_calendar_date" + onclick="showCalendar('date')"><span>Calendar</span> + </button> + <div id="con_calendar_date"></div> + </td> +</tr> + +<tr> + <td align="right"><strong>Event Location: <span style="color: red;">*</span></strong><br /><small>(City, Country; or City, State)</small></td> + <td> + <input type="text" name="location" id="location" value="" size="50" maxlength="80" /> + </td> +</tr> + +<tr> + <td align="right"><strong>Event Website: <span style="color: red;">*</span></strong></td> + <td> + <input type="text" name="website" id="website" value="" size="50" maxlength="120" /> + </td> +</tr> + +<tr> + <td align="right"><strong>Event Description and Key Objectives: <span style="color: red;">*</span></strong></td> + <td> + <textarea id="goals" name="goals" rows="5" cols="50"></textarea> + </td> +</tr> + +<tr> + <td align="right"><strong>What will you be doing at the event? <span style="color: red;">*</span></strong></td> + <td> + <input type="checkbox" id="doing-booth" name="doing" value="Booth or Table"><label for="doing-booth">Booth/Table</label><br /> + <input type="checkbox" id="doing-speaking" name="doing" value="Speaking Opportunity"><label for="doing-speaking">Speaking Opportunity</label><br /> + <input type="checkbox" id="doing-outreach" name="doing" value="PR or Media Outreach"><label for="doing-outreach">PR or Media Outreach</label><br /> + <input type="checkbox" id="doing-other" name="doing" value="Other"><label for="doing-other">Other, please explain:</label> + <input type="text" name="doing-other-what" id="doing-other-what" value="" size="50" maxlength="120"><br /> + </td> +</tr> + +<tr> + <td><!-- spacer --> </td> +</tr> + +<tr> + <td align="right"><strong>How many attendees will be at the event?</strong></td> + <td> + <select name="attendees" id="attendees"> + <option value="--Please Select--" selected>--Please Select--</option> + <option value="1-99">1-99</option> + <option value="100-499">100-499</option> + <option value="500-999">500-999</option> + <option value="1000+">1000+</option> + </select> + </td> +</tr> + +<tr> + <td align="right"><strong>Targeted Audience:</strong></td> + <td> + <select name="audience" id="audience"> + <option value="--Please Select--" selected>--Please Select--</option> + <option value="Contributors">Contributors (Developers, Education, Security, Designers, Localization, Support & Marketing)</option> + <option value="Potential New Users">Potential New Users</option> + <option value="User Community">User Community (Recent adopters, fans, Mozilla product evangelizers)</option> + </select> + </td> +</tr> + +<tr> + <td align="right"><strong>How will you measure the<br />success of your event? <span style="color: red;">*</span></strong></td> + <td> + <textarea id="successmeasure" name="successmeasure" rows="5" cols="50"></textarea> + </td> +</tr> + + + </table> + <br> + <input type="submit" id="commit" value="Submit Request"> + +<p> + <strong><span style="color: red;">*</span></strong> - Required field<br /> + Thanks for contacting us. + +</p> + +<script type="text/javascript"> + createCalendar('date'); +</script> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl new file mode 100644 index 000000000..39a372351 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl @@ -0,0 +1,306 @@ +[%# 1.0@bugzilla.org %] +[%# 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): Gervase Markham <gerv@gerv.net> + # Ville Skyttä <ville.skytta@iki.fi> + # John Hoogstrate <hoogstrate@zeelandnet.nl> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Discussion Forum / Mailing List Requests" + javascript_urls = [ 'extensions/BMO/web/js/form_validate.js', + 'js/field.js' ] + yui = [ 'autocomplete' ] +%] + +<script type="text/javascript"> +<!-- + function toggleGroup (theRadio) { + var radioValue = theRadio.value; + var groupDiv = YAHOO.util.Dom.get('groups'); + var group = YAHOO.util.Dom.get('group_35'); + if (radioValue == 'lists.mozilla.org') { + YAHOO.util.Dom.setStyle('listNameTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listNameDiscussion', 'display', 'inline'); + YAHOO.util.Dom.setStyle('listNameOther', 'display', 'none'); + YAHOO.util.Dom.setStyle('listAdminTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listShortDescTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listShortDescMailman', 'display', 'inline'); + YAHOO.util.Dom.setStyle('listShortDescZimbra', 'display', 'none'); + YAHOO.util.Dom.setStyle('listLongDescTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listCommentTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('CCTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('URLTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('groups', 'display', 'none'); + group.disabled = true; + YAHOO.util.Dom.setStyle('submitDiv', 'display', 'block'); + } else if (radioValue == 'mozilla.org') { + YAHOO.util.Dom.setStyle('listNameTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listNameDiscussion', 'display', 'none'); + YAHOO.util.Dom.setStyle('listNameOther', 'display', 'inline'); + YAHOO.util.Dom.setStyle('listAdminTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listShortDescTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listShortDescMailman', 'display', 'inline'); + YAHOO.util.Dom.setStyle('listShortDescZimbra', 'display', 'none'); + YAHOO.util.Dom.setStyle('listLongDescTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listCommentTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('CCTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('URLTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('groups', 'display', 'table-row'); + group.disabled = false; + YAHOO.util.Dom.setStyle('submitDiv', 'display', 'block'); + } else { + YAHOO.util.Dom.setStyle('listNameTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listNameDiscussion', 'display', 'none'); + YAHOO.util.Dom.setStyle('listNameOther', 'display', 'inline'); + YAHOO.util.Dom.setStyle('listAdminTR', 'display', 'none'); + YAHOO.util.Dom.setStyle('listShortDescTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('listShortDescMailman', 'display', 'none'); + YAHOO.util.Dom.setStyle('listShortDescZimbra', 'display', 'inline'); + YAHOO.util.Dom.setStyle('listLongDescTR', 'display', 'none'); + YAHOO.util.Dom.setStyle('listCommentTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('CCTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('URLTR', 'display', 'table-row'); + YAHOO.util.Dom.setStyle('groups', 'display', 'table-row'); + group.disabled = false; + YAHOO.util.Dom.setStyle('submitDiv', 'display', 'block'); + } + } + + function trySubmit() { + var listName = document.getElementById('listName').value; + var listAdmin = document.getElementById('listAdmin').value; + var listTypeRadio = document.getElementsByName('listType'); + var listType = ""; + + for (var i = 0; i < listTypeRadio.length; i++) { + if (listTypeRadio[i].checked) { + listType = listTypeRadio[i].value; + } + } + + var alert_text = ""; + var short_desc = ""; + + if (listType) { + if (listType == "lists.mozilla.org") { + document.getElementById('component').value = "Discussion Forums"; + short_desc = "Discussion Forum: " + listName; + } else if (listType == "mozilla.com" ) { + document.getElementById('component').value = "Server Operations: Desktop Issues"; + short_desc = "[Zimbra Distribution List Request] " + listName + "@" + listType; + } else { + document.getElementById('component').value = "Server Operations"; + short_desc = "[Mailman List Request] " + listName + "@" + listType; + } + } else { + alert_text += "Please select a list type\n"; + } + + if (!isFilledOut('listName')) { + alert_text += "Please enter the list name\n"; + } + + if ((!isValidEmail(listAdmin)) && (listType != 'mozilla.com')) { + alert_text += "Please enter a valid email address for the list administrator\n"; + } + + if (alert_text) { + alert(alert_text); + return false; + } + + document.getElementById('short_desc').value = short_desc; + + return true; + } +// --> +</script> + +<form method="post" action="post_bug.cgi" id="mozListRequestForm" + enctype="multipart/form-data" onSubmit="return trySubmit();"> + <input type="hidden" id="format" name="format" value="mozlist"> + <input type="hidden" id="product" name="product" value="mozilla.org"> + <input type="hidden" id="rep_platform" name="rep_platform" value="All"> + <input type="hidden" id="op_sys" name="op_sys" value="Other"> + <input type="hidden" id="priority" name="priority" value="--"> + <input type="hidden" id="version" name="version" value="other"> + <input type="hidden" id="short_desc" name="short_desc" value=""> + <input type="hidden" id="component" name="component" value=""> + <input type="hidden" id="bug_severity" name="bug_severity" value="normal"> + <input type="hidden" id="token" name="token" value="[% token FILTER html %]"> + + <table> + <tr id="listTypeTR" style="display: table-row;"> + <td align="right" width="15%"><strong>List Type:</strong></td> + <td> + <dl> + <dt> + <input type="radio" name="listType" id="lists_mozilla_org" + onclick="toggleGroup(this);" value="lists.mozilla.org"> + <label for="lists_mozilla_org">Standard Discussion Forum</label> + </dt> + <dd> + <label for="lists_mozilla_org"> + This option gives you a Mozilla <a href="https://www.mozilla.org/about/forums/">Discussion Forum</a>. + These are the normal mechanism for public discussion in the Mozilla project. They are made up of a + mailing list, a newsgroup and a Google Group (which maintains the list archives), all linked together. + Users can add and remove themselves. If you aren't sure, pick this one. + </label> + </dd> + <dt> + <input type="radio" name="listType" id="mozilla_org" + onclick="toggleGroup(this);" value="mozilla.org"> + <label for="mozilla_org">Mailing List Only</label> + </dt> + <dd> + <label for="mozilla_org"> + This option gives you a mailing list without the other access mechanisms. The + list can be private, although Mozilla is an "open by default" organization so + you need a good reason to have a private list. The archives are maintained by + Mailman, our mailing list software. Subscription can be open or + moderator-controlled. This type of list is normally hosted on the <b>mozilla.org</b> domain. + </label> + </dd> + <dt> + <input type="radio" name="listType" id="mozilla_com" + onclick="toggleGroup(this)" value="mozilla.com"> + <label for="mozilla_com">Distribution List</label> + </dt> + <dd> + <label for="mozilla_com"> + This option gives you a distribution list - basically, a mail exploder - on + mozilla.com. (This option is only appropriate for things which relate + specifically to Mozilla Corporation, such as confidential partner projects + or internal department lists.) Send email to the address, and it gets remailed + out to everyone on the list. There are no archives, and the "subscriber" list + is controlled by the IT team. + </label> + </dd> + </dl> + <hr> + </td> + </tr> + <tr id="listNameTR" style="display: none;"> + <td align="right" valign="top"><strong>List Name:</strong></td> + <td> + <input name="listName" id="listName" size="60" value="[% listName FILTER html %]"><br> + <span id="listNameDiscussion" style="display: none;">The desired name for the newsgroup. Should start with 'mozilla.' and fit somewhere in the hierarchy described <a href="https://www.mozilla.org/about/forums/">here</a>.</span> + <span id="listNameOther" style="display: none;">Only enter the part before the @, the domain name is chosen based on the list type.</span> + <hr> + </td> + </tr> + <tr id="listAdminTR" style="display: none;"> + <td align="right" valign="top" width="15%"><strong>List Administrator:</strong></td> + <td> + [% INCLUDE global/userselect.html.tmpl + id => "listAdmin" + name => "listAdmin" + value => "" + size => 60 + multiple => 5 + %] + <br> + <b>Note:</b>The list administrator is also initially considered to be the list moderator + and will be responsible for moderation tasks unless delegated to someone else. For + convenience, [% terms.Bugzilla %] user accounts will autocomplete. The administrator is not required + to have a [% terms.Bugzilla %] account, and you can enter an address that doesn't autocomplete if + necessary.<hr /> + </td> + </tr> + <tr id="listShortDescTR" style="display: none;"> + <td align="right" valign="top"><strong>Short one-line description:</strong></td> + <td> + <input name="listShortDesc" id="listShortDesc" size="60" value="[% listShortDesc FILTER html %]"><br /> + <span id="listShortDescMailman" style="display: none;">This will be shown to users on the index of lists on the server.</span> + <span id="listShortDescZimbra" style="display: none;">This will be shown as the "real name" in the Zimbra address book.</span> + <hr /> + </td> + </tr> + <tr id="listLongDescTR" style="display: none;"> + <td align="right" valign="top"><strong>Long description:</strong></td> + <td colspan="3"> + [% INCLUDE global/textarea.html.tmpl + name = 'listLongDesc' + id = 'listLongDesc' + minrows = 10 + maxrows = 25 + cols = constants.COMMENT_COLS + defaultcontent = listLongDesc + %] + <br>This will be shown at the top of the list's listinfo page. + <hr> + </td> + </tr> + <tr id="listCommentTR" style="display: none;"> + <td align="right" valign="top"><strong>Additional comments:</strong></td> + <td colspan="3"> + Justification for the list, special instructions, etc.<br> + [% INCLUDE global/textarea.html.tmpl + name = 'comment' + id = 'comment' + minrows = 10 + maxrows = 25 + cols = constants.COMMENT_COLS + defaultcontent = comment + %] + <hr> + </td> + </tr> + <tr id="CCTR" style="display: none;"> + <td align="right"><strong>CC (optional):</strong></td> + <td> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 60 + multiple => 5 + %] + </td> + </tr> + <tr id="URLTR" style="display: none;"> + <td align="right"><strong>URL (optional):</strong></td> + <td colspan="3"> + <input name="bug_file_loc" size="60" + value="[% bug_file_loc FILTER html %]"> + </td> + </tr> + </table> + <br> + + <div id="groups" style="display:none;"> + <!-- infra [% terms.bugs %] --> + <input type="checkbox" name="groups" id="group_35" value="infra" disabled="true"> + <label for="group_35"><strong>This is an internal issue which should not be publicly visible.</strong></label> + <br><br> + </div> + + <div id="submitDiv" style="display: none;"> + <input type="submit" id="commit" value="Submit Request"> + +<p> + Thanks for contacting us. You will be notified by email of any progress made + in resolving your request. +</p> + </div> +</form> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl new file mode 100644 index 000000000..a272e0b41 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl @@ -0,0 +1,654 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + # Ville Skyttä <ville.skytta@iki.fi> + # Shane H. W. Travis <travis@sedsystems.ca> + # Marc Schumann <wurblzap@gmail.com> + # Akamai Technologies <bugzilla-dev@akamai.com> + # Max Kanat-Alexander <mkanat@bugzilla.org> + # Frédéric Buclin <LpSolit@gmail.com> + #%] + +[% PROCESS "global/field-descs.none.tmpl" %] + +[% title = BLOCK %]Create a PR Request[% END %] + +[% PROCESS global/header.html.tmpl + title = title + style_urls = [ 'skins/standard/attachment.css' ] + javascript_urls = [ "js/attachment.js", "js/util.js", + "js/field.js", "js/TUI.js" ] + onload = 'set_assign_to();' + yui = [ 'autocomplete' ] +%] + +<script type="text/javascript"> +<!-- + +var initialowners = new Array([% product.components.size %]); +var last_initialowner; +var initialccs = new Array([% product.components.size %]); +var components = new Array([% product.components.size %]); +var comp_desc = new Array([% product.components.size %]); +var flags = new Array([% product.components.size %]); +[% IF Param("useqacontact") %] + var initialqacontacts = new Array([% product.components.size %]); + var last_initialqacontact; +[% END %] +[% count = 0 %] +[%- FOREACH c = product.components %] + [% NEXT IF NOT c.is_active %] + components[[% count %]] = "[% c.name FILTER js %]"; + comp_desc[[% count %]] = "[% c.description FILTER html_light FILTER js %]"; + initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]"; + [% flag_list = [] %] + [% FOREACH f = c.flag_types(is_active=>1).bug %] + [% flag_list.push(f.id) %] + [% END %] + [% FOREACH f = c.flag_types(is_active=>1).attachment %] + [% flag_list.push(f.id) %] + [% END %] + flags[[% count %]] = [[% flag_list.join(",") FILTER js %]]; + [% IF Param("useqacontact") %] + initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]"; + [% END %] + + [% SET initial_cc_list = [] %] + [% FOREACH cc_user = c.initial_cc %] + [% initial_cc_list.push(cc_user.login) %] + [% END %] + initialccs[[% count %]] = "[% initial_cc_list.join(', ') FILTER js %]"; + + [% count = count + 1 %] +[%- END %] + +function set_assign_to() { + // Based on the selected component, fill the "Assign To:" field + // with the default component owner, and the "QA Contact:" field + // with the default QA Contact. It also selectively enables flags. + var form = document.Create; + var assigned_to = form.assigned_to.value; + +[% IF Param("useqacontact") %] + var qa_contact = form.qa_contact.value; +[% END %] + + var index = -1; + if (form.component.type == 'select-one') { + index = form.component.selectedIndex; + } else if (form.component.type == 'hidden') { + // Assume there is only one component in the list + index = 0; + } + if (index != -1) { + var owner = initialowners[index]; + var component = components[index]; + if (assigned_to == last_initialowner + || assigned_to == owner + || assigned_to == '') { + form.assigned_to.value = owner; + last_initialowner = owner; + } + + document.getElementById('initial_cc').innerHTML = initialccs[index]; + document.getElementById('comp_desc').innerHTML = comp_desc[index]; + + [% IF Param("useqacontact") %] + var contact = initialqacontacts[index]; + if (qa_contact == last_initialqacontact + || qa_contact == contact + || qa_contact == '') { + form.qa_contact.value = contact; + last_initialqacontact = contact; + } + [% END %] + + // First, we disable all flags. Then we re-enable those + // which are available for the selected component. + var inputElements = document.getElementsByTagName("select"); + var inputElement, flagField; + for ( var i=0 ; i<inputElements.length ; i++ ) { + inputElement = inputElements.item(i); + if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) { + var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1"); + inputElement.disabled = true; + // Also disable the requestee field, if it exists. + inputElement = document.getElementById("requestee_type-" + id); + if (inputElement) inputElement.disabled = true; + } + } + // Now enable flags available for the selected component. + for (var i = 0; i < flags[index].length; i++) { + flagField = document.getElementById("flag_type-" + flags[index][i]); + // Do not enable flags the user cannot set nor request. + if (flagField && flagField.options.length > 1) { + flagField.disabled = false; + // Re-enabling the requestee field depends on the status + // of the flag. + toggleRequesteeField(flagField, 1); + } + } + } +} + +function fix_component() { + var form = document.Create; + var location = form.location.options[form.location.selectedIndex].value; + var fakecomp = form.fakecomp.options[form.fakecomp.selectedIndex].value; + var newcomp = location + " - " + fakecomp; + form.component.value = newcomp; + set_assign_to(); +} + +function handleWantsAttachment(wants_attachment) { + if (wants_attachment) { + document.getElementById('attachment_false').style.display = 'none'; + document.getElementById('attachment_true').style.display = 'block'; + } + else { + document.getElementById('attachment_false').style.display = 'block'; + document.getElementById('attachment_true').style.display = 'none'; + clearAttachmentFields(); + } +} + + +TUI_alternates['expert_fields'] = 'Show Advanced Fields'; +// Hide the Advanced Fields by default, unless the user has a cookie +// that specifies otherwise. +TUI_hide_default('expert_fields'); + +--> +</script> + +[% IF user.in_group("mozilla-confidential") %] + +[% USE Bugzilla %] +[% SET select_fields = {} %] +[% FOREACH field = Bugzilla.get_fields( + { type => constants.FIELD_TYPE_SINGLE_SELECT, custom => 0 }) +%] + [% select_fields.${field.name} = field %] +[% END %] + +<form name="Create" id="Create" method="post" action="post_bug.cgi" + enctype="multipart/form-data"> +<input type="hidden" name="product" value="[% product.name FILTER html %]"> +<input type="hidden" name="token" value="[% token FILTER html %]"> + +<table cellspacing="4" cellpadding="2" border="0" style="background: url(extensions/BMO/web/images/presshat.png) top right no-repeat"> +<tbody> + <tr> + <td colspan="2"> + <a id="expert_fields_controller" class="controller bz_default_hidden" + href="javascript:TUI_toggle_class('expert_fields')">Hide + Advanced Fields</a> + [%# Show the link if the browser supports JS %] + <script type="text/javascript"> + YAHOO.util.Dom.removeClass('expert_fields_controller', + 'bz_default_hidden'); + </script> + </td> + <td colspan="2"> + (<span class="required_star">*</span> = + <span class="required_explanation">Required Field</span>) + </td> + </tr> + + <tr> + <th>Product:</th> + <td width="10%">[% product.name FILTER html %]</td> + + <th>Reporter:</th> + <td width="100%">[% user.login FILTER html %]</td> + </tr> + + [%# We can't use the select block in these two cases for various reasons. %] +[% matches = default.component_.matches('^(.*) - (.*)$') %] +[% default.location = matches.0 %] +[% default.fakecomp = matches.1 %] +[% IF default.location == '' %] + [% default.location = 'US' %] +[% END %] +[% locations = [] %] +[% fakecomps = [] %] +[% FOREACH c = product.components %] + [% matches = c.name.match('^(.*) - (.*)$') %] + [% locations.push(matches.0) %] + [% fakecomps.push(matches.1) %] +[% END %] +[% locations = locations.unique %] +[% fakecomps = fakecomps.unique %] + <tr> + <th class="required"> + Location: + </th> + <td> + + <select name="location" onchange="fix_component();" size="7"> + [% FOREACH l = locations %] + <option value="[% l FILTER html %]" [% " selected=\"selected\"" IF l == default.location %]> + [% l FILTER html %] + </option> + [% END %] + </select> + <select name="component" onchange="set_assign_to();" size="7" + aria-required="true" class="required" style="display: none;"> + [%# Build the lists of assignees and QA contacts if "usemenuforusers" is enabled. %] + [% IF Param("usemenuforusers") %] + [% assignees_list = user.get_userlist.clone %] + [% qa_contacts_list = user.get_userlist.clone %] + [% END %] + + [%- FOREACH c = product.components %] + [% NEXT IF NOT c.is_active %] + <option value="[% c.name FILTER html %]" + [% " selected=\"selected\"" IF c.name == default.component_ %]> + [% c.name FILTER html -%] + </option> + [% IF Param("usemenuforusers") %] + [% INCLUDE build_userlist default_user = c.default_assignee, + userlist = assignees_list %] + [% INCLUDE build_userlist default_user = c.default_qa_contact, + userlist = qa_contacts_list %] + [% END %] + [%- END %] + </select> + </td> + + </tr> + <tr> + <th> + Request type: + </th> + <td> + + <select name="fakecomp" onchange="fix_component();" size="7"> + [% FOREACH f = fakecomps %] + <option value="[% f FILTER html %]" [% " selected=\"selected\"" IF f == default.fakecomp %]> + [% f FILTER html %] + </option> + [% END %] + </select> + </td> + <td colspan="2"> + [%# Enclose the fieldset in a nested table so that its width changes based + # on the length on the component description. %] + <table> + <tr> + <td> + <fieldset> + <legend>Request Description</legend> + <div id="comp_desc" class="comment">Select a request type to read its description.</div> + </fieldset> + </td> + </tr> + </table> + <input type="hidden" name="bug_severity" value="[% default.bug_severity FILTER html %]"> + <input type="hidden" name="rep_platform" value="[% default.rep_platform FILTER html %]"> + <input type="hidden" name="op_sys" value="[% default.op_sys FILTER html %]"> + <input type="hidden" name="version" value="unspecified"> + </td> + </tr> +</tbody> + +<tbody class="expert_fields"> + <tr> + <td colspan="4"> </td> + </tr> + + <tr> +[% IF bug_status.size <= 1 %] + <input type="hidden" name="bug_status" + value="[% default.bug_status FILTER html %]"> + <th>Initial State:</th> + <td>[% display_value("bug_status", default.bug_status) FILTER html %]</td> +[% ELSE %] + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.bug_status, + editable = (bug_status.size > 1), value = default.bug_status + override_legal_values = bug_status %] +[% END %] + + <td> </td> + [%# Calculate the number of rows we can use for flags %] + [% num_rows = 6 + (Param("useqacontact") ? 1 : 0) + + (user.is_timetracker ? 3 : 0) + + (Param("usebugaliases") ? 1 : 0) + %] + + <td rowspan="[% num_rows FILTER html %]"> + [% IF product.flag_types(is_active=>1).bug.size > 0 %] + [% display_flag_headers = 0 %] + [% any_flags_requesteeble = 0 %] + + [% FOREACH flag_type = product.flag_types(is_active=>1).bug %] + [% display_flag_headers = 1 %] + [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %] + [% END %] + + [% IF display_flag_headers %] + [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types(is_active=>1).bug + any_flags_requesteeble = any_flags_requesteeble + flag_table_id = "bug_flags" + %] + [% END %] + [% END %] + </td> + </tr> + + <tr> + <th><a href="page.cgi?id=fields.html#assigned_to">Assign To</a>:</th> + <td colspan="2"> + [% INCLUDE global/userselect.html.tmpl + id => "assigned_to" + name => "assigned_to" + value => assigned_to + disabled => assigned_to_disabled + size => 30 + emptyok => 1 + custom_userlist => assignees_list + %] + <noscript>(Leave blank to assign to component's default assignee)</noscript> + </td> + </tr> + +[% IF Param("useqacontact") %] + <tr> + <th>QA Contact:</th> + <td colspan="2"> + [% INCLUDE global/userselect.html.tmpl + id => "qa_contact" + name => "qa_contact" + value => qa_contact + disabled => qa_contact_disabled + size => 30 + emptyok => 1 + custom_userlist => qa_contacts_list + %] + <noscript>(Leave blank to assign to default qa contact)</noscript> + </td> + </tr> +[% END %] + + <tr> + <th>CC:</th> + <td colspan="2"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + disabled => cc_disabled + size => 30 + multiple => 5 + %] + </td> + </tr> + + <tr> + <th>Default CC:</th> + <td colspan="2"> + <div id="initial_cc"> + </div> + </td> + </tr> + + <tr> + <td colspan="3"> </td> + </tr> + +[% IF user.is_timetracker %] + <tr> + <th>Estimated Hours:</th> + <td colspan="2"> + <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]"> + </td> + </tr> + <tr> + <th>Deadline:</th> + <td colspan="2"> + <input name="deadline" size="10" maxlength="10" value="[% deadline FILTER html %]"> + <small>(YYYY-MM-DD)</small> + </td> + </tr> + + <tr> + <td colspan="3"> </td> + </tr> +[% END %] + +[% IF Param("usebugaliases") %] + <tr> + <th>Alias:</th> + <td colspan="2"> + <input name="alias" size="20" value="[% alias FILTER html %]"> + </td> + </tr> +[% END %] + + <tr> + <th>URL:</th> + <td colspan="2"> + <input name="bug_file_loc" size="40" + value="[% bug_file_loc FILTER html %]"> + </td> + </tr> +</tbody> + +<tbody> + + <tr> + <th class="required">Summary:</th> + <td colspan="3"> + <input name="short_desc" size="70" value="[% short_desc FILTER html %]" + maxlength="255" spellcheck="true" aria-required="true" + class="required"> + </td> + </tr> + + <tr> + <th>Description:</th> + <td colspan="3"> + [% defaultcontent = BLOCK %] + [% IF cloned_bug_id %] ++++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id FILTER html %] +++ + + + [% END %] + [%-# We are within a BLOCK. The comment will be correctly HTML-escaped + # by global/textarea.html.tmpl. So we must not escape the comment here. %] + [% comment FILTER none %] + [%- END %] + [% INCLUDE global/textarea.html.tmpl + name = 'comment' + id = 'comment' + minrows = 10 + maxrows = 25 + cols = constants.COMMENT_COLS + defaultcontent = defaultcontent + %] + <br> + </td> + </tr> + + [% IF user.is_insider %] + <tr class="expert_fields"> + <th> </th> + <td colspan="3"> + + <input type="checkbox" id="commentprivacy" name="commentprivacy" + [% " checked=\"checked\"" IF commentprivacy %]> + <label for="commentprivacy"> + Make description private (visible only to members of the + <strong>[% Param('insidergroup') FILTER html %]</strong> group) + </label> + </td> + </tr> + [% END %] + + <tr> + <th>Attachment:</th> + <td colspan="3"> + <script type="text/javascript"> + <!-- + document.write( '<div id="attachment_false">' + + '<input type="button" value="Add an attachment" ' + + 'onClick="handleWantsAttachment(true)"> ' + + '<em style="display: none">This button has no ' + + 'functionality for you because your browser does ' + + 'not support CSS or does not use it.<\/em>' + + '<\/div>' + + '<div id="attachment_true" style="display: none">' + + '<input type="button" ' + + 'value="Don\'t add an attachment " ' + + 'onClick="handleWantsAttachment(false)">'); + //--> + </script> + <fieldset> + <legend>Add an attachment</legend> + <table class="attachment_entry"> + [% PROCESS attachment/createformcontents.html.tmpl + flag_types = product.flag_types(is_active=>1).attachment + any_flags_requesteeble = 1 + flag_table_id ="attachment_flags" %] + </table> + </fieldset> + <script type="text/javascript"> + <!-- + document.write('<\/div>'); + //--> + </script> + </td> + </tr> +</tbody> + +<tbody class="expert_fields"> + [% IF user.in_group('editbugs', product.id) %] + [% IF use_keywords %] + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.keywords, editable = 1, + value = keywords, desc_url = "describekeywords.cgi", + value_span = 3 %] + </tr> + [% END %] + + <tr> + <th>Status Whiteboard:</th> + <td colspan="3"> + <input id="status_whiteboard" name="status_whiteboard" size="70" + value="[% status_whiteboard FILTER html %]"> + </td> + </tr> + <tr> + <th>Depends on:</th> + <td colspan="3"> + <input name="dependson" accesskey="d" value="[% dependson FILTER html %]"> + </td> + </tr> + <tr> + <th>Blocks:</th> + <td colspan="3"> + <input name="blocked" accesskey="b" value="[% blocked FILTER html %]"> + </td> + </tr> + [% END %] +</tbody> + +<tbody class="expert_fields"> + [% IF product.groups_available.size %] + <tr> + <th> </th> + <td colspan="3"> + <br> + <strong> + Only users in all of the selected groups can view this + [%+ terms.bug %]: + </strong> + <br> + <font size="-1"> + (Leave all boxes unchecked to make this a public [% terms.bug %].) + </font> + <br> + <br> + + <!-- Checkboxes --> + <input type="hidden" name="defined_groups" value="1"> + [% FOREACH group = product.groups_available %] + <input type="checkbox" id="group_[% group.id FILTER html %]" + name="groups" value="[% group.name FILTER html %]" + [% ' checked="checked"' IF default.groups.contains(group.name) + OR group.is_default %]> + <label for="group_[% group.id FILTER html %]"> + [%- group.description FILTER html_light %]</label><br> + [% END %] + </td> + </tr> + [% END %] +</tbody> + +<tbody> + [%# Form controls for entering additional data about the bug being created. %] + [% Hook.process("form") %] + + <tr> + <th> </th> + <td colspan="3"> + <input type="submit" id="commit" value="Submit [% terms.Bug %]" + onclick="if (this.form.short_desc.value == '') + { alert('Please enter a summary sentence for this [% terms.bug %].'); + return false; } return true;"> + + <input type="submit" name="maketemplate" id="maketemplate" + value="Remember values as bookmarkable template" + class="expert_fields"> + </td> + </tr> +</tbody> + </table> + <input type="hidden" name="form_name" value="enter_bug"> +</form> + +[%# Links or content with more information about the bug being created. %] +[% Hook.process("end") %] + +[% ELSE %] + +<p>Sorry, you do not have access to this page.</p> + +[% END %] + +[% PROCESS global/footer.html.tmpl %] + +[% BLOCK build_userlist %] + [% user_found = 0 %] + [% default_login = default_user.login %] + [% RETURN UNLESS default_login %] + + [% FOREACH user = userlist %] + [% IF user.login == default_login %] + [% user_found = 1 %] + [% LAST %] + [% END %] + [% END %] + + [% userlist.push({login => default_login, + identity => default_user.identity, + visible => 1}) + UNLESS user_found %] +[% END %] diff --git a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl new file mode 100644 index 000000000..e231cd9d5 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl @@ -0,0 +1,87 @@ +[%# 1.0@bugzilla.org %] +[%# 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): Gervase Markham <gerv@gerv.net> + # Ville SkyttŠ <ville.skytta@iki.fi> + # John Hoogstrate <hoogstrate@zeelandnet.nl> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Powered by Mozilla Logo Requests" +%] + +[% USE Bugzilla %] + +<p>If you are interested in using the <a href="http://www.mozilla.org/poweredby">Powered by Mozilla logo</a>, +please provide some information about your application or product.</p> + +<p><strong>Please use this form for Powered by Mozilla logo requests only.</strong></p> + +<form method="post" action="post_bug.cgi" id="tmRequestForm"> + + <input type="hidden" name="product" value="Marketing"> + <input type="hidden" name="component" value="Trademark Permissions"> + <input type="hidden" name="bug_severity" value="enhancement"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="version" value="unspecified"> + <input type="hidden" name="assigned_to" value="dboswell@mozilla.com"> + <input type="hidden" name="cc" value="liz@mozilla.com"> + <input type="hidden" name="groups" value="marketing-private"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + + <table> + <tr> + <td align="right"><strong>Application or Product Name:</strong></td> + <td colspan="3"> + <input name="short_desc" size="60" value="Powered by Mozilla request for: [% short_desc FILTER html %]"> + </td> + </tr> + + <tr> + <td align="right"><strong>URL (optional):</strong></td> + <td colspan="3"> + <input name="bug_file_loc" size="60" + value="[% bug_file_loc FILTER html %]"> + </td> + </tr> + + <tr><td align="right" valign="top"><strong>Comments (optional):</strong></td> + <td colspan="3"> + <textarea name="comment" rows="10" cols="80"> + [% comment FILTER html %]</textarea> + <br> + </td> + </tr> + + </table> + + <br> + + <input type="submit" id="commit" value="Submit Request"> +</form> + +<p>Thanks for contacting us. + You will be notified by email of any progress made in resolving your + request. +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl new file mode 100644 index 000000000..fd8d3c655 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl @@ -0,0 +1,219 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Mozilla Corporation. + # Portions created by Mozilla are Copyright (C) 2008 Mozilla + # Corporation. All Rights Reserved. + # + # Contributor(s): Reed Loden <reed@mozilla.com> + # David Tran <dtran@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Corporation Mountain View Presentation Request" + javascript_urls = [ 'js/field.js', 'js/util.js' ] + style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }" + yui = [ 'autocomplete', 'calendar' ] +%] + +<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Mountain View Presentation Request</div> + +<p><strong>Mountain View Presentation Request:</strong> Please use this form if you plan on hosting a presentation so that IT will be able to properly provide support. </p> + +<p>Process:</p> + +<ol><li>Complete and submit request below.</li> + <li>Your request will be reviewed and assigned to the appropriate person in IT.</li> +</ol> + +<p>These requests will only be visible internally in all cases and only to the +person who submitted the request and any persons designated in the CC line.</p> + +<script type="text/javascript"> +function trySubmit() { + var out = 'Topic: the_topic\r\nPresenter: the_presenter\r\nDate: the_date\r\nTime: the_time\r\nAudience: the_audience\r\nAir Mozilla: air_mozilla\r\nDial-in: dial_in\r\nArchive: to_archive\r\nMember of IT to help with A/V: it_help\r\nDescription: the_description'; + + var topic = document.getElementById('topic').value; + var presenter = document.getElementById('presenter').value; + var date = document.getElementById('date').value; + var time = document.getElementById('time_hour').value + ':' + document.getElementById('time_minute').value + document.getElementById('ampm').value; + var shortdesc = 'Mountain View Presentation Request - ' + topic + ' (' + date + ' ' + time + ')'; + var airmozilla = document.getElementById('airmozilla').checked? 'yes' : 'no'; + var dialin = document.getElementById('dialin').checked? 'yes' : 'no'; + var archive = document.getElementById('archive').checked? 'yes' : 'no'; + var ithelp = document.getElementById('ithelp').checked? 'yes' : 'no'; + + out = out.replace( /the_topic/, topic ); + out = out.replace( /the_presenter/, presenter ); + out = out.replace( /the_date/, date); + out = out.replace( /the_time/, time); + out = out.replace( /the_audience/, document.getElementById('audience').value ); + out = out.replace( /air_mozilla/, airmozilla); + out = out.replace( /dial_in/, dialin); + out = out.replace( /the_description/, document.getElementById('description').value ); + out = out.replace( /to_archive/, archive); + out = out.replace( /it_help/, ithelp); + + document.getElementById('comment').value = out; + document.getElementById('short_desc').value = shortdesc; + + return true; +} + +</script> + +<form method="post" action="post_bug.cgi" id="presentationRequestForm" enctype="multipart/form-data" + onSubmit="return trySubmit();"> + + <input type="hidden" name="product" value="mozilla.org"> + <input type="hidden" name="component" value="Server Operations: Desktop Issues"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="version" value="other"> + <input type="hidden" name="bug_severity" id="bug_severity" value="normal"> + <input type="hidden" name="comment" id="comment" value=""> + <input type="hidden" name="short_desc" id="short_desc" value=""> + <input type="hidden" name="groups" value="mozilla-corporation-confidential"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + +<table> + +<tr> + <td align="right"><strong>Presenter:</strong></td> + <td> + <input type="text" name="presenter" id="presenter" value="" size="60" /> + </td> + +</tr> + +<tr> + <td align="right"><strong>Topic:</strong></td> + <td> + <input type="text" name="topic" id="topic" value="" size="60" /> + </td> +</tr> + +<tr> + <td align="right"><strong>Date:</strong></td> + <td> + <input type="text" id="date" name="date" size="10" + onchange="updateCalendarFromField(this)"> + <button type="button" class="calendar_button" id="button_calendar_date" + onclick="showCalendar('date')"><span>Calendar</span> + </button> + <div id="con_calendar_date"></div> + </td> +</tr> + +<tr> + <td align="right"><strong>Start Time:</strong></td> + <td> + <select name="time_hour" id="time_hour"> + <option value="12" selected>12</option> + <option value="1">1</option> + <option value="2">2</option> + <option value="3">3</option> + <option value="4">4</option> + <option value="5">5</option> + <option value="6">6</option> + <option value="7">7</option> + <option value="8">8</option> + <option value="9">9</option> + <option value="10">10</option> + <option value="11">11</option> + </select>:<select name="time_minute" id="time_minute"> + <option value="00" selected>00</option> + <option value="15">15</option> + <option value="30">30</option> + <option value="45">45</option> + </select> + <select name="ampm" id="ampm"> + <option value="AM" selected>AM</option> + <option value="PM">PM</option> + </select> + </td> +</tr> + +<tr> + <td align="right"><strong>Intended Audience:</strong></td> + <td> + <select name="audience" id="audience"> + <option value="Public" selected>Open to Public</option> + <option value="Employees Only">Employees Only</option> + <option value="Interns">Interns</option> + </select> + </td> +</tr> + +<tr> + <td align="right"><strong>Air Mozilla Broadcasting?</strong></td> + <td align="left"><input type="checkbox" name="airmozilla" id="airmozilla"></td> +</tr> + +<tr> + <td align="right"><strong>Dial In?</strong></td> + <td align="left"><input type="checkbox" name="dialin" id="dialin"></td> +</tr> + +<tr> +<td align="right"><strong>Archive this?</strong></td> +<td align="left"><input type="checkbox" name="archive" id="archive" value="yes"></td> +</tr> + + +<tr> +<td align="right"><strong>Need IT to help run A/V?</strong></td> +<td align="left"><input type="checkbox" name="ithelp" id="ithelp" value="yes" checked></td> +</tr> + +<tr> + <td align="right"><strong>CC (optional):</strong></td> + <td colspan="3"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 60 + multiple => 5 + %] + </td> +</tr> + +<tr> + <th><label for="description">Description</label>:</th> + <td> + <em>Please briefly describe the presentation and any specific needs you might have.</em><br> + + <textarea id="description" name="description" rows="10" cols="80"></textarea> + </td> +</tr> + + </table> + + <br> + <input type="submit" id="commit" value="Submit Request"> +</form> + +<p>Thanks for contacting us. + You will be notified by email of any progress made in resolving your request. + +</p> + +<script type="text/javascript"> + createCalendar('date'); +</script> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl new file mode 100644 index 000000000..a75959abb --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-recoverykey.html.tmpl @@ -0,0 +1,70 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Corporation/Foundation Encryption Recovery Key" +%] + +<p>Please complete the following information as you are encrypting your laptop.</p> + +<ul> + <li>The Recovery Key will be displayed during the encryption process + (<a href="https://mana.mozilla.org/wiki/display/INFRASEC/Desktop+Security#DesktopSecurity-DiskencryptionFileVault">more info</a>) + </li> + <li>The asset tag number is located on a sticker typically on the bottom of the device.</li> +</ul> + +<form method="post" action="post_bug.cgi" id="recoveryKeyForm" enctype="multipart/form-data"> + <input type="hidden" name="product" value="mozilla.org"> + <input type="hidden" name="component" value="Server Operations: Desktop Issues"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="All"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="version" value="other"> + <input type="hidden" name="bug_severity" value="normal"> + <input type="hidden" name="groups" value="mozilla-corporation-confidential"> + <input type="hidden" name="groups" value="infra"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + <input type="hidden" name="cc" value="tfairfield@mozilla.com, ghuerta@mozilla.com"> + <input type="hidden" name="short_desc" value="Encryption Recovery Key for [% user.name || user.login FILTER html %]"> + <input type="hidden" name="format" value="recoverykey"> + <table> + <tr> + <td align="right"><strong>Recovery Key:</strong></td> + <td> + <input name="recoverykey" size="60" value="[% recoverykey FILTER html %]"> + </td> + </tr> + <tr> + <td align="right"><strong>Asset Tag Number:</strong></td> + <td> + <input name="assettag" size="60" value="[% assettag FILTER html %]"> + </td> + </tr> + <tr> + <td></td> + <td><input type="submit" id="commit" value="Submit"></td> + </tr> + </table> +</form> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl new file mode 100644 index 000000000..58eb39d5f --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl @@ -0,0 +1,222 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Mozilla Corporation. + # Portions created by Mozilla are Copyright (C) 2008 Mozilla + # Corporation. All Rights Reserved. + # + # Contributor(s): Reed Loden <reed@mozilla.com> + # David Tran <dtran@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Swag Request Form" + javascript_urls = [ 'extensions/BMO/web/js/swag.js', + 'extensions/BMO/web/js/form_validate.js', + 'js/field.js' ] + yui = [ 'autocomplete' ] +%] + +<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Swag Request Form</div> + +<p><strong>Swag Request:</strong> Please use this form to file a request for swag. </p> + +<ol> + <li>You first need submit a <a href="/enter_bug.cgi?product=Marketing&format=mktgevent">Event Request Form</a>. You'll be asked for the [% terms.bug %] number below.</li> + <li>Complete and submit request below.</li> + <li>Your request will be reviewed by the appropriate person in the Engagement team.</li> + <li>Your swag request will be reviewed and if approved shipped to you from + one of our two fulfillment houses. <i>Please note that swag is expensive and + products change over time - we are happy to send you a small quantity of swag + to use at your event!</i></li> +</ol> + +<p>These requests will only be visible to the person who submitted the request, +any persons designated in the CC line, and authorized members of the Mozilla +Engagement team.</p> + +<script language="javascript" type="text/javascript"> +function trySubmit() { + + var firstname = document.getElementById('firstname').value; + var lastname = document.getElementById('lastname').value; + var requester = firstname + ' ' + lastname; + var shortdesc = 'Swag Request - ' + requester; + document.getElementById('short_desc').value = shortdesc; + + // the following fields we don't let the user mess with because they're + // calculated, but they need to be submitted, and disabled fields don't submit + document.getElementById('Totalswag').disabled = false; + document.getElementById('mens_total').disabled = false; + document.getElementById('womens_total').disabled = false; + + return true; +} + +function validateAndSubmit() { + + var alert_text = ''; + if(!isFilledOut('firstname')) alert_text += "Please enter your first name\n"; + if(!isFilledOut('lastname')) alert_text += "Please enter your last name\n"; + if(!isFilledOut('dependson')) alert_text += "Please enter the [% terms.bug %] number for your Event Request Form\n"; + if(!isValidEmail(document.getElementById('email').value)) alert_text += "Please enter a valid email address\n"; + + //Everything required is filled out..try to submit the form! + if(alert_text == '') { + return trySubmit(); + } + + //alert text, stay here on the pagee + alert(alert_text); + return false; +} + +</script> + +<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data" + onSubmit="return validateAndSubmit();"> + + <input type="hidden" name="format" value="swag"> + <input type="hidden" name="product" value="Marketing"> + <input type="hidden" name="component" value="Swag Requests"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="priority" value="--"> + <input type="hidden" name="version" value="unspecified"> + <input type="hidden" name="bug_severity" id="bug_severity" value="normal"> + <input type="hidden" name="short_desc" id="short_desc" value=""> + <input type="hidden" name="groups" value="mozilla-corporation-confidential"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + +<table> + +<tr> + <td align="right"><strong>First Name: <span style="color: red;">*</span></strong></td> + <td align="left"> + <input type="text" name="firstname" id="firstname" value="" size="20" maxlength="20" /> + </td> +</tr> +<tr> + <td align="right"><strong>Last Name: <span style="color: red;">*</span></strong></td> + <td align="left"> + <input type="text" name="lastname" id="lastname" value="" size="20" maxlength="20"/> + </td> +</tr> + +<tr> + <td align="right"><strong>Email Address: <span style="color: red;">*</span></strong></td> + <td> + <input type="text" name="email" id="email" value="" size="50" maxlength="50"/> + </td> +</tr> + +<tr> + <td align="right"><strong>CC:</strong></td> + <td colspan="3"> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + size => 50 + multiple => 5 + %] + </td> +</tr> + +<tr> + <td><!-- spacer --> </td> +</tr> + +<tr> + <td><!-- spacer --> </td> +</tr> + +<tr> + <td align="right"><strong>[% terms.Bug %] number assigned to previously- <br>submitted <a href="/enter_bug.cgi?product=Marketing&format=mktgevent">Event Request Form</a>: <span style="color: red;">*</span></strong></td> + <td colspan="3"><input name="dependson" id="dependson"></td> +</tr> + +<tr> + <td align="right"><strong>Specific swag needed?</strong></td> + <td> + <textarea id="additional" name="additional" rows="5" cols="50"></textarea> + </td> +</tr> + +<tr> + <td align="right"><br><br><strong>Ship to:</strong></td> + <td colspan="3"></td> +</tr> +<tr> + <td align="right"><strong>First name:</strong></td> + <td colspan="3"><input name="shiptofirstname" id="shiptofirstname"></td> +</tr> +<tr> + <td align="right"><strong>Last name:</strong></td> + <td colspan="3"><input name="shiptolastname" id="shiptolastname"></td> +</tr> +<tr> + <td align="right"><strong>Address</strong></td> + <td colspan="3"><input name="shiptoaddress" id="shiptoaddress" size="60"></td> +</tr> +<tr> + <td align="right"><strong>Address 2</strong></td> + <td colspan="3"><input name="shiptoaddress2" id="shiptoaddress2" size="60"></td> +</tr> +<tr> + <td align="right"><strong>City</strong></td> + <td colspan="3"><input name="shiptocity" id="shiptocity"></td> +</tr> +<tr> + <td align="right"><strong>State</strong></td> + <td colspan="3"><input name="shiptostate" id="shiptostate"></td> +</tr> +<tr> + <td align="right"><strong>Country</strong></td> + <td colspan="3"><input name="shiptocountry" id="shiptocountry"></td> +</tr> +<tr> + <td align="right"><strong>Postal Code</strong></td> + <td colspan="3"><input name="shiptopcode" id="shiptopcode"></td> +</tr> +<tr> + <td align="right"><strong>Telephone</strong></td> + <td colspan="3"><input name="shiptophone" id="shiptophone"></td> +</tr> +<tr> + <td align="right"><strong>Personal ID/RUT</strong><br><small>(if your country requires this)</small></td> + <td colspan="3"><input name="shiptoidrut" id="shiptoidrut"></td> +</tr> + +<tr><td colspan="4"><br><br></td></tr> + +<tr> + <td align="right"><label for="comment"><strong>Any additional comments?</strong></label></td> + <td> + <textarea id="comment" name="comment" rows="5" cols="50"></textarea> + </td> +</tr> + + </table> + <br> + <input type="submit" id="commit" value="Submit Request"> + +<p> + <strong><span style="color: red;">*</span></strong> - Required field<br /> + Thanks for contacting us. + You will be notified by email of any progress made in resolving your request. +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl new file mode 100644 index 000000000..977ad00d4 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl @@ -0,0 +1,87 @@ +[%# 1.0@bugzilla.org %] +[%# 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): Gervase Markham <gerv@gerv.net> + # Ville Skyttä <ville.skytta@iki.fi> + # John Hoogstrate <hoogstrate@zeelandnet.nl> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Trademark Usage Requests" +%] + +[% USE Bugzilla %] + +<p> + If, after reading + <a href="http://www.mozilla.org/foundation/trademarks/">the trademark policy + documents</a>, you know you need permission to use a certain trademark, this + is the place to be. +</p> + +<p><strong>Please use this form for trademark requests only!</strong></p> + +<form method="post" action="post_bug.cgi" id="tmRequestForm"> + + <input type="hidden" name="product" value="Marketing"> + <input type="hidden" name="component" value="Trademark Permissions"> + <input type="hidden" name="bug_severity" value="enhancement"> + <input type="hidden" name="rep_platform" value="All"> + <input type="hidden" name="priority" value="P3"> + <input type="hidden" name="op_sys" value="Other"> + <input type="hidden" name="version" value="unspecified"> + <input type="hidden" name="groups" value="marketing-private"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + + <table> + <tr> + <td align="right"><strong>Summary:</strong></td> + <td colspan="3"> + <input name="short_desc" size="60" value="[% short_desc FILTER html %]"> + </td> + </tr> + + <tr><td align="right" valign="top"><strong>Description:</strong></td> + <td colspan="3"> + <textarea name="comment" rows="10" cols="80"> + [% comment FILTER html %]</textarea> + <br> + </td> + </tr> + <tr> + <td align="right"><strong>URL (optional):</strong></td> + <td colspan="3"> + <input name="bug_file_loc" size="60" + value="[% bug_file_loc FILTER html %]"> + </td> + </tr> + </table> + + <br> + + <input type="submit" id="commit" value="Submit Request"> +</form> + +<p>Thanks for contacting us. + You will be notified by email of any progress made in resolving your + request. +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl new file mode 100644 index 000000000..d14cca810 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/create-winqual.html.tmpl @@ -0,0 +1,800 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + # Ville Skyttä <ville.skytta@iki.fi> + # Shane H. W. Travis <travis@sedsystems.ca> + # Marc Schumann <wurblzap@gmail.com> + # Akamai Technologies <bugzilla-dev@akamai.com> + # Max Kanat-Alexander <mkanat@bugzilla.org> + # Frédéric Buclin <LpSolit@gmail.com> + #%] + +[% PROCESS "global/field-descs.none.tmpl" %] + +[% title = BLOCK %]Enter [% terms.Bug %]: [% product.name FILTER html %][% END %] + +[% PROCESS global/header.html.tmpl + title = title + yui = [ 'autocomplete', 'calendar', 'datatable', 'button' ] + style_urls = [ 'skins/standard/attachment.css', + 'skins/standard/enter_bug.css', + 'skins/custom/create_bug.css' ] + javascript_urls = [ "js/attachment.js", "js/util.js", + "js/field.js", "js/TUI.js", "js/bug.js", + "js/create_bug.js" ] + onload = "init();" +%] + +<script type="text/javascript"> +<!-- + +function init() { + set_assign_to(); + hideElementById('attachment_true'); + showElementById('attachment_false'); + showElementById('btn_no_attachment'); + initCrashSignatureField(); + init_take_handler('[% user.login FILTER js %]'); +} + +function initCrashSignatureField() { + var el = document.getElementById('cf_crash_signature'); + if (!el) return; + [% IF cf_crash_signature.length %] + YAHOO.util.Dom.addClass('cf_crash_signature_container', 'bz_default_hidden'); + [% ELSE %] + hideEditableField('cf_crash_signature_container','cf_crash_signature_input', + 'cf_crash_signature_action', 'cf_crash_signature'); + [% END %] +} + +var initialowners = new Array(); +var last_initialowner; +var initialccs = new Array(); +var components = new Array(); +var comp_desc = new Array(); +var flags = new Array(); +[% IF Param("useqacontact") %] + var initialqacontacts = new Array([% product.components.size %]); + var last_initialqacontact; +[% END %] +[% count = 0 %] +[%- FOREACH c = product.components %] + [% NEXT IF NOT c.is_active %] + [% NEXT IF c.name != 'WinQual Reports' %] + components[[% count %]] = "[% c.name FILTER js %]"; + comp_desc[[% count %]] = "[% c.description FILTER html_light FILTER js %]"; + initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]"; + [% flag_list = [] %] + [% FOREACH f = c.flag_types(is_active=>1).bug %] + [% flag_list.push(f.id) %] + [% END %] + [% FOREACH f = c.flag_types(is_active=>1).attachment %] + [% flag_list.push(f.id) %] + [% END %] + flags[[% count %]] = [[% flag_list.join(",") FILTER js %]]; + [% IF Param("useqacontact") %] + initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]"; + [% END %] + + [% SET initial_cc_list = [] %] + [% FOREACH cc_user = c.initial_cc %] + [% initial_cc_list.push(cc_user.login) %] + [% END %] + initialccs[[% count %]] = "[% initial_cc_list.join(', ') FILTER js %]"; + + [% count = count + 1 %] +[%- END %] + +function set_assign_to() { + // Based on the selected component, fill the "Assign To:" field + // with the default component owner, and the "QA Contact:" field + // with the default QA Contact. It also selectively enables flags. + var form = document.Create; + var assigned_to = form.assigned_to.value; + +[% IF Param("useqacontact") %] + var qa_contact = form.qa_contact.value; +[% END %] + + var index = -1; + if (form.component.type == 'select-one') { + index = form.component.selectedIndex; + } else if (form.component.type == 'hidden') { + // Assume there is only one component in the list + index = 0; + } + if (index != -1) { + var owner = initialowners[index]; + var component = components[index]; + if (assigned_to == last_initialowner + || assigned_to == owner + || assigned_to == '') { + form.assigned_to.value = owner; + last_initialowner = owner; + } + + document.getElementById('initial_cc').innerHTML = initialccs[index]; + document.getElementById('comp_desc').innerHTML = comp_desc[index]; + + if (initialccs[index]) { + showElementById('initial_cc_label'); + showElementById('initial_cc'); + } else { + hideElementById('initial_cc_label'); + hideElementById('initial_cc'); + } + + [% IF Param("useqacontact") %] + var contact = initialqacontacts[index]; + if (qa_contact == last_initialqacontact + || qa_contact == contact + || qa_contact == '') { + form.qa_contact.value = contact; + last_initialqacontact = contact; + } + [% END %] + + // First, we disable all flags. Then we re-enable those + // which are available for the selected component. + var inputElements = document.getElementsByTagName("select"); + var inputElement, flagField; + for ( var i=0 ; i<inputElements.length ; i++ ) { + inputElement = inputElements.item(i); + if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) { + var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1"); + inputElement.disabled = true; + // Also hide the requestee field, if it exists. + inputElement = document.getElementById("requestee_type-" + id); + if (inputElement) + YAHOO.util.Dom.addClass(inputElement.parentNode, 'bz_default_hidden'); + } + } + // Now enable flags available for the selected component. + for (var i = 0; i < flags[index].length; i++) { + flagField = document.getElementById("flag_type-" + flags[index][i]); + // Do not enable flags the user cannot set nor request. + if (flagField && flagField.options.length > 1) { + flagField.disabled = false; + // Re-enabling the requestee field depends on the status + // of the flag. + toggleRequesteeField(flagField, 1); + } + } + } +} + +var status_comment_required = new Array(); +[% FOREACH status = bug_status %] + status_comment_required['[% status.name FILTER js %]'] = + [% status.comment_required_on_change_from() ? 'true' : 'false' %] +[% END %] + +TUI_alternates['expert_fields'] = 'Show Advanced Fields'; +// Hide the Advanced Fields by default, unless the user has a cookie +// that specifies otherwise. +TUI_hide_default('expert_fields'); + +--> +</script> + +<form name="Create" id="Create" method="post" action="post_bug.cgi" + class="enter_bug_form" enctype="multipart/form-data" + onsubmit="return validateEnterBug(this)"> + <input type="hidden" name="product" value="Firefox"> + <input type="hidden" name="component" value="WinQual Reports"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + <input type="hidden" name="groups" value="winqual-data"> + +<table> +<tbody> + <tr> + <td colspan="4"> + [%# Migration note: The following file corresponds to the old Param + # 'entryheaderhtml' + #%] + [% PROCESS 'bug/create/user-message.html.tmpl' %] + </td> + </tr> + + <tr> + <td colspan="2"> + <input type="button" id="expert_fields_controller" + value="Hide Advanced Fields" onClick="toggleAdvancedFields()"> + [%# Show the link if the browser supports JS %] + <script type="text/javascript"> + YAHOO.util.Dom.removeClass('expert_fields_controller', + 'bz_default_hidden'); + </script> + </td> + <td colspan="2"> + (<span class="required_star">*</span> = + <span class="required_explanation">Required Field</span>) + </td> + </tr> + + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.product, editable = 0, + value = product.name %] + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.reporter, editable = 0, + value = user.login %] + </tr> + + [%# We can't use the select block in these two cases for various reasons. %] + <tr> + [% component_desc_url = BLOCK -%] + describecomponents.cgi?product=[% product.name FILTER uri %] + [% END %] + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.component editable = 1 + desc_url = component_desc_url + %] + <td id="field_container_component"> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.component, editable = 0, + value = "WinQual Reports", no_tds = 1 %] + <script type="text/javascript"> + <!-- + [%+ INCLUDE "bug/field-events.js.tmpl" + field = bug_fields.component %] + YAHOO.util.Event.onDOMReady(set_assign_to); + //--> + </script> + </td> + + <td colspan="2" id="comp_desc_container"> + [%# Enclose the fieldset in a nested table so that its width changes based + # on the length on the component description. %] + <table> + <tr> + <td> + <fieldset> + <legend>Component Description</legend> + <div id="comp_desc" class="comment"></div> + </fieldset> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.version editable = 1 rowspan = 3 + %] + <td rowspan="3"> + <select name="version" id="version" size="5"> + [%- FOREACH v = version %] + [% NEXT IF NOT v.is_active %] + <option value="[% v.name FILTER html %]" + [% ' selected="selected"' IF v.name == default.version %]>[% v.name FILTER html -%] + </option> + [%- END %] + </select> + </td> + + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.bug_severity, editable = 1, + value = default.bug_severity %] + </tr> + + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.rep_platform, editable = 1, + value = default.rep_platform %] + </tr> + + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.op_sys, editable = 1, + value = default.op_sys %] + </tr> + [% IF !Param('defaultplatform') || !Param('defaultopsys') %] + <tr> + <th colspan="3"> </th> + <td id="os_guess_note" class="comment"> + <div>We've made a guess at your + [% IF Param('defaultplatform') %] + operating system. Please check it + [% ELSIF Param('defaultopsys') %] + platform. Please check it + [% ELSE %] + operating system and platform. Please check them + [% END %] + and make any corrections if necessary.</div> + </td> + </tr> + [% END %] +</tbody> + +<tbody class="expert_fields"> + <tr> + [% IF Param('usetargetmilestone') && Param('letsubmitterchoosemilestone') %] + [% INCLUDE select field = bug_fields.target_milestone %] + [% ELSE %] + <td colspan="2"> </td> + [% END %] + + [% IF Param('letsubmitterchoosepriority') %] + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.priority, editable = 1, + value = default.priority %] + [% ELSE %] + <td colspan="2"> </td> + [% END %] + </tr> +</tbody> + +<tbody class="expert_fields"> + <tr> + <td colspan="4"> </td> + </tr> + + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.bug_status, + editable = (bug_status.size > 1), value = default.bug_status + override_legal_values = bug_status %] + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.assigned_to editable = 1 + %] + <td> + [% INCLUDE global/userselect.html.tmpl + id => "assigned_to" + name => "assigned_to" + value => assigned_to + disabled => assigned_to_disabled + size => 30 + emptyok => 1 + custom_userlist => assignees_list + %] + [% UNLESS assigned_to_disabled %] + <span id="take_bug"> + (<a title="Assign to yourself" href="#" + onclick="return take_bug('[% user.login FILTER js %]')">take</a>) + </span> + [% END %] + <noscript>(Leave blank to assign to component's default assignee)</noscript> + </td> + +[% IF Param("useqacontact") %] + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.qa_contact editable = 1 + %] + <td> + [% INCLUDE global/userselect.html.tmpl + id => "qa_contact" + name => "qa_contact" + value => qa_contact + disabled => qa_contact_disabled + size => 30 + emptyok => 1 + custom_userlist => qa_contacts_list + %] + <noscript>(Leave blank to assign to default qa contact)</noscript> + </td> + </tr> +[% END %] + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.cc editable = 1 + %] + <td> + [% INCLUDE global/userselect.html.tmpl + id => "cc" + name => "cc" + value => cc + disabled => cc_disabled + size => 30 + multiple => 5 + %] + </td> + <th> + <span id="initial_cc_label" class="bz_default_hidden"> + Default [% field_descs.cc FILTER html %]: + </span> + </th> + <td> + <span id="initial_cc"></span> + </td> + </tr> + + <tr> + <td colspan="3"> </td> + </tr> + +[% IF Param("usebugaliases") %] + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.alias editable = 1 + %] + <td colspan="2"> + <input name="alias" size="20" value="[% alias FILTER html %]"> + </td> + </tr> +[% END %] +</tbody> + +<tbody> + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.short_desc editable = 1 + %] + <td colspan="3" class="field_value"> + <input name="short_desc" size="70" value="[% short_desc FILTER html %]" + maxlength="255" spellcheck="true" aria-required="true" + class="required text_input" id="short_desc"> + </td> + </tr> + + [% IF feature_enabled('jsonrpc') AND !cloned_bug_id %] + <tr id="possible_duplicates_container" class="bz_default_hidden"> + <th>Possible<br>Duplicates:</th> + <td colspan="3"> + <div id="possible_duplicates"></div> + <script type="text/javascript"> + var dt_columns = [ + { key: "id", label: "[% field_descs.bug_id FILTER js %]", + formatter: YAHOO.bugzilla.dupTable.formatBugLink }, + { key: "summary", + label: "[% field_descs.short_desc FILTER js %]", + formatter: "text" }, + { key: "status", + label: "[% field_descs.bug_status FILTER js %]", + formatter: YAHOO.bugzilla.dupTable.formatStatus }, + { key: "update_token", label: '', + formatter: YAHOO.bugzilla.dupTable.formatCcButton } + ]; + YAHOO.bugzilla.dupTable.addCcMessage = "Add Me to the CC List"; + YAHOO.bugzilla.dupTable.init({ + container: 'possible_duplicates', + columns: dt_columns, + product_name: '[% product.name FILTER js %]', + summary_field: 'short_desc', + options: { + MSG_LOADING: 'Searching for possible duplicates...', + MSG_EMPTY: 'No possible duplicates found.', + SUMMARY: 'Possible Duplicates' + } + }); + </script> + </td> + </tr> + [% END %] + + <tr> + <th>Description:</th> + <td colspan="3"> + + [% defaultcontent = BLOCK %] + [% IF cloned_bug_id %] ++++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id FILTER html %] +++ + + + [% END %] + [%-# We are within a BLOCK. The comment will be correctly HTML-escaped + # by global/textarea.html.tmpl. So we must not escape the comment here. %] + [% comment FILTER none %] + [%- END %] + [% INCLUDE global/textarea.html.tmpl + name = 'comment' + id = 'comment' + minrows = 10 + maxrows = 25 + cols = constants.COMMENT_COLS + defaultcontent = defaultcontent + %] + <br> + </td> + </tr> + +<tbody class="expert_fields"> + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.bug_file_loc editable = 1 + %] + <td colspan="3" class="field_value"> + <input name="bug_file_loc" id="bug_file_loc" class="text_input" + size="40" value="[% bug_file_loc FILTER html %]"> + </td> + </tr> +</tbody> + +<tbody> + [% IF Param("maxattachmentsize") %] + <tr> + <th>Attachment:</th> + <td colspan="3"> + <div id="attachment_false" class="bz_default_hidden"> + <input type="button" value="Add an attachment" onClick="handleWantsAttachment(true)"> + </div> + + <div id="attachment_true"> + <input type="button" id="btn_no_attachment" value="Don't add an attachment" + class="bz_default_hidden" onClick="handleWantsAttachment(false)"> + <fieldset> + <legend>Add an attachment</legend> + <table class="attachment_entry"> + [% PROCESS attachment/createformcontents.html.tmpl + flag_types = product.flag_types(is_active=>1).attachment + any_flags_requesteeble = 1 + flag_table_id ="attachment_flags" %] + </table> + + [% IF user.is_insider %] + <input type="checkbox" id="comment_is_private" name="comment_is_private" + [% ' checked="checked"' IF comment_is_private %] + onClick="updateCommentTagControl(this, 'comment')"> + <label for="comment_is_private"> + Make this attachment and [% terms.bug %] description private (visible only + to members of the <strong>[% Param('insidergroup') FILTER html %]</strong> group) + </label> + [% END %] + </fieldset> + </div> + </td> + </tr> + [% END %] +</tbody> + +<tbody class="expert_fields"> + [% IF user.in_group('editbugs', product.id) %] + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.dependson editable = 1 + %] + <td> + <input name="dependson" accesskey="d" value="[% dependson FILTER html %]" size="30"> + </td> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.blocked editable = 1 + %] + <td> + <input name="blocked" accesskey="b" value="[% blocked FILTER html %]" size="30"> + </td> + </tr> + + [% IF use_keywords %] + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.keywords, editable = 1, + value = keywords, desc_url = "describekeywords.cgi", + value_span = 3 + %] + </tr> + [% END %] + + <tr> + <th>Status Whiteboard:</th> + <td colspan="3" class="field_value"> + <input id="status_whiteboard" name="status_whiteboard" size="70" + value="[% status_whiteboard FILTER html %]" class="text_input"> + </td> + </tr> + [% END %] + + [% IF user.is_timetracker %] + <tr> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.estimated_time editable = 1 + %] + <td> + <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]"> + </td> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.deadline, value = deadline, editable = 1 + %] + </tr> + [% END %] +</tbody> + +<tbody> +[%# non-tracking flags custom fields %] +[% FOREACH field = Bugzilla.active_custom_fields %] + [% NEXT UNLESS field.enter_bug %] + [% NEXT IF cf_hidden_in_product(field.name, product.name, component.name, 1) %] + [%# crash-signature gets custom handling %] + [% NEXT IF field.name == 'cf_crash_signature' %] + + [% SET value = ${field.name}.defined ? ${field.name} : "" %] + <tr [% 'class="expert_fields"' IF !field.is_mandatory %]> + [% INCLUDE bug/field.html.tmpl + bug = default, field = field, value = value, editable = 1, + value_span = 3 %] + </tr> +[% END %] +</tbody> + +[%# crash-signature handling %] +[% UNLESS cf_hidden_in_product('cf_crash_signature', product.name, component.name, 1) %] +<tbody class="expert_fields"> + <tr> + <th id="field_label_cf_crash_signature" class="field_label"> + <label for="cf_crash_signature"> Crash Signature: </label> + </th> + <td colspan="3"> + <span id="cf_crash_signature_container"> + <span id="cf_crash_signature_nonedit_display"><i>None</i></span> + (<a id="cf_crash_signature_action" href="#">edit</a>) + </span> + <span id="cf_crash_signature_input"> + <textarea id="cf_crash_signature" name="cf_crash_signature" rows="4" cols="60" + >[% cf_crash_signature FILTER html %]</textarea> + </span> + </td> + </tr> +</tbody> +[% END %] + +[% display_bug_flags = 0 %] +[% FOREACH field = Bugzilla.active_custom_fields %] + [% NEXT UNLESS field.enter_bug %] + [% NEXT IF cf_hidden_in_product(field.name, product.name, component.name, 2) %] + [% display_bug_flags = 1 %] + [% LAST %] +[% END %] + +[% display_flags = 0 %] +[% any_flags_requesteeble = 0 %] +[% FOREACH flag_type = product.flag_types(is_active=>1).bug %] + [% display_flags = 1 %] + [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %] + [% LAST IF display_flags && any_flags_requesteeable %] +[% END %] + +[% IF display_bug_flags || display_flags %] + <tbody class="expert_fields"> + <tr> + <th>Flags:</th> + <td colspan="3"> + <div id="bug_flags_false" class="bz_default_hidden"> + <input type="button" value="Set [% terms.bug FILTER html %] flags" onClick="handleWantsBugFlags(true)"> + </div> + + <div id="bug_flags_true"> + <input type="button" id="btn_no_bug_flags" value="Don't set [% terms.bug %] flags" + class="bz_default_hidden" onClick="handleWantsBugFlags(false)"> + + <fieldset> + <legend>Set [% terms.bug %] flags</legend> + + <table cellpadding="0" cellspacing="0"> + <tr> + [% IF display_bug_flags %] + <td> + <table id="bug_tracking_flags"> + <tr> + <th colspan="2" style="text-align:left">Tracking Flags:</th> + </tr> + <tr> + [% FOREACH field = Bugzilla.active_custom_fields %] + [% NEXT UNLESS field.enter_bug %] + [% NEXT IF cf_hidden_in_product(field.name, product.name, component.name, 2) %] + + [% SET value = ${field.name}.defined ? ${field.name} : "" %] + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = field, value = value, editable = 1, + value_span = 3 %] + </tr> + [% END %] + </tr> + </table> + </td> + [% END %] + [% IF display_flags %] + <td> + [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types(is_active=>1).bug + any_flags_requesteeble = any_flags_requesteeble + flag_table_id = "bug_flags" + %] + </td> + [% END %] + </tr> + </table> + </fieldset> + </div> + </td> + </tr> + </tbody> +[% END %] + +<tbody> + [%# Form controls for entering additional data about the bug being created. %] + [% Hook.process("form") %] + + <tr> + <th> </th> + <td colspan="3"> + <input type="submit" id="commit" value="Submit [% terms.Bug %]"> + + <input type="submit" name="maketemplate" id="maketemplate" + value="Remember values as bookmarkable template" + onclick="bz_no_validate_enter_bug=true" class="expert_fields"> + </td> + </tr> +</tbody> + [%# "status whiteboard" and "qa contact" are the longest labels + # add them here to avoid shifting the page when toggling advanced fields %] + <tr> + <th class="hidden_text">Status Whiteboard:</th> + <td> </td> + <th class="hidden_text">QA Contact:</th> + </tr> + </table> + <input type="hidden" name="form_name" value="enter_bug"> +</form> + +[%# Links or content with more information about the bug being created. %] +[% Hook.process("end") %] + +<div id="guided"> + <a id="guided_img" href="enter_bug.cgi?format=guided&product=[% product.name FILTER uri %]"><img + src="extensions/BMO/web/images/guided.png" width="16" height="16" border="0" align="absmiddle"></a> + <a id="guided_link" href="enter_bug.cgi?format=guided&product=[% product.name FILTER uri %]" + >Switch to the [% terms.Bugzilla %] Helper</a> +</div> + +[% PROCESS global/footer.html.tmpl %] + +[%############################################################################%] +[%# Block for SELECT fields #%] +[%############################################################################%] + +[% BLOCK select %] + + [% INCLUDE "bug/field-label.html.tmpl" + field = field editable = 1 + %] + <td> + <select name="[% field.name FILTER html %]" + id="[% field.name FILTER html %]"> + [%- FOREACH x = ${field.name} %] + [% NEXT IF NOT x.is_active %] + <option value="[% x.name FILTER html %]" + [% " selected=\"selected\"" IF x.name == default.${field.name} %]> + [% display_value(field.name, x.name) FILTER html %] + </option> + [% END %] + </select> + </td> +[% END %] + +[% BLOCK build_userlist %] + [% user_found = 0 %] + [% default_login = default_user.login %] + [% RETURN UNLESS default_login %] + + [% FOREACH user = userlist %] + [% IF user.login == default_login %] + [% user_found = 1 %] + [% LAST %] + [% END %] + [% END %] + + [% userlist.push({login => default_login, + identity => default_user.identity, + visible => 1}) + UNLESS user_found %] +[% END %] diff --git a/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl b/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl new file mode 100644 index 000000000..e9a480090 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl @@ -0,0 +1,38 @@ +[%# 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 BMO Bugzilla Extension. + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): Byron Jones <glob@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% PROCESS global/header.html.tmpl + title = "Mozilla Reps - Application Form" + +%] + +<h1>Thank you!</h1> + +<p> +Thank you for submitting your Mozilla Reps Application Form. A Mozilla Rep +mentor will contact you shortly at your bugzilla email address. +</p> + +<p style="font-size: x-small"> +Reference: <a href="show_bug.cgi?id=[% id FILTER uri %]">#[% id FILTER html %]</a> +</p> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl new file mode 100644 index 000000000..ccf008a38 --- /dev/null +++ b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl @@ -0,0 +1,37 @@ +<!-- 1.0@bugzilla.org --> +[%# 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): Matthew Tuck <matty@chariot.net.au> + #%] + +[% PROCESS global/variables.none.tmpl %] + +<p> + [% UNLESS cloned_bug_id %] + Consider using the + <a href="enter_bug.cgi?product=[% product.name FILTER html %]&format=guided" + ><img src="extensions/BMO/web/images/guided.png" width="16" height="16" align="absmiddle" border="0"> + [%+ terms.Bugzilla %] Helper</a> instead of this form. + [% END +%] + Before reporting a [% terms.bug %], make sure you've read our + <a href="http://www.mozilla.org/quality/bug-writing-guidelines.html"> + [% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already + been reported. Consult our list of <a href="https://bugzilla.mozilla.org/duplicates.cgi"> + most frequently reported [% terms.bugs %]</a> and <a href="https://bugzilla.mozilla.org/query.cgi"> + search through descriptions</a> of previously reported [% terms.bugs %]. +</p> diff --git a/extensions/BMO/template/en/default/global/choose-product.html.tmpl b/extensions/BMO/template/en/default/global/choose-product.html.tmpl new file mode 100644 index 000000000..9daae1d25 --- /dev/null +++ b/extensions/BMO/template/en/default/global/choose-product.html.tmpl @@ -0,0 +1,194 @@ +[%# 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): Gervase Markham <gerv@gerv.net> + #%] + +[%# INTERFACE: + # classifications: array of hashes, with an 'object' key representing a + # classification object and 'products' the list of + # product objects the user can enter bugs into. + # target: the script that displays this template. + # cloned_bug_id: ID of the bug being cloned. + # format: the desired format to display the target. + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% IF target == "enter_bug.cgi" %] + [% title = "Enter $terms.Bug" %] + [% h2 = BLOCK %]First, you must pick a product on which to enter [% terms.abug %]. [% END %] +[% ELSIF target == "describecomponents.cgi" %] + [% title = "Browse" %] + [% h2 = "Please specify the product whose components you want described." %] +[% END %] + +[% DEFAULT title = "Choose a Product" %] +[% PROCESS global/header.html.tmpl %] + +<center> +<hr> +<p><span style="font-family: verdana,helvetica;">Looking for technical support or help getting your site to work with Mozilla? <a +href="http://www.mozilla.org/support/">Visit the mozilla.org support page</a> before filing [% terms.bugs %].</span></p> +<hr> +</center> + +<br> +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] +[% SET classification = cgi.param('classification') %] +[% IF NOT ((cgi.param("full")) OR (user.settings.product_chooser.value == 'full_product_chooser')) %] +[% IF target == "enter_bug.cgi" %] +<h2 align="center">Which product is affected by the problem you would like to report?</h2> +[% END %] +<table align="center" border="0" width="600" cellpadding="5" cellspacing="0"> +[% INCLUDE easyproduct + name="Core" + icon="dino.png" +%] +[% INCLUDE easyproduct + name="Firefox" + icon="firefox.png" +%] +[% INCLUDE easyproduct + name="Thunderbird" + icon="thunderbird.png" +%] +[% INCLUDE easyproduct + name="Calendar" + icon="sunbird.png" +%] +[% INCLUDE easyproduct + name="Camino" + icon="camino.png" +%] +[% INCLUDE easyproduct + name="SeaMonkey" + icon="seamonkey.png" +%] +[% INCLUDE easyproduct + name="Fennec" + icon="fennec.png" +%] +[% INCLUDE easyproduct + name="Mozilla Localizations" + icon="dino.png" +%] +[% INCLUDE easyproduct + name="Mozilla Labs" + icon="labs.png" +%] +[% INCLUDE easyproduct + name="Mozilla Services" + icon="dino.png" +%] +<tr> + <td><a href="[% target FILTER uri %]?full=1 + [%- IF cloned_bug_id %]&cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%] + [%- IF classification %]&classification=[% classification FILTER uri %][% END -%] + [%- IF format %]&format=[% format FILTER uri %][% END %]"> + <img src="extensions/BMO/web/producticons/other.png" height="64" width="64" border="0"></a></td> + <td><h2 align="left" style="margin-bottom: 0px;"><a href="[% target FILTER uri %]?full=1 + [%- IF cloned_bug_id %]&cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%] + [%- IF classification %]&classification=[% classification FILTER uri %][% END -%] + [%- IF format %]&format=[% format FILTER uri %][% END %]"> + Other Products</a></h2> + <p style="margin-top: 0px;">Other Mozilla products which aren't listed here</p> + </td> +</tr> +</table> +[% ELSE %] +<h2>[% h2 FILTER html %]</h2> + +<table> + +[% FOREACH c = classifications %] + [% IF c.object %] + <tr> + <td align="right"><h2>[% c.object.name FILTER html %]</h2></td> + <td><strong>[%+ c.object.description FILTER html_light %]</strong></td> + </tr> + [% END %] + + [% FOREACH p = c.products %] + [% class = "" %] + [% has_entry_groups = 0 %] + [% FOREACH gid = p.group_controls.keys %] + [% IF p.group_controls.$gid.entry %] + [% has_entry_groups = 1 %] + [% class = class _ " group_$gid" %] + [% END %] + [% END %] + <tr class="[% "group_secure" IF has_entry_groups +%] [% class FILTER html %]" + [%- IF has_entry_groups %] title="This product requires one or more + group memberships in order to enter [% terms.bugs %] in it. You have them, but be + aware not everyone else does."[% END %]> + <th align="right" valign="top"> + [% IF p.name == "Mozilla PR" AND target == "enter_bug.cgi" AND NOT format AND NOT cgi.param("debug") %] + <a href="[% target FILTER uri %]?product=[% p.name FILTER uri -%] + [%- IF cloned_bug_id %]&cloned_bug_id=[% cloned_bug_id FILTER uri %][% END %]&format=mozpr"> + [% p.name FILTER html FILTER no_break %]</a>: + [% ELSE %] + <a href="[% target FILTER uri %]?product=[% p.name FILTER uri -%] + [%- IF cloned_bug_id %]&cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%] + [%- IF format %]&format=[% format FILTER uri %][% END %]"> + [% p.name FILTER html FILTER no_break %]</a>: + [% END %] + </th> + <td valign="top">[% p.description FILTER html_light %]</td> + </tr> + [% END %] +[% END %] + +</table> + +<br> +[% IF target == "enter_bug.cgi" AND user.settings.product_chooser.value != 'full_product_chooser' %] +<p align="center">You can choose to get this screen by default when you click "New [% terms.Bug %]" by changing your <a href="userprefs.cgi?tab=settings">preferences</a>.</p> +[% END %] +[% END %] +<br> + +[% PROCESS global/footer.html.tmpl %] + +[%###########################################################################%] +[%# Block for "easy" product sections #%] +[%###########################################################################%] + +[% BLOCK easyproduct %] + [% FOREACH c = classifications %] + [% FOREACH p = c.products %] + [% IF p.name == name %] + <tr> + <td><a href="[% target FILTER uri %]?product=[% p.name FILTER uri %] + [%- IF cloned_bug_id %]&cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%] + [%- IF format %]&format=[% format FILTER uri %][% END %]"> + <img src="extensions/BMO/web/producticons/[% icon FILTER uri %]" height="64" width="64" border="0"></a></td> + <td><h2 align="left" style="margin-bottom: 0px"><a href="[% target FILTER uri %]?product=[% p.name FILTER uri %] + [%- IF cloned_bug_id %]&cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%] + [%- IF format %]&format=[% format FILTER uri %][% END %]"> + [% p.name FILTER html FILTER no_break %]</a>:</h2> + [% IF p.description %] + <p style="margin-top: 0px;">[% p.description FILTER html_light %]</p> + [% END %] + </td> + </tr> + [% LAST %] + [% END %] + [% END %] + [% END %] +[% END %] diff --git a/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl b/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl new file mode 100644 index 000000000..3dc727b87 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl @@ -0,0 +1,2 @@ +[% mimetypes.push({type => "image/svg+xml", desc => "SVG image"}) %] +[% mimetypes.push({type => "application/vnd.mozilla.xul+xml", desc => "XUL"}) %]
\ No newline at end of file diff --git a/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl b/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl new file mode 100644 index 000000000..ea80fdc5e --- /dev/null +++ b/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl @@ -0,0 +1 @@ +<em>You can <a href="http://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree">read about the patch submission and approval process</a>.</em><br> diff --git a/extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl new file mode 100644 index 000000000..caf7acca7 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/comments-a_comment-end.html.tmpl @@ -0,0 +1,19 @@ +[%# 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. + #%] + +[% IF user.id && comment.author.login_name == 'tbplbot@gmail.com' %] + [% has_tbpl_comment = 1 %] + <script> + var id = [% count FILTER none %]; + tbpl_comment_ids.push(id); + collapse_comment( + document.getElementById('comment_link_' + id), + document.getElementById('comment_text_' + id) + ); + </script> +[% END %] diff --git a/extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl new file mode 100644 index 000000000..d8dc5bba0 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/comments-aftercomments.html.tmpl @@ -0,0 +1,42 @@ +[%# 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. + #%] + +[% IF has_tbpl_comment %] + [% expand_caption = 'Expand TinderboxPushlog Comments' %] + [% collapse_caption = 'Collapse TinderboxPushlog Comments' %] + <script> + YAHOO.util.Event.onDOMReady(function () { + var ul = document.getElementsByClassName('bz_collapse_expand_comments'); + if (ul.length == 0) + return; + var li = document.createElement('li'); + var a = document.createElement('a'); + Dom.setAttribute(a, 'href', 'javascript:void(0)'); + Dom.setAttribute(a, 'id', 'toggle_tbplbot_comments'); + a.innerHTML = '[% expand_caption FILTER js %]'; + YAHOO.util.Event.on(a, 'click', function() { + var do_expand = a.innerHTML == '[% expand_caption FILTER js %]'; + for (var i = 0, n = tbpl_comment_ids.length; i < n; i++) { + var id = tbpl_comment_ids[i]; + var link = document.getElementById('comment_link_' + id); + var text = document.getElementById('comment_text_' + id); + if (do_expand) { + expand_comment(link, text); + } else { + collapse_comment(link, text); + } + } + a.innerHTML = do_expand + ? '[% collapse_caption FILTER js %]' + : '[% expand_caption FILTER js %]'; + }); + li.appendChild(a); + ul[0].appendChild(li); + }); + </script> +[% END %] diff --git a/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl new file mode 100644 index 000000000..2ae367456 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl @@ -0,0 +1,13 @@ +[%# *** Disclaimer for Legal bugs *** %] +[% IF bug.product == "Legal" %] + <div id="legal_disclaimer"> + The material and information contained herein is Confidential and + subject to Attorney-Client Privilege and Work Product Doctrine. + </div> +[% END %] + +[%# Needed for collapsing TinderboxPushlog comments %] +[% has_tbpl_comment = 0 %] +<script> + var tbpl_comment_ids = new Array(); +</script> diff --git a/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl b/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl new file mode 100644 index 000000000..1b1f1d67d --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl @@ -0,0 +1,18 @@ + <tr> + <th>Security:</th> + <td colspan="3"> + [% sec_group = sec_groups.${product.name} || sec_groups._default %] + + <input type="checkbox" name="groups" + value="[% sec_group FILTER none %]" id="groups" + [% FOREACH g = group %] + [% IF g.name == sec_group %] + [% " checked=\"checked\"" IF g.checked %] + [% END %] + [% END %] + > + <label for="groups">Many users could be harmed by this security problem: + it should be kept hidden from the public until it is resolved.</label> + <br><br> + </td> + </tr> diff --git a/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl new file mode 100644 index 000000000..a0fff4175 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl @@ -0,0 +1,22 @@ + <tr bgcolor="[% tablecolour FILTER html %]"> + <td valign="middle" align="right"> + <b>Security</b> + </td> + <td valign="top"> + <p> + [% sec_group = sec_groups.${product.name} || sec_groups._default %] + + <input type="checkbox" name="groups" + id="groups" value="[% sec_group FILTER none %]" + [% FOREACH g = group %] + [% IF g.name == sec_group %] + [% " checked=\"checked\"" IF g.checked %] + [% END %] + [% END %] + > + <label for="groups"> + Many users could be harmed by this security problem: it should be kept + hidden from the public until it is resolved.</label> + </p> + </td> + </tr> diff --git a/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl new file mode 100644 index 000000000..4be267b79 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl @@ -0,0 +1,116 @@ +[%# ***** BEGIN LICENSE BLOCK ***** + # Version: MPL 1.1 + # + # 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 BMO Bugzilla Extension; + # + # The Initial Developer of the Original Code is the Mozilla Foundation. + # Portions created by the Initial Developer are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # Byron Jones <glob@mozilla.com> + # + # ***** END LICENSE BLOCK ***** + #%] + +[% tracking_flags = [] %] +[% project_flags = [] %] +[% FOREACH field = Bugzilla.active_custom_fields(product=>bug.product_obj,component=>bug.component_obj,type=>2) %] + [% NEXT IF NOT user.id AND bug.${field.name} == "---" %] + [% NEXT IF cf_flag_disabled(field.name, bug) %] + [% IF cf_is_project_flag(field.name) %] + [% project_flags.push(field) %] + [% ELSE %] + [% tracking_flags.push(field) %] + [% END %] +[% END %] + +[% IF project_flags.size %] + <tr> + <th class="field_label"> + <label>Project Flags:</label> + </td> + <td> + <table id="project-flags"> + [% FOREACH field = project_flags %] + [% NEXT IF NOT user.id AND field.value == "---" %] + <tr id="row_[% field.name FILTER js %]"> + <td> </td> + <td> + <label for="[% field.name FILTER html %]"> + [% field_descs.${field.name} FILTER html %]: + </label> + </td> + <td> + [% PROCESS bug/field.html.tmpl value = bug.${field.name} + editable = user.id + no_tds = 1 %] + [% IF user.id %] + <span id="ro_[% field.name FILTER html %]" class="bz_hidden"> + [% bug.${field.name} FILTER html %] + </span> + [% END %] + </td> + </tr> + [% END %] + </table> + </td> + </tr> +[% END %] + +[% IF tracking_flags.size %] + <tr> + <td class="" colspan="2"> + <label><b>Tracking Flags:</b></label> + [% IF user.id %] + <span id="edit_tracking_fields_action"> + (<a onclick="bmo_show_tracking_flags()" href="javascript:void(0)">edit</a>) + </span> + [% END %] + </td> + </tr> + <tr> + <td colspan="2"> + <table id="custom-flags"> + [% FOREACH field = tracking_flags %] + [% NEXT IF NOT user.id AND field.value == "---" %] + <tr id="row_[% field.name FILTER js %]"> + <td> </td> + <td> + <label for="[% field.name FILTER html %]"> + [% field_descs.${field.name} FILTER html %]: + </label> + </td> + <td> + [% PROCESS bug/field.html.tmpl value = bug.${field.name} + editable = user.id + no_tds = 1 %] + [% IF user.id %] + <span id="ro_[% field.name FILTER html %]" class="bz_hidden"> + [% bug.${field.name} FILTER html %] + </span> + [% END %] + </td> + </tr> + [% END %] + </table> + </td> + </tr> + <script type="text/javascript"> + var bmo_custom_flags = new Array([% tracking_flags.size FILTER none %]); + [% FOREACH field = tracking_flags %] + bmo_custom_flags['[% field.name FILTER js %]'] = '[% bug.${field.name} FILTER js %]'; + [% END %] + bmo_hide_tracking_flags(); + </script> +[% END %] diff --git a/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl b/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl new file mode 100644 index 000000000..70132d7e0 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl @@ -0,0 +1,114 @@ +[%# 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 BMO Extension + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # Dave Lawrence <dkl@mozilla.com> + #%] + +[% USE Bugzilla %] +[% IF Bugzilla.request_cache.bmo_fields_page %] + [% filtered_severity_blocker = display_value("bug_severity", "blocker") FILTER html %] + [% filtered_severity_critical = display_value("bug_severity", "critical") FILTER html %] + [% filtered_severity_major = display_value("bug_severity", "major") FILTER html %] + [% filtered_severity_normal = display_value("bug_severity", "normal") FILTER html %] + [% filtered_severity_minor = display_value("bug_severity", "minor") FILTER html %] + [% filtered_severity_trivial = display_value("bug_severity", "trivial") FILTER html %] + [% filtered_severity_enhancement = display_value("bug_severity", "enhancement") FILTER html %] + + [% filtered_platform_all = display_value("rep_platform", "All") FILTER html %] + [% filtered_platform_x86_64 = display_value("rep_platform", "x86_64") FILTER html %] + [% filtered_platform_arm = display_value("rep_platform", "ARM") FILTER html %] + + [% filtered_opsys_all = display_value("op_sys", "All") FILTER html %] + [% filtered_opsys_windows = display_value("op_sys", "Windows 7") FILTER html %] + [% filtered_opsys_mac = display_value("op_sys", "Mac OS X") FILTER html %] + [% filtered_opsys_linux = display_value("op_sys", "Linux") FILTER html %] + + [% filtered_status_new = display_value("bug_status", "NEW") FILTER html %] + + [% + vars.help_html.priority = + "This field describes the importance and order in which $terms.abug + should be fixed compared to other ${terms.bugs}. This field is utilized + by the programmers/engineers to prioritize their work to be done." + + vars.help_html.bug_severity = + "This field describes the impact of ${terms.abug}. + <table> + <tr> + <th>$filtered_severity_blocker</th> + <td>Blocks development and/or testing work</td> + </tr> + <tr> + <th>$filtered_severity_critical</th> + <td>crashes, loss of data, severe memory leak</td> + </tr> + <tr> + <th>$filtered_severity_major</th> + <td>major loss of function</td> + </tr> + <tr> + <th>$filtered_severity_normal</th> + <td>regular issue, some loss of functionality under specific circumstances</td> + </tr> + <tr> + <th>$filtered_severity_minor</th> + <td>minor loss of function, or other problem where easy + workaround is present</td> + </tr> + <tr> + <th>$filtered_severity_trivial</th> + <td>cosmetic problem like misspelled words or misaligned + text</td> + </tr> + <tr> + <th>$filtered_severity_enhancement</th> + <td>Request for enhancement</td> + </table>" + + vars.help_html.rep_platform = + "This is the hardware platform against which the $terms.bug was reported. + Legal platforms include: + <ul> + <li>$filtered_platform_all (happens on all platforms; cross-platform ${terms.bug})</li> + <li>$filtered_platform_x86_64</li> + <li>$filtered_platform_arm</li> + </ul> + <b>Note:</b> When searching, selecting the option + <em>$filtered_platform_all</em> does not + select $terms.bugs assigned against any platform. It merely selects + $terms.bugs that are marked as occurring on all platforms, i.e. are + designated <em>$filtered_platform_all</em>.", + + vars.help_html.op_sys = + "This is the operating system against which the $terms.bug was + reported. Legal operating systems include: + <ul> + <li>$filtered_opsys_all (happens on all operating systems; cross-platform ${terms.bug})</li> + <li>$filtered_opsys_windows</li> + <li>$filtered_opsys_mac</li> + <li>$filtered_opsys_linux</li> + </ul> + Sometimes the operating system implies the platform, but not + always. For example, Linux can run on x86_64, ARM, and others.", + + vars.help_html.assigned_to = + "This is the person in charge of resolving the ${terms.bug}. Every time + this field changes, the status changes to + <b>$filtered_status_new</b> to make it + easy to see which new $terms.bugs have appeared on a person's list.</p>", + %] +[% END %] diff --git a/extensions/BMO/template/en/default/hook/bug/process/header-title.html.tmpl b/extensions/BMO/template/en/default/hook/bug/process/header-title.html.tmpl new file mode 100644 index 000000000..a99b4f9f6 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/process/header-title.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. + #%] + +[% title = title.replace('^' _ terms.Bug _ ' ', '') %] diff --git a/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl new file mode 100644 index 000000000..e903b811d --- /dev/null +++ b/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl @@ -0,0 +1,14 @@ +[%# 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/BMO/web/styles/edit_bug.css') %] +[% javascript_urls.push('extensions/BMO/web/js/edit_bug.js') %] +[% title = "$bug.bug_id – $filtered_desc" %] +[% javascript = javascript _ + "document.title = document.title.replace(/^" _ terms.Bug _ " /, '');" +%] diff --git a/extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl b/extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl new file mode 100644 index 000000000..2c8bb7494 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/field-descs-end.none.tmpl @@ -0,0 +1,11 @@ +[%# 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. + #%] + +[% IF in_template_var %] + [% vars.field_descs.cc_count = "CC Count" %] +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/footer-end.html.tmpl b/extensions/BMO/template/en/default/hook/global/footer-end.html.tmpl new file mode 100644 index 000000000..45fe0b1a4 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/footer-end.html.tmpl @@ -0,0 +1,17 @@ +[% IF urlbase == 'https://bugzilla.mozilla.org/' %] +<script type="text/javascript" src="[% 'extensions/BMO/web/js/webtrends.js' FILTER mtime %]"></script> +<script type="text/javascript"> +//<![CDATA[ +var _tag=new WebTrends({"dcsid":"dcsqjgr30wz5bd6zokoukhwj3_7z7z","rate":100,"fpcdom":"mozilla.org"}); +_tag.dcsGetId(); +//]]> +</script> +<script> +//<![CDATA[ +_tag.dcsCollect(); +//]]> +</script> +<noscript> +<div><img alt="DCSIMG" id="DCSIMG" width="1" height="1" src="//statse.webtrendslive.com/dcsqjgr30wz5bd6zokoukhwj3_7z7z/njs.gif?dcsuri=/nojavascript&WT.js=No&WT.tv=8.6.2"/></div> +</noscript> +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl b/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl new file mode 100644 index 000000000..b5bb4719c --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl @@ -0,0 +1 @@ +<a href="https://www.mozilla.org/about/policies/privacy-policy.html">Privacy Policy</a> diff --git a/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl new file mode 100644 index 000000000..88ad47583 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl @@ -0,0 +1,60 @@ +[%# + # 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 BMOHeader Bugzilla Extension. + # + # The Initial Developer of the Original Code is Reed Loden. + # Portions created by the Initial Developer are Copyright (C) 2010 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # Reed Loden <reed@reedloden.com> + #%] + +<link rel="shortcut icon" href="extensions/BMO/web/images/favicon.ico"> +[% IF bug %] +<link id="shorturl" rev="canonical" href="https://bugzil.la/[% bug.bug_id FILTER uri %]"> +[% END %] + +<style type="text/css"> +body { + background: url("extensions/BMO/web/images/background.png") repeat-x; +} +</style> + +[%# *** Bug List Navigation *** %] +[% IF bug %] + [% SET my_search = user.recent_search_for(bug) %] + [% IF my_search %] + [% SET last_bug_list = my_search.bug_list %] + [% SET this_bug_idx = lsearch(last_bug_list, bug.id) %] + <link rel="Up" href="buglist.cgi?regetlastlist= + [%- my_search.id FILTER uri %]"> + <link rel="First" href="show_bug.cgi?id= + [%- last_bug_list.first FILTER uri %]&list_id= + [%- my_search.id FILTER uri %]"> + <link rel="Last" href="show_bug.cgi?id= + [%- last_bug_list.last FILTER uri %]&list_id= + [%- my_search.id FILTER uri %]"> + [% IF this_bug_idx > 0 %] + [% prev_bug = this_bug_idx - 1 %] + <link rel="Prev" href="show_bug.cgi?id= + [%- last_bug_list.$prev_bug FILTER uri %]&list_id= + [%- my_search.id FILTER uri %]"> + [% END %] + [% IF this_bug_idx + 1 < last_bug_list.size %] + [% next_bug = this_bug_idx + 1 %] + <link rel="Next" href="show_bug.cgi?id= + [%- last_bug_list.$next_bug FILTER uri %]&list_id= + [%- my_search.id FILTER uri %]"> + [% END %] + [% END %] +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl b/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl new file mode 100644 index 000000000..e265d0bb6 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl @@ -0,0 +1,40 @@ +[% IF !javascript_urls %] + [% javascript_urls = [] %] +[% END %] + +[% IF template.name == 'list/list.html.tmpl' %] + [% javascript_urls.push('extensions/BMO/web/js/sorttable.js') %] +[% END %] + +[% IF !bodyclasses %] + [% bodyclasses = [] %] +[% END %] + +[%# Change the background/border for bugs/attachments in certain bug groups %] +[% IF template.name == 'attachment/edit.html.tmpl' + || template.name == 'attachment/create.html.tmpl' + || template.name == 'attachment/diff-header.html.tmpl' %] + [% style_urls.push("skins/custom/bug_groups.css") %] + + [% IF template.name == 'attachment/edit.html.tmpl' + || template.name == 'attachment/diff-header.html.tmpl' %] + [% IF bodyclasses == 'no_javascript' %] + [% bodyclasses = ['no_javascript'] %] + [% END %] + [% FOREACH group = attachment.bug.groups_in %] + [% bodyclasses.push("bz_group_$group.name") %] + [% END %] + [% END %] + + [% IF template.name == 'attachment/create.html.tmpl' %] + [% FOREACH group = bug.groups_in %] + [% bodyclasses.push("bz_group_$group.name") %] + [% END %] + [% END %] +[% END %] + +[% IF user.in_group('canconfirm') %] + [% yui.push('container', 'menu') %] + [% style_urls.push('js/yui/assets/skins/sam/menu.css') %] + [% javascript_urls.push('extensions/BMO/web/js/edituser_menu.js') %] +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl b/extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl new file mode 100644 index 000000000..0c90b97b9 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/messages-messages.html.tmpl @@ -0,0 +1,5 @@ +[% IF message_tag == "employee_incident_creation_failed" %] + The [% terms.bug %] was created successfully, but the dependent + Employee Incident [% terms.bug %] creation failed. The error has + been logged and no further action is required at this time. +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl b/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl new file mode 100644 index 000000000..666621d8b --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl @@ -0,0 +1,5 @@ +[% + setting_descs.product_chooser = "Product chooser to use when entering bugs", + setting_descs.pretty_product_chooser = "Pretty chooser with common products and icons", + setting_descs.full_product_chooser = "Full chooser with all products", +%] diff --git a/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl new file mode 100644 index 000000000..0a674aa30 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl @@ -0,0 +1,5 @@ +[% IF object == 'group_admins' %] + the group administrators report +[% ELSIF object == 'email_queue' %] + the email queue status report +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl new file mode 100644 index 000000000..eff0e35cc --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl @@ -0,0 +1,36 @@ +[%# 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 BMO Extension + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # Byron Jones <bjones@mozilla.com> + #%] + +[% IF error == "user_activity_missing_username" %] + [% title = "Missing Username" %] + You must provide at least one email address to report on. + +[% ELSIF error == "report_invalid_date" %] + [% title = "Invalid Date" %] + The date '[% date FILTER html %]' is invalid. + +[% ELSIF error == "report_invalid_parameter" %] + [% title = "Invalid Parameter" %] + The value for parameter [% name FILTER html %] is invalid. + +[% ELSIF error == "invalid_object" %] + Invalid [% object FILTER html %]: "[% value FILTER html %]" + +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl new file mode 100644 index 000000000..346e02373 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl @@ -0,0 +1,29 @@ +<!-- 1.0@bugzilla.org --> +[%# 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): Gervase Markham <gerv@gerv.net> + # Reed Loden <reed@reedloden.com> + #%] + +[% IF (group == "canconfirm" OR group == "editbugs") AND !reason %] + <p> + If you are attempting to confirm an unconfirmed [% terms.bug %] or edit the fields of a [% terms.bug %], + <a href="http://www.gerv.net/hacking/before-you-mail-gerv.html#bugzilla-permissions">find + out how to get the necessary permissions</a>. + </p> +[% END %] diff --git a/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl b/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl new file mode 100644 index 000000000..89eef6fc4 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl @@ -0,0 +1,3 @@ +[% + terms.BugzillaTitle = "Bugzilla@Mozilla" +%] diff --git a/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl b/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl new file mode 100644 index 000000000..56a133c6c --- /dev/null +++ b/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl @@ -0,0 +1,10 @@ +<li> +| +<a href="page.cgi?id=etiquette.html"> + [%- terms.Bugzilla %] Etiquette</a> +</li> +<li> +| +<a href="https://developer.mozilla.org/en/Bug_writing_guidelines"> + [%- terms.Bug %] Writing Guidelines</a> +</li> diff --git a/extensions/BMO/template/en/default/hook/index-intro.html.tmpl b/extensions/BMO/template/en/default/hook/index-intro.html.tmpl new file mode 100644 index 000000000..d81d91491 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/index-intro.html.tmpl @@ -0,0 +1,2 @@ +<a id="get_help" class="bz_common_actions" + href="page.cgi?id=get_help.html"><span>Get Help</span></a>
\ No newline at end of file diff --git a/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl b/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl new file mode 100644 index 000000000..4d12ab345 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl @@ -0,0 +1,13 @@ +<dt> + [% display_value("resolution", "INCOMPLETE") FILTER html %] +</dt> +<dd> + The problem is vaguely described with no steps to reproduce, + or is a support request. The reporter should be directed to the + product's support page for help diagnosing the issue. If there + are only a few comments in the [% terms.bug %], it may be reopened only if + the original reporter provides more info, or confirms someone + else's steps to reproduce. If the [% terms.bug %] is long, when enough info + is provided a new [% terms.bug %] should be filed and the original [% terms.bug %] + marked as a duplicate of it. +</dd> diff --git a/extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl b/extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl new file mode 100644 index 000000000..4d12ab345 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl @@ -0,0 +1,13 @@ +<dt> + [% display_value("resolution", "INCOMPLETE") FILTER html %] +</dt> +<dd> + The problem is vaguely described with no steps to reproduce, + or is a support request. The reporter should be directed to the + product's support page for help diagnosing the issue. If there + are only a few comments in the [% terms.bug %], it may be reopened only if + the original reporter provides more info, or confirms someone + else's steps to reproduce. If the [% terms.bug %] is long, when enough info + is provided a new [% terms.bug %] should be filed and the original [% terms.bug %] + marked as a duplicate of it. +</dd> diff --git a/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl b/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl new file mode 100644 index 000000000..dae7f9108 --- /dev/null +++ b/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl @@ -0,0 +1,49 @@ +[%# 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. + #%] + +<h2>Other Reports</h2> + +<ul> + <li> + <strong> + <a href="[% urlbase FILTER none %]page.cgi?id=user_activity.html">User Changes</a> + </strong> - Show changes made by an individual user. + </li> + <li> + <strong> + <a href="[% urlbase FILTER none %]page.cgi?id=triage_reports.html">Triage Report</a> + </strong> - Report on UNCONFIRMED [% terms.bugs %] to assist triage. + </li> + <li> + <strong> + <a href="[% urlbase FILTER none %]page.cgi?id=release_tracking_report.html">Release Tracking Report</a> + </strong> - For triaging release-train flag information. + </li> + [% IF user.in_group('editusers') %] + <li> + <strong> + <a href="[% urlbase FILTER none %]page.cgi?id=group_admins.html">Group Admins</a> + </strong> - Group Admins Report + </li> + [% END %] + [% IF user.in_group('editusers') || user.in_group('infrasec') %] + <li> + <strong> + <a href="[% urlbase FILTER none %]page.cgi?id=group_membership.html">Group Membership Report</a> + </strong> - Lists the groups a user is a member of. + </li> + [% END %] + [% IF user.in_group('admin') || user.in_group('infra') %] + <li> + <strong> + <a href="[% urlbase FILTER none %]page.cgi?id=email_queue.html">Email Queue</a> + </strong> - TheSchwartz queue + </li> + [% END %] +</ul> + diff --git a/extensions/BMO/template/en/default/list/list.microsummary.tmpl b/extensions/BMO/template/en/default/list/list.microsummary.tmpl new file mode 100644 index 000000000..8925db8dd --- /dev/null +++ b/extensions/BMO/template/en/default/list/list.microsummary.tmpl @@ -0,0 +1,29 @@ +[%# 1.0@bugzilla.org %] +[%# 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): Ronaldo Maia <rmaia@everythingsolved.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + + +[% IF searchname %] + [% searchname FILTER html %] ([% bugs.size %]) +[% ELSE %] + [% terms.Bug %] List ([% bugs.size %]) +[% END %] diff --git a/extensions/BMO/template/en/default/list/server-push.html.tmpl b/extensions/BMO/template/en/default/list/server-push.html.tmpl new file mode 100644 index 000000000..1c1f3cf36 --- /dev/null +++ b/extensions/BMO/template/en/default/list/server-push.html.tmpl @@ -0,0 +1,52 @@ +[%# 1.0@bugzilla.org %] +[%# 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): Myk Melez <myk@mozilla.org> + #%] + +[%# INTERFACE: + # debug: boolean. True if we want the search displayed while we wait. + # query: string. The SQL query which makes the buglist. + #%] + +[% PROCESS global/variables.none.tmpl %] + +<html> + <head> + <title>[% terms.Bugzilla %] is pondering your search</title> + </head> + <body> + <div style="margin-top: 15%; text-align: center;"> + <center><img src="extensions/BMO/web/images/mozchomp.gif" alt="" + width="160" height="87"></center> + <h1>Please wait while your [% terms.bugs %] are retrieved.</h1> + </div> + + [% IF debug %] + <p> + [% FOREACH debugline = debugdata %] + <code>[% debugline FILTER html %]</code><br> + [% END %] + </p> + <p> + <code>[% query FILTER html %]</code> + </p> + [% END %] + + </body> +</html> diff --git a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl new file mode 100644 index 000000000..f326d1821 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl @@ -0,0 +1,25 @@ +[%# 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): David Lawrence <dkl@mozilla.com> + #%] + +<html> + <head> + <meta http-equiv="refresh" content="0;url=https://developer.mozilla.org/en/Bug_writing_guidelines"> + </head> +</html> diff --git a/extensions/BMO/template/en/default/pages/email_queue.html.tmpl b/extensions/BMO/template/en/default/pages/email_queue.html.tmpl new file mode 100644 index 000000000..0e4a37551 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/email_queue.html.tmpl @@ -0,0 +1,66 @@ +[%# 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. + #%] + +[% INCLUDE global/header.html.tmpl + title = "Job Queue Status" + style_urls = [ "extensions/BMO/web/styles/reports.css" ] +%] + +[% IF jobs.size %] + + <p><i>[% jobs.size FILTER none %] email(s) in the queue.</i></p> + + <table id="report" cellspacing="0" border="0"> + <tr id="report-header"> + <th>Insert Time</th> + <th>Run Time</th> + <th>Age</th> + <th>Error Count</th> + <th>Last Error</th> + <th>Error Message</th> + </tr> + [% FOREACH job IN jobs %] + <tr class="report item [% loop.count % 2 == 1 ? "report_row_odd" : "report_row_even" %]"> + <td nowrap>[% time2str("%Y-%m-%d %H:%M:%S %Z", job.insert_time) FILTER html %]</td> + <td nowrap>[% time2str("%Y-%m-%d %H:%M:%S %Z", job.run_time) FILTER html %]</td> + <td nowrap> + [% age = now - job.insert_time %] + [% IF age < 60 %] + [% age FILTER none %]s + [% ELSIF age < 60 * 60 %] + [% age / 60 FILTER format('%.0f') %]m + [% ELSE %] + [% age / (60 * 60) FILTER format('%.0f') %]h + [% END %] + </td> + <td nowrap>[% job.error_count FILTER html %]</td> + <td nowrap> + [% IF job.error_count %] + [% time2str("%Y-%m-%d %H:%M:%S %Z", job.error_time) FILTER html %] + [% ELSE %] + - + [% END %] + </td> + <td> + [% IF job.error_count %] + [% job.error_message FILTER html %] + [% ELSE %] + - + [% END %] + </td> + </tr> + [% END %] + </table> + +[% ELSE %] + +<p><i>The email queue is empty.</i></p> + +[% END %] + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl new file mode 100644 index 000000000..2f8a89503 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl @@ -0,0 +1,146 @@ +<!-- 1.0@bugzilla.org --> +[%# 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): Stefan Seifert <nine@detonation.org> + # Gervase Markham <gerv@gerv.net> + #%] + +[% PROCESS global/header.html.tmpl + title = "Bugzilla Etiquette" + style = "li { margin: 5px } .heading { font-weight: bold }" %] + +<p> + There's a number of <i lang="fr">faux pas</i> you can commit when using + [%+ terms.Bugzilla %]. At the very + least, these will make Mozilla contributors upset at you; if committed enough + times they will cause those contributors to demand the disabling of your + [%+ terms.Bugzilla %] account. So, ignore this advice at your peril. +</p> + +<p> + That said, Mozilla developers are generally a friendly bunch, and will be + friendly towards you as long as you follow these guidelines. +</p> + +<h3>1. Commenting</h3> + +<p> + This is the most important section. +</p> + +<ol> + <li> + <span class="heading">No pointless comments</span>. + Unless you have something constructive and helpful to say, do not add a + comment to a [% terms.bug %]. In [% terms.bugs %] where there is a heated debate going on, you + should be even more + inclined not to add a comment. Unless you have something new to contribute, + then the [% terms.bug %] owner is aware of all the issues, and will make a judgement + as to what to do. If you agree the [% terms.bug %] should be fixed, vote for it. + Additional "I see this too" or "It works for me" comments are unnecessary + unless they are on a different platform or a significantly different build. + Constructive and helpful thoughts unrelated to the topic of the [% terms.bug %] + should go in the appropriate + <a href="http://www.mozilla.org/about/forums/">newsgroup</a>. + </li> + + <li> + <span class="heading">No obligation</span>. + "Open Source" is not the same as "the developers must do my bidding." + Everyone here wants to help, but no one else has any <i>obligation</i> to fix + the [% terms.bugs %] you want fixed. Therefore, you should not act as if you + expect someone to fix a [% terms.bug %] by a particular date or release. + Aggressive or repeated demands will not be received well and will almost + certainly diminish the impact and interest in your suggestions. + </li> + + <li> + <span class="heading">No abusing people</span>. + Constant and intense critique is one of the reasons we build great products. + It's harder to fall into group-think if there is always a healthy amount of + dissent. We want to encourage vibrant debate inside of the Mozilla + community, we want you to disagree with us, and we want you to effectively + argue your case. However, we require that in the process, you attack + <i>things</i>, not <i>people</i>. Examples of things include: interfaces, + algorithms, and schedules. Examples of people include: developers, + designers and users. <b>Attacking a person may result in you being banned + from [% terms.Bugzilla %].</b> + </li> + + <li> + <span class="heading">No private email</span>. + Unless the [% terms.bug %] owner or another respected project contributor has asked you + to email them with specific information, please place all information + relating to [% terms.bugs %] + in the [% terms.bug %] itself. Do not send them by private email; no-one else can read + them if you do that, and they'll probably just get ignored. If a file + is too big for [% terms.Bugzilla %], add a comment giving the file size and contents + and ask what to do. + </li> +</ol> + +<h3>2. Changing Fields</h3> + +<ol> + <li> + <span class="heading">No messing with other people's [% terms.bugs %]</span>. + Unless you are the [% terms.bug %] assignee, or have some say over the use of their + time, never change the Priority or Target Milestone fields. If in doubt, + do not change the fields of [% terms.bugs %] you do not own - add a comment + instead, suggesting the change. + </li> + + <li> + <span class="heading">No whining about decisions</span>. + If a respected project contributor has marked a [% terms.bug %] as INVALID, then it is + invalid. Someone filing another duplicate of it does not change this. Unless + you have further important evidence, do not post a comment arguing that an + INVALID or WONTFIX [% terms.bug %] should be reopened. + </li> + +</ol> + +<h3>3. Applicability</h3> + +<ol> + <li> + Some of these rules may not apply to you. If they do not, you will know + exactly which ones do not, and why they do not apply. If you are not + sure, then they definitely all apply to you. + </li> +</ol> + +<p> + If you see someone not following these rules, the first step is, as an exception + to guideline 1.4, to make them aware of this document by <em>private</em> mail. + Flaming people publically in [% terms.bugs %] violates guidelines 1.1 and 1.3. In the case of + persistent offending you should report the matter to + <a href="mailto:gerv@mozilla.org">Gerv</a>. +</p> + +<p> + This entire document can be summed up in one sentence: + do unto others as you would have them do unto you. +</p> + +<p> + Other useful documents: + <a href="page.cgi?id=bug-writing.html">The [% terms.Bug %] Writing Guidelines</a>. +</p> + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/get_help.html.tmpl b/extensions/BMO/template/en/default/pages/get_help.html.tmpl new file mode 100644 index 000000000..70ff0a12b --- /dev/null +++ b/extensions/BMO/template/en/default/pages/get_help.html.tmpl @@ -0,0 +1,42 @@ +[%# 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): David Miller <justdave@bugzilla.org> + #%] + +[% PROCESS global/variables.none.tmpl %] +[% INCLUDE global/header.html.tmpl title = "Get Help with Mozilla Products" %] + +<div id="steps"> +<h2>Got a problem?</h2> + +<ul> +<li><a href="http://www.mozilla.org/support/">Get help with your mozilla.org product</a></li> +<li><a href="http://hendrix.mozilla.org/">Leave quick feedback</a></li> +<li><a href="http://input.mozilla.com/feedback">Report a broken website</a></li> +<li><a href="enter_bug.cgi">Report a [% terms.bug %]</a> - latest release only + [% IF NOT user.id %] + (you'll need an + <a href="createaccount.cgi">account</a>) + [% END %] +</li> +</ul> +</div> + +<br> + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl new file mode 100644 index 000000000..8a7e5b96f --- /dev/null +++ b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl @@ -0,0 +1,54 @@ +[%# 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 BMO Extension + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # David Lawrence <dkl@mozilla.com> + #%] + +[% INCLUDE global/header.html.tmpl + title = "Group Admins Report" + style_urls = [ "extensions/BMO/web/styles/reports.css" ] + javascript_urls = [ "js/yui/datasource/datasource-min.js" ] +%] + +[% IF groups.size > 0 %] + <table border="0" cellspacing="0" id="report" width="100%"> + <tr id="report-header"> + <th align="left">Name</th> + <th align="left">Admins</th> + </tr> + + [% FOREACH group = groups %] + [% count = loop.count() %] + <tr class="report_item [% count % 2 == 1 ? "report_row_odd" : "report_row_even" %]"> + <td> + [% group.name FILTER html %] + </td> + <td> + [% FOREACH admin = group.admins %] + [% INCLUDE global/user.html.tmpl who = admin %][% ", " UNLESS loop.last %] + [% END %] + </td> + </tr> + [% END %] + </table> +[% ELSE %] + <p> + No groups found. + </p> +[% END %] + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/group_membership.html.tmpl b/extensions/BMO/template/en/default/pages/group_membership.html.tmpl new file mode 100644 index 000000000..2680c7da2 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/group_membership.html.tmpl @@ -0,0 +1,75 @@ +[%# 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. + #%] + +[% PROCESS global/header.html.tmpl + title = "Group Membership Report" + yui = [ 'autocomplete' ] + style_urls = [ "extensions/BMO/web/styles/reports.css" ] + javascript_urls = [ "js/field.js" ] +%] + +<form method="GET" action="page.cgi"> +<input type="hidden" name="id" id="id" value="group_membership.html"> + +<table id="parameters"> +<tr> + <th>User(s):</th> + <td> + [% INCLUDE global/userselect.html.tmpl + id => "who" + name => "who" + value => who.join(', ') + size => 40 + classes => ["bz_userfield"] + multiple => 5 + field_title => "One or more email address (comma delimited)" + %] + </td> + <td> </td> + <td> + <select name="output" + onchange="document.getElementById('id').value = 'group_membership.' + this.value"> + <option value="html" [% 'selected' IF output == 'html' %]>HTML</option> + <option value="txt" [% 'selected' IF output == 'txt' %]>Text</option> + </select> + </td> + <td> + <input type="submit" value="Generate"> + </td> +</tr> +</table> + +</form> + +[% IF users.size %] + + <table border="0" cellspacing="0" id="report" width="100%"> + [% FOREACH u = users %] + <tr> + <th colspan="3">[% u.user.identity FILTER html %]</th> + </tr> + [% FOREACH g = u.groups %] + <tr> + <td> </td> + <td>[% g.name FILTER html %]</td> + <td>[% g.desc FILTER html %]</td> + <td> + [% IF g.via == '' %] + direct + [% ELSE %] + <i>[% g.via FILTER html %]</i> + [% END %] + </td> + </tr> + [% END %] + [% END %] + </table> + +[% END %] + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/group_membership.txt.tmpl b/extensions/BMO/template/en/default/pages/group_membership.txt.tmpl new file mode 100644 index 000000000..9958f0877 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/group_membership.txt.tmpl @@ -0,0 +1,16 @@ +[%# 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. + #%] + +[% FOREACH u = users %] +[% u.user.login FILTER none%]: + [% FOREACH g = u.groups %] + [% g.name FILTER none %] + [% ',' UNLESS loop.last %] + [% END %] + [% "\n" %] +[% END %] diff --git a/extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl b/extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl new file mode 100644 index 000000000..71228014a --- /dev/null +++ b/extensions/BMO/template/en/default/pages/release_tracking_report.html.tmpl @@ -0,0 +1,103 @@ +[%# 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. + #%] + +[% INCLUDE global/header.html.tmpl + title = "Release Tracking Report" + style_urls = [ "extensions/BMO/web/styles/reports.css" ] + javascript_urls = [ "extensions/BMO/web/js/release_tracking_report.js" ] +%] + +<noscript> +<h1>JavaScript is required to use this report.</h1> +</noscript> + +<script> +var flags_data = [% flags_json FILTER none %]; +var products_data = [% products_json FILTER none %]; +var fields_data = [% fields_json FILTER none %]; +var default_query = '[% default_query FILTER js %]'; +</script> + +<form action="page.cgi" method="get" onSubmit="return onFormSubmit()"> +<input type="hidden" name="id" value="release_tracking_report.html"> +<input type="hidden" name="q" id="q" value=""> +<table> + +<tr> + <th>Approval:</th> + <td> + Show [% terms.bugs %] where + <select id="flag" onChange="onFlagChange()"> + [% FOREACH flag_name = flag_names %] + <option value="[% flag_name FILTER html %]">[% flag_name FILTER html %]</option> + [% END %] + </select> + + was changed to (and is currently) + <select id="flag_value"> + <option value="?">?</option> + <option value="-">-</option> + <option value="+">+</option> + </select> + + between + <select id="range" onChange="serialiseForm()"> + [% FOREACH range = ranges %] + <option value="[% range.value FILTER html %]"> + [% range.label FILTER html %] + </option> + [% END %] + </select> + </td> +</tr> + +<tr> + <th>Status:</th> + <td> + for the product + <select id="product" onChange="onProductChange()"> + </select> + </td> +</tr> + +<tr> + <td> </td> + <td> + <select id="op" onChange="serialiseForm()"> + <option value="and">All selected tracking fields (AND)</option> + <option value="or">Any selected tracking fields (OR)</option> + </select> + [ + <a href="javascript:void(0)" onClick="selectAllFields()">All</a> | + <a href="javascript:void(0)" onClick="selectNoFields()">None</a> + ] + [ + <a href="javascript:void(0)" onClick="invertFields()">Invert</a> + ] + <br> + <span id="tracking_span"> + </span> + </td> +</tr> + +<tr> + <td> </td> + <td colspan="2"> + <input type="submit" value="Search"> + <input type="submit" value="Reset" onClick="onFormReset(); return false"> + <a href="?" id="bookmark">Bookmarkable Link</a> + </td> +</tr> +</table> +</form> + +<p> + <i>"fixed" in the status field checks for the "verified" status as well as "fixed".</i> +</p> + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl b/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl new file mode 100644 index 000000000..a7f26e86d --- /dev/null +++ b/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl @@ -0,0 +1,199 @@ +[%# 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 BMO Extension + # + # The Initial Developer of the Original Code is the Mozilla Foundation + # Portions created by the Initial Developers are Copyright (C) 2011 the + # Initial Developer. All Rights Reserved. + # + # Contributor(s): + # Byron Jones <bjones@mozilla.com> + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% js_data = BLOCK %] +var useclassification = false; +var first_load = true; +var last_sel = []; +var cpts = new Array(); +[% n = 1 %] +[% FOREACH p = user.get_selectable_products %] + cpts['[% n FILTER js %]'] = [ + [%- FOREACH c = p.components %]'[% c.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ]; + [% n = n+1 %] +[% END %] + +var selected_components = [ + [%- FOREACH c = input.component %]'[% c FILTER js %]' + [%- ',' UNLESS loop.last %] [%- END ~%] ]; + +[% END %] + +[% INCLUDE global/header.html.tmpl + title = "Triage Reports" + yui = [ 'autocomplete', 'calendar' ] + javascript = js_data + javascript_urls = [ "js/util.js", "js/field.js", "js/productform.js", + "extensions/BMO/web/js/triage_reports.js" ] + style_urls = [ "skins/standard/buglist.css", + "extensions/BMO/web/styles/triage_reports.css" ] +%] + +<noscript> +<h2>Javascript is required to use this report.</h2> +</noscript> + +[% PROCESS "global/field-descs.none.tmpl" %] + +<form id="activity_form" name="activity_form" action="page.cgi" method="get" + onSubmit="return onGenerateReport()"> +<input type="hidden" name="id" value="triage_reports.html"> +<input type="hidden" name="action" value="run"> + +Show UNCONFIRMED [% terms.bugs %] with: +<table id="triage_form"> + +<tr> + <th>Product:</th> + <td> + <select name="product" id="product" onChange="onSelectProduct()"> + <option value=""></option> + [% FOREACH p = user.get_selectable_products %] + <option value="[% p.name FILTER html %]" + [% " selected" IF input.product == p.name %]> + [% p.name FILTER html %] + </option> + [% END %] + </select> + </td> + <td rowspan="2" valign="top"> + <b>Comment:</b><br> + + <input type="checkbox" name="filter_commenter" id="filter_commenter" value="1" + [% 'checked' IF input.filter_commenter %]> + <label for="filter_commenter">where the last commenter</label> + <select name="commenter" id="commenter" onChange="onCommenterChange()"> + <option value="reporter" [% 'selected' IF input.commenter == 'reporter' %]>is the reporter</option> + <option value="noconfirm" [% 'selected' IF input.commenter == 'noconfirm' %]>does not have canconfirm</option> + <option value="is" [% 'selected' IF input.commenter == 'is' %]>is</option> + </select> + [%+ INCLUDE global/userselect.html.tmpl + id => "commenter_is" + name => "commenter_is" + value => input.commenter_is + size => 20 + emptyok => 0 + classes = input.commenter == "is" ? "" : "hidden" + %] + <br> + + <input type="checkbox" name="filter_last" id="filter_last" value="1" + [% 'checked' IF input.filter_last %]> + <label for="filter_last">where the last comment is older than</label> + <select name="last" id="last" onChange="onLastChange()"> + <option value="30" [% 'selected' IF input.last == '30' %]>30 days</option> + <option value="60" [% 'selected' IF input.last == '60' %]>60 days</option> + <option value="90" [% 'selected' IF input.last == '90' %]>90 days</option> + <option value="365" [% 'selected' IF input.last == '365' %]>one year</option> + <option value="is" [% 'selected' IF input.last == 'is' %]>the date</option> + </select> + <span id="last_is_span" class="[% 'hidden' IF input.last != 'is' %]"> + <input type="text" id="last_is" name="last_is" size="11" maxlength="10" + value="[% input.last_is FILTER html %]" + onChange="updateCalendarLastIs(this)"> + <button type="button" class="calendar_button" id="button_calendar_last_is" + onClick="showCalendar('last_is')"><span>Calendar</span> + </button> + <div id="con_calendar_last_is"></div> + </span> + <br> + </td> +</tr> + +<tr> + <th>Component:</th> + <td> + <select name="component" id="component" multiple size="5"> + </select> + </td> +</tr> + +<tr> + <td> </td> + <td> + <input type="submit" value="Generate Report"> + </td> +</tr> + +</table> + +</form> +<script> + createCalendar('last_is'); +</script> + +[% IF input.action == 'run' %] +<hr> +[% IF bugs.size > 0 %] + <p> + Found [% bugs.size %] [%+ terms.bug %][% 's' IF bugs.size != 1 %]: + </p> + <table border="0" cellspacing="0" id="report" width="100%"> + <tr id="report-header"> + <th>[% terms.Bug %] / Date</th> + <th>Summary</th> + <th>Reporter / Commenter</th> + <th>Comment Date</th> + <th>Last Comment</th> + </tr> + + [% FOREACH bug = bugs %] + [% count = loop.count() %] + <tr class="bz_bugitem [% count % 2 == 1 ? "bz_row_odd" : "bz_row_even" %]"> + <td> + [% bug.id FILTER bug_link(bug.id) FILTER none %]<br> + [% bug.creation_ts.replace(' .*' '') FILTER html FILTER no_break %] + </td> + <td> + [% bug.summary FILTER html %] + </td> + <td> + [% INCLUDE global/user.html.tmpl who = bug.reporter %] + [% IF bug.commenter.id != bug.reporter.id %] + <br>[% INCLUDE global/user.html.tmpl who = bug.commenter %] + [% END %] + </td> + <td> + [% bug.comment_ts FILTER html FILTER no_break %] + </td> + <td> + [% bug.comment FILTER html %] + </td> + </tr> + [% END %] + </table> + + <p> + <a href="buglist.cgi?bug_id= + [%- FOREACH bug = bugs %][% bug.id FILTER uri %],[% END -%] + ">Show as a [% terms.Bug %] List</a> + </p> + +[% ELSE %] + <p> + No [% terms.bugs %] found. + </p> +[% END %] + +[% END %] + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl b/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl new file mode 100644 index 000000000..8fa944ae6 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl @@ -0,0 +1,304 @@ +[%# 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): David Miller <justdave@bugzilla.org> + # Reed Loden <reed@reedloden.com> + #%] + +[% PROCESS global/variables.none.tmpl %] +[% INCLUDE global/header.html.tmpl + title = "Bugzilla 3.6 Upgrade" +%] +[% USE date %] + +<p><b>Last Updated:</b> [% date.format(template.modtime, "%d-%b-%Y %H:%M %Z") %]</p> + +<p>On Friday, July 9, 2010, at 11:40pm PDT (0640 UTC), bugzilla.mozilla.org was + <a href="show_bug.cgi?id=558044">upgraded</a> to Bugzilla 3.6.1+. Please + <a href="enter_bug.cgi?product=mozilla.org&component=Bugzilla:+Other+b.m.o+Issues&blocked=bmo-regressions">file + any regressions</a> for tracking purposes.</p> + +<h3>Known Issues</h3> + +<p>The following is a list of issues which are known to be broken or incomplete with this upgrade so far.</p> + +<ul> + +<li>The <a href="https://bugzilla.mozilla.org/showdependencytree.cgi?id=577801&hide_resolved=1">stuff filed in Bugzilla</a>.</li> + +</ul> + +<h3>What's New</h3> + +<h4>Custom bugzilla.mozilla.org Changes</h4> + +<ul> + <li>Addition of autocomplete support for all user-related fields (assignee, + QA contact, and CC list) and the keywords field.</li> + <li>New attachment details UI.</li> + <li>New icons for the front page.</li> + <li>Removal of unused "Patches" column from buglist.</li> + <li>Initial support for <a href="http://en.wikipedia.org/wiki/Strict_Transport_Security">Strict-Transport-Security</a> (STS) header.</li> +</ul> + +<h4>General Usability Improvements</h4> + +<p>A <a href="https://wiki.mozilla.org/Bugzilla:CMU_HCI_Research_2008">scientific + usability study</a> was done on [% terms.Bugzilla %] by researchers + from Carnegie-Mellon University. As a result of this study, + <a href="https://bugzilla.mozilla.org/showdependencytree.cgi?id=490786&hide_resolved=0">several + usability issues</a> were prioritized to be fixed, based on specific data + from the study.</p> + +<p>As a result, you will see many small improvements in [% terms.Bugzilla %]'s + usability, such as using Javascript to validate certain forms before + they are submitted, standardizing the words that we use in the user interface, + being clearer about what [% terms.Bugzilla %] needs from the user, + and other changes, all of which are also listed individually in this New + Features section.</p> + +<p>Work continues on improving usability for the next release of + [%+ terms.Bugzilla %], but the results of the research have already + had an impact on this 3.6 release.</p> + +<h4>Improved Quicksearch</h4> + +<p>The "quicksearch" box that appears on the front page of + [%+ terms.Bugzilla %] and in the header/footer of every page + is now simplified and made more powerful. There is a + <kbd>[?]</kbd> link next to the box that will take you to + the simplified <a href="page.cgi?id=quicksearch.html">Quicksearch Help</a>, + which describes every single feature of the system in a simple layout, + including new features such as the ability to use partial field names + when searching.</p> + +<p>Quicksearch should also be much faster than it was before, particularly + on large installations.</p> + +<p>Note that in order to implement the new quicksearch, certain old + and rarely-used features had to be removed: + +<ul> + <li><b>+</b> as a prefix to mean "search additional resolutions", and + <b>+</b> as a prefix to mean "search just the summary". You can + instead use <kbd>summary:</kbd> to explicitly search summaries.</li> + <li>Searching the Severity field if you type something that matches + the first few characters of a severity. You can explicitly search + the Severity field if you want to find [% terms.bugs %] by severity.</li> + <li>Searching the Priority field if you typed something that exactly + matched the name of a priority. You can explicitly search the + Priority field if you want to find [% terms.bugs %] by priority.</li> + <li>Searching the Platform and OS fields if you typed in one of a + certain hard-coded list of strings (like "pc", "windows", etc.). + You can explicitly search these fields, instead, if you want to + find [% terms.bugs %] with a specific Platform or OS set.</li> +</ul> + +<h4>Simple "Browse" Interface</h4> + +<p>There is now a "Browse" link in the header of each [% terms.Bugzilla %] + page that presents a very basic interface that allows users to simply + browse through all open [% terms.bugs %] in particular components.</p> + +<h4>JSON-RPC Interface</h4> + +<p>[% terms.Bugzilla %] now has support for the + <a href="http://json-rpc.org/">JSON-RPC</a> WebServices protocol via + <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Server/JSONRPC.html">jsonrpc.cgi</a>. + The JSON-RPC interface is experimental in this release--if you want any + fundamental changes in how it works, + <a href="http://www.bugzilla.org/developers/reporting_bugs.html">let us + know</a>, for the next release of [% terms.Bugzilla %].</p> + +<h3>New Features</h3> + +<h4>Enhancements for Users</h4> + +<ul> + <li><b>[% terms.Bug %] Filing:</b> When filing [% terms.abug %], + [%+ terms.Bugzilla %] now visually indicates which fields are + mandatory.</li> + <li><b>[% terms.Bug %] Filing:</b> "Bookmarkable templates" now + support the "alias" and "estimated hours" fields.</li> + + <li><b>[% terms.Bug %] Editing:</b> In previous versions of + [%+ terms.Bugzilla %], if you added a private comment to [% terms.abug %], + then <em>none</em> of the changes that you made at that time were + sent to users who couldn't see the private comment. Now, for users + who can't see private comments, public changes are sent, but the private + comment is excluded from their email notification.</li> + <li><b>[% terms.Bug %] Editing:</b> The controls for groups now + appear to the right of the attachment and time-tracking tables, + when editing [% terms.abug %].</li> + <li><b>[% terms.Bug %] Editing:</b> The "Collapse All Comments" + and "Expand All Comments" links now appear to the right of the + comment list instead of above it.</li> + <li><b>[% terms.Bug %] Editing:</b> The See Also field now supports + URLs for Google Code Issues and the Debian B[% %]ug-Tracking System.</li> + <li><b>[% terms.Bug %] Editing:</b> There have been significant performance + improvements in <kbd>show_bug.cgi</kbd> (the script that displays the + [% terms.bug %]-editing form), particularly for [% terms.bugs %] that + have lots of comments or attachments.</li> + + <li><b>Attachments:</b> The "Details" page of an attachment + now displays itself as uneditable if you can't edit the fields + there.</li> + <li><b>Attachments:</b> We now make sure that there is + a Description specified for an attachment, using JavaScript, before + the form is submitted.</li> + <li><b>Attachments:</b> There is now a link back to the [% terms.bug %] + at the bottom of the "Details" page for an attachment.</li> + <li><b>Attachments:</b> When you click on an "attachment 12345" link + in a comment, if the attachment is a patch, you will now see the + formatted "Diff" view instead of the raw patch.</li> + <li><b>Attachments</b>: For text attachments, we now let the browser + auto-detect the character encoding, instead of forcing the browser to + always assume the attachment is in UTF-8.</li> + + <li><b>Search:</b> You can now display [% terms.bug %] flags as a column + in search results.</li> + <li><b>Search:</b> When viewing search results, you can see which columns are + being sorted on, and which direction the sort is on, as indicated + by arrows next to the column headers.</li> + <li><b>Search:</b> You can now search the Deadline field using relative + dates (like "1d", "2w", etc.).</li> + <li><b>Search:</b> The iCalendar format of search results now includes + a PRIORITY field.</li> + <li><b>Search:</b> It is no longer an error to enter an invalid search + order in a search URL--[% terms.Bugzilla %] will simply warn you that + some of your order options are invalid.</li> + <li><b>Search:</b> When there are no search results, some helpful + links are displayed, offering actions you might want to take.</li> + <li><b>Search:</b> For those who like to make their own + <kbd>buglist.cgi</kbd> URLs (and for people working on customizations), + <kbd>buglist.cgi</kbd> now accepts nearly every valid field in + [%+ terms.Bugzilla %] as a direct URL parameter, like + <kbd>&field=value</kbd>.</li> + + <li><b>Requests:</b> When viewing the "My Requests" page, you can now + see the lists as a normal search result by clicking a link at the + bottom of each table.</li> + <li><b>Requests:</b> When viewing the "My Requests" page, if you are + using Classifications, the Product drop-down will be grouped by + Classification.</li> + + <li>If there are multiple languages available for your + [%+ terms.Bugzilla %], you can now select what language you want + [%+ terms.Bugzilla %] displayed in using links at the top of every + page.</li> + <li>When creating a new account, you will be automatically logged in + after setting your password.</li> + <li>There is no longer a maximum password length for accounts.</li> + <li>In the Dusk skin, it's now easier to see links.</li> + <li>In the Whining system, you can now choose to receive emails even + if there are no [% terms.bugs %] that match your searches.</li> + <li>The arrows in dependency graphs now point the other way, so that + [%+ terms.bugs %] point at their dependencies.</li> + + <li><b>New Charts:</b> You can now convert an existing Saved Search + into a data series for New Charts.</li> + <li><b>New Charts:</b> There is now an interface that allows you to + delete data series.</li> + <li><b>New Charts:</b> When deleting a product, you now have the option + to delete the data series that are associated with that product.</li> +</ul> + +<h4>Enhancements for Administrators and Developers</h4> + +<ul> + <li>Depending on how your workflow is set up, it is now possible to + have both UNCONFIRMED and REOPENED show up as status choices for + a closed [% terms.bug %]. If you only want one or the other to + show up, you should edit your status workflow appropriately + (possibly by removing or disabling the REOPENED status).</li> + <li>You can now "disable" field values so that they don't show + up as choices on [% terms.abug %] unless they are already set as + the value for that [% terms.bug %]. This doesn't work for the + per-product field values (component, target_milestone, and version) + yet, though.</li> + <li>Users are now locked out of their accounts for 30 minutes after + trying five bad passwords in a row during login. Every time a + user is locked out like this, the user in the "maintainer" parameter + will get an email.</li> + <li>The minimum length allowed for a password is now 6 characters.</li> + <li>The <kbd>UNCONFIRMED</kbd> status being enabled in a product + is now unrelated to the voting parameters. Instead, there is a checkbox + to enable the <kbd>UNCONFIRMED</kbd> status in a product.</li> + <li>Information about duplicates is now stored in the database instead + of being stored in the <kbd>data/</kbd> directory. On large installations + this could save several hundred megabytes of disk space.</li> + + <li>When editing a group, you can now specify that members of a group + are allowed to grant others membership in that group itself.</li> + <li>The ability to compress BMP attachments to PNGs is now an Extension. + To enable the feature, remove the file + <kbd>extensions/BmpConvert/disabled</kbd> and then run checksetup.pl.</li> + <li>The default list of values for the Priority field are now clear English + words instead of P1, P2, etc.</li> + <li><kbd>config.cgi</kbd> now returns an ETag header and understands + the If-None-Match header in HTTP requests.</li> + <li>The XML format of <kbd>show_bug.cgi</kbd> now returns more information: + the numeric id of each comment, whether an attachment is a URL, + the modification time of an attachment, the numeric id of a flag, + and the numeric id of a flag's type.</li> +</ul> + +<h4>WebService Changes</h4> + +<ul> + <li>The WebService now returns all dates and times in the UTC timezone. + <kbd>B[% %]ugzilla.time</kbd> now acts as though the [% terms.Bugzilla %] + server were in the UTC timezone, always. If you want to write clients + that are compatible across all [% terms.Bugzilla %] versions, + check the timezone from <kbd>B[% %]ugzilla.timezone</kbd> or + <kbd>B[% %]ugzilla.time</kbd>, and always input times in that timezone + and expect times to be returned in that format.</li> + <li>You can now log in by passing <kbd>Bugzilla_login</kbd> and + <kbd>Bugzilla_password</kbd> as arguments to any WebService function. + See the + <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService.html#LOGGING_IN">Bugzilla::WebService</a> + documentation for details.</li> + <li>New Method: + <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Bug.html#attachments">B[% %]ug.attachments</a> + which allows getting information about attachments.</li> + <li>New Method: + <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Bug.html#fields">B[% %]ug.fields</a>, + which gets information about all the fields that [% terms.abug %] can have + in [% terms.Bugzilla %], include custom fields and legal values for + all fields. The <kbd>B[% %]ug.legal_values</kbd> method is now deprecated.</li> + <li>In the <kbd>B[% %]ug.add_comment</kbd> method, the "private" parameter + has been renamed to "is_private" (for consistency with other methods). + You can still use "private", though, for backwards-compatibility.</li> + <li>The WebService now has Perl's "taint mode" turned on. This means that + it validates all data passed in before sending it to the database. + Also, all parameter names are validated, and if you pass in a parameter + whose name contains anything other than letters, numbers, or underscores, + that parameter will be ignored. Mostly this just affects + customizers--[% terms.Bugzilla %]'s WebService is not functionally + affected by these changes.</li> + <li>In previous versions of [% terms.Bugzilla %], error messages were + sent word-wrapped to the client, from the WebService. Error messages + are now sent as one unbroken line.</li> +</ul> + +<h3>Last Ten Commits</h3> + +<pre>[% bzr_history.join('') FILTER html %]</pre> + +<br> + +[% INCLUDE global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/pages/user_activity.html.tmpl b/extensions/BMO/template/en/default/pages/user_activity.html.tmpl new file mode 100644 index 000000000..3e6695484 --- /dev/null +++ b/extensions/BMO/template/en/default/pages/user_activity.html.tmpl @@ -0,0 +1,219 @@ +[%# 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. + #%] + +[% IF who %] +[% who_title = ' (' _ who _ ')' %] +[% ELSE %] +[% who_title = '' %] +[% END %] + +[% INCLUDE global/header.html.tmpl + title = "User Activity Report" _ who_title + yui = [ 'autocomplete', 'calendar' ] + javascript_urls = [ "js/util.js", "js/field.js" ] + style_urls = [ "extensions/BMO/web/styles/reports.css" ] + +%] + +[% PROCESS "global/field-descs.none.tmpl" %] +[% PROCESS bug/time.html.tmpl %] + +<form id="activity_form" name="activity_form" action="page.cgi" method="get"> +<input type="hidden" name="id" value="user_activity.html"> +<input type="hidden" name="action" value="run"> +<table id="parameters"> + +<tr> + <th> + Who: + </th> + <td> + [% INCLUDE global/userselect.html.tmpl + id => "who" + name => "who" + value => who + size => 40 + emptyok => 0 + title => "One or more email address (comma delimited)" + %] + + </td> + <th> + Period: + </th> + <td> + <input type="text" id="from" name="from" size="11" + align="right" value="[% from FILTER html %]" maxlength="10" + onchange="updateCalendarFromField(this)"> + <button type="button" class="calendar_button" id="button_calendar_from" + onclick="showCalendar('from')"><span>Calendar</span> + </button> + <div id="con_calendar_from"></div> + to + <input type="text" name="to" size="11" id="to" + align="right" value ="[% to FILTER html %]" maxlength="10" + onchange="updateCalendarFromField(this)"> + <button type="button" class="calendar_button" id="button_calendar_to" + onclick="showCalendar('to')"><span>Calendar</span> + </button> + <div id="con_calendar_to"></div> + </td> + <th> + Sort: + </th> + <td> + <select name="sort"> + <option value="when" [% 'selected' IF sort == 'when' %]>When</option> + <option value="bug" [% 'selected' IF sort == 'bug' %]>[% terms.Bug %]</option> + </select> + </td> + <td> + <input type="submit" id="run" value="Generate Report"> + </td> +</tr> + +</table> +</form> + +<script type="text/javascript"> + createCalendar('from'); + createCalendar('to'); +</script> + +[% IF action == 'run' %] + +[% IF incomplete_data %] + <p> + There used to be an issue in <a href="http://www.bugzilla.org/">Bugzilla</a> + which caused activity data to be lost if there were a large number of cc's + or dependencies. That has been fixed, but some data was already lost in + your activity table that could not be regenerated. The changes that + could not reliably determine are prefixed by '?'. + </p> +[% END %] + +[% IF operations.size > 0 %] + <br> + <table border="1" cellpadding="4" cellspacing="0" id="report"> + <tr id="report-header"> + [% IF who_count > 1 %] + <th>Who</th> + [% END %] + [% IF sort == 'when' %] + <th class="sorted">[% INCLUDE sort_when_link %]</th> + <th>[% INCLUDE sort_bug_link %]</th> + [% ELSE %] + <th class="sorted">[% INCLUDE sort_bug_link %]</th> + <th>[% INCLUDE sort_when_link %]</th> + [% END %] + <th>What</th> + <th>Removed</th> + <th>Added</th> + </tr> + + [% FOREACH operation = operations %] + [% tr_class = loop.count % 2 ? 'report_row_even' : 'report_row_odd' %] + [% FOREACH change = operation.changes %] + <tr class="[% tr_class FILTER none %]"> + [% IF loop.count == 1 %] + [% IF who_count > 1 %] + <td>[% operation.who FILTER email FILTER html %]</td> + [% END %] + [% IF sort == 'when' %] + <td>[% change.when FILTER time FILTER no_break %]</td> + <td>[% operation.bug FILTER bug_link(operation.bug) FILTER none %]</td> + [% ELSE %] + <td>[% operation.bug FILTER bug_link(operation.bug) FILTER none %]</td> + <td>[% change.when FILTER time FILTER no_break %]</td> + [% END %] + [% ELSE %] + [% IF who_count > 1 %] + <td> </td> + [% END %] + <td> </td> + [% IF sort == 'when' %] + <td> </td> + [% ELSE %] + <td>[% change.when FILTER time FILTER no_break %]</td> + [% END %] + [% END %] + <td> + [% IF change.attachid %] + <a href="attachment.cgi?id=[% change.attachid FILTER uri %]" + title="[% change.attach.description FILTER html %] + [%- %] - [% change.attach.filename FILTER html %]" + >Attachment #[% change.attachid FILTER html %]</a> + [% END %] + [%IF change.comment.defined && change.fieldname == 'longdesc' %] + [% "Comment $change.comment.count" + FILTER bug_link(operation.bug, comment_num => change.comment.count) + FILTER none %] + [% ELSE %] + [%+ field_descs.${change.fieldname} FILTER html %] + [% END %] + </td> + [% PROCESS change_column change_type = change.removed %] + [% PROCESS change_column change_type = change.added %] + </tr> + [% END %] + [% END %] + </table> + <p> + <a href="buglist.cgi?bug_id=[% bug_ids.join(',') FILTER uri %]"> + Show as a [% terms.Bug %] List</a> + </p> + +[% ELSE %] + <p> + No changes. + </p> +[% END %] + +[% BLOCK change_column %] + <td> + [% IF change_type.defined %] + [% IF change.fieldname == 'estimated_time' || + change.fieldname == 'remaining_time' || + change.fieldname == 'work_time' %] + [% PROCESS formattimeunit time_unit=change_type %] + [% ELSIF change.fieldname == 'blocked' || + change.fieldname == 'dependson' %] + [% change_type FILTER bug_list_link FILTER none %] + [% ELSIF change.fieldname == 'assigned_to' || + change.fieldname == 'reporter' || + change.fieldname == 'qa_contact' || + change.fieldname == 'cc' || + change.fieldname == 'flagtypes.name' %] + [% display_value(change.fieldname, change_type) FILTER email FILTER html %] + [% ELSE %] + [% display_value(change.fieldname, change_type) FILTER html %] + [% END %] + [% ELSE %] + + [% END %] + </td> +[% END %] +[% END %] + +[% INCLUDE global/footer.html.tmpl %] + +[% BLOCK sort_when_link %] + <a href="page.cgi?id=user_activity.html&action=run& + [%~%]who=[% who FILTER uri %]& + [%~%]from=[% from FILTER uri %]& + [%~%]to=[% to FILTER uri %]& + [%~%]sort=when">When</a> +[% END %] + +[% BLOCK sort_bug_link %] + <a href="page.cgi?id=user_activity.html&action=run& + [%~%]who=[% who FILTER uri %]& + [%~%]from=[% from FILTER uri %]& + [%~%]to=[% to FILTER uri %]& + [%~%]sort=bug">[% terms.Bug %]</a> +[% END %] diff --git a/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl b/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl new file mode 100644 index 000000000..5d187bf40 --- /dev/null +++ b/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl @@ -0,0 +1,24 @@ +[%# 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): Frédéric Buclin <LpSolit@gmail.com> + # + #%] +[% PROCESS global/variables.none.tmpl %] +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> +<ShortName>[% terms.BugzillaTitle %]</ShortName> +<Description>[% terms.BugzillaTitle %] Quick Search</Description> +<InputEncoding>UTF-8</InputEncoding> +<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABGdBTUEAAK%2FINwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz%2F%2Fz8DJQAggJiQOe%2Ffv2fv7Oz8rays%2FN%2BVkfG%2FiYnJfyD%2F1%2BrVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw%2F8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi%2FG%2BQKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo%2BMXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia%2BCuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq%2FvLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg%2FkdypqCg4H8lUIACnQ%2FSOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD%2BaDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg%3D%3D</Image> +<Url type="text/html" method="GET" template="[% urlbase FILTER xml %]buglist.cgi?quicksearch={searchTerms}"/> +</OpenSearchDescription> diff --git a/extensions/BMO/web/images/background.png b/extensions/BMO/web/images/background.png Binary files differnew file mode 100644 index 000000000..eb254aab9 --- /dev/null +++ b/extensions/BMO/web/images/background.png diff --git a/extensions/BMO/web/images/bugzilla.png b/extensions/BMO/web/images/bugzilla.png Binary files differnew file mode 100644 index 000000000..4b7c10284 --- /dev/null +++ b/extensions/BMO/web/images/bugzilla.png diff --git a/extensions/BMO/web/images/favicon.ico b/extensions/BMO/web/images/favicon.ico Binary files differnew file mode 100644 index 000000000..c14fec40a --- /dev/null +++ b/extensions/BMO/web/images/favicon.ico diff --git a/extensions/BMO/web/images/groups/bugzilla-approvers.png b/extensions/BMO/web/images/groups/bugzilla-approvers.png Binary files differnew file mode 100644 index 000000000..d2414e041 --- /dev/null +++ b/extensions/BMO/web/images/groups/bugzilla-approvers.png diff --git a/extensions/BMO/web/images/groups/calendar-drivers.png b/extensions/BMO/web/images/groups/calendar-drivers.png Binary files differnew file mode 100644 index 000000000..fc2c1d1e5 --- /dev/null +++ b/extensions/BMO/web/images/groups/calendar-drivers.png diff --git a/extensions/BMO/web/images/guided.png b/extensions/BMO/web/images/guided.png Binary files differnew file mode 100644 index 000000000..46ba060f8 --- /dev/null +++ b/extensions/BMO/web/images/guided.png diff --git a/extensions/BMO/web/images/mozchomp.gif b/extensions/BMO/web/images/mozchomp.gif Binary files differnew file mode 100644 index 000000000..ac6549527 --- /dev/null +++ b/extensions/BMO/web/images/mozchomp.gif diff --git a/extensions/BMO/web/images/presshat.png b/extensions/BMO/web/images/presshat.png Binary files differnew file mode 100644 index 000000000..a61de59e5 --- /dev/null +++ b/extensions/BMO/web/images/presshat.png diff --git a/extensions/BMO/web/images/stop-sign.gif b/extensions/BMO/web/images/stop-sign.gif Binary files differnew file mode 100644 index 000000000..9b420ec6c --- /dev/null +++ b/extensions/BMO/web/images/stop-sign.gif diff --git a/extensions/BMO/web/js/edit_bug.js b/extensions/BMO/web/js/edit_bug.js new file mode 100644 index 000000000..e630eb995 --- /dev/null +++ b/extensions/BMO/web/js/edit_bug.js @@ -0,0 +1,91 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * 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 BMO Bugzilla Extension; + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Byron Jones <glob@mozilla.com> + * + * ***** END LICENSE BLOCK ***** + */ + +// --- custom flags +var Dom = YAHOO.util.Dom; + +function bmo_hide_tracking_flags() { + for (var field in bmo_custom_flags) { + var el = Dom.get(field); + var value = el ? el.value : bmo_custom_flags[field]; + if (el && (value != bmo_custom_flags[field])) { + bmo_show_tracking_flags(); + return; + } + if (value == '---') { + Dom.addClass('row_' + field, 'bz_hidden'); + } else { + Dom.addClass(field, 'bz_hidden'); + Dom.removeClass('ro_' + field, 'bz_hidden'); + } + } +} + +function bmo_show_tracking_flags() { + Dom.addClass('edit_tracking_fields_action', 'bz_hidden'); + for (var field in bmo_custom_flags) { + if (Dom.get(field).value == '---') { + Dom.removeClass('row_' + field, 'bz_hidden'); + } else { + Dom.removeClass(field, 'bz_hidden'); + Dom.addClass('ro_' + field, 'bz_hidden'); + } + } +} + +function init_clone_bug_menu(el, bug_id, product, component) { + var diff_url = 'enter_bug.cgi?cloned_bug_id=' + bug_id; + var cur_url = diff_url + + '&product=' + encodeURIComponent(product) + + '&component=' + encodeURIComponent(component); + var menu = new YAHOO.widget.Menu('clone_bug_menu', { position : 'dynamic' }); + menu.addItems([ + { text: 'Clone to the current product', url: cur_url }, + { text: 'Clone to a different product', url: diff_url } + ]); + menu.render(document.body); + YAHOO.util.Event.addListener(el, 'click', show_clone_bug_menu, menu); +} + +function show_clone_bug_menu(event, menu) { + menu.cfg.setProperty('xy', YAHOO.util.Event.getXY(event)); + menu.show(); + event.preventDefault(); +} + +// -- make attachment table, comments, new comment textarea equal widths + +YAHOO.util.Event.onDOMReady(function() { + var comment_tables = Dom.getElementsByClassName('bz_comment_table', 'table', 'comments'); + if (comment_tables.length) { + var comment_width = comment_tables[0].getElementsByTagName('td')[0].clientWidth + 'px'; + var attachment_table = Dom.get('attachment_table'); + if (attachment_table) + attachment_table.style.width = comment_width; + var new_comment = Dom.get('comment'); + if (new_comment) + new_comment.style.width = comment_width; + } +}); diff --git a/extensions/BMO/web/js/edituser_menu.js b/extensions/BMO/web/js/edituser_menu.js new file mode 100644 index 000000000..f9f20d959 --- /dev/null +++ b/extensions/BMO/web/js/edituser_menu.js @@ -0,0 +1,30 @@ +var admin_usermenu; + +YAHOO.util.Event.onDOMReady(function() { + admin_usermenu = new YAHOO.widget.Menu('admin_usermenu', { position : 'dynamic' }); + admin_usermenu.addItems([ + { text: 'Activity', url: '#', target: '_blank' }, + { text: 'Mail', url: '#', target: '_blank' }, + { text: 'Edit', url: '#', target: '_blank' } + ]); + admin_usermenu.render(document.body); +}); + +function show_admin_usermenu(event, id, email, show_edit) { + if (!admin_usermenu) + return; + admin_usermenu.getItem(0).cfg.setProperty('url', + 'page.cgi?id=user_activity.html&action=run' + + '&from=' + YAHOO.util.Date.format(new Date(new Date() - (1000 * 60 * 60 * 24 * 14)), {format: '%Y-%m-%d'}) + + '&to=' + YAHOO.util.Date.format(new Date(), {format: '%Y-%m-%d'}) + + '&who=' + encodeURIComponent(email)); + admin_usermenu.getItem(1).cfg.setProperty('url', 'mailto:' + encodeURIComponent(email)); + if (show_edit) { + admin_usermenu.getItem(2).cfg.setProperty('url', 'editusers.cgi?action=edit&userid=' + id); + } else { + admin_usermenu.removeItem(2); + } + admin_usermenu.cfg.setProperty('xy', YAHOO.util.Event.getXY(event)); + admin_usermenu.show(); +} + diff --git a/extensions/BMO/web/js/form_validate.js b/extensions/BMO/web/js/form_validate.js new file mode 100644 index 000000000..6c8fa6f07 --- /dev/null +++ b/extensions/BMO/web/js/form_validate.js @@ -0,0 +1,21 @@ +/** + * Some Form Validation and Interaction + **/ +//Makes sure that there is an '@' in the address with a '.' +//somewhere after it (and at least one character in between them + +function isValidEmail(email) { + var at_index = email.indexOf("@"); + var last_dot = email.lastIndexOf("."); + return at_index > 0 && last_dot > (at_index + 1); +} + +//Takes a DOM element id and makes sure that it is filled out +function isFilledOut(elem_id) { + var str = document.getElementById(elem_id).value; + return str.length>0 && str!="noneselected"; +} + +function isChecked(elem_id) { + return document.getElementById(elem_id).checked; +} diff --git a/extensions/BMO/web/js/release_tracking_report.js b/extensions/BMO/web/js/release_tracking_report.js new file mode 100644 index 000000000..840b57df1 --- /dev/null +++ b/extensions/BMO/web/js/release_tracking_report.js @@ -0,0 +1,203 @@ +/* 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. */ + +var Dom = YAHOO.util.Dom; +var flagEl; +var productEl; +var trackingEl; +var selectedFields; + +// events + +function onFieldToggle(cbEl, id) { + if (cbEl.checked) { + Dom.removeClass('field_' + id + '_td', 'disabled'); + selectedFields['field_' + id] = id; + } else { + Dom.addClass('field_' + id + '_td', 'disabled'); + selectedFields['field_' + id] = false; + } + Dom.get('field_' + id + '_select').disabled = !cbEl.checked; + serialiseForm(); +} + +function onProductChange() { + var product = productEl.value; + var productData = product == '0' ? getFlagByName(flagEl.value) : getProductById(product); + var html = ''; + selectedFields = new Array(); + + if (productData) { + // update status fields + html = '<table>'; + for(var i = 0, l = productData.fields.length; i < l; i++) { + var field = getFieldById(productData.fields[i]); + selectedFields['field_' + field.id] = false; + html += '<tr>' + + '<td>' + + '<input type="checkbox" id="field_' + field.id + '_cb" ' + + 'onClick="onFieldToggle(this,' + field.id + ')">' + + '</td>' + + '<td class="disabled" id="field_' + field.id + '_td">' + + '<label for="field_' + field.id + '_cb">' + + YAHOO.lang.escapeHTML(field.name) + ':</label>' + + '</td>' + + '<td>' + + '<select disabled id="field_' + field.id + '_select">' + + '<option value="+">fixed</option>' + + '<option value="-">not fixed</option>' + + '</select>' + + '</td>' + + '</tr>'; + } + html += '</table>'; + } + trackingEl.innerHTML = html; + serialiseForm(); +} + +function onFlagChange() { + var flag = flagEl.value; + var flagData = getFlagByName(flag); + productEl.options.length = 0; + + if (flagData) { + // update product select + var currentProduct = productEl.value; + productEl.options[0] = new Option('(Any Product)', '0'); + for(var i = 0, l = flagData.products.length; i < l; i++) { + var product = getProductById(flagData.products[i]); + var n = productEl.length; + productEl.options[n] = new Option(product.name, product.id); + productEl.options[n].selected = product.id == currentProduct; + } + } + onProductChange(); +} + +// form + +function selectAllFields() { + for(var i = 0, l = fields_data.length; i < l; i++) { + var cb = Dom.get('field_' + fields_data[i].id + '_cb'); + cb.checked = true; + onFieldToggle(cb, fields_data[i].id); + } + serialiseForm(); +} + +function selectNoFields() { + for(var i = 0, l = fields_data.length; i < l; i++) { + var cb = Dom.get('field_' + fields_data[i].id + '_cb'); + cb.checked = false; + onFieldToggle(cb, fields_data[i].id); + } + serialiseForm(); +} + +function invertFields() { + for(var i = 0, l = fields_data.length; i < l; i++) { + var el = Dom.get('field_' + fields_data[i].id + '_select'); + if (el.value == '+') { + el.options[1].selected = true; + } else { + el.options[0].selected = true; + } + } + serialiseForm(); +} + +function onFormSubmit() { + serialiseForm(); + return true; +} + +function onFormReset() { + deserialiseForm(''); +} + +function serialiseForm() { + var q = flagEl.value + ':' + + Dom.get('flag_value').value + ':' + + Dom.get('range').value + ':' + + productEl.value + ':' + + Dom.get('op').value + ':'; + + for(var id in selectedFields) { + if (selectedFields[id]) { + q += selectedFields[id] + Dom.get(id + '_select').value + ':'; + } + } + + Dom.get('q').value = q; + Dom.get('bookmark').href = 'page.cgi?id=release_tracking_report.html&q=' + + encodeURIComponent(q); +} + +function deserialiseForm(q) { + var parts = q.split(/:/); + selectValue(flagEl, parts[0]); + onFlagChange(); + selectValue(Dom.get('flag_value'), parts[1]); + selectValue(Dom.get('range'), parts[2]); + selectValue(productEl, parts[3]); + onProductChange(); + selectValue(Dom.get('op'), parts[4]); + for(var i = 5, l = parts.length; i < l; i++) { + var part = parts[i]; + if (part.length) { + var value = part.substr(part.length - 1, 1); + var id = part.substr(0, part.length - 1); + var cb = Dom.get('field_' + id + '_cb'); + cb.checked = true; + onFieldToggle(cb, id); + selectValue(Dom.get('field_' + id + '_select'), value); + } + } + serialiseForm(); +} + +// utils + +YAHOO.util.Event.onDOMReady(function() { + flagEl = Dom.get('flag'); + productEl = Dom.get('product'); + trackingEl = Dom.get('tracking_span'); + onFlagChange(); + deserialiseForm(default_query); +}); + +function getFlagByName(name) { + for(var i = 0, l = flags_data.length; i < l; i++) { + if (flags_data[i].name == name) + return flags_data[i]; + } +} + +function getProductById(id) { + for(var i = 0, l = products_data.length; i < l; i++) { + if (products_data[i].id == id) + return products_data[i]; + } +} + +function getFieldById(id) { + for(var i = 0, l = fields_data.length; i < l; i++) { + if (fields_data[i].id == id) + return fields_data[i]; + } +} + +function selectValue(el, value) { + for(var i = 0, l = el.options.length; i < l; i++) { + if (el.options[i].value == value) { + el.options[i].selected = true; + return; + } + } + el.options[0].selected = true; +} diff --git a/extensions/BMO/web/js/sorttable.js b/extensions/BMO/web/js/sorttable.js new file mode 100644 index 000000000..33b35de88 --- /dev/null +++ b/extensions/BMO/web/js/sorttable.js @@ -0,0 +1,709 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add <script src="sorttable.js"></script> to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + /* + * Prepares the table so that it can be sorted + * + */ + makeSortable: function(table) { + + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + //if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backwards compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i<table.rows.length; i++) { + if (table.rows[i].className.search(/\bsortbottom\b/) != -1) { + sortbottomrows[sortbottomrows.length] = table.rows[i]; + } + } + + if (sortbottomrows) { + if (table.tFoot == null) { + // table doesn't have a tfoot. Create one. + tfo = document.createElement('tfoot'); + table.appendChild(tfo); + } + for (var i=0; i<sortbottomrows.length; i++) { + tfo.appendChild(sortbottomrows[i]); + } + delete sortbottomrows; + } + + sorttable._walk_through_headers(table); + }, + + /* + * Helper function for preparing the table + * + */ + _walk_through_headers: function(table) { + // First, gather some information we need to sort the table. + var bodies = []; + var table_rows = []; + var body_size = table.tBodies[0].rows.length; + + // We need to get all the rows + for (var i=0; i<table.tBodies.length; i++) { + if (!table.tBodies[i].className.match(/\bsorttable_body\b/)) + continue; + + bodies[bodies.length] = table.tBodies[i]; + for (j=0; j<table.tBodies[i].rows.length; j++) { + table_rows[table_rows.length] = table.tBodies[i].rows[j]; + } + } + + table.sorttable_rows = table_rows; + table.sorttable_body_size = body_size; + table.sorttable_bodies = bodies; + + + // work through each column and calculate its type + + // For each row in the header.. + for (var row_index=0; row_index < table.tHead.rows.length; row_index++) { + + headrow = table.tHead.rows[row_index].cells; + // ... Walk through each column and calculate the type. + for (var i=0; i<headrow.length; i++) { + // Don't sort this column, please + if (headrow[i].className.match(/\bsorttable_nosort\b/)) continue; + + // Override sort column index. + column_index = i; + mtch = headrow[i].className.match(/\bsortable_column_([a-z0-9]+)\b/); + if (mtch) column_index = mtch[1]; + + + // Manually override the type with a sorttable_type attribute + // Override sort function + mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/); + if (mtch) override = mtch[1]; + + if (mtch && typeof sorttable["sort_"+override] == 'function') { + headrow[i].sorttable_sortfunction = sorttable["sort_"+override]; + } else { + headrow[i].sorttable_sortfunction = sorttable.guessType(table, column_index); + } + + // make it clickable to sort + headrow[i].sorttable_columnindex = column_index; + headrow[i].table = table; + + // If the header contains a link, clear the href. + for (var k=0; k<headrow[i].childNodes.length; k++) { + if (headrow[i].childNodes[k].tagName == 'A') { + headrow[i].childNodes[k].href = "javascript:void(0);"; + } + } + + dean_addEvent(headrow[i], "click", sorttable._on_column_header_clicked); + + } // inner for (var i=0; i<headrow.length; i++) + } // outer for + }, + + + + + /* + * Helper function for the _on_column_header_clicked handler + * + */ + + _remove_sorted_classes: function(header) { + // For each row in the header.. + for (var j=0; j< header.rows.length; j++) { + // ... Walk through each column and calculate the type. + row = header.rows[j].cells; + + for (var i=0; i<row.length; i++) { + cell = row[i]; + if (cell.nodeType != 1) return; // an element + + mtch = cell.className.match(/\bsorted_([0-9]+)\b/); + if (mtch) { + cell.className = cell.className.replace('sorted_'+mtch[1], + 'sorted_'+(parseInt(mtch[1])+1)); + } + + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + } + }, + + _check_already_sorted: function(cell) { + if (cell.className.search(/\bsorttable_sorted\b/) != -1) { + // if we're already sorted by this column, just + // reverse the table, which is quicker + sorttable.reverse_table(cell); + + sorttable._mark_column_as_sorted(cell, '▲', 1); + return 1; + } + + if (cell.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse_table(cell); + + sorttable._mark_column_as_sorted(cell, '▼', 0); + + return 1; + } + + return 0; + }, + + /* Visualy mark the cell as sorted. + * + * @param cell: the cell being marked + * @param text: the text being used to mark. you can use html + * @param reversed: whether the column is reversed or not. + * + */ + _mark_column_as_sorted: function(cell, text, reversed) { + // remove eventual class + cell.className = cell.className.replace('sorttable_sorted', ''); + cell.className = cell.className.replace('sorttable_sorted_reverse', ''); + + // the column is reversed + if (reversed) { + cell.className += ' sorttable_sorted_reverse'; + } + else { + // remove eventual class + cell.className += ' sorttable_sorted'; + } + + sorttable._remove_sorting_marker(); + + marker = document.createElement('span'); + marker.id = "sorttable_sort_mark"; + marker.className = "bz_sort_order_primary"; + marker.innerHTML = text; + cell.appendChild(marker); + }, + + _remove_sorting_marker: function() { + mark = document.getElementById('sorttable_sort_mark'); + if (mark) { mark.parentNode.removeChild(mark); } + els = sorttable._getElementsByClassName('bz_sort_order_primary'); + for(var i=0,j=els.length; i<j; i++) { + els[i].parentNode.removeChild(els[i]); + } + els = sorttable._getElementsByClassName('bz_sort_order_secondary'); + for(var i=0,j=els.length; i<j; i++) { + els[i].parentNode.removeChild(els[i]); + } + }, + + _getElementsByClassName: function(classname, node) { + if(!node) node = document.getElementsByTagName("body")[0]; + var a = []; + var re = new RegExp('\\b' + classname + '\\b'); + var els = node.getElementsByTagName("*"); + for(var i=0,j=els.length; i<j; i++) + if(re.test(els[i].className))a.push(els[i]); + return a; + }, + + /* + * This is the callback for when the table header is clicked. + * + * @param evt: the event that triggered this callback + */ + _on_column_header_clicked: function(evt) { + + // The table is already sorted by this column. Just reverse it. + if (sorttable._check_already_sorted(this)) + return; + + + // First, remove sorttable_sorted classes from the other header + // that is currently sorted and its marker (the simbol indicating + // that its sorted. + sorttable._remove_sorted_classes(this.table.tHead); + mtch = this.className.match(/\bsorted_([0-9]+)\b/); + if (mtch) { + this.className = this.className.replace('sorted_'+mtch[1], ''); + } + this.className += ' sorted_0 '; + + // This is the text that indicates that the column is sorted. + sorttable._mark_column_as_sorted(this, '▼', 0); + + sorttable.sort_table(this); + + }, + + sort_table: function(cell) { + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + col = cell.sorttable_columnindex; + rows = cell.table.sorttable_rows; + + var BUGLIST = ''; + + for (var j = 0; j < cell.table.sorttable_rows.length; j++) { + rows[j].sort_data = sorttable.getInnerText(rows[j].cells[col]); + } + + /* If you want a stable sort, uncomment the following line */ + sorttable.shaker_sort(rows, cell.sorttable_sortfunction); + /* and comment out this one */ + //rows.sort(cell.sorttable_sortfunction); + + // Rebuild the table, using he sorted rows. + tb = cell.table.sorttable_bodies[0]; + body_size = cell.table.sorttable_body_size; + body_index = 0; + + for (var j=0; j<rows.length; j++) { + if (j % 2) + rows[j].className = rows[j].className.replace('bz_row_even', + 'bz_row_odd'); + else + rows[j].className = rows[j].className.replace('bz_row_odd', + 'bz_row_even'); + + tb.appendChild(rows[j]); + var bug_id = sorttable.getInnerText(rows[j].cells[0].childNodes[1]); + BUGLIST = BUGLIST ? BUGLIST+':'+bug_id : bug_id; + + if (j % body_size == body_size-1) { + body_index++; + if (body_index < cell.table.sorttable_bodies.length) { + tb = cell.table.sorttable_bodies[body_index]; + } + } + } + + document.cookie = 'BUGLIST='+BUGLIST; + + cell.table.sorttable_rows = rows; + }, + + reverse_table: function(cell) { + oldrows = cell.table.sorttable_rows; + newrows = []; + + for (var i=0; i < oldrows.length; i++) { + newrows[newrows.length] = oldrows[i]; + } + + tb = cell.table.sorttable_bodies[0]; + body_size = cell.table.sorttable_body_size; + body_index = 0; + + var BUGLIST = ''; + + cell.table.sorttable_rows = []; + for (var i = newrows.length-1; i >= 0; i--) { + if (i % 2) + newrows[i].className = newrows[i].className.replace('bz_row_even', + 'bz_row_odd'); + else + newrows[i].className = newrows[i].className.replace('bz_row_odd', + 'bz_row_even'); + + tb.appendChild(newrows[i]); + cell.table.sorttable_rows.push(newrows[i]); + + var bug_id = sorttable.getInnerText(newrows[i].cells[0].childNodes[1]); + BUGLIST = BUGLIST ? BUGLIST+':'+bug_id : bug_id; + + if ((newrows.length-1-i) % body_size == body_size-1) { + body_index++; + if (body_index < cell.table.sorttable_bodies.length) { + tb = cell.table.sorttable_bodies[body_index]; + } + } + + } + + document.cookie = 'BUGLIST='+BUGLIST; + + delete newrows; + }, + + guessType: function(table, column) { + // guess the type of a column based on its first non-blank row + sortfn = sorttable.sort_alpha; + for (var i=0; i<table.sorttable_bodies[0].rows.length; i++) { + text = sorttable.getInnerText(table.sorttable_bodies[0].rows[i].cells[column]); + if (text != '') { + if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) { + return sorttable.sort_numeric; + } + // check for a date: dd/mm/yyyy or dd/mm/yy + // can have / or . or - as separator + // can be mm/dd as well + possdate = text.match(sorttable.DATE_RE) + if (possdate) { + // looks like a date + first = parseInt(possdate[1]); + second = parseInt(possdate[2]); + if (first > 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for <input> fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (typeof node.getAttribute != 'undefined' && node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a.sort_data and b.sort_data */ + sort_numeric: function(a,b) { + aa = parseFloat(a.sort_data.replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b.sort_data.replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + + sort_alpha: function(a,b) { + if (a.sort_data.toLowerCase()==b.sort_data.toLowerCase()) return 0; + if (a.sort_data.toLowerCase()<b.sort_data.toLowerCase()) return -1; + return 1; + }, + + sort_ddmm: function(a,b) { + mtch = a.sort_data.match(sorttable.DATE_RE); + y = mtch[3]; m = mtch[2]; d = mtch[1]; + if (m.length == 1) m = '0'+m; + if (d.length == 1) d = '0'+d; + dt1 = y+m+d; + mtch = b.sort_data.match(sorttable.DATE_RE); + y = mtch[3]; m = mtch[2]; d = mtch[1]; + if (m.length == 1) m = '0'+m; + if (d.length == 1) d = '0'+d; + dt2 = y+m+d; + if (dt1==dt2) return 0; + if (dt1<dt2) return -1; + return 1; + }, + + sort_mmdd: function(a,b) { + mtch = a.sort_data.match(sorttable.DATE_RE); + y = mtch[3]; d = mtch[2]; m = mtch[1]; + if (m.length == 1) m = '0'+m; + if (d.length == 1) d = '0'+d; + dt1 = y+m+d; + mtch = b.sort_data.match(sorttable.DATE_RE); + y = mtch[3]; d = mtch[2]; m = mtch[1]; + if (m.length == 1) m = '0'+m; + if (d.length == 1) d = '0'+d; + dt2 = y+m+d; + if (dt1==dt2) return 0; + if (dt1<dt2) return -1; + return 1; + }, + + shaker_sort: function(list, comp_func) { + // A stable sort function to allow multi-level sorting of data + // see: http://en.wikipedia.org/wiki/Cocktail_sort + // thanks to Joseph Nahmias + var b = 0; + var t = list.length - 1; + var swap = true; + + while(swap) { + swap = false; + for(var i = b; i < t; ++i) { + if ( comp_func(list[i], list[i+1]) > 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + // IE doesn't have a way to test if the DOM is loaded + // doing a deferred script load with onReadyStateChange checks is + // problematic, so poll the document until it is scrollable + // http://blogs.atlassian.com/developer/2008/03/when_ie_says_dom_is_ready_but.html + var loadTestTimer = function() { + try { + if (document.readyState != "loaded" && document.readyState != "complete") { + document.documentElement.doScroll("left"); + } + sorttable.init(); // call the onload handler + } catch(error) { + setTimeout(loadTestTimer, 100); + } + }; + loadTestTimer(); +/*@end @*/ + +/* for Safari */ +if (/WebKit/i.test(navigator.userAgent)) { // sniff + var _timer = setInterval(function() { + if (/loaded|complete/.test(document.readyState)) { + sorttable.init(); // call the onload handler + } + }, 10); +} + +/* for other browsers */ +window.onload = sorttable.init; + +// written by Dean Edwards, 2005 +// with input from Tino Zijdel, Matthias Miller, Diego Perini + +// http://dean.edwards.name/weblog/2005/10/add-event/ + +function dean_addEvent(element, type, handler) { + if (element.addEventListener) { + element.addEventListener(type, handler, false); + } else { + // assign each event handler a unique ID + if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++; + // create a hash table of event types for the element + if (!element.events) element.events = {}; + // create a hash table of event handlers for each element/event pair + var handlers = element.events[type]; + if (!handlers) { + handlers = element.events[type] = {}; + // store the existing event handler (if there is one) + if (element["on" + type]) { + handlers[0] = element["on" + type]; + } + } + // store the event handler in the hash table + handlers[handler.$$guid] = handler; + // assign a global event handler to do all the work + element["on" + type] = handleEvent; + } +}; +// a counter used to create unique IDs +dean_addEvent.guid = 1; + +function removeEvent(element, type, handler) { + if (element.removeEventListener) { + element.removeEventListener(type, handler, false); + } else { + // delete the event handler from the hash table + if (element.events && element.events[type]) { + delete element.events[type][handler.$$guid]; + } + } +}; + +function handleEvent(event) { + var returnValue = true; + // grab the event object (IE uses a global event object) + event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); + // get a reference to the hash table of event handlers + var handlers = this.events[event.type]; + // execute each event handler + for (var i in handlers) { + this.$$handleEvent = handlers[i]; + if (this.$$handleEvent(event) === false) { + returnValue = false; + } + } + return returnValue; +}; + +function fixEvent(event) { + // add W3C standard event methods + event.preventDefault = fixEvent.preventDefault; + event.stopPropagation = fixEvent.stopPropagation; + return event; +}; +fixEvent.preventDefault = function() { + this.returnValue = false; +}; +fixEvent.stopPropagation = function() { + this.cancelBubble = true; +} + +// Dean's forEach: http://dean.edwards.name/base/forEach.js +/* + forEach, version 1.0 + Copyright 2006, Dean Edwards + License: http://www.opensource.org/licenses/mit-license.php +*/ + +// array-like enumeration +if (!Array.forEach) { // mozilla already supports this + Array.forEach = function(array, block, context) { + for (var i = 0; i < array.length; i++) { + block.call(context, array[i], i, array); + } + }; +} + +// generic enumeration +Function.prototype.forEach = function(object, block, context) { + for (var key in object) { + if (typeof this.prototype[key] == "undefined") { + block.call(context, object[key], key, object); + } + } +}; + +// character enumeration +String.forEach = function(string, block, context) { + Array.forEach(string.split(""), function(chr, index) { + block.call(context, chr, index, string); + }); +}; + +// globally resolve forEach enumeration +var forEach = function(object, block, context) { + if (object) { + var resolve = Object; // default + if (object instanceof Function) { + // functions have a "length" property + resolve = Function; + } else if (object.forEach instanceof Function) { + // the object implements a custom forEach method so use that + object.forEach(block, context); + return; + } else if (typeof object == "string") { + // the object is a string + resolve = String; + } else if (typeof object.length == "number") { + // the object is array-like + resolve = Array; + } + resolve.forEach(object, block, context); + } +}; + diff --git a/extensions/BMO/web/js/swag.js b/extensions/BMO/web/js/swag.js new file mode 100644 index 000000000..cd9561b54 --- /dev/null +++ b/extensions/BMO/web/js/swag.js @@ -0,0 +1,60 @@ +/** + * Swag Request Form Functions + * Form Interal Swag Request Form + * dtran + * 7/6/09 + **/ + + +function evalToNumber(numberString) { + if(numberString=='') return 0; + return parseInt(numberString); +} + +function evalToNumberString(numberString) { + if(numberString=='') return '0'; + return numberString; +} +//item_array should be an array of DOM element ids +function getTotal(item_array) { + var total = 0; + for(var i in item_array) { + total += evalToNumber(document.getElementById(item_array[i]).value); + } + return total; +} + +function calculateTotalSwag() { + document.getElementById('Totalswag').value = + getTotal( new Array('Lanyards', + 'Stickers', + 'Bracelets', + 'Tattoos', + 'Buttons', + 'Posters')); + +} + + +function calculateTotalMensShirts() { + document.getElementById('mens_total').value = + getTotal( new Array('mens_s', + 'mens_m', + 'mens_l', + 'mens_xl', + 'mens_xxl', + 'mens_xxxl')); + +} + + +function calculateTotalWomensShirts() { + document.getElementById('womens_total').value = + getTotal( new Array('womens_s', + 'womens_m', + 'womens_l', + 'womens_xl', + 'womens_xxl', + 'womens_xxxl')); + +} diff --git a/extensions/BMO/web/js/triage_reports.js b/extensions/BMO/web/js/triage_reports.js new file mode 100644 index 000000000..855b577d7 --- /dev/null +++ b/extensions/BMO/web/js/triage_reports.js @@ -0,0 +1,83 @@ +var Dom = YAHOO.util.Dom; + +function onSelectProduct() { + var component = Dom.get('component'); + if (Dom.get('product').value == '') { + bz_clearOptions(component); + return; + } + selectProduct(Dom.get('product'), component); + // selectProduct only supports __Any__ on both elements + // we only want it on component, so add it back in + try { + component.add(new Option('__Any__', ''), component.options[0]); + } catch(e) { + // support IE + component.add(new Option('__Any__', ''), 0); + } + component.value = ''; +} + +function onCommenterChange() { + var commenter_is = Dom.get('commenter_is'); + if (Dom.get('commenter').value == 'is') { + Dom.removeClass(commenter_is, 'hidden'); + } else { + Dom.addClass(commenter_is, 'hidden'); + } +} + +function onLastChange() { + var last_is_span = Dom.get('last_is_span'); + if (Dom.get('last').value == 'is') { + Dom.removeClass(last_is_span, 'hidden'); + } else { + Dom.addClass(last_is_span, 'hidden'); + } +} + +function onGenerateReport() { + if (Dom.get('product').value == '') { + alert('You must select a product.'); + return false; + } + if (Dom.get('component').value == '' && !Dom.get('component').options[0].selected) { + alert('You must select at least one component.'); + return false; + } + if (!(Dom.get('filter_commenter').checked || Dom.get('filter_last').checked)) { + alert('You must select at least one comment filter.'); + return false; + } + if (Dom.get('filter_commenter').checked + && Dom.get('commenter').value == 'is' + && Dom.get('commenter_is').value == '') + { + alert('You must specify the last commenter\'s email address.'); + return false; + } + if (Dom.get('filter_last').checked + && Dom.get('last').value == 'is' + && Dom.get('last_is').value == '') + { + alert('You must specify the "comment is older than" date.'); + return false; + } + return true; +} + +YAHOO.util.Event.onDOMReady(function() { + onSelectProduct(); + onCommenterChange(); + onLastChange(); + + var component = Dom.get('component'); + if (selected_components.length == 0) + return; + component.options[0].selected = false; + for (var i = 0, n = selected_components.length; i < n; i++) { + var index = bz_optionIndex(component, selected_components[i]); + if (index != -1) + component.options[index].selected = true; + } +}); diff --git a/extensions/BMO/web/js/webtrends.js b/extensions/BMO/web/js/webtrends.js new file mode 100644 index 000000000..fd0aca29e --- /dev/null +++ b/extensions/BMO/web/js/webtrends.js @@ -0,0 +1,213 @@ +function WebTrends(options){var that=this;this.dcsid="dcsis0ifv10000gg3ag82u4rf_7b1e";this.rate=100;this.fpcdom=".mozilla.org";this.trackevents=false;if(typeof(options)!="undefined") +{if(typeof(options.dcsid)!="undefined")this.dcsid=options.dcsid;if(typeof(options.rate)!="undefined")this.rate=options.rate;if(typeof(options.fpcdom)!="undefined")this.fpcdom=options.fpcdom;if(typeof(this.fpcdom)!="undefined"&&this.fpcdom.substring(0,1)!='.')this.fpcdom='.'+this.fpcdom;if(typeof(options.trackevents)!="undefined")this.trackevents=options.trackevents;} +this.domain="statse.webtrendslive.com";this.timezone=0;this.onsitedoms="";this.downloadtypes="xls,doc,pdf,txt,csv,zip,dmg,exe";this.navigationtag="div,table";this.enabled=true;this.i18n=false;this.fpc="WT_FPC";this.paidsearchparams="gclid";this.splitvalue="";this.preserve=true;this.DCSdir={};this.DCS={};this.WT={};this.DCSext={};this.images=[];this.index=0;this.exre=(function() +{return(window.RegExp?new RegExp("dcs(uri)|(ref)|(aut)|(met)|(sta)|(sip)|(pro)|(byt)|(dat)|(p3p)|(cfg)|(redirect)|(cip)","i"):"");})();this.re=(function() +{return(window.RegExp?(that.i18n?{"%25":/\%/g,"%26":/\&/g}:{"%09":/\t/g,"%20":/ /g,"%23":/\#/g,"%26":/\&/g,"%2B":/\+/g,"%3F":/\?/g,"%5C":/\\/g,"%22":/\"/g,"%7F":/\x7F/g,"%A0":/\xA0/g}):"");})();} +WebTrends.prototype.dcsGetId=function(){if(this.enabled&&(document.cookie.indexOf(this.fpc+"=")==-1)&&(document.cookie.indexOf("WTLOPTOUT=")==-1)){document.write("<scr"+"ipt type='text/javascript' src='"+"http"+(window.location.protocol.indexOf('https:')==0?'s':'')+"://"+this.domain+"/"+this.dcsid+"/wtid.js"+"'><\/scr"+"ipt>");}} +WebTrends.prototype.dcsGetCookie=function(name) +{var cookies=document.cookie.split("; ");var cmatch=[];var idx=0;var i=0;var namelen=name.length;var clen=cookies.length;for(i=0;i<clen;i++) +{var c=cookies[i];if((c.substring(0,namelen+1))==(name+"=")){cmatch[idx++]=c;}} +var cmatchCount=cmatch.length;if(cmatchCount>0) +{idx=0;if((cmatchCount>1)&&(name==this.fpc)) +{var dLatest=new Date(0);for(i=0;i<cmatchCount;i++) +{var lv=parseInt(this.dcsGetCrumb(cmatch[i],"lv"));var dLst=new Date(lv);if(dLst>dLatest) +{dLatest.setTime(dLst.getTime());idx=i;}}} +return unescape(cmatch[idx].substring(namelen+1));} +else +{return null;}} +WebTrends.prototype.dcsGetCrumb=function(cval,crumb,sep){var aCookie=cval.split(sep||":");for(var i=0;i<aCookie.length;i++){var aCrumb=aCookie[i].split("=");if(crumb==aCrumb[0]){return aCrumb[1];}} +return null;} +WebTrends.prototype.dcsGetIdCrumb=function(cval,crumb){var id=cval.substring(0,cval.indexOf(":lv="));var aCrumb=id.split("=");for(var i=0;i<aCrumb.length;i++){if(crumb==aCrumb[0]){return aCrumb[1];}} +return null;} +WebTrends.prototype.dcsIsFpcSet=function(name,id,lv,ss){var c=this.dcsGetCookie(name);if(c){return((id==this.dcsGetIdCrumb(c,"id"))&&(lv==this.dcsGetCrumb(c,"lv"))&&(ss==this.dcsGetCrumb(c,"ss")))?0:3;} +return 2;} +WebTrends.prototype.dcsFPC=function(){if(document.cookie.indexOf("WTLOPTOUT=")!=-1){return;} +var WT=this.WT;var name=this.fpc;var dCur=new Date();var adj=(dCur.getTimezoneOffset()*60000)+(this.timezone*3600000);dCur.setTime(dCur.getTime()+adj);var dExp=new Date(dCur.getTime()+315360000000);var dSes=new Date(dCur.getTime());WT.co_f=WT.vtid=WT.vtvs=WT.vt_f=WT.vt_f_a=WT.vt_f_s=WT.vt_f_d=WT.vt_f_tlh=WT.vt_f_tlv="";if(document.cookie.indexOf(name+"=")==-1){if((typeof(gWtId)!="undefined")&&(gWtId!="")){WT.co_f=gWtId;} +else if((typeof(gTempWtId)!="undefined")&&(gTempWtId!="")){WT.co_f=gTempWtId;WT.vt_f="1";} +else{WT.co_f="2";var curt=dCur.getTime().toString();for(var i=2;i<=(32-curt.length);i++){WT.co_f+=Math.floor(Math.random()*16.0).toString(16);} +WT.co_f+=curt;WT.vt_f="1";} +if(typeof(gWtAccountRollup)=="undefined"){WT.vt_f_a="1";} +WT.vt_f_s=WT.vt_f_d="1";WT.vt_f_tlh=WT.vt_f_tlv="0";} +else{var c=this.dcsGetCookie(name);var id=this.dcsGetIdCrumb(c,"id");var lv=parseInt(this.dcsGetCrumb(c,"lv"));var ss=parseInt(this.dcsGetCrumb(c,"ss"));if((id==null)||(id=="null")||isNaN(lv)||isNaN(ss)){return;} +WT.co_f=id;var dLst=new Date(lv);WT.vt_f_tlh=Math.floor((dLst.getTime()-adj)/1000);dSes.setTime(ss);if((dCur.getTime()>(dLst.getTime()+1800000))||(dCur.getTime()>(dSes.getTime()+28800000))){WT.vt_f_tlv=Math.floor((dSes.getTime()-adj)/1000);dSes.setTime(dCur.getTime());WT.vt_f_s="1";} +if((dCur.getDay()!=dLst.getDay())||(dCur.getMonth()!=dLst.getMonth())||(dCur.getYear()!=dLst.getYear())){WT.vt_f_d="1";}} +WT.co_f=escape(WT.co_f);WT.vtid=(typeof(this.vtid)=="undefined")?WT.co_f:(this.vtid||"");WT.vtvs=(dSes.getTime()-adj).toString();var expiry="; expires="+dExp.toGMTString();var cur=dCur.getTime().toString();var ses=dSes.getTime().toString();document.cookie=name+"="+"id="+WT.co_f+":lv="+cur+":ss="+ses+expiry+"; path=/"+(((this.fpcdom!=""))?("; domain="+this.fpcdom):(""));var rc=this.dcsIsFpcSet(name,WT.co_f,cur,ses);if(rc!=0){WT.co_f=WT.vtvs=WT.vt_f_s=WT.vt_f_d=WT.vt_f_tlh=WT.vt_f_tlv="";if(typeof(this.vtid)=="undefined"){WT.vtid="";} +WT.vt_f=WT.vt_f_a=rc;}} +WebTrends.prototype.dcsIsOnsite=function(host){if(host.length>0){host=host.toLowerCase();if(host==window.location.hostname.toLowerCase()){return true;} +if(typeof(this.onsitedoms.test)=="function"){return this.onsitedoms.test(host);} +else if(this.onsitedoms.length>0){var doms=this.dcsSplit(this.onsitedoms);var len=doms.length;for(var i=0;i<len;i++){if(host==doms[i]){return true;}}}} +return false;} +WebTrends.prototype.dcsTypeMatch=function(pth,typelist){var type=pth.toLowerCase().substring(pth.lastIndexOf(".")+1,pth.length);var types=this.dcsSplit(typelist);var tlen=types.length;for(var i=0;i<tlen;i++){if(type==types[i]){return true;}} +return false;} +WebTrends.prototype.dcsEvt=function(evt,tag){var e=evt.target||evt.srcElement;while(e.tagName&&(e.tagName.toLowerCase()!=tag.toLowerCase())){e=e.parentElement||e.parentNode;} +return e;} +WebTrends.prototype.dcsNavigation=function(evt){var id="";var cname="";var elems=this.dcsSplit(this.navigationtag);var elen=elems.length;var i,e,elem;for(i=0;i<elen;i++) +{elem=elems[i];if(elem.length) +{e=this.dcsEvt(evt,elem);id=(e.getAttribute&&e.getAttribute("id"))?e.getAttribute("id"):"";cname=e.className||"";if(id.length||cname.length){break;}}} +return id.length?id:cname;} +WebTrends.prototype.dcsBind=function(event,func){if((typeof(func)=="function")&&document.body){if(document.body.addEventListener){document.body.addEventListener(event,func.wtbind(this),true);} +else if(document.body.attachEvent){document.body.attachEvent("on"+event,func.wtbind(this));}}} +WebTrends.prototype.dcsET=function(){var e=(navigator.appVersion.indexOf("MSIE")!=-1)?"click":"mousedown";this.dcsBind(e,this.dcsDownload);this.dcsBind("contextmenu",this.dcsRightClick);this.dcsBind(e,this.dcsLinkTrack);} +WebTrends.prototype.dcsMultiTrack=function(){var args=dcsMultiTrack.arguments?dcsMultiTrack.arguments:arguments;if(args.length%2==0){this.dcsSaveProps(args);this.dcsSetProps(args);var dCurrent=new Date();this.DCS.dcsdat=dCurrent.getTime();this.dcsFPC();this.dcsTag();this.dcsRestoreProps();}} +WebTrends.prototype.dcsLinkTrack=function(evt) +{evt=evt||(window.event||"");if(evt&&((typeof(evt.which)!="number")||(evt.which==1))) +{var e=this.dcsEvt(evt,"A");var f=this.dcsEvt(evt,"IMG");if(e.href&&e.protocol&&e.protocol.indexOf("http")!=-1&&!this.dcsLinkTrackException(e)) +{if((navigator.appVersion.indexOf("MSIE")==-1)&&((e.onclick)||(e.onmousedown))) +{this.dcsSetVarCap(e);} +var hn=e.hostname?(e.hostname.split(":")[0]):"";var qry=e.search?e.search.substring(e.search.indexOf("?")+1,e.search.length):"";var pth=e.pathname?((e.pathname.indexOf("/")!=0)?"/"+e.pathname:e.pathname):"/";var ti='';if(f.alt) +{ti=f.alt;} +else +{if(document.all) +{ti=e.title||e.innerText||e.innerHTML||"";} +else +{ti=e.title||e.text||e.innerHTML||"";}} +hn=this.DCS.setvar_dcssip||hn;pth=this.DCS.setvar_dcsuri||pth;qry=this.DCS.setvar_dcsqry||qry;ti=this.WT.setvar_ti||ti;ti=this.dcsTrim(ti);this.WT.mc_id=this.WT.setvar_mc_id||"";this.WT.sp=this.WT.ad=this.DCS.setvar_dcsuri=this.DCS.setvar_dcssip=this.DCS.setvar_dcsqry=this.WT.setvar_ti=this.WT.setvar_mc_id="";this.dcsMultiTrack("DCS.dcssip",hn,"DCS.dcsuri",pth,"DCS.dcsqry",this.trimoffsiteparams?"":qry,"DCS.dcsref",window.location,"WT.ti","Link:"+ti,"WT.dl","1","WT.nv",this.dcsNavigation(evt),"WT.sp","","WT.ad","","WT.AutoLinkTrack","1");this.DCS.dcssip=this.DCS.dcsuri=this.DCS.dcsqry=this.DCS.dcsref=this.WT.ti=this.WT.dl=this.WT.nv="";}}} +WebTrends.prototype.dcsTrim=function(sString) +{while(sString.substring(0,1)==' ') +{sString=sString.substring(1,sString.length);} +while(sString.substring(sString.length-1,sString.length)==' ') +{sString=sString.substring(0,sString.length-1);} +return sString;} +WebTrends.prototype.dcsSetVarCap=function(e) +{if(e.onclick) +var gCap=e.onclick.toString();else if(e.onmousedown) +var gCap=e.onmousedown.toString();var gStart=gCap.substring(gCap.indexOf("dcsSetVar(")+10,gCap.length)||gCap.substring(gCap.indexOf("_tag.dcsSetVar(")+16,gCap.length);var gEnd=gStart.substring(0,gStart.indexOf(");")).replace(/\s"/gi,"").replace(/"/gi,"");var gSplit=gEnd.split(",");if(gSplit.length!=-1) +{for(var i=0;i<gSplit.length;i+=2) +{if(gSplit[i].indexOf('WT.')==0) +{if(this.dcsSetVarValidate(gSplit[i])) +{this.WT["setvar_"+gSplit[i].substring(3)]=gSplit[i+1];} +else +{this.WT[gSplit[i].substring(3)]=gSplit[i+1];}} +else if(gSplit[i].indexOf('DCS.')==0) +{if(this.dcsSetVarValidate(gSplit[i])) +{this.DCS["setvar_"+gSplit[i].substring(4)]=gSplit[i+1];} +else +{this.DCS[gSplit[i].substring(4)]=gSplit[i+1];}} +else if(gSplit[i].indexOf('DCSext.')==0) +{if(this.dcsSetVarValidate(gSplit[i])) +{this.DCSext["setvar_"+gSplit[i].substring(7)]=gSplit[i+1];} +else +{this.DCSext[gSplit[i].substring(7)]=gSplit[i+1];}} +else if(gSplit[i].indexOf('DCSdir.')==0) +{if(this.dcsSetVarValidate(gSplit[i])) +{this.DCSdir["setvar_"+gSplit[i].substring(7)]=gSplit[i+1];} +else +{this.DCSdir[gSplit[i].substring(7)]=gSplit[i+1];}}}}} +WebTrends.prototype.dcsSetVarValidate=function(validate) +{var wtParamList="DCS.dcssip,DCS.dcsuri,DCS.dcsqry,WT.ti,WT.mc_id".split(",");for(var i=0;i<wtParamList.length;i++) +{if(wtParamList[i]==validate) +{return 1;}} +return 0;} +WebTrends.prototype.dcsSetVar=function() +{var args=dcsSetVar.arguments?dcsSetVar.arguments:arguments;if((args.length%2==0)&&(navigator.appVersion.indexOf("MSIE")!=-1)){for(var i=0;i<args.length;i+=2){if(args[i].indexOf('WT.')==0){if(this.dcsSetVarValidate(args[i])){this.WT["setvar_"+args[i].substring(3)]=args[i+1];} +else{this.WT[args[i].substring(3)]=args[i+1];}} +else if(args[i].indexOf('DCS.')==0){if(this.dcsSetVarValidate(args[i])){this.DCS["setvar_"+args[i].substring(4)]=args[i+1];} +else{this.DCS[args[i].substring(4)]=args[i+1];}} +else if(args[i].indexOf('DCSext.')==0){if(this.dcsSetVarValidate(args[i])){this.DCSext["setvar_"+args[i].substring(7)]=args[i+1];} +else{this.DCSext[args[i].substring(7)]=args[i+1];}} +else if(args[i].indexOf('DCSdir.')==0){if(this.dcsSetVarValidate(args[i])){this.DCSdir["setvar_"+args[i].substring(7)]=args[i+1];} +else{this.DCSdir[args[i].substring(7)]=args[i+1];}}}}} +WebTrends.prototype.dcsLinkTrackException=function(n) +{try +{var b=0;if(this.DCSdir.gTrackExceptions) +{var e=this.DCSdir.gTrackExceptions.split(",");while(b!=1) +{if(n.tagName&&n.tagName=="body") +{b=1;return false} +else +{if(n.className) +{var f=String(n.className).split(" ");for(var c=0;c<e.length;c++)for(var d=0;d<f.length;d++) +{if(f[d]==e[c]) +{b=1;return true}}}} +n=n.parentNode}} +else +{return false;}} +catch(g){}} +WebTrends.prototype.dcsCleanUp=function(){this.DCS={};this.WT={};this.DCSext={};if(arguments.length%2==0){this.dcsSetProps(arguments);}} +WebTrends.prototype.dcsSetProps=function(args){for(var i=0;i<args.length;i+=2){if(args[i].indexOf('WT.')==0){this.WT[args[i].substring(3)]=args[i+1];} +else if(args[i].indexOf('DCS.')==0){this.DCS[args[i].substring(4)]=args[i+1];} +else if(args[i].indexOf('DCSext.')==0){this.DCSext[args[i].substring(7)]=args[i+1];}}} +WebTrends.prototype.dcsSaveProps=function(args){var i,key,param;if(this.preserve){this.args=[];for(i=0;i<args.length;i+=2){param=args[i];if(param.indexOf('WT.')==0){key=param.substring(3);this.args[i]=param;this.args[i+1]=this.WT[key]||"";} +else if(param.indexOf('DCS.')==0){key=param.substring(4);this.args[i]=param;this.args[i+1]=this.DCS[key]||"";} +else if(param.indexOf('DCSext.')==0){key=param.substring(7);this.args[i]=param;this.args[i+1]=this.DCSext[key]||"";}}}} +WebTrends.prototype.dcsRestoreProps=function(){if(this.preserve){this.dcsSetProps(this.args);this.args=[];}} +WebTrends.prototype.dcsSplit=function(list){var items=list.toLowerCase().split(",");var len=items.length;for(var i=0;i<len;i++){items[i]=items[i].replace(/^\s*/,"").replace(/\s*$/,"");} +return items;} +WebTrends.prototype.dcsDownload=function(evt){evt=evt||(window.event||"");if(evt&&((typeof(evt.which)!="number")||(evt.which==1))){var e=this.dcsEvt(evt,"A");if(e.href){var hn=e.hostname?(e.hostname.split(":")[0]):"";if(this.dcsIsOnsite(hn)&&this.dcsTypeMatch(e.pathname,this.downloadtypes)){var qry=e.search?e.search.substring(e.search.indexOf("?")+1,e.search.length):"";var pth=e.pathname?((e.pathname.indexOf("/")!=0)?"/"+e.pathname:e.pathname):"/";var ttl="";var text=document.all?e.innerText:e.text;var img=this.dcsEvt(evt,"IMG");if(img.alt){ttl=img.alt;} +else if(text){ttl=text;} +else if(e.innerHTML){ttl=e.innerHTML;} +this.dcsMultiTrack("DCS.dcssip",hn,"DCS.dcsuri",pth,"DCS.dcsqry",e.search||"","WT.ti","Download:"+ttl,"WT.dl","20","WT.nv",this.dcsNavigation(evt));}}}} +WebTrends.prototype.dcsRightClick=function(evt){evt=evt||(window.event||"");if(evt){var btn=evt.which||evt.button;if((btn!=1)||(navigator.userAgent.indexOf("Safari")!=-1)){var e=this.dcsEvt(evt,"A");if((typeof(e.href)!="undefined")&&e.href){if((typeof(e.protocol)!="undefined")&&e.protocol&&(e.protocol.indexOf("http")!=-1)){if((typeof(e.pathname)!="undefined")&&this.dcsTypeMatch(e.pathname,this.downloadtypes)){var pth=e.pathname?((e.pathname.indexOf("/")!=0)?"/"+e.pathname:e.pathname):"/";var hn=e.hostname?(e.hostname.split(":")[0]):"";this.dcsMultiTrack("DCS.dcssip",hn,"DCS.dcsuri",pth,"DCS.dcsqry","","WT.ti","RightClick:"+pth,"WT.dl","25");}}}}}} +WebTrends.prototype.dcsAdv=function(){if(this.trackevents&&(typeof(this.dcsET)=="function")){if(window.addEventListener){window.addEventListener("load",this.dcsET.wtbind(this),false);} +else if(window.attachEvent){window.attachEvent("onload",this.dcsET.wtbind(this));}} +this.dcsFPC();} +WebTrends.prototype.dcsVar=function(){var dCurrent=new Date();var WT=this.WT;var DCS=this.DCS;WT.tz=parseInt(dCurrent.getTimezoneOffset()/60*-1)||"0";WT.bh=dCurrent.getHours()||"0";WT.ul=navigator.appName=="Netscape"?navigator.language:navigator.userLanguage;if(typeof(screen)=="object"){WT.cd=navigator.appName=="Netscape"?screen.pixelDepth:screen.colorDepth;WT.sr=screen.width+"x"+screen.height;} +if(typeof(navigator.javaEnabled())=="boolean"){WT.jo=navigator.javaEnabled()?"Yes":"No";} +if(document.title){if(window.RegExp){var tire=new RegExp("^"+window.location.protocol+"//"+window.location.hostname+"\\s-\\s");WT.ti=document.title.replace(tire,"");} +else{WT.ti=document.title;}} +WT.js="Yes";WT.jv=(function(){var agt=navigator.userAgent.toLowerCase();var major=parseInt(navigator.appVersion);var mac=(agt.indexOf("mac")!=-1);var ff=(agt.indexOf("firefox")!=-1);var ff0=(agt.indexOf("firefox/0.")!=-1);var ff10=(agt.indexOf("firefox/1.0")!=-1);var ff15=(agt.indexOf("firefox/1.5")!=-1);var ff20=(agt.indexOf("firefox/2.0")!=-1);var ff3up=(ff&&!ff0&&!ff10&!ff15&!ff20);var nn=(!ff&&(agt.indexOf("mozilla")!=-1)&&(agt.indexOf("compatible")==-1));var nn4=(nn&&(major==4));var nn6up=(nn&&(major>=5));var ie=((agt.indexOf("msie")!=-1)&&(agt.indexOf("opera")==-1));var ie4=(ie&&(major==4)&&(agt.indexOf("msie 4")!=-1));var ie5up=(ie&&!ie4);var op=(agt.indexOf("opera")!=-1);var op5=(agt.indexOf("opera 5")!=-1||agt.indexOf("opera/5")!=-1);var op6=(agt.indexOf("opera 6")!=-1||agt.indexOf("opera/6")!=-1);var op7up=(op&&!op5&&!op6);var jv="1.1";if(ff3up){jv="1.8";} +else if(ff20){jv="1.7";} +else if(ff15){jv="1.6";} +else if(ff0||ff10||nn6up||op7up){jv="1.5";} +else if((mac&&ie5up)||op6){jv="1.4";} +else if(ie5up||nn4||op5){jv="1.3";} +else if(ie4){jv="1.2";} +return jv;})();WT.ct="unknown";if(document.body&&document.body.addBehavior){try{document.body.addBehavior("#default#clientCaps");WT.ct=document.body.connectionType||"unknown";document.body.addBehavior("#default#homePage");WT.hp=document.body.isHomePage(location.href)?"1":"0";} +catch(e){}} +if(document.all){WT.bs=document.body?document.body.offsetWidth+"x"+document.body.offsetHeight:"unknown";} +else{WT.bs=window.innerWidth+"x"+window.innerHeight;} +WT.fv=(function(){var i,flash;if(window.ActiveXObject){for(i=15;i>0;i--){try{flash=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);return i+".0";} +catch(e){}}} +else if(navigator.plugins&&navigator.plugins.length){for(i=0;i<navigator.plugins.length;i++){if(navigator.plugins[i].name.indexOf('Shockwave Flash')!=-1){return navigator.plugins[i].description.split(" ")[2];}}} +return"Not enabled";})();WT.slv=(function(){var slv="Not enabled";try{if(navigator.userAgent.indexOf('MSIE')!=-1){var sli=new ActiveXObject('AgControl.AgControl');if(sli){slv="Unknown";}} +else if(navigator.plugins["Silverlight Plug-In"]){slv="Unknown";}} +catch(e){} +if(slv!="Not enabled"){var i,m,M,F;if((typeof(Silverlight)=="object")&&(typeof(Silverlight.isInstalled)=="function")){for(i=9;i>0;i--){M=i;if(Silverlight.isInstalled(M+".0")){break;} +if(slv==M){break;}} +for(m=9;m>=0;m--){F=M+"."+m;if(Silverlight.isInstalled(F)){slv=F;break;} +if(slv==F){break;}}}} +return slv;})();if(this.i18n){if(typeof(document.defaultCharset)=="string"){WT.le=document.defaultCharset;} +else if(typeof(document.characterSet)=="string"){WT.le=document.characterSet;} +else{WT.le="unknown";}} +WT.tv="9.3.0";WT.sp=this.splitvalue;WT.dl="0";WT.ssl=(window.location.protocol.indexOf('https:')==0)?"1":"0";DCS.dcsdat=dCurrent.getTime();DCS.dcssip=window.location.hostname;DCS.dcsuri=window.location.pathname;WT.es=DCS.dcssip+DCS.dcsuri;if(window.location.search){DCS.dcsqry=window.location.search;} +if(DCS.dcsqry){var dcsqry=DCS.dcsqry.toLowerCase();var params=this.paidsearchparams.length?this.paidsearchparams.toLowerCase().split(","):[];for(var i=0;i<params.length;i++){if(dcsqry.indexOf(params[i]+"=")!=-1){WT.srch="1";break;}}} +if((window.document.referrer!="")&&(window.document.referrer!="-")){if(!(navigator.appName=="Microsoft Internet Explorer"&&parseInt(navigator.appVersion)<4)){DCS.dcsref=window.document.referrer;}}} +WebTrends.prototype.dcsEscape=function(S,REL){if(REL!=""){S=S.toString();for(var R in REL){if(REL[R]instanceof RegExp){S=S.replace(REL[R],R);}} +return S;} +else{return escape(S);}} +WebTrends.prototype.dcsA=function(N,V){if(this.i18n&&(this.exre!="")&&!this.exre.test(N)){if(N=="dcsqry"){var newV="";var params=V.substring(1).split("&");for(var i=0;i<params.length;i++){var pair=params[i];var pos=pair.indexOf("=");if(pos!=-1){var key=pair.substring(0,pos);var val=pair.substring(pos+1);if(i!=0){newV+="&";} +newV+=key+"="+this.dcsEncode(val);}} +V=V.substring(0,1)+newV;} +else{V=this.dcsEncode(V);}} +return"&"+N+"="+this.dcsEscape(V,this.re);} +WebTrends.prototype.dcsEncode=function(S){return(typeof(encodeURIComponent)=="function")?encodeURIComponent(S):escape(S);} +WebTrends.prototype.dcsCreateImage=function(dcsSrc){if(document.images){this.images[this.index]=new Image();this.images[this.index].src=dcsSrc;this.index++;} +else{document.write('<img alt="" border="0" name="DCSIMG" width="1" height="1" src="'+dcsSrc+'">');}} +WebTrends.prototype.dcsMeta=function(){var elems;if(document.documentElement){elems=document.getElementsByTagName("meta");} +else if(document.all){elems=document.all.tags("meta");} +if(typeof(elems)!="undefined"){var length=elems.length;for(var i=0;i<length;i++){var name=elems.item(i).name;var content=elems.item(i).content;var equiv=elems.item(i).httpEquiv;if(name.length>0){if(name.toUpperCase().indexOf("WT.")==0){this.WT[name.substring(3)]=content;} +else if(name.toUpperCase().indexOf("DCSEXT.")==0){this.DCSext[name.substring(7)]=content;} +else if(name.toUpperCase().indexOf("DCSDIR.")==0){this.DCSdir[name.substring(7)]=content;} +else if(name.toUpperCase().indexOf("DCS.")==0){this.DCS[name.substring(4)]=content;}}}}} +WebTrends.prototype.dcsTag=function(){if(document.cookie.indexOf("WTLOPTOUT=")!=-1||!this.dcsChk()){return;} +var WT=this.WT;var DCS=this.DCS;var DCSext=this.DCSext;var i18n=this.i18n;var P="http"+(window.location.protocol.indexOf('https:')==0?'s':'')+"://"+this.domain+(this.dcsid==""?'':'/'+this.dcsid)+"/dcs.gif?";if(i18n){WT.dep="";} +for(var N in DCS){if(DCS[N]&&(typeof DCS[N]!="function")){P+=this.dcsA(N,DCS[N]);}} +for(N in WT){if(WT[N]&&(typeof WT[N]!="function")){P+=this.dcsA("WT."+N,WT[N]);}} +for(N in DCSext){if(DCSext[N]&&(typeof DCSext[N]!="function")){if(i18n){WT.dep=(WT.dep.length==0)?N:(WT.dep+";"+N);} +P+=this.dcsA(N,DCSext[N]);}} +if(i18n&&(WT.dep.length>0)){P+=this.dcsA("WT.dep",WT.dep);} +if(P.length>2048&&navigator.userAgent.indexOf('MSIE')>=0){P=P.substring(0,2040)+"&WT.tu=1";} +this.dcsCreateImage(P);this.WT.ad="";} +WebTrends.prototype.dcsDebug=function(){var t=this;var i=t.images[0].src;var q=i.indexOf("?");var r=i.substring(0,q).split("/");var m="<b>Protocol</b><br><code>"+r[0]+"<br></code>";m+="<b>Domain</b><br><code>"+r[2]+"<br></code>";m+="<b>Path</b><br><code>/"+r[3]+"/"+r[4]+"<br></code>";m+="<b>Query Params</b><code>"+i.substring(q+1).replace(/\&/g,"<br>")+"</code>";m+="<br><b>Cookies</b><br><code>"+document.cookie.replace(/\;/g,"<br>")+"</code>";if(t.w&&!t.w.closed){t.w.close();} +t.w=window.open("","dcsDebug","width=500,height=650,scrollbars=yes,resizable=yes");t.w.document.write(m);t.w.focus();} +WebTrends.prototype.dcsCollect=function(){if(this.enabled){this.dcsVar();this.dcsMeta();this.dcsAdv();this.dcsBounce();if(typeof(this.dcsCustom)=="function"){this.dcsCustom();} +this.dcsTag();}} +function dcsMultiTrack(){if(typeof(_tag)!="undefined"){return(_tag.dcsMultiTrack());}} +function dcsSetVar(){if(typeof(_tag)!="undefined"){return(_tag.dcsSetVar());}} +function dcsDebug(){if(typeof(_tag)!="undefined"){return(_tag.dcsDebug());}} +Function.prototype.wtbind=function(obj){var method=this;var temp=function(){return method.apply(obj,arguments);};return temp;} +WebTrends.prototype.dcsBounce=function(){if(typeof(this.WT.vt_f_s)!="undefined"&&this.WT.vt_f_s==1){this.WT.z_bounce="1";}else{this.WT.z_bounce="0";}} +WebTrends.prototype.dcsChk=function() +{if(this.rate==100){return"true";} +var cname='wtspl';cval=this.dcsGetCookie(cname);if(cval==null) +{cval=Math.floor(Math.random()*1000000);var date=new Date();date.setTime(date.getTime()+(30*24*60*60*1000));document.cookie=cname+"="+cval+"; expires="+date.toGMTString()+"; path=/; domain="+this.fpcdom+";";} +return((cval%1000)<(this.rate*10));}
\ No newline at end of file diff --git a/extensions/BMO/web/producticons/camino.png b/extensions/BMO/web/producticons/camino.png Binary files differnew file mode 100644 index 000000000..c833b4d04 --- /dev/null +++ b/extensions/BMO/web/producticons/camino.png diff --git a/extensions/BMO/web/producticons/dino.png b/extensions/BMO/web/producticons/dino.png Binary files differnew file mode 100644 index 000000000..9e0470a07 --- /dev/null +++ b/extensions/BMO/web/producticons/dino.png diff --git a/extensions/BMO/web/producticons/fennec.png b/extensions/BMO/web/producticons/fennec.png Binary files differnew file mode 100644 index 000000000..ebad7e358 --- /dev/null +++ b/extensions/BMO/web/producticons/fennec.png diff --git a/extensions/BMO/web/producticons/firefox.png b/extensions/BMO/web/producticons/firefox.png Binary files differnew file mode 100644 index 000000000..582a6952a --- /dev/null +++ b/extensions/BMO/web/producticons/firefox.png diff --git a/extensions/BMO/web/producticons/idea.png b/extensions/BMO/web/producticons/idea.png Binary files differnew file mode 100644 index 000000000..9480dce62 --- /dev/null +++ b/extensions/BMO/web/producticons/idea.png diff --git a/extensions/BMO/web/producticons/input.png b/extensions/BMO/web/producticons/input.png Binary files differnew file mode 100644 index 000000000..81f355d85 --- /dev/null +++ b/extensions/BMO/web/producticons/input.png diff --git a/extensions/BMO/web/producticons/labs.png b/extensions/BMO/web/producticons/labs.png Binary files differnew file mode 100644 index 000000000..346e0ef06 --- /dev/null +++ b/extensions/BMO/web/producticons/labs.png diff --git a/extensions/BMO/web/producticons/mozilla.png b/extensions/BMO/web/producticons/mozilla.png Binary files differnew file mode 100644 index 000000000..e506328bc --- /dev/null +++ b/extensions/BMO/web/producticons/mozilla.png diff --git a/extensions/BMO/web/producticons/other.png b/extensions/BMO/web/producticons/other.png Binary files differnew file mode 100644 index 000000000..e436c22ae --- /dev/null +++ b/extensions/BMO/web/producticons/other.png diff --git a/extensions/BMO/web/producticons/seamonkey.png b/extensions/BMO/web/producticons/seamonkey.png Binary files differnew file mode 100644 index 000000000..fcb261ae1 --- /dev/null +++ b/extensions/BMO/web/producticons/seamonkey.png diff --git a/extensions/BMO/web/producticons/sunbird.png b/extensions/BMO/web/producticons/sunbird.png Binary files differnew file mode 100644 index 000000000..6b15c257d --- /dev/null +++ b/extensions/BMO/web/producticons/sunbird.png diff --git a/extensions/BMO/web/producticons/thunderbird.png b/extensions/BMO/web/producticons/thunderbird.png Binary files differnew file mode 100644 index 000000000..f3523183a --- /dev/null +++ b/extensions/BMO/web/producticons/thunderbird.png diff --git a/extensions/BMO/web/styles/create_account.css b/extensions/BMO/web/styles/create_account.css new file mode 100644 index 000000000..0ab527629 --- /dev/null +++ b/extensions/BMO/web/styles/create_account.css @@ -0,0 +1,62 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * 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 + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Byron Jones <glob@mozilla.com> + * + * ***** END LICENSE BLOCK ***** */ + +#create-account h2 { + margin: 0px; +} + +.column-header { + padding: 20px 20px 20px 0px; +} + +#create-account-left { + border-right: 2px solid #888888; + padding-right: 10px; +} + +#product-list td { + padding-top: 10px; +} + +#product-list img { + padding-right: 10px; +} + +#create-account-right { + padding-left: 10px; +} + +#right-blurb { + font-size: large; +} + +#right-blurb li { + padding-bottom: 1em; +} + +#create-account-right { + padding-bottom: 5em; +} + diff --git a/extensions/BMO/web/styles/edit_bug.css b/extensions/BMO/web/styles/edit_bug.css new file mode 100644 index 000000000..089a92fbb --- /dev/null +++ b/extensions/BMO/web/styles/edit_bug.css @@ -0,0 +1,38 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * 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 BMO Bugzilla Extension; + * + * The Initial Developer of the Original Code is the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Byron Jones <glob@mozilla.com> + * + * ***** END LICENSE BLOCK ***** + */ + +#project-flags, +#custom-flags { + width: auto; +} + +.bz_hidden { + display: none; +} + +.bz_collapse_comment { + font-family: monospace; +} + diff --git a/extensions/BMO/web/styles/reports.css b/extensions/BMO/web/styles/reports.css new file mode 100644 index 000000000..2a6bc54fc --- /dev/null +++ b/extensions/BMO/web/styles/reports.css @@ -0,0 +1,58 @@ +.hidden { + display: none; +} + +#product, #component { + width: 20em; +} + +#parameters th { + text-align: left; + vertical-align: middle !important; +} + +#report tr.bugitem:hover { + background: #ccccff; +} + +#report td, #report th { + padding: 3px 10px 3px 3px; +} + +#report th { + text-align: left; +} + +#report th.sorted { + text-decoration: underline; +} + +#report-header { + background: #cccccc; +} + +.report_row_odd { + background-color: #eeeeee; + color: #000000; +} + +.report_row_even { + background-color: #ffffff; + color: #000000; +} + +#report tr:hover { + background-color: #ccccff; +} + +#report { + border: 1px solid #888888; +} + +#report th, #report td { + border: 0px; +} + +.disabled { + color: #888888; +} diff --git a/extensions/BMO/web/styles/triage_reports.css b/extensions/BMO/web/styles/triage_reports.css new file mode 100644 index 000000000..6190fd32c --- /dev/null +++ b/extensions/BMO/web/styles/triage_reports.css @@ -0,0 +1,23 @@ +.hidden { + display: none; +} + +#triage_form th { + text-align: left; +} + +#product, #component { + width: 20em; +} + +#report tr.bugitem:hover { + background: #ccccff; +} + +#report td { + padding: 1px 10px 1px 10px; +} + +#report-header { + background: #dddddd; +} |