github.com/GoogleCloudPlatform/testgrid@v0.0.174/web/src/testgrid-group-summary.ts (about)

     1  import { LitElement, html, css } from 'lit';
     2  import { customElement, property, state } from 'lit/decorators.js';
     3  import { ListDashboardSummariesResponse } from './gen/pb/api/v1/data';
     4  import { DashboardSummary } from './gen/pb/api/v1/data';
     5  import { map } from 'lit/directives/map.js';
     6  import { TabStatusIcon } from './testgrid-dashboard-summary';
     7  
     8  /**
     9   * RenderedDashboardSummary defines the dashboard summary representation required for rendering
    10   */
    11  interface RenderedDashboardSummary {
    12    name: string;
    13    overallStatus: string;
    14    icon: string;
    15    tabDescription: string;
    16  }
    17  
    18  @customElement('testgrid-group-summary')
    19  export class TestgridGroupSummary extends LitElement {
    20  
    21    @property({ type: String })
    22    groupName = '';
    23  
    24    @state()
    25    dashboardSummaries: RenderedDashboardSummary[] = [];
    26  
    27    render() {
    28      return html`
    29        <link
    30          rel="stylesheet"
    31          href="https://fonts.googleapis.com/icon?family=Material+Icons"
    32        />
    33        <table>
    34          <thead>
    35            <tr>
    36              <th>Status</th>
    37              <th>Dashboard</th>
    38              <th>Health</th>
    39            </tr>
    40          </thead>
    41          <tbody>
    42            ${map(this.dashboardSummaries,
    43              (ds: RenderedDashboardSummary) => html`
    44                <tr>
    45                  <td><i class="material-icons ${ds.overallStatus}">${ds.icon}</i></td>
    46                  <td>${ds.name}</td>
    47                  <td>${ds.tabDescription}</td>
    48                </tr>
    49              `)}
    50          </tbody>
    51        </table>
    52      `;
    53    }
    54  
    55    connectedCallback() {
    56      super.connectedCallback();
    57      this.fetchDashboardSummaries();
    58    }
    59  
    60    private async fetchDashboardSummaries() {
    61      try {
    62        const response = await fetch(
    63          `http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboard-groups/${this.groupName}/dashboard-summaries`
    64        );
    65        if (!response.ok) {
    66          throw new Error(`HTTP error: ${response.status}`);
    67        }
    68        const data = ListDashboardSummariesResponse.fromJson(await response.json());
    69        var summaries: RenderedDashboardSummary[] = [];
    70        data.dashboardSummaries.forEach(summary => summaries.push(this.convertResponse(summary)));
    71        this.dashboardSummaries = summaries;
    72      } catch (error) {
    73        console.error(`Could not get grid rows: ${error}`);
    74      }
    75    }
    76  
    77    private convertResponse(summary: DashboardSummary){
    78      const sortedStatuses: string[] = [
    79        "PASSING",
    80        "ACCEPTABLE",
    81        "FLAKY",
    82        "FAILING",
    83        "STALE",
    84        "BROKEN",
    85        "PENDING"
    86      ]
    87  
    88      var numPassing = 0;
    89      var total = 0;
    90      for (const key in summary.tabStatusCount){
    91        if (key === "PASSING"){
    92          numPassing = summary.tabStatusCount[key];
    93        }
    94        total += summary.tabStatusCount[key];
    95      }
    96  
    97      var prefix = `${numPassing} / ${total} PASSING`;
    98      var descriptions: string [] = [];
    99      sortedStatuses.forEach(status => {
   100        if (summary.tabStatusCount[status] > 0){
   101          descriptions.push(`${summary.tabStatusCount[status]} ${status}`);
   102        }
   103      });
   104  
   105      if (descriptions.length >0){
   106        prefix += " ("+ descriptions.join(", ") +")";
   107      }
   108  
   109      const rds: RenderedDashboardSummary = {
   110        name: summary.name,
   111        overallStatus: summary.overallStatus,
   112        icon: TabStatusIcon.get(summary.overallStatus)!,
   113        tabDescription: prefix
   114      };
   115  
   116      return rds;
   117    }
   118  
   119    static styles = css`
   120  
   121      body{
   122        font-size: 12px;
   123      }
   124  
   125      .material-icons{
   126        font-size: 2em;
   127      }
   128  
   129      th, td {
   130        padding: 0.5em 2em;
   131      }
   132  
   133      thead{
   134        background-color: #e0e0e0;
   135      }
   136  
   137      table {
   138        border-radius: 6px;
   139        border: 1px solid #cbcbcb;
   140        border-spacing: 0;
   141      }
   142  
   143      .PENDING {
   144        color: #cc8200;
   145      }
   146  
   147      .PASSING {
   148        color: #0c3;
   149      }
   150  
   151      .FAILING {
   152        color: #a00;
   153      }
   154  
   155      .FLAKY {
   156        color: #609;
   157      }
   158  
   159      .ACCEPTABLE {
   160        color: #39a2ae;
   161      }
   162  
   163      .STALE {
   164        color: #808b96;
   165      }
   166  
   167      .BROKEN {
   168        color: #000;
   169      }
   170    `;
   171  }