The main page still depended on the pre-datetime.js ShowDateTime() JavaScript function, which the new one is not compatible with. Add GenerateTipDateTime() so a timestamp can easily be added as a tooltip to an arbitrary HTML chunk. Tweak the column title to better reflect its content (contrast duration with elapsed time).
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- The tooltip for this column was in fact broken by commit 78f2c0fd53ea "Handle the timestamp formatting in ValueFormatter".
This is because the main page was implicitly depending on the ShowDateTime() JavaScript function defined by the collection block. However that commit changed the way ShowDateTime() works, making it incompatible with the main page. What masked the issue is the fallback plain-HTML case. It just caused the completion timestamps to be shown in the server's timezone instead of the user's.
Also this is a case where the formatting cannot usefully be delegated to DisplayProperty() because this actually makes use of two different values: - The timestamp to be shown as the tooltip. - And a totally unrelated value to be shown as the base text (here the elapsed time from job submission to completion).
The framework and GenerateValueHTML() could be extended to expect two values for the 'tipdatetime' format but this would require providing a way to override a column's default value (or providing a custom GetPropertyValue() implementation in FormPage's case) which would be no simpler nor maintainable than simply doing it in Generate{Data,Value}View(). --- testbot/lib/ObjectModel/CGI/ValueFormatter.pm | 47 ++++++++++++++++++- testbot/web/WineTestBot.css | 1 + testbot/web/index.pl | 12 ++--- testbot/web/js/datetime.js | 19 ++++++-- 4 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/testbot/lib/ObjectModel/CGI/ValueFormatter.pm b/testbot/lib/ObjectModel/CGI/ValueFormatter.pm index 638504d32..d987cee55 100644 --- a/testbot/lib/ObjectModel/CGI/ValueFormatter.pm +++ b/testbot/lib/ObjectModel/CGI/ValueFormatter.pm @@ -22,7 +22,7 @@ use strict; package ObjectModel::CGI::ValueFormatter;
use Exporter 'import'; -our @EXPORT = qw(GetDateTimeJSFile GenerateDateTime +our @EXPORT = qw(GetDateTimeJSFile GenerateDateTime GenerateTipDateTime GenerateTimeTipDate GenerateValueHTML);
use POSIX qw(strftime); @@ -106,6 +106,51 @@ sub GenerateDateTime($;$$) =pod =over 12
+=item C<GenerateTipDateTime()> + +Adds a tooltip containing the timestamp to the specified HTML chunk. + +The timestamp is converted to the ISO 8601 format in the user's timezone if +JavaScript is available and in the server's timezone otherwise. + +The default for TagAttrs is 'a' and it should always be a tag that shows the +content of the title attribute as a tooltip. + +See GenerateDateTime() for more details. + +=back +=cut + +sub GenerateTipDateTime($$;$$) +{ + my ($Sec1970, $Html, $Class, $TagAttrs) = @_; + + if (defined $Sec1970) + { + my $Tag; + if ($TagAttrs) + { + $Tag = $TagAttrs; + $Tag =~ s/ .*$//; + } + else + { + $TagAttrs = $Tag = "a"; + } + $Class = "$Class " if ($Class); + print "<$TagAttrs class='${Class}tipdatetime' timestamp='$Sec1970' ", + strftime("title='%Y-%m-%d %H:%M:%S'>", localtime($Sec1970)), + "$Html</$Tag>"; + } + else + { + print $Html; + } +} + +=pod +=over 12 + =item C<GenerateTimeTipDate()>
Show the timestamp's time with the date as a tooltip. diff --git a/testbot/web/WineTestBot.css b/testbot/web/WineTestBot.css index 0955f58cf..350ab64a4 100644 --- a/testbot/web/WineTestBot.css +++ b/testbot/web/WineTestBot.css @@ -408,6 +408,7 @@ pre .log-fullnew { color: red; font-weight: bold; }
a.title { color:inherit; text-decoration: none; } +a.tipdatetime { color:inherit; text-decoration: none; } a.timetipdate { color:inherit; text-decoration: none; }
th.Record { text-align: center; } diff --git a/testbot/web/index.pl b/testbot/web/index.pl index 4048cacd3..b07b39d22 100644 --- a/testbot/web/index.pl +++ b/testbot/web/index.pl @@ -25,7 +25,7 @@ package JobStatusBlock; use ObjectModel::CGI::CollectionBlock; our @ISA = qw(ObjectModel::CGI::CollectionBlock);
-use POSIX qw(strftime); +use ObjectModel::CGI::ValueFormatter;
use WineTestBot::Branches; use WineTestBot::Users; @@ -65,7 +65,7 @@ sub GenerateHeaderView($$$) } elsif ($PropertyName eq "Ended") { - print "<a class='title' title='Ended'>Time</a>"; + print "<a class='title' title='Completion timestamp'>Elapsed</a>"; } else { @@ -156,13 +156,7 @@ sub GenerateDataView($$$) if (defined $Job->Ended) { my $Duration = $Job->Ended - $Job->Submitted; - my $TagId = "E". $Job->Id; - print "<a id='$TagId' class='title' title='", - strftime("%Y-%m-%d %H:%M:%S", localtime($Job->Ended)), - "'>", DurationToString($Duration), "</a>\n"; - print "<script type='text/javascript'><!--\n"; - print " ShowDateTime(", $Job->Ended, ",'$TagId');\n"; - print "--></script>"; + GenerateTipDateTime($Job->Ended, DurationToString($Duration)); } else { diff --git a/testbot/web/js/datetime.js b/testbot/web/js/datetime.js index 47b0feb0f..23b7b2718 100644 --- a/testbot/web/js/datetime.js +++ b/testbot/web/js/datetime.js @@ -23,13 +23,21 @@ function Pad2(n) return n < 10 ? '0' + n : n; }
-function ShowDateTime(dom) +function ShowDateTime(dom, attr) { const sec1970 = dom.getAttribute("timestamp"); const dt = new Date(sec1970 * 1000); - dom.innerHTML = dt.getFullYear() +'-'+ Pad2(dt.getMonth() + 1) +'-'+ - Pad2(dt.getDate()) +' '+ Pad2(dt.getHours()) +':'+ - Pad2(dt.getMinutes()) +':'+ Pad2(dt.getSeconds()) + const pretty = dt.getFullYear() +'-'+ Pad2(dt.getMonth() + 1) +'-'+ + Pad2(dt.getDate()) +' '+ Pad2(dt.getHours()) +':'+ + Pad2(dt.getMinutes()) +':'+ Pad2(dt.getSeconds()); + if (attr == null) + { + dom.innerHTML = pretty; + } + else + { + dom.setAttribute(attr, pretty); + } }
function ShowTimeTipDate(dom) @@ -47,6 +55,9 @@ function init() document.querySelectorAll(".datetime").forEach(dom => { ShowDateTime(dom); }); + document.querySelectorAll(".tipdatetime").forEach(dom => { + ShowDateTime(dom, 'title'); + }); document.querySelectorAll(".timetipdate").forEach(dom => { ShowTimeTipDate(dom); });