Merge "Update README to use navigationToken for stubbing"
diff --git a/polygerrit-ui/app/api/ai-code-review.ts b/polygerrit-ui/app/api/ai-code-review.ts
index 640dc1b..6c0c759 100644
--- a/polygerrit-ui/app/api/ai-code-review.ts
+++ b/polygerrit-ui/app/api/ai-code-review.ts
@@ -259,6 +259,10 @@
}
export declare interface ContextItem {
+ /**
+ * The type of the context item, e.g. 'gerrit' or 'buganizer'.
+ * Corresponds to the 'type' of a GerritReference provided by the plugin.
+ */
type_id: string;
link: string;
title: string;
diff --git a/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog.ts b/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog.ts
index a990898..1b73243 100644
--- a/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog.ts
@@ -16,6 +16,9 @@
import {subscribe} from '../../lit/subscription-controller';
import {resolve} from '../../../models/dependency';
import {changeModelToken} from '../../../models/change/change-model';
+import {commentsModelToken} from '../../../models/comments/comments-model';
+import {CommentThread} from '../../../types/common';
+import {isUnresolved} from '../../../utils/comment-util';
import {ParsedChangeInfo} from '../../../types/types';
import {PatchSetNum} from '../../../types/common';
import {HELP_ME_REVIEW_PROMPT, IMPROVE_COMMIT_MESSAGE} from './prompts';
@@ -42,6 +45,11 @@
label: 'Just patch content',
prompt: '{{patch}}',
},
+ RESOLVE_COMMENTS: {
+ id: 'resolve_comments',
+ label: 'Unresolved Comments',
+ prompt: '{{comments}}',
+ },
};
const CONTEXT_OPTIONS = [
@@ -76,12 +84,17 @@
@state() private context = 3;
+ // private but used in tests
+ @state() threads: CommentThread[] = [];
+
@state() private promptContent = '';
@state() private promptSize = '';
private readonly getChangeModel = resolve(this, changeModelToken);
+ private readonly getCommentsModel = resolve(this, commentsModelToken);
+
private readonly restApiService = getAppContext().restApiService;
constructor() {
@@ -96,6 +109,11 @@
() => this.getChangeModel().patchNum$,
x => (this.patchNum = x)
);
+ subscribe(
+ this,
+ () => this.getCommentsModel().threads$,
+ x => (this.threads = x)
+ );
}
static override get styles() {
@@ -297,7 +315,8 @@
override willUpdate(changedProperties: PropertyValues) {
if (
changedProperties.has('patchContent') ||
- changedProperties.has('selectedTemplate')
+ changedProperties.has('selectedTemplate') ||
+ changedProperties.has('threads')
) {
this.updatePromptContent();
}
@@ -338,6 +357,29 @@
this.patchContent = content;
}
+ private getUnresolvedCommentsFormatted(): string {
+ const unresolvedThreads = this.threads.filter(isUnresolved);
+ if (unresolvedThreads.length === 0) return 'No unresolved comments.';
+
+ return unresolvedThreads
+ .map(thread => {
+ const comments = thread.comments.map(
+ c => `${c.author?.name ?? 'Unknown'}:\n${c.message}`
+ );
+ let loc = '';
+ if (thread.line) {
+ loc = `Line ${thread.line}`;
+ } else if (thread.range) {
+ loc = `Lines ${thread.range.start_line}-${thread.range.end_line}`;
+ } else {
+ loc = 'File level';
+ }
+ return `* File: ${thread.path} (${loc})
+${comments.join('\n\n')}`;
+ })
+ .join('\n\n');
+ }
+
private updatePromptContent() {
if (!this.patchContent) {
this.promptContent = '';
@@ -349,6 +391,12 @@
'{{patch}}',
this.patchContent
);
+ if (this.selectedTemplate === 'RESOLVE_COMMENTS') {
+ this.promptContent = this.promptContent.replace(
+ '{{comments}}',
+ this.getUnresolvedCommentsFormatted()
+ );
+ }
// Inserts a space before each capital letter to handle CamelCase
const textWithSpaces = this.promptContent.replace(/([A-Z])/g, ' $1');
diff --git a/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog_test.ts
index 8165a0f..6ac9971 100644
--- a/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-ai-prompt-dialog/gr-ai-prompt-dialog_test.ts
@@ -10,6 +10,9 @@
import {createParsedChange} from '../../../test/test-data-generators';
import {CommitId, PatchSetNum} from '../../../api/rest-api';
import {stubRestApi, waitUntil} from '../../../test/test-utils';
+import {testResolver} from '../../../test/common-test-setup';
+import {commentsModelToken} from '../../../models/comments/comments-model';
+import {of} from 'rxjs';
suite('gr-ai-prompt-dialog test', () => {
let element: GrAiPromptDialog;
@@ -17,6 +20,12 @@
setup(async () => {
getPatchContentStub = stubRestApi('getPatchContent');
getPatchContentStub.resolves('test code');
+ const commentsModel = testResolver(commentsModelToken);
+ Object.defineProperty(commentsModel, 'threads$', {
+ value: of([]),
+ writable: true,
+ });
+
element = await fixture(html`<gr-ai-prompt-dialog></gr-ai-prompt-dialog>`);
element.change = createParsedChange();
element.change.revisions['abc'].commit!.parents = [
@@ -69,6 +78,14 @@
</md-radio>
Just patch content
</label>
+ <label class="template-option">
+ <md-radio
+ name="template"
+ tabindex="-1"
+ >
+ </md-radio>
+ Unresolved Comments
+ </label>
</div>
</div>
<div class="context-selector">
@@ -167,4 +184,42 @@
)
);
});
+ test('renders help review prompt', async () => {
+ element.selectedTemplate = 'HELP_REVIEW';
+ await element.updateComplete;
+ assert.include(
+ (element as any).promptContent,
+ 'You are a highly experienced code reviewer'
+ );
+ });
+
+ test('renders resolve comments prompt', async () => {
+ element.selectedTemplate = 'RESOLVE_COMMENTS';
+ await element.updateComplete;
+ assert.include((element as any).promptContent, 'No unresolved comments.');
+ });
+
+ test('renders resolve comments prompt with comments', async () => {
+ element.threads = [
+ {
+ comments: [
+ {
+ message: 'test comment',
+ author: {name: 'Tester'},
+ updated: '2025-01-01 10:00:00.000000000',
+ unresolved: true,
+ },
+ ],
+ path: 'test.txt',
+ line: 1,
+ rootId: '1',
+ },
+ ] as any[];
+ element.selectedTemplate = 'RESOLVE_COMMENTS';
+ await element.updateComplete;
+ const expected = `* File: test.txt (Line 1)
+Tester:
+test comment`;
+ assert.include((element as any).promptContent, expected);
+ });
});
diff --git a/polygerrit-ui/app/elements/chat-panel/context-chip.ts b/polygerrit-ui/app/elements/chat-panel/context-chip.ts
index c451bbb..92a8ac4 100644
--- a/polygerrit-ui/app/elements/chat-panel/context-chip.ts
+++ b/polygerrit-ui/app/elements/chat-panel/context-chip.ts
@@ -53,6 +53,7 @@
}
md-filter-chip {
--md-sys-color-primary: var(--primary-text-color);
+ --md-filter-chip-label-text-color: var(--primary-text-color);
--md-filter-chip-container-height: 20px;
--md-filter-chip-label-text-size: var(--font-size-small);
--md-filter-chip-label-text-weight: var(--font-weight-medium);
@@ -90,9 +91,8 @@
.isCustomAction
? 'custom-action-chip'
: ''}"
- .label=${this.text}
- ?selected=${this.isCustomAction}
- .title=${this.tooltip ?? ''}
+ .label=${this.contextItem?.title ?? this.text}
+ .title=${this.contextItem?.tooltip ?? this.tooltip ?? ''}
@click=${this.navigateToUrl}
?removable=${this.isRemovable && !this.isSuggestion}
@remove=${this.onRemoveContextChip}
diff --git a/polygerrit-ui/app/elements/chat-panel/prompt-box.ts b/polygerrit-ui/app/elements/chat-panel/prompt-box.ts
index 4474b4f..95afaf1 100644
--- a/polygerrit-ui/app/elements/chat-panel/prompt-box.ts
+++ b/polygerrit-ui/app/elements/chat-panel/prompt-box.ts
@@ -8,7 +8,7 @@
import './context-chip';
import './context-input-chip';
-import {css, html, LitElement} from 'lit';
+import {css, html, LitElement, nothing} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {when} from 'lit/directives/when.js';
@@ -18,13 +18,16 @@
ModelInfo,
} from '../../api/ai-code-review';
import {chatModelToken, Turn} from '../../models/chat/chat-model';
+import {changeModelToken} from '../../models/change/change-model';
import {
contextItemEquals,
searchForContextLinks,
} from '../../models/chat/context-item-util';
import {resolve} from '../../models/dependency';
+import {ParsedChangeInfo} from '../../types/types';
import {debounce, DelayedTask} from '../../utils/async-util';
import {fire} from '../../utils/event-util';
+import {createChangeUrl} from '../../models/views/change';
import {subscribe} from '../lit/subscription-controller';
const MAX_VISIBLE_CONTEXT_ITEMS_COLLAPSED = 3;
@@ -65,6 +68,8 @@
@state() contextItemTypes: readonly ContextItemType[] = [];
+ @state() private change?: ParsedChangeInfo;
+
// TODO(milutin): Find out if we need this.
// @ts-ignore
private turnBasisForUserInput?: number;
@@ -77,10 +82,17 @@
private readonly getChatModel = resolve(this, chatModelToken);
+ private readonly getChangeModel = resolve(this, changeModelToken);
+
constructor() {
super();
subscribe(
this,
+ () => this.getChangeModel().change$,
+ x => (this.change = x)
+ );
+ subscribe(
+ this,
() => this.getChatModel().modelsLoadingError$,
x => (this.hasModelLoadingError = !!x)
);
@@ -340,6 +352,28 @@
)}`;
}
+ private renderThisChangeChip() {
+ // This Change is implicitly added to the context, so we don't need to add it.
+ // The chip makes it clear to the user that it is already in the context.
+ if (!this.change) return nothing;
+ const changeContextItem: ContextItem = {
+ type_id: 'gerrit',
+ link: createChangeUrl({
+ change: this.change,
+ }),
+ title: 'This Change',
+ identifier: this.change.id,
+ tooltip: 'File diffs (against base), commit message, and comments.',
+ };
+ return html`
+ <context-chip
+ class="this-change-context"
+ .contextItem=${changeContextItem}
+ .isRemovable=${false}
+ ></context-chip>
+ `;
+ }
+
private renderAddContext() {
return html`
<md-chip-set class="context-chip-set">
@@ -347,6 +381,7 @@
@context-item-added=${(e: CustomEvent<ContextItem>) =>
this.onContextItemAdded(e.detail)}
></context-input-chip>
+ ${this.renderThisChangeChip()}
${(this.showAllContextItems
? this.contextItems
: this.contextItems.slice(0, MAX_VISIBLE_CONTEXT_ITEMS_COLLAPSED)
diff --git a/polygerrit-ui/app/elements/chat-panel/prompt-box_test.ts b/polygerrit-ui/app/elements/chat-panel/prompt-box_test.ts
index 429bba7..2913d9d 100644
--- a/polygerrit-ui/app/elements/chat-panel/prompt-box_test.ts
+++ b/polygerrit-ui/app/elements/chat-panel/prompt-box_test.ts
@@ -63,6 +63,7 @@
</div>
<md-chip-set class="context-chip-set">
<context-input-chip> </context-input-chip>
+ <context-chip class="this-change-context"> </context-chip>
</md-chip-set>
`
);
@@ -134,7 +135,9 @@
},
});
await element.updateComplete;
- const contextChips = element.shadowRoot?.querySelectorAll('context-chip');
+ const contextChips = element.shadowRoot?.querySelectorAll(
+ 'context-chip.external-context'
+ );
assert.isOk(contextChips);
assert.equal(contextChips?.length, 2);
});
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png
index 4b6e5e7..c7ad776 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png
index 9494d6e..dac5fa2 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png
index 277550e..105a290 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-citations.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png
index 1f1cd44..c460946 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png
index 9d635d5..7914809 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-comment.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png
index c2d1f08..14f8b9d 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png
index 9677c0f..18a3a1eb 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-error.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png
index caa010a..694df41 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png
index fd428cd..924e634 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode-with-references.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png
index 9c55238..387d1bf 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-chat-mode.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png
index c85405c..7493690 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png
index ceadc1d..a9c0589 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-custom-actions.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png
index 94e160f..a888964 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png
index 204f938..8fcf45d 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png
index 8ccf3b6..43b6c10 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page-private.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png
index 6344dc9..904a4d4 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/chat-panel-splash-page.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open-dark.png
index b1ee87c..6ed4e5d 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open.png
index 6be0d064..0cdb6c6 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-change-view-1280px-chat-open.png
Binary files differ