Merge "Parse ChangeResource from cache (not index) on /create.change endpoint"
diff --git a/plugins/codemirror-editor b/plugins/codemirror-editor
index 13dcd3f..25301d7 160000
--- a/plugins/codemirror-editor
+++ b/plugins/codemirror-editor
@@ -1 +1 @@
-Subproject commit 13dcd3f4673c56e2b1001ef19eb54236943a35e6
+Subproject commit 25301d7a9cd661122d3be0723a246be6bdcd74c4
diff --git a/plugins/package.json b/plugins/package.json
index 134c433..612062b 100644
--- a/plugins/package.json
+++ b/plugins/package.json
@@ -29,6 +29,7 @@
"@codemirror/lint": "^6.1.1",
"@codemirror/search": "^6.2.3",
"@codemirror/state": "^6.2.0",
+ "@codemirror/theme-one-dark": "^6.1.1",
"@codemirror/view": "^6.9.1",
"lit": "^2.2.3",
"rxjs": "^6.6.7",
diff --git a/plugins/yarn.lock b/plugins/yarn.lock
index 1512abe..3156f4c 100644
--- a/plugins/yarn.lock
+++ b/plugins/yarn.lock
@@ -129,9 +129,9 @@
"@lezer/php" "^1.0.0"
"@codemirror/lang-python@^6.0.0", "@codemirror/lang-python@^6.1.1":
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/@codemirror/lang-python/-/lang-python-6.1.1.tgz#378c69199da41e0b09eaadc56f6d70ad6001fd34"
- integrity sha512-AddGMIKUssUAqaDKoxKWA5GAzy/CVE0eSY7/ANgNzdS1GYBkp6N49XKEyMElkuN04UsZ+bTIQdj+tVV75NMwJw==
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/@codemirror/lang-python/-/lang-python-6.1.2.tgz#cabb57529679981f170491833dbf798576e7ab18"
+ integrity sha512-nbQfifLBZstpt6Oo4XxA2LOzlSp4b/7Bc5cmodG1R+Cs5PLLCTUvsMNWDnziiCfTOG/SW1rVzXq/GbIr6WXlcw==
dependencies:
"@codemirror/autocomplete" "^6.3.2"
"@codemirror/language" "^6.0.0"
@@ -239,6 +239,16 @@
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2"
integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==
+"@codemirror/theme-one-dark@^6.1.1":
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.1.tgz#76600555cbb314c495216f018f75b0c28daff158"
+ integrity sha512-+CfzmScfJuD6uDF5bHJkAjWTQ2QAAHxODCPxUEgcImDYcJLT+4l5vLnBHmDVv46kCC5uUJGMrBJct2Z6JbvqyQ==
+ dependencies:
+ "@codemirror/language" "^6.0.0"
+ "@codemirror/state" "^6.0.0"
+ "@codemirror/view" "^6.0.0"
+ "@lezer/highlight" "^1.0.0"
+
"@codemirror/view@^6.0.0", "@codemirror/view@^6.2.2", "@codemirror/view@^6.6.0", "@codemirror/view@^6.9.1":
version "6.9.1"
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.9.1.tgz#2ce4c528974b6172a5a4a738b7b0a0f04a4c1140"
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index ccb750d..aba9a8b 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -1569,6 +1569,7 @@
const payload = {
base: e.detail.base,
allow_conflicts: e.detail.allowConflicts,
+ on_behalf_of_uploader: e.detail.onBehalfOfUploader,
};
const rebaseChain = !!e.detail.rebaseChain;
this.fireAction(
@@ -1576,7 +1577,10 @@
assertUIActionInfo(this.revisionActions.rebase),
rebaseChain ? false : true,
payload,
- {allow_conflicts: payload.allow_conflicts}
+ {
+ allow_conflicts: payload.allow_conflicts,
+ on_behalf_of_uploader: payload.on_behalf_of_uploader,
+ }
);
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
index 9c01f2f..277eddd 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
@@ -624,15 +624,20 @@
assert.isTrue(fetchChangesStub.called);
element.handleRebaseConfirm(
new CustomEvent('', {
- detail: {base: '1234', allowConflicts: false, rebaseChain: false},
+ detail: {
+ base: '1234',
+ allowConflicts: false,
+ rebaseChain: false,
+ onBehalfOfUploader: true,
+ },
})
);
assert.deepEqual(fireActionStub.lastCall.args, [
'/rebase',
assertUIActionInfo(rebaseAction),
true,
- {base: '1234', allow_conflicts: false},
- {allow_conflicts: false},
+ {base: '1234', allow_conflicts: false, on_behalf_of_uploader: true},
+ {allow_conflicts: false, on_behalf_of_uploader: true},
]);
});
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
index 34869f2..5604b95 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
@@ -23,6 +23,7 @@
import {ValueChangedEvent} from '../../../types/events';
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {fireNoBubbleNoCompose} from '../../../utils/event-util';
+import {KnownExperimentId} from '../../../services/flags/flags';
export interface RebaseChange {
name: string;
@@ -33,6 +34,7 @@
base: string | null;
allowConflicts: boolean;
rebaseChain: boolean;
+ onBehalfOfUploader: boolean;
}
@customElement('gr-confirm-rebase-dialog')
@@ -88,6 +90,9 @@
@query('#rebaseOnOtherInput')
rebaseOnOtherInput!: HTMLInputElement;
+ @query('#rebaseOnBehalfOfUploader')
+ private rebaseOnBehalfOfUploader?: HTMLInputElement;
+
@query('#rebaseAllowConflicts')
private rebaseAllowConflicts!: HTMLInputElement;
@@ -99,6 +104,8 @@
private readonly restApiService = getAppContext().restApiService;
+ private readonly flagsService = getAppContext().flagsService;
+
constructor() {
super();
this.query = input => this.getChangeSuggestions(input);
@@ -135,7 +142,7 @@
display: block;
width: 100%;
}
- .rebaseAllowConflicts {
+ .rebaseCheckbox:first-of-type {
margin-top: var(--spacing-m);
}
.rebaseOption {
@@ -225,7 +232,20 @@
>
</gr-autocomplete>
</div>
- <div class="rebaseAllowConflicts">
+ ${when(
+ this.flagsService.isEnabled(
+ KnownExperimentId.REBASE_ON_BEHALF_OF_UPLOADER
+ ),
+ () => html`
+ <div class="rebaseCheckbox">
+ <input id="rebaseOnBehalfOfUploader" type="checkbox" checked />
+ <label for="rebaseOnBehalfOfUploader"
+ >Rebase on behalf of uploader</label
+ >
+ </div>
+ `
+ )}
+ <div class="rebaseCheckbox">
<input id="rebaseAllowConflicts" type="checkbox" />
<label for="rebaseAllowConflicts"
>Allow rebase with conflicts</label
@@ -234,7 +254,7 @@
${when(
this.hasParent,
() =>
- html`<div>
+ html`<div class="rebaseCheckbox">
<input
id="rebaseChain"
type="checkbox"
@@ -351,6 +371,7 @@
base: this.getSelectedBase(),
allowConflicts: this.rebaseAllowConflicts.checked,
rebaseChain: !!this.rebaseChain?.checked,
+ onBehalfOfUploader: !!this.rebaseOnBehalfOfUploader?.checked,
};
fireNoBubbleNoCompose(this, 'confirm-rebase', detail);
this.text = '';
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts
index 2644d81..79d8647 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.ts
@@ -9,6 +9,7 @@
import {
pressKey,
queryAndAssert,
+ stubFlags,
stubRestApi,
waitUntil,
} from '../../../test/test-utils';
@@ -22,6 +23,7 @@
let element: GrConfirmRebaseDialog;
setup(async () => {
+ stubFlags('isEnabled').returns(true);
element = await fixture(
html`<gr-confirm-rebase-dialog></gr-confirm-rebase-dialog>`
);
@@ -78,7 +80,13 @@
>
</gr-autocomplete>
</div>
- <div class="rebaseAllowConflicts">
+ <div class="rebaseCheckbox">
+ <input id="rebaseOnBehalfOfUploader" type="checkbox" checked="" />
+ <label for="rebaseOnBehalfOfUploader">
+ Rebase on behalf of uploader
+ </label>
+ </div>
+ <div class="rebaseCheckbox">
<input id="rebaseAllowConflicts" type="checkbox" />
<label for="rebaseAllowConflicts">
Allow rebase with conflicts
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.ts
index 3a88eaf..a20135b 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.ts
@@ -9,6 +9,7 @@
queryAndAssert,
stubRestApi,
waitEventLoop,
+ waitUntil,
} from '../../../test/test-utils';
import {GrReplyDialog} from './gr-reply-dialog';
@@ -23,6 +24,7 @@
import {GrButton} from '../../shared/gr-button/gr-button';
import {testResolver} from '../../../test/common-test-setup';
import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
+import {GrComment} from '../../shared/gr-comment/gr-comment';
suite('gr-reply-dialog-it tests', () => {
let element: GrReplyDialog;
@@ -96,10 +98,15 @@
});
test('lgtm plugin', async () => {
+ const attachStub = sinon.stub();
+ const callbackStub = sinon.stub();
window.Gerrit.install(
plugin => {
const replyApi = plugin.changeReply();
+ const hook = plugin.hook('reply-text');
+ hook.onAttached(attachStub);
replyApi.addReplyTextChangedCallback(text => {
+ callbackStub(text);
const label = 'Code-Review';
const labelValue = replyApi.getLabelValue(label);
if (labelValue && labelValue === ' 0' && text.indexOf('LGTM') === 0) {
@@ -114,16 +121,27 @@
setupElement(element);
const pluginLoader = testResolver(pluginLoaderToken);
pluginLoader.loadPlugins([]);
- await pluginLoader.awaitPluginsLoaded();
- await waitEventLoop();
- await waitEventLoop();
+ // This may seem a bit weird, but we have to somehow make sure that the
+ // event listener is actually installed, and apparently a `gr-comment` is
+ // attached twice inside the 'reply-text' endpoint. Could not find a better
+ // way to make sure that the callback is ready to receive events.
+ await waitUntil(() => attachStub.callCount === 2);
+
+ const comment = queryAndAssert<GrComment>(
+ element,
+ 'gr-comment#patchsetLevelComment'
+ );
+ comment.messageText = 'LGTM';
+
+ await waitUntil(() => callbackStub.calledWith('LGTM'));
+
const labelScoreRows = queryAndAssert(
element.getLabelScores(),
'gr-label-score-row[name="Code-Review"]'
);
const selectedBtn = queryAndAssert(
labelScoreRows,
- 'gr-button[data-value="+1"]'
+ 'gr-button[data-value="+1"].iron-selected'
);
assert.isOk(selectedBtn);
});
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index 893eeb9..38acf80 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -914,6 +914,8 @@
}}
@comment-text-changed=${(e: ValueChangedEvent<string>) => {
this.patchsetLevelDraftMessage = e.detail.value;
+ // See `addReplyTextChangedCallback` in `ChangeReplyPluginApi`.
+ fire(e.currentTarget as HTMLElement, 'value-changed', e.detail);
}}
.messagePlaceholder=${this.messagePlaceholder}
hide-header
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
index 12b19c7..cf555eb 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
@@ -39,6 +39,7 @@
} from '../../../models/views/change';
import {userModelToken} from '../../../models/user/user-model';
import {storageServiceToken} from '../../../services/storage/gr-storage_impl';
+import {isDarkTheme} from '../../../utils/theme-util';
const RESTORED_MESSAGE = 'Content restored from a previous edit.';
const SAVING_MESSAGE = 'Saving changes...';
@@ -88,6 +89,8 @@
// private but used in test
@state() latestPatchsetNumber?: RevisionPatchSetNum;
+ @state() private darkMode = false;
+
private readonly restApiService = getAppContext().restApiService;
private readonly reporting = getAppContext().reportingService;
@@ -132,6 +135,13 @@
() => this.getChangeModel().latestPatchNumWithEdit$,
x => (this.latestPatchsetNumber = x)
);
+ subscribe(
+ this,
+ () => this.getUserModel().preferenceTheme$,
+ theme => {
+ this.darkMode = isDarkTheme(theme);
+ }
+ );
this.shortcuts.addLocal({key: 's', modifiers: [Modifier.CTRL_KEY]}, () =>
this.handleSaveShortcut()
);
@@ -284,6 +294,10 @@
name="lineNum"
.value=${this.viewState?.editView?.lineNum}
></gr-endpoint-param>
+ <gr-endpoint-param
+ name="darkMode"
+ .value=${this.darkMode}
+ ></gr-endpoint-param>
<gr-default-editor
id="file"
.fileContent=${this.newContent}
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts
index 0a36a05..a2c92c5 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts
@@ -117,6 +117,7 @@
<gr-endpoint-param name="prefs"> </gr-endpoint-param>
<gr-endpoint-param name="fileType"> </gr-endpoint-param>
<gr-endpoint-param name="lineNum"> </gr-endpoint-param>
+ <gr-endpoint-param name="darkMode"> </gr-endpoint-param>
<gr-default-editor id="file"> </gr-default-editor>
</gr-endpoint-decorator>
</div>
diff --git a/polygerrit-ui/app/services/flags/flags.ts b/polygerrit-ui/app/services/flags/flags.ts
index 7488e79..5c7bf2d 100644
--- a/polygerrit-ui/app/services/flags/flags.ts
+++ b/polygerrit-ui/app/services/flags/flags.ts
@@ -19,4 +19,5 @@
PUSH_NOTIFICATIONS_DEVELOPER = 'UiFeature__push_notifications_developer',
PUSH_NOTIFICATIONS = 'UiFeature__push_notifications',
SUGGEST_EDIT = 'UiFeature__suggest_edit',
+ REBASE_ON_BEHALF_OF_UPLOADER = 'UiFeature__rebase_on_behalf_of_uploader',
}