[tools 5/5] testbot/web: Fix and share the main page's job completion date formatting.

Francois Gouget fgouget at codeweavers.com
Mon Apr 25 13:50:49 CDT 2022


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 at 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);
     });
-- 
2.30.2



More information about the wine-devel mailing list