- add locale selection for test results;

- updated widgets for use with admin tools;
- in-progress work on admin tools
This commit is contained in:
ccooper%deadsquid.com 2005-12-13 03:03:37 +00:00
Родитель 5b95cc7199
Коммит 17518b3c30
28 изменённых файлов: 819 добавлений и 81 удалений

Просмотреть файл

@ -56,7 +56,7 @@ sub rebuildCache {
# whole thing out as javascript with Data::JavaScript
# shield your eyes, we're in for a long trip
my @litmusconfig;
my @products = Litmus::DB::Product->retrieve_all();
my @products = Litmus::DB::Product->search(enabled => 'Yes');
my $prodcount = 0;
foreach my $curproduct (@products) {
my $prodrow = \%{$litmusconfig[$prodcount]};
@ -117,7 +117,7 @@ sub rebuildCache {
print CACHE $data;
close(CACHE);
system("mv", "data/litmusconfig.js.new", "data/litmusconfig.js");
system("chmod", "-R", "755", "data/");
#system("chmod", "-R", "755", "data/");
}
1;

Просмотреть файл

@ -0,0 +1,46 @@
# -*- mode: cperl; c-basic-offset: 8; indent-tabs-mode: nil; -*-
=head1 COPYRIGHT
# ***** 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 Litmus.
#
# The Initial Developer of the Original Code is
# the Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Cooper <ccooper@deadsquid.com>
# Zach Lipton <zach@zachlipton.com>
#
# ***** END LICENSE BLOCK *****
=cut
package Litmus::DB::Locale;
use strict;
use base 'Litmus::DBI';
Litmus::DB::Locale->table('locale_lookup');
Litmus::DB::Locale->columns(All => qw/abbrev name/);
Litmus::DB::Locale->column_alias("abbrev", "locale");
Litmus::DB::Locale->has_many(test_results => "Litmus::DB::Testresult");
1;

Просмотреть файл

@ -37,7 +37,7 @@ use base 'Litmus::DBI';
Litmus::DB::Product->table('products');
Litmus::DB::Product->columns(All => qw/product_id name iconpath/);
Litmus::DB::Product->columns(All => qw/product_id name iconpath enabled/);
Litmus::DB::Product->column_alias("product_id", "productid");

Просмотреть файл

@ -55,6 +55,7 @@ sub community_coverage() {
my $self = shift;
my $platform = shift;
my $build_id = shift;
my $locale = shift;
my $community_only = shift;
my @tests;
@ -73,7 +74,7 @@ sub community_coverage() {
if (@tests == 0) { return "N/A" }
my $num_completed = 0;
foreach my $curtest (@tests) {
if ($curtest->is_completed($platform,$build_id)) {
if ($curtest->is_completed($platform,$build_id,$locale)) {
$num_completed++;
}
}
@ -91,6 +92,7 @@ sub personal_coverage() {
my $self = shift;
my $platform = shift;
my $build_id = shift;
my $locale = shift;
my $community_only = shift;
my $user = shift;
@ -110,7 +112,7 @@ sub personal_coverage() {
if (@tests == 0) { return "N/A" }
my $num_completed = 0;
foreach my $curtest (@tests) {
if ($curtest->is_completed($platform,$build_id,$user)) {
if ($curtest->is_completed($platform,$build_id,$locale,$user)) {
$num_completed++;
}
}

Просмотреть файл

@ -79,7 +79,7 @@ sub isrecent {
}
#########################################################################
# is_completed($$$$)
# is_completed($$$$$)
#
# Check whether we have test results for the current test that correspond
# to the provided platform, build_id, and user(optional).
@ -89,6 +89,7 @@ sub is_completed {
my $self = shift;
my $platform = shift;
my $build_id = shift;
my $locale = shift;
my $user = shift; # optional
my @results;
@ -96,12 +97,14 @@ sub is_completed {
@results = $self->testresults(
platform => $platform,
buildid => $build_id,
locale => $locale,
user => $user,
);
} else {
@results = $self->testresults(
platform => $platform,
buildid => $build_id,
locale => $locale,
);
}

Просмотреть файл

@ -52,6 +52,7 @@ sub community_coverage {
my $self = shift;
my $platform = shift;
my $build_id = shift;
my $locale = shift;
my $community_only = shift;
my $percent_completed = 0;
@ -62,6 +63,7 @@ sub community_coverage {
my $subgroup_percent = $subgroup->community_coverage(
$platform,
$build_id,
$locale,
$community_only
);
if ($subgroup_percent eq "N/A") {
@ -85,6 +87,7 @@ sub personal_coverage {
my $self = shift;
my $platform = shift;
my $build_id = shift;
my $locale = shift;
my $community_only = shift;
my $user = shift;
@ -96,6 +99,7 @@ sub personal_coverage {
my $subgroup_percent = $subgroup->personal_coverage(
$platform,
$build_id,
$locale,
$community_only,
$user,
);
@ -116,3 +120,11 @@ sub personal_coverage {
}
1;

Просмотреть файл

@ -44,7 +44,7 @@ our $_num_results_default = 15;
Litmus::DB::Testresult->table('test_results');
Litmus::DB::Testresult->columns(All => qw/testresult_id test_id last_updated submission_time user_id platform_id opsys_id branch_id buildid user_agent result_id build_type_id machine_name exit_status_id duration_ms talkback_id validity_id vetting_status_id/);
Litmus::DB::Testresult->columns(All => qw/testresult_id test_id last_updated submission_time user_id platform_id opsys_id branch_id buildid user_agent result_id build_type_id machine_name exit_status_id duration_ms talkback_id validity_id vetting_status_id locale_abbrev/);
Litmus::DB::Testresult->column_alias("testresult_id", "testresultid");
Litmus::DB::Testresult->column_alias("test_id", "testid");
@ -59,6 +59,7 @@ Litmus::DB::Testresult->column_alias("build_type_id", "build_type");
Litmus::DB::Testresult->column_alias("exit_status_id", "exit_status");
Litmus::DB::Testresult->column_alias("validity_id", "validity");
Litmus::DB::Testresult->column_alias("vetting_status_id", "vetting_status");
Litmus::DB::Testresult->column_alias("locale_abbrev", "locale");
Litmus::DB::Testresult->has_a(platform => "Litmus::DB::Platform");
Litmus::DB::Testresult->has_a(opsys => "Litmus::DB::Opsys");
@ -71,6 +72,7 @@ Litmus::DB::Testresult->has_a(build_type => "Litmus::DB::BuildType");
Litmus::DB::Testresult->has_a(exit_status => "Litmus::DB::ExitStatus");
Litmus::DB::Testresult->has_a(validity => "Litmus::DB::Validity");
Litmus::DB::Testresult->has_a(vetting_status => "Litmus::DB::VettingStatus");
Litmus::DB::Testresult->has_a(locale => "Litmus::DB::Locale");
Litmus::DB::Testresult->has_many("logs" => "Litmus::DB::Log", {order_by => 'submission_time'});
Litmus::DB::Testresult->has_many(comments => "Litmus::DB::Comment", {order_by => 'comment_id ASC, submission_time ASC'});

Просмотреть файл

@ -36,6 +36,7 @@ use strict;
require Exporter;
use Litmus;
use Litmus::DB::Locale;
use Litmus::DB::Product;
use Litmus::Error;
use Litmus::Utils;
@ -47,7 +48,7 @@ our @EXPORT = qw();
my $configcookiename = $Litmus::Config::sysconfig_cookiename;
sub new {
my ($class, $product, $platform, $opsys, $branch, $buildid) = @_;
my ($class, $product, $platform, $opsys, $branch, $buildid, $locale) = @_;
my $self = {};
bless($self);
@ -55,8 +56,9 @@ sub new {
$self->{"product"} = $product;
$self->{"platform"} = $platform;
$self->{"opsys"} = $opsys;
$self->{"branch"} = $branch;
$self->{"branch"} = $branch;
$self->{"buildid"} = $buildid;
$self->{"locale"} = $locale;
return $self;
}
@ -70,7 +72,7 @@ sub setCookie {
my $cookie = $c->cookie(
-name => $configcookiename.'_'.$self->{"product"}->productid(),
-value => join('|', $self->{"product"}->productid(), $self->{"platform"}->platformid(),
$self->{"opsys"}->opsysid(), $self->{"branch"}->branchid(), $self->{"buildid"}),
$self->{"opsys"}->opsysid(), $self->{"branch"}->branchid(), $self->{"buildid"}, $self->{"locale"}->abbrev()),
-domain => $main::ENV{"HTTP_HOST"},
);
@ -95,6 +97,7 @@ sub getCookie() {
Litmus::DB::Opsys->retrieve($sysconfig[2]),
Litmus::DB::Branch->retrieve($sysconfig[3]),
$sysconfig[4],
Litmus::DB::Locale->retrieve($sysconfig[5])
);
}
@ -128,6 +131,13 @@ sub buildid() {
return $self->{"buildid"};
}
sub locale() {
my $self = shift;
return $self->{"locale"};
}
# display the system configuration form
# optionally takes the product to configure for
# and requires a url to load when done. this
@ -152,7 +162,12 @@ sub displayForm {
@products = Litmus::DB::Product->retrieve_all();
}
my @locales = Litmus::DB::Locale->retrieve_all(
{ order_by => 'abbrev' }
);
my $vars = {
locales => \@locales,
products => \@products,
ua => Litmus::UserAgentDetect->new(),
"goto" => $goto,
@ -166,6 +181,7 @@ sub displayForm {
$vars->{"defaultplatform"} = $sysconfig->platform();
$vars->{"defaultopsys"} = $sysconfig->opsys();
$vars->{"defaultbranch"} = $sysconfig->branch();
$vars->{"defaultlocale"} = $sysconfig->locale();
}
my $cookie = Litmus::Auth::getCookie();
@ -189,12 +205,14 @@ sub processForm {
my $opsys = Litmus::DB::Opsys->retrieve($c->param("opsys"));
my $branch = Litmus::DB::Branch->retrieve($c->param("branch"));
my $buildid = $c->param("buildid");
my $locale = Litmus::DB::Locale->retrieve($c->param("locale"));
requireField("product", $product);
requireField("platform", $platform);
requireField("opsys", $opsys);
requireField("branch", $branch);
requireField("buildid", $buildid);
requireField("locale", $locale);
# set a cookie with the user's testing details:
my $prod = Litmus::DB::Product->retrieve($c->param("product"));
@ -203,9 +221,13 @@ sub processForm {
$platform,
$opsys,
$branch,
$buildid
$buildid,
$locale
);
return $sysconfig;
}
1;

Просмотреть файл

@ -101,6 +101,21 @@ sub buildid {
return $1;
}
sub locale {
my $self = shift;
my $ua = $self->{ua};
# mozilla products only
unless ($ua =~ /Mozilla\/5\.0/) {
return undef;
}
# Format (e.g.):
# Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051111 Firefox/1.5
$ua =~ /Mozilla\/5\.0 \([^;]*; [^;]*; [^;]*; ([^;]*); [^;]*\)/;
return $1;
}
sub platform {
my $self = shift;
my $product = shift; # optionally, just lookup for one product

Просмотреть файл

@ -764,6 +764,10 @@ div.error {
display: none;
}
#notification {
display: none;
}
#printheader {
display: none;
}
@ -935,9 +939,9 @@ table.category h1 {
font-size: 1.1em;
}
input.button {
font-size: 0.9em;
margin-top: 5px;
input.category {
font-size: 1em;
margin: 5px 0px 0px 0px;
}
div.advSearchForm {

Просмотреть файл

@ -35,8 +35,8 @@ $|++;
use Litmus;
use Litmus::Auth;
use Litmus::Cache;
use Litmus::Error;
use Litmus::DB::Testresult;
use Litmus::FormWidget;
use CGI;
@ -44,7 +44,50 @@ use Time::Piece::MySQL;
use diagnostics;
my ($criteria,$results) = Litmus::DB::Testresult->getDefaultTestResults;
my $c = new CGI;
print $c->header();
if ($c->param) {
my $product;
my $rebuild_cache;
if ($c->param('add_product')) {
my $name = $c->param('new_product_name');
my $icon_path = $c->param('new_icon_path') || "";
my $enabled = $c->param('new_enabled') ? 'Yes' : 'No';
eval {
$product = Litmus::DB::Product->create({
name => $name,
iconpath => $icon_path,
enabled => $enabled,
});
$rebuild_cache = 1;
};
}
if ($c->param('delete_product')) {
$product = Litmus::DB::Product->retrieve($c->param('modify_product_id'));
$product->delete;
$rebuild_cache = 1;
}
if ($c->param('update_product')) {
$product = Litmus::DB::Product->retrieve($c->param('modify_product_id'));
$product->name($c->param('modify_product_name'));
$product->iconpath($c->param('modify_icon_path'));
if ($c->param('modify_enabled')) {
$product->enabled('Yes');
} else {
$product->enabled('No');
}
eval {
$product->update;
$rebuild_cache = 1;
};
}
if ($rebuild_cache) {
use Litmus::Cache;
rebuildCache();
}
}
my $products = Litmus::FormWidget->getProducts();
my $platforms = Litmus::FormWidget->getPlatforms();
@ -52,9 +95,6 @@ my $branches = Litmus::FormWidget->getBranches();
my $opsyses = Litmus::FormWidget->getOpsyses();
my $log_types = Litmus::FormWidget->getLogTypes();
my $c = new CGI;
print $c->header();
my $vars = {
title => 'Edit Categories',
products => $products,

Просмотреть файл

@ -0,0 +1,306 @@
var iBugNumber = "This field must be a valid, positive integer (>0). Please re-enter it now.";
var iEmail = "This field must be a valid email address (like foo@bar.com). Please re-enter it now.";
var iBuildId = "This field must be a valid build id, which is a string of 8 digits most easily found in the About dialog. Please re-enter it now.";
var defaultEmptyOK = false;
var mPrefix = "You did not enter a value into the ";
var mSuffix = " field. This is a required field. Please enter it now.";
var whitespace = " \t\n\r";
// Check whether string s is empty.
function isEmpty(s)
{
return ((s == null) || (s.length == 0));
}
// Returns true if string s is empty or
// whitespace characters only.
function isWhitespace (s)
{
var i;
// Is s empty?
if (isEmpty(s)) return true;
// Search through string's characters one by one
// until we find a non-whitespace character.
// When we do, return false; if we don't, return true.
for (i = 0; i < s.length; i++) {
// Check that current character isn't whitespace.
var c = s.charAt(i);
if (whitespace.indexOf(c) == -1) return false;
}
// All characters are whitespace.
return true;
}
// Returns true if character c is a digit
// (0 .. 9).
function isDigit (c)
{
return ((c >= "0") && (c <= "9"));
}
// Notify user that required field theField is empty.
// String s describes expected contents of theField.value.
// Put focus in theField and return false.
function warnEmpty (theField, s)
{
theField.focus();
alert(mPrefix + s + mSuffix);
return false;
}
// Notify user that contents of field theField are invalid.
// String s describes expected contents of theField.value.
// Put select theField, put focus in it, and return false.
function warnInvalid (theField, s)
{
theField.focus();
theField.select();
alert(s);
return false;
}
// isEmail (STRING s [, BOOLEAN emptyOK])
//
// Email address must be of form a@b.c -- in other words:
// * there must be at least one character before the @
// * there must be at least one character before and after the .
// * the characters @ and . are both required
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isEmail (s)
{
if (isEmpty(s)) {
if (isEmail.arguments.length == 1) {
return defaultEmptyOK;
} else {
return (isEmail.arguments[1] == true);
}
}
// is s whitespace?
if (isWhitespace(s)) {
return false;
}
// there must be >= 1 character before @, so we
// start looking at character position 1
// (i.e. second character)
var i = 1;
var sLength = s.length;
// look for @
while ((i < sLength) && (s.charAt(i) != "@")) {
i++;
}
if ((i >= sLength) || (s.charAt(i) != "@")) {
return false;
} else {
i += 2;
}
// look for .
while ((i < sLength) && (s.charAt(i) != ".")) {
i++;
}
// there must be at least one character after the .
if ((i >= sLength - 1) || (s.charAt(i) != ".")) {
return false;
} else {
return true;
}
}
// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is not all whitespace.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function checkString (theField, s, emptyOK)
{
// Next line is needed on NN3 to avoid "undefined is not a number" error
// in equality comparison below.
if (checkString.arguments.length == 2) {
emptyOK = defaultEmptyOK;
}
if ((emptyOK == true) && (isEmpty(theField.value))) {
return true;
}
if (isWhitespace(theField.value)) {
return warnEmpty(theField, s);
} else {
return true;
}
}
// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid Email.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function checkEmail (theField, emptyOK)
{
if (checkEmail.arguments.length == 1) {
emptyOK = defaultEmptyOK;
}
if ((emptyOK == true) && (isEmpty(theField.value))) {
return true;
} else {
if (!isEmail(theField.value, false)) {
return warnInvalid (theField, iEmail);
} else {
return true;
}
}
}
// checkBuildId (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid build id.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function checkBuildId (theField, emptyOK)
{
if (checkBuildId.arguments.length == 1) {
emptyOK = defaultEmptyOK;
}
if ((emptyOK == true) && (isEmpty(theField.value))) {
return true;
} else {
if (!/\d{8,}/.test(theField.value)) {
return warnInvalid (theField, iBuildId);
} else {
return true;
}
}
}
// isInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters in string s are numbers.
//
// Accepts non-signed integers only. Does not accept floating
// point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// By default, returns defaultEmptyOK if s is empty.
// There is an optional second argument called emptyOK.
// emptyOK is used to override for a single function call
// the default behavior which is specified globally by
// defaultEmptyOK.
// If emptyOK is false (or any value other than true),
// the function will return false if s is empty.
// If emptyOK is true, the function will return true if s is empty.
//
// EXAMPLE FUNCTION CALL: RESULT:
// isInteger ("5") true
// isInteger ("") defaultEmptyOK
// isInteger ("-5") false
// isInteger ("", true) true
// isInteger ("", false) false
// isInteger ("5", false) true
function isInteger (s)
{
var i;
if (isEmpty(s))
if (isInteger.arguments.length == 1) return defaultEmptyOK;
else return (isInteger.arguments[1] == true);
// Search through string's characters one by one
// until we find a non-numeric character.
// When we do, return false; if we don't, return true.
for (i = 0; i < s.length; i++)
{
// Check that current character is number.
var c = s.charAt(i);
if (!isDigit(c)) return false;
}
// All characters are numbers.
return true;
}
// isSignedInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters are numbers;
// first character is allowed to be + or - as well.
//
// Does not accept floating point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
//
// EXAMPLE FUNCTION CALL: RESULT:
// isSignedInteger ("5") true
// isSignedInteger ("") defaultEmptyOK
// isSignedInteger ("-5") true
// isSignedInteger ("+5") true
// isSignedInteger ("", false) false
// isSignedInteger ("", true) true
function isSignedInteger (s)
{
if (isEmpty(s))
if (isSignedInteger.arguments.length == 1) return defaultEmptyOK;
else return (isSignedInteger.arguments[1] == true);
else {
var startPos = 0;
var secondArg = defaultEmptyOK;
if (isSignedInteger.arguments.length > 1)
secondArg = isSignedInteger.arguments[1];
// skip leading + or -
if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
startPos = 1;
return (isInteger(s.substring(startPos, s.length), secondArg));
}
}
// isPositiveInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if string s is an integer > 0.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isPositiveInteger (s)
{
var secondArg = defaultEmptyOK;
if (isPositiveInteger.arguments.length > 1)
secondArg = isPositiveInteger.arguments[1];
// The next line is a bit byzantine. What it means is:
// a) s must be a signed integer, AND
// b) one of the following must be true:
// i) s is empty and we are supposed to return true for
// empty strings
// ii) this is a positive, not negative, number
return (isSignedInteger(s, secondArg)
&& ( (isEmpty(s) && secondArg) || (parseInt (s) > 0) ) );
}

Просмотреть файл

@ -150,6 +150,7 @@ foreach my $curtestid (@tests) {
opsys => $sysconfig->opsys(),
branch => $sysconfig->branch(),
buildid => $sysconfig->buildid(),
locale_abbrev => $sysconfig->locale(),
});
# if there's a note, create an entry in the comments table for it

Просмотреть файл

@ -155,6 +155,8 @@ sub page_test {
# get all possible test results:
my @results = Litmus::DB::Result->retrieve_all();
my $sysconfig = Litmus::SysConfig->getCookie($tests[0]->product());
my $vars = {
title => $title,
sysconfig => Litmus::SysConfig->getCookie($tests[0]->product()),

Просмотреть файл

@ -25,9 +25,24 @@
# ***** END LICENSE BLOCK *****
#%]
[% INCLUDE global/html_header.tmpl js_files=['js/prototype.lite.js','js/moo.fx.js','js/moo.fx.pack.js','js/EditCategories.js'] %]
[% INCLUDE global/html_header.tmpl js_files=['js/prototype.lite.js','js/moo.fx.js','js/moo.fx.pack.js','js/FormValidation.js','js/EditCategories.js'] %]
[% INCLUDE global/litmus_header.tmpl %]
<script type="text/javascript">
function createRequestObject() {
var ro;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
ro = new ActiveXObject("Microsoft.XMLHTTP");
}else{
ro = new XMLHttpRequest();
}
return ro;
}
var http = createRequestObject();
</script>
<div id="page">
[% INCLUDE sidebar/sidebar.tmpl %]
@ -36,6 +51,12 @@
<h1 class="firstHeading">[% title %]</h1>
<div id="notification" class="category">
<h2>Status</h2>
<div id="notification-content">
</div>
</div>
<div id="categories">
[% INCLUDE admin/form_widgets/update_products.tmpl %]
@ -61,3 +82,6 @@
[% INCLUDE global/litmus_footer.tmpl %]
[% INCLUDE global/html_footer.tmpl %]

Просмотреть файл

@ -1,14 +1,54 @@
<script type="text/javascript">
function checkAddBranchForm(f) {
return (
checkString(f.new_branch_name,"branch name",false) &&
checkProduct(f.branch_add_product) &&
checkString(f.new_branch_detect_regexp,"detect regexp",false)
);
}
function getBarnchByName(branchName) {
http.open('get', 'rpc.cgi?action=getBranchByName&branchName='+branchName);
http.onreadystatechange = updateBranchForm;
http.send(null);
}
function updateBranchForm() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
var em = document.getElementById("notification-content")
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById("modify_branch_id").value = update[0];
document.getElementById("modify_branch_name").disabled = false;
document.getElementById("modify_branch_name").value = update[1];
// lookup product
document.getElementById("modify_branch_detect_regexp").disabled = false;
document.getElementById("modify_branch_detect_regexp").value = update[2];
document.getElementById("delete_branch").disabled = false;
document.getElementById("update_branch").disabled = false;
} else {
document.getElementById("notification").style.display = 'block';
em.innerHTML = response;
}
}
}
</script>
<div id="branches" class="category">
<h2>Branches</h2>
<h3 class="display branch_add"><a name="#branch_add">Add&nbsp;&raquo;</a></h3>
<div id="branch_add" class="collapsable">
<form name="branch_add">
<form id="branch_add_form" name="branch_add_form" action="edit_categories.cgi" method="post" onSubmit="checkAddBranchForm(this);">
<table class="category">
<tr>
<td>Name:</td>
<td><input name="new_branch_name" type="text" size="30"></td>
<td><input id="new_branch_name" name="new_branch_name" type="text" size="30"></td>
</tr>
<tr>
<td>Product:</td>
@ -18,7 +58,7 @@
</tr>
<tr>
<td>Detect Regexp:</td>
<td><input name="new_detect_regexp" type="text" size="30"></td>
<td><input id="new_branch_detect_regexp" name="new_branch_detect_regexp" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">
@ -31,17 +71,18 @@
<h3 class="display branch_modify"><a name="#branch_modify">Modify / Delete&nbsp;&raquo;</a></h3>
<div id="branch_modify" class="collapsable">
<form name="branch_modify">
<form id="branch_modify_form" name="branch_modify_form" action="edit_categories.cgi" method="post">
<input id="modify_branch_id" name="modify_branch_id" type="hidden" value="">
<table class="category">
<tr>
<td colspan="2" align="left">
Select Existing Branch:<br/>
[% INCLUDE form_widgets/select_branch.tmpl size=5 name="branch_modify_existing" %]
[% INCLUDE form_widgets/select_branch.tmpl size=5 name="branch_modify_existing" onChange="getBranchByName(this.options[this.selectedIndex].value);" %]
</td>
</tr>
<tr>
<td>Name:</td>
<td><input disabled name="modify_branch_name" type="text" size="30"></td>
<td><input disabled id="modify_branch_name" name="modify_branch_name" type="text" size="30"></td>
</tr>
<tr>
<td>Product:</td>
@ -51,7 +92,7 @@ Select Existing Branch:<br/>
</tr>
<tr>
<td>Detect Regexp:</td>
<td><input disabled name="modify_detect_regexp" type="text" size="30"></td>
<td><input disabled id="modify_branch_detect_regexp" name="modify_branch_detect_regexp" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">

Просмотреть файл

@ -1,14 +1,48 @@
<script type="text/javascript">
function checkAddLogTypeForm(f) {
return (
checkString(f.new_log_type_name,"log type name",false)
);
}
function getLogTypeByName(logTypeName) {
http.open('get', 'rpc.cgi?action=getLogTypeByName&logTypeName='+logTypeName);
http.onreadystatechange = updateLogTypeForm;
http.send(null);
}
function updateLogTypeForm() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
var em = document.getElementById("notification-content")
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById("modify_log_type_id").value = update[0];
document.getElementById("modify_log_type_name").disabled = false;
document.getElementById("modify_log_type_name").value = update[1];
document.getElementById("delete_log_type").disabled = false;
document.getElementById("update_log_type").disabled = false;
} else {
document.getElementById("notification").style.display = 'block';
em.innerHTML = response;
}
}
}
</script>
<div id="log_types" class="category">
<h2>Log Types</h2>
<h3 class="display log_type_add"><a name="#log_type_add">Add&nbsp;&raquo;</a></h3>
<div id="log_type_add" class="collapsable">
<form name="log_type_add">
<form name="log_type_add_form" id="log_type_add_form" action="edit_categories.cgi" method="post" onSubmit="return checkAddLogTypeForm(this);">
<table class="category">
<tr>
<td>Name:</td>
<td><input name="new_log_type_name" type="text" size="30"></td>
<td><input id="new_log_type_name" name="new_log_type_name" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">
@ -21,17 +55,18 @@
<h3 class="display log_type_modify"><a name="#log_type_modify">Modify / Delete&nbsp;&raquo;</a></h3>
<div id="log_type_modify" class="collapsable">
<form name="log_type_modify">
<form name="log_type_modify_form" id="log_type_modify_form" action="edit_categories.cgi" method="post">
<input id="modify_log_type_id" name="modify_log_type_id" type="hidden" value="">
<table class="category">
<tr>
<td colspan="2" align="left">
Select Existing Log Type:<br/>
[% INCLUDE form_widgets/select_log_type.tmpl name="log_type_modify_existing" size=5 %]
[% INCLUDE form_widgets/select_log_type.tmpl name="log_type_modify_existing" size=5 onChange="getLogTypeByName(this.options[this.selectedIndex].value);" %]
</td>
</tr>
<tr>
<td>Name:</td>
<td><input disabled name="modify_log_type_name" type="text" size="30"></td>
<td><input disabled id="modify_log_type_name" name="modify_log_type_name" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">

Просмотреть файл

@ -1,14 +1,55 @@
<script type="text/javascript">
function checkAddOpsysForm(f) {
return (
checkString(f.new_opsys_name,"operating system name",false) &&
checkPlatform(f.opsys_add_platform) &&
checkString(f.new_opsys_detect_regexp,"detect regexp",false)
);
}
function getOpsysByName(opsysName) {
http.open('get', 'rpc.cgi?action=getOpsysByName&opsysName='+opsysName);
http.onreadystatechange = updateOpsysForm;
http.send(null);
}
function updateOpsysForm() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
var em = document.getElementById("notification-content")
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById("modify_opsys_id").value = update[0];
document.getElementById("modify_opsys_name").disabled = false;
document.getElementById("modify_opsys_name").value = update[1];
// lookup platform
document.getElementById("modify_opsys_detect_regexp").disabled = false;
document.getElementById("modify_opsys_detect_regexp").value = update[2];
document.getElementById("modify_opsys_icon_path").disabled = false;
document.getElementById("modify_opsys_icon_path").value = update[3];
document.getElementById("delete_opsys").disabled = false;
document.getElementById("update_opsys").disabled = false;
} else {
document.getElementById("notification").style.display = 'block';
em.innerHTML = response;
}
}
}
</script>
<div id="opsyses" class="category">
<h2>Operating Systems</h2>
<h3 class="display opsys_add"><a name="#opsys_add">Add&nbsp;&raquo;</a></h3>
<div id="opsys_add" class="collapsable">
<form name="opsys_add">
<form name="opsys_add_form" id="opsys_add_form" action="edit_categories.cgi" method="post" onSubmit="return checkAddOpsysForm(this);">
<table class="category">
<tr>
<td>Name:</td>
<td><input name="new_opsys_name" type="text" size="30"></td>
<td><input d="new_opsys_name" name="new_opsys_name" type="text" size="30"></td>
</tr>
<tr>
<td>Platform:</td>
@ -18,7 +59,7 @@
</tr>
<tr>
<td>Detect Regexp:</td>
<td><input name="new_detect_regexp" type="text" size="30"></td>
<td><input id="new_opsys_detect_regexp" name="new_opsys_detect_regexp" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">
@ -31,17 +72,18 @@
<h3 class="display opsys_modify"><a name="#opsys_modify">Modify / Delete&nbsp;&raquo;</a></h3>
<div id="opsys_modify" class="collapsable">
<form name="opsys_modify">
<form id="opsys_modify_form" name="opsys_modify_form" action="edit_categories.cgi" method="post">
<input id="modify_opsys_id" name="modify_opsys_id" type="hidden" value="">
<table class="category">
<tr>
<td colspan="2" align="left">
Select Existing Operating System:<br/>
[% INCLUDE form_widgets/select_opsys.tmpl size=5 name="opsys_modify_existing" %]
[% INCLUDE form_widgets/select_opsys.tmpl size=5 name="opsys_modify_existing" onChange="getOpsysByName(this.options[this.selectedIndex].value);" %]
</td>
</tr>
<tr>
<td>Name:</td>
<td><input disabled name="modify_opsys_name" type="text" size="30"></td>
<td><input disabled id="modify_opsys_name" name="modify_opsys_name" type="text" size="30"></td>
</tr>
<tr>
<td>Platform:</td>
@ -51,7 +93,7 @@ Select Existing Operating System:<br/>
</tr>
<tr>
<td>Detect Regexp:</td>
<td><input disabled name="modify_detect_regexp" type="text" size="30"></td>
<td><input disabled id="modify_opsys_detect_regexp" name="modify_opsys_detect_regexp" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">

Просмотреть файл

@ -1,10 +1,52 @@
<script type="text/javascript">
function checkAddPlatformForm(f) {
return (
checkString(f.new_platform_name,"platform name",false) &&
checkProduct(f.platform_add_product) &&
checkString(f.new_platform_detect_regexp,"detect regexp",false) &&
checkString(f.new_platform_icon_path,"icon path",true)
);
}
function getPlatformByName(platformName) {
http.open('get', 'rpc.cgi?action=getPlatformByName&platformName='+platformName);
http.onreadystatechange = updatePlatformForm;
http.send(null);
}
function updatePlatformForm() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
var em = document.getElementById("notification-content")
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById("modify_platform_id").value = update[0];
document.getElementById("modify_platform_name").disabled = false;
document.getElementById("modify_platform_name").value = update[1];
// lookup product
document.getElementById("modify_platform_detect_regexp").disabled = false;
document.getElementById("modify_platform_detect_regexp").value = update[2];
document.getElementById("modify_platform_icon_path").disabled = false;
document.getElementById("modify_platform_icon_path").value = update[3];
document.getElementById("delete_platform").disabled = false;
document.getElementById("update_platform").disabled = false;
} else {
document.getElementById("notification").style.display = 'block';
em.innerHTML = response;
}
}
}
</script>
<div id="platforms" class="category">
<h2>Platforms</h2>
<h3 class="display platform_add"><a name="#platform_add">Add&nbsp;&raquo;</a></h3>
<div id="platform_add" class="collapsable">
<form name="platform_add">
<form name="platform_add_form" id="platform_add_form" action="edit_categories.cgi" method="post" onSubmit="return checkAddPlatformForm(this);">
<table class="category">
<tr>
<td>Name:</td>
@ -18,11 +60,11 @@
</tr>
<tr>
<td>Detect Regexp:</td>
<td><input name="new_detect_regexp" type="text" size="30"></td>
<td><input name="new_platform_detect_regexp" type="text" size="30"></td>
</tr>
<tr>
<td>Icon Path:</td>
<td><input name="new_icon_path" type="text" size="30"></td>
<td><input name="new_platform_icon_path" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">
@ -35,12 +77,13 @@
<h3 class="display platform_modify"><a name="#platform_modify">Modify / Delete&nbsp;&raquo;</a></h3>
<div id="platform_modify" class="collapsable">
<form name="platform_modify">
<form id="platform_modify_form" name="platform_modify_form" action="edit_categories.cgi" method="post">
<input id="modify_platform_id" name="modify_platform_id" type="hidden" value="">
<table class="category">
<tr>
<td colspan="2" align="left">
Select Existing Platform:<br/>
[% INCLUDE form_widgets/select_platform.tmpl size=5 name="platform_modify_existing" %]
[% INCLUDE form_widgets/select_platform.tmpl size=5 name="platform_modify_existing" onChange="getPlatformByName(this.options[this.selectedIndex].value);" %]
</td>
</tr>
<tr>
@ -55,11 +98,11 @@ Select Existing Platform:<br/>
</tr>
<tr>
<td>Detect Regexp:</td>
<td><input disabled name="modify_detect_regexp" type="text" size="30"></td>
<td><input disabled name="modify_platform_detect_regexp" type="text" size="30"></td>
</tr>
<tr>
<td>Icon Path:</td>
<td><input disabled name="modify_icon_path" type="text" size="30"></td>
<td><input disabled name="modify_platform_icon_path" type="text" size="30"></td>
</tr>
<tr>
<td colspan="2" align="right">

Просмотреть файл

@ -1,18 +1,61 @@
<script type="text/javascript">
function checkAddProductForm(f) {
return (
checkString(f.new_product_name,"product name",false) &&
checkString(f.new_product_icon_path,"icon path",true)
);
}
function getProductByName(productName) {
http.open('get', 'rpc.cgi?action=getProductByName&productName='+productName);
http.onreadystatechange = updateProductForm;
http.send(null);
}
function updateProductForm() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
var em = document.getElementById("notification-content")
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById("modify_product_id").value = update[0];
document.getElementById("modify_product_name").disabled = false;
document.getElementById("modify_product_name").value = update[1];
document.getElementById("modify_product_icon_path").disabled = false;
document.getElementById("modify_product_icon_path").value = update[2];
document.getElementById("modify_product_enabled").disabled = false;
document.getElementById("modify_product_enabled").checked = update[3] == 'Yes' ? true : false;
document.getElementById("delete_product").disabled = false;
document.getElementById("update_product").disabled = false;
} else {
document.getElementById("notification").style.display = 'block';
em.innerHTML = response;
}
}
}
</script>
<div id="products" class="category">
<h2>Products</h2>
<h3 class="display product_add"><a name="#product_add">Add&nbsp;&raquo;</a></h3>
<div id="product_add" class="collapsable">
<form name="product_add">
<form name="product_add_form" id="product_add_form" action="edit_categories.cgi" method="post" onSubmit="return checkAddProductForm(this);">
<table class="category">
<tr>
<td>Name:</td>
<td><input name="new_product_name" type="text" size="30"></td>
<td><input id="new_product_name" name="new_product_name" type="text" size="30"></td>
</tr>
<tr>
<td>Icon Path:</td>
<td><input name="new_icon_path" type="text" size="30"></td>
<td><input id="new_product_icon_path" name="new_product_icon_path" type="text" size="30"></td>
</tr>
<tr>
<td>Enabled:</td>
<td><input id="new_product_enabled" name="new_product_enabled" type="checkbox" class="category" checked></td>
</tr>
<tr>
<td colspan="2" align="right">
@ -25,25 +68,30 @@
<h3 class="display product_modify"><a name="#product_modify">Modify / Delete&nbsp;&raquo;</a></h3>
<div id="product_modify" class="collapsable">
<form name="product_modify">
<form id="product_modify_form" name="product_modify_form" action="edit_categories.cgi" method="post">
<input id="modify_product_id" name="modify_product_id" type="hidden" value="">
<table class="category">
<tr>
<td colspan="2" align="left">
Select Existing Product:<br/>
[% INCLUDE form_widgets/select_product.tmpl name="product_modify_existing" size=5 %]
[% INCLUDE form_widgets/select_product.tmpl name="product_modify_existing" size=5 onChange="getProductByName(this.options[this.selectedIndex].value);" %]
</td>
</tr>
<tr>
<td>Name:</td>
<td><input disabled name="modify_product_name" type="text" size="30"></td>
<td><input disabled id="modify_product_name" name="modify_product_name" type="text" size="30"></td>
</tr>
<tr>
<td>Icon Path:</td>
<td><input disabled name="modify_icon_path" type="text" size="30"></td>
<td><input disabled id="modify_product_icon_path" name="modify_product_icon_path" type="text" size="30"></td>
</tr>
<tr>
<td>Enabled:</td>
<td><input disabled id="modify_product_enabled" name="modify_product_enabled" type="checkbox" class="category"></td>
</tr>
<tr>
<td colspan="2" align="right">
<input disabled class="category" name="delete_product" type="submit" value="Delete Product">&nbsp;<input disabled class="category" name="update_product" type="submit" value="Update Product">
<input disabled class="category" id="delete_product" name="delete_product" type="submit" value="Delete Product">&nbsp;<input disabled class="category" id="update_product" name="update_product" type="submit" value="Update Product">
</td>
</tr>
</table>

Просмотреть файл

@ -0,0 +1,9 @@
<select id="[% name %]" name="[% name %]"[% IF size %] size="[% size %]"[% END %][% IF disabled %] disabled[% END %][% IF onChange %] onChange="[% onChange %]"[% END %]>
[% IF placeholder %]<option value="">-Locale-</option>[% END %]
[% IF locales %]
[% FOREACH locale=locales %]
<option[% IF defaults.locale==locale.abbrev %] selected[% END %]
value="[% locale.abbrev | html %]">[% locale.abbrev | html %]</option>
[% END %]
[% END %]
</select>

Просмотреть файл

@ -1,4 +1,4 @@
<select name="[% name %]"[% IF size %] size="[% size %]"[% END %][% IF disabled %] disabled[% END %]>
<select name="[% name %]"[% IF size %] size="[% size %]"[% END %][% IF disabled %] disabled[% END %][% IF onChange %] onChange="[% onChange %]"[% END %]>
[% IF placeholder %]<option value="">-Product-</option>[% END %]
[% IF products %]
[% FOREACH product=products %]

Просмотреть файл

@ -95,6 +95,26 @@
</select>
[% END %]
[% # locale dropdown box
# defaultlocale - default locale selection
# (can be either a single object or a list)
# test (optional) - if given, the select name will be locale_localeid
%]
[% BLOCK localebox %]
[% IF test %] [% testidflag = "_$test.testid" %]
[% ELSE %] [% testidflag = "" %][% END %]
[% IF defaultbranch %]
[% valuelist = defaultlocale.list.join(',') %]
<input name="locale[%testidflag FILTER html %]_default"
id="locale[%testidflag FILTER html %]_default"
type="hidden"
value="[%valuelist FILTER html%]">
[% END %]
<select name="locale[%testidflag FILTER html%]" id="locale[%testidflag FILTER html%]"
class="select_locale">
</select>
[% END %]
[% # testgroup drowndown box
# default (optional) - the default selection
# (can be either a single object or a list)

Просмотреть файл

@ -71,7 +71,7 @@ Results submitted
[% ELSE %]
[% count = 0 %]
[% END %]
<tr class="[% curresult FILTER lower %]">
<tr class="[% curresult.search('unclear') ? 'unclear' : curresult FILTER lower %]">
<td><strong>[% curresult FILTER html %]:</strong></td>
<td>[% count FILTER html %]</td>
</tr>
@ -93,10 +93,7 @@ Results submitted
[% IF return %]
<a href="[% return | html | uri %]">Go Back</a> or
[% END %]
<a href="run_tests.cgi?product=[% product.productid | html | uri %]
&continuetesting=1&defaulttestgroup=
[% testgroup.testgroupid | html | uri %]">
Run Some More Tests</a>
<a href="run_tests.cgi?product=[% product.productid | html | uri %]&continuetesting=1&defaulttestgroup=[% testgroup.testgroupid | html | uri %]">Run Some More Tests</a>
</p>
</div> <!--END section-content-->
@ -112,3 +109,8 @@ Run Some More Tests</a>

Просмотреть файл

@ -41,3 +41,4 @@
<input class="button" type="submit" name="Submit" value="Submit">
</form>
[% INCLUDE global/footer.html.tmpl %]

Просмотреть файл

@ -58,7 +58,7 @@
<td>
<div class="dh">Product:</div><div class="dv">[% sysconfig.product.name FILTER html %]</div>
<div class="t_link"><a href="run_tests.cgi">Change Configuration</a></div>
<div class="dh">Locale:</div><div class="dv">[% sysconfig.locale.name FILTER html %] ([% sysconfig.locale.abbrev FILTER html %])</div>
</td>
<td>
<div class="dh">Platform:</div><div class="dv">[% sysconfig.platform.name FILTER html %]</div>
@ -69,6 +69,11 @@
<div class="dh">Build ID:</div><div class="dv">[% sysconfig.buildid FILTER html %]</div>
</td>
</tr>
<tr>
<td colspan="3">
<div class="t_link"><a href="run_tests.cgi">Change Configuration</a></div>
</td>
</tr>
</table>
</div> <!--END sum-->
@ -109,8 +114,8 @@ Select Testing Group
[% END %]
[% FOREACH curgroup = groups %]
[% community_completed = curgroup.community_coverage(sysconfig.platform, sysconfig.buildid, 0) %]
[% personal_completed = curgroup.personal_coverage(sysconfig.platform, sysconfig.buildid, 0, user) %]
[% community_completed = curgroup.community_coverage(sysconfig.platform, sysconfig.buildid, sysconfig.locale, 0) %]
[% personal_completed = curgroup.personal_coverage(sysconfig.platform, sysconfig.buildid, sysconfig.locale, 0, user) %]
[% IF community_completed == 100 OR completed == 'N/A' %]
[% groupstyle = 'completegroup' %]
@ -183,8 +188,8 @@ Please select a testing group with testcases, or that has not yet been tested in
[% select_first_avail_subgroup=1 %]
[% FOREACH cursubgroup = cursubgrouplist %]
[% community_completed = cursubgroup.community_coverage(sysconfig.platform, sysconfig.buildid, 0) %]
[% personal_completed = cursubgroup.personal_coverage(sysconfig.platform, sysconfig.buildid, 0, user) %]
[% community_completed = cursubgroup.community_coverage(sysconfig.platform, sysconfig.buildid, sysconfig.locale, 0) %]
[% personal_completed = cursubgroup.personal_coverage(sysconfig.platform, sysconfig.buildid, sysconfig.locale, 0, user) %]
[% IF community_completed == 100 OR completed == 'N/A' %]
[% groupstyle = 'completegroup' %]
@ -200,7 +205,7 @@ Please select a testing group with testcases, or that has not yet been tested in
<td align="left"><input [% IF personal_completed == 100 OR personal_completed == 'N/A' %]disabled [% ELSIF select_first_avail_subgroup==1 %][% select_first_avail_subgroup=0 %]checked [% END %]type="radio" name="subgroup_[% curgroup FILTER html %]"
value="[% cursubgroup.id FILTER html %]">
[% cursubgroup.name FILTER html %]</input></td>
<td align="center">[% counttests = cursubgroup.tests %]
<td align="center">[% counttests = cursubgroup.tests('status_id',1) %]
[% IF ! counttests %] 0
[% ELSIF ! counttests.testid %][% counttests.list.size %]
[% ELSE %]

Просмотреть файл

@ -44,9 +44,19 @@
[% PROCESS global/selects.none.tmpl %]
[% includeselects=1 %]
[% INCLUDE global/html_header.tmpl js_files=['js/SelectBoxes.js'] %]
[% INCLUDE global/html_header.tmpl js_files=['js/SelectBoxes.js','js/FormValidation.js'] %]
[% INCLUDE global/litmus_header.tmpl %]
<script type="text/javascript">
function checkFormContents(f) {
return (
checkBuildId(f.buildid) &&
checkEmail(f.email)
);
}
</script>
<div id="page">
[% INCLUDE sidebar/sidebar.tmpl %]
@ -62,7 +72,7 @@ System Information
<div class="section-content">
<p>To run tests, please enter some information about your system configuration.</p>
<form action="[% goto | html %]" method="post" name="form" id="form">
<form action="[% goto | html %]" method="post" name="sysconfig_form" id="sysconfig_form" onSubmit="return checkFormContents(this);">
<input name="isSysConfig" type="hidden" value="1">
<input name="testgroup" type="hidden" value="[% testgroup | html %]">
@ -113,6 +123,10 @@ System Information
<td>[% INCLUDE branchbox branches=branches defaultbranch=ua.branch(product) %]</td>
</tr>
<tr>
<td><div align="right">Locale: </div></td>
<td>[% INCLUDE form_widgets/select_locale.tmpl name="locale" defaults.locale=ua.locale %]</td>
</tr>
<tr>
<td><div align="right">Build ID:</div></td>
<td><input type="text" id="buildid" name="buildid" size="25" value="[% ua.buildid FILTER html %]"></td>
</tr>
@ -125,7 +139,7 @@ System Information
<td>PRIVACY NOTICE: Like <a href="https://bugzilla.mozilla.org/">Bugzilla</a>, Litmus is an open system. All testing results you submit will be visible to the public, including the email addresses of those involved. Although steps are taken to hide addresses from email harvesters, the spammers are continually getting better technology and it is almost guaranteed that the address you use with Litmus will get spam. We recommend using a free web email service (such as Yahoo or Hotmail or similar) and not your primary email address if this concerns you. There are solutions being worked on to allow you to hide your email address from other users, but that option is not yet available.
<tr>
<td colspan="2">
<input class="button" type="submit" name="Submit" value="Submit">
<input class="category" type="submit" name="Submit" value="Submit">
</td>
</tr>
</table>

Просмотреть файл

@ -57,26 +57,26 @@
<td>
<div class="dh">Product:</div><div class="dv">[% sysconfig.product.name FILTER html %]</div>
<div class="t_link"><a href="run_tests.cgi">Change Configuration</a></div>
<div class="dh">Locale:</div><div class="dv">[% sysconfig.locale.name FILTER html %] ([% sysconfig.locale.abbrev FILTER html %])</div>
</td>
<td>
<div class="dh">Platform:</div><div class="dv">[% sysconfig.platform.name FILTER html %]</div>
<div class="dh">Opsys:</div><div class="dv">[% sysconfig.opsys.name FILTER html %]</div>
</td>
<td>
<div class="dh">Branch:</div><div class="dv">[% sysconfig.branch.name FILTER html %]</div>
<div class="dh">Build ID:</div><div class="dv">[% sysconfig.buildid FILTER html %]</div>
</td>
<td>
<div class="dh">Group:</div><div class="dv">[% group.name FILTER html %]</div>
<div class="dh">Subgroup:</div><div class="dv">[% subgroup.name FILTER html %]</div>
</td>
</tr>
<tr>
<td colspan="3">
<div class="t_link"><a href="run_tests.cgi">Change Configuration</a></div>
</td>
</tr>
</table>
</div>
</div> <!--END sum-->
</div>
<form action="process_test.cgi" method="post" name="form" id="form">
@ -214,4 +214,3 @@ var tmp_menub=new Array([% i=1 %][% FOREACH test_id=test_ids %]"mb[% i %]",[% i=
[% INCLUDE global/litmus_footer.tmpl %]
[% INCLUDE global/html_footer.tmpl %]