blob: 5303c578264083697ae90f39d09c3f3235b3c5d8 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {LitElement, html, css} from 'lit-element';
6
7import {SHARED_STYLES} from 'shared/shared-styles';
8import './mr-edit-field.js';
9
10/**
11 * `<mr-edit-status>`
12 *
13 * Editing form for either an approval or the overall issue.
14 *
15 */
16export class MrEditStatus extends LitElement {
17 /** @override */
18 static get styles() {
19 return [
20 SHARED_STYLES,
21 css`
22 :host {
23 width: 100%;
24 }
25 select {
26 width: var(--mr-edit-field-width);
27 padding: var(--mr-edit-field-padding);
28 }
29 .grid-input {
30 margin-top: 8px;
31 display: grid;
32 grid-gap: var(--mr-input-grid-gap);
33 grid-template-columns: auto 1fr;
34 }
35 .grid-input[hidden] {
36 display: none;
37 }
38 label {
39 font-weight: bold;
40 word-wrap: break-word;
41 text-align: left;
42 }
43 #mergedIntoInput {
44 width: 160px;
45 }
46 `,
47 ];
48 }
49
50 /** @override */
51 render() {
52 return html`
53 <select
54 @change=${this._selectChangeHandler}
55 aria-label="Status"
56 id="statusInput"
57 >
58 ${this._statusesGrouped.map((group) => html`
59 <optgroup label=${group.name} ?hidden=${!group.name}>
60 ${group.statuses.map((item) => html`
61 <option
62 value=${item.status}
63 .selected=${this.status === item.status}
64 >
65 ${item.status}
66 ${item.docstring ? `= ${item.docstring}` : ''}
67 </option>
68 `)}
69 </optgroup>
70
71 ${!group.name ? html`
72 ${group.statuses.map((item) => html`
73 <option
74 value=${item.status}
75 .selected=${this.status === item.status}
76 >
77 ${item.status}
78 ${item.docstring ? `= ${item.docstring}` : ''}
79 </option>
80 `)}
81 ` : ''}
82 `)}
83 </select>
84
85 <div class="grid-input" ?hidden=${!this._showMergedInto}>
86 <label for="mergedIntoInput" id="mergedIntoLabel">Merged into:</label>
87 <input
88 id="mergedIntoInput"
89 value=${this.mergedInto || ''}
90 @change=${this._changeHandler}
91 ></input>
92 </div>`;
93 }
94
95 /** @override */
96 static get properties() {
97 return {
98 initialStatus: {type: String},
99 status: {type: String},
100 statuses: {type: Array},
101 isApproval: {type: Boolean},
102 mergedInto: {type: String},
103 };
104 }
105
106 /** @override */
107 update(changedProperties) {
108 if (changedProperties.has('initialStatus')) {
109 this.status = this.initialStatus;
110 }
111 super.update(changedProperties);
112 }
113
114 get _showMergedInto() {
115 const status = this.status || this.initialStatus;
116 return (status === 'Duplicate');
117 }
118
119 get _statusesGrouped() {
120 const statuses = this.statuses;
121 const isApproval = this.isApproval;
122 if (!statuses) return [];
123 if (isApproval) {
124 return [{statuses: statuses}];
125 }
126 return [
127 {
128 name: 'Open',
129 statuses: statuses.filter((s) => s.meansOpen),
130 },
131 {
132 name: 'Closed',
133 statuses: statuses.filter((s) => !s.meansOpen),
134 },
135 ];
136 }
137
138 async reset() {
139 await this.updateComplete;
140 const mergedIntoInput = this.shadowRoot.querySelector('#mergedIntoInput');
141 if (mergedIntoInput) {
142 mergedIntoInput.value = this.mergedInto || '';
143 }
144 this.status = this.initialStatus;
145 }
146
147 get delta() {
148 const result = {};
149
150 if (this.status !== this.initialStatus) {
151 result['status'] = this.status;
152 }
153
154 if (this._showMergedInto) {
155 const newMergedInto = this.shadowRoot.querySelector(
156 '#mergedIntoInput').value;
157 if (newMergedInto !== this.mergedInto) {
158 result['mergedInto'] = newMergedInto;
159 }
160 } else if (this.initialStatus === 'Duplicate') {
161 result['mergedInto'] = '';
162 }
163
164 return result;
165 }
166
167 _selectChangeHandler(e) {
168 const statusInput = e.target;
169 this.status = statusInput.value;
170 this._changeHandler(e);
171 }
172
173 /**
174 * @param {Event} e
175 * @fires CustomEvent#change
176 * @private
177 */
178 _changeHandler(e) {
179 this.dispatchEvent(new CustomEvent('change'));
180 }
181}
182
183customElements.define('mr-edit-status', MrEditStatus);