This is an automated email from the ASF dual-hosted git repository.
jialiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ambari-website.git
The following commit(s) were added to refs/heads/main by this push:
new 48b0f79 AMBARI-26497: Website: Team page avatar can not fetch #37
48b0f79 is described below
commit 48b0f799c42ee780bb934bda064b44cd21268d80
Author: zrain <[email protected]>
AuthorDate: Tue May 13 08:46:15 2025 +0800
AMBARI-26497: Website: Team page avatar can not fetch #37
---
.github/workflows/website.yml | 6 +-
package.json | 3 +-
scripts/updateTeamAvatar.js | 92 ++++++++++++++++++++++
src/pages/team/index.js | 94 +++++++++++------------
src/pages/team/index.less | 174 +++++++++++++++++++++++-------------------
src/pages/team/languages.json | 10 +--
6 files changed, 244 insertions(+), 135 deletions(-)
diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml
index e290332..8b0677a 100644
--- a/.github/workflows/website.yml
+++ b/.github/workflows/website.yml
@@ -2,7 +2,7 @@ name: Build and Deploy
permissions:
contents: write
-
+
on:
pull_request:
branches:
@@ -25,7 +25,7 @@ jobs:
node-version: 18.12.1
- name: Build Main Document
- run: yarn && yarn build
+ run: yarn && yarn update-avatar && yarn build && git checkout .
- name: Deploy
if: ${{ github.event_name == 'push' }}
@@ -54,4 +54,4 @@ jobs:
git commit -m '.asf.yaml'
git push origin asf-site
env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/package.json b/package.json
index 03727c6..ad526c4 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,8 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
- "typecheck": "tsc"
+ "typecheck": "tsc",
+ "update-avatar": "node scripts/updateTeamAvatar.js"
},
"config": {
"commitizen": {
diff --git a/scripts/updateTeamAvatar.js b/scripts/updateTeamAvatar.js
new file mode 100644
index 0000000..0ac6de7
--- /dev/null
+++ b/scripts/updateTeamAvatar.js
@@ -0,0 +1,92 @@
+const fs = require('fs');
+const path = require('path');
+const https = require('https');
+const { promisify } = require('util');
+
+const readFile = promisify(fs.readFile);
+const writeFile = promisify(fs.writeFile);
+const mkdir = promisify(fs.mkdir);
+
+const AVATAR_JSON_PATH = path.resolve(__dirname,
'../src/pages/team/languages.json');
+const OUTPUT_DIR = './static/img/team';
+const RELATIVE_PATH_PREFIX = '/img/team/';
+
+async function ensureDirectoryExists(dirPath) {
+ try {
+ await mkdir(dirPath, { recursive: true });
+ } catch (err) {
+ if (err.code !== 'EEXIST') throw err;
+ }
+}
+
+async function downloadImage(url, filePath) {
+ return new Promise((resolve, reject) => {
+ const file = fs.createWriteStream(filePath);
+
+ https.get(url, (response) => {
+ if (response.statusCode !== 200) {
+ reject(new Error(`Request error, status code:
${response.statusCode}`));
+ return;
+ }
+
+ const contentType = response.headers['content-type'];
+ if (!contentType || !contentType.startsWith('image/')) {
+ reject(new Error(`Invalid content type: ${contentType}`));
+ return;
+ }
+
+ response.pipe(file);
+
+ file.on('finish', () => {
+ file.close(resolve);
+ });
+ }).on('error', (err) => {
+ fs.unlink(filePath, () => { });
+ reject(err);
+ });
+ });
+}
+
+
+async function processAvatars() {
+ try {
+ await ensureDirectoryExists(OUTPUT_DIR);
+ const data = await readFile(AVATAR_JSON_PATH, 'utf8');
+ const jsonData = JSON.parse(data);
+
+ if (jsonData.en && jsonData.en.pmc) await
avatarSectionProcess(jsonData.en.pmc)
+ if (jsonData.en && jsonData.en.committer) await
avatarSectionProcess(jsonData.en.committer)
+
+ await writeFile(AVATAR_JSON_PATH, JSON.stringify(jsonData, null, 2));
+ console.log('JSON update!');
+ } catch (err) {
+ console.error('Error cause:', err);
+ }
+}
+
+async function avatarSectionProcess(avatarList) {
+ if (!Array.isArray(avatarList)) {
+ throw new Error('Invalid json');
+ }
+
+ for (let i = 0; i < avatarList.length; i++) {
+ const item = avatarList[i];
+ if (!item.avatarUrl) continue;
+
+ try {
+ const url = item.avatarUrl;
+ const ext = path.extname(url) || '.png';
+ const filename = `avatar_${Date.now()}_${i}${ext}`;
+ const outputPath = path.join(OUTPUT_DIR, filename);
+
+ await downloadImage(url, outputPath);
+
+ item.avatarUrl = RELATIVE_PATH_PREFIX + filename;
+ console.log(`Download success: ${url} -> ${item.avatarUrl}`);
+ } catch (err) {
+ console.error(`Download failed ${item.avatarUrl}: ${err.message}`);
+ }
+ }
+}
+
+processAvatars();
diff --git a/src/pages/team/index.js b/src/pages/team/index.js
index b19e483..1965e32 100644
--- a/src/pages/team/index.js
+++ b/src/pages/team/index.js
@@ -5,53 +5,53 @@ import Layout from '@theme/Layout';
import './index.less';
export default function () {
- const isBrowser = useIsBrowser();
- const language = isBrowser && location.pathname.indexOf('/zh-CN/') === 0 ?
'zh-CN' : 'en';
- const dataSource = config?.[language];
+ const isBrowser = useIsBrowser();
+ const language = isBrowser && location.pathname.indexOf('/zh-CN/') === 0 ?
'zh-CN' : 'en';
+ const dataSource = config?.[language];
- return (
- <Layout title="team" description="team page">
- <div className="container">
- <div className="block team_page">
- <h3 className="team_title">Ambari Team</h3>
- <p className="team_desc" dangerouslySetInnerHTML={ { __html:
dataSource.info.desc } }/>
- <h3 className="team_title">PMC</h3>
- <p className="team_desc">{dataSource.info.tip}</p>
- <ul className="character_list">
- {
- dataSource.pmc.map((item, i) => (
- <a href={'https://github.com/' + item.githubId}
key={i} target="_blank">
- <li className="character_item text_center"
style={{'listStyle': 'none'}}>
- <img className="character_avatar"
src={item.avatarUrl} alt={item.name}/>
- <div className="character_desc">
- <h3
className="character_name">{item.name}</h3>
- <h3 className="character_id"><span
className="githubId">githubId:</span>{item.githubId}</h3>
- </div>
- </li>
- </a>
- ))
- }
- </ul>
+ return (
+ <Layout title="team" description="team page">
+ <div className="container">
+ <div className="block team_page">
+ <h3 className="team_title">Ambari Team</h3>
+ <p className="team_desc" dangerouslySetInnerHTML={{ __html:
dataSource.info.desc }} />
+ <h3 className="team_title">PMC</h3>
+ <p className="team_desc">{dataSource.info.tip}</p>
+ <ul className="character_list">
+ {
+ dataSource.pmc.map((item, i) => (
+ <li key={i} className="character_item text_center" style={{
'listStyle': 'none' }}>
+ <a href={'https://github.com/' + item.githubId}
target="_blank">
+ <img className="character_avatar" src={item.avatarUrl}
alt={item.name} />
+ <div className="character_desc">
+ <h3 className="character_name">{item.name}</h3>
+ <h3 className="character_id"><span
class="mdi--github"></span>{item.githubId}</h3>
+ </div>
+ </a>
+ </li>
+ ))
+ }
+ </ul>
- <h3 className="team_title">Committers</h3>
- <p className="team_desc">{dataSource.info.tip}</p>
- <ul className="character_list">
- {
- dataSource.committer.map((item, i) => (
- <a href={'https://github.com/' + item.githubId} key={i}
target="_blank">
- <li className="character_item text_center"
style={{'listStyle': 'none'}}>
- <img className="character_avatar"
src={item.avatarUrl} alt={item.name}/>
- <div className="character_desc">
- <h3 className="character_name">{item.name}</h3>
- <h3 className="character_id"><span
className="githubId">githubId:</span>{item.githubId}</h3>
- </div>
- </li>
- </a>
- ))
- }
- </ul>
- </div>
- </div>
- </Layout>
- );
+ <h3 className="team_title">Committers</h3>
+ <p className="team_desc">{dataSource.info.tip}</p>
+ <ul className="character_list">
+ {
+ dataSource.committer.map((item, i) => (
+ <li key={i} className="character_item text_center" style={{
'listStyle': 'none' }}>
+ <a href={'https://github.com/' + item.githubId}
target="_blank">
+ <img className="character_avatar" src={item.avatarUrl}
alt={item.name} />
+ <div className="character_desc">
+ <h3 className="character_name">{item.name}</h3>
+ <h3 className="character_id"><span
class="mdi--github"></span>{item.githubId}</h3>
+ </div>
+ </a>
+ </li>
+ ))
+ }
+ </ul>
+ </div>
+ </div>
+ </Layout>
+ );
}
diff --git a/src/pages/team/index.less b/src/pages/team/index.less
index 26bf048..816b1f8 100644
--- a/src/pages/team/index.less
+++ b/src/pages/team/index.less
@@ -1,91 +1,107 @@
- @active-color: #3B84F6;//#2863f9
+ @active-color: #3B84F6; //#2863f9
@enhance-color: #0F1222;
-.team_page {
+ .mdi--github {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 2A10 10 0 0 0 2 12c0 4.42
2.87 8.17 6.84
9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1
.07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07
2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2
1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33
2.5-.33s1.71.11 2.5.33c1 [...]
+ background-color: currentColor;
+ -webkit-mask-image: var(--svg);
+ mask-image: var(--svg);
+ -webkit-mask-repeat: no-repeat;
+ mask-repeat: no-repeat;
+ -webkit-mask-size: 100% 100%;
+ mask-size: 100% 100%;
+ }
- a {
- text-decoration: none;
- }
+ .team_page {
- margin-top: 50px;
+ a {
+ text-decoration: none;
+ }
- .team_title {
- font-size: 25px;
- font-weight: 500;
- color: #0F1222;
- margin-top: 50px;
- }
+ margin-top: 50px;
- .team_desc {
- margin-bottom: 40px;
- }
+ .team_title {
+ font-size: 25px;
+ font-weight: 500;
+ color: #0F1222;
+ }
- .character_list {
- display: grid;
- grid-template-columns: repeat(6, 1fr);
- grid-column-gap: 15px;
- grid-row-gap: 15px;
- padding: 20px 0 0px;
+ .team_desc {
+ margin-bottom: 24px;
+ }
- .character_item {
- border: 1px solid rgba(205, 221, 250, 0.8);
- background-color: rgba(205, 222, 234, 0.2);
- box-shadow: 0 3px 5px rgb(47 85 212 / 8%);
- border-radius: 2px;
- min-width: 0;
- padding: 0 10px 5px;
- margin: 40px 0 42px 0;
+ .character_list {
+ padding: 0;
+ margin: 0;
+ margin-bottom: 28px;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, 200px);
+ grid-row-gap: 20px;
+ grid-column-gap: 20px;
- .character_avatar {
- width: 120px;
- height: 120px;
- background: #D8D8D8;
- display: inline-block;
- border-radius: 50%;
- border: 5px solid rgba(255,255,255,.08);
- margin: -4rem auto -.5rem;
- }
+ .character_item {
+ margin-top: 30px;
+ position: relative;
+ min-width: 200px;
+ border-radius: 4px;
+ box-shadow: rgba(0, 0, 0, 0.02) 0px 1px 3px 0px, rgba(27, 31, 35, 0.15)
0px 0px 0px 1px;
+ flex-shrink: 0;
- .character_name {
- color: @enhance-color;
- line-height: 36px;
- font-size: 15px;
- white-space: nowrap;
- font-weight: 400;
- overflow: hidden;
- background-color: #fff;
- margin-top: 20px;
- border-radius: 18px;
- text-overflow: ellipsis;
- border: 1px solid rgba(205, 221, 250, 0.6);
- box-shadow: 0 3px 5px rgb(47 85 212 / 5%);
- }
+ h3 {
+ margin-bottom: 0;
+ }
- .character_id {
- color: #333;
- line-height: 36px;
- font-size: 12px;
- white-space: nowrap;
- font-weight: 400;
- overflow: hidden;
- border-radius: 18px;
- background-color: #fff;
- text-overflow: ellipsis;
- border: 1px solid rgba(205, 221, 250, 0.6);
- box-shadow: 0 3px 5px rgb(47 85 212 / 5%);
- .githubId {
- color: #666;
- margin-right: 2px;
- }
- }
+ .character_avatar {
+ position: absolute;
+ left: 8px;
+ top: -30px;
+ width: 60px;
+ height: 60px;
+ background: #D8D8D8;
+ display: inline-block;
+ border-radius: 50%;
+ box-shadow: rgba(0, 0, 0, 0.02) 0px 1px 3px 0px, rgba(27, 31, 35,
0.15) 0px 0px 0px 1px;
+ }
- .character_link {
- color: rgba(15, 18, 34, 0.65);
- font-weight: 400;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- }
- }
-}
\ No newline at end of file
+ .character_name {
+ color: @enhance-color;
+ padding: 0 8px;
+ padding-top: 40px;
+ font-size: 15px;
+ white-space: nowrap;
+ font-weight: 400;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-bottom: 8px;
+ }
+
+ .character_id {
+ padding: 0 8px;
+ padding-bottom: 13px;
+ font-size: 12px;
+ color: #666;
+ font-weight: 400;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ .mdi--github {
+ margin-right: 4px;
+ color: #333;
+ vertical-align: -6px;
+ }
+ }
+
+ .character_link {
+ color: rgba(15, 18, 34, 0.65);
+ font-weight: 400;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+ }
+ }
diff --git a/src/pages/team/languages.json b/src/pages/team/languages.json
index 1c0eef9..89092e6 100644
--- a/src/pages/team/languages.json
+++ b/src/pages/team/languages.json
@@ -148,9 +148,7 @@
"gitUrl": "https://github.com/virajjasani",
"githubId": "virajjasani",
"name": "Viraj Jasani"
- }
- ],
- "committer": [
+ },
{
"apacheId": "jialiang",
"avatarUrl": "https://avatars.githubusercontent.com/u/18082602?v=4",
@@ -158,7 +156,9 @@
"gitUrl": "https://github.com/Jialiangc",
"githubId": "Jialiangc",
"name": "Jialiang Cai"
- },
+ }
+ ],
+ "committer": [
{
"apacheId": "zhangyu",
"avatarUrl": "https://avatars.githubusercontent.com/u/16508606?v=4",
@@ -185,4 +185,4 @@
}
]
}
-}
\ No newline at end of file
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]