<commit_before>// Copyright 2021 The LUCI Authors.
//
// 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 '@material/mwc-button';
import '@material/mwc-dialog';
import '@material/mwc-icon';
import { MobxLitElement } from '@adobe/lit-mobx';
import { css, customElement, html } from 'lit-element';
import { observable } from 'mobx';

import { consumeTestHistoryPageState, TestHistoryPageState } from '../../../context/test_history_page_state';
import { consumer } from '../../../libs/context';
import commonStyle from '../../../styles/common_style.css';

@customElement('milo-thdt-config-widget')
@consumer
export class TestHistoryDetailsTableConfigWidgetElement extends MobxLitElement {
  @observable.ref
  @consumeTestHistoryPageState()
  pageState!: TestHistoryPageState;

  // These properties are frequently updated.
  // Don't set them as observables so updating them won't have big performance
  // impact.
  private uncommittedColumnKeys: readonly string[] = [];
  private uncommittedSortingKeys: readonly string[] = [];

  @observable.ref private showTableConfigDialog = false;

  private renderPropKeysConfigRow(label: string, keys: readonly string[], updateKeys: (newKeys: string[]) => void) {
    return html`
      <tr>
        <td>${label}:</td>
        <td>
          <input
            .value=${keys.join(', ')}
            placeholder="A list of comma-separated property keys (e.g. v.test_suite,v.gpu)."
            @input=${(e: InputEvent) => {
              const newKeys = (e.target as HTMLInputElement).value
                .split(',')
                .map((k) => k.trim())
                .filter((k) => k !== '');
              updateKeys(newKeys);
            }}
          />
        </td>
      </tr>
    `;
  }

  protected render() {
    return html`
      <div
        id="configure-table"
        class="filters-container"
        @click=${() => {
          this.uncommittedColumnKeys = this.pageState.columnKeys;
          this.uncommittedSortingKeys = this.pageState.sortingKeys;
          this.showTableConfigDialog = true;
        }}
      >
        <mwc-icon class="inline-icon">table_chart</mwc-icon>
        <span>Configure Table</span>
      </div>
      <mwc-dialog
        id="table-config-dialog"
        heading="Table Configuration"
        ?open=${this.showTableConfigDialog}
        @closed=${(event: CustomEvent<{ action: string }>) => {
          if (event.detail.action === 'apply') {
            this.pageState.setColumnKeys(this.uncommittedColumnKeys);
            this.pageState.setSortingKeys(this.uncommittedSortingKeys);
          }
          this.showTableConfigDialog = false;
        }}
      >
        <table>
          ${this.renderPropKeysConfigRow(
            'Additional columns',
            this.uncommittedColumnKeys,
            (newKeys) => (this.uncommittedColumnKeys = newKeys)
          )}
          ${this.renderPropKeysConfigRow(
            'Sort by',
            this.uncommittedSortingKeys,
            (newKeys) => (this.uncommittedSortingKeys = newKeys)
          )}
          </tr>
        </table>
        <mwc-button
          id="reset-table-config"
          dense
          unelevated
          @click=${() => {
            this.uncommittedColumnKeys = this.pageState.defaultColumnKeys;
            this.uncommittedSortingKeys = this.pageState.defaultSortingKeys;

            // this.uncommittedXXXKeys are not observables.
            // Manually trigger an updated.
            this.update(new Map());
          }}
        >
          Reset to default
        </mwc-button>
        <p>A key must be one of the following:</p>
        <ol>
          <li>'status': status of the test variant (e.g. Unexpected, Flaky).</li>
          <li>'name': name of the test variant.</li>
          <li>'v.{variant_key}': variant key of the test variant (e.g. v.gpu).</li>
        </ol>
        <p>Sorting keys can have '-' prefix to sort in descending order (e.g. -status, -v.gpu).</p>
        <!-- TODO(weiweilin): add link to a more detailed instruction. -->
        <mwc-button slot="primaryAction" dialogAction="apply" dense unelevated>Apply</mwc-button>
        <mwc-button slot="secondaryAction" dialogAction="cancel">Cancel</mwc-button>
      </mwc-dialog>
`;
  }

  static styles = [
    commonStyle,
    css`
      #configure-table {
        cursor: pointer;
        line-height: 24px;
        color: var(--active-text-color);
      }

      #table-config-dialog {
        --mdc-dialog-min-width: 700px;
      }
      #table-config-dialog table {
        width: 100%;
      }
      #table-config-dialog table td:first-child {<commit_msg>[milo][history] remove unsupported column from config instructions<commit_after>// Copyright 2021 The LUCI Authors.
//
// 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 '@material/mwc-button';
import '@material/mwc-dialog';
import '@material/mwc-icon';
import { MobxLitElement } from '@adobe/lit-mobx';
import { css, customElement, html } from 'lit-element';
import { observable } from 'mobx';

import { consumeTestHistoryPageState, TestHistoryPageState } from '../../../context/test_history_page_state';
import { consumer } from '../../../libs/context';
import commonStyle from '../../../styles/common_style.css';

@customElement('milo-thdt-config-widget')
@consumer
export class TestHistoryDetailsTableConfigWidgetElement extends MobxLitElement {
  @observable.ref
  @consumeTestHistoryPageState()
  pageState!: TestHistoryPageState;

  // These properties are frequently updated.
  // Don't set them as observables so updating them won't have big performance
  // impact.
  private uncommittedColumnKeys: readonly string[] = [];
  private uncommittedSortingKeys: readonly string[] = [];

  @observable.ref private showTableConfigDialog = false;

  private renderPropKeysConfigRow(label: string, keys: readonly string[], updateKeys: (newKeys: string[]) => void) {
    return html`
      <tr>
        <td>${label}:</td>
        <td>
          <input
            .value=${keys.join(', ')}
            placeholder="A list of comma-separated property keys (e.g. v.test_suite,v.gpu)."
            @input=${(e: InputEvent) => {
              const newKeys = (e.target as HTMLInputElement).value
                .split(',')
                .map((k) => k.trim())
                .filter((k) => k !== '');
              updateKeys(newKeys);
            }}
          />
        </td>
      </tr>
    `;
  }

  protected render() {
    return html`
      <div
        id="configure-table"
        class="filters-container"
        @click=${() => {
          this.uncommittedColumnKeys = this.pageState.columnKeys;
          this.uncommittedSortingKeys = this.pageState.sortingKeys;
          this.showTableConfigDialog = true;
        }}
      >
        <mwc-icon class="inline-icon">table_chart</mwc-icon>
        <span>Configure Table</span>
      </div>
      <mwc-dialog
        id="table-config-dialog"
        heading="Table Configuration"
        ?open=${this.showTableConfigDialog}
        @closed=${(event: CustomEvent<{ action: string }>) => {
          if (event.detail.action === 'apply') {
            this.pageState.setColumnKeys(this.uncommittedColumnKeys);
            this.pageState.setSortingKeys(this.uncommittedSortingKeys);
          }
          this.showTableConfigDialog = false;
        }}
      >
        <table>
          ${this.renderPropKeysConfigRow(
            'Additional columns',
            this.uncommittedColumnKeys,
            (newKeys) => (this.uncommittedColumnKeys = newKeys)
          )}
          ${this.renderPropKeysConfigRow(
            'Sort by',
            this.uncommittedSortingKeys,
            (newKeys) => (this.uncommittedSortingKeys = newKeys)
          )}
          </tr>
        </table>
        <mwc-button
          id="reset-table-config"
          dense
          unelevated
          @click=${() => {
            this.uncommittedColumnKeys = this.pageState.defaultColumnKeys;
            this.uncommittedSortingKeys = this.pageState.defaultSortingKeys;

            // this.uncommittedXXXKeys are not observables.
            // Manually trigger an updated.
            this.update(new Map());
          }}
        >
          Reset to default
        </mwc-button>
        <p>A key must be one of the following:</p>
        <ol>
          <li>'status': status of the test variant (e.g. Unexpected, Flaky).</li>
          <li>'v.{variant_key}': variant key of the test variant (e.g. v.gpu).</li>
        </ol>
        <p>Sorting keys can have '-' prefix to sort in descending order (e.g. -status, -v.gpu).</p>
        <!-- TODO(weiweilin): add link to a more detailed instruction. -->
        <mwc-button slot="primaryAction" dialogAction="apply" dense unelevated>Apply</mwc-button>
        <mwc-button slot="secondaryAction" dialogAction="cancel">Cancel</mwc-button>
      </mwc-dialog>
`;
  }

  static styles = [
    commonStyle,
    css`
      #configure-table {
        cursor: pointer;
        line-height: 24px;
        color: var(--active-text-color);
      }

      #table-config-dialog {
        --mdc-dialog-min-width: 700px;
      }
      #table-config-dialog table {
        width: 100%;
      }
      #table-config-dialog table td:first-child {
{'fraction_non_alphanumeric': 0.1295826833073323, 'fraction_numerical': 0.0031201248049922, 'mean_word_length': 2.2864466517141944, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5222214', 'n_tokens_mistral': 2960, 'n_tokens_neox': 2877, 'n_words': 716}