Convert gr-group-list to lit element

Change-Id: Ie2d36ab8f9b0524d89a50be362393d23da91caf8
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.ts b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.ts
index a367969..c2480fc 100644
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.ts
+++ b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.ts
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import '../../../styles/shared-styles';
-import '../../../styles/gr-form-styles';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-group-list_html';
+
 import {GerritNav} from '../../core/gr-navigation/gr-navigation';
-import {customElement, property} from '@polymer/decorators';
 import {GroupInfo, GroupId} from '../../../types/common';
 import {appContext} from '../../../services/app-context';
+import {formStyles} from '../../../styles/gr-form-styles';
+import {sharedStyles} from '../../../styles/shared-styles';
+import {GrLitElement} from '../../lit/gr-lit-element';
+import {css, customElement, html, internalProperty} from 'lit-element';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -29,13 +29,9 @@
   }
 }
 @customElement('gr-group-list')
-export class GrGroupList extends PolymerElement {
-  static get template() {
-    return htmlTemplate;
-  }
-
-  @property({type: Array})
-  _groups: GroupInfo[] = [];
+export class GrGroupList extends GrLitElement {
+  @internalProperty()
+  protected _groups: GroupInfo[] = [];
 
   private readonly restApiService = appContext.restApiService;
 
@@ -48,8 +44,54 @@
     });
   }
 
-  _computeVisibleToAll(group: GroupInfo) {
-    return group.options && group.options.visible_to_all ? 'Yes' : 'No';
+  static get styles() {
+    return [
+      sharedStyles,
+      formStyles,
+      css`
+        #groups .nameColumn {
+          min-width: 11em;
+          width: auto;
+        }
+        .descriptionHeader {
+          min-width: 21.5em;
+        }
+        .visibleCell {
+          text-align: center;
+          width: 6em;
+        }
+      `,
+    ];
+  }
+
+  render() {
+    return html` <div class="gr-form-styles">
+      <table id="groups">
+        <thead>
+          <tr>
+            <th class="nameHeader">Name</th>
+            <th class="descriptionHeader">Description</th>
+            <th class="visibleCell">Visible to all</th>
+          </tr>
+        </thead>
+        <tbody>
+          ${(this._groups ?? []).map(group => {
+            const href = this._computeGroupPath(group);
+            return html`
+              <tr>
+                <td class="nameColumn">
+                  <a href="${href}"> ${group.name} </a>
+                </td>
+                <td>${group.description}</td>
+                <td class="visibleCell">
+                  ${group?.options?.visible_to_all ? 'Yes' : 'No'}
+                </td>
+              </tr>
+            `;
+          })}
+        </tbody>
+      </table>
+    </div>`;
   }
 
   _computeGroupPath(group: GroupInfo) {
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_html.ts b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_html.ts
deleted file mode 100644
index 5f98a82..0000000
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_html.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
-  <style include="shared-styles">
-    /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
-  </style>
-  <style include="gr-form-styles">
-    #groups .nameColumn {
-      min-width: 11em;
-      width: auto;
-    }
-    .descriptionHeader {
-      min-width: 21.5em;
-    }
-    .visibleCell {
-      text-align: center;
-      width: 6em;
-    }
-  </style>
-  <div class="gr-form-styles">
-    <table id="groups">
-      <thead>
-        <tr>
-          <th class="nameHeader">Name</th>
-          <th class="descriptionHeader">Description</th>
-          <th class="visibleCell">Visible to all</th>
-        </tr>
-      </thead>
-      <tbody>
-        <template is="dom-repeat" items="[[_groups]]">
-          <tr>
-            <td class="nameColumn">
-              <a href$="[[_computeGroupPath(item)]]"> [[item.name]] </a>
-            </td>
-            <td>[[item.description]]</td>
-            <td class="visibleCell">[[_computeVisibleToAll(item)]]</td>
-          </tr>
-        </template>
-      </tbody>
-    </table>
-  </div>
-`;
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.ts b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.ts
index aa964ad..3dce295 100644
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.ts
@@ -63,7 +63,9 @@
     });
   });
 
-  test('renders', () => {
+  test('renders', async () => {
+    await flush();
+
     const rows = Array.from(queryAll(element, 'tbody tr'));
 
     assert.equal(rows.length, 3);
@@ -77,11 +79,6 @@
     assert.equal(nameCells[2], 'Group 3');
   });
 
-  test('_computeVisibleToAll', () => {
-    assert.equal(element._computeVisibleToAll(groups[0]), 'No');
-    assert.equal(element._computeVisibleToAll(groups[1]), 'Yes');
-  });
-
   test('_computeGroupPath', () => {
     let urlStub = sinon
       .stub(GerritNav, 'getUrlForGroup')
diff --git a/polygerrit-ui/app/styles/gr-form-styles.ts b/polygerrit-ui/app/styles/gr-form-styles.ts
index f58a02c..a2a4bab 100644
--- a/polygerrit-ui/app/styles/gr-form-styles.ts
+++ b/polygerrit-ui/app/styles/gr-form-styles.ts
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+import {css} from 'lit-element';
+
 // Mark the file as a module. Otherwise typescript assumes this is a script
 // and $_documentContainer is a global variable.
 // See: https://www.typescriptlang.org/docs/handbook/modules.html
@@ -22,103 +24,107 @@
 
 const $_documentContainer = document.createElement('template');
 
+export const formStyles = css`
+  .gr-form-styles input {
+    background-color: var(--view-background-color);
+    color: var(--primary-text-color);
+  }
+  .gr-form-styles select {
+    background-color: var(--select-background-color);
+    color: var(--primary-text-color);
+  }
+  .gr-form-styles h1,
+  .gr-form-styles h2 {
+    margin-bottom: var(--spacing-s);
+  }
+  .gr-form-styles h4 {
+    font-weight: var(--font-weight-bold);
+  }
+  .gr-form-styles fieldset {
+    border: none;
+    margin-bottom: var(--spacing-xxl);
+  }
+  .gr-form-styles section {
+    display: flex;
+    margin: var(--spacing-s) 0;
+    min-height: 2em;
+  }
+  .gr-form-styles section * {
+    vertical-align: middle;
+  }
+  .gr-form-styles .title,
+  .gr-form-styles .value {
+    display: inline-block;
+  }
+  .gr-form-styles .title {
+    color: var(--deemphasized-text-color);
+    font-weight: var(--font-weight-bold);
+    padding-right: var(--spacing-m);
+    width: 15em;
+  }
+  .gr-form-styles th {
+    color: var(--deemphasized-text-color);
+    text-align: left;
+    vertical-align: bottom;
+  }
+  .gr-form-styles td,
+  .gr-form-styles tfoot th {
+    padding: var(--spacing-s) 0;
+    vertical-align: middle;
+  }
+  .gr-form-styles .emptyHeader {
+    text-align: right;
+  }
+  .gr-form-styles table {
+    width: 50em;
+  }
+  .gr-form-styles th:first-child,
+  .gr-form-styles td:first-child {
+    width: 15em;
+  }
+  .gr-form-styles th:first-child input,
+  .gr-form-styles td:first-child input {
+    width: 14em;
+  }
+  .gr-form-styles input:not([type='checkbox']),
+  .gr-form-styles select,
+  .gr-form-styles textarea {
+    border: 1px solid var(--border-color);
+    border-radius: var(--border-radius);
+    padding: var(--spacing-s);
+  }
+  .gr-form-styles td:last-child {
+    width: 5em;
+  }
+  .gr-form-styles th:last-child gr-button,
+  .gr-form-styles td:last-child gr-button {
+    width: 100%;
+  }
+  .gr-form-styles iron-autogrow-textarea {
+    height: auto;
+    min-height: 4em;
+  }
+  .gr-form-styles gr-autocomplete {
+    width: 14em;
+  }
+  @media only screen and (max-width: 40em) {
+    .gr-form-styles section {
+      margin-bottom: var(--spacing-l);
+    }
+    .gr-form-styles .title,
+    .gr-form-styles .value {
+      display: block;
+    }
+    .gr-form-styles table {
+      width: 100%;
+    }
+  }
+`;
+
 $_documentContainer.innerHTML = `<dom-module id="gr-form-styles">
   <template>
     <style>
-      .gr-form-styles input {
-        background-color: var(--view-background-color);
-        color: var(--primary-text-color);
-      }
-      .gr-form-styles select {
-        background-color: var(--select-background-color);
-        color: var(--primary-text-color);
-      }
-      .gr-form-styles h1,
-      .gr-form-styles h2 {
-        margin-bottom: var(--spacing-s);
-      }
-      .gr-form-styles h4 {
-        font-weight: var(--font-weight-bold);
-      }
-      .gr-form-styles fieldset {
-        border: none;
-        margin-bottom: var(--spacing-xxl);
-      }
-      .gr-form-styles section {
-        display: flex;
-        margin: var(--spacing-s) 0;
-        min-height: 2em;
-      }
-      .gr-form-styles section * {
-        vertical-align: middle;
-      }
-      .gr-form-styles .title,
-      .gr-form-styles .value {
-        display: inline-block;
-      }
-      .gr-form-styles .title {
-        color: var(--deemphasized-text-color);
-        font-weight: var(--font-weight-bold);
-        padding-right: var(--spacing-m);
-        width: 15em;
-      }
-      .gr-form-styles th {
-        color: var(--deemphasized-text-color);
-        text-align: left;
-        vertical-align: bottom;
-      }
-      .gr-form-styles td,
-      .gr-form-styles tfoot th {
-        padding: var(--spacing-s) 0;
-        vertical-align: middle;
-      }
-      .gr-form-styles .emptyHeader {
-        text-align: right;
-      }
-      .gr-form-styles table {
-        width: 50em;
-      }
-      .gr-form-styles th:first-child,
-      .gr-form-styles td:first-child {
-        width: 15em;
-      }
-      .gr-form-styles th:first-child input,
-      .gr-form-styles td:first-child input {
-        width: 14em;
-      }
-      .gr-form-styles input:not([type="checkbox"]),
-      .gr-form-styles select,
-      .gr-form-styles textarea {
-        border: 1px solid var(--border-color);
-        border-radius: var(--border-radius);
-        padding: var(--spacing-s);
-      }
-      .gr-form-styles td:last-child {
-        width: 5em;
-      }
-      .gr-form-styles th:last-child gr-button,
-      .gr-form-styles td:last-child gr-button {
-        width: 100%;
-      }
-      .gr-form-styles iron-autogrow-textarea {
-        height: auto;
-        min-height: 4em;
-      }
-      .gr-form-styles gr-autocomplete {
-        width: 14em;
-      }
-      @media only screen and (max-width: 40em) {
-        .gr-form-styles section {
-          margin-bottom: var(--spacing-l);
-        }
-        .gr-form-styles .title,
-        .gr-form-styles .value {
-          display: block;
-        }
-        .gr-form-styles table {
-          width: 100%;
-        }
-      }
+    ${formStyles.cssText}
     </style>
   </template>
 </dom-module>`;