Dave Borowitz | 8cdc76b | 2018-03-26 10:04:27 -0400 | [diff] [blame] | 1 | /** |
| 2 | * @license |
Ben Rohlfs | 94fcbbc | 2022-05-27 10:45:03 +0200 | [diff] [blame] | 3 | * Copyright 2016 Google LLC |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
Dave Borowitz | 8cdc76b | 2018-03-26 10:04:27 -0400 | [diff] [blame] | 5 | */ |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 6 | import '../../shared/gr-button/gr-button'; |
Dhruv Srivastava | e77b66c | 2020-12-23 11:44:13 +0100 | [diff] [blame] | 7 | import {ServerInfo} from '../../../types/common'; |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 8 | import {LitElement, css, html} from 'lit'; |
Frank Borden | 42c1a45 | 2022-08-11 16:27:20 +0200 | [diff] [blame] | 9 | import {customElement, property, state} from 'lit/decorators.js'; |
Milutin Kristofic | 4aa368a | 2022-04-05 20:49:37 +0200 | [diff] [blame] | 10 | import {sharedStyles} from '../../../styles/shared-styles'; |
Milutin Kristofic | aa1c08b | 2023-09-06 10:34:16 +0200 | [diff] [blame] | 11 | import {grFormStyles} from '../../../styles/gr-form-styles'; |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 12 | import {fire} from '../../../utils/event-util'; |
| 13 | import {ValueChangedEvent} from '../../../types/events'; |
Dhruv | 980b910 | 2022-05-05 14:22:24 +0200 | [diff] [blame] | 14 | import {ColumnNames} from '../../../constants/constants'; |
Dhruv Srivastava | efe10d9c | 2022-06-28 12:22:48 +0200 | [diff] [blame] | 15 | import {subscribe} from '../../lit/subscription-controller'; |
| 16 | import {resolve} from '../../../models/dependency'; |
| 17 | import {configModelToken} from '../../../models/config/config-model'; |
brohlfs | bb5a93a | 2021-08-27 22:23:46 +0200 | [diff] [blame] | 18 | |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 19 | @customElement('gr-change-table-editor') |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 20 | export class GrChangeTableEditor extends LitElement { |
| 21 | @property({type: Array}) |
Ben Rohlfs | 819aad0 | 2021-03-08 16:34:26 +0100 | [diff] [blame] | 22 | displayedColumns: string[] = []; |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 23 | |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 24 | @property({type: Boolean}) |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 25 | showNumber?: boolean; |
| 26 | |
Dhruv Srivastava | e77b66c | 2020-12-23 11:44:13 +0100 | [diff] [blame] | 27 | @property({type: Array}) |
Ben Rohlfs | f3f83a5 | 2023-08-23 10:49:12 +0200 | [diff] [blame] | 28 | defaultColumns: string[] = Object.values(ColumnNames); |
Dhruv Srivastava | e77b66c | 2020-12-23 11:44:13 +0100 | [diff] [blame] | 29 | |
Dhruv Srivastava | efe10d9c | 2022-06-28 12:22:48 +0200 | [diff] [blame] | 30 | @state() |
| 31 | serverConfig?: ServerInfo; |
| 32 | |
Dhruv Srivastava | efe10d9c | 2022-06-28 12:22:48 +0200 | [diff] [blame] | 33 | private readonly getConfigModel = resolve(this, configModelToken); |
| 34 | |
Ben Rohlfs | 9d6c32a | 2023-05-24 11:10:59 +0200 | [diff] [blame] | 35 | static override get styles() { |
| 36 | return [ |
| 37 | sharedStyles, |
Milutin Kristofic | aa1c08b | 2023-09-06 10:34:16 +0200 | [diff] [blame] | 38 | grFormStyles, |
Ben Rohlfs | 9d6c32a | 2023-05-24 11:10:59 +0200 | [diff] [blame] | 39 | css` |
| 40 | #changeCols { |
| 41 | width: auto; |
| 42 | } |
| 43 | #changeCols .visibleHeader { |
| 44 | text-align: center; |
| 45 | } |
| 46 | .checkboxContainer { |
| 47 | cursor: pointer; |
| 48 | text-align: center; |
| 49 | } |
| 50 | .checkboxContainer input { |
| 51 | cursor: pointer; |
| 52 | } |
| 53 | .checkboxContainer:hover { |
| 54 | outline: 1px solid var(--border-color); |
| 55 | } |
| 56 | `, |
| 57 | ]; |
| 58 | } |
Milutin Kristofic | 4aa368a | 2022-04-05 20:49:37 +0200 | [diff] [blame] | 59 | |
Dhruv Srivastava | efe10d9c | 2022-06-28 12:22:48 +0200 | [diff] [blame] | 60 | constructor() { |
| 61 | super(); |
| 62 | subscribe( |
| 63 | this, |
| 64 | () => this.getConfigModel().serverConfig$, |
| 65 | config => { |
| 66 | this.serverConfig = config; |
| 67 | } |
| 68 | ); |
| 69 | } |
| 70 | |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 71 | override render() { |
Milutin Kristofic | 4aa368a | 2022-04-05 20:49:37 +0200 | [diff] [blame] | 72 | return html`<div class="gr-form-styles"> |
| 73 | <table id="changeCols"> |
| 74 | <thead> |
| 75 | <tr> |
| 76 | <th class="nameHeader">Column</th> |
| 77 | <th class="visibleHeader">Visible</th> |
| 78 | </tr> |
| 79 | </thead> |
| 80 | <tbody> |
| 81 | <tr> |
| 82 | <td><label for="numberCheckbox">Number</label></td> |
| 83 | <td |
| 84 | class="checkboxContainer" |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 85 | @click=${this.handleCheckboxContainerClick} |
Milutin Kristofic | 4aa368a | 2022-04-05 20:49:37 +0200 | [diff] [blame] | 86 | > |
| 87 | <input |
| 88 | id="numberCheckbox" |
| 89 | type="checkbox" |
| 90 | name="number" |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 91 | @click=${this.handleNumberCheckboxClick} |
| 92 | ?checked=${this.showNumber} |
Milutin Kristofic | 4aa368a | 2022-04-05 20:49:37 +0200 | [diff] [blame] | 93 | /> |
| 94 | </td> |
| 95 | </tr> |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 96 | ${this.defaultColumns.map(column => this.renderRow(column))} |
Milutin Kristofic | 4aa368a | 2022-04-05 20:49:37 +0200 | [diff] [blame] | 97 | </tbody> |
| 98 | </table> |
| 99 | </div>`; |
| 100 | } |
| 101 | |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 102 | renderRow(column: string) { |
| 103 | return html`<tr> |
| 104 | <td><label for=${column}>${column}</label></td> |
| 105 | <td class="checkboxContainer" @click=${this.handleCheckboxContainerClick}> |
| 106 | <input |
| 107 | id=${column} |
| 108 | type="checkbox" |
| 109 | name=${column} |
| 110 | @click=${this.handleTargetClick} |
| 111 | ?checked=${!this.computeIsColumnHidden(column)} |
| 112 | /> |
| 113 | </td> |
| 114 | </tr>`; |
| 115 | } |
| 116 | |
Frank Borden | ca8165b | 2021-09-28 17:57:09 +0200 | [diff] [blame] | 117 | /** |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 118 | * Get the list of enabled column names from whichever checkboxes are |
| 119 | * checked (excluding the number checkbox). |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 120 | * private but used in test |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 121 | */ |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 122 | getDisplayedColumns() { |
| 123 | if (this.shadowRoot === null) return []; |
Ben Rohlfs | 3f27968 | 2022-02-25 12:07:27 +0100 | [diff] [blame] | 124 | return Array.from( |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 125 | this.shadowRoot.querySelectorAll<HTMLInputElement>( |
Ben Rohlfs | 3f27968 | 2022-02-25 12:07:27 +0100 | [diff] [blame] | 126 | '.checkboxContainer input:not([name=number])' |
| 127 | ) |
Chris Poucet | caeea1b | 2021-08-19 22:12:56 +0000 | [diff] [blame] | 128 | ) |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 129 | .filter(checkbox => checkbox.checked) |
| 130 | .map(checkbox => checkbox.name); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 131 | } |
| 132 | |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 133 | private computeIsColumnHidden(columnToCheck?: string) { |
| 134 | if (!this.displayedColumns || !columnToCheck) { |
Frank Borden | ca8165b | 2021-09-28 17:57:09 +0200 | [diff] [blame] | 135 | return false; |
| 136 | } |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 137 | return !this.displayedColumns.includes(columnToCheck); |
Frank Borden | ca8165b | 2021-09-28 17:57:09 +0200 | [diff] [blame] | 138 | } |
| 139 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 140 | /** |
| 141 | * Handle a click on a checkbox container and relay the click to the checkbox it |
| 142 | * contains. |
| 143 | */ |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 144 | private handleCheckboxContainerClick(e: MouseEvent) { |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 145 | if (e.target === null) return; |
| 146 | const checkbox = (e.target as HTMLElement).querySelector('input'); |
| 147 | if (!checkbox) { |
| 148 | return; |
| 149 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 150 | checkbox.click(); |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * Handle a click on the number checkbox and update the showNumber property |
| 155 | * accordingly. |
| 156 | */ |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 157 | private handleNumberCheckboxClick(e: MouseEvent) { |
| 158 | this.showNumber = (e.target as HTMLInputElement).checked; |
| 159 | fire(this, 'show-number-changed', {value: this.showNumber}); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | /** |
| 163 | * Handle a click on a displayed column checkboxes (excluding number) and |
| 164 | * update the displayedColumns property accordingly. |
| 165 | */ |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 166 | private handleTargetClick() { |
| 167 | this.displayedColumns = this.getDisplayedColumns(); |
| 168 | fire(this, 'displayed-columns-changed', {value: this.displayedColumns}); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 169 | } |
| 170 | } |
| 171 | |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 172 | declare global { |
Milutin Kristofic | fb5b14c | 2022-04-05 22:27:29 +0200 | [diff] [blame] | 173 | interface HTMLElementEventMap { |
| 174 | 'show-number-changed': ValueChangedEvent<boolean>; |
| 175 | 'displayed-columns-changed': ValueChangedEvent<string[]>; |
| 176 | } |
Milutin Kristofic | 65f35c1 | 2020-08-19 20:35:28 +0200 | [diff] [blame] | 177 | interface HTMLElementTagNameMap { |
| 178 | 'gr-change-table-editor': GrChangeTableEditor; |
| 179 | } |
| 180 | } |