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 | */ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 6 | import '../../admin/gr-create-change-dialog/gr-create-change-dialog'; |
| 7 | import '../../shared/gr-button/gr-button'; |
| 8 | import '../../shared/gr-dialog/gr-dialog'; |
| 9 | import '../../shared/gr-dropdown/gr-dropdown'; |
Chris Poucet | 1c71386 | 2022-07-25 13:12:24 +0200 | [diff] [blame] | 10 | import '../../shared/gr-icon/gr-icon'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 11 | import '../gr-confirm-abandon-dialog/gr-confirm-abandon-dialog'; |
| 12 | import '../gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog'; |
| 13 | import '../gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog'; |
| 14 | import '../gr-confirm-move-dialog/gr-confirm-move-dialog'; |
| 15 | import '../gr-confirm-rebase-dialog/gr-confirm-rebase-dialog'; |
| 16 | import '../gr-confirm-revert-dialog/gr-confirm-revert-dialog'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 17 | import '../gr-confirm-submit-dialog/gr-confirm-submit-dialog'; |
| 18 | import '../../../styles/shared-styles'; |
Ben Rohlfs | 54934de | 2022-09-22 12:44:33 +0200 | [diff] [blame] | 19 | import {navigationToken} from '../../core/gr-navigation/gr-navigation'; |
Chris Poucet | c6e880b | 2021-11-15 19:57:06 +0100 | [diff] [blame] | 20 | import {getAppContext} from '../../../services/app-context'; |
Paladox none | d22af55 | 2023-04-10 15:31:00 +0000 | [diff] [blame] | 21 | import { |
| 22 | CURRENT, |
| 23 | hasEditBasedOnCurrentPatchSet, |
| 24 | } from '../../../utils/patch-set-util'; |
Dmitrii Filippov | 3bf6889 | 2020-07-12 00:19:10 +0200 | [diff] [blame] | 25 | import { |
| 26 | changeIsOpen, |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 27 | isOwner, |
Dmitrii Filippov | 3bf6889 | 2020-07-12 00:19:10 +0200 | [diff] [blame] | 28 | listChangesOptionsToHex, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 29 | } from '../../../utils/change-util'; |
| 30 | import { |
| 31 | ChangeStatus, |
| 32 | DraftsAction, |
| 33 | HttpMethod, |
| 34 | NotifyType, |
| 35 | } from '../../../constants/constants'; |
Ben Rohlfs | 4e91353 | 2022-10-24 12:31:58 +0200 | [diff] [blame] | 36 | import {TargetElement} from '../../../api/plugin'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 37 | import { |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 38 | AccountInfo, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 39 | ActionInfo, |
| 40 | ActionNameToActionInfoMap, |
| 41 | BranchName, |
Kamil Musin | d3f6497 | 2022-12-27 18:01:48 +0100 | [diff] [blame] | 42 | ChangeActionDialog, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 43 | ChangeInfo, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 44 | CherryPickInput, |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 45 | CommentThread, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 46 | CommitId, |
| 47 | InheritedBooleanInfo, |
| 48 | isDetailedLabelInfo, |
| 49 | isQuickLabelInfo, |
| 50 | LabelInfo, |
Chris Poucet | fceaf78 | 2023-08-16 15:11:04 +0200 | [diff] [blame] | 51 | ListChangesOption, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 52 | NumericChangeId, |
Paladox none | f4ddeed | 2023-02-22 19:30:47 +0000 | [diff] [blame] | 53 | PatchSetNumber, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 54 | RequestPayload, |
| 55 | RevertSubmissionInfo, |
| 56 | ReviewInput, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 57 | } from '../../../types/common'; |
| 58 | import {GrConfirmAbandonDialog} from '../gr-confirm-abandon-dialog/gr-confirm-abandon-dialog'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 59 | import {GrDialog} from '../../shared/gr-dialog/gr-dialog'; |
| 60 | import {GrCreateChangeDialog} from '../../admin/gr-create-change-dialog/gr-create-change-dialog'; |
| 61 | import {GrConfirmSubmitDialog} from '../gr-confirm-submit-dialog/gr-confirm-submit-dialog'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 62 | import { |
| 63 | ConfirmRevertEventDetail, |
| 64 | GrConfirmRevertDialog, |
| 65 | RevertType, |
| 66 | } from '../gr-confirm-revert-dialog/gr-confirm-revert-dialog'; |
| 67 | import {GrConfirmMoveDialog} from '../gr-confirm-move-dialog/gr-confirm-move-dialog'; |
| 68 | import {GrConfirmCherrypickDialog} from '../gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog'; |
| 69 | import {GrConfirmCherrypickConflictDialog} from '../gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog'; |
| 70 | import { |
| 71 | ConfirmRebaseEventDetail, |
| 72 | GrConfirmRebaseDialog, |
| 73 | } from '../gr-confirm-rebase-dialog/gr-confirm-rebase-dialog'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 74 | import {GrButton} from '../../shared/gr-button/gr-button'; |
| 75 | import { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 76 | GrChangeActionsElement, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 77 | UIActionInfo, |
| 78 | } from '../../shared/gr-js-api-interface/gr-change-actions-js-api'; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 79 | import { |
| 80 | fire, |
| 81 | fireAlert, |
Ben Rohlfs | 6bb9053 | 2023-02-17 18:55:56 +0100 | [diff] [blame] | 82 | fireError, |
Ben Rohlfs | 44f0104 | 2023-02-18 13:27:57 +0100 | [diff] [blame] | 83 | fireNoBubbleNoCompose, |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 84 | } from '../../../utils/event-util'; |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 85 | import { |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 86 | getApprovalInfo, |
| 87 | getVotingRange, |
Milutin Kristofic | bd44580 | 2021-10-20 21:00:21 +0200 | [diff] [blame] | 88 | StandardLabels, |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 89 | } from '../../../utils/label-util'; |
Ben Rohlfs | a7ab950 | 2021-02-15 17:45:45 +0100 | [diff] [blame] | 90 | import { |
| 91 | ActionPriority, |
| 92 | ActionType, |
| 93 | ChangeActions, |
| 94 | PrimaryActionKey, |
| 95 | RevisionActions, |
| 96 | } from '../../../api/change-actions'; |
| 97 | import {ErrorCallback} from '../../../api/rest'; |
Dhruv Srivastava | e68d45a | 2021-04-07 11:50:00 +0200 | [diff] [blame] | 98 | import {GrDropdown} from '../../shared/gr-dropdown/gr-dropdown'; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 99 | import {resolve} from '../../../models/dependency'; |
Chris Poucet | bf65b8f | 2022-01-18 21:18:12 +0000 | [diff] [blame] | 100 | import {changeModelToken} from '../../../models/change/change-model'; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 101 | import {sharedStyles} from '../../../styles/shared-styles'; |
| 102 | import {LitElement, PropertyValues, css, html, nothing} from 'lit'; |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 103 | import {customElement, query, state} from 'lit/decorators.js'; |
Frank Borden | 42c1a45 | 2022-08-11 16:27:20 +0200 | [diff] [blame] | 104 | import {ifDefined} from 'lit/directives/if-defined.js'; |
Ben Rohlfs | ba44082 | 2023-04-11 18:08:03 +0200 | [diff] [blame] | 105 | import {assertIsDefined, queryAll, uuid} from '../../../utils/common-util'; |
Milutin Kristofic | 174c343 | 2022-09-16 12:33:28 +0200 | [diff] [blame] | 106 | import {Interaction} from '../../../constants/reporting'; |
Ben Rohlfs | e9051fe | 2022-09-16 11:08:40 +0200 | [diff] [blame] | 107 | import {rootUrl} from '../../../utils/url-util'; |
Ben Rohlfs | 77c489a | 2022-09-21 14:25:56 +0200 | [diff] [blame] | 108 | import {createSearchUrl} from '../../../models/views/search'; |
Ben Rohlfs | aa53390 | 2022-09-22 09:07:12 +0200 | [diff] [blame] | 109 | import {createChangeUrl} from '../../../models/views/change'; |
Chris Poucet | 20f0958 | 2022-10-24 23:29:27 +0200 | [diff] [blame] | 110 | import {storageServiceToken} from '../../../services/storage/gr-storage_impl'; |
Ben Rohlfs | 4e91353 | 2022-10-24 12:31:58 +0200 | [diff] [blame] | 111 | import {ShowRevisionActionsDetail} from '../../shared/gr-js-api-interface/gr-js-api-types'; |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 112 | import {whenVisible} from '../../../utils/dom-util'; |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 113 | import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader'; |
Dhruv Srivastava | 84575c9 | 2022-10-26 19:13:59 +0200 | [diff] [blame] | 114 | import {modalStyles} from '../../../styles/gr-modal-styles'; |
Paladox none | f4ddeed | 2023-02-22 19:30:47 +0000 | [diff] [blame] | 115 | import {subscribe} from '../../lit/subscription-controller'; |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 116 | import {userModelToken} from '../../../models/user/user-model'; |
| 117 | import {ParsedChangeInfo} from '../../../types/types'; |
| 118 | import {configModelToken} from '../../../models/config/config-model'; |
Kamil Musin | 1d8a1a3 | 2024-02-29 14:49:41 +0100 | [diff] [blame] | 119 | import {readJSONResponsePayload} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper'; |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 120 | import {commentsModelToken} from '../../../models/comments/comments-model'; |
| 121 | import {when} from 'lit/directives/when.js'; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 122 | |
| 123 | const ERR_BRANCH_EMPTY = 'The destination branch can’t be empty.'; |
| 124 | const ERR_COMMIT_EMPTY = 'The commit message can’t be empty.'; |
| 125 | const ERR_REVISION_ACTIONS = 'Couldn’t load revision actions.'; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 126 | |
Milutin Kristofic | b2237d6 | 2021-12-09 20:29:55 +0100 | [diff] [blame] | 127 | export enum LabelStatus { |
Viktar Donich | 0713056 | 2016-12-06 11:21:39 -0800 | [diff] [blame] | 128 | /** |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 129 | * This label provides what is necessary for submission. |
Viktar Donich | 0713056 | 2016-12-06 11:21:39 -0800 | [diff] [blame] | 130 | */ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 131 | OK = 'OK', |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 132 | /** |
| 133 | * This label prevents the change from being submitted. |
| 134 | */ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 135 | REJECT = 'REJECT', |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 136 | /** |
| 137 | * The label may be set, but it's neither necessary for submission |
| 138 | * nor does it block submission if set. |
| 139 | */ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 140 | MAY = 'MAY', |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 141 | /** |
| 142 | * The label is required for submission, but has not been satisfied. |
| 143 | */ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 144 | NEED = 'NEED', |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 145 | /** |
| 146 | * The label is required for submission, but is impossible to complete. |
| 147 | * The likely cause is access has not been granted correctly by the |
| 148 | * project owner or site administrator. |
| 149 | */ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 150 | IMPOSSIBLE = 'IMPOSSIBLE', |
| 151 | OPTIONAL = 'OPTIONAL', |
| 152 | } |
Viktar Donich | 0713056 | 2016-12-06 11:21:39 -0800 | [diff] [blame] | 153 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 154 | const ActionLoadingLabels: {[actionKey: string]: string} = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 155 | abandon: 'Abandoning...', |
| 156 | cherrypick: 'Cherry-picking...', |
| 157 | delete: 'Deleting...', |
| 158 | move: 'Moving..', |
| 159 | rebase: 'Rebasing...', |
| 160 | restore: 'Restoring...', |
| 161 | revert: 'Reverting...', |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 162 | submit: 'Submitting...', |
| 163 | }; |
Andrew Bonventre | 1508cac | 2016-04-02 21:37:15 -0400 | [diff] [blame] | 164 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 165 | const ADDITIONAL_ACTION_KEY_PREFIX = '__additionalAction_'; |
Andrew Bonventre | cd73e96 | 2016-06-22 17:52:56 -0400 | [diff] [blame] | 166 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 167 | interface QuickApproveUIActionInfo extends UIActionInfo { |
| 168 | key: string; |
| 169 | payload?: RequestPayload; |
| 170 | } |
| 171 | |
| 172 | const QUICK_APPROVE_ACTION: QuickApproveUIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 173 | __key: 'review', |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 174 | __type: ActionType.CHANGE, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 175 | enabled: true, |
| 176 | key: 'review', |
| 177 | label: 'Quick approve', |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 178 | method: HttpMethod.POST, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 179 | }; |
Viktar Donich | 50e2c00 | 2016-11-11 14:41:24 -0800 | [diff] [blame] | 180 | |
Dhruv Srivastava | 25ca8ea | 2021-03-31 21:37:30 +0200 | [diff] [blame] | 181 | function isQuickApproveAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 182 | action: UIActionInfo |
| 183 | ): action is QuickApproveUIActionInfo { |
| 184 | return (action as QuickApproveUIActionInfo).key === QUICK_APPROVE_ACTION.key; |
| 185 | } |
Viktar Donich | 7f412ae | 2017-04-18 16:08:13 -0700 | [diff] [blame] | 186 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 187 | const DOWNLOAD_ACTION: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 188 | enabled: true, |
| 189 | label: 'Download patch', |
| 190 | title: 'Open download dialog', |
| 191 | __key: 'download', |
| 192 | __primary: false, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 193 | __type: ActionType.REVISION, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 194 | }; |
Kasper Nilsson | f6c0b50 | 2017-04-25 10:45:28 +0200 | [diff] [blame] | 195 | |
Dhruv Srivastava | 4dcb543 | 2021-04-26 16:45:07 +0200 | [diff] [blame] | 196 | const INCLUDED_IN_ACTION: UIActionInfo = { |
| 197 | enabled: true, |
| 198 | label: 'Included In', |
| 199 | title: 'Open Included In dialog', |
| 200 | __key: 'includedIn', |
| 201 | __primary: false, |
| 202 | __type: ActionType.CHANGE, |
| 203 | }; |
| 204 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 205 | const REBASE_EDIT: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 206 | enabled: true, |
| 207 | label: 'Rebase edit', |
| 208 | title: 'Rebase change edit', |
| 209 | __key: 'rebaseEdit', |
| 210 | __primary: false, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 211 | __type: ActionType.CHANGE, |
| 212 | method: HttpMethod.POST, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 213 | }; |
Paladox none | a95b368 | 2017-09-18 17:25:29 +0000 | [diff] [blame] | 214 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 215 | const PUBLISH_EDIT: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 216 | enabled: true, |
| 217 | label: 'Publish edit', |
| 218 | title: 'Publish change edit', |
| 219 | __key: 'publishEdit', |
| 220 | __primary: false, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 221 | __type: ActionType.CHANGE, |
| 222 | method: HttpMethod.POST, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 223 | }; |
Paladox none | 68b75ba | 2017-09-13 21:23:07 +0000 | [diff] [blame] | 224 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 225 | const DELETE_EDIT: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 226 | enabled: true, |
| 227 | label: 'Delete edit', |
| 228 | title: 'Delete change edit', |
| 229 | __key: 'deleteEdit', |
| 230 | __primary: false, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 231 | __type: ActionType.CHANGE, |
| 232 | method: HttpMethod.DELETE, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 233 | }; |
Paladox none | 68b75ba | 2017-09-13 21:23:07 +0000 | [diff] [blame] | 234 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 235 | const EDIT: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 236 | enabled: true, |
| 237 | label: 'Edit', |
| 238 | title: 'Edit this change', |
| 239 | __key: 'edit', |
| 240 | __primary: false, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 241 | __type: ActionType.CHANGE, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 242 | }; |
Kasper Nilsson | 7d6fb7b | 2018-01-16 12:45:45 -0800 | [diff] [blame] | 243 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 244 | const STOP_EDIT: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 245 | enabled: true, |
| 246 | label: 'Stop editing', |
| 247 | title: 'Stop editing this change', |
| 248 | __key: 'stopEdit', |
| 249 | __primary: false, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 250 | __type: ActionType.CHANGE, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 251 | }; |
Kasper Nilsson | 59d66d8 | 2018-01-23 17:46:47 -0800 | [diff] [blame] | 252 | |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 253 | // Set of keys that have icons. |
| 254 | const ACTIONS_WITH_ICONS = new Map< |
| 255 | string, |
Chris Poucet | a6b629c | 2022-08-12 16:25:48 +0200 | [diff] [blame] | 256 | Pick<UIActionInfo, 'filled' | 'icon'> |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 257 | >([ |
| 258 | [ChangeActions.ABANDON, {icon: 'block'}], |
| 259 | [ChangeActions.DELETE_EDIT, {icon: 'delete', filled: true}], |
| 260 | [ChangeActions.EDIT, {icon: 'edit', filled: true}], |
| 261 | [ChangeActions.PUBLISH_EDIT, {icon: 'publish', filled: true}], |
| 262 | [ChangeActions.READY, {icon: 'visibility', filled: true}], |
Chris Poucet | a6b629c | 2022-08-12 16:25:48 +0200 | [diff] [blame] | 263 | [ChangeActions.REBASE_EDIT, {icon: 'rebase_edit'}], |
| 264 | [RevisionActions.REBASE, {icon: 'rebase'}], |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 265 | [ChangeActions.RESTORE, {icon: 'history'}], |
| 266 | [ChangeActions.REVERT, {icon: 'undo'}], |
| 267 | [ChangeActions.STOP_EDIT, {icon: 'stop', filled: true}], |
| 268 | [QUICK_APPROVE_ACTION.key, {icon: 'check'}], |
| 269 | [RevisionActions.SUBMIT, {icon: 'done_all'}], |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 270 | ]); |
Kasper Nilsson | 59b6595 | 2018-05-14 17:44:10 -0700 | [diff] [blame] | 271 | |
Dhruv Srivastava | bc329e9 | 2020-10-30 09:02:15 +0100 | [diff] [blame] | 272 | const EDIT_ACTIONS: Set<string> = new Set([ |
| 273 | ChangeActions.DELETE_EDIT, |
| 274 | ChangeActions.EDIT, |
| 275 | ChangeActions.PUBLISH_EDIT, |
| 276 | ChangeActions.REBASE_EDIT, |
| 277 | ChangeActions.STOP_EDIT, |
| 278 | ]); |
| 279 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 280 | const AWAIT_CHANGE_ATTEMPTS = 5; |
| 281 | const AWAIT_CHANGE_TIMEOUT_MS = 1000; |
Wyatt Allen | 15ed72f | 2017-08-10 09:29:20 -0700 | [diff] [blame] | 282 | |
David Ostrovsky | 954e508 | 2021-05-05 12:28:13 +0200 | [diff] [blame] | 283 | const SKIP_ACTION_KEYS: string[] = [ |
Han-Wen Nienhuys | 64080a5 | 2021-08-10 13:03:41 +0200 | [diff] [blame] | 284 | // REVIEWED/UNREVIEWED is made obsolete by AttentionSet. Once the |
| 285 | // backend stops supporting (UN)REVIEWED, we can remove these. |
Ben Rohlfs | 50768ee | 2020-06-29 09:51:32 +0200 | [diff] [blame] | 286 | ChangeActions.REVIEWED, |
| 287 | ChangeActions.UNREVIEWED, |
Han-Wen Nienhuys | 64080a5 | 2021-08-10 13:03:41 +0200 | [diff] [blame] | 288 | // REVERT_SUBMISSION is folded into the dialog for REVERT. |
Dhruv Srivastava | 4f2f938 | 2021-05-14 08:33:45 +0000 | [diff] [blame] | 289 | ChangeActions.REVERT_SUBMISSION, |
Ben Rohlfs | 50768ee | 2020-06-29 09:51:32 +0200 | [diff] [blame] | 290 | ]; |
| 291 | |
Dhruv Srivastava | e68d45a | 2021-04-07 11:50:00 +0200 | [diff] [blame] | 292 | export function assertUIActionInfo(action?: ActionInfo): UIActionInfo { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 293 | // TODO(TS): Remove this function. The gr-change-actions adds properties |
| 294 | // to existing ActionInfo objects instead of creating a new objects. This |
| 295 | // function checks, that 'action' has all property required by UIActionInfo. |
| 296 | // In the future, we should avoid updates of an existing ActionInfos and |
| 297 | // instead create a new object to make code cleaner. However, at the current |
| 298 | // state this is unsafe, because other code can expect these properties to be |
| 299 | // set in ActionInfo. |
| 300 | if (!action) { |
| 301 | throw new Error('action is undefined'); |
| 302 | } |
| 303 | const result = action as UIActionInfo; |
| 304 | if (result.__key === undefined || result.__type === undefined) { |
| 305 | throw new Error('action is not an UIActionInfo'); |
| 306 | } |
| 307 | return result; |
| 308 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 309 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 310 | interface MenuAction { |
| 311 | name: string; |
| 312 | id: string; |
| 313 | action: UIActionInfo; |
| 314 | tooltip?: string; |
| 315 | } |
| 316 | |
| 317 | interface OverflowAction { |
| 318 | type: ActionType; |
| 319 | key: string; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | interface ActionPriorityOverride { |
| 323 | type: ActionType.CHANGE | ActionType.REVISION; |
| 324 | key: string; |
| 325 | priority: ActionPriority; |
| 326 | } |
| 327 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 328 | @customElement('gr-change-actions') |
Frank Borden | 6988bdf | 2021-04-07 14:42:00 +0200 | [diff] [blame] | 329 | export class GrChangeActions |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 330 | extends LitElement |
Chris Poucet | caeea1b | 2021-08-19 22:12:56 +0000 | [diff] [blame] | 331 | implements GrChangeActionsElement |
| 332 | { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 333 | /** |
| 334 | * Fired when the change should be reloaded. |
| 335 | * |
Dhruv Srivastava | 8449e77 | 2020-07-22 11:57:29 +0200 | [diff] [blame] | 336 | * @event reload |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 337 | */ |
Dhruv Srivastava | 535e85d | 2020-02-13 19:15:20 +0100 | [diff] [blame] | 338 | |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 339 | /** |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 340 | * Fired when an action is tapped. |
| 341 | * |
| 342 | * @event custom-tap - naming pattern: <action key>-tap |
Tao Zhou | 9a07681 | 2019-12-17 09:59:28 +0100 | [diff] [blame] | 343 | */ |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 344 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 345 | @query('#mainContent') mainContent?: Element; |
| 346 | |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 347 | @query('#actionsModal') actionsModal?: HTMLDialogElement; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 348 | |
| 349 | @query('#confirmRebase') confirmRebase?: GrConfirmRebaseDialog; |
| 350 | |
| 351 | @query('#confirmCherrypick') confirmCherrypick?: GrConfirmCherrypickDialog; |
| 352 | |
| 353 | @query('#confirmCherrypickConflict') |
| 354 | confirmCherrypickConflict?: GrConfirmCherrypickConflictDialog; |
| 355 | |
| 356 | @query('#confirmMove') confirmMove?: GrConfirmMoveDialog; |
| 357 | |
| 358 | @query('#confirmRevertDialog') confirmRevertDialog?: GrConfirmRevertDialog; |
| 359 | |
| 360 | @query('#confirmAbandonDialog') confirmAbandonDialog?: GrConfirmAbandonDialog; |
| 361 | |
| 362 | @query('#confirmSubmitDialog') confirmSubmitDialog?: GrConfirmSubmitDialog; |
| 363 | |
| 364 | @query('#createFollowUpDialog') createFollowUpDialog?: GrDialog; |
| 365 | |
| 366 | @query('#createFollowUpChange') createFollowUpChange?: GrCreateChangeDialog; |
| 367 | |
| 368 | @query('#confirmDeleteDialog') confirmDeleteDialog?: GrDialog; |
| 369 | |
| 370 | @query('#confirmDeleteEditDialog') confirmDeleteEditDialog?: GrDialog; |
| 371 | |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 372 | @query('#confirmPublishEditDialog') confirmPublishEditDialog?: GrDialog; |
| 373 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 374 | @query('#moreActions') moreActions?: GrDropdown; |
| 375 | |
| 376 | @query('#secondaryActions') secondaryActions?: HTMLElement; |
| 377 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 378 | @state() change?: ParsedChangeInfo; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 379 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 380 | @state() actions: ActionNameToActionInfoMap = {}; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 381 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 382 | @state() primaryActionKeys: PrimaryActionKey[] = [ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 383 | ChangeActions.READY, |
| 384 | RevisionActions.SUBMIT, |
| 385 | ]; |
| 386 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 387 | @state() _hideQuickApproveAction = false; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 388 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 389 | @state() account?: AccountInfo; |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 390 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 391 | @state() changeNum?: NumericChangeId; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 392 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 393 | @state() changeStatus?: ChangeStatus; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 394 | |
Ben Rohlfs | 2add82f | 2024-02-26 19:23:01 +0100 | [diff] [blame] | 395 | @state() mergeable?: boolean; |
| 396 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 397 | @state() commitNum?: CommitId; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 398 | |
Paladox none | f4ddeed | 2023-02-22 19:30:47 +0000 | [diff] [blame] | 399 | @state() latestPatchNum?: PatchSetNumber; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 400 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 401 | @state() commitMessage = ''; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 402 | |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 403 | // The unfiltered result of calling `restApiService.getChangeRevisionActions()`. |
| 404 | // The DOWNLOAD action is also added to it in `actionsChanged()`. |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 405 | @state() revisionActions?: ActionNameToActionInfoMap; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 406 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 407 | @state() privateByDefault?: InheritedBooleanInfo; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 408 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 409 | @state() actionLoadingMessage = ''; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 410 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 411 | @state() inProgressActionKeys = new Set<string>(); |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 412 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 413 | @state() allActionValues: UIActionInfo[] = []; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 414 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 415 | @state() topLevelActions?: UIActionInfo[]; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 416 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 417 | @state() topLevelPrimaryActions?: UIActionInfo[]; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 418 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 419 | @state() topLevelSecondaryActions?: UIActionInfo[]; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 420 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 421 | @state() menuActions?: MenuAction[]; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 422 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 423 | @state() overflowActions: OverflowAction[] = [ |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 424 | { |
| 425 | type: ActionType.CHANGE, |
| 426 | key: ChangeActions.WIP, |
| 427 | }, |
| 428 | { |
| 429 | type: ActionType.CHANGE, |
| 430 | key: ChangeActions.DELETE, |
| 431 | }, |
| 432 | { |
| 433 | type: ActionType.REVISION, |
| 434 | key: RevisionActions.CHERRYPICK, |
| 435 | }, |
| 436 | { |
| 437 | type: ActionType.CHANGE, |
| 438 | key: ChangeActions.MOVE, |
| 439 | }, |
| 440 | { |
| 441 | type: ActionType.REVISION, |
| 442 | key: RevisionActions.DOWNLOAD, |
| 443 | }, |
| 444 | { |
| 445 | type: ActionType.CHANGE, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 446 | key: ChangeActions.REVIEWED, |
| 447 | }, |
| 448 | { |
| 449 | type: ActionType.CHANGE, |
| 450 | key: ChangeActions.UNREVIEWED, |
| 451 | }, |
| 452 | { |
| 453 | type: ActionType.CHANGE, |
| 454 | key: ChangeActions.PRIVATE, |
| 455 | }, |
| 456 | { |
| 457 | type: ActionType.CHANGE, |
| 458 | key: ChangeActions.PRIVATE_DELETE, |
| 459 | }, |
| 460 | { |
| 461 | type: ActionType.CHANGE, |
| 462 | key: ChangeActions.FOLLOW_UP, |
| 463 | }, |
Dhruv Srivastava | 4dcb543 | 2021-04-26 16:45:07 +0200 | [diff] [blame] | 464 | { |
| 465 | type: ActionType.CHANGE, |
| 466 | key: ChangeActions.INCLUDED_IN, |
| 467 | }, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 468 | ]; |
| 469 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 470 | @state() actionPriorityOverrides: ActionPriorityOverride[] = []; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 471 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 472 | @state() additionalActions: UIActionInfo[] = []; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 473 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 474 | @state() hiddenActions: string[] = []; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 475 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 476 | @state() disabledMenuActions: string[] = []; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 477 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 478 | @state() editPatchsetLoaded = false; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 479 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 480 | @state() editMode = false; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 481 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 482 | @state() editBasedOnCurrentPatchSet = true; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 483 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 484 | @state() loggedIn = false; |
Paladox none | 7e2f9f3 | 2022-02-21 09:31:04 +0000 | [diff] [blame] | 485 | |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 486 | @state() pluginsLoaded = false; |
| 487 | |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 488 | @state() threadsWithSuggestions?: CommentThread[]; |
| 489 | |
Chris Poucet | c6e880b | 2021-11-15 19:57:06 +0100 | [diff] [blame] | 490 | private readonly restApiService = getAppContext().restApiService; |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 491 | |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 492 | private readonly reporting = getAppContext().reportingService; |
| 493 | |
| 494 | private readonly getPluginLoader = resolve(this, pluginLoaderToken); |
| 495 | |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 496 | private readonly getUserModel = resolve(this, userModelToken); |
| 497 | |
| 498 | private readonly getConfigModel = resolve(this, configModelToken); |
| 499 | |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 500 | private readonly getChangeModel = resolve(this, changeModelToken); |
| 501 | |
Chris Poucet | 20f0958 | 2022-10-24 23:29:27 +0200 | [diff] [blame] | 502 | private readonly getStorage = resolve(this, storageServiceToken); |
paladox | a80ea7c | 2022-02-19 17:42:15 +0000 | [diff] [blame] | 503 | |
Ben Rohlfs | 77c489a | 2022-09-21 14:25:56 +0200 | [diff] [blame] | 504 | private readonly getNavigation = resolve(this, navigationToken); |
| 505 | |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 506 | private readonly getCommentsModel = resolve(this, commentsModelToken); |
| 507 | |
Ben Rohlfs | f7f1e8e | 2021-03-12 14:36:40 +0100 | [diff] [blame] | 508 | constructor() { |
| 509 | super(); |
Paladox none | f4ddeed | 2023-02-22 19:30:47 +0000 | [diff] [blame] | 510 | subscribe( |
| 511 | this, |
| 512 | () => this.getChangeModel().latestPatchNum$, |
| 513 | x => (this.latestPatchNum = x) |
| 514 | ); |
Paladox none | d22af55 | 2023-04-10 15:31:00 +0000 | [diff] [blame] | 515 | subscribe( |
| 516 | this, |
| 517 | () => this.getChangeModel().patchsets$, |
| 518 | x => (this.editBasedOnCurrentPatchSet = hasEditBasedOnCurrentPatchSet(x)) |
| 519 | ); |
| 520 | subscribe( |
| 521 | this, |
| 522 | () => this.getChangeModel().patchNum$, |
| 523 | x => (this.editPatchsetLoaded = x === 'edit') |
| 524 | ); |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 525 | subscribe( |
| 526 | this, |
| 527 | () => this.getChangeModel().changeNum$, |
| 528 | x => (this.changeNum = x) |
| 529 | ); |
| 530 | subscribe( |
| 531 | this, |
| 532 | () => this.getChangeModel().change$, |
| 533 | x => (this.change = x) |
| 534 | ); |
| 535 | subscribe( |
| 536 | this, |
| 537 | () => this.getChangeModel().status$, |
| 538 | x => (this.changeStatus = x) |
| 539 | ); |
| 540 | subscribe( |
| 541 | this, |
Ben Rohlfs | 2add82f | 2024-02-26 19:23:01 +0100 | [diff] [blame] | 542 | () => this.getChangeModel().mergeable$, |
| 543 | x => (this.mergeable = x) |
| 544 | ); |
| 545 | subscribe( |
| 546 | this, |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 547 | () => this.getChangeModel().editMode$, |
| 548 | x => (this.editMode = x) |
| 549 | ); |
| 550 | subscribe( |
| 551 | this, |
| 552 | () => this.getChangeModel().revision$, |
| 553 | rev => (this.commitNum = rev?.commit?.commit) |
| 554 | ); |
| 555 | subscribe( |
| 556 | this, |
| 557 | () => this.getChangeModel().latestRevision$, |
| 558 | rev => (this.commitMessage = rev?.commit?.message ?? '') |
| 559 | ); |
| 560 | subscribe( |
| 561 | this, |
| 562 | () => this.getUserModel().account$, |
| 563 | x => (this.account = x) |
| 564 | ); |
| 565 | subscribe( |
| 566 | this, |
| 567 | () => this.getUserModel().loggedIn$, |
| 568 | x => (this.loggedIn = x) |
| 569 | ); |
| 570 | subscribe( |
| 571 | this, |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 572 | () => this.getPluginLoader().pluginsModel.pluginsLoaded$, |
| 573 | x => (this.pluginsLoaded = x) |
| 574 | ); |
| 575 | subscribe( |
| 576 | this, |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 577 | () => this.getConfigModel().repoConfig$, |
| 578 | config => (this.privateByDefault = config?.private_by_default) |
| 579 | ); |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 580 | subscribe( |
| 581 | this, |
| 582 | () => this.getCommentsModel().threadsWithSuggestions$, |
| 583 | x => (this.threadsWithSuggestions = x) |
| 584 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 585 | } |
Kasper Nilsson | 2d9610c | 2018-08-23 13:18:11 -0700 | [diff] [blame] | 586 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 587 | override connectedCallback() { |
| 588 | super.connectedCallback(); |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 589 | this.getPluginLoader().jsApiService.addElement( |
| 590 | TargetElement.CHANGE_ACTIONS, |
| 591 | this |
| 592 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 593 | } |
| 594 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 595 | static override get styles() { |
| 596 | return [ |
| 597 | sharedStyles, |
Dhruv Srivastava | 84575c9 | 2022-10-26 19:13:59 +0200 | [diff] [blame] | 598 | modalStyles, |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 599 | css` |
| 600 | :host { |
| 601 | display: flex; |
| 602 | font-family: var(--font-family); |
| 603 | } |
| 604 | #actionLoadingMessage, |
| 605 | #mainContent, |
| 606 | section { |
| 607 | display: flex; |
| 608 | } |
| 609 | #actionLoadingMessage, |
| 610 | gr-button, |
| 611 | gr-dropdown { |
| 612 | /* px because don't have the same font size */ |
| 613 | margin-left: 8px; |
| 614 | } |
| 615 | gr-button { |
| 616 | display: block; |
| 617 | } |
| 618 | #actionLoadingMessage { |
| 619 | align-items: center; |
| 620 | color: var(--deemphasized-text-color); |
| 621 | } |
| 622 | #confirmSubmitDialog .changeSubject { |
| 623 | margin: var(--spacing-l); |
| 624 | text-align: center; |
| 625 | } |
Chris Poucet | 1c71386 | 2022-07-25 13:12:24 +0200 | [diff] [blame] | 626 | gr-icon { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 627 | color: inherit; |
| 628 | margin-right: var(--spacing-xs); |
| 629 | } |
Chris Poucet | 1c71386 | 2022-07-25 13:12:24 +0200 | [diff] [blame] | 630 | #moreActions gr-icon { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 631 | margin: 0; |
| 632 | } |
| 633 | #moreMessage, |
| 634 | .hidden { |
| 635 | display: none; |
| 636 | } |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 637 | .info { |
| 638 | background-color: var(--info-background); |
| 639 | padding: var(--spacing-l) var(--spacing-xl); |
| 640 | margin-bottom: var(--spacing-l); |
| 641 | } |
| 642 | .info gr-icon { |
| 643 | color: var(--selected-foreground); |
| 644 | margin-right: var(--spacing-xl); |
| 645 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 646 | @media screen and (max-width: 50em) { |
| 647 | #mainContent { |
| 648 | flex-wrap: wrap; |
| 649 | } |
| 650 | gr-button { |
| 651 | --gr-button-padding: var(--spacing-m); |
| 652 | white-space: nowrap; |
| 653 | } |
| 654 | gr-button, |
| 655 | gr-dropdown { |
| 656 | margin: 0; |
| 657 | } |
| 658 | #actionLoadingMessage { |
| 659 | margin: var(--spacing-m); |
| 660 | text-align: center; |
| 661 | } |
| 662 | #moreMessage { |
| 663 | display: inline; |
| 664 | } |
| 665 | } |
| 666 | `, |
| 667 | ]; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 668 | } |
| 669 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 670 | override render() { |
| 671 | if (!this.change) return nothing; |
| 672 | return html` |
| 673 | <div id="mainContent"> |
| 674 | <span id="actionLoadingMessage" ?hidden=${!this.actionLoadingMessage}> |
| 675 | ${this.actionLoadingMessage} |
| 676 | </span> |
| 677 | <section |
| 678 | id="primaryActions" |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 679 | ?hidden=${this.isLoading() || |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 680 | !this.topLevelActions || |
| 681 | !this.topLevelActions.length} |
| 682 | > |
| 683 | ${this.topLevelPrimaryActions?.map(action => |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 684 | this.renderUIAction(action) |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 685 | )} |
| 686 | </section> |
| 687 | <section |
| 688 | id="secondaryActions" |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 689 | ?hidden=${this.isLoading() || |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 690 | !this.topLevelActions || |
| 691 | !this.topLevelActions.length} |
| 692 | > |
| 693 | ${this.topLevelSecondaryActions?.map(action => |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 694 | this.renderUIAction(action) |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 695 | )} |
| 696 | </section> |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 697 | <gr-button ?hidden=${!this.isLoading()}>Loading actions...</gr-button> |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 698 | <gr-dropdown |
| 699 | id="moreActions" |
| 700 | link |
| 701 | .verticalOffset=${32} |
| 702 | .horizontalAlign=${'right'} |
| 703 | @tap-item=${this.handleOverflowItemTap} |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 704 | ?hidden=${this.isLoading() || |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 705 | !this.menuActions || |
| 706 | !this.menuActions.length} |
| 707 | .disabledIds=${this.disabledMenuActions} |
| 708 | .items=${this.menuActions} |
| 709 | > |
Chris Poucet | 1c71386 | 2022-07-25 13:12:24 +0200 | [diff] [blame] | 710 | <gr-icon icon="more_vert" aria-labelledby="moreMessage"></gr-icon> |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 711 | <span id="moreMessage">More</span> |
| 712 | </gr-dropdown> |
| 713 | </div> |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 714 | <dialog id="actionsModal" tabindex="-1"> |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 715 | <gr-confirm-rebase-dialog |
| 716 | id="confirmRebase" |
| 717 | class="confirmDialog" |
Ben Rohlfs | 5b3c655 | 2023-02-18 13:02:46 +0100 | [diff] [blame] | 718 | @confirm-rebase=${this.handleRebaseConfirm} |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 719 | @cancel=${this.handleConfirmDialogCancel} |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 720 | .disableActions=${this.inProgressActionKeys.has( |
| 721 | RevisionActions.REBASE |
| 722 | )} |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 723 | .branch=${this.change?.branch} |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 724 | .rebaseOnCurrent=${!!this.revisionActions?.rebase?.enabled} |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 725 | ></gr-confirm-rebase-dialog> |
| 726 | <gr-confirm-cherrypick-dialog |
| 727 | id="confirmCherrypick" |
| 728 | class="confirmDialog" |
| 729 | .changeStatus=${this.changeStatus} |
| 730 | .commitMessage=${this.commitMessage} |
| 731 | .commitNum=${this.commitNum} |
| 732 | @confirm=${this.handleCherrypickConfirm} |
| 733 | @cancel=${this.handleConfirmDialogCancel} |
| 734 | .project=${this.change?.project} |
| 735 | ></gr-confirm-cherrypick-dialog> |
| 736 | <gr-confirm-cherrypick-conflict-dialog |
| 737 | id="confirmCherrypickConflict" |
| 738 | class="confirmDialog" |
| 739 | @confirm=${this.handleCherrypickConflictConfirm} |
| 740 | @cancel=${this.handleConfirmDialogCancel} |
| 741 | ></gr-confirm-cherrypick-conflict-dialog> |
| 742 | <gr-confirm-move-dialog |
| 743 | id="confirmMove" |
| 744 | class="confirmDialog" |
| 745 | @confirm=${this.handleMoveConfirm} |
| 746 | @cancel=${this.handleConfirmDialogCancel} |
| 747 | .project=${this.change?.project} |
| 748 | ></gr-confirm-move-dialog> |
| 749 | <gr-confirm-revert-dialog |
| 750 | id="confirmRevertDialog" |
| 751 | class="confirmDialog" |
Ben Rohlfs | 5b3c655 | 2023-02-18 13:02:46 +0100 | [diff] [blame] | 752 | @confirm-revert=${this.handleRevertDialogConfirm} |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 753 | @cancel=${this.handleConfirmDialogCancel} |
| 754 | ></gr-confirm-revert-dialog> |
| 755 | <gr-confirm-abandon-dialog |
| 756 | id="confirmAbandonDialog" |
| 757 | class="confirmDialog" |
| 758 | @confirm=${this.handleAbandonDialogConfirm} |
| 759 | @cancel=${this.handleConfirmDialogCancel} |
| 760 | ></gr-confirm-abandon-dialog> |
| 761 | <gr-confirm-submit-dialog |
| 762 | id="confirmSubmitDialog" |
| 763 | class="confirmDialog" |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 764 | .action=${this.revisionActions?.submit} |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 765 | @cancel=${this.handleConfirmDialogCancel} |
| 766 | @confirm=${this.handleSubmitConfirm} |
| 767 | ></gr-confirm-submit-dialog> |
| 768 | <gr-dialog |
| 769 | id="createFollowUpDialog" |
| 770 | class="confirmDialog" |
| 771 | confirm-label="Create" |
| 772 | @confirm=${this.handleCreateFollowUpChange} |
| 773 | @cancel=${this.handleCloseCreateFollowUpChange} |
| 774 | > |
| 775 | <div class="header" slot="header">Create Follow-Up Change</div> |
| 776 | <div class="main" slot="main"> |
| 777 | <gr-create-change-dialog |
| 778 | id="createFollowUpChange" |
| 779 | .branch=${this.change?.branch} |
| 780 | .baseChange=${this.change?.id} |
| 781 | .repoName=${this.change?.project} |
| 782 | .privateByDefault=${this.privateByDefault} |
| 783 | ></gr-create-change-dialog> |
| 784 | </div> |
| 785 | </gr-dialog> |
| 786 | <gr-dialog |
| 787 | id="confirmDeleteDialog" |
| 788 | class="confirmDialog" |
| 789 | confirm-label="Delete" |
| 790 | confirm-on-enter="" |
| 791 | @cancel=${this.handleConfirmDialogCancel} |
| 792 | @confirm=${this.handleDeleteConfirm} |
| 793 | > |
| 794 | <div class="header" slot="header">Delete Change</div> |
| 795 | <div class="main" slot="main"> |
| 796 | Do you really want to delete the change? |
| 797 | </div> |
| 798 | </gr-dialog> |
| 799 | <gr-dialog |
| 800 | id="confirmDeleteEditDialog" |
| 801 | class="confirmDialog" |
| 802 | confirm-label="Delete" |
| 803 | confirm-on-enter="" |
| 804 | @cancel=${this.handleConfirmDialogCancel} |
| 805 | @confirm=${this.handleDeleteEditConfirm} |
| 806 | > |
| 807 | <div class="header" slot="header">Delete Change Edit</div> |
| 808 | <div class="main" slot="main"> |
| 809 | Do you really want to delete the edit? |
| 810 | </div> |
| 811 | </gr-dialog> |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 812 | <gr-dialog |
| 813 | id="confirmPublishEditDialog" |
| 814 | class="confirmDialog" |
| 815 | confirm-label="Publish" |
| 816 | confirm-on-enter="" |
| 817 | @cancel=${this.handleConfirmDialogCancel} |
| 818 | @confirm=${this.handlePublishEditConfirm} |
| 819 | > |
| 820 | <div class="header" slot="header">Publish Change Edit</div> |
| 821 | <div class="main" slot="main"> |
| 822 | ${when( |
| 823 | this.numberOfThreadsWithSuggestions() > 0, |
| 824 | () => html`<p class="info"> |
| 825 | <gr-icon id="icon" icon="info" small></gr-icon> |
| 826 | Heads Up! ${this.numberOfThreadsWithSuggestions()} comments have |
| 827 | suggestions you can apply before publishing |
| 828 | </p>` |
| 829 | )} |
| 830 | Do you really want to publish the edit? |
| 831 | </div> |
| 832 | </gr-dialog> |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 833 | </dialog> |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 834 | `; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 835 | } |
| 836 | |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 837 | private renderUIAction(action: UIActionInfo) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 838 | return html` |
| 839 | <gr-tooltip-content |
| 840 | title=${ifDefined(action.title)} |
| 841 | .hasTooltip=${!!action.title} |
| 842 | ?position-below=${true} |
| 843 | > |
| 844 | <gr-button |
| 845 | link |
| 846 | class=${action.__key} |
| 847 | data-action-key=${action.__key} |
| 848 | data-label=${action.label} |
| 849 | ?disabled=${this.calculateDisabled(action)} |
| 850 | @click=${(e: MouseEvent) => |
| 851 | this.handleActionTap(e, action.__key, action.__type)} |
| 852 | > |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 853 | ${this.renderUIActionIcon(action)} ${action.label} |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 854 | </gr-button> |
| 855 | </gr-tooltip-content> |
| 856 | `; |
| 857 | } |
| 858 | |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 859 | private renderUIActionIcon(action: UIActionInfo) { |
| 860 | if (!action.icon) return nothing; |
Chris Poucet | a6b629c | 2022-08-12 16:25:48 +0200 | [diff] [blame] | 861 | return html` |
| 862 | <gr-icon icon=${action.icon} ?filled=${action.filled}></gr-icon> |
| 863 | `; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 864 | } |
| 865 | |
| 866 | override willUpdate(changedProperties: PropertyValues) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 867 | if (changedProperties.has('change')) { |
| 868 | this.reload(); |
Milutin Kristofic | 7e0312a | 2022-06-17 15:58:26 +0200 | [diff] [blame] | 869 | this.actions = this.change?.actions ?? {}; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 870 | } |
| 871 | |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 872 | this.editStatusChanged(); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 873 | |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 874 | this.actionsChanged(); |
| 875 | this.allActionValues = this.computeAllActions(); |
| 876 | this.topLevelActions = this.allActionValues.filter(a => { |
| 877 | if (this.hiddenActions.includes(a.__key)) return false; |
| 878 | if (this.editMode) return EDIT_ACTIONS.has(a.__key); |
Ben Rohlfs | 7329430 | 2024-02-26 17:07:40 +0100 | [diff] [blame] | 879 | return !this.isOverflowAction(a.__type, a.__key); |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 880 | }); |
| 881 | this.topLevelPrimaryActions = this.topLevelActions.filter( |
| 882 | action => action.__primary |
| 883 | ); |
| 884 | this.topLevelSecondaryActions = this.topLevelActions.filter( |
| 885 | action => !action.__primary |
| 886 | ); |
| 887 | this.menuActions = this.computeMenuActions(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 888 | } |
| 889 | |
| 890 | reload() { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 891 | if (!this.changeNum || !this.latestPatchNum || !this.change) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 892 | return Promise.resolve(); |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 893 | } |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 894 | const change = this.change; |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 895 | this.revisionActions = undefined; |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 896 | return this.restApiService |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 897 | .getChangeRevisionActions(this.changeNum, this.latestPatchNum) |
| 898 | .then(revisionActions => { |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 899 | this.revisionActions = revisionActions ?? {}; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 900 | this.sendShowRevisionActions({ |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 901 | change: change as ChangeInfo, |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 902 | revisionActions: this.revisionActions, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 903 | }); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 904 | }) |
| 905 | .catch(err => { |
Milutin Kristofic | 860fe4d | 2020-11-23 16:13:45 +0100 | [diff] [blame] | 906 | fireAlert(this, ERR_REVISION_ACTIONS); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 907 | throw err; |
| 908 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 909 | } |
Andrew Bonventre | 1508cac | 2016-04-02 21:37:15 -0400 | [diff] [blame] | 910 | |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 911 | private isLoading() { |
| 912 | return ( |
| 913 | !this.pluginsLoaded || |
| 914 | !this.change || |
Ben Rohlfs | 2add82f | 2024-02-26 19:23:01 +0100 | [diff] [blame] | 915 | this.mergeable === undefined || |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 916 | this.revisionActions === undefined |
Ben Rohlfs | 5550f45 | 2024-02-26 19:12:11 +0100 | [diff] [blame] | 917 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 918 | } |
Viktar Donich | 935b4e9 | 2018-03-26 13:13:00 -0700 | [diff] [blame] | 919 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 920 | // private but used in test |
Ben Rohlfs | 4e91353 | 2022-10-24 12:31:58 +0200 | [diff] [blame] | 921 | sendShowRevisionActions(detail: ShowRevisionActionsDetail) { |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 922 | this.getPluginLoader().jsApiService.handleShowRevisionActions(detail); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 923 | } |
Tao Zhou | 2943bec | 2020-03-09 09:29:35 +0100 | [diff] [blame] | 924 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 925 | addActionButton(type: ActionType, label: string) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 926 | if (type !== ActionType.CHANGE && type !== ActionType.REVISION) { |
| 927 | throw Error(`Invalid action type: ${type}`); |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 928 | } |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 929 | const action: UIActionInfo = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 930 | enabled: true, |
| 931 | label, |
| 932 | __type: type, |
Ben Rohlfs | ba44082 | 2023-04-11 18:08:03 +0200 | [diff] [blame] | 933 | __key: ADDITIONAL_ACTION_KEY_PREFIX + uuid(), |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 934 | }; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 935 | this.additionalActions.push(action); |
| 936 | this.requestUpdate('additionalActions'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 937 | return action.__key; |
| 938 | } |
Andrew Bonventre | cd73e96 | 2016-06-22 17:52:56 -0400 | [diff] [blame] | 939 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 940 | removeActionButton(key: string) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 941 | const idx = this.indexOfActionButtonWithKey(key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 942 | if (idx === -1) { |
| 943 | return; |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 944 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 945 | this.additionalActions.splice(idx, 1); |
| 946 | this.requestUpdate('additionalActions'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 947 | } |
Andrew Bonventre | cd73e96 | 2016-06-22 17:52:56 -0400 | [diff] [blame] | 948 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 949 | setActionButtonProp<T extends keyof UIActionInfo>( |
| 950 | key: string, |
| 951 | prop: T, |
| 952 | value: UIActionInfo[T] |
| 953 | ) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 954 | this.additionalActions[this.indexOfActionButtonWithKey(key)][prop] = value; |
| 955 | this.requestUpdate('additionalActions'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 956 | } |
Andrew Bonventre | a6eb943 | 2016-06-28 16:37:41 -0400 | [diff] [blame] | 957 | |
Ben Rohlfs | 7329430 | 2024-02-26 17:07:40 +0100 | [diff] [blame] | 958 | // TODO: Rename to toggleOverflow(). |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 959 | setActionOverflow(type: ActionType, key: string, overflow: boolean) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 960 | if (type !== ActionType.CHANGE && type !== ActionType.REVISION) { |
| 961 | throw Error(`Invalid action type given: ${type}`); |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 962 | } |
Ben Rohlfs | 7329430 | 2024-02-26 17:07:40 +0100 | [diff] [blame] | 963 | const isCurrentlyOverflow = this.isOverflowAction(type, key); |
| 964 | if (overflow === isCurrentlyOverflow) { |
| 965 | return; |
| 966 | } |
| 967 | |
| 968 | // remove from overflowActions |
| 969 | if (!overflow) { |
| 970 | this.overflowActions = this.overflowActions.filter( |
| 971 | action => action.type !== type || action.key !== key |
| 972 | ); |
| 973 | } |
| 974 | // add to overflowActions |
| 975 | if (overflow) { |
| 976 | this.overflowActions = [...this.overflowActions, {type, key}]; |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 977 | } |
| 978 | } |
| 979 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 980 | setActionPriority( |
| 981 | type: ActionType.CHANGE | ActionType.REVISION, |
| 982 | key: string, |
| 983 | priority: ActionPriority |
| 984 | ) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 985 | if (type !== ActionType.CHANGE && type !== ActionType.REVISION) { |
| 986 | throw Error(`Invalid action type given: ${type}`); |
| 987 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 988 | const index = this.actionPriorityOverrides.findIndex( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 989 | action => action.type === type && action.key === key |
| 990 | ); |
| 991 | const action: ActionPriorityOverride = { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 992 | type, |
| 993 | key, |
| 994 | priority, |
| 995 | }; |
| 996 | if (index !== -1) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 997 | this.actionPriorityOverrides[index] = action; |
| 998 | this.requestUpdate('actionPriorityOverrides'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 999 | } else { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1000 | this.actionPriorityOverrides.push(action); |
| 1001 | this.requestUpdate('actionPriorityOverrides'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1002 | } |
| 1003 | } |
| 1004 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1005 | setActionHidden( |
| 1006 | type: ActionType.CHANGE | ActionType.REVISION, |
| 1007 | key: string, |
| 1008 | hidden: boolean |
| 1009 | ) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1010 | if (type !== ActionType.CHANGE && type !== ActionType.REVISION) { |
| 1011 | throw Error(`Invalid action type given: ${type}`); |
| 1012 | } |
| 1013 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1014 | const idx = this.hiddenActions.indexOf(key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1015 | if (hidden && idx === -1) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1016 | this.hiddenActions.push(key); |
| 1017 | this.requestUpdate('hiddenActions'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1018 | } else if (!hidden && idx !== -1) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1019 | this.hiddenActions.splice(idx, 1); |
| 1020 | this.requestUpdate('hiddenActions'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1021 | } |
| 1022 | } |
| 1023 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1024 | getActionDetails(actionName: string) { |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1025 | if (this.revisionActions?.[actionName]) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1026 | return this.revisionActions[actionName]; |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1027 | } else if (this.actions?.[actionName]) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1028 | return this.actions[actionName]; |
| 1029 | } else { |
| 1030 | return undefined; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1031 | } |
| 1032 | } |
| 1033 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1034 | private indexOfActionButtonWithKey(key: string) { |
| 1035 | for (let i = 0; i < this.additionalActions.length; i++) { |
| 1036 | if (this.additionalActions[i].__key === key) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1037 | return i; |
| 1038 | } |
| 1039 | } |
| 1040 | return -1; |
| 1041 | } |
| 1042 | |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1043 | private actionsChanged() { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1044 | this.actionLoadingMessage = ''; |
| 1045 | this.disabledMenuActions = []; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1046 | |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1047 | if (this.revisionActions && !this.revisionActions.download) { |
Ben Rohlfs | 2eb8d52 | 2023-08-21 14:59:15 +0200 | [diff] [blame] | 1048 | this.revisionActions = { |
| 1049 | ...this.revisionActions, |
| 1050 | download: DOWNLOAD_ACTION, |
| 1051 | }; |
| 1052 | fire(this, 'revision-actions-changed', { |
| 1053 | value: this.revisionActions, |
| 1054 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1055 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1056 | if ( |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1057 | !this.actions.includedIn && |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1058 | this.change?.status === ChangeStatus.MERGED |
| 1059 | ) { |
| 1060 | this.actions = {...this.actions, includedIn: INCLUDED_IN_ACTION}; |
Dhruv Srivastava | 4dcb543 | 2021-04-26 16:45:07 +0200 | [diff] [blame] | 1061 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1062 | } |
| 1063 | |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1064 | private editStatusChanged() { |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1065 | if (!this.change || !this.loggedIn) return; |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1066 | if (this.editPatchsetLoaded) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1067 | // Only show actions that mutate an edit if an actual edit patch set |
| 1068 | // is loaded. |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1069 | if (changeIsOpen(this.change)) { |
| 1070 | if (this.editBasedOnCurrentPatchSet) { |
| 1071 | if (!this.actions.publishEdit) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1072 | this.actions = {...this.actions, publishEdit: PUBLISH_EDIT}; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1073 | } |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1074 | delete this.actions.rebaseEdit; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1075 | } else { |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1076 | if (!this.actions.rebaseEdit) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1077 | this.actions = {...this.actions, rebaseEdit: REBASE_EDIT}; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1078 | } |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1079 | delete this.actions.publishEdit; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1080 | } |
| 1081 | } |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1082 | if (!this.actions.deleteEdit) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1083 | this.actions = {...this.actions, deleteEdit: DELETE_EDIT}; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1084 | } |
| 1085 | } else { |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1086 | delete this.actions.rebaseEdit; |
| 1087 | delete this.actions.publishEdit; |
| 1088 | delete this.actions.deleteEdit; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1089 | } |
| 1090 | |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1091 | if (changeIsOpen(this.change)) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1092 | // Only show edit button if there is no edit patchset loaded and the |
| 1093 | // file list is not in edit mode. |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1094 | if (this.editPatchsetLoaded || this.editMode) { |
| 1095 | delete this.actions.edit; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1096 | } else { |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1097 | if (!this.actions.edit) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1098 | this.actions = {...this.actions, edit: EDIT}; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1099 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1100 | } |
| 1101 | // Only show STOP_EDIT if edit mode is enabled, but no edit patch set |
| 1102 | // is loaded. |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1103 | if (this.editMode && !this.editPatchsetLoaded) { |
| 1104 | if (!this.actions.stopEdit) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1105 | this.actions = {...this.actions, stopEdit: STOP_EDIT}; |
Milutin Kristofic | f0b380e | 2021-01-26 11:55:12 +0100 | [diff] [blame] | 1106 | fireAlert(this, 'Change is in edit mode'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1107 | } |
| 1108 | } else { |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1109 | delete this.actions.stopEdit; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1110 | } |
| 1111 | } else { |
| 1112 | // Remove edit button. |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 1113 | delete this.actions.edit; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1114 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1115 | } |
| 1116 | |
| 1117 | private getValuesFor<T>(obj: {[key: string]: T}): T[] { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1118 | return Object.keys(obj).map(key => obj[key]); |
| 1119 | } |
| 1120 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1121 | private getLabelStatus(label: LabelInfo): LabelStatus { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1122 | if (isQuickLabelInfo(label)) { |
| 1123 | if (label.approved) { |
| 1124 | return LabelStatus.OK; |
| 1125 | } else if (label.rejected) { |
| 1126 | return LabelStatus.REJECT; |
| 1127 | } |
| 1128 | } |
| 1129 | if (label.optional) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1130 | return LabelStatus.OPTIONAL; |
| 1131 | } else { |
| 1132 | return LabelStatus.NEED; |
| 1133 | } |
| 1134 | } |
| 1135 | |
| 1136 | /** |
| 1137 | * Get highest score for last missing permitted label for current change. |
| 1138 | * Returns null if no labels permitted or more than one label missing. |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1139 | */ |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1140 | private getTopMissingApproval() { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1141 | if (!this.change || !this.change.labels || !this.change.permitted_labels) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1142 | return null; |
| 1143 | } |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1144 | if (this.change?.status === ChangeStatus.MERGED) { |
Frank Borden | 99c15d7 | 2020-12-10 17:30:29 -0800 | [diff] [blame] | 1145 | return null; |
| 1146 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1147 | let result; |
Ben Rohlfs | 7b71b11 | 2021-02-12 10:36:08 +0100 | [diff] [blame] | 1148 | for (const [label, labelInfo] of Object.entries(this.change.labels)) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1149 | if (!(label in this.change.permitted_labels)) { |
| 1150 | continue; |
| 1151 | } |
| 1152 | if (this.change.permitted_labels[label].length === 0) { |
| 1153 | continue; |
| 1154 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1155 | const status = this.getLabelStatus(labelInfo); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1156 | if (status === LabelStatus.NEED) { |
| 1157 | if (result) { |
Dhruv Srivastava | 25ca8ea | 2021-03-31 21:37:30 +0200 | [diff] [blame] | 1158 | // More than one label is missing, so check if Code Review can be |
| 1159 | // given |
| 1160 | result = null; |
| 1161 | break; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1162 | } |
| 1163 | result = label; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1164 | } else if ( |
| 1165 | status === LabelStatus.REJECT || |
| 1166 | status === LabelStatus.IMPOSSIBLE |
| 1167 | ) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1168 | return null; |
| 1169 | } |
| 1170 | } |
Frank Borden | a42cf77 | 2020-11-23 21:10:09 -0800 | [diff] [blame] | 1171 | // Allow the user to use quick approve to vote the max score on code review |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 1172 | // even if it is already granted by someone else. Does not apply if the |
| 1173 | // user owns the change or has already granted the max score themselves. |
Milutin Kristofic | bd44580 | 2021-10-20 21:00:21 +0200 | [diff] [blame] | 1174 | const codeReviewLabel = this.change.labels[StandardLabels.CODE_REVIEW]; |
| 1175 | const codeReviewPermittedValues = |
| 1176 | this.change.permitted_labels[StandardLabels.CODE_REVIEW]; |
Frank Borden | a42cf77 | 2020-11-23 21:10:09 -0800 | [diff] [blame] | 1177 | if ( |
| 1178 | !result && |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 1179 | codeReviewLabel && |
| 1180 | codeReviewPermittedValues && |
| 1181 | this.account?._account_id && |
| 1182 | isDetailedLabelInfo(codeReviewLabel) && |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 1183 | !isOwner(this.change, this.account) && |
| 1184 | getApprovalInfo(codeReviewLabel, this.account)?.value !== |
| 1185 | getVotingRange(codeReviewLabel)?.max |
Frank Borden | a42cf77 | 2020-11-23 21:10:09 -0800 | [diff] [blame] | 1186 | ) { |
Milutin Kristofic | bd44580 | 2021-10-20 21:00:21 +0200 | [diff] [blame] | 1187 | result = StandardLabels.CODE_REVIEW; |
Frank Borden | a42cf77 | 2020-11-23 21:10:09 -0800 | [diff] [blame] | 1188 | } |
| 1189 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1190 | if (result) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1191 | const labelInfo = this.change.labels[result]; |
| 1192 | if (!isDetailedLabelInfo(labelInfo)) { |
| 1193 | return null; |
| 1194 | } |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 1195 | const permittedValues = this.change.permitted_labels[result]; |
| 1196 | const usersMaxPermittedScore = |
| 1197 | permittedValues[permittedValues.length - 1]; |
| 1198 | const maxScoreForLabel = getVotingRange(labelInfo)?.max; |
| 1199 | if (Number(usersMaxPermittedScore) === maxScoreForLabel) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1200 | // Allow quick approve only for maximal score. |
| 1201 | return { |
| 1202 | label: result, |
Frank Borden | 481e5f9 | 2020-11-30 19:59:09 -0800 | [diff] [blame] | 1203 | score: usersMaxPermittedScore, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1204 | }; |
| 1205 | } |
| 1206 | } |
| 1207 | return null; |
| 1208 | } |
| 1209 | |
| 1210 | hideQuickApproveAction() { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1211 | if (!this.topLevelSecondaryActions) { |
| 1212 | throw new Error('topLevelSecondaryActions must be set'); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1213 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1214 | this.topLevelSecondaryActions = this.topLevelSecondaryActions.filter( |
Dhruv Srivastava | 25ca8ea | 2021-03-31 21:37:30 +0200 | [diff] [blame] | 1215 | sa => !isQuickApproveAction(sa) |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1216 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1217 | this._hideQuickApproveAction = true; |
| 1218 | } |
| 1219 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1220 | private getQuickApproveAction(): QuickApproveUIActionInfo | null { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1221 | if (this._hideQuickApproveAction) { |
| 1222 | return null; |
| 1223 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1224 | const approval = this.getTopMissingApproval(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1225 | if (!approval) { |
| 1226 | return null; |
| 1227 | } |
Tao Zhou | 4cd35cb | 2020-07-22 11:28:22 +0200 | [diff] [blame] | 1228 | const action = {...QUICK_APPROVE_ACTION}; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1229 | action.label = approval.label + approval.score; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1230 | |
| 1231 | const score = Number(approval.score); |
| 1232 | if (isNaN(score)) { |
| 1233 | return null; |
| 1234 | } |
| 1235 | |
| 1236 | const review: ReviewInput = { |
| 1237 | drafts: DraftsAction.PUBLISH_ALL_REVISIONS, |
| 1238 | labels: { |
| 1239 | [approval.label]: score, |
| 1240 | }, |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1241 | }; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1242 | action.payload = review; |
| 1243 | return action; |
| 1244 | } |
| 1245 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1246 | private getActionValues( |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1247 | actionsChange: ActionNameToActionInfoMap | undefined, |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1248 | primariesChange: PrimaryActionKey[], |
| 1249 | additionalActionsChange: UIActionInfo[], |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1250 | type: ActionType |
| 1251 | ): UIActionInfo[] { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1252 | if (!actionsChange || !primariesChange) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1253 | return []; |
| 1254 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1255 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1256 | const actions = actionsChange; |
| 1257 | const primaryActionKeys = primariesChange; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1258 | const result: UIActionInfo[] = []; |
| 1259 | const values: Array<ChangeActions | RevisionActions> = |
| 1260 | type === ActionType.CHANGE |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1261 | ? this.getValuesFor(ChangeActions) |
| 1262 | : this.getValuesFor(RevisionActions); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1263 | |
| 1264 | const pluginActions: UIActionInfo[] = []; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1265 | Object.keys(actions).forEach(a => { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1266 | const action: UIActionInfo = actions[a] as UIActionInfo; |
| 1267 | action.__key = a; |
| 1268 | action.__type = type; |
| 1269 | action.__primary = primaryActionKeys.includes(a as PrimaryActionKey); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1270 | // Plugin actions always contain ~ in the key. |
| 1271 | if (a.indexOf('~') !== -1) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1272 | this.populateActionUrl(action); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1273 | pluginActions.push(action); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1274 | // Add server-side provided plugin actions to overflow menu. |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1275 | this.overflowActions.push({ |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1276 | type, |
| 1277 | key: a, |
| 1278 | }); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1279 | this.requestUpdate('overflowActions'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1280 | return; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1281 | } else if (!values.includes(a as PrimaryActionKey)) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1282 | return; |
| 1283 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1284 | action.label = this.getActionLabel(action); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1285 | |
| 1286 | // Triggers a re-render by ensuring object inequality. |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1287 | result.push({...action}); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1288 | }); |
| 1289 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1290 | let additionalActions = additionalActionsChange; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1291 | additionalActions = additionalActions |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1292 | .filter(a => a.__type === type) |
| 1293 | .map(a => { |
| 1294 | a.__primary = primaryActionKeys.includes(a.__key as PrimaryActionKey); |
| 1295 | // Triggers a re-render by ensuring object inequality. |
| 1296 | return {...a}; |
| 1297 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1298 | return result.concat(additionalActions).concat(pluginActions); |
| 1299 | } |
| 1300 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1301 | private populateActionUrl(action: UIActionInfo) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1302 | const patchNum = |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1303 | action.__type === ActionType.REVISION ? this.latestPatchNum : undefined; |
| 1304 | if (!this.changeNum) { |
| 1305 | return; |
| 1306 | } |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 1307 | this.restApiService |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1308 | .getChangeActionURL(this.changeNum, patchNum, '/' + action.__key) |
| 1309 | .then(url => (action.__url = url)); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1310 | } |
| 1311 | |
| 1312 | /** |
| 1313 | * Given a change action, return a display label that uses the appropriate |
| 1314 | * casing or includes explanatory details. |
| 1315 | */ |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1316 | private getActionLabel(action: UIActionInfo) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1317 | if (action.label === 'Delete') { |
| 1318 | // This label is common within change and revision actions. Make it more |
| 1319 | // explicit to the user. |
| 1320 | return 'Delete change'; |
| 1321 | } else if (action.label === 'WIP') { |
| 1322 | return 'Mark as work in progress'; |
| 1323 | } |
| 1324 | // Otherwise, just map the name to sentence case. |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1325 | return this.toSentenceCase(action.label); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1326 | } |
| 1327 | |
| 1328 | /** |
Frank Borden | 5bf43b6 | 2022-06-24 16:29:49 +0200 | [diff] [blame] | 1329 | * Capitalize the first letter and lowercase all others. |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1330 | * |
| 1331 | * private but used in test |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1332 | */ |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1333 | toSentenceCase(s: string) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1334 | if (!s.length) { |
| 1335 | return ''; |
| 1336 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1337 | return s[0].toUpperCase() + s.slice(1).toLowerCase(); |
| 1338 | } |
| 1339 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1340 | private computeLoadingLabel(action: string) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1341 | return ActionLoadingLabels[action] || 'Working...'; |
| 1342 | } |
| 1343 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1344 | // private but used in test |
| 1345 | canSubmitChange() { |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1346 | if (!this.change) return false; |
| 1347 | const change = this.change as ChangeInfo; |
| 1348 | const revision = this.getRevision(change, this.latestPatchNum); |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 1349 | return this.getPluginLoader().jsApiService.canSubmitChange( |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1350 | change, |
| 1351 | revision |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1352 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1353 | } |
| 1354 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1355 | // private but used in test |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1356 | getRevision(change: ChangeInfo, patchNum?: PatchSetNumber) { |
| 1357 | for (const rev of Object.values(change.revisions ?? {})) { |
Dhruv Srivastava | d1da458 | 2021-01-11 16:34:19 +0100 | [diff] [blame] | 1358 | if (rev._number === patchNum) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1359 | return rev; |
| 1360 | } |
| 1361 | } |
| 1362 | return null; |
| 1363 | } |
| 1364 | |
| 1365 | showRevertDialog() { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1366 | const change = this.change; |
| 1367 | if (!change) return; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1368 | const query = `submissionid: "${change.submission_id}"`; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1369 | /* A chromium plugin expects that the modifyRevertMsg hook will only |
| 1370 | be called after the revert button is pressed, hence we populate the |
| 1371 | revert dialog after revert button is pressed. */ |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 1372 | this.restApiService.getChanges(0, query).then(changes => { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1373 | if (!changes) { |
Kamil Musin | f0ece02 | 2022-10-14 15:22:44 +0200 | [diff] [blame] | 1374 | this.reporting.error( |
| 1375 | 'Change Actions', |
| 1376 | new Error('getChanges returns undefined') |
| 1377 | ); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1378 | return; |
| 1379 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1380 | assertIsDefined(this.confirmRevertDialog, 'confirmRevertDialog'); |
Kamil Musin | 808b4f2 | 2022-12-08 17:43:11 +0100 | [diff] [blame] | 1381 | this.confirmRevertDialog.populate( |
| 1382 | change, |
| 1383 | this.commitMessage, |
| 1384 | changes.length |
| 1385 | ); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1386 | this.showActionDialog(this.confirmRevertDialog); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1387 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1388 | } |
| 1389 | |
Joerg Zieren | 79b448c | 2021-08-12 16:36:37 +0200 | [diff] [blame] | 1390 | showSubmitDialog() { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1391 | if (!this.canSubmitChange()) { |
Joerg Zieren | 79b448c | 2021-08-12 16:36:37 +0200 | [diff] [blame] | 1392 | return; |
| 1393 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1394 | assertIsDefined(this.confirmSubmitDialog, 'confirmSubmitDialog'); |
| 1395 | this.showActionDialog(this.confirmSubmitDialog); |
Joerg Zieren | 79b448c | 2021-08-12 16:36:37 +0200 | [diff] [blame] | 1396 | } |
| 1397 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1398 | private handleActionTap(e: MouseEvent, key: string, type: string) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1399 | e.preventDefault(); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1400 | let el = e.target as Element; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1401 | while (el.tagName.toLowerCase() !== 'gr-button') { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1402 | if (!el.parentElement) { |
| 1403 | return; |
| 1404 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1405 | el = el.parentElement; |
| 1406 | } |
| 1407 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1408 | if ( |
| 1409 | key.startsWith(ADDITIONAL_ACTION_KEY_PREFIX) || |
| 1410 | key.indexOf('~') !== -1 |
| 1411 | ) { |
| 1412 | this.dispatchEvent( |
| 1413 | new CustomEvent(`${key}-tap`, { |
| 1414 | detail: {node: el}, |
| 1415 | composed: true, |
| 1416 | bubbles: true, |
| 1417 | }) |
| 1418 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1419 | return; |
| 1420 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1421 | this.handleAction(type as ActionType, key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1422 | } |
| 1423 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1424 | private handleOverflowItemTap(e: CustomEvent<MenuAction>) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1425 | e.preventDefault(); |
Paladox none | 999b73a9 | 2022-06-25 16:04:43 +0000 | [diff] [blame] | 1426 | const el = e.target as Element; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1427 | const key = e.detail.action.__key; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1428 | if ( |
| 1429 | key.startsWith(ADDITIONAL_ACTION_KEY_PREFIX) || |
| 1430 | key.indexOf('~') !== -1 |
| 1431 | ) { |
| 1432 | this.dispatchEvent( |
| 1433 | new CustomEvent(`${key}-tap`, { |
| 1434 | detail: {node: el}, |
| 1435 | composed: true, |
| 1436 | bubbles: true, |
| 1437 | }) |
| 1438 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1439 | return; |
| 1440 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1441 | this.handleAction(e.detail.action.__type, e.detail.action.__key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1442 | } |
| 1443 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1444 | // private but used in test |
| 1445 | handleAction(type: ActionType, key: string) { |
Milutin Kristofic | da88b33 | 2020-03-24 10:19:12 +0100 | [diff] [blame] | 1446 | this.reporting.reportInteraction(`${type}-${key}`); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1447 | switch (type) { |
| 1448 | case ActionType.REVISION: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1449 | this.handleRevisionAction(key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1450 | break; |
| 1451 | case ActionType.CHANGE: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1452 | this.handleChangeAction(key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1453 | break; |
| 1454 | default: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1455 | this.fireAction( |
| 1456 | this.prependSlash(key), |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1457 | assertUIActionInfo(this.actions[key]), |
| 1458 | false |
| 1459 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1460 | } |
| 1461 | } |
| 1462 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1463 | // private but used in test |
| 1464 | handleChangeAction(key: string) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1465 | switch (key) { |
| 1466 | case ChangeActions.REVERT: |
| 1467 | this.showRevertDialog(); |
| 1468 | break; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1469 | case ChangeActions.ABANDON: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1470 | assertIsDefined(this.confirmAbandonDialog, 'confirmAbandonDialog'); |
| 1471 | this.showActionDialog(this.confirmAbandonDialog); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1472 | break; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1473 | case QUICK_APPROVE_ACTION.key: { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1474 | const action = this.allActionValues.find(isQuickApproveAction); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1475 | if (!action) { |
| 1476 | return; |
| 1477 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1478 | this.fireAction(this.prependSlash(key), action, true, action.payload); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1479 | break; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1480 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1481 | case ChangeActions.EDIT: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1482 | this.handleEditTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1483 | break; |
| 1484 | case ChangeActions.STOP_EDIT: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1485 | this.handleStopEditTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1486 | break; |
| 1487 | case ChangeActions.DELETE: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1488 | this.handleDeleteTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1489 | break; |
| 1490 | case ChangeActions.DELETE_EDIT: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1491 | this.handleDeleteEditTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1492 | break; |
| 1493 | case ChangeActions.FOLLOW_UP: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1494 | this.handleFollowUpTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1495 | break; |
| 1496 | case ChangeActions.WIP: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1497 | this.handleWipTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1498 | break; |
| 1499 | case ChangeActions.MOVE: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1500 | this.handleMoveTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1501 | break; |
| 1502 | case ChangeActions.PUBLISH_EDIT: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1503 | this.handlePublishEditTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1504 | break; |
| 1505 | case ChangeActions.REBASE_EDIT: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1506 | this.handleRebaseEditTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1507 | break; |
Dhruv Srivastava | 4dcb543 | 2021-04-26 16:45:07 +0200 | [diff] [blame] | 1508 | case ChangeActions.INCLUDED_IN: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1509 | this.handleIncludedInTap(); |
Dhruv Srivastava | 4dcb543 | 2021-04-26 16:45:07 +0200 | [diff] [blame] | 1510 | break; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1511 | default: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1512 | this.fireAction( |
| 1513 | this.prependSlash(key), |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1514 | assertUIActionInfo(this.actions[key]), |
| 1515 | false |
| 1516 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1517 | } |
| 1518 | } |
| 1519 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1520 | private handleRevisionAction(key: string) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1521 | switch (key) { |
| 1522 | case RevisionActions.REBASE: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1523 | assertIsDefined(this.confirmRebase, 'confirmRebase'); |
| 1524 | this.showActionDialog(this.confirmRebase); |
| 1525 | this.confirmRebase.fetchRecentChanges(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1526 | break; |
| 1527 | case RevisionActions.CHERRYPICK: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1528 | this.handleCherrypickTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1529 | break; |
| 1530 | case RevisionActions.DOWNLOAD: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1531 | this.handleDownloadTap(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1532 | break; |
| 1533 | case RevisionActions.SUBMIT: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1534 | if (!this.canSubmitChange()) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1535 | return; |
| 1536 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1537 | assertIsDefined(this.confirmSubmitDialog, 'confirmSubmitDialog'); |
| 1538 | this.showActionDialog(this.confirmSubmitDialog); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1539 | break; |
| 1540 | default: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1541 | this.fireAction( |
| 1542 | this.prependSlash(key), |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1543 | assertUIActionInfo(this.revisionActions?.[key]), |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1544 | true |
| 1545 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1546 | } |
| 1547 | } |
| 1548 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1549 | private prependSlash(key: string) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1550 | return key === '/' ? key : `/${key}`; |
| 1551 | } |
| 1552 | |
Ben Rohlfs | 4250087 | 2023-02-27 19:16:38 +0100 | [diff] [blame] | 1553 | private calculateDisabled(action: UIActionInfo) { |
| 1554 | // TODO(b/270972983): Remove this special casing once the backend is more |
| 1555 | // aggressive about setting`enabled:true`. |
| 1556 | if (action.__key === 'rebase') return false; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1557 | return !action.enabled; |
| 1558 | } |
| 1559 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1560 | private handleConfirmDialogCancel() { |
| 1561 | this.hideAllDialogs(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1562 | } |
| 1563 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1564 | private hideAllDialogs() { |
| 1565 | assertIsDefined(this.confirmSubmitDialog, 'confirmSubmitDialog'); |
| 1566 | const dialogEls = queryAll(this, '.confirmDialog'); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1567 | for (const dialogEl of dialogEls) { |
| 1568 | (dialogEl as HTMLElement).hidden = true; |
| 1569 | } |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1570 | assertIsDefined(this.actionsModal, 'actionsModal'); |
| 1571 | this.actionsModal.close(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1572 | } |
| 1573 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1574 | // private but used in test |
| 1575 | handleRebaseConfirm(e: CustomEvent<ConfirmRebaseEventDetail>) { |
| 1576 | assertIsDefined(this.confirmRebase, 'confirmRebase'); |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1577 | assertIsDefined(this.actionsModal, 'actionsModal'); |
Milutin Kristofic | 842c313 | 2022-08-25 21:00:57 +0200 | [diff] [blame] | 1578 | const payload = { |
| 1579 | base: e.detail.base, |
| 1580 | allow_conflicts: e.detail.allowConflicts, |
Milutin Kristofic | 0ff6b2c | 2023-03-01 15:02:07 +0100 | [diff] [blame] | 1581 | on_behalf_of_uploader: e.detail.onBehalfOfUploader, |
Kaushik Lingarkar | 2c68bf7 | 2023-06-06 15:20:01 -0700 | [diff] [blame] | 1582 | committer_email: e.detail.committerEmail, |
Milutin Kristofic | 842c313 | 2022-08-25 21:00:57 +0200 | [diff] [blame] | 1583 | }; |
Milutin Kristofic | 1225214 | 2023-01-11 15:13:45 +0100 | [diff] [blame] | 1584 | const rebaseChain = !!e.detail.rebaseChain; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1585 | this.fireAction( |
Milutin Kristofic | 1225214 | 2023-01-11 15:13:45 +0100 | [diff] [blame] | 1586 | rebaseChain ? '/rebase:chain' : '/rebase', |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1587 | assertUIActionInfo(this.revisionActions?.rebase), |
Milutin Kristofic | 1225214 | 2023-01-11 15:13:45 +0100 | [diff] [blame] | 1588 | rebaseChain ? false : true, |
Milutin Kristofic | 174c343 | 2022-09-16 12:33:28 +0200 | [diff] [blame] | 1589 | payload, |
Milutin Kristofic | 0ff6b2c | 2023-03-01 15:02:07 +0100 | [diff] [blame] | 1590 | { |
| 1591 | allow_conflicts: payload.allow_conflicts, |
| 1592 | on_behalf_of_uploader: payload.on_behalf_of_uploader, |
| 1593 | } |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1594 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1595 | } |
| 1596 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1597 | // private but used in test |
| 1598 | handleCherrypickConfirm() { |
| 1599 | this.handleCherryPickRestApi(false); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1600 | } |
| 1601 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1602 | // private but used in test |
| 1603 | handleCherrypickConflictConfirm() { |
| 1604 | this.handleCherryPickRestApi(true); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1605 | } |
| 1606 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1607 | private handleCherryPickRestApi(conflicts: boolean) { |
| 1608 | assertIsDefined(this.confirmCherrypick, 'confirmCherrypick'); |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1609 | assertIsDefined(this.actionsModal, 'actionsModal'); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1610 | const el = this.confirmCherrypick; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1611 | if (!el.branch) { |
Milutin Kristofic | 860fe4d | 2020-11-23 16:13:45 +0100 | [diff] [blame] | 1612 | fireAlert(this, ERR_BRANCH_EMPTY); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1613 | return; |
| 1614 | } |
| 1615 | if (!el.message) { |
Milutin Kristofic | 860fe4d | 2020-11-23 16:13:45 +0100 | [diff] [blame] | 1616 | fireAlert(this, ERR_COMMIT_EMPTY); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1617 | return; |
| 1618 | } |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1619 | this.actionsModal.close(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1620 | el.hidden = true; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1621 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1622 | '/cherrypick', |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1623 | assertUIActionInfo(this.revisionActions?.cherrypick), |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1624 | true, |
| 1625 | { |
| 1626 | destination: el.branch, |
| 1627 | base: el.baseCommit ? el.baseCommit : null, |
| 1628 | message: el.message, |
| 1629 | allow_conflicts: conflicts, |
Yash Chaturvedi | 13bf88e | 2023-09-28 08:48:32 +0000 | [diff] [blame] | 1630 | committer_email: el.committerEmail ? el.committerEmail : null, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1631 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1632 | ); |
| 1633 | } |
| 1634 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1635 | // private but used in test |
| 1636 | handleMoveConfirm() { |
| 1637 | assertIsDefined(this.confirmMove, 'confirmMove'); |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1638 | assertIsDefined(this.actionsModal, 'actionsModal'); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1639 | const el = this.confirmMove; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1640 | if (!el.branch) { |
Milutin Kristofic | 860fe4d | 2020-11-23 16:13:45 +0100 | [diff] [blame] | 1641 | fireAlert(this, ERR_BRANCH_EMPTY); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1642 | return; |
| 1643 | } |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1644 | this.actionsModal.close(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1645 | el.hidden = true; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1646 | this.fireAction('/move', assertUIActionInfo(this.actions.move), false, { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1647 | destination_branch: el.branch, |
| 1648 | message: el.message, |
| 1649 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1650 | } |
| 1651 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1652 | private handleRevertDialogConfirm(e: CustomEvent<ConfirmRevertEventDetail>) { |
| 1653 | assertIsDefined(this.confirmRevertDialog, 'confirmRevertDialog'); |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1654 | assertIsDefined(this.actionsModal, 'actionsModal'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1655 | const revertType = e.detail.revertType; |
| 1656 | const message = e.detail.message; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1657 | const el = this.confirmRevertDialog; |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1658 | this.actionsModal.close(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1659 | el.hidden = true; |
| 1660 | switch (revertType) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1661 | case RevertType.REVERT_SINGLE_CHANGE: |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1662 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1663 | '/revert', |
| 1664 | assertUIActionInfo(this.actions.revert), |
| 1665 | false, |
Frank Borden | bd99811 | 2022-11-22 14:48:52 +0000 | [diff] [blame] | 1666 | {message} |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1667 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1668 | break; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1669 | case RevertType.REVERT_SUBMISSION: |
Dhruv Srivastava | e4de13b | 2021-05-14 10:17:52 +0200 | [diff] [blame] | 1670 | // TODO(dhruvsri): replace with this.actions.revert_submission once |
| 1671 | // BE starts sending it again |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1672 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1673 | '/revert_submission', |
Dhruv Srivastava | e4de13b | 2021-05-14 10:17:52 +0200 | [diff] [blame] | 1674 | {__key: 'revert_submission', method: HttpMethod.POST} as UIActionInfo, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1675 | false, |
Frank Borden | bd99811 | 2022-11-22 14:48:52 +0000 | [diff] [blame] | 1676 | {message} |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1677 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1678 | break; |
| 1679 | default: |
Kamil Musin | f0ece02 | 2022-10-14 15:22:44 +0200 | [diff] [blame] | 1680 | this.reporting.error( |
| 1681 | 'Change Actions', |
| 1682 | new Error('invalid revert type') |
| 1683 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1684 | } |
| 1685 | } |
| 1686 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1687 | // private but used in test |
| 1688 | handleAbandonDialogConfirm() { |
| 1689 | assertIsDefined(this.confirmAbandonDialog, 'confirmAbandonDialog'); |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1690 | assertIsDefined(this.actionsModal, 'actionsModal'); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1691 | const el = this.confirmAbandonDialog; |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1692 | this.actionsModal.close(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1693 | el.hidden = true; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1694 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1695 | '/abandon', |
| 1696 | assertUIActionInfo(this.actions.abandon), |
| 1697 | false, |
| 1698 | { |
| 1699 | message: el.message, |
| 1700 | } |
| 1701 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1702 | } |
| 1703 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1704 | private handleCreateFollowUpChange() { |
| 1705 | assertIsDefined(this.createFollowUpChange, 'createFollowUpChange'); |
| 1706 | this.createFollowUpChange.handleCreateChange(); |
| 1707 | this.handleCloseCreateFollowUpChange(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1708 | } |
| 1709 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1710 | private handleCloseCreateFollowUpChange() { |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1711 | assertIsDefined(this.actionsModal, 'actionsModal'); |
| 1712 | this.actionsModal.close(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1713 | } |
| 1714 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1715 | private handleDeleteConfirm() { |
| 1716 | this.hideAllDialogs(); |
| 1717 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1718 | '/', |
| 1719 | assertUIActionInfo(this.actions[ChangeActions.DELETE]), |
| 1720 | false |
| 1721 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1722 | } |
| 1723 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1724 | private handleDeleteEditConfirm() { |
| 1725 | this.hideAllDialogs(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1726 | |
paladox | a80ea7c | 2022-02-19 17:42:15 +0000 | [diff] [blame] | 1727 | // We need to make sure that all cached version of a change |
| 1728 | // edit are deleted. |
Chris Poucet | 20f0958 | 2022-10-24 23:29:27 +0200 | [diff] [blame] | 1729 | this.getStorage().eraseEditableContentItemsForChangeEdit(this.changeNum); |
paladox | a80ea7c | 2022-02-19 17:42:15 +0000 | [diff] [blame] | 1730 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1731 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1732 | '/edit', |
| 1733 | assertUIActionInfo(this.actions.deleteEdit), |
| 1734 | false |
| 1735 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1736 | } |
| 1737 | |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 1738 | private handlePublishEditConfirm() { |
| 1739 | this.hideAllDialogs(); |
| 1740 | |
| 1741 | if (!this.actions.publishEdit) return; |
| 1742 | |
| 1743 | // We need to make sure that all cached version of a change |
| 1744 | // edit are deleted. |
| 1745 | this.getStorage().eraseEditableContentItemsForChangeEdit(this.changeNum); |
| 1746 | |
| 1747 | this.fireAction( |
| 1748 | '/edit:publish', |
| 1749 | assertUIActionInfo(this.actions.publishEdit), |
| 1750 | false, |
| 1751 | {notify: NotifyType.NONE} |
| 1752 | ); |
| 1753 | } |
| 1754 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1755 | // private but used in test |
| 1756 | handleSubmitConfirm() { |
| 1757 | if (!this.canSubmitChange()) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1758 | return; |
| 1759 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1760 | this.hideAllDialogs(); |
| 1761 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1762 | '/submit', |
Ben Rohlfs | 4af8c1d | 2024-02-29 11:41:35 +0100 | [diff] [blame] | 1763 | assertUIActionInfo(this.revisionActions?.submit), |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1764 | true |
| 1765 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1766 | } |
| 1767 | |
Ben Rohlfs | 7329430 | 2024-02-26 17:07:40 +0100 | [diff] [blame] | 1768 | private isOverflowAction(type: string, key: string) { |
| 1769 | return this.overflowActions.some( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1770 | action => action.type === type && action.key === key |
| 1771 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1772 | } |
| 1773 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1774 | // private but used in test |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 1775 | setLoadingOnButtonWithKey(action: UIActionInfo) { |
| 1776 | const key = action.__key; |
| 1777 | this.inProgressActionKeys.add(key); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1778 | this.actionLoadingMessage = this.computeLoadingLabel(key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1779 | let buttonKey = key; |
| 1780 | // TODO(dhruvsri): clean this up later |
| 1781 | // If key is revert-submission, then button key should be 'revert' |
| 1782 | if (buttonKey === ChangeActions.REVERT_SUBMISSION) { |
| 1783 | // Revert submission button no longer exists |
| 1784 | buttonKey = ChangeActions.REVERT; |
| 1785 | } |
| 1786 | |
Ben Rohlfs | 7329430 | 2024-02-26 17:07:40 +0100 | [diff] [blame] | 1787 | if (this.isOverflowAction(action.__type, buttonKey)) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1788 | this.disabledMenuActions.push(buttonKey === '/' ? 'delete' : buttonKey); |
| 1789 | this.requestUpdate('disabledMenuActions'); |
Tao Zhou | 38b3e0d | 2020-09-09 17:02:21 +0200 | [diff] [blame] | 1790 | return () => { |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 1791 | this.inProgressActionKeys.delete(key); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1792 | this.actionLoadingMessage = ''; |
| 1793 | this.disabledMenuActions = []; |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 1794 | this.requestUpdate(); |
Tao Zhou | 38b3e0d | 2020-09-09 17:02:21 +0200 | [diff] [blame] | 1795 | }; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1796 | } |
| 1797 | |
| 1798 | // Otherwise it's a top-level action. |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1799 | const buttonEl = this.shadowRoot!.querySelector( |
| 1800 | `[data-action-key="${buttonKey}"]` |
| 1801 | ) as GrButton; |
| 1802 | if (!buttonEl) { |
| 1803 | throw new Error(`Can't find button by data-action-key '${buttonKey}'`); |
| 1804 | } |
| 1805 | buttonEl.setAttribute('loading', 'true'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1806 | buttonEl.disabled = true; |
Tao Zhou | 38b3e0d | 2020-09-09 17:02:21 +0200 | [diff] [blame] | 1807 | return () => { |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 1808 | this.inProgressActionKeys.delete(action.__key); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1809 | this.actionLoadingMessage = ''; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1810 | buttonEl.removeAttribute('loading'); |
| 1811 | buttonEl.disabled = false; |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 1812 | this.requestUpdate(); |
Tao Zhou | 38b3e0d | 2020-09-09 17:02:21 +0200 | [diff] [blame] | 1813 | }; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1814 | } |
| 1815 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1816 | // private but used in test |
| 1817 | fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1818 | endpoint: string, |
| 1819 | action: UIActionInfo, |
| 1820 | revAction: boolean, |
Milutin Kristofic | 174c343 | 2022-09-16 12:33:28 +0200 | [diff] [blame] | 1821 | payload?: RequestPayload, |
| 1822 | toReport?: Object |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1823 | ) { |
Frank Borden | 10a6925 | 2022-12-08 17:28:49 +0100 | [diff] [blame] | 1824 | const cleanupFn = this.setLoadingOnButtonWithKey(action); |
Milutin Kristofic | 174c343 | 2022-09-16 12:33:28 +0200 | [diff] [blame] | 1825 | this.reporting.reportInteraction(Interaction.CHANGE_ACTION_FIRED, { |
| 1826 | endpoint, |
| 1827 | toReport, |
| 1828 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1829 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1830 | this.send( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1831 | action.method, |
| 1832 | payload, |
| 1833 | endpoint, |
| 1834 | revAction, |
| 1835 | cleanupFn, |
| 1836 | action |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1837 | ).then(res => this.handleResponse(action, res)); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1838 | } |
| 1839 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1840 | // private but used in test |
| 1841 | showActionDialog(dialog: ChangeActionDialog) { |
| 1842 | this.hideAllDialogs(); |
Dhruv Srivastava | c48d694 | 2021-02-08 13:42:57 +0100 | [diff] [blame] | 1843 | if (dialog.init) dialog.init(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1844 | dialog.hidden = false; |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1845 | assertIsDefined(this.actionsModal, 'actionsModal'); |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1846 | if (this.actionsModal.isConnected) this.actionsModal.showModal(); |
Dhruv Srivastava | 38e0b16 | 2022-10-24 14:22:17 +0200 | [diff] [blame] | 1847 | whenVisible(dialog, () => { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1848 | if (dialog.resetFocus) { |
| 1849 | dialog.resetFocus(); |
| 1850 | } |
| 1851 | }); |
| 1852 | } |
| 1853 | |
| 1854 | // TODO(rmistry): Redo this after |
Edwin Kempin | 11da19d | 2023-06-19 14:17:00 +0000 | [diff] [blame] | 1855 | // https://issues.gerritcodereview.com/issues/40004936 is resolved. |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1856 | // private but used in test |
| 1857 | setReviewOnRevert(newChangeId: NumericChangeId) { |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 1858 | const review = this.getPluginLoader().jsApiService.getReviewPostRevert( |
Ben Rohlfs | f56f71c | 2023-04-27 17:20:43 +0200 | [diff] [blame] | 1859 | this.change as ChangeInfo |
Chris Poucet | e3d6686 | 2022-10-26 11:19:50 +0200 | [diff] [blame] | 1860 | ); |
Edward Lesmes | a63a1cd | 2021-01-25 11:51:20 -0800 | [diff] [blame] | 1861 | if (!review) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1862 | return Promise.resolve(undefined); |
| 1863 | } |
Edward Lesmes | a63a1cd | 2021-01-25 11:51:20 -0800 | [diff] [blame] | 1864 | return this.restApiService.saveChangeReview(newChangeId, CURRENT, review); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1865 | } |
| 1866 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1867 | // private but used in test |
Kamil Musin | 1d8a1a3 | 2024-02-29 14:49:41 +0100 | [diff] [blame] | 1868 | async handleResponse(action: UIActionInfo, response: Response | undefined) { |
| 1869 | if (!response?.ok) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1870 | return; |
| 1871 | } |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 1872 | switch (action.__key) { |
| 1873 | case ChangeActions.REVERT: { |
Kamil Musin | 1d8a1a3 | 2024-02-29 14:49:41 +0100 | [diff] [blame] | 1874 | const revertChangeInfo = (await readJSONResponsePayload(response)) |
| 1875 | .parsed as unknown as ChangeInfo; |
Kamil Musin | 48677cb | 2024-02-27 17:06:12 +0100 | [diff] [blame] | 1876 | this.restApiService.addRepoNameToCache( |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 1877 | revertChangeInfo._number, |
| 1878 | revertChangeInfo.project |
| 1879 | ); |
| 1880 | const reachable = await this.waitForChangeReachable( |
| 1881 | revertChangeInfo._number |
| 1882 | ); |
| 1883 | if (!reachable) return; |
| 1884 | await this.setReviewOnRevert(revertChangeInfo._number); |
| 1885 | this.getNavigation().setUrl( |
| 1886 | createChangeUrl({change: revertChangeInfo}) |
| 1887 | ); |
| 1888 | break; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1889 | } |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 1890 | case RevisionActions.CHERRYPICK: { |
Kamil Musin | 1d8a1a3 | 2024-02-29 14:49:41 +0100 | [diff] [blame] | 1891 | const cherrypickChangeInfo = (await readJSONResponsePayload(response)) |
| 1892 | .parsed as unknown as ChangeInfo; |
Kamil Musin | 48677cb | 2024-02-27 17:06:12 +0100 | [diff] [blame] | 1893 | this.restApiService.addRepoNameToCache( |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 1894 | cherrypickChangeInfo._number, |
| 1895 | cherrypickChangeInfo.project |
| 1896 | ); |
| 1897 | const reachable = this.waitForChangeReachable( |
| 1898 | cherrypickChangeInfo._number |
| 1899 | ); |
| 1900 | if (!reachable) return; |
| 1901 | this.getNavigation().setUrl( |
| 1902 | createChangeUrl({change: cherrypickChangeInfo}) |
| 1903 | ); |
| 1904 | break; |
| 1905 | } |
| 1906 | case ChangeActions.DELETE: |
| 1907 | if (action.__type === ActionType.CHANGE) { |
| 1908 | this.getNavigation().setUrl(rootUrl()); |
| 1909 | } |
| 1910 | break; |
| 1911 | case ChangeActions.WIP: |
| 1912 | case ChangeActions.DELETE_EDIT: |
| 1913 | case ChangeActions.PUBLISH_EDIT: |
| 1914 | case ChangeActions.REBASE_EDIT: |
| 1915 | case ChangeActions.REBASE: |
| 1916 | case ChangeActions.SUBMIT: |
| 1917 | // Hide rebase dialog only if the action succeeds |
| 1918 | this.actionsModal?.close(); |
| 1919 | this.hideAllDialogs(); |
| 1920 | this.getChangeModel().navigateToChangeResetReload(); |
| 1921 | break; |
| 1922 | case ChangeActions.REVERT_SUBMISSION: { |
Kamil Musin | 1d8a1a3 | 2024-02-29 14:49:41 +0100 | [diff] [blame] | 1923 | const revertSubmistionInfo = (await readJSONResponsePayload(response)) |
| 1924 | .parsed as unknown as RevertSubmissionInfo; |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 1925 | if ( |
| 1926 | !revertSubmistionInfo.revert_changes || |
| 1927 | !revertSubmistionInfo.revert_changes.length |
| 1928 | ) |
| 1929 | return; |
| 1930 | /* If there is only 1 change then gerrit will automatically |
| 1931 | redirect to that change */ |
| 1932 | const topic = revertSubmistionInfo.revert_changes[0].topic; |
| 1933 | this.getNavigation().setUrl(createSearchUrl({topic})); |
| 1934 | break; |
| 1935 | } |
| 1936 | default: |
| 1937 | this.getChangeModel().navigateToChangeResetReload(); |
| 1938 | break; |
| 1939 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1940 | } |
| 1941 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1942 | // private but used in test |
| 1943 | handleResponseError( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1944 | action: UIActionInfo, |
| 1945 | response: Response | undefined | null, |
| 1946 | body?: RequestPayload |
| 1947 | ) { |
| 1948 | if (!response) { |
| 1949 | return Promise.resolve(() => { |
Ben Rohlfs | 6bb9053 | 2023-02-17 18:55:56 +0100 | [diff] [blame] | 1950 | fireError(this, `Could not perform action '${action.__key}'`); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1951 | }); |
| 1952 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1953 | if (action && action.__key === RevisionActions.CHERRYPICK) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1954 | if ( |
| 1955 | response.status === 409 && |
| 1956 | body && |
| 1957 | !(body as CherryPickInput).allow_conflicts |
| 1958 | ) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1959 | assertIsDefined( |
| 1960 | this.confirmCherrypickConflict, |
| 1961 | 'confirmCherrypickConflict' |
| 1962 | ); |
| 1963 | this.showActionDialog(this.confirmCherrypickConflict); |
Ben Rohlfs | 885e0e7 | 2022-02-25 12:51:30 +0100 | [diff] [blame] | 1964 | return; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1965 | } |
| 1966 | } |
| 1967 | return response.text().then(errText => { |
Ben Rohlfs | 6bb9053 | 2023-02-17 18:55:56 +0100 | [diff] [blame] | 1968 | fireError(this, `Could not perform action: ${errText}`); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1969 | if (!errText.startsWith('Change is already up to date')) { |
| 1970 | throw Error(errText); |
| 1971 | } |
| 1972 | }); |
| 1973 | } |
| 1974 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1975 | // private but used in test |
| 1976 | send( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1977 | method: HttpMethod | undefined, |
| 1978 | payload: RequestPayload | undefined, |
| 1979 | actionEndpoint: string, |
| 1980 | revisionAction: boolean, |
| 1981 | cleanupFn: () => void, |
| 1982 | action: UIActionInfo |
Kamil Musin | 1d8a1a3 | 2024-02-29 14:49:41 +0100 | [diff] [blame] | 1983 | ): Promise<Response | undefined> { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1984 | const handleError: ErrorCallback = response => { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1985 | cleanupFn.call(this); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 1986 | this.handleResponseError(action, response, payload); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 1987 | }; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 1988 | const change = this.change; |
| 1989 | const changeNum = this.changeNum; |
| 1990 | if (!change || !changeNum) { |
| 1991 | return Promise.reject( |
| 1992 | new Error('Properties change and changeNum must be set.') |
| 1993 | ); |
| 1994 | } |
Chris Poucet | bf65b8f | 2022-01-18 21:18:12 +0000 | [diff] [blame] | 1995 | return this.getChangeModel() |
| 1996 | .fetchChangeUpdates(change) |
| 1997 | .then(result => { |
| 1998 | if (!result.isLatest) { |
Ben Rohlfs | a36fa83 | 2023-02-18 14:55:02 +0100 | [diff] [blame] | 1999 | fire(this, 'show-alert', { |
Ben Rohlfs | 6bb9053 | 2023-02-17 18:55:56 +0100 | [diff] [blame] | 2000 | message: |
| 2001 | 'Cannot set label: a newer patch has been ' + |
| 2002 | 'uploaded to this change.', |
| 2003 | action: 'Reload', |
Ben Rohlfs | d49e833 | 2023-04-20 22:40:04 +0200 | [diff] [blame] | 2004 | callback: () => this.getChangeModel().navigateToChangeResetReload(), |
Ben Rohlfs | 6bb9053 | 2023-02-17 18:55:56 +0100 | [diff] [blame] | 2005 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2006 | |
Chris Poucet | bf65b8f | 2022-01-18 21:18:12 +0000 | [diff] [blame] | 2007 | // Because this is not a network error, call the cleanup function |
| 2008 | // but not the error handler. |
| 2009 | cleanupFn(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2010 | |
Chris Poucet | bf65b8f | 2022-01-18 21:18:12 +0000 | [diff] [blame] | 2011 | return Promise.resolve(undefined); |
| 2012 | } |
| 2013 | const patchNum = revisionAction ? this.latestPatchNum : undefined; |
| 2014 | return this.restApiService |
| 2015 | .executeChangeAction( |
| 2016 | changeNum, |
| 2017 | method, |
| 2018 | actionEndpoint, |
| 2019 | patchNum, |
| 2020 | payload, |
| 2021 | handleError |
| 2022 | ) |
| 2023 | .then(response => { |
| 2024 | cleanupFn.call(this); |
| 2025 | return response; |
| 2026 | }); |
| 2027 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2028 | } |
| 2029 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2030 | // private but used in test |
Chris Poucet | c55c7db | 2023-07-21 11:08:06 +0200 | [diff] [blame] | 2031 | async handleCherrypickTap() { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2032 | if (!this.change) { |
| 2033 | throw new Error('The change property must be set'); |
| 2034 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2035 | assertIsDefined(this.confirmCherrypick, 'confirmCherrypick'); |
| 2036 | this.confirmCherrypick.branch = '' as BranchName; |
Chris Poucet | c55c7db | 2023-07-21 11:08:06 +0200 | [diff] [blame] | 2037 | const changes = await this.getCherryPickChanges(); |
| 2038 | if (!changes.length) return; |
| 2039 | this.confirmCherrypick.updateChanges(changes); |
| 2040 | this.showActionDialog(this.confirmCherrypick); |
| 2041 | } |
| 2042 | |
| 2043 | private async getCherryPickChanges() { |
| 2044 | if (!this.change) return []; |
| 2045 | if (!this.change.topic) return [this.change]; |
Dhruv Srivastava | bab00cf | 2020-03-19 12:11:50 +0100 | [diff] [blame] | 2046 | const query = `topic: "${this.change.topic}"`; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2047 | const options = listChangesOptionsToHex( |
| 2048 | ListChangesOption.MESSAGES, |
| 2049 | ListChangesOption.ALL_REVISIONS |
| 2050 | ); |
Chris Poucet | c55c7db | 2023-07-21 11:08:06 +0200 | [diff] [blame] | 2051 | return this.restApiService |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 2052 | .getChanges(0, query, undefined, options) |
| 2053 | .then(changes => { |
| 2054 | if (!changes) { |
Kamil Musin | f0ece02 | 2022-10-14 15:22:44 +0200 | [diff] [blame] | 2055 | this.reporting.error( |
| 2056 | 'Change Actions', |
| 2057 | new Error('getChanges returns undefined') |
| 2058 | ); |
Chris Poucet | c55c7db | 2023-07-21 11:08:06 +0200 | [diff] [blame] | 2059 | return []; |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 2060 | } |
Chris Poucet | c55c7db | 2023-07-21 11:08:06 +0200 | [diff] [blame] | 2061 | return changes; |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 2062 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2063 | } |
| 2064 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2065 | // private but used in test |
| 2066 | handleMoveTap() { |
| 2067 | assertIsDefined(this.confirmMove, 'confirmMove'); |
| 2068 | this.confirmMove.branch = '' as BranchName; |
| 2069 | this.confirmMove.message = ''; |
| 2070 | this.showActionDialog(this.confirmMove); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2071 | } |
| 2072 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2073 | // private but used in test |
| 2074 | handleDownloadTap() { |
Ben Rohlfs | 44f0104 | 2023-02-18 13:27:57 +0100 | [diff] [blame] | 2075 | fire(this, 'download-tap', {}); |
Dhruv Srivastava | 4dcb543 | 2021-04-26 16:45:07 +0200 | [diff] [blame] | 2076 | } |
| 2077 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2078 | // private but used in test |
| 2079 | handleIncludedInTap() { |
Ben Rohlfs | 44f0104 | 2023-02-18 13:27:57 +0100 | [diff] [blame] | 2080 | fire(this, 'included-tap', {}); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2081 | } |
| 2082 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2083 | // private but used in test |
| 2084 | handleDeleteTap() { |
| 2085 | assertIsDefined(this.confirmDeleteDialog, 'confirmDeleteDialog'); |
| 2086 | this.showActionDialog(this.confirmDeleteDialog); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2087 | } |
| 2088 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2089 | // private but used in test |
| 2090 | handleDeleteEditTap() { |
| 2091 | assertIsDefined(this.confirmDeleteEditDialog, 'confirmDeleteEditDialog'); |
| 2092 | this.showActionDialog(this.confirmDeleteEditDialog); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2093 | } |
| 2094 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2095 | private handleFollowUpTap() { |
| 2096 | assertIsDefined(this.createFollowUpDialog, 'createFollowUpDialog'); |
| 2097 | this.showActionDialog(this.createFollowUpDialog); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2098 | } |
| 2099 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2100 | private handleWipTap() { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2101 | if (!this.actions.wip) { |
| 2102 | return; |
| 2103 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2104 | this.fireAction('/wip', assertUIActionInfo(this.actions.wip), false); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2105 | } |
| 2106 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2107 | private handlePublishEditTap() { |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 2108 | assertIsDefined(this.confirmPublishEditDialog, 'confirmPublishEditDialog'); |
| 2109 | this.showActionDialog(this.confirmPublishEditDialog); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2110 | } |
| 2111 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2112 | private handleRebaseEditTap() { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2113 | if (!this.actions.rebaseEdit) { |
| 2114 | return; |
| 2115 | } |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2116 | this.fireAction( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2117 | '/edit:rebase', |
| 2118 | assertUIActionInfo(this.actions.rebaseEdit), |
| 2119 | false |
| 2120 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2121 | } |
| 2122 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2123 | /** |
| 2124 | * Merge sources of change actions into a single ordered array of action |
| 2125 | * values. |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2126 | */ |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 2127 | private computeAllActions(): UIActionInfo[] { |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 2128 | if (this.change === undefined) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2129 | return []; |
| 2130 | } |
| 2131 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2132 | const revisionActionValues = this.getActionValues( |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 2133 | this.revisionActions, |
| 2134 | this.primaryActionKeys, |
| 2135 | this.additionalActions, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2136 | ActionType.REVISION |
| 2137 | ); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2138 | const changeActionValues = this.getActionValues( |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 2139 | this.actions, |
| 2140 | this.primaryActionKeys, |
| 2141 | this.additionalActions, |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2142 | ActionType.CHANGE |
| 2143 | ); |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2144 | const quickApprove = this.getQuickApproveAction(); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2145 | if (quickApprove) { |
| 2146 | changeActionValues.unshift(quickApprove); |
| 2147 | } |
| 2148 | |
| 2149 | return revisionActionValues |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2150 | .concat(changeActionValues) |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2151 | .sort((a, b) => this.actionComparator(a, b)) |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2152 | .map(action => { |
Chris Poucet | 1cd6394d | 2022-07-12 16:43:28 +0200 | [diff] [blame] | 2153 | return { |
| 2154 | ...action, |
| 2155 | ...(ACTIONS_WITH_ICONS.get(action.__key) ?? {}), |
| 2156 | }; |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2157 | }) |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2158 | .filter(action => !this.shouldSkipAction(action)); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2159 | } |
| 2160 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2161 | private getActionPriority(action: UIActionInfo) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2162 | if (action.__type && action.__key) { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2163 | const overrideAction = this.actionPriorityOverrides.find( |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2164 | i => i.type === action.__type && i.key === action.__key |
| 2165 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2166 | |
| 2167 | if (overrideAction !== undefined) { |
| 2168 | return overrideAction.priority; |
| 2169 | } |
| 2170 | } |
| 2171 | if (action.__key === 'review') { |
| 2172 | return ActionPriority.REVIEW; |
| 2173 | } else if (action.__primary) { |
| 2174 | return ActionPriority.PRIMARY; |
| 2175 | } else if (action.__type === ActionType.CHANGE) { |
| 2176 | return ActionPriority.CHANGE; |
| 2177 | } else if (action.__type === ActionType.REVISION) { |
| 2178 | return ActionPriority.REVISION; |
| 2179 | } |
| 2180 | return ActionPriority.DEFAULT; |
| 2181 | } |
| 2182 | |
| 2183 | /** |
| 2184 | * Sort comparator to define the order of change actions. |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2185 | * |
| 2186 | * private but used in test |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2187 | */ |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2188 | actionComparator(actionA: UIActionInfo, actionB: UIActionInfo) { |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2189 | const priorityDelta = |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2190 | this.getActionPriority(actionA) - this.getActionPriority(actionB); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2191 | // Sort by the button label if same priority. |
| 2192 | if (priorityDelta === 0) { |
| 2193 | return actionA.label > actionB.label ? 1 : -1; |
| 2194 | } else { |
| 2195 | return priorityDelta; |
| 2196 | } |
| 2197 | } |
| 2198 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2199 | private shouldSkipAction(action: UIActionInfo) { |
David Ostrovsky | 954e508 | 2021-05-05 12:28:13 +0200 | [diff] [blame] | 2200 | return SKIP_ACTION_KEYS.includes(action.__key); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2201 | } |
| 2202 | |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 2203 | private computeMenuActions(): MenuAction[] { |
| 2204 | return this.allActionValues |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2205 | .filter(a => { |
Ben Rohlfs | 7329430 | 2024-02-26 17:07:40 +0100 | [diff] [blame] | 2206 | const overflow = this.isOverflowAction(a.__type, a.__key); |
Chris Poucet | 9369a9f | 2022-05-09 17:15:44 +0200 | [diff] [blame] | 2207 | return overflow && !this.hiddenActions.includes(a.__key); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2208 | }) |
| 2209 | .map(action => { |
| 2210 | let key = action.__key; |
| 2211 | if (key === '/') { |
| 2212 | key = 'delete'; |
| 2213 | } |
| 2214 | return { |
| 2215 | name: action.label, |
| 2216 | id: `${key}-${action.__type}`, |
| 2217 | action, |
| 2218 | tooltip: action.title, |
| 2219 | }; |
| 2220 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2221 | } |
| 2222 | |
| 2223 | /** |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2224 | * Occasionally, a change created by a change action is not yet known to the |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2225 | * API for a brief time. Wait for the given change number to be recognized. |
| 2226 | * |
| 2227 | * Returns a promise that resolves with true if a request is recognized, or |
| 2228 | * false if the change was never recognized after all attempts. |
| 2229 | * |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2230 | * private but used in test |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2231 | */ |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 2232 | waitForChangeReachable(changeNum: NumericChangeId): Promise<boolean> { |
David Ostrovsky | f91f966 | 2021-02-22 19:34:37 +0100 | [diff] [blame] | 2233 | let attemptsRemaining = AWAIT_CHANGE_ATTEMPTS; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2234 | return new Promise(resolve => { |
| 2235 | const check = () => { |
David Ostrovsky | f91f966 | 2021-02-22 19:34:37 +0100 | [diff] [blame] | 2236 | attemptsRemaining--; |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 2237 | // Pass a no-op error handler to avoid the "not found" error toast, |
| 2238 | // unless it's the last attempt |
Ben Rohlfs | 43935a4 | 2020-12-01 19:14:09 +0100 | [diff] [blame] | 2239 | this.restApiService |
Kamil Musin | 3fb732f | 2023-08-25 15:48:09 +0200 | [diff] [blame] | 2240 | .getChange(changeNum, attemptsRemaining !== 0 ? () => {} : undefined) |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2241 | .then(response => { |
| 2242 | // If the response is 404, the response will be undefined. |
| 2243 | if (response) { |
| 2244 | resolve(true); |
| 2245 | return; |
| 2246 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2247 | |
David Ostrovsky | f91f966 | 2021-02-22 19:34:37 +0100 | [diff] [blame] | 2248 | if (attemptsRemaining) { |
Ben Rohlfs | 6b07893 | 2021-03-10 15:20:03 +0100 | [diff] [blame] | 2249 | setTimeout(check, AWAIT_CHANGE_TIMEOUT_MS); |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2250 | } else { |
| 2251 | resolve(false); |
| 2252 | } |
| 2253 | }); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2254 | }; |
| 2255 | check(); |
| 2256 | }); |
| 2257 | } |
| 2258 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2259 | private handleEditTap() { |
Ben Rohlfs | 44f0104 | 2023-02-18 13:27:57 +0100 | [diff] [blame] | 2260 | fireNoBubbleNoCompose(this, 'edit-tap', {}); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2261 | } |
| 2262 | |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2263 | private handleStopEditTap() { |
Ben Rohlfs | 44f0104 | 2023-02-18 13:27:57 +0100 | [diff] [blame] | 2264 | fireNoBubbleNoCompose(this, 'stop-edit-tap', {}); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2265 | } |
Milutin Kristofic | 7c84f7e | 2024-04-02 21:41:58 +0200 | [diff] [blame] | 2266 | |
| 2267 | private numberOfThreadsWithSuggestions() { |
| 2268 | if (!this.threadsWithSuggestions) return 0; |
| 2269 | return this.threadsWithSuggestions.length; |
| 2270 | } |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 2271 | } |
| 2272 | |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2273 | declare global { |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2274 | interface HTMLElementEventMap { |
Ben Rohlfs | 5b3c655 | 2023-02-18 13:02:46 +0100 | [diff] [blame] | 2275 | 'download-tap': CustomEvent<{}>; |
| 2276 | 'edit-tap': CustomEvent<{}>; |
| 2277 | 'included-tap': CustomEvent<{}>; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2278 | 'revision-actions-changed': CustomEvent<{value: ActionNameToActionInfoMap}>; |
Ben Rohlfs | 5b3c655 | 2023-02-18 13:02:46 +0100 | [diff] [blame] | 2279 | 'stop-edit-tap': CustomEvent<{}>; |
paladox | 32b861a | 2022-04-25 16:45:06 +0100 | [diff] [blame] | 2280 | } |
Dmitrii Filippov | 353bfbf | 2020-09-30 11:40:14 +0200 | [diff] [blame] | 2281 | interface HTMLElementTagNameMap { |
| 2282 | 'gr-change-actions': GrChangeActions; |
| 2283 | } |
| 2284 | } |