| /** |
| * @license |
| * Copyright (C) 2018 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 '@polymer/iron-icon/iron-icon'; |
| import '../../shared/gr-icons/gr-icons'; |
| import '../../shared/gr-dialog/gr-dialog'; |
| import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator'; |
| import '../../plugins/gr-endpoint-param/gr-endpoint-param'; |
| import '../gr-thread-list/gr-thread-list'; |
| import {ChangeInfo, ActionInfo} from '../../../types/common'; |
| import {GrDialog} from '../../shared/gr-dialog/gr-dialog'; |
| import {pluralize} from '../../../utils/string-util'; |
| import {CommentThread, isUnresolved} from '../../../utils/comment-util'; |
| import {sharedStyles} from '../../../styles/shared-styles'; |
| import {LitElement, css, html} from 'lit'; |
| import {customElement, property, query} from 'lit/decorators'; |
| import {fontStyles} from '../../../styles/gr-font-styles'; |
| |
| @customElement('gr-confirm-submit-dialog') |
| export class GrConfirmSubmitDialog extends LitElement { |
| @query('#dialog') |
| dialog?: GrDialog; |
| |
| /** |
| * Fired when the confirm button is pressed. |
| * |
| * @event confirm |
| */ |
| |
| /** |
| * Fired when the cancel button is pressed. |
| * |
| * @event cancel |
| */ |
| |
| @property({type: Object}) |
| change?: ChangeInfo; |
| |
| @property({type: Object}) |
| action?: ActionInfo; |
| |
| @property({type: Array}) |
| commentThreads?: CommentThread[] = []; |
| |
| @property({type: Boolean}) |
| _initialised = false; |
| |
| static override get styles() { |
| return [ |
| sharedStyles, |
| fontStyles, |
| css` |
| #dialog { |
| min-width: 40em; |
| } |
| p { |
| margin-bottom: var(--spacing-l); |
| } |
| .warningBeforeSubmit { |
| color: var(--warning-foreground); |
| vertical-align: top; |
| margin-right: var(--spacing-s); |
| } |
| @media screen and (max-width: 50em) { |
| #dialog { |
| min-width: inherit; |
| width: 100%; |
| } |
| } |
| `, |
| ]; |
| } |
| |
| private renderPrivate() { |
| if (!this.change?.is_private) return ''; |
| return html` |
| <p> |
| <iron-icon |
| icon="gr-icons:warning" |
| class="warningBeforeSubmit" |
| ></iron-icon> |
| <strong>Heads Up!</strong> |
| Submitting this private change will also make it public. |
| </p> |
| `; |
| } |
| |
| private renderUnresolvedCommentCount() { |
| if (!this.change?.unresolved_comment_count) return ''; |
| return html` |
| <p> |
| <iron-icon |
| icon="gr-icons:warning" |
| class="warningBeforeSubmit" |
| ></iron-icon> |
| ${this._computeUnresolvedCommentsWarning(this.change)} |
| </p> |
| <gr-thread-list |
| id="commentList" |
| .threads="${this._computeUnresolvedThreads(this.commentThreads)}" |
| .change="${this.change}" |
| .change-num="${this.change?._number}" |
| logged-in="true" |
| hide-dropdown |
| > |
| </gr-thread-list> |
| `; |
| } |
| |
| private renderChangeEdit() { |
| if (!this._computeHasChangeEdit(this.change)) return ''; |
| return html` |
| <iron-icon |
| icon="gr-icons:warning" |
| class="warningBeforeSubmit" |
| ></iron-icon> |
| Your unpublished edit will not be submitted. Did you forget to click |
| <b>PUBLISH</b> |
| `; |
| } |
| |
| private renderInitialised() { |
| if (!this._initialised) return ''; |
| return html` |
| <div class="header" slot="header">${this.action?.label}</div> |
| <div class="main" slot="main"> |
| <gr-endpoint-decorator name="confirm-submit-change"> |
| <p>Ready to submit “<strong>${this.change?.subject}</strong>”?</p> |
| ${this.renderPrivate()} ${this.renderUnresolvedCommentCount()} |
| ${this.renderChangeEdit()} |
| <gr-endpoint-param |
| name="change" |
| .value="${this.change}" |
| ></gr-endpoint-param> |
| <gr-endpoint-param |
| name="action" |
| .value="${this.action}" |
| ></gr-endpoint-param> |
| </gr-endpoint-decorator> |
| </div> |
| `; |
| } |
| |
| override render() { |
| return html` <gr-dialog |
| id="dialog" |
| confirm-label="Continue" |
| confirm-on-enter="" |
| @cancel=${this._handleCancelTap} |
| @confirm=${this._handleConfirmTap} |
| > |
| ${this.renderInitialised()} |
| </gr-dialog>`; |
| } |
| |
| init() { |
| this._initialised = true; |
| } |
| |
| resetFocus() { |
| this.dialog?.resetFocus(); |
| } |
| |
| _computeHasChangeEdit(change?: ChangeInfo) { |
| return ( |
| !!change && |
| !!change.revisions && |
| Object.values(change.revisions).some(rev => rev._number === 'edit') |
| ); |
| } |
| |
| _computeUnresolvedThreads(commentThreads?: CommentThread[]) { |
| if (!commentThreads) return []; |
| return commentThreads.filter(thread => isUnresolved(thread)); |
| } |
| |
| _computeUnresolvedCommentsWarning(change?: ChangeInfo) { |
| if (!change) return ''; |
| const unresolvedCount = change.unresolved_comment_count; |
| if (!unresolvedCount) throw new Error('unresolved comments undefined or 0'); |
| return `Heads Up! ${pluralize(unresolvedCount, 'unresolved comment')}.`; |
| } |
| |
| _handleConfirmTap(e: Event) { |
| e.preventDefault(); |
| e.stopPropagation(); |
| this.dispatchEvent(new CustomEvent('confirm', {bubbles: false})); |
| } |
| |
| _handleCancelTap(e: Event) { |
| e.preventDefault(); |
| e.stopPropagation(); |
| this.dispatchEvent(new CustomEvent('cancel', {bubbles: false})); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'gr-confirm-submit-dialog': GrConfirmSubmitDialog; |
| } |
| } |