提交 8c37a11c 编写于 作者: T Tomas Vik

Merge branch '257-respond-in-thread' into 'main'

fix(webview): can't respond in comment thread in webview for MR/Issue

See merge request gitlab-org/gitlab-vscode-extension!153
......@@ -132,12 +132,15 @@ const discussionsFragment = gql`
}
}
`;
const queryGetMrDiscussions = gql`
const constructGetDiscussionsQuery = (isMr: boolean) => gql`
${discussionsFragment}
query GetMrDiscussions($projectPath: ID!, $iid: String!, $afterCursor: String) {
query Get${
isMr ? 'Mr' : 'Issue'
}Discussions($projectPath: ID!, $iid: String!, $afterCursor: String) {
project(fullPath: $projectPath) {
id
mergeRequest(iid: $iid) {
${isMr ? 'mergeRequest' : 'issue'}(iid: $iid) {
discussions(after: $afterCursor) {
...discussions
}
......@@ -146,20 +149,19 @@ const queryGetMrDiscussions = gql`
}
`;
const queryGetIssueDiscussions = gql`
${discussionsFragment}
query GetIssueDiscussions($projectPath: ID!, $iid: String!, $afterCursor: String) {
project(fullPath: $projectPath) {
id
issue(iid: $iid) {
discussions(after: $afterCursor) {
...discussions
}
}
const createNoteMutation = gql`
mutation CreateNote($issuableId: NoteableID!, $body: String!, $replyId: DiscussionID) {
createNote(input: { noteableId: $issuableId, body: $body, discussionId: $replyId }) {
errors
}
}
`;
const getProjectPath = (issuable: RestIssuable) => issuable.references.full.split(/[#!]/)[0];
const isMr = (issuable: RestIssuable) => Boolean(issuable.sha);
const getIssuableGqlId = (issuable: RestIssuable) =>
`gid://gitlab/${isMr(issuable) ? 'MergeRequest' : 'Issue'}/${issuable.id}`;
export class GitLabNewService {
client: GraphQLClient;
......@@ -270,8 +272,8 @@ export class GitLabNewService {
issuable: RestIssuable,
endCursor?: string,
): Promise<GqlDiscussion[]> {
const [projectPath] = issuable.references.full.split(/[#!]/);
const query = issuable.sha ? queryGetMrDiscussions : queryGetIssueDiscussions;
const projectPath = getProjectPath(issuable);
const query = constructGetDiscussionsQuery(isMr(issuable));
const result = await this.client.request<GqlProjectResult<GqlDiscussionsProject>>(query, {
projectPath,
iid: String(issuable.iid),
......@@ -280,7 +282,7 @@ export class GitLabNewService {
assert(result.project, `Project ${projectPath} was not found.`);
const discussions =
result.project.issue?.discussions || result.project.mergeRequest?.discussions;
assert(discussions, `Discussions for issuable ${projectPath}#!${issuable.iid} were not found.`);
assert(discussions, `Discussions for issuable ${issuable.references.full} were not found.`);
if (discussions.pageInfo?.hasNextPage) {
assert(discussions.pageInfo.endCursor);
const remainingPages = await this.getDiscussions(issuable, discussions.pageInfo.endCursor);
......@@ -290,7 +292,7 @@ export class GitLabNewService {
}
private async getLabelEvents(issuable: RestIssuable): Promise<RestLabelEvent[]> {
const type = issuable.sha ? 'merge_requests' : 'issues';
const type = isMr(issuable) ? 'merge_requests' : 'issues';
const labelEventsUrl = `${this.instanceUrl}/api/v4/projects/${issuable.project_id}/${type}/${issuable.iid}/resource_label_events?sort=asc&per_page=100`;
const result = await crossFetch(labelEventsUrl, this.fetchOptions);
if (!result.ok) {
......@@ -314,4 +316,12 @@ export class GitLabNewService {
return combinedEvents;
}
async createNote(issuable: RestIssuable, body: string, replyId?: string): Promise<void> {
await this.client.request<void>(createNoteMutation, {
issuableId: getIssuableGqlId(issuable),
body,
replyId,
});
}
}
......@@ -516,23 +516,3 @@ export async function renderMarkdown(markdown: string, workspaceFolder: string)
return rendered.html;
}
export async function saveNote(params: {
issuable: RestIssuable;
note: string;
noteType: { path: string };
}) {
try {
const projectId = params.issuable.project_id;
const { iid } = params.issuable;
const { path } = params.noteType;
const { response } = await fetch(`/projects/${projectId}/${path}/${iid}/notes`, 'POST', {
body: params.note,
});
return response;
} catch (e) {
logError(e);
}
return { success: false };
}
......@@ -51,7 +51,7 @@ export default {
<template v-else>
<issuable-details :issuable="issuable" />
<issuable-discussions :discussions="discussions" />
<comment-form :issuable="issuable" />
<comment-form />
</template>
</div>
</template>
......@@ -88,7 +88,7 @@ export default {
#app {
margin-bottom: 600px; // to give editor scroll past end effect
max-width: 960px;
.loading {
text-align: center;
font-size: 14px;
......
import { mount } from '@vue/test-utils';
import CommentForm from './CommentForm';
const getSubmitButton = wrapper => wrapper.find('.js-submit');
const getCancelButton = wrapper => wrapper.find('.js-cancel');
describe('CommentForm', () => {
let wrapper;
beforeEach(() => {
window.vsCodeApi = { postMessage: jest.fn() };
});
describe('not a part of a discussion thread', () => {
beforeEach(() => {
wrapper = mount(CommentForm, {
propsData: {},
});
});
it("doesn't show cancel button", async () => {
expect(getCancelButton(wrapper).exists()).toBe(false);
});
describe('upon submitting the message', () => {
beforeEach(async () => {
await wrapper.find('textarea').setValue('test message');
await getSubmitButton(wrapper).trigger('click');
});
it('sends out VS Code event', () => {
expect(window.vsCodeApi.postMessage).toHaveBeenCalledWith({
command: 'saveNote',
note: 'test message',
});
});
it('indicates the message is being sent', () => {
expect(getSubmitButton(wrapper).text()).toBe('Saving...');
});
it('handles success', async () => {
const event = new Event('message');
event.data = { type: 'noteSaved' };
await window.dispatchEvent(event);
expect(wrapper.find('textarea').element.value).toBe('');
});
it('handles failure', async () => {
const event = new Event('message');
event.data = { type: 'noteSaved', status: false };
await window.dispatchEvent(event);
expect(wrapper.find('textarea').element.value).toBe('test message');
expect(wrapper.text()).toContain('Failed to save your comment. Please try again.');
});
});
it('submits the message', async () => {
await wrapper.find('textarea').setValue('test message');
await getSubmitButton(wrapper).trigger('click');
expect(window.vsCodeApi.postMessage).toHaveBeenCalledWith({
command: 'saveNote',
note: 'test message',
});
});
});
describe('is a part of a discussion thread', () => {
beforeEach(() => {
wrapper = mount(CommentForm, {
propsData: { replyId: 'testReplyId' },
});
});
it('submits the message with replyId', async () => {
await wrapper.find('textarea').setValue('test message');
await getSubmitButton(wrapper).trigger('click');
expect(window.vsCodeApi.postMessage).toHaveBeenCalledWith({
command: 'saveNote',
note: 'test message',
replyId: 'testReplyId',
});
});
});
});
<script>
export default {
props: {
issuable: {
type: Object,
required: true,
replyId: {
type: String,
default: undefined,
},
},
data() {
......@@ -21,36 +21,37 @@ export default {
canSubmit() {
return !this.isSaving && this.note.length > 0;
},
isThreadReply() {
return Boolean(this.replyId);
},
},
methods: {
getNoteType() {
return this.issuable.sha
? { type: 'merge_request', path: 'merge_requests' }
: { type: 'issue', path: 'issues' };
},
addComment() {
if (!this.canSubmit) {
return;
}
const { issuable, note, command } = this;
const { note, command, replyId } = this;
this.isSaving = true;
this.isFailed = false;
const noteType = this.getNoteType();
window.vsCodeApi.postMessage({ command, issuable, note, noteType });
window.vsCodeApi.postMessage({ command, note, replyId });
},
handleKeydown({ key, ctrlKey, shiftKey, metaKey, altKey }) {
if (key === 'Enter' && (ctrlKey || metaKey) && !shiftKey && !altKey) {
this.addComment();
}
},
cancelEdit() {
this.$emit('cancel-edit');
},
},
mounted() {
window.addEventListener('message', event => {
if (event.data.type === 'noteSaved') {
if (event.data.status !== false) {
this.note = '';
this.cancelEdit();
} else {
this.isFailed = true;
}
......@@ -63,11 +64,14 @@ export default {
</script>
<template>
<div class="main-comment-form">
<div class="main-comment-form" :class="{ 'thread-reply': isThreadReply }">
<textarea v-model="note" @keydown="handleKeydown" placeholder="Write a comment..." />
<button @click="addComment" :disabled="!canSubmit">
<button class="primary js-submit" @click="addComment" :disabled="!canSubmit">
{{ buttonTitle }}
</button>
<button class="secondary js-cancel" v-if="isThreadReply" @click="cancelEdit">
Cancel
</button>
<span v-if="isFailed">Failed to save your comment. Please try again.</span>
</div>
</template>
......@@ -75,6 +79,11 @@ export default {
<style lang="scss">
.main-comment-form {
margin: 20px 0 30px 0;
background: var(--vscode-editor-background);
&.thread-reply {
padding: 30px;
margin: 0px;
}
textarea {
width: 100%;
......@@ -84,35 +93,44 @@ export default {
font-size: 13px;
box-sizing: border-box;
border: 1px solid var(--vscode-input-border);
background-color: var(--vscode-input-background);
color: var(--vscode-input-foreground);
resize: vertical;
margin-bottom: 8px;
outline: 0;
&:focus {
outline: 0;
border-color: var(--vscode-focusBorder);
box-shadow: 0 0 0 0.2rem var(--vscode-widget-shadow);
box-shadow: 0 0 0 1px var(--vscode-focusBorder);
}
}
button {
background-color: var(--vscode-button-background);
color: var(--vscode-button-foreground);
border-color: var(--vscode-button-background);
border-radius: 3px;
border: 0;
padding: 6px 10px;
font-size: 14px;
outline: 0;
margin-right: 10px;
cursor: pointer;
&:disabled {
opacity: 0.9;
cursor: default;
&.primary {
background-color: var(--vscode-button-background);
color: var(--vscode-button-foreground);
&:hover {
background-color: var(--vscode-button-hoverBackground);
}
}
&.secondary {
background-color: var(--vscode-button-secondaryBackground);
color: var(--vscode-button-secondaryForeground);
&:hover {
background-color: var(--vscode-button-secondaryHoverBackground);
}
}
&:hover {
background-color: var(--vscode-button-hoverBackground);
border-color: var(--vscode-button-hoverBackground);
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
}
......
import { mount } from '@vue/test-utils';
import Discussion from './Discussion';
import CommentForm from './CommentForm';
const {
multipleNotes,
note1TextSnippet,
note2TextSnippet,
} = require('../../../../test/integration/fixtures/graphql/discussions');
const getReplyButton = wrapper => wrapper.find('.js-reply');
const getCollapseButton = wrapper => wrapper.find('.js-collapse');
const getCommentForm = wrapper => wrapper.findComponent(CommentForm);
describe('Discussion', () => {
let wrapper;
describe('with multiple comments', () => {
beforeEach(() => {
wrapper = mount(Discussion, {
propsData: {
noteable: multipleNotes,
},
stubs: {
date: true,
},
});
});
it('shows all comments by default', () => {
expect(wrapper.text()).toContain(note1TextSnippet);
expect(wrapper.text()).toContain(note2TextSnippet);
});
it('shows reply button', () => {
expect(getReplyButton(wrapper).exists()).toBe(true);
});
describe('collapsing and uncollapsing', () => {
it('hides reply button and second message when we collapse replies', async () => {
await getCollapseButton(wrapper).trigger('click');
expect(wrapper.text()).not.toContain(note2TextSnippet);
expect(getReplyButton(wrapper).exists()).toBe(false);
});
it('shows reply button and the replies if they were uncollapsed', async () => {
const collapseButton = getCollapseButton(wrapper);
await collapseButton.trigger('click');
await collapseButton.trigger('click');
expect(wrapper.text()).toContain(note2TextSnippet);
expect(getReplyButton(wrapper).exists()).toBe(true);
});
});
describe('comment form', () => {
it("doesn't show comment form by default", () => {
expect(getCommentForm(wrapper).exists()).toBe(false);
});
it('opens the comment form when we click reply button', async () => {
await getReplyButton(wrapper).trigger('click');
expect(getCommentForm(wrapper).exists()).toBe(true);
});
it('hides the comment form when we click cancel button', async () => {
await getReplyButton(wrapper).trigger('click');
const commentForm = getCommentForm(wrapper);
await commentForm.find('.js-cancel').trigger('click');
expect(getCommentForm(wrapper).exists()).toBe(false);
});
});
});
});
<script>
import Note from './Note';
import CommentForm from './CommentForm';
import icons from '../assets/icons';
export default {
......@@ -13,10 +14,13 @@ export default {
data() {
return {
isRepliesVisible: true,
isEditing: false,
reply: '',
};
},
components: {
Note,
CommentForm,
},
computed: {
initialDiscussion() {
......@@ -39,6 +43,9 @@ export default {
toggleReplies() {
this.isRepliesVisible = !this.isRepliesVisible;
},
toggleEditting() {
this.isEditing = !this.isEditing;
},
},
created() {
this.chevronDownSvg = icons.chevronDown;
......@@ -48,13 +55,17 @@ export default {
</script>
<template>
<div :class="{ collapsed: !isRepliesVisible }" class="discussion">
<div class="discussion">
<note :noteable="initialDiscussion" />
<div v-if="hasReplies" @click="toggleReplies" class="toggle-widget">
<button v-if="hasReplies" @click="toggleReplies" class="collapse js-collapse">
<span class="chevron" v-html="toggleRepliesIcon" /> {{ toggleRepliesText }}
</div>
</button>
<template v-if="isRepliesVisible">
<note v-for="note in replies" :key="note.id" :noteable="note" />
<button v-if="!isEditing" class="reply js-reply" @click="toggleEditting">
Reply
</button>
<comment-form v-if="isEditing" :reply-id="noteable.replyId" @cancel-edit="toggleEditting" />
</template>
</div>
</template>
......@@ -67,28 +78,34 @@ export default {
border-radius: 4px;
background: var(--vscode-editor-background);
&.collapsed {
.toggle-widget {
border-radius: 0 0 4px 4px;
}
}
> .note {
border: none;
margin: 0;
}
.toggle-widget {
background: var(--vscode-activityBar-dropBackground);
padding: 8px 16px;
cursor: pointer;
user-select: none;
position: relative;
}
.chevron svg {
width: 10px;
height: 10px;
}
.collapse,
.reply {
display: inline-block;
border: none;
color: inherit;
background: inherit;
margin: 8px 16px;
cursor: pointer;
font-family: sans-serif;
font-size: inherit;
outline: 0;
&:hover,
&:focus {
text-decoration: underline;
}
&:last-child {
margin-bottom: 16px;
}
}
}
</style>
import { mount } from '@vue/test-utils';
import IssuableDiscussions from './IssuableDiscussions';
import Discussion from './Discussion';
import SystemNote from './SystemNote';
import LabelNote from './LabelNote';
const discussionsResponse = require('../../../../test/integration/fixtures/graphql/discussions.json');
const {
singleNote,
multipleNotes,
systemNote,
note1TextSnippet,
note2TextSnippet,
systemNoteTextSnippet,
} = require('../../../../test/integration/fixtures/graphql/discussions');
const labelNote = require('../../../../test/integration/fixtures/rest/label_events/added_normal.json');
const partOfLabelNote = 'added Category:Editor Extension';
describe('IssuableDiscussions', () => {
beforeEach(() => {
window.vsCodeApi = { postMessage: jest.fn() };
});
it('renders', () => {
it.each`
name | discussion | component | noteText
${'single note'} | ${singleNote} | ${Discussion} | ${note1TextSnippet}
${'multiple notes with note1'} | ${multipleNotes} | ${Discussion} | ${note1TextSnippet}
${'multiple notes with note2'} | ${multipleNotes} | ${Discussion} | ${note2TextSnippet}
${'system note'} | ${systemNote} | ${SystemNote} | ${systemNoteTextSnippet}
${'label event'} | ${labelNote} | ${LabelNote} | ${partOfLabelNote}
`('renders $name with correct component and text', ({ discussion, component, noteText }) => {
const wrapper = mount(IssuableDiscussions, {
propsData: {
discussions: discussionsResponse.project.issue.discussions.nodes,
discussions: [discussion],
},
stubs: {
date: true,
},
});
expect(wrapper.element).toMatchSnapshot();
const discussions = wrapper.findAllComponents(component);
expect(discussions.length).toBe(1);
expect(discussions.at(0).text()).toMatch(noteText);
});
});
......@@ -4,7 +4,8 @@ import Discussion from './Discussion';
import SystemNote from './SystemNote';
import LabelNote from './LabelNote';
const hasSingleNote = discussion => discussion.notes && discussion.notes.nodes.length === 1;
const isLabel = discussion => Boolean(discussion.label);
const isSystem = discussion => discussion.notes && discussion.notes.nodes[0].system;
export default {
props: {
......@@ -21,24 +22,18 @@ export default {
},
methods: {
getComponentName(discussion) {
if (hasSingleNote(discussion)) {
if (discussion.notes.nodes[0].system) {
return SystemNote;
}
return Note;
}
if (discussion.label) {
if (isLabel(discussion)) {
return LabelNote;
}
if (isSystem(discussion)) {
return SystemNote;
}
return Discussion;
},
getComponentData(discussion) {
if (discussion.label) {
return discussion;
}
return hasSingleNote(discussion) ? discussion.notes.nodes[0] : discussion;
// only system component needs us to pass down the first (and only) note
return isSystem(discussion) ? discussion.notes.nodes[0] : discussion;
},
},
};
......@@ -79,7 +74,7 @@ export default {
bottom: 0;
width: 2px;
box-sizing: border-box;
z-index: 4px;
z-index: -1;
}
}
</style>
......@@ -82,7 +82,8 @@ export default {
position: static;
&:last-child {
position: relative;
// hides the timeline that connects all notes (through avatar pictures)
background: var(--vscode-editor-background);
}
.timelineContent {
......
......@@ -45,11 +45,9 @@ export default {
<style lang="scss">
.note {
border: 1px solid;
border-color: var(--vscode-panel-border);
border-radius: 4px;
padding: 16px;
margin: 16px 0;
background: var(--vscode-editor-background);
box-sizing: border-box;
display: block;
position: relative;
......
......@@ -149,7 +149,8 @@ export default {
position: static;
&:last-child {
position: relative;
// hides the timeline that connects all notes (through avatar pictures)
background: var(--vscode-editor-background);
}
.timelineContent {
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`IssuableDiscussions renders 1`] = `
<ul
class="issuable-discussions"
>
<li
class="note system-note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<svg
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.8759,8.99237 C11.4346,10.7215 9.86658,12 8,12 C6.13342,12 4.56545,10.7215 4.12406,8.99238 C4.08342,8.99741 4.04201,9 4,9 L1,9 C0.447715,9 0,8.55228 0,8 C0,7.44771 0.447715,7 1,7 L4,7 C4.04201,7 4.08342,7.00259 4.12406,7.00762 C4.56545,5.27853 6.13342,4 8,4 C9.86658,4 11.4346,5.27853 11.8759,7.00763 C11.9166,7.00259 11.958,7 12,7 L15,7 C15.5523,7 16,7.44772 16,8 C16,8.55228 15.5523,9 15,9 L12,9 C11.958,9 11.9166,8.9974 11.8759,8.99237 Z M8,10 C9.10457,10 10,9.10457 10,8 C10,6.89543 9.10457,6 8,6 C6.89543,6 6,6.89543 6,8 C6,9.10457 6.89543,10 8,10 Z"
fill="currentColor"
fill-rule="evenodd"
/>
</svg>
</span>
</div>
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/vymarkov"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
Vitaly Markov
</strong>
<span>
@vymarkov
</span>
</span>
</a>
</span>
added 2 commits
<date-stub
date="2020-12-02T09:44:11Z"
style="margin-left: 2px;"
/>
</div>
<div
class="note-body"
style="margin-left: 25px;"
>
<div
class="body"
>
<p>
&lt;ul&gt;&lt;li&gt;5b63a281 - fix(lint): Fix linter errors&lt;/li&gt;&lt;li&gt;618c91eb - docs: Update CONTRIBUTING.md&lt;/li&gt;&lt;/ul&gt;
</p>
<p>
<a
href="/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?diff_id=128320927&start_sha=2a7d1c93417adaafaee85b0345fdf8ea3f28c847"
>
Compare with previous version
</a>
</p>
</div>
</div>
</div>
<!---->
</div>
</li>
<li
class="note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<a
href="https://gitlab.com/viktomas"
target="_blank"
>
<img
class="avatar s40"
src="https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon"
/>
<!---->
</a>
</span>
</div>
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/viktomas"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
Tomas Vik
</strong>
<span>
@viktomas
</span>
</span>
</a>
</span>
·
<date-stub
date="2020-12-02T17:00:04Z"
style="margin-left: 2px;"
/>
</div>
<div
class="note-body"
>
<div
class="body"
>
<p
data-sourcepos="1:1-1:59"
dir="auto"
>
<a
class="gfm gfm-project_member js-user-link"
data-container="body"
data-placement="top"
data-reference-type="user"
data-user="359491"
href="/vymarkov"
title="Vitaly Markov"
>
@vymarkov
</a>
Thank you for fixing the
<code>
CONTRIBUTING.md
</code>
<gl-emoji
data-name="tada"
data-unicode-version="6.0"
title="party popper"
>
🎉
</gl-emoji>
</p>
<p
data-sourcepos="3:1-3:182"
dir="auto"
>
Regarding the change in
<code>
src/gitlab_service.ts
</code>
, I think we should still show some message to the user when they try to run
<code>
GitLab: *
</code>
command and the extension fails to execute it.
</p>
<p
data-sourcepos="5:1-5:217"
dir="auto"
>
We had a lot of troubles in the past when we were swallowing errors and then we weren't able to help the extension users debug any potential issues. (
<a
class="gfm gfm-issue has-tooltip"
data-container="body"
data-issue="30087182"
data-link="false"
data-link-reference="true"
data-original="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145"
data-placement="top"
data-project="278964"
data-reference-type="issue"
href="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145"
title="Error reporting to VSCode OutputChannel"
>
#145 (closed)
</a>
)
</p>
</div>
</div>
</div>
</div>
</li>
<li
class="note system-note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<svg
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.325 7.225a4 4 0 1 0-6.65 0A4.002 4.002 0 0 0 2 11v4h12v-4a4.002 4.002 0 0 0-2.675-3.775zM10 5a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM6 9a2 2 0 0 0-2 2v2h8v-2a2 2 0 0 0-2-2H6z"
fill="currentColor"
/>
</svg>
</span>
</div>
<!---->
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/viktomas"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
Tomas Vik
</strong>
<span>
@viktomas
</span>
</span>
</a>
</span>
<div
class="note-body"
style="margin-right: 2px;"
>
<div
class="body"
>
<p>
assigned to @viktomas
</p>
</div>
</div>
·
<date-stub
date="2020-12-02T17:00:15Z"
style="margin-left: 2px;"
/>
</div>
</div>
</div>
</li>
<li
class="note system-note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<svg
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.325 7.225a4 4 0 1 0-6.65 0A4.002 4.002 0 0 0 2 11v4h12v-4a4.002 4.002 0 0 0-2.675-3.775zM10 5a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM6 9a2 2 0 0 0-2 2v2h8v-2a2 2 0 0 0-2-2H6z"
fill="currentColor"
/>
</svg>
</span>
</div>
<!---->
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/viktomas"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
Tomas Vik
</strong>
<span>
@viktomas
</span>
</span>
</a>
</span>
<div
class="note-body"
style="margin-right: 2px;"
>
<div
class="body"
>
<p>
assigned to @vymarkov
</p>
</div>
</div>
·
<date-stub
date="2020-12-02T17:00:22Z"
style="margin-left: 2px;"
/>
</div>
</div>
</div>
</li>
<li
class="note system-note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<svg
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14 1a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4.71L1.5 14.855A1 1 0 0 1 0 13.99V3a2 2 0 0 1 2-2h12zm0 2H2v9.257L4.175 11H14V3zM5 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm3 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm3 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"
fill="currentColor"
/>
</svg>
</span>
</div>
<!---->
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/gitlab-bot"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
🤖 GitLab Bot 🤖
</strong>
<span>
@gitlab-bot
</span>
</span>
</a>
</span>
<div
class="note-body"
style="margin-right: 2px;"
>
<div
class="body"
>
<p>
mentioned in issue gitlab-org/quality/triage-reports#1062
</p>
</div>
</div>
·
<date-stub
date="2020-12-03T00:11:43Z"
style="margin-left: 2px;"
/>
</div>
</div>
</div>
</li>
<li
class="note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<a
href="https://gitlab.com/vymarkov"
target="_blank"
>
<img
class="avatar s40"
src="https://secure.gravatar.com/avatar/24d3a696fcc9592d18db6e623c0e654e?s=80&d=identicon"
/>
<!---->
</a>
</span>
</div>
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/vymarkov"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
Vitaly Markov
</strong>
<span>
@vymarkov
</span>
</span>
</a>
</span>
·
<date-stub
date="2020-12-03T10:58:37Z"
style="margin-left: 2px;"
/>
</div>
<div
class="note-body"
>
<div
class="body"
>
<blockquote
data-sourcepos="1:1-1:135"
dir="auto"
>
<p
data-sourcepos="1:3-1:135"
>
I think we should still show some message to the user when they try to run
<code>
GitLab: *
</code>
command and the extension fails to execute it.
</p>
</blockquote>
<p
data-sourcepos="3:1-3:64"
dir="auto"
>
Will it be enough to log the error message
<code>
project not found
</code>
?
</p>
<p
data-sourcepos="5:1-5:129"
dir="auto"
>
It's critical issue, I can't use ext cause I have on my workspace some repo from Github, it lead to issue what I'm trying to fix.
</p>
</div>
</div>
</div>
</div>
</li>
<li
class="note system-note"
>
<div
class="timeline-entry-inner"
>
<div
class="timelineIcon"
>
<span>
<svg
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14 1a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4.71L1.5 14.855A1 1 0 0 1 0 13.99V3a2 2 0 0 1 2-2h12zm0 2H2v9.257L4.175 11H14V3zM5 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm3 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm3 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"
fill="currentColor"
/>
</svg>
</span>
</div>
<!---->
<div
class="timelineContent"
>
<div
class="note-header"
>
<span
style="margin-right: 2px;"
>
<a
href="https://gitlab.com/viktomas"
target="_blank"
>
<!---->
<span
class="author"
>
<strong>
Tomas Vik
</strong>
<span>
@viktomas
</span>
</span>
</a>
</span>
<div
class="note-body"
style="margin-right: 2px;"
>
<div
class="body"
>
<p>
mentioned in issue #275
</p>
</div>
</div>
·
<date-stub
date="2020-12-03T12:50:21Z"
style="margin-left: 2px;"
/>
</div>
</div>
</div>
</li>
</ul>
`;
......@@ -4,6 +4,7 @@ const crypto = require('crypto');
const vscode = require('vscode');
const gitLabService = require('./gitlab_service');
const { createGitLabNewService } = require('./service_factory');
const { logError } = require('./log');
let context = null;
......@@ -53,6 +54,7 @@ const createPanel = issuable => {
return vscode.window.createWebviewPanel('glWorkflow', title, vscode.ViewColumn.One, {
enableScripts: true,
localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'src'))],
retainContextWhenHidden: true,
});
};
......@@ -78,14 +80,9 @@ const createMessageHandler = (panel, issuable, workspaceFolder) => async message
}
if (message.command === 'saveNote') {
const response = await gitLabService.saveNote({
issuable: message.issuable,
note: message.note,
noteType: message.noteType,
});
if (response.success !== false) {
const gitlabNewService = await createGitLabNewService(workspaceFolder);
const gitlabNewService = await createGitLabNewService(workspaceFolder);
try {
await gitlabNewService.createNote(issuable, message.note, message.replyId);
const discussionsAndLabels = await gitlabNewService.getDiscussionsAndLabelEvents(issuable);
panel.webview.postMessage({
type: 'issuableFetch',
......@@ -93,7 +90,8 @@ const createMessageHandler = (panel, issuable, workspaceFolder) => async message
discussions: discussionsAndLabels,
});
panel.webview.postMessage({ type: 'noteSaved' });
} else {
} catch (e) {
logError(e);
panel.webview.postMessage({ type: 'noteSaved', status: false });
}
}
......
const systemNote = {
replyId: 'gid://gitlab/IndividualNoteDiscussion/3e120050b42400665aa728f283cfa167d800f03e',
createdAt: '2020-12-02T09:44:11Z',
notes: {
pageInfo: {
hasNextPage: false,
endCursor: 'MQ',
},
nodes: [
{
id: 'gid://gitlab/Note/458662425',
createdAt: '2020-12-02T09:44:11Z',
system: true,
author: {
avatarUrl:
'https://secure.gravatar.com/avatar/24d3a696fcc9592d18db6e623c0e654e?s=80&d=identicon',
name: 'Vitaly Markov',
username: 'vymarkov',
webUrl: 'https://gitlab.com/vymarkov',
},
body:
'added 2 commits\n\n<ul><li>5b63a281 - fix(lint): Fix linter errors</li><li>618c91eb - docs: Update CONTRIBUTING.md</li></ul>\n\n[Compare with previous version](/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?diff_id=128320927&start_sha=2a7d1c93417adaafaee85b0345fdf8ea3f28c847)',
bodyHtml:
'<p data-sourcepos="1:1-1:15" dir="auto">added 2 commits</p>&#x000A;<ul dir="auto">&#x000A;<li>&#x000A;<a href="/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?commit_id=5b63a28151c5028e6bc0758ec1c28d4c36256a58" data-original="5b63a281" data-link="false" data-link-reference="false" data-project="278964" data-commit="5b63a28151c5028e6bc0758ec1c28d4c36256a58" data-reference-type="commit" data-container="body" data-placement="top" title="fix(lint): Fix linter errors" class="gfm gfm-commit has-tooltip">5b63a281</a> - fix(lint): Fix linter errors</li>&#x000A;<li>&#x000A;<a href="/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?commit_id=618c91ebd1527deef3740f66d8950ecc85032782" data-original="618c91eb" data-link="false" data-link-reference="false" data-project="278964" data-commit="618c91ebd1527deef3740f66d8950ecc85032782" data-reference-type="commit" data-container="body" data-placement="top" title="docs: Update CONTRIBUTING.md" class="gfm gfm-commit has-tooltip">618c91eb</a> - docs: Update CONTRIBUTING.md</li>&#x000A;</ul>&#x000A;<p data-sourcepos="5:1-5:164" dir="auto"><a href="/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?diff_id=128320927&amp;start_sha=2a7d1c93417adaafaee85b0345fdf8ea3f28c847">Compare with previous version</a></p>',
},
],
},
};
const systemNoteTextSnippet = 'added 2 commits';
const note1 = {
id: 'gid://gitlab/Note/459020558',
createdAt: '2020-12-02T17:00:04Z',
system: false,
author: {
avatarUrl:
'https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon',
name: 'Tomas Vik',
username: 'viktomas',
webUrl: 'https://gitlab.com/viktomas',
},
body:
"@vymarkov Thank you for fixing the `CONTRIBUTING.md` :tada:\n\nRegarding the change in `src/gitlab_service.ts`, I think we should still show some message to the user when they try to run `GitLab: *` command and the extension fails to execute it.\n\nWe had a lot of troubles in the past when we were swallowing errors and then we weren't able to help the extension users debug any potential issues. (https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145)",
bodyHtml:
'<p data-sourcepos="1:1-1:59" dir="auto"><a href="/vymarkov" data-user="359491" data-reference-type="user" data-container="body" data-placement="top" class="gfm gfm-project_member js-user-link" title="Vitaly Markov">@vymarkov</a> Thank you for fixing the <code>CONTRIBUTING.md</code> <gl-emoji title="party popper" data-name="tada" data-unicode-version="6.0">🎉</gl-emoji></p>&#x000A;<p data-sourcepos="3:1-3:182" dir="auto">Regarding the change in <code>src/gitlab_service.ts</code>, I think we should still show some message to the user when they try to run <code>GitLab: *</code> command and the extension fails to execute it.</p>&#x000A;<p data-sourcepos="5:1-5:217" dir="auto">We had a lot of troubles in the past when we were swallowing errors and then we weren\'t able to help the extension users debug any potential issues. (<a href="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145" data-original="https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145" data-link="false" data-link-reference="true" data-project="278964" data-issue="30087182" data-reference-type="issue" data-container="body" data-placement="top" title="Error reporting to VSCode OutputChannel" class="gfm gfm-issue has-tooltip">#145 (closed)</a>)</p>',
};
const note1TextSnippet =
'I think we should still show some message to the user when they try to run';
const note2 = {
id: 'gid://gitlab/DiscussionNote/465896084',
createdAt: '2020-12-14T08:51:37Z',
system: false,
author: {
avatarUrl:
'https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon',
name: 'Tomas Vik',
username: 'viktomas',
webUrl: 'https://gitlab.com/viktomas',
},
body:
'@KevSlashNull This is a good improvement :money_with_wings:. Would it be possible to also replace `moment` in [`Date.vue`](https://gitlab.com/gitlab-org/gitlab-vscode-extension/blob/bec5ccb142e4890e20f5f0036cc1e878ff761309/src%2Fwebview%2Fsrc%2Fcomponents%2FDate.vue#L14-18) in the `webview`? I know that the dependencies are managed separately, but it would be good for consistency to update both places.',
bodyHtml:
'<p data-sourcepos="1:1-1:405" dir="auto"><a href="/KevSlashNull" data-user="2190515" data-reference-type="user" data-container="body" data-placement="top" class="gfm gfm-project_member js-user-link" title="Kev">@KevSlashNull</a> This is a good improvement <gl-emoji title="money with wings" data-name="money_with_wings" data-unicode-version="6.0">💸</gl-emoji>. Would it be possible to also replace <code>moment</code> in <a href="https://gitlab.com/gitlab-org/gitlab-vscode-extension/blob/bec5ccb142e4890e20f5f0036cc1e878ff761309/src%2Fwebview%2Fsrc%2Fcomponents%2FDate.vue#L14-18"><code>Date.vue</code></a> in the <code>webview</code>? I know that the dependencies are managed separately, but it would be good for consistency to update both places.</p>',
};
const note2TextSnippet = 'I know that the dependencies are managed separately, but it would';
const singleNote = {
replyId: 'gid://gitlab/IndividualNoteDiscussion/afbf8f461a773fc130aa8091c6636f22efb5f4c5',
createdAt: '2020-12-02T17:00:04Z',
notes: {
pageInfo: {
hasNextPage: false,
endCursor: 'MQ',
},
nodes: [note1],
},
};
const multipleNotes = {
replyId: 'gid://gitlab/IndividualNoteDiscussion/afbf8f461a773fc130aa8091c6636f22efb5f4c5',
createdAt: '2020-12-02T17:00:04Z',
notes: {
pageInfo: {
hasNextPage: false,
endCursor: 'MQ',
},
nodes: [note1, note2],
},
};
const projectWithDiscussions = {
project: {
id: 'gid://gitlab/Project/278964',
issue: {
discussions: {
pageInfo: {
hasNextPage: false,
endCursor: 'Nw',
},
nodes: [systemNote, singleNote, multipleNotes],
},
},
},
};
module.exports = {
projectWithDiscussions,
note1,
note1TextSnippet,
note2,
note2TextSnippet,
singleNote,
multipleNotes,
systemNote,
systemNoteTextSnippet,
};
{
"project": {
"id": "gid://gitlab/Project/278964",
"issue": {
"discussions": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "Nw"
},
"nodes": [
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/3e120050b42400665aa728f283cfa167d800f03e",
"createdAt": "2020-12-02T09:44:11Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/458662425",
"createdAt": "2020-12-02T09:44:11Z",
"system": true,
"author": {
"avatarUrl": "https://secure.gravatar.com/avatar/24d3a696fcc9592d18db6e623c0e654e?s=80&d=identicon",
"name": "Vitaly Markov",
"username": "vymarkov",
"webUrl": "https://gitlab.com/vymarkov"
},
"body": "added 2 commits\n\n<ul><li>5b63a281 - fix(lint): Fix linter errors</li><li>618c91eb - docs: Update CONTRIBUTING.md</li></ul>\n\n[Compare with previous version](/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?diff_id=128320927&start_sha=2a7d1c93417adaafaee85b0345fdf8ea3f28c847)",
"bodyHtml": "<p data-sourcepos=\"1:1-1:15\" dir=\"auto\">added 2 commits</p>&#x000A;<ul dir=\"auto\">&#x000A;<li>&#x000A;<a href=\"/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?commit_id=5b63a28151c5028e6bc0758ec1c28d4c36256a58\" data-original=\"5b63a281\" data-link=\"false\" data-link-reference=\"false\" data-project=\"278964\" data-commit=\"5b63a28151c5028e6bc0758ec1c28d4c36256a58\" data-reference-type=\"commit\" data-container=\"body\" data-placement=\"top\" title=\"fix(lint): Fix linter errors\" class=\"gfm gfm-commit has-tooltip\">5b63a281</a> - fix(lint): Fix linter errors</li>&#x000A;<li>&#x000A;<a href=\"/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?commit_id=618c91ebd1527deef3740f66d8950ecc85032782\" data-original=\"618c91eb\" data-link=\"false\" data-link-reference=\"false\" data-project=\"278964\" data-commit=\"618c91ebd1527deef3740f66d8950ecc85032782\" data-reference-type=\"commit\" data-container=\"body\" data-placement=\"top\" title=\"docs: Update CONTRIBUTING.md\" class=\"gfm gfm-commit has-tooltip\">618c91eb</a> - docs: Update CONTRIBUTING.md</li>&#x000A;</ul>&#x000A;<p data-sourcepos=\"5:1-5:164\" dir=\"auto\"><a href=\"/gitlab-org/gitlab-vscode-extension/-/merge_requests/130/diffs?diff_id=128320927&amp;start_sha=2a7d1c93417adaafaee85b0345fdf8ea3f28c847\">Compare with previous version</a></p>"
}
]
}
},
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/afbf8f461a773fc130aa8091c6636f22efb5f4c5",
"createdAt": "2020-12-02T17:00:04Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/459020558",
"createdAt": "2020-12-02T17:00:04Z",
"system": false,
"author": {
"avatarUrl": "https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon",
"name": "Tomas Vik",
"username": "viktomas",
"webUrl": "https://gitlab.com/viktomas"
},
"body": "@vymarkov Thank you for fixing the `CONTRIBUTING.md` :tada:\n\nRegarding the change in `src/gitlab_service.ts`, I think we should still show some message to the user when they try to run `GitLab: *` command and the extension fails to execute it.\n\nWe had a lot of troubles in the past when we were swallowing errors and then we weren't able to help the extension users debug any potential issues. (https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145)",
"bodyHtml": "<p data-sourcepos=\"1:1-1:59\" dir=\"auto\"><a href=\"/vymarkov\" data-user=\"359491\" data-reference-type=\"user\" data-container=\"body\" data-placement=\"top\" class=\"gfm gfm-project_member js-user-link\" title=\"Vitaly Markov\">@vymarkov</a> Thank you for fixing the <code>CONTRIBUTING.md</code> <gl-emoji title=\"party popper\" data-name=\"tada\" data-unicode-version=\"6.0\">🎉</gl-emoji></p>&#x000A;<p data-sourcepos=\"3:1-3:182\" dir=\"auto\">Regarding the change in <code>src/gitlab_service.ts</code>, I think we should still show some message to the user when they try to run <code>GitLab: *</code> command and the extension fails to execute it.</p>&#x000A;<p data-sourcepos=\"5:1-5:217\" dir=\"auto\">We had a lot of troubles in the past when we were swallowing errors and then we weren't able to help the extension users debug any potential issues. (<a href=\"https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145\" data-original=\"https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/145\" data-link=\"false\" data-link-reference=\"true\" data-project=\"278964\" data-issue=\"30087182\" data-reference-type=\"issue\" data-container=\"body\" data-placement=\"top\" title=\"Error reporting to VSCode OutputChannel\" class=\"gfm gfm-issue has-tooltip\">#145 (closed)</a>)</p>"
}
]
}
},
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/27801445b1ed5c1344c3d7f2354cd6144046cd31",
"createdAt": "2020-12-02T17:00:15Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/459020697",
"createdAt": "2020-12-02T17:00:15Z",
"system": true,
"author": {
"avatarUrl": "https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon",
"name": "Tomas Vik",
"username": "viktomas",
"webUrl": "https://gitlab.com/viktomas"
},
"body": "assigned to @viktomas",
"bodyHtml": "<p data-sourcepos=\"1:1-1:21\" dir=\"auto\">assigned to <a href=\"/viktomas\" data-user=\"3457201\" data-reference-type=\"user\" data-container=\"body\" data-placement=\"top\" class=\"gfm gfm-project_member js-user-link\" title=\"Tomas Vik\">@viktomas</a></p>"
}
]
}
},
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/34493f511812d89dd5992fea24d52764aaf89096",
"createdAt": "2020-12-02T17:00:22Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/459020793",
"createdAt": "2020-12-02T17:00:22Z",
"system": true,
"author": {
"avatarUrl": "https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon",
"name": "Tomas Vik",
"username": "viktomas",
"webUrl": "https://gitlab.com/viktomas"
},
"body": "assigned to @vymarkov",
"bodyHtml": "<p data-sourcepos=\"1:1-1:21\" dir=\"auto\">assigned to <a href=\"/vymarkov\" data-user=\"359491\" data-reference-type=\"user\" data-container=\"body\" data-placement=\"top\" class=\"gfm gfm-project_member js-user-link\" title=\"Vitaly Markov\">@vymarkov</a></p>"
}
]
}
},
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/590262a4335578f03bbf725a6ee01345b20c3acf",
"createdAt": "2020-12-03T00:11:43Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/459233800",
"createdAt": "2020-12-03T00:11:43Z",
"system": true,
"author": {
"avatarUrl": "/uploads/-/system/user/avatar/1786152/avatar.png",
"name": "🤖 GitLab Bot 🤖",
"username": "gitlab-bot",
"webUrl": "https://gitlab.com/gitlab-bot"
},
"body": "mentioned in issue gitlab-org/quality/triage-reports#1062",
"bodyHtml": "<p data-sourcepos=\"1:1-1:57\" dir=\"auto\">mentioned in issue <a href=\"/gitlab-org/quality/triage-reports/-/issues/1062\" data-original=\"gitlab-org/quality/triage-reports#1062\" data-link=\"false\" data-link-reference=\"false\" data-project=\"16233736\" data-issue=\"75514620\" data-reference-type=\"issue\" data-container=\"body\" data-placement=\"top\" title=\"2020-12-03 Untriaged community merge requests requiring initial triage\" class=\"gfm gfm-issue has-tooltip\">gitlab-org/quality/triage-reports#1062 (closed)</a></p>"
}
]
}
},
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/f5677c52b69037d2311aa0d4d842b434df5c5ae6",
"createdAt": "2020-12-03T10:58:37Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/459646571",
"createdAt": "2020-12-03T10:58:37Z",
"system": false,
"author": {
"avatarUrl": "https://secure.gravatar.com/avatar/24d3a696fcc9592d18db6e623c0e654e?s=80&d=identicon",
"name": "Vitaly Markov",
"username": "vymarkov",
"webUrl": "https://gitlab.com/vymarkov"
},
"body": "> I think we should still show some message to the user when they try to run `GitLab: *` command and the extension fails to execute it.\n\nWill it be enough to log the error message `project not found`? \n\nIt's critical issue, I can't use ext cause I have on my workspace some repo from Github, it lead to issue what I'm trying to fix.",
"bodyHtml": "<blockquote data-sourcepos=\"1:1-1:135\" dir=\"auto\">&#x000A;<p data-sourcepos=\"1:3-1:135\">I think we should still show some message to the user when they try to run <code>GitLab: *</code> command and the extension fails to execute it.</p>&#x000A;</blockquote>&#x000A;<p data-sourcepos=\"3:1-3:64\" dir=\"auto\">Will it be enough to log the error message <code>project not found</code>?</p>&#x000A;<p data-sourcepos=\"5:1-5:129\" dir=\"auto\">It's critical issue, I can't use ext cause I have on my workspace some repo from Github, it lead to issue what I'm trying to fix.</p>"
}
]
}
},
{
"replyId": "gid://gitlab/IndividualNoteDiscussion/ffd1e603c157acaa58f1bdeb45e03fbc47450c57",
"createdAt": "2020-12-03T12:50:21Z",
"notes": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "gid://gitlab/Note/459784823",
"createdAt": "2020-12-03T12:50:21Z",
"system": true,
"author": {
"avatarUrl": "https://secure.gravatar.com/avatar/6042a9152ada74d9fb6a0cdce895337e?s=80&d=identicon",
"name": "Tomas Vik",
"username": "viktomas",
"webUrl": "https://gitlab.com/viktomas"
},
"body": "mentioned in issue #275",
"bodyHtml": "<p data-sourcepos=\"1:1-1:23\" dir=\"auto\">mentioned in issue <a href=\"/gitlab-org/gitlab-vscode-extension/-/issues/275\" data-original=\"#275\" data-link=\"false\" data-link-reference=\"false\" data-project=\"278964\" data-issue=\"75467458\" data-reference-type=\"issue\" data-container=\"body\" data-placement=\"top\" title=\"API request failed when trying to get current project because: Error: 404 Project Not Found\" class=\"gfm gfm-issue has-tooltip\">#275</a></p>"
}
]
}
}
]
}
}
}
}
......@@ -6,13 +6,9 @@ const { graphql } = require('msw');
const webviewController = require('../../src/webview_controller');
const { tokenService } = require('../../src/services/token_service');
const openIssueResponse = require('./fixtures/rest/open_issue.json');
const discussionsResponse = require('./fixtures/graphql/discussions.json');
const { projectWithDiscussions } = require('./fixtures/graphql/discussions');
const {
getServer,
createJsonEndpoint,
createPostEndpoint,
} = require('./test_infrastructure/mock_server');
const { getServer, createJsonEndpoint } = require('./test_infrastructure/mock_server');
const { GITLAB_URL } = require('./test_infrastructure/constants');
const waitForMessage = (panel, type) =>
......@@ -33,17 +29,25 @@ describe('GitLab webview', () => {
server = getServer([
graphql.query('GetIssueDiscussions', (req, res, ctx) => {
if (req.variables.projectPath === 'gitlab-org/gitlab')
return res(ctx.data(discussionsResponse));
return res(ctx.data(projectWithDiscussions));
return res(ctx.data({ project: null }));
}),
graphql.mutation('CreateNote', (req, res, ctx) => {
const { issuableId, body } = req.variables;
if (issuableId === 'gid://gitlab/Issue/35284557' && body === 'Hello')
return res(
ctx.data({
createNote: {
errors: [],
},
}),
);
return res(ctx.status(500));
}),
createJsonEndpoint(
`/projects/${openIssueResponse.project_id}/issues/${openIssueResponse.iid}/resource_label_events`,
[],
),
createPostEndpoint(
`/projects/${openIssueResponse.project_id}/issues/${openIssueResponse.iid}/notes`,
{},
),
]);
await tokenService.setToken(GITLAB_URL, 'abcd-secret');
});
......@@ -91,9 +95,7 @@ describe('GitLab webview', () => {
it('sends a message', async () => {
webviewPanel.webview.postMessage({
command: 'saveNote',
issuable: openIssueResponse,
note: 'Hello',
noteType: { path: 'issues' },
});
const sentMessage = await waitForMessage(webviewPanel, 'noteSaved');
assert.strictEqual(sentMessage.type, 'noteSaved');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册