diff --git a/website/package.json b/website/package.json index 1ab7e698b318..22f1dd202e89 100644 --- a/website/package.json +++ b/website/package.json @@ -31,6 +31,7 @@ "docusaurus-plugin-openapi-docs": "2.0.0-beta.3", "docusaurus-plugin-remote-content": "^3.1.0", "docusaurus-theme-openapi-docs": "2.0.0-beta.2", + "git-url-parse": "^14.0.0", "plugin-image-zoom": "flexanalytics/plugin-image-zoom", "prism-svelte": "^0.5.0", "react": "18.2.0", diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 26fb467341e0..407e8d03043e 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -17,6 +17,7 @@ --navbar-link-color: #122d33; --unleash-font-size-smaller: 90%; + --ifm-footer-logo-max-width: 250px; /* navbar is independent of the theme in general */ --ifm-navbar-background-color: var(--unleash-color-green); diff --git a/website/src/theme/DocItem/Footer/GitHubContributors.jsx b/website/src/theme/DocItem/Footer/GitHubContributors.jsx new file mode 100644 index 000000000000..fd3ff533227e --- /dev/null +++ b/website/src/theme/DocItem/Footer/GitHubContributors.jsx @@ -0,0 +1,92 @@ +// biome-ignore lint/correctness/noUnusedImports: Needs this for React to work +import React, { useState, useEffect } from 'react'; +import { getContributors } from './contributors'; +import styles from './contributors.module.scss'; + +const unleashTeam = new Map([ + ['alvinometric', 'developer advocate, Unleash'], + ['andreas-unleash', 'developer, Unleash'], + ['chriswk', 'principal developer, Unleash'], + ['daveleek', 'developer, Unleash'], + ['FredrikOseberg', 'principal developer, Unleash'], + ['gardleopard', 'platform lead, Unleash'], + ['gastonfournier', 'senior developer, Unleash'], + ['ivarconr', 'co-founder, Unleash'], + ['kwasniew', 'senior developer, Unleash'], + ['nnennandukwe', 'developer advocate, Unleash'], + ['nunogois', 'senior developer, Unleash'], + ['sighphyre', 'senior developer, Unleash'], + ['sjaanus', 'senior developer, Unleash'], + ['thomasheartman', 'developer, Unleash'], + ['Tymek', 'developer, Unleash'], +]); + +const GitHubContributors = ({ owner, repo, filePath }) => { + const [contributors, setContributors] = useState([]); + const url = `https://api.github.com/repos/${owner}/${repo}/commits?path=${filePath}`; + + useEffect(() => { + const fetchFileContributors = () => { + fetch(url) + .then((response) => response.json()) + .then((commits) => { + const contributors = getContributors(commits); + + contributors.sort((a, b) => { + if (unleashTeam.has(a.login)) { + return -1; + } + return 1; + }); + setContributors(contributors); + }) + .catch((error) => { + console.error(error); + setContributors([]); + }); + }; + + fetchFileContributors(); + }, []); + + if (!contributors.length) { + return null; + } + + return ( +
+

Contributors

+ + +
+ ); +}; + +export default GitHubContributors; diff --git a/website/src/theme/DocItem/Footer/contributors.js b/website/src/theme/DocItem/Footer/contributors.js new file mode 100644 index 000000000000..9e501be5f13b --- /dev/null +++ b/website/src/theme/DocItem/Footer/contributors.js @@ -0,0 +1,23 @@ +export const getContributors = (commits) => { + // filter out commits that don't have an author + const commitsWithAuthors = commits.filter((commit) => !!commit.author); + + // use a Set to deduplicate the list of contributors + const contributorSet = new Set(); + for (const commit of commitsWithAuthors) { + contributorSet.add(JSON.stringify(commit.author)); + } + + const contributors = Array.from(contributorSet).map((str) => { + const contributor = JSON.parse(str); + const { login, html_url, avatar_url } = contributor; + return { login, html_url, avatar_url }; + }); + + // sort alphabetically + contributors.sort((a, b) => { + return a.login.localeCompare(b.login); + }); + + return contributors; +}; diff --git a/website/src/theme/DocItem/Footer/contributors.module.scss b/website/src/theme/DocItem/Footer/contributors.module.scss new file mode 100644 index 000000000000..da4353128af4 --- /dev/null +++ b/website/src/theme/DocItem/Footer/contributors.module.scss @@ -0,0 +1,56 @@ +.contributors { + margin-block: var(--ifm-spacing-vertical); +} + +.wrapper { + display: flex; + flex-wrap: wrap; + gap: 20px; + margin: 0; + padding: 0; + + li{ + list-style: none; + } +} + +.unleash{ + position: relative; + display: block; +} + +.unleash:before{ + display: block; + position: absolute; + z-index: 2; + content: ''; + top: -5px; + right: -5px; + width: 30px; + height: 30px; + background-image: url(/img/logo.svg); +} + +.contributor { + margin-top: 10px; + + img{ + border-radius: 100%; + margin:0; + padding: 0; + border: 2px solid var(--unleash-color-gray); + transition: border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default), + scale var(--ifm-transition-fast) var(--ifm-transition-timing-default); + } +} + +.contributor img:hover{ + border-color: var(--ifm-pagination-nav-color-hover); + scale: 1.1; +} + +@media (max-width: 600px) { + .wrapper { + display: block; + } +} diff --git a/website/src/theme/DocItem/Footer/contributors.test.js b/website/src/theme/DocItem/Footer/contributors.test.js new file mode 100644 index 000000000000..1c96cee9bdca --- /dev/null +++ b/website/src/theme/DocItem/Footer/contributors.test.js @@ -0,0 +1,99 @@ +const commits = [ + { + sha: '2754c26f2e022b623e46e08fc1108b350710ef91', + node_id: + 'C_kwDOAXdJ9doAKDI3NTRjMjZmMmUwMjJiNjIzZTQ2ZTA4ZmMxMTA4YjM1MDcxMGVmOTE', + url: 'https://api.github.com/repos/Unleash/unleash/commits/2754c26f2e022b623e46e08fc1108b350710ef91', + html_url: + 'https://github.com/Unleash/unleash/commit/2754c26f2e022b623e46e08fc1108b350710ef91', + comments_url: + 'https://api.github.com/repos/Unleash/unleash/commits/2754c26f2e022b623e46e08fc1108b350710ef91/comments', + author: { + login: 'markunl', + id: 128738155, + node_id: 'U_kgDOB6xjaw', + avatar_url: 'https://avatars.githubusercontent.com/u/128738155?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/markunl', + html_url: 'https://github.com/markunl', + type: 'User', + site_admin: false, + }, + }, + { + sha: 'd5fbd0b743cc99791d34864c70f78985cc83b2d8', + node_id: + 'C_kwDOAXdJ9doAKGQ1ZmJkMGI3NDNjYzk5NzkxZDM0ODY0YzcwZjc4OTg1Y2M4M2IyZDg', + url: 'https://api.github.com/repos/Unleash/unleash/commits/d5fbd0b743cc99791d34864c70f78985cc83b2d8', + html_url: + 'https://github.com/Unleash/unleash/commit/d5fbd0b743cc99791d34864c70f78985cc83b2d8', + comments_url: + 'https://api.github.com/repos/Unleash/unleash/commits/d5fbd0b743cc99791d34864c70f78985cc83b2d8/comments', + author: { + login: 'thomasheartman', + id: 17786332, + node_id: 'MDQ6VXNlcjE3Nzg2MzMy', + avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/thomasheartman', + html_url: 'https://github.com/thomasheartman', + type: 'User', + site_admin: false, + }, + }, + { + sha: 'ebcab898e7610082d3ada81ab0b729ba1f17655d', + node_id: + 'C_kwDOAXdJ9doAKGViY2FiODk4ZTc2MTAwODJkM2FkYTgxYWIwYjcyOWJhMWYxNzY1NWQ', + url: 'https://api.github.com/repos/Unleash/unleash/commits/ebcab898e7610082d3ada81ab0b729ba1f17655d', + html_url: + 'https://github.com/Unleash/unleash/commit/ebcab898e7610082d3ada81ab0b729ba1f17655d', + comments_url: + 'https://api.github.com/repos/Unleash/unleash/commits/ebcab898e7610082d3ada81ab0b729ba1f17655d/comments', + author: { + login: 'thomasheartman', + id: 17786332, + node_id: 'MDQ6VXNlcjE3Nzg2MzMy', + avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/thomasheartman', + html_url: 'https://github.com/thomasheartman', + type: 'User', + site_admin: false, + }, + }, + { + sha: 'ead86ed62191777895d5a5f1a7c58f16a87ebde7', + node_id: + 'C_kwDOAXdJ9doAKGVhZDg2ZWQ2MjE5MTc3Nzg5NWQ1YTVmMWE3YzU4ZjE2YTg3ZWJkZTc', + author: { + login: 'thomasheartman', + id: 17786332, + node_id: 'MDQ6VXNlcjE3Nzg2MzMy', + avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/thomasheartman', + html_url: 'https://github.com/thomasheartman', + type: 'User', + site_admin: false, + }, + }, +]; + +const expectedContributors = [ + { + login: 'thomasheartman', + html_url: 'https://github.com/thomasheartman', + avatar_url: 'https://avatars.githubusercontent.com/u/17786332?v=4', + }, + { + login: 'markunl', + html_url: 'https://github.com/markunl', + avatar_url: 'https://avatars.githubusercontent.com/u/128738155?v=4', + }, +]; + +test('getContributors should return the correct list of contributors', () => { + const contributors = getContributors(commits); + expect(contributors).toEqual(expectedContributors); +}); diff --git a/website/src/theme/DocItem/Footer/index.jsx b/website/src/theme/DocItem/Footer/index.jsx new file mode 100644 index 000000000000..eceb37171b48 --- /dev/null +++ b/website/src/theme/DocItem/Footer/index.jsx @@ -0,0 +1,25 @@ +// biome-ignore lint/correctness/noUnusedImports: Needs this for React to work +import React from 'react'; +import Footer from '@theme-original/DocItem/Footer'; +import { useDoc } from '@docusaurus/theme-common/internal'; +import GitHubContributors from './GitHubContributors'; +import GitUrlParse from 'git-url-parse'; + +export default function FooterWrapper(props) { + const { metadata } = useDoc(); + const file = metadata.editUrl; + + if (!file) { + return