Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f69d2c6

Browse files
Merge pull request cangzhang#18 from cangzhang/feat/mr-status
2 parents c6483d2 + 16b38d1 commit f69d2c6

24 files changed

+362
-77
lines changed

‎README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
## How to use
44

55
1. Install the plugin
6-
1. Open a repo host by `coding.net`
6+
1. Open a repo hosted by `coding.net`
77
1. Click on `Log in` button
8-
1. You will be redirected back to the editor, free to try & open an issue
8+
1. You will be redirected back to the editor, feel free to try & open an issue
99

1010
## Development
1111

‎package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "coding-plugin",
33
"displayName": "CODING Merge Requests & Releases",
44
"description": "CODING plugin for VS Code.",
5-
"version": "0.2.1",
5+
"version": "0.3.0",
66
"publisher": "coding-net",
77
"license": "MIT",
88
"engines": {
@@ -19,7 +19,7 @@
1919
"icon": "assets/coding.png",
2020
"repository": {
2121
"type": "git",
22-
"url": "https://github.com/cangzhang/coding-vscode.git"
22+
"url": "https://github.com/Coding/coding-vscode.git"
2323
},
2424
"main": "./out/extension.js",
2525
"contributes": {

‎src/codingServer.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
IMemberListResp,
1818
IMRContentResp,
1919
ICreateCommentResp,
20+
IMRStatusResp,
2021
} from 'src/typings/respResult';
2122
import { PromiseAdapter, promiseFromEvent, parseQuery, parseCloneUrl } from 'src/common/utils';
2223
import { GitService } from 'src/common/gitService';
@@ -96,6 +97,13 @@ export class CodingServer {
9697
await vscode.commands.executeCommand('setContext', 'hasRepo', !!repoInfo?.repo);
9798
const result = await this.getUserInfo(repoInfo?.team || ``, accessToken);
9899
const { data: userInfo } = result;
100+
101+
if (userInfo.team !== repoInfo?.team) {
102+
this._loggedIn = false;
103+
await vscode.commands.executeCommand('setContext', 'loggedIn', this._loggedIn);
104+
throw new Error(`team not match`);
105+
}
106+
99107
const ret: ISessionData = {
100108
id: nanoid(),
101109
user: userInfo,
@@ -686,6 +694,27 @@ export class CodingServer {
686694
}
687695
}
688696

697+
public async fetchMRStatus(iid: string) {
698+
try {
699+
const { repoApiPrefix } = await this.getApiPrefix();
700+
const resp: IMRStatusResp = await got
701+
.get(`${repoApiPrefix}/merge/${iid}/commit-statuses`, {
702+
searchParams: {
703+
access_token: this._session?.accessToken,
704+
},
705+
})
706+
.json();
707+
708+
if (resp.code) {
709+
return Promise.reject(resp);
710+
}
711+
712+
return resp;
713+
} catch (e) {
714+
return Promise.reject(e);
715+
}
716+
}
717+
689718
get loggedIn() {
690719
return this._loggedIn;
691720
}

‎src/panel.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,17 @@ export class Panel {
106106
break;
107107
case 'mr.update.reviewers': {
108108
try {
109-
const { iid, list: selected }: { iid: string; list: number[] } = args;
109+
const {
110+
iid,
111+
list: selected,
112+
author,
113+
}: { iid: string; list: number[]; author: string } = args;
110114
const {
111115
data: { list: memberList },
112116
} = await this._codingSrv.getProjectMembers();
117+
113118
const list = memberList
114-
.filter((i) => i.user.global_key !== this._codingSrv.session?.user?.global_key)
119+
.filter((i) => i.user.global_key !== author)
115120
.map((i) => ({
116121
label: i.user.name,
117122
description: i.user.global_key,
@@ -152,6 +157,14 @@ export class Panel {
152157
} catch (e) {}
153158
break;
154159
}
160+
case `mr.fetch.status`: {
161+
try {
162+
const { iid } = args;
163+
const resp = await this._codingSrv.fetchMRStatus(iid);
164+
this._replyMessage(message, resp.data);
165+
} catch (e) {}
166+
break;
167+
}
155168
default:
156169
return this.MESSAGE_UNHANDLED;
157170
}

‎src/tree/mrTree.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ enum ItemType {
2020
Node = `node`,
2121
}
2222

23+
const capitalized = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
24+
2325
const getIcon = (name: string, theme: string) =>
2426
path.join(__filename, `../../../assets/${theme}/${name}.png`);
2527

@@ -58,7 +60,7 @@ export class MRTreeDataProvider implements vscode.TreeDataProvider<ListItem<ITre
5860
private _disposables: vscode.Disposable[];
5961

6062
private _context: vscode.ExtensionContext;
61-
private _service: CodingServer;
63+
private readonly_service: CodingServer;
6264

6365
constructor(context: vscode.ExtensionContext, service: CodingServer) {
6466
this._context = context;
@@ -83,7 +85,7 @@ export class MRTreeDataProvider implements vscode.TreeDataProvider<ListItem<ITre
8385

8486
getChildren(element?: ListItem<ITreeNode>): Thenable<ListItem<ITreeNode>[]> {
8587
if (!this._service.loggedIn) {
86-
vscode.window.showErrorMessage(`[MR Tree] Invalid credentials.`);
88+
console.error(`[MR Tree] Invalid credentials.`);
8789
return Promise.resolve([]);
8890
}
8991

@@ -94,17 +96,13 @@ export class MRTreeDataProvider implements vscode.TreeDataProvider<ListItem<ITre
9496

9597
if (!element) {
9698
return Promise.resolve([
99+
new CategoryItem(capitalized(MRType.Open), MRType.Open, TreeItemCollapsibleState.Collapsed),
97100
new CategoryItem(
98-
MRType.Open.toUpperCase(),
99-
MRType.Open,
100-
TreeItemCollapsibleState.Collapsed,
101-
),
102-
new CategoryItem(
103-
MRType.Closed.toUpperCase(),
101+
capitalized(MRType.Closed),
104102
MRType.Closed,
105103
TreeItemCollapsibleState.Collapsed,
106104
),
107-
new CategoryItem(MRType.All.toUpperCase(), MRType.All, TreeItemCollapsibleState.Collapsed),
105+
new CategoryItem(capitalized(MRType.All), MRType.All, TreeItemCollapsibleState.Collapsed),
108106
]);
109107
}
110108

@@ -115,7 +113,7 @@ export class MRTreeDataProvider implements vscode.TreeDataProvider<ListItem<ITre
115113
.then((resp) => {
116114
if (resp.code) {
117115
const msg = Object.values(resp.msg || {})[0];
118-
vscode.window.showErrorMessage(`[MR] list: ${msg}`);
116+
console.error(`[MR] list: ${msg}`);
119117
return [];
120118
}
121119

‎src/typings/commonTypes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IMRDetail, IUserItem } from './respResult';
1+
import { IMRDetail, IMRStatusItem,IUserItem } from './respResult';
22

33
export interface IRepoInfo {
44
team: string;
@@ -37,6 +37,7 @@ export interface IMRWebViewDetail {
3737
data: IMRDetail & {
3838
loading: boolean;
3939
editingDesc: boolean;
40+
commit_statuses: IMRStatusItem[];
4041
};
4142
user: IUserItem;
4243
}

‎src/typings/respResult.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,25 @@ export interface IMRContentResp extends CodingResponse {
244244
export interface ICreateCommentResp extends CodingResponse {
245245
data: IComment;
246246
}
247+
248+
export interface IMRStatusItem {
249+
state: string;
250+
sha: string;
251+
context: string;
252+
target_url: string;
253+
description: string;
254+
ignore: boolean;
255+
}
256+
257+
export interface IMRStatus {
258+
state: string;
259+
pendingStateCount: number;
260+
successStateCount: number;
261+
failureStateCount: number;
262+
errorStateCount: number;
263+
statuses: IMRStatusItem[];
264+
}
265+
266+
export interface IMRStatusResp extends CodingResponse {
267+
data: IMRStatus;
268+
}

‎webviews/App.tsx

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import React, { FormEvent, useRef, useState } from 'react';
1+
import React, { FormEvent, useEffect,useRef, useState,useCallback } from 'react';
22
import { view } from '@risingstack/react-easy-state';
33

4+
import { IMRStatus } from 'src/typings/respResult';
5+
46
import appStore from 'webviews/store/appStore';
57
import persistDataHook from 'webviews/hooks/persistDataHook';
6-
import Activities from 'webviews/components/Activities';
7-
import Reviewers from 'webviews/components/Reviewers';
88
import initDataHook from 'webviews/hooks/initDataHook';
9-
import EditButton from 'webviews/components/EditButton';
10-
// import { requestUpdateMRContent } from 'webviews/service/mrService';
9+
10+
import Activities from 'webviews/components/mr/Activities';
11+
import Reviewers from 'webviews/components/mr/Reviewers';
12+
import EditButton from 'webviews/components/mr/EditButton';
13+
import StatusCheck from 'webviews/components/mr/StatusCheck';
1114

1215
import {
1316
EmptyWrapper,
@@ -25,18 +28,46 @@ import {
2528
} from 'webviews/app.styles';
2629

2730
function App() {
28-
const { currentMR, updateMRTitle, toggleUpdatingDesc, updateMRDesc } = appStore;
31+
const { currentMR, updateMRTitle, toggleUpdatingDesc, updateMRDesc, fetchMRStatus } = appStore;
2932
const [isEditingTitle, setEditingTitle] = useState(false);
3033
const [title, setTitle] = useState(currentMR?.data?.merge_request?.title);
3134
const inputRef = useRef<HTMLInputElement | null>(null);
3235
const [desc, setDesc] = useState(``);
36+
const statusChecker = useRef<undefined | number>();
37+
const [statusData, setStatusData] = useState<IMRStatus | null>(null);
3338

3439
const { repoInfo, data } = currentMR;
3540
const { merge_request: mergeRequest } = data || {};
3641

3742
persistDataHook();
3843
initDataHook();
3944

45+
useEffect(() => {
46+
statusChecker.current = window.setTimeout(async () => {
47+
try {
48+
await onRefreshStatus();
49+
} finally {
50+
window.clearTimeout(statusChecker.current);
51+
52+
statusChecker.current = window.setInterval(async () => {
53+
await onRefreshStatus();
54+
}, 30 * 1000);
55+
}
56+
}, 3 * 1000);
57+
58+
return () => {
59+
window.clearTimeout(statusChecker.current);
60+
window.clearInterval(statusChecker.current);
61+
setStatusData(null);
62+
};
63+
}, [currentMR.iid]);
64+
65+
const onRefreshStatus = useCallback(async () => {
66+
const resp = await fetchMRStatus(currentMR.iid);
67+
setStatusData(resp);
68+
return null;
69+
}, [currentMR.iid]);
70+
4071
const handleKeyDown = async (event: any) => {
4172
if (event.key === 'Enter') {
4273
await updateMRTitle(title);
@@ -146,6 +177,9 @@ function App() {
146177
onChange={onChangeDesc}
147178
/>
148179
)}
180+
181+
<StatusCheck data={statusData} onRefresh={onRefreshStatus} />
182+
149183
<SectionTitle>Activities</SectionTitle>
150184
<Activities />
151185
</Body>

‎webviews/assets/edit.svg

Lines changed: 1 addition & 1 deletion
Loading[フレーム]

‎webviews/assets/refresh.svg

Lines changed: 54 additions & 0 deletions
Loading[フレーム]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /