Handle SKIPPED state better

The SKIPPED results have a fake URL and no run-time.

Make the run-time part of the match optional so we start matching
these lines.

Because the URL is fake, null the result for SKIPPED matches so the
job name won't be a link to nowhere.

Put a secondary-color span around the job name in the null case so
it's a bit more obvious it was skipped.

A weird thing with the CSS matchers is that "first-child" doesn't work
with the templating "dom-if" we use.  "first-child" seems to refer to
the "if={{job.link}}" template tag -- so it works when job.link is
defined, but when it is not, the "if={{!job.link}}" *isn't* the first
child, despite being the only thing displayed.  Anyway,
"first-of-type" seems more like what we want -- the first <td> element
no matter what ... that should always be the first column.  Update
that match.

Change-Id: I5c3bed85d7f64cd0890757237f93d13406c33788
diff --git a/zuul-results-summary/zuul-results-summary.js b/zuul-results-summary/zuul-results-summary.js
index de8f899..f8160db 100644
--- a/zuul-results-summary/zuul-results-summary.js
+++ b/zuul-results-summary/zuul-results-summary.js
@@ -57,8 +57,8 @@
       color: var(--primary-text-color, rgb(33, 33, 33));
     }
 
-    thead tr th:first-child,
-    tbody tr td:first-child {
+    thead tr th:first-of-type,
+    tbody tr td:first-of-type {
      padding-left: 12px;
     }
 
@@ -140,7 +140,7 @@
      <template is="dom-repeat" items="[[item.results]]" as="job">
       <tr>
        <template is="dom-if" if="{{job.link}}"><td><a href="{{job.link}}">[[job.job]]</a></td></template>
-       <template is="dom-if" if="{{!job.link}}"><td><a>[[job.job]]</a></td></template>
+       <template is="dom-if" if="{{!job.link}}"><td><span style="color: var(--secondary-text-color)">[[job.job]]</span></td></template>
        <td><span class$="status-[[job.result]]">[[job.result]]</span></td>
        <td>[[job.time]]</td>
       </tr>
@@ -262,10 +262,17 @@
       //   - openstack-tox-py35 http://... : SUCCESS in 2m 45
       const results = [];
       const lines = message.message.split('\n');
-      const resultRe = /^- (?<job>[^ ]+) (?:(?<link>https?:\/\/[^ ]+)|[^ ]+) : (?<result>[^ ]+) in (?<time>.*)/;
+      const resultRe = /^- (?<job>[^ ]+) (?:(?<link>https?:\/\/[^ ]+)|[^ ]+) : (?<result>[^ ]+)( in (?<time>.*))?/;
       lines.forEach(line => {
         const result = resultRe.exec(line);
-        if (result) {
+          if (result) {
+            // Note SKIPPED jobs have no time and an invalid placeholder
+            // URL.  Since there's no point linking this URL, null
+            // that match out and it will just use the job name but not
+            // make it a <a>.
+            if (result.groups.result === "SKIPPED") {
+              result.groups.link = null;
+            }
           results.push(result.groups);
         }
       });