SimpleCollectionPage embeds a single collection block. But unlike CollectionPage it is only a Page subclass instead of implementing both the Page and CollectionBlock interfaces. Customizing the collection block is done by creating a CollectionBlock subclass and passing the appropriate creator function to the page constructor.
This better separates the page customization aspects (implement a SimpleCollectionPage subclass) from the collection block ones (implement a CollectionBlock subclass). Most of the time only the collection block needs to be customized and SimpleCollectionPage can be used as is.
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- .../lib/ObjectModel/CGI/CollectionBlock.pm | 5 + .../ObjectModel/CGI/SimpleCollectionPage.pm | 138 ++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm
diff --git a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm index 9a52f11bc..200734a6a 100644 --- a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm +++ b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm @@ -91,6 +91,11 @@ sub _initialize($$$) #my ($self, $Collection, $EnclosingPage) = @_; }
+sub Create($$@) +{ + return ObjectModel::CGI::CollectionBlock->new(@_); +} + sub CallGetDetailsPage($) { my ($self) = @_; diff --git a/testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm b/testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm new file mode 100644 index 000000000..76e4d5195 --- /dev/null +++ b/testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm @@ -0,0 +1,138 @@ +# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*- +# Base class for list pages +# +# Copyright 2009 Ge van Geldorp +# Copyright 2014, 2017-2018, 2022 Francois Gouget +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +use strict; + +package ObjectModel::CGI::SimpleCollectionPage; + +=head1 NAME + +ObjectModel::CGI::SimpleCollectionPage - Base class for list pages + +A page containing a single collection block. + +The SimpleCollectionPage instances have the following properties: +=over +=item Collection +The collection containing the items to be shown in the CollectionBlock widget. + +=item CollectionBlock +The widget showing the items in the specified collection. + +=item ActionPerformed +Set to true if an action was specified and succeeded. +=back + +=cut + +use ObjectModel::CGI::Page; +our @ISA = qw(ObjectModel::CGI::Page); + +# Use require to avoid overriding Page::new() +require ObjectModel::CGI::CollectionBlock; + + +=pod +=over 12 + +=item C<_initialize()> + +Sets up the new page object. + +Parameters: +=over + +=item Request +=item RequiredRole +See Page::new(). + +=item Collection +This is the collection of items that should be shown in the CollectionBlock +widget. + +=item BlockCreator +If undefined the page will create an instance of the CollectionBlock class. +Otherwise it will use this function to create the CollectionBlock widget, thus +enabling use of a CollectionBlock subclass. + +=back + +=back +=cut + +sub _initialize($$$$;$) +{ + my ($self, $Request, $RequiredRole, $Collection, $BlockCreator) = @_; + + $self->{Collection} = $Collection; + $BlockCreator ||= &ObjectModel::CGI::CollectionBlock::Create; + $self->{CollectionBlock} = &$BlockCreator($Collection, $self); + $self->SUPER::_initialize($Request, $RequiredRole); +} + + +# +# HTML page generation +# + +sub GetTitle($) +{ + my ($self) = @_; + + my $Title = ucfirst($self->{Collection}->GetCollectionName()); + $Title =~ s/([a-z])([A-Z])/$1 $2/g; + return $Title; +} + +sub GenerateTitle($) +{ + my ($self) = @_; + + my $Title = $self->GetTitle(); + if ($Title) + { + print "<h1 id='PageTitle'>", $self->escapeHTML($Title), "</h1>\n"; + } +} + +sub GenerateBody($) +{ + my ($self) = @_; + + print "<div class='CollectionPageBody'>\n"; + $self->GenerateTitle(); + print "<div class='Content'>\n"; + $self->{CollectionBlock}->GenerateList(); + print "</div>\n"; + print "</div>\n"; +} + +sub GeneratePage($) +{ + my ($self) = @_; + + if ($self->GetParam("Action")) + { + $self->{ActionPerformed} = $self->{CollectionBlock}->OnAction($self->GetParam("Action")); + } + $self->SUPER::GeneratePage(); +} + +1;
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- testbot/web/JobDetails.pl | 378 +++++++++++++++++++++----------------- 1 file changed, 205 insertions(+), 173 deletions(-)
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl index 5b8b7013a..c4d6b1a1b 100644 --- a/testbot/web/JobDetails.pl +++ b/testbot/web/JobDetails.pl @@ -2,7 +2,7 @@ # Job details page # # Copyright 2009 Ge van Geldorp -# Copyright 2012-2014,2017-2020 Francois Gouget +# Copyright 2012-2014,2017-2022 Francois Gouget # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,73 +20,35 @@
use strict;
-package JobDetailsPage; +package StepsTasksBlock;
-use ObjectModel::CGI::CollectionPage; -our @ISA = qw(ObjectModel::CGI::CollectionPage); +use ObjectModel::CGI::CollectionBlock; +our @ISA = qw(ObjectModel::CGI::CollectionBlock);
-use File::Basename; -use POSIX qw(strftime); use URI::Escape; +use POSIX qw(strftime);
-use WineTestBot::Config; -use WineTestBot::Jobs; -use WineTestBot::Log; # For Elapsed() -use WineTestBot::LogUtils; -use WineTestBot::Missions; -use WineTestBot::StepsTasks; use WineTestBot::Utils; +use WineTestBot::Missions; use WineTestBot::Engine::Notify;
-sub _initialize($$$) +sub Create($$) { - my ($self, $Request, $RequiredRole) = @_; - $self->{start} = Time(); + my ($Collection, $EnclosingPage) = @_;
- my $JobId = $self->GetParam("Key"); - if (! defined($JobId)) - { - $JobId = $self->GetParam("JobId"); - } - $self->{Job} = CreateJobs()->GetItem($JobId); - if (!defined $self->{Job}) - { - exit($self->Redirect("/")); - } - $self->{JobId} = $JobId; - - $self->SUPER::_initialize($Request, $RequiredRole, CreateStepsTasks(undef, $self->{Job})); - if ($self->{Job}->Status =~ /^(?:queued|running)$/) - { - $self->SetRefreshInterval(30); - } -} - -sub GetPageTitle($) -{ - my ($self) = @_; - - my $PageTitle = $self->{Job}->Remarks; - $PageTitle =~ s/^[[]\Q$PatchesMailingList\E[]] //; - $PageTitle = "Job " . $self->{JobId} if ($PageTitle eq ""); - $PageTitle .= " - ${ProjectName} Test Bot"; - return $PageTitle; + return StepsTasksBlock->new($Collection, $EnclosingPage); }
-sub GetTitle($) -{ - my ($self) = @_; - - return "Job " . $self->{JobId} . " - " . $self->{Job}->Remarks; -} +# +# Individual item property support +#
-sub DisplayProperty($$$) +sub DisplayProperty($$) { - my ($self, $CollectionBlock, $PropertyDescriptor) = @_; + my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName(); - return $PropertyName eq "StepNo" || $PropertyName eq "TaskNo" || $PropertyName eq "Status" || $PropertyName eq "VM" || $PropertyName eq "Timeout" || $PropertyName eq "FileName" || @@ -94,9 +56,22 @@ sub DisplayProperty($$$) $PropertyName eq "Ended" || $PropertyName eq "TestFailures"; }
-sub GenerateHeaderCell($$$) +sub SortKeys($$) { - my ($self, $CollectionBlock, $PropertyDescriptor) = @_; + my ($self, $Keys) = @_; + + my @SortedKeys = sort { $a <=> $b } @$Keys; + return @SortedKeys; +} + + +# +# Item cell generation +# + +sub GenerateHeaderCell($$) +{ + my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName(); if ($PropertyName eq "CmdLineArg") @@ -109,13 +84,104 @@ sub GenerateHeaderCell($$$) } else { - return $self->SUPER::GenerateHeaderCell($CollectionBlock, $PropertyDescriptor); + return $self->SUPER::GenerateHeaderCell($PropertyDescriptor); + } +} + +sub GenerateDataCell($$$$) +{ + my ($self, $StepTask, $PropertyDescriptor, $DetailsPage) = @_; + + my $PropertyName = $PropertyDescriptor->GetName(); + if ($PropertyName eq "VM") + { + print "<td><a href='#k", $self->escapeHTML($StepTask->GetKey()), "'>"; + print $self->escapeHTML($self->GetDisplayValue($StepTask, $PropertyDescriptor)); + print "</a></td>\n"; + } + elsif ($PropertyName eq "FileName") + { + my $FileName = $StepTask->GetFullFileName(); + if ($FileName and -r $FileName) + { + my $JobId = $self->{EnclosingPage}->GetJob()->Id; + my $URI = "/GetFile.pl?JobKey=" . uri_escape($JobId) . + "&StepKey=" . uri_escape($StepTask->StepNo); + print "<td><a href='" . $self->escapeHTML($URI) . "'>"; + print $self->escapeHTML($self->GetDisplayValue($StepTask, $PropertyDescriptor)); + print "</a></td>\n"; + } + else + { + $self->SUPER::GenerateDataCell($StepTask, $PropertyDescriptor, $DetailsPage); + } + } + elsif ($PropertyName eq "CmdLineArg") + { + my $Args = $self->escapeHTML($StepTask->CmdLineArg); + if ($Args eq "" or $StepTask->VM->Type eq "wine") + { + $Args .= "<br>" if ($Args ne ""); + my ($ErrMessage, $Missions) = ParseMissionStatement($StepTask->Missions); + if (defined $ErrMessage) + { + $Args .= "<span class='Mission'>$ErrMessage</span>"; + } + else + { + $Args .= "<span class='Mission'>". $self->escapeHTML(GetTaskMissionDescription($Missions->[0], $StepTask->Type)) ."</span>"; + } + } + print "<td>$Args</td>\n"; + } + elsif ($PropertyName eq "Ended") + { + if (defined $StepTask->Ended) + { + my $Duration = $StepTask->Ended - $StepTask->Started; + my $TagId = "E". $StepTask->Id; + print "<td><a id='$TagId' class='title' title='", + strftime("%Y-%m-%d %H:%M:%S", localtime($StepTask->Ended)), + "'>", DurationToString($Duration), "</a>\n"; + print "<script type='text/javascript'><!--\n"; + print " ShowDateTime(", $StepTask->Ended, ",'$TagId');\n"; + print "--></script>\n"; + print "</td>\n"; + } + else + { + print "<td> </td>\n"; + } + } + else + { + $self->SUPER::GenerateDataCell($StepTask, $PropertyDescriptor, $DetailsPage); } }
-sub GetItemActions($$) + +# +# Per-item actions handling +# + +sub GetItemActions($) { - #my ($self, $CollectionBlock) = @_; + #my ($self) = @_; + return []; +} + + +# +# Actions handling +# + +sub GetActions($) +{ + my ($self) = @_; + + # These are mutually exclusive + return ["Cancel job"] if (!defined $self->CanCancel()); + return ["Restart job"] if (!defined $self->CanRestart()); return []; }
@@ -123,20 +189,21 @@ sub CanCancel($) { my ($self) = @_;
- my $Status = $self->{Job}->Status; + my $Job = $self->{EnclosingPage}->GetJob(); + my $Status = $Job->Status; if ($Status ne "queued" && $Status ne "running") { - return "Job already $Status"; + return "Job already $Status"; }
- my $Session = $self->GetCurrentSession(); + my $Session = $self->{EnclosingPage}->GetCurrentSession(); if (! defined($Session)) { return "You are not authorized to cancel this job"; } my $CurrentUser = $Session->User; if (! $CurrentUser->HasRole("admin") && - $self->{Job}->User->GetKey() ne $CurrentUser->GetKey()) + $Job->User->GetKey() ne $CurrentUser->GetKey()) { return "You are not authorized to cancel this job"; } @@ -148,20 +215,21 @@ sub CanRestart($) { my ($self) = @_;
- my $Status = $self->{Job}->Status; + my $Job = $self->{EnclosingPage}->GetJob(); + my $Status = $Job->Status; if ($Status ne "boterror" && $Status ne "canceled") { return "Not a failed / canceled Job"; }
- my $Session = $self->GetCurrentSession(); + my $Session = $self->{EnclosingPage}->GetCurrentSession(); if (! defined($Session)) { return "You are not authorized to restart this job"; } my $CurrentUser = $Session->User; if (! $CurrentUser->HasRole("admin") && - $self->{Job}->User->GetKey() ne $CurrentUser->GetKey()) # FIXME: Admin only? + $Job->User->GetKey() ne $CurrentUser->GetKey()) # FIXME: Admin only? { return "You are not authorized to restart this job"; } @@ -169,35 +237,26 @@ sub CanRestart($) return undef; }
-sub GetActions($$) -{ - my ($self, $CollectionBlock) = @_; - - # These are mutually exclusive - return ["Cancel job"] if (!defined $self->CanCancel()); - return ["Restart job"] if (!defined $self->CanRestart()); - return []; -} - sub OnCancel($) { my ($self) = @_;
my $ErrMessage = $self->CanCancel(); - if (defined($ErrMessage)) + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- $ErrMessage = JobCancel($self->{JobId}); - if (defined($ErrMessage)) + my $JobId = $self->{EnclosingPage}->GetJob()->Id; + $ErrMessage = JobCancel($JobId); + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- exit($self->Redirect("/JobDetails.pl?Key=" . $self->{JobId})); + exit($self->{EnclosingPage}->Redirect("/JobDetails.pl?Key=$JobId")); }
sub OnRestart($) @@ -205,44 +264,89 @@ sub OnRestart($) my ($self) = @_;
my $ErrMessage = $self->CanRestart(); - if (defined($ErrMessage)) + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- $ErrMessage = JobRestart($self->{JobId}); - if (defined($ErrMessage)) + my $JobId = $self->{EnclosingPage}->GetJob()->Id; + $ErrMessage = JobRestart($JobId); + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- exit($self->Redirect("/JobDetails.pl?Key=" . $self->{JobId})); + exit($self->{EnclosingPage}->Redirect("/JobDetails.pl?Key=$JobId")); }
-sub OnAction($$$) +sub OnAction($$) { - my ($self, $CollectionBlock, $Action) = @_; + my ($self, $Action) = @_;
- if ($Action eq "Cancel job") - { - return $self->OnCancel(); - } - elsif ($Action eq "Restart job") + return $Action eq "Cancel job" ? $self->OnCancel() : + $Action eq "Restart job" ? $self->OnRestart() : + $self->SUPER::OnAction($Action); +} + + +package JobDetailsPage; + +use ObjectModel::CGI::SimpleCollectionPage; +our @ISA = qw(ObjectModel::CGI::SimpleCollectionPage); + +use URI::Escape; + +use WineTestBot::Config; +use WineTestBot::Jobs; +use WineTestBot::Log; # For Elapsed() +use WineTestBot::LogUtils; +use WineTestBot::StepsTasks; + + +sub _initialize($$$) +{ + my ($self, $Request, $RequiredRole) = @_; + $self->{start} = Time(); + + $self->{JobId} = $self->GetParam("Key"); + $self->{JobId} = $self->GetParam("JobId") if (!defined $self->{JobId}); + + $self->{Job} = CreateJobs()->GetItem($self->{JobId}); + exit($self->Redirect("/")) if (!defined $self->{Job}); + + my $Collection = CreateStepsTasks(undef, $self->{Job}); + $self->SUPER::_initialize($Request, $RequiredRole, $Collection, &StepsTasksBlock::Create); + if ($self->{Job}->Status =~ /^(?:queued|running)$/) { - return $self->OnRestart(); + $self->SetRefreshInterval(30); } +} + +sub GetJob($) +{ + my ($self) = @_;
- return $self->SUPER::OnAction($CollectionBlock, $Action); + return $self->{Job}; }
-sub SortKeys($$$) +sub GetPageTitle($) { - my ($self, $CollectionBlock, $Keys) = @_; + my ($self) = @_;
- my @SortedKeys = sort { $a <=> $b } @$Keys; - return @SortedKeys; + my $PageTitle = $self->{Job}->Remarks; + $PageTitle =~ s/^[[]\Q$PatchesMailingList\E[]] //; + $PageTitle = "Job " . $self->{JobId} if ($PageTitle eq ""); + $PageTitle .= " - ${ProjectName} Test Bot"; + return $PageTitle; +} + +sub GetTitle($) +{ + my ($self) = @_; + + return "Job $self->{JobId} - ". $self->{Job}->Remarks; }
sub InitMoreInfo($) @@ -250,7 +354,7 @@ sub InitMoreInfo($) my ($self) = @_;
my $More = $self->{More} = {}; - my $Keys = $self->SortKeys(undef, $self->{Collection}->GetKeys()); + my $Keys = $self->{CollectionBlock}->SortKeys($self->{Collection}->GetKeys()); foreach my $Key (@$Keys) { my $StepTask = $self->{Collection}->GetItem($Key); @@ -458,7 +562,7 @@ function HideLog(event, url) EOF
print "<div class='Content'>\n"; - my $Keys = $self->SortKeys(undef, $self->{Collection}->GetKeys()); + my $Keys = $self->{CollectionBlock}->SortKeys($self->{Collection}->GetKeys()); my $KeyIndex = 0; foreach my $Key (@$Keys) { @@ -627,78 +731,6 @@ EOF print "</div>\n"; }
-sub GenerateDataCell($$$$$) -{ - my ($self, $CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage) = @_; - - my $PropertyName = $PropertyDescriptor->GetName(); - if ($PropertyName eq "VM") - { - print "<td><a href='#k", $self->escapeHTML($StepTask->GetKey()), "'>"; - print $self->escapeHTML($self->GetDisplayValue($CollectionBlock, $StepTask, - $PropertyDescriptor)); - print "</a></td>\n"; - } - elsif ($PropertyName eq "FileName") - { - my $FileName = $StepTask->GetFullFileName(); - if ($FileName and -r $FileName) - { - my $URI = "/GetFile.pl?JobKey=" . uri_escape($self->{JobId}) . - "&StepKey=" . uri_escape($StepTask->StepNo); - print "<td><a href='" . $self->escapeHTML($URI) . "'>"; - print $self->escapeHTML($self->GetDisplayValue($CollectionBlock, $StepTask, - $PropertyDescriptor)); - print "</a></td>\n"; - } - else - { - $self->SUPER::GenerateDataCell($CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage); - } - } - elsif ($PropertyName eq "CmdLineArg") - { - my $Args = $self->escapeHTML($StepTask->CmdLineArg); - if ($Args eq "" or $StepTask->VM->Type eq "wine") - { - $Args .= "<br>" if ($Args ne ""); - my ($ErrMessage, $Missions) = ParseMissionStatement($StepTask->Missions); - if (defined $ErrMessage) - { - $Args .= "<span class='Mission'>$ErrMessage</span>"; - } - else - { - $Args .= "<span class='Mission'>". $self->escapeHTML(GetTaskMissionDescription($Missions->[0], $StepTask->Type)) ."</span>"; - } - } - print "<td>$Args</td>\n"; - } - elsif ($PropertyName eq "Ended") - { - if (defined $StepTask->Ended) - { - my $Duration = $StepTask->Ended - $StepTask->Started; - my $TagId = "E". $StepTask->Id; - print "<td><a id='$TagId' class='title' title='", - strftime("%Y-%m-%d %H:%M:%S", localtime($StepTask->Ended)), - "'>", DurationToString($Duration), "</a>\n"; - print "<script type='text/javascript'><!--\n"; - print " ShowDateTime(", $StepTask->Ended, ",'$TagId');\n"; - print "--></script>\n"; - print "</td>\n"; - } - else - { - print "<td> </td>\n"; - } - } - else - { - $self->SUPER::GenerateDataCell($CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage); - } -} - sub GenerateFooter($) { my ($self) = @_;
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- testbot/web/PatchesList.pl | 63 ++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/testbot/web/PatchesList.pl b/testbot/web/PatchesList.pl index 04ca0208c..e756a76ff 100644 --- a/testbot/web/PatchesList.pl +++ b/testbot/web/PatchesList.pl @@ -2,6 +2,7 @@ # Patch list page # # Copyright 2010 Ge van Geldorp +# Copyright 2012-2018, 2022 Francois Gouget # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -19,34 +20,25 @@
use strict;
-package PatchesListPage; +package PatchesBlock;
-use ObjectModel::CGI::CollectionPage; -our @ISA = qw(ObjectModel::CGI::CollectionPage); +use ObjectModel::CGI::CollectionBlock; +our @ISA = qw(ObjectModel::CGI::CollectionBlock);
use URI::Escape; use WineTestBot::Patches;
-sub _initialize($$$) +sub Create($$) { - my ($self, $Request, $RequiredRole) = @_; + my ($Collection, $EnclosingPage) = @_;
- $self->SUPER::_initialize($Request, $RequiredRole, CreatePatches()); - $self->SetRefreshInterval(60); + return PatchesBlock->new($Collection, $EnclosingPage); }
-sub SortKeys($$$) +sub DisplayProperty($$) { - my ($self, $CollectionBlock, $Keys) = @_; - - my @SortedKeys = sort { $b <=> $a } @$Keys; - return @SortedKeys; -} - -sub DisplayProperty($$$) -{ - my ($self, $CollectionBlock, $PropertyDescriptor) = @_; + my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName();
@@ -54,21 +46,9 @@ sub DisplayProperty($$$) $PropertyName eq "FromName" || $PropertyName eq "Subject"; }
-sub GetItemActions($$) -{ - #my ($self, $CollectionBlock) = @_; - return []; -} - -sub GetActions($$) -{ - #my ($self, $CollectionBlock) = @_; - return []; -} - sub GenerateDataCell($$$$$) { - my ($self, $CollectionBlock, $Item, $PropertyDescriptor, $DetailsPage) = @_; + my ($self, $Item, $PropertyDescriptor, $DetailsPage) = @_;
my $PropertyName = $PropertyDescriptor->GetName(); if ($PropertyName eq "Disposition" and $Item->Disposition =~ /job ([0-9]+)$/) @@ -80,14 +60,29 @@ sub GenerateDataCell($$$$$) } else { - $self->SUPER::GenerateDataCell($CollectionBlock, $Item, $PropertyDescriptor, $DetailsPage); + $self->SUPER::GenerateDataCell($Item, $PropertyDescriptor, $DetailsPage); } }
+sub GetItemActions($) +{ + #my ($self) = @_; + return []; +} + +sub GetActions($) +{ + #my ($self) = @_; + return []; +} +
package main;
-my $Request = shift; +use ObjectModel::CGI::SimpleCollectionPage; +use WineTestBot::Patches;
-my $PatchesListPage = PatchesListPage->new($Request, ""); -$PatchesListPage->GeneratePage(); +my $Request = shift; +my $Page = ObjectModel::CGI::SimpleCollectionPage->new($Request, "", CreatePatches(), &PatchesBlock::Create); +$Page->SetRefreshInterval(60); +$Page->GeneratePage();