Skip to content

Commit a412132

Browse files
authored
Merge pull request cangzhang#4 from cangzhang/feat/webview
feat: add mr detail webview ui
2 parents 3689b5a + 97e6f31 commit a412132

File tree

10 files changed

+134
-56
lines changed

10 files changed

+134
-56
lines changed

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"rightside": [
6969
{
7070
"id": "WebviewContainerId",
71-
"title": "WEBVIEW"
71+
"title": "CODING 合并请求详情"
7272
}
7373
]
7474
},
@@ -88,7 +88,7 @@
8888
"WebviewContainerId": [
8989
{
9090
"id": "codingPlugin.webview",
91-
"title": "WEBVIEW"
91+
"title": "CODING 合并请求详情"
9292
}
9393
]
9494
}
@@ -116,12 +116,14 @@
116116
},
117117
"dependencies": {
118118
"axios": "^0.21.0",
119+
"classnames": "^2.2.6",
119120
"isomorphic-git": "^1.8.0",
120121
"querystring": "^0.2.0",
121122
"react": "^17.0.1",
122123
"react-dom": "^17.0.1"
123124
},
124125
"devDependencies": {
126+
"@types/classnames": "^2.2.11",
125127
"@types/node": "^14.14.7",
126128
"@types/react": "^16.9.56",
127129
"@types/react-dom": "^16.9.9",

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import ACTIONS, { dispatch } from './utils/actions';
55
import { proxyCtx } from './utils/proxy';
66
import toast from './utils/toast';
77

8-
const accessToken = '1b7fca3bd7594a89b0f5e2a0250c1147';
8+
const accessToken = '7e4d9d17f87875e731d536d13635a700ddf52b12';
99
const user = {
1010
id: 8005956,
1111
avatar: 'https://coding-net-production-static-ci.codehub.cn/WM-TEXT-AVATAR-lvVeBfbGLtCPdcsAOPod.jpg',

src/init.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import DepotTreeDataProvider from './trees/depot';
33
import MRTreeDataProvider from './trees/mr';
44

55
import toast from './utils/toast';
6-
import { getMRUrl } from './utils/repo';
76
import ACTIONS, { dispatch } from './utils/actions';
87
import { IDepot, IMRItem } from './typings/common';
98

109
const { registerCommand } = hx.commands;
1110

1211
export function registerCommands(context: IContext) {
13-
const { codingServer } = context;
12+
const { codingServer, webviewProvider } = context;
1413

1514
context.subscriptions.push(
1615
registerCommand('codingPlugin.helloWorld', () => {
@@ -20,7 +19,10 @@ export function registerCommands(context: IContext) {
2019

2120
context.subscriptions.push(
2221
registerCommand('codingPlugin.mrTreeItemClick', function ([team, mrItem]: [string, IMRItem]) {
23-
hx.env.openExternal(getMRUrl(team, mrItem));
22+
webviewProvider.update({
23+
team,
24+
...mrItem,
25+
});
2426
}),
2527
);
2628

@@ -40,8 +42,8 @@ export function registerCommands(context: IContext) {
4042
prompt: '请输入仓库名',
4143
});
4244
const team = codingServer.session?.user?.team;
43-
const result = await codingServer.createDepot(team, depot, depot);
44-
// TODO: 拉取代码,更新workspace
45+
await codingServer.createDepot(team, depot, depot);
46+
toast.info('仓库创建成功');
4547
}),
4648
);
4749
}

src/services/codingServer.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ export default class CodingServer {
2424
return this._session;
2525
}
2626

27-
get repo() {
28-
return this._repo;
29-
}
27+
getHeaders = (token?: string) => ({
28+
Authorization: `token ${token || this._session.accessToken}`,
29+
});
3030

3131
static async getRepoParams() {
3232
const folders = await hx.workspace.getWorkspaceFolders();
@@ -49,9 +49,7 @@ export default class CodingServer {
4949
const result = await axios({
5050
method: 'get',
5151
url: `https://${team}.coding.net/api/current_user`,
52-
params: {
53-
access_token: token,
54-
},
52+
headers: this.getHeaders(),
5553
});
5654

5755
return result?.data;
@@ -66,13 +64,13 @@ export default class CodingServer {
6664
const result = await axios({
6765
method: 'get',
6866
url,
67+
headers: this.getHeaders(),
6968
params: {
7069
status: `open`,
7170
sort: `action_at`,
7271
page: 1,
7372
PageSize: 100,
7473
sortDirection: `DESC`,
75-
access_token: this._session.accessToken,
7674
},
7775
});
7876
return result?.data?.list || [];
@@ -87,9 +85,7 @@ export default class CodingServer {
8785
const result = await axios({
8886
method: 'get',
8987
url: `https://${team}.coding.net/api/user/${team}/project/${project}/repos`,
90-
params: {
91-
access_token: this._session.accessToken,
92-
},
88+
headers: this.getHeaders(),
9389
});
9490

9591
return result?.data?.depots || [];
@@ -102,7 +98,8 @@ export default class CodingServer {
10298
try {
10399
const result = await axios({
104100
method: 'post',
105-
url: `https://${team}.coding.net/api/team/${team}/template-project?access_token=${this._session.accessToken}`,
101+
url: `https://${team}.coding.net/api/team/${team}/template-project`,
102+
headers: this.getHeaders(),
106103
data: {
107104
name: project,
108105
displayName: project,
@@ -123,9 +120,10 @@ export default class CodingServer {
123120

124121
const result = await axios({
125122
method: 'post',
126-
url: `https://${team}.coding.net/api/user/${team}/project/${project}/depot?access_token=${this._session.accessToken}`,
123+
url: `https://${team}.coding.net/api/user/${team}/project/${project}/depot`,
127124
headers: {
128125
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
126+
...this.getHeaders(),
129127
},
130128
data: qs.stringify({
131129
name: depot,

src/webview.ts

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import hx from 'hbuilderx';
2-
import fs from 'fs';
32
import path from 'path';
43

4+
interface IMessage {
5+
command: string;
6+
text: string;
7+
}
8+
59
export default class WebviewProvider {
610
panel: IWebviewPanel;
711

@@ -11,8 +15,14 @@ export default class WebviewProvider {
1115
}
1216

1317
listen() {
14-
this.panel.webView.onDidReceiveMessage((message: any) => {
18+
this.panel.webView.onDidReceiveMessage((message: IMessage) => {
1519
console.log('webview receive message => ', message);
20+
const { command, text } = message;
21+
if (command === 'webview.mrDetail') {
22+
hx.env.openExternal(text);
23+
} else {
24+
hx.commands.executeCommand(command);
25+
}
1626
});
1727
}
1828

@@ -24,35 +34,17 @@ export default class WebviewProvider {
2434
return webviewPanel;
2535
}
2636

27-
update(itemId: string) {
37+
update(data: any) {
2838
const webview = this.panel.webView;
2939
const fileInfo = hx.Uri.file(path.resolve(__dirname, '../out/webviews/main.js'));
3040

3141
webview.html = `
3242
<body>
33-
<div style="max-width:200px;">
43+
<div>
3444
<div id='root'></div>
35-
<button onclick="test()">测试</button>
36-
<div>${itemId}</div>
3745
</div>
3846
<script>
39-
window.__TEXT__ = '${itemId}'
40-
function test() {
41-
alert('abc')
42-
43-
window.fetch("https://api.github.com/search/repositories?q=react", {
44-
"method": "GET",
45-
"mode": "cors",
46-
"credentials": "include"
47-
}).then((res) => {
48-
res.json().then(data => alert(JSON.stringify(data.items[0])))
49-
})
50-
}
51-
</script>
52-
<script>
53-
window.addEventListener("message", (msg) => {
54-
console.log(msg);
55-
});
47+
window.__CODING__ = '${JSON.stringify(data)}'
5648
</script>
5749
<script src='${fileInfo}'></script>
5850
</body>

webpack.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ module.exports = {
2727
},
2828
{
2929
loader: 'css-loader',
30+
options: {
31+
modules: {
32+
localIdentName: '[path][name]__[local]--[hash:base64:5]',
33+
},
34+
},
3035
},
3136
],
3237
},

webviews/App.tsx

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React from 'react';
2+
import cn from 'classnames';
3+
import style from './style.css';
24

35
const App = () => {
4-
const [msg, setMsg] = useState();
6+
const data = JSON.parse(window.__CODING__);
7+
const { team, title, srcBranch, desBranch, author, path } = data;
8+
const url = `https://${team}.coding.net${path}`;
59

6-
useEffect(() => {
7-
window.addEventListener('message', (msg: any) => {
8-
setMsg(msg);
10+
const viewOnWeb = () => {
11+
window.hbuilderx.postMessage({
12+
command: 'webview.mrDetail',
13+
text: url
914
});
10-
}, []);
11-
12-
const handleClick = () => {
13-
alert((window as any).__TEXT__);
1415
};
1516

1617
return (
17-
<div>
18-
app
19-
<button onClick={handleClick}>哈哈哈</button>
20-
{msg}
18+
<div className={style.root}>
19+
<a onClick={viewOnWeb}>前往 web 端查看</a>
20+
21+
<div className={style.title}>
22+
{title}
23+
</div>
24+
<div>{`将分支 ${srcBranch} 合并到分支 ${desBranch}`}</div>
25+
<div>创建人:{author.name}</div>
26+
27+
<div className={style.btnGroup}>
28+
<div className={cn(style.btn, style.btnPrimary)}>合并</div>
29+
<div className={cn(style.btn, style.btnPrimary)}>允许合并</div>
30+
<div className={style.btn}>关闭</div>
31+
</div>
2132
</div>
2233
);
2334
};

webviews/style.css

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
html, body {
2+
margin: 0;
3+
padding: 0;
4+
font-family: "PingFang SC", "Helvetica Neue", "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei", 微软雅黑, sans-serif;
5+
}
6+
7+
a {
8+
cursor: pointer;
9+
color: #06f;
10+
}
11+
12+
a:hover {
13+
text-decoration: underline;
14+
}
15+
16+
.root {
17+
padding: 20px;
18+
font-size: 14px;
19+
}
20+
21+
.title {
22+
margin-top: 20px;
23+
font-size: 18px;
24+
font-weight: 600;
25+
}
26+
27+
.btnGroup {
28+
display: flex;
29+
align-items: center;
30+
margin-top: 20px;
31+
}
32+
33+
.btn {
34+
margin-right: 10px;
35+
padding: 3px 5px;
36+
border-radius: 3px;
37+
border: 1px solid #ccc;
38+
cursor: pointer;
39+
}
40+
41+
.btn:hover {
42+
opacity: 0.8;
43+
}
44+
45+
.btnPrimary {
46+
border: none;
47+
background-color: #06f;
48+
color: #fff;
49+
}

webviews/typings/global.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
interface Window {
2+
hbuilderx: any;
3+
__CODING__: string;
4+
}
5+
6+
declare module '*.css' {
7+
const content: any;
8+
export default content;
9+
}

yarn.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@
6060
"@nodelib/fs.scandir" "2.1.3"
6161
fastq "^1.6.0"
6262

63+
"@types/classnames@^2.2.11":
64+
version "2.2.11"
65+
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.11.tgz#2521cc86f69d15c5b90664e4829d84566052c1cf"
66+
integrity sha512-2koNhpWm3DgWRp5tpkiJ8JGc1xTn2q0l+jUNUE7oMKXUf5NpI9AIdC4kbjGNFBdHtcxBD18LAksoudAVhFKCjw==
67+
6368
"@types/eslint-scope@^3.7.0":
6469
version "3.7.0"
6570
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86"
@@ -559,6 +564,11 @@ ci-info@^2.0.0:
559564
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
560565
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
561566

567+
classnames@^2.2.6:
568+
version "2.2.6"
569+
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
570+
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
571+
562572
clean-git-ref@^2.0.1:
563573
version "2.0.1"
564574
resolved "https://registry.yarnpkg.com/clean-git-ref/-/clean-git-ref-2.0.1.tgz#dcc0ca093b90e527e67adb5a5e55b1af6816dcd9"

0 commit comments

Comments
 (0)