diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index e2903329..8b0677a5 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 03727c6f..ad526c4d 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 00000000..0ac6de78 --- /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 b19e4835..1965e327 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 ( - -
-
-

Ambari Team

-

-

PMC

-

{dataSource.info.tip}

- + return ( + +
+
+

Ambari Team

+

+

PMC

+

{dataSource.info.tip}

+ -

Committers

-

{dataSource.info.tip}

- -
-
-
- ); +

Committers

+

{dataSource.info.tip}

+ +
+
+
+ ); } diff --git a/src/pages/team/index.less b/src/pages/team/index.less index 26bf048c..816b1f81 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.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2'/%3E%3C/svg%3E"); + 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 1c0eef9e..89092e68 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 +}