Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
## How to use

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

## Development

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "coding-plugin",
"displayName": "CODING Merge Requests & Releases",
"description": "CODING plugin for VS Code.",
"version": "0.2.1",
"version": "0.3.0",
"publisher": "coding-net",
"license": "MIT",
"engines": {
Expand All @@ -19,7 +19,7 @@
"icon": "assets/coding.png",
"repository": {
"type": "git",
"url": "https://github.com/cangzhang/coding-vscode.git"
"url": "https://github.com/Coding/coding-vscode.git"
},
"main": "./out/extension.js",
"contributes": {
Expand Down
29 changes: 29 additions & 0 deletions src/codingServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
IMemberListResp,
IMRContentResp,
ICreateCommentResp,
IMRStatusResp,
} from 'src/typings/respResult';
import { PromiseAdapter, promiseFromEvent, parseQuery, parseCloneUrl } from 'src/common/utils';
import { GitService } from 'src/common/gitService';
Expand Down Expand Up @@ -96,6 +97,13 @@ export class CodingServer {
await vscode.commands.executeCommand('setContext', 'hasRepo', !!repoInfo?.repo);
const result = await this.getUserInfo(repoInfo?.team || ``, accessToken);
const { data: userInfo } = result;

if (userInfo.team !== repoInfo?.team) {
this._loggedIn = false;
await vscode.commands.executeCommand('setContext', 'loggedIn', this._loggedIn);
throw new Error(`team not match`);
}

const ret: ISessionData = {
id: nanoid(),
user: userInfo,
Expand Down Expand Up @@ -686,6 +694,27 @@ export class CodingServer {
}
}

public async fetchMRStatus(iid: string) {
try {
const { repoApiPrefix } = await this.getApiPrefix();
const resp: IMRStatusResp = await got
.get(`${repoApiPrefix}/merge/${iid}/commit-statuses`, {
searchParams: {
access_token: this._session?.accessToken,
},
})
.json();

if (resp.code) {
return Promise.reject(resp);
}

return resp;
} catch (e) {
return Promise.reject(e);
}
}

get loggedIn() {
return this._loggedIn;
}
Expand Down
17 changes: 15 additions & 2 deletions src/panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,17 @@ export class Panel {
break;
case 'mr.update.reviewers': {
try {
const { iid, list: selected }: { iid: string; list: number[] } = args;
const {
iid,
list: selected,
author,
}: { iid: string; list: number[]; author: string } = args;
const {
data: { list: memberList },
} = await this._codingSrv.getProjectMembers();

const list = memberList
.filter((i) => i.user.global_key !== this._codingSrv.session?.user?.global_key)
.filter((i) => i.user.global_key !== author)
.map((i) => ({
label: i.user.name,
description: i.user.global_key,
Expand Down Expand Up @@ -152,6 +157,14 @@ export class Panel {
} catch (e) {}
break;
}
case `mr.fetch.status`: {
try {
const { iid } = args;
const resp = await this._codingSrv.fetchMRStatus(iid);
this._replyMessage(message, resp.data);
} catch (e) {}
break;
}
default:
return this.MESSAGE_UNHANDLED;
}
Expand Down
18 changes: 8 additions & 10 deletions src/tree/mrTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ enum ItemType {
Node = `node`,
}

const capitalized = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);

const getIcon = (name: string, theme: string) =>
path.join(__filename, `../../../assets/${theme}/${name}.png`);

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

private _context: vscode.ExtensionContext;
private _service: CodingServer;
private readonly _service: CodingServer;

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

getChildren(element?: ListItem<ITreeNode>): Thenable<ListItem<ITreeNode>[]> {
if (!this._service.loggedIn) {
vscode.window.showErrorMessage(`[MR Tree] Invalid credentials.`);
console.error(`[MR Tree] Invalid credentials.`);
return Promise.resolve([]);
}

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

if (!element) {
return Promise.resolve([
new CategoryItem(capitalized(MRType.Open), MRType.Open, TreeItemCollapsibleState.Collapsed),
new CategoryItem(
MRType.Open.toUpperCase(),
MRType.Open,
TreeItemCollapsibleState.Collapsed,
),
new CategoryItem(
MRType.Closed.toUpperCase(),
capitalized(MRType.Closed),
MRType.Closed,
TreeItemCollapsibleState.Collapsed,
),
new CategoryItem(MRType.All.toUpperCase(), MRType.All, TreeItemCollapsibleState.Collapsed),
new CategoryItem(capitalized(MRType.All), MRType.All, TreeItemCollapsibleState.Collapsed),
]);
}

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

Expand Down
3 changes: 2 additions & 1 deletion src/typings/commonTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IMRDetail, IUserItem } from './respResult';
import { IMRDetail, IMRStatusItem, IUserItem } from './respResult';

export interface IRepoInfo {
team: string;
Expand Down Expand Up @@ -37,6 +37,7 @@ export interface IMRWebViewDetail {
data: IMRDetail & {
loading: boolean;
editingDesc: boolean;
commit_statuses: IMRStatusItem[];
};
user: IUserItem;
}
22 changes: 22 additions & 0 deletions src/typings/respResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,25 @@ export interface IMRContentResp extends CodingResponse {
export interface ICreateCommentResp extends CodingResponse {
data: IComment;
}

export interface IMRStatusItem {
state: string;
sha: string;
context: string;
target_url: string;
description: string;
ignore: boolean;
}

export interface IMRStatus {
state: string;
pendingStateCount: number;
successStateCount: number;
failureStateCount: number;
errorStateCount: number;
statuses: IMRStatusItem[];
}

export interface IMRStatusResp extends CodingResponse {
data: IMRStatus;
}
46 changes: 40 additions & 6 deletions webviews/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React, { FormEvent, useRef, useState } from 'react';
import React, { FormEvent, useEffect, useRef, useState, useCallback } from 'react';
import { view } from '@risingstack/react-easy-state';

import { IMRStatus } from 'src/typings/respResult';

import appStore from 'webviews/store/appStore';
import persistDataHook from 'webviews/hooks/persistDataHook';
import Activities from 'webviews/components/Activities';
import Reviewers from 'webviews/components/Reviewers';
import initDataHook from 'webviews/hooks/initDataHook';
import EditButton from 'webviews/components/EditButton';
// import { requestUpdateMRContent } from 'webviews/service/mrService';

import Activities from 'webviews/components/mr/Activities';
import Reviewers from 'webviews/components/mr/Reviewers';
import EditButton from 'webviews/components/mr/EditButton';
import StatusCheck from 'webviews/components/mr/StatusCheck';

import {
EmptyWrapper,
Expand All @@ -25,18 +28,46 @@ import {
} from 'webviews/app.styles';

function App() {
const { currentMR, updateMRTitle, toggleUpdatingDesc, updateMRDesc } = appStore;
const { currentMR, updateMRTitle, toggleUpdatingDesc, updateMRDesc, fetchMRStatus } = appStore;
const [isEditingTitle, setEditingTitle] = useState(false);
const [title, setTitle] = useState(currentMR?.data?.merge_request?.title);
const inputRef = useRef<HTMLInputElement | null>(null);
const [desc, setDesc] = useState(``);
const statusChecker = useRef<undefined | number>();
const [statusData, setStatusData] = useState<IMRStatus | null>(null);

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

persistDataHook();
initDataHook();

useEffect(() => {
statusChecker.current = window.setTimeout(async () => {
try {
await onRefreshStatus();
} finally {
window.clearTimeout(statusChecker.current);

statusChecker.current = window.setInterval(async () => {
await onRefreshStatus();
}, 30 * 1000);
}
}, 3 * 1000);

return () => {
window.clearTimeout(statusChecker.current);
window.clearInterval(statusChecker.current);
setStatusData(null);
};
}, [currentMR.iid]);

const onRefreshStatus = useCallback(async () => {
const resp = await fetchMRStatus(currentMR.iid);
setStatusData(resp);
return null;
}, [currentMR.iid]);

const handleKeyDown = async (event: any) => {
if (event.key === 'Enter') {
await updateMRTitle(title);
Expand Down Expand Up @@ -146,6 +177,9 @@ function App() {
onChange={onChangeDesc}
/>
)}

<StatusCheck data={statusData} onRefresh={onRefreshStatus} />

<SectionTitle>Activities</SectionTitle>
<Activities />
</Body>
Expand Down
2 changes: 1 addition & 1 deletion webviews/assets/edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions webviews/assets/refresh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 0 additions & 41 deletions webviews/components/EditButton.tsx

This file was deleted.

Loading