Convert gr-create-change-dialog to lit
I tested this on my local gerrit dev site and made sure it worked.
Change-Id: Iaba1d3b1001f1833cd337ebbc225224142e4aa14
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
index 15f6f4b..bd9bc7a 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
@@ -20,98 +20,77 @@
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-select/gr-select';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-create-change-dialog_html';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
-import {customElement, property, observe} from '@polymer/decorators';
import {
RepoName,
BranchName,
ChangeId,
- ConfigInfo,
InheritedBooleanInfo,
} from '../../../types/common';
import {InheritedBooleanInfoConfiguredValue} from '../../../constants/constants';
-import {GrTypedAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import {appContext} from '../../../services/app-context';
import {Subject} from 'rxjs';
-import {
- repoConfig$,
- serverConfig$,
-} from '../../../services/config/config-model';
+import {serverConfig$} from '../../../services/config/config-model';
import {takeUntil} from 'rxjs/operators';
-import {IronInputElement} from '@polymer/iron-input/iron-input';
+import {formStyles} from '../../../styles/gr-form-styles';
+import {sharedStyles} from '../../../styles/shared-styles';
+import {LitElement, PropertyValues, css, html} from 'lit';
+import {customElement, property, query, state} from 'lit/decorators';
+import {BindValueChangeEvent} from '../../../types/events';
+import {fireEvent} from '../../../utils/event-util';
const SUGGESTIONS_LIMIT = 15;
const REF_PREFIX = 'refs/heads/';
-export interface GrCreateChangeDialog {
- $: {
- privateChangeCheckBox: HTMLInputElement;
- branchInput: GrTypedAutocomplete<BranchName>;
- tagNameInput: IronInputElement;
- messageInput: IronAutogrowTextareaElement;
- };
-}
-@customElement('gr-create-change-dialog')
-export class GrCreateChangeDialog extends PolymerElement {
- static get template() {
- return htmlTemplate;
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-create-change-dialog': GrCreateChangeDialog;
}
+}
+
+@customElement('gr-create-change-dialog')
+export class GrCreateChangeDialog extends LitElement {
+ // private but used in test
+ @query('#privateChangeCheckBox') privateChangeCheckBox!: HTMLInputElement;
@property({type: String})
repoName?: RepoName;
- @property({type: String})
- branch = '' as BranchName;
+ // private but used in test
+ @state() branch = '' as BranchName;
- @property({type: Object})
- _repoConfig?: ConfigInfo;
+ // private but used in test
+ @state() subject = '';
- @property({type: String})
- subject = '';
+ // private but used in test
+ @state() topic?: string;
- @property({type: String})
- topic?: string;
+ @state() private baseChange?: ChangeId;
- @property({type: Object})
- _query?: (input: string) => Promise<{name: BranchName}[]>;
-
- @property({type: String})
- baseChange?: ChangeId;
-
- @property({type: String})
- baseCommit?: string;
+ @state() private baseCommit?: string;
@property({type: Object})
privateByDefault?: InheritedBooleanInfo;
- @property({type: Boolean, notify: true})
- canCreate = false;
+ @state() private privateChangesEnabled = false;
- @property({type: Boolean})
- _privateChangesEnabled = false;
+ private readonly query: (input: string) => Promise<{name: BranchName}[]>;
- restApiService = appContext.restApiService;
+ private readonly restApiService = appContext.restApiService;
disconnected$ = new Subject();
constructor() {
super();
- this._query = (input: string) => this._getRepoBranchesSuggestions(input);
+ this.query = (input: string) => this.getRepoBranchesSuggestions(input);
}
override connectedCallback() {
super.connectedCallback();
if (!this.repoName) return;
- repoConfig$.pipe(takeUntil(this.disconnected$)).subscribe(config => {
- this.privateByDefault = config?.private_by_default;
- });
-
serverConfig$.pipe(takeUntil(this.disconnected$)).subscribe(config => {
- this._privateChangesEnabled =
+ this.privateChangesEnabled =
config?.change?.disable_private_changes ?? false;
});
}
@@ -121,20 +100,136 @@
super.disconnectedCallback();
}
- _computeBranchClass(baseChange?: ChangeId) {
- return baseChange ? 'hide' : '';
+ static override get styles() {
+ return [
+ formStyles,
+ sharedStyles,
+ css`
+ input:not([type='checkbox']),
+ gr-autocomplete,
+ iron-autogrow-textarea {
+ width: 100%;
+ }
+ .value {
+ width: 32em;
+ }
+ .hide {
+ display: none;
+ }
+ @media only screen and (max-width: 40em) {
+ .value {
+ width: 29em;
+ }
+ }
+ `,
+ ];
}
- @observe('branch', 'subject')
- _allowCreate(branch: BranchName, subject: string) {
- this.canCreate = !!branch && !!subject;
+ override render() {
+ return html`
+ <div class="gr-form-styles">
+ <section class=${this.baseChange ? 'hide' : ''}>
+ <span class="title">Select branch for new change</span>
+ <span class="value">
+ <gr-autocomplete
+ id="branchInput"
+ .text=${this.branch}
+ .query=${this.query}
+ placeholder="Destination branch"
+ @text-changed=${(e: CustomEvent) => {
+ this.branch = e.detail.value;
+ }}
+ >
+ </gr-autocomplete>
+ </span>
+ </section>
+ <section class=${this.baseChange ? 'hide' : ''}>
+ <span class="title">Provide base commit sha1 for change</span>
+ <span class="value">
+ <iron-input
+ maxlength="40"
+ placeholder="(optional)"
+ .bindValue=${this.baseCommit}
+ @bind-value-changed=${(e: BindValueChangeEvent) => {
+ this.baseCommit = e.detail.value;
+ }}
+ >
+ <input
+ id="baseCommitInput"
+ maxlength="40"
+ placeholder="(optional)"
+ />
+ </iron-input>
+ </span>
+ </section>
+ <section>
+ <span class="title">Enter topic for new change</span>
+ <span class="value">
+ <iron-input
+ maxlength="1024"
+ placeholder="(optional)"
+ .bindValue=${this.topic}
+ @bind-value-changed=${(e: BindValueChangeEvent) => {
+ this.topic = e.detail.value;
+ }}
+ >
+ <input
+ id="tagNameInput"
+ maxlength="1024"
+ placeholder="(optional)"
+ />
+ </iron-input>
+ </span>
+ </section>
+ <section id="description">
+ <span class="title">Description</span>
+ <span class="value">
+ <iron-autogrow-textarea
+ id="messageInput"
+ class="message"
+ autocomplete="on"
+ rows="4"
+ maxRows="15"
+ .bindValue=${this.subject}
+ placeholder="Insert the description of the change."
+ @bind-value-changed=${(e: BindValueChangeEvent) => {
+ this.subject = e.detail.value;
+ }}
+ >
+ </iron-autogrow-textarea>
+ </span>
+ </section>
+ <section class=${this.privateChangesEnabled ? 'hide' : ''}>
+ <label class="title" for="privateChangeCheckBox"
+ >Private change</label
+ >
+ <span class="value">
+ <input
+ type="checkbox"
+ id="privateChangeCheckBox"
+ ?checked=${this.formatPrivateByDefaultBoolean()}
+ />
+ </span>
+ </section>
+ </div>
+ `;
+ }
+
+ override willUpdate(changedProperties: PropertyValues) {
+ if (changedProperties.has('branch') || changedProperties.has('subject')) {
+ this.allowCreate();
+ }
+ }
+
+ private allowCreate() {
+ fireEvent(this, 'can-create-change');
}
handleCreateChange(): Promise<void> {
if (!this.repoName || !this.branch || !this.subject) {
return Promise.resolve();
}
- const isPrivate = this.$.privateChangeCheckBox.checked;
+ const isPrivate = this.privateChangeCheckBox.checked;
const isWip = true;
return this.restApiService
.createChange(
@@ -148,14 +243,13 @@
this.baseCommit || undefined
)
.then(changeCreated => {
- if (!changeCreated) {
- return;
- }
+ if (!changeCreated) return;
GerritNav.navigateToChange(changeCreated);
});
}
- _getRepoBranchesSuggestions(input: string) {
+ // private but used in test
+ getRepoBranchesSuggestions(input: string) {
if (!this.repoName) {
return Promise.reject(new Error('missing repo name'));
}
@@ -178,34 +272,19 @@
});
}
- _formatBooleanString(config?: InheritedBooleanInfo) {
- if (
- config &&
- config.configured_value === InheritedBooleanInfoConfiguredValue.TRUE
- ) {
- return true;
- } else if (
- config &&
- config.configured_value === InheritedBooleanInfoConfiguredValue.FALSE
- ) {
- return false;
- } else if (
- config &&
- config.configured_value === InheritedBooleanInfoConfiguredValue.INHERITED
- ) {
- return !!(config && config.inherited_value);
- } else {
- return false;
+ // private but used in test
+ formatPrivateByDefaultBoolean() {
+ const config = this.privateByDefault;
+ if (config === undefined) return false;
+ switch (config.configured_value) {
+ case InheritedBooleanInfoConfiguredValue.TRUE:
+ return true;
+ case InheritedBooleanInfoConfiguredValue.FALSE:
+ return false;
+ case InheritedBooleanInfoConfiguredValue.INHERITED:
+ return !!config.inherited_value;
+ default:
+ return false;
}
}
-
- _computePrivateSectionClass(config: boolean) {
- return config ? 'hide' : '';
- }
-}
-
-declare global {
- interface HTMLElementTagNameMap {
- 'gr-create-change-dialog': GrCreateChangeDialog;
- }
}
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_html.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_html.ts
deleted file mode 100644
index 47f3818..0000000
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_html.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style include="shared-styles">
- /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
- </style>
- <style include="gr-form-styles">
- input:not([type='checkbox']),
- gr-autocomplete,
- iron-autogrow-textarea {
- width: 100%;
- }
- .value {
- width: 32em;
- }
- .hide {
- display: none;
- }
- @media only screen and (max-width: 40em) {
- .value {
- width: 29em;
- }
- }
- </style>
- <div class="gr-form-styles">
- <section class$="[[_computeBranchClass(baseChange)]]">
- <span class="title">Select branch for new change</span>
- <span class="value">
- <gr-autocomplete
- id="branchInput"
- text="{{branch}}"
- query="[[_query]]"
- placeholder="Destination branch"
- >
- </gr-autocomplete>
- </span>
- </section>
- <section class$="[[_computeBranchClass(baseChange)]]">
- <span class="title">Provide base commit sha1 for change</span>
- <span class="value">
- <iron-input
- maxlength="40"
- placeholder="(optional)"
- bind-value="{{baseCommit}}"
- >
- <input
- is="iron-input"
- id="baseCommitInput"
- maxlength="40"
- placeholder="(optional)"
- bind-value="{{baseCommit}}"
- />
- </iron-input>
- </span>
- </section>
- <section>
- <span class="title">Enter topic for new change</span>
- <span class="value">
- <iron-input
- maxlength="1024"
- placeholder="(optional)"
- bind-value="{{topic}}"
- >
- <input
- is="iron-input"
- id="tagNameInput"
- maxlength="1024"
- placeholder="(optional)"
- bind-value="{{topic}}"
- />
- </iron-input>
- </span>
- </section>
- <section id="description">
- <span class="title">Description</span>
- <span class="value">
- <iron-autogrow-textarea
- id="messageInput"
- class="message"
- autocomplete="on"
- rows="4"
- max-rows="15"
- bind-value="{{subject}}"
- placeholder="Insert the description of the change."
- >
- </iron-autogrow-textarea>
- </span>
- </section>
- <section class$="[[_computePrivateSectionClass(_privateChangesEnabled)]]">
- <label class="title" for="privateChangeCheckBox">Private change</label>
- <span class="value">
- <input
- type="checkbox"
- id="privateChangeCheckBox"
- checked$="[[_formatBooleanString(privateByDefault)]]"
- />
- </span>
- </section>
- </div>
-`;
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts
index 9ed5d81..626b03f 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts
@@ -20,19 +20,16 @@
import {GrCreateChangeDialog} from './gr-create-change-dialog';
import {BranchName, GitRef, RepoName} from '../../../types/common';
import {InheritedBooleanInfoConfiguredValue} from '../../../constants/constants';
-import {
- createChange,
- createConfig,
- TEST_CHANGE_ID,
-} from '../../../test/test-data-generators';
-import {stubRestApi} from '../../../test/test-utils';
+import {createChange} from '../../../test/test-data-generators';
+import {queryAndAssert, stubRestApi} from '../../../test/test-utils';
+import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
const basicFixture = fixtureFromElement('gr-create-change-dialog');
suite('gr-create-change-dialog tests', () => {
let element: GrCreateChangeDialog;
- setup(() => {
+ setup(async () => {
stubRestApi('getRepoBranches').callsFake((input: string) => {
if (input.startsWith('test')) {
return Promise.resolve([
@@ -47,15 +44,8 @@
}
});
element = basicFixture.instantiate();
+ await element.updateComplete;
element.repoName = 'test-repo' as RepoName;
- element._repoConfig = {
- ...createConfig(),
- private_by_default: {
- value: false,
- configured_value: InheritedBooleanInfoConfiguredValue.FALSE,
- inherited_value: false,
- },
- };
});
test('new change created with default', async () => {
@@ -74,9 +64,13 @@
element.branch = 'test-branch' as BranchName;
element.topic = 'test-topic';
element.subject = 'first change created with polygerrit ui';
- assert.isFalse(element.$.privateChangeCheckBox.checked);
+ assert.isFalse(element.privateChangeCheckBox.checked);
- element.$.messageInput.bindValue = configInputObj.subject;
+ const messageInput = queryAndAssert<IronAutogrowTextareaElement>(
+ element,
+ '#messageInput'
+ );
+ messageInput.bindValue = configInputObj.subject;
await element.handleCreateChange();
// Private change
@@ -92,8 +86,8 @@
inherited_value: false,
value: true,
};
- sinon.stub(element, '_formatBooleanString').callsFake(() => true);
- flush();
+ sinon.stub(element, 'formatPrivateByDefaultBoolean').callsFake(() => true);
+ await element.updateComplete;
const configInputObj = {
branch: 'test-branch',
@@ -110,9 +104,13 @@
element.branch = 'test-branch' as BranchName;
element.topic = 'test-topic';
element.subject = 'first change created with polygerrit ui';
- assert.isTrue(element.$.privateChangeCheckBox.checked);
+ assert.isTrue(element.privateChangeCheckBox.checked);
- element.$.messageInput.bindValue = configInputObj.subject;
+ const messageInput = queryAndAssert<IronAutogrowTextareaElement>(
+ element,
+ '#messageInput'
+ );
+ messageInput.bindValue = configInputObj.subject;
await element.handleCreateChange();
// Private change
@@ -122,24 +120,14 @@
assert.isTrue(saveStub.called);
});
- test('_getRepoBranchesSuggestions empty', async () => {
- const branches = await element._getRepoBranchesSuggestions('nonexistent');
+ test('getRepoBranchesSuggestions empty', async () => {
+ const branches = await element.getRepoBranchesSuggestions('nonexistent');
assert.equal(branches.length, 0);
});
- test('_getRepoBranchesSuggestions non-empty', async () => {
- const branches = await element._getRepoBranchesSuggestions('test-branch');
+ test('getRepoBranchesSuggestions non-empty', async () => {
+ const branches = await element.getRepoBranchesSuggestions('test-branch');
assert.equal(branches.length, 1);
assert.equal(branches[0].name, 'test-branch');
});
-
- test('_computeBranchClass', () => {
- assert.equal(element._computeBranchClass(TEST_CHANGE_ID), 'hide');
- assert.equal(element._computeBranchClass(undefined), '');
- });
-
- test('_computePrivateSectionClass', () => {
- assert.equal(element._computePrivateSectionClass(true), 'hide');
- assert.equal(element._computePrivateSectionClass(false), '');
- });
});
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts
index de43dc6..7145d10 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.ts
@@ -77,7 +77,7 @@
_repoConfig?: ConfigInfo;
@property({type: Boolean})
- _canCreate = false;
+ _canCreateChange = false;
@property({type: Boolean})
_creatingChange = false;
@@ -185,6 +185,12 @@
this._editingConfig = false;
});
}
+
+ _handleCanCreateChange() {
+ this._canCreateChange =
+ !!this.$.createNewChangeModal.branch &&
+ !!this.$.createNewChangeModal.subject;
+ }
}
declare global {
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.ts b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.ts
index 9948f8f..51a26f7 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.ts
@@ -75,7 +75,7 @@
<gr-dialog
id="createChangeDialog"
confirm-label="Create"
- disabled="[[!_canCreate]]"
+ disabled="[[!_canCreateChange]]"
on-confirm="_handleCreateChange"
on-cancel="_handleCloseCreateChange"
>
@@ -83,8 +83,9 @@
<div class="main" slot="main">
<gr-create-change-dialog
id="createNewChangeModal"
- can-create="{{_canCreate}}"
repo-name="[[repo]]"
+ private-by-default="[[_repoConfig.private_by_default]]"
+ on-can-create-change="_handleCanCreateChange"
></gr-create-change-dialog>
</div>
</gr-dialog>