Skip to content

Commit 48b0f79

Browse files
authored
AMBARI-26497: Website: Team page avatar can not fetch #37
1 parent a543d48 commit 48b0f79

File tree

6 files changed

+244
-135
lines changed

6 files changed

+244
-135
lines changed

.github/workflows/website.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Build and Deploy
22

33
permissions:
44
contents: write
5-
5+
66
on:
77
pull_request:
88
branches:
@@ -25,7 +25,7 @@ jobs:
2525
node-version: 18.12.1
2626

2727
- name: Build Main Document
28-
run: yarn && yarn build
28+
run: yarn && yarn update-avatar && yarn build && git checkout .
2929

3030
- name: Deploy
3131
if: ${{ github.event_name == 'push' }}
@@ -54,4 +54,4 @@ jobs:
5454
git commit -m '.asf.yaml'
5555
git push origin asf-site
5656
env:
57-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"serve": "docusaurus serve",
1414
"write-translations": "docusaurus write-translations",
1515
"write-heading-ids": "docusaurus write-heading-ids",
16-
"typecheck": "tsc"
16+
"typecheck": "tsc",
17+
"update-avatar": "node scripts/updateTeamAvatar.js"
1718
},
1819
"config": {
1920
"commitizen": {

scripts/updateTeamAvatar.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const https = require('https');
4+
const { promisify } = require('util');
5+
6+
const readFile = promisify(fs.readFile);
7+
const writeFile = promisify(fs.writeFile);
8+
const mkdir = promisify(fs.mkdir);
9+
10+
const AVATAR_JSON_PATH = path.resolve(__dirname, '../src/pages/team/languages.json');
11+
const OUTPUT_DIR = './static/img/team';
12+
const RELATIVE_PATH_PREFIX = '/img/team/';
13+
14+
async function ensureDirectoryExists(dirPath) {
15+
try {
16+
await mkdir(dirPath, { recursive: true });
17+
} catch (err) {
18+
if (err.code !== 'EEXIST') throw err;
19+
}
20+
}
21+
22+
async function downloadImage(url, filePath) {
23+
return new Promise((resolve, reject) => {
24+
const file = fs.createWriteStream(filePath);
25+
26+
https.get(url, (response) => {
27+
if (response.statusCode !== 200) {
28+
reject(new Error(`Request error, status code: ${response.statusCode}`));
29+
return;
30+
}
31+
32+
const contentType = response.headers['content-type'];
33+
if (!contentType || !contentType.startsWith('image/')) {
34+
reject(new Error(`Invalid content type: ${contentType}`));
35+
return;
36+
}
37+
38+
response.pipe(file);
39+
40+
file.on('finish', () => {
41+
file.close(resolve);
42+
});
43+
}).on('error', (err) => {
44+
fs.unlink(filePath, () => { });
45+
reject(err);
46+
});
47+
});
48+
}
49+
50+
51+
async function processAvatars() {
52+
try {
53+
await ensureDirectoryExists(OUTPUT_DIR);
54+
const data = await readFile(AVATAR_JSON_PATH, 'utf8');
55+
const jsonData = JSON.parse(data);
56+
57+
if (jsonData.en && jsonData.en.pmc) await avatarSectionProcess(jsonData.en.pmc)
58+
if (jsonData.en && jsonData.en.committer) await avatarSectionProcess(jsonData.en.committer)
59+
60+
await writeFile(AVATAR_JSON_PATH, JSON.stringify(jsonData, null, 2));
61+
console.log('JSON update!');
62+
} catch (err) {
63+
console.error('Error cause:', err);
64+
}
65+
}
66+
67+
async function avatarSectionProcess(avatarList) {
68+
if (!Array.isArray(avatarList)) {
69+
throw new Error('Invalid json');
70+
}
71+
72+
for (let i = 0; i < avatarList.length; i++) {
73+
const item = avatarList[i];
74+
if (!item.avatarUrl) continue;
75+
76+
try {
77+
const url = item.avatarUrl;
78+
const ext = path.extname(url) || '.png';
79+
const filename = `avatar_${Date.now()}_${i}${ext}`;
80+
const outputPath = path.join(OUTPUT_DIR, filename);
81+
82+
await downloadImage(url, outputPath);
83+
84+
item.avatarUrl = RELATIVE_PATH_PREFIX + filename;
85+
console.log(`Download success: ${url} -> ${item.avatarUrl}`);
86+
} catch (err) {
87+
console.error(`Download failed ${item.avatarUrl}: ${err.message}`);
88+
}
89+
}
90+
}
91+
92+
processAvatars();

src/pages/team/index.js

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,53 @@ import Layout from '@theme/Layout';
55
import './index.less';
66

77
export default function () {
8-
const isBrowser = useIsBrowser();
9-
const language = isBrowser && location.pathname.indexOf('/zh-CN/') === 0 ? 'zh-CN' : 'en';
10-
const dataSource = config?.[language];
8+
const isBrowser = useIsBrowser();
9+
const language = isBrowser && location.pathname.indexOf('/zh-CN/') === 0 ? 'zh-CN' : 'en';
10+
const dataSource = config?.[language];
1111

12-
return (
13-
<Layout title="team" description="team page">
14-
<div className="container">
15-
<div className="block team_page">
16-
<h3 className="team_title">Ambari Team</h3>
17-
<p className="team_desc" dangerouslySetInnerHTML={ { __html: dataSource.info.desc } }/>
18-
<h3 className="team_title">PMC</h3>
19-
<p className="team_desc">{dataSource.info.tip}</p>
20-
<ul className="character_list">
21-
{
22-
dataSource.pmc.map((item, i) => (
23-
<a href={'https://github.com/' + item.githubId} key={i} target="_blank">
24-
<li className="character_item text_center" style={{'listStyle': 'none'}}>
25-
<img className="character_avatar" src={item.avatarUrl} alt={item.name}/>
26-
<div className="character_desc">
27-
<h3 className="character_name">{item.name}</h3>
28-
<h3 className="character_id"><span className="githubId">githubId:</span>{item.githubId}</h3>
29-
</div>
30-
</li>
31-
</a>
32-
))
33-
}
34-
</ul>
12+
return (
13+
<Layout title="team" description="team page">
14+
<div className="container">
15+
<div className="block team_page">
16+
<h3 className="team_title">Ambari Team</h3>
17+
<p className="team_desc" dangerouslySetInnerHTML={{ __html: dataSource.info.desc }} />
18+
<h3 className="team_title">PMC</h3>
19+
<p className="team_desc">{dataSource.info.tip}</p>
20+
<ul className="character_list">
21+
{
22+
dataSource.pmc.map((item, i) => (
23+
<li key={i} className="character_item text_center" style={{ 'listStyle': 'none' }}>
24+
<a href={'https://github.com/' + item.githubId} target="_blank">
25+
<img className="character_avatar" src={item.avatarUrl} alt={item.name} />
26+
<div className="character_desc">
27+
<h3 className="character_name">{item.name}</h3>
28+
<h3 className="character_id"><span class="mdi--github"></span>{item.githubId}</h3>
29+
</div>
30+
</a>
31+
</li>
32+
))
33+
}
34+
</ul>
3535

36-
<h3 className="team_title">Committers</h3>
37-
<p className="team_desc">{dataSource.info.tip}</p>
38-
<ul className="character_list">
39-
{
40-
dataSource.committer.map((item, i) => (
41-
<a href={'https://github.com/' + item.githubId} key={i} target="_blank">
42-
<li className="character_item text_center" style={{'listStyle': 'none'}}>
43-
<img className="character_avatar" src={item.avatarUrl} alt={item.name}/>
44-
<div className="character_desc">
45-
<h3 className="character_name">{item.name}</h3>
46-
<h3 className="character_id"><span className="githubId">githubId:</span>{item.githubId}</h3>
47-
</div>
48-
</li>
49-
</a>
50-
))
51-
}
52-
</ul>
53-
</div>
54-
</div>
55-
</Layout>
56-
);
36+
<h3 className="team_title">Committers</h3>
37+
<p className="team_desc">{dataSource.info.tip}</p>
38+
<ul className="character_list">
39+
{
40+
dataSource.committer.map((item, i) => (
41+
<li key={i} className="character_item text_center" style={{ 'listStyle': 'none' }}>
42+
<a href={'https://github.com/' + item.githubId} target="_blank">
43+
<img className="character_avatar" src={item.avatarUrl} alt={item.name} />
44+
<div className="character_desc">
45+
<h3 className="character_name">{item.name}</h3>
46+
<h3 className="character_id"><span class="mdi--github"></span>{item.githubId}</h3>
47+
</div>
48+
</a>
49+
</li>
50+
))
51+
}
52+
</ul>
53+
</div>
54+
</div>
55+
</Layout>
56+
);
5757
}

0 commit comments

Comments
 (0)