Skip to content

Commit f5ec00a

Browse files
committed
feat(mr): edit desc.
1 parent afed00c commit f5ec00a

File tree

6 files changed

+236
-209
lines changed

6 files changed

+236
-209
lines changed

src/panel.ts

Lines changed: 157 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,9 @@ export class Panel {
1919
private readonly _extensionPath: string;
2020
private _disposables: vscode.Disposable[] = [];
2121

22-
public static createOrShow(context: vscode.ExtensionContext, codingSrv: CodingServer) {
23-
const { extensionUri, extensionPath } = context;
24-
const column = vscode.window.activeTextEditor
25-
? vscode.window.activeTextEditor.viewColumn
26-
: undefined;
27-
28-
// If we already have a panel, show it.
29-
if (Panel.currentPanel) {
30-
Panel.currentPanel._panel.reveal(column);
31-
return;
32-
}
33-
34-
// Otherwise, create a new panel.
35-
const panel = vscode.window.createWebviewPanel(
36-
Panel.viewType,
37-
'Coding',
38-
column || vscode.ViewColumn.One,
39-
{
40-
// Enable javascript in the webview
41-
enableScripts: true,
42-
43-
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'out')],
44-
},
45-
);
46-
47-
Panel.currentPanel = new Panel(panel, codingSrv, extensionUri, extensionPath);
48-
}
49-
50-
public static revive(
51-
panel: vscode.WebviewPanel,
52-
codingSrv: CodingServer,
53-
extensionUri: vscode.Uri,
54-
extensionPath: string,
55-
) {
56-
Panel.currentPanel = new Panel(panel, codingSrv, extensionUri, extensionPath);
57-
}
22+
private _waitForReady: Promise<void>;
23+
private _onIsReady: vscode.EventEmitter<void> = new vscode.EventEmitter();
24+
protected readonly MESSAGE_UNHANDLED: string = 'message not handled';
5825

5926
private constructor(
6027
panel: vscode.WebviewPanel,
@@ -86,123 +53,174 @@ export class Panel {
8653
);
8754

8855
// Handle messages from the webview
89-
this._panel.webview.onDidReceiveMessage(
90-
async (message: IRequestMessage<any>) => {
91-
const { command, args } = message;
92-
try {
93-
switch (command) {
94-
case 'alert':
95-
vscode.window.showErrorMessage(args);
96-
return;
97-
case 'mr.close':
98-
await this._codingSrv.closeMR(args);
99-
this.replyMessage(message);
100-
break;
101-
case 'mr.approve':
102-
await this._codingSrv.approveMR(args);
103-
this.replyMessage(message);
104-
break;
105-
case 'mr.disapprove':
106-
await this._codingSrv.disapproveMR(args);
107-
this.replyMessage(message);
108-
break;
109-
case 'mr.merge':
110-
await this._codingSrv.mergeMR(args);
111-
this.replyMessage(message);
112-
break;
113-
case 'mr.update.title':
114-
await this._codingSrv.updateMRTitle(args.iid, args.title);
115-
this.replyMessage(message);
116-
break;
117-
case 'mr.add.comment':
118-
const commentRes = await this._codingSrv.commentMR(args.id, args.comment);
119-
this.broadcast(command, commentRes.data);
120-
break;
121-
case 'mr.get.activities':
122-
const getActivitiesRes = await this._codingSrv.getMRActivities(args);
123-
this.replyMessage(message, getActivitiesRes.data);
124-
break;
125-
case 'mr.update.reviewers': {
126-
try {
127-
const [iid, selected]: [string, number[]] = args;
128-
const {
129-
data: { list: memberList },
130-
} = await codingSrv.getProjectMembers();
131-
const list = memberList
132-
.filter((i) => i.user.global_key !== codingSrv.session?.user?.global_key)
133-
.map((i) => ({
134-
label: i.user.name,
135-
description: i.user.global_key,
136-
picked: selected.includes(i.user.id),
137-
userId: i.user.id,
138-
}));
139-
const selection = await vscode.window.showQuickPick(list, {
140-
canPickMany: true,
141-
ignoreFocusOut: true,
142-
});
143-
144-
if (!selection) {
145-
return;
146-
}
147-
148-
const s = selection.map((i) => i.userId);
149-
const added = s.filter((i) => !selected.includes(i));
150-
const removed = selected.filter((i) => !s.includes(i));
151-
const tasks = [];
152-
if (added.length) {
153-
tasks.push(codingSrv.addMRReviewers(iid, added));
154-
}
155-
if (removed.length) {
156-
tasks.push(codingSrv.removeMRReviewers(iid, removed));
157-
}
158-
159-
await Promise.all(tasks);
160-
const resp = await codingSrv.getMRReviewers(iid);
161-
this.broadcast(command, resp.data);
162-
} catch (err) {}
163-
break;
164-
}
165-
case `mr.update.desc`: {
166-
try {
167-
const [iid, content] = args;
168-
const resp = await codingSrv.updateMRDesc(iid, content);
169-
this.broadcast(command, [iid, resp.data]);
170-
} catch (e) {}
171-
break;
172-
}
173-
default:
174-
break;
175-
}
176-
} catch (err) {
177-
this.throwError(message, err.msg);
178-
vscode.window.showErrorMessage(formatErrorMessage(err.msg));
179-
}
56+
this._panel.webview?.onDidReceiveMessage(
57+
async (message) => {
58+
await this._onDidReceiveMessage(message);
18059
},
18160
null,
18261
this._disposables,
18362
);
63+
64+
this._waitForReady = new Promise((resolve) => {
65+
const disposable = this._onIsReady.event(() => {
66+
disposable.dispose();
67+
resolve();
68+
});
69+
});
18470
}
18571

186-
public replyMessage(originalMessage: IRequestMessage<any>, message?: any) {
72+
protected async _onDidReceiveMessage(message: IRequestMessage<any>) {
73+
const { command, args } = message;
74+
try {
75+
switch (command) {
76+
case 'alert':
77+
vscode.window.showErrorMessage(args);
78+
return;
79+
case 'mr.close':
80+
await this._codingSrv.closeMR(args);
81+
this._replyMessage(message, {});
82+
break;
83+
case 'mr.approve':
84+
await this._codingSrv.approveMR(args);
85+
this._replyMessage(message, {});
86+
break;
87+
case 'mr.disapprove':
88+
await this._codingSrv.disapproveMR(args);
89+
this._replyMessage(message, {});
90+
break;
91+
case 'mr.merge':
92+
await this._codingSrv.mergeMR(args);
93+
this._replyMessage(message, {});
94+
break;
95+
case 'mr.update.title':
96+
await this._codingSrv.updateMRTitle(args.iid, args.title);
97+
this._replyMessage(message, {});
98+
break;
99+
case 'mr.add.comment':
100+
const commentRes = await this._codingSrv.commentMR(args.id, args.comment);
101+
this._replyMessage(message, commentRes.data);
102+
break;
103+
case 'mr.get.activities':
104+
const getActivitiesRes = await this._codingSrv.getMRActivities(args);
105+
this._replyMessage(message, getActivitiesRes.data);
106+
break;
107+
case 'mr.update.reviewers': {
108+
try {
109+
const [iid, selected]: [string, number[]] = args;
110+
const {
111+
data: { list: memberList },
112+
} = await this._codingSrv.getProjectMembers();
113+
const list = memberList
114+
.filter((i) => i.user.global_key !== this._codingSrv.session?.user?.global_key)
115+
.map((i) => ({
116+
label: i.user.name,
117+
description: i.user.global_key,
118+
picked: selected.includes(i.user.id),
119+
userId: i.user.id,
120+
}));
121+
const selection = await vscode.window.showQuickPick(list, {
122+
canPickMany: true,
123+
ignoreFocusOut: true,
124+
});
125+
126+
if (!selection) {
127+
return;
128+
}
129+
130+
const s = selection.map((i) => i.userId);
131+
const added = s.filter((i) => !selected.includes(i));
132+
const removed = selected.filter((i) => !s.includes(i));
133+
const tasks = [];
134+
if (added.length) {
135+
tasks.push(this._codingSrv.addMRReviewers(iid, added));
136+
}
137+
if (removed.length) {
138+
tasks.push(this._codingSrv.removeMRReviewers(iid, removed));
139+
}
140+
141+
await Promise.all(tasks);
142+
const resp = await this._codingSrv.getMRReviewers(iid);
143+
this.broadcast(command, resp.data);
144+
} catch (err) {}
145+
break;
146+
}
147+
case `mr.update.desc`: {
148+
try {
149+
const { iid, content } = args;
150+
const resp = await this._codingSrv.updateMRDesc(iid, content);
151+
this._replyMessage(message, resp.data);
152+
} catch (e) {}
153+
break;
154+
}
155+
default:
156+
return this.MESSAGE_UNHANDLED;
157+
}
158+
} catch (err) {
159+
this._throwError(message, err.msg);
160+
vscode.window.showErrorMessage(formatErrorMessage(err.msg));
161+
}
162+
}
163+
164+
protected async _postMessage(message: any) {
165+
// Without the following ready check, we can end up in a state where the message handler in the webview
166+
// isn't ready for any of the messages we post.
167+
await this._waitForReady;
168+
this._panel.webview?.postMessage({
169+
res: message,
170+
});
171+
}
172+
173+
protected async _replyMessage(originalMessage: IRequestMessage<any>, message: any = {}) {
187174
const reply: IReplyMessage = {
188175
seq: originalMessage.req,
189176
res: message,
190177
};
191-
this._panel.webview.postMessage(reply);
178+
this._panel.webview?.postMessage(reply);
192179
}
193180

194-
public throwError(originalMessage: IRequestMessage<any>, error: any) {
181+
protected async _throwError(originalMessage: IRequestMessage<any>, error: any) {
195182
const reply: IReplyMessage = {
196183
seq: originalMessage.req,
197184
err: error,
198185
};
199-
this._panel.webview.postMessage(reply);
186+
this._panel.webview?.postMessage(reply);
187+
}
188+
189+
public static createOrShow(context: vscode.ExtensionContext, codingSrv: CodingServer) {
190+
const { extensionUri, extensionPath } = context;
191+
const column = vscode.window.activeTextEditor
192+
? vscode.window.activeTextEditor.viewColumn
193+
: undefined;
194+
195+
// If we already have a panel, show it.
196+
if (Panel.currentPanel) {
197+
Panel.currentPanel._panel.reveal(column);
198+
return;
199+
}
200+
201+
// Otherwise, create a new panel.
202+
const panel = vscode.window.createWebviewPanel(
203+
Panel.viewType,
204+
'Coding',
205+
column || vscode.ViewColumn.One,
206+
{
207+
// Enable javascript in the webview
208+
enableScripts: true,
209+
210+
localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'out')],
211+
},
212+
);
213+
214+
Panel.currentPanel = new Panel(panel, codingSrv, extensionUri, extensionPath);
200215
}
201216

202-
public doRefactor() {
203-
// Send a message to the webview webview.
204-
// You can send any JSON serializable data.
205-
this._panel.webview.postMessage({ command: 'refactor' });
217+
public static revive(
218+
panel: vscode.WebviewPanel,
219+
codingSrv: CodingServer,
220+
extensionUri: vscode.Uri,
221+
extensionPath: string,
222+
) {
223+
Panel.currentPanel = new Panel(panel, codingSrv, extensionUri, extensionPath);
206224
}
207225

208226
public broadcast(command: string, res: any) {
@@ -232,21 +250,21 @@ export class Panel {
232250
// Vary the webview's content based on where it is located in the editor.
233251
switch (this._panel.viewColumn) {
234252
case vscode.ViewColumn.Two:
235-
this._updateForCat(webview);
253+
this._updateForPanel(webview);
236254
return;
237255

238256
case vscode.ViewColumn.Three:
239-
this._updateForCat(webview);
257+
this._updateForPanel(webview);
240258
return;
241259

242260
case vscode.ViewColumn.One:
243261
default:
244-
this._updateForCat(webview);
262+
this._updateForPanel(webview);
245263
return;
246264
}
247265
}
248266

249-
private _updateForCat(webview: vscode.Webview) {
267+
private _updateForPanel(webview: vscode.Webview) {
250268
this._panel.title = `Merge Request Overview`;
251269
this._panel.webview.html = this._getHtmlForWebview(webview);
252270
}

webviews/App.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Activities from 'webviews/components/Activities';
77
import Reviewers from 'webviews/components/Reviewers';
88
import messageTransferHook from 'webviews/hooks/messageTransferHook';
99
import EditButton from 'webviews/components/EditButton';
10-
import { requestUpdateMRContent } from 'webviews/service/mrService';
10+
// import { requestUpdateMRContent } from 'webviews/service/mrService';
1111

1212
import {
1313
EmptyWrapper,
@@ -25,7 +25,7 @@ import {
2525
} from 'webviews/app.styles';
2626

2727
function App() {
28-
const { currentMR, updateMRTitle, toggleUpdatingDesc } = appStore;
28+
const { currentMR, updateMRTitle, toggleUpdatingDesc, updateMRDesc } = appStore;
2929
const [isEditingTitle, setEditingTitle] = useState(false);
3030
const [title, setTitle] = useState(currentMR?.data?.merge_request?.title);
3131
const inputRef = useRef<HTMLInputElement | null>(null);
@@ -59,7 +59,7 @@ function App() {
5959
};
6060

6161
const onEditDesc = () => {
62-
toggleUpdatingDesc();
62+
toggleUpdatingDesc(true);
6363
setDesc(currentMR.data.merge_request.body_plan);
6464
};
6565

@@ -68,7 +68,7 @@ function App() {
6868
};
6969

7070
const onSaveDesc = async () => {
71-
await requestUpdateMRContent(currentMR.iid, desc);
71+
await updateMRDesc(currentMR.iid, desc);
7272
};
7373

7474
if (!currentMR.iid) {
@@ -119,7 +119,9 @@ function App() {
119119
<OperationBtn className={`colored`} onClick={onSaveDesc}>
120120
Save
121121
</OperationBtn>
122-
<OperationBtn className={`colored secondary`} onClick={() => toggleUpdatingDesc()}>
122+
<OperationBtn
123+
className={`colored secondary`}
124+
onClick={() => toggleUpdatingDesc(false)}>
123125
Cancel
124126
</OperationBtn>
125127
</>

0 commit comments

Comments
 (0)