-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #283 from php-school/contributors
Add contributors list
- Loading branch information
Showing
8 changed files
with
168 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,4 +9,5 @@ CACHE.ENABLE=false | |
DISPLAY_ERRORS=true | ||
GITHUB_CLIENT_ID= | ||
GITHUB_CLIENT_SECRET= | ||
GITHUB_TOKEN= | ||
DEV_MODE=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<script setup> | ||
import { ChatBubbleLeftRightIcon } from "@heroicons/vue/24/solid"; | ||
import Modal from "../Online/ModalDialog.vue"; | ||
import { onMounted, ref } from "vue"; | ||
const { open } = defineProps({ | ||
open: Boolean, | ||
}); | ||
const emit = defineEmits(["close"]); | ||
const contributors = ref([]); | ||
onMounted(async () => { | ||
const response = await fetch("/api/contributors"); | ||
contributors.value = await response.json(); | ||
}); | ||
</script> | ||
|
||
<template> | ||
<Teleport to="body"> | ||
<Transition | ||
enter-active-class="transition-opacity duration-100 ease-in" | ||
leave-active-class="transition-opacity duration-200 ease-in" | ||
enter-from-class="opacity-0" | ||
enter-to-class="opacity-100" | ||
leave-from-class="opacity-100" | ||
leave-to-class="opacity-0" | ||
> | ||
<Modal :scroll-content="true" size="md" max-height="max-h-[calc(5/6*100%)]" v-if="open" @close="emit('close')"> | ||
<template #header> | ||
<div class="flex items-center"> | ||
<ChatBubbleLeftRightIcon class="mr-2 h-6 w-6 text-pink-500" /> | ||
<h3 class="mt-0 pt-0 font-mono text-base font-semibold text-white lg:text-xl">Contributors</h3> | ||
</div> | ||
</template> | ||
<template #body> | ||
<p class="mb-4 text-justify text-sm italic text-white">The PHP School project is made possible by the following contributors. Thank you for your hard work and dedication to the project!</p> | ||
<ul role="list" class="divide-y divide-gray-800"> | ||
<li v-for="contributor in contributors" :key="contributor.username" class="flex justify-between gap-x-6 py-2"> | ||
<div class="flex min-w-0 gap-x-3"> | ||
<img class="h-8 w-8 flex-none rounded-full bg-gray-800" :src="contributor.profilePic" alt="" /> | ||
<div class="min-w-0 flex-auto"> | ||
<a :href="contributor.profile" target="_blank" class="text-sm leading-6 text-white">{{ contributor.username }}</a> | ||
</div> | ||
</div> | ||
<div class="hidden shrink-0 sm:flex sm:flex-col sm:items-end"> | ||
<p class="mt-1 text-xs leading-5 text-pink-500"> | ||
<b>{{ contributor.contributions }}</b> | ||
Commit{{ contributor.contributions > 1 ? "s" : "" }} | ||
</p> | ||
</div> | ||
</li> | ||
</ul> | ||
</template> | ||
</Modal> | ||
</Transition> | ||
</Teleport> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,10 +3,12 @@ import GitHubIcon from "../Icons/GitHubIcon.vue"; | |
import Logo from "./SiteLogo.vue"; | ||
import { ref } from "vue"; | ||
import JoinSlack from "./JoinSlack.vue"; | ||
import Contributors from "./ProjectContributors.vue"; | ||
const currentYear = new Date().getFullYear(); | ||
const slackModalOpen = ref(false); | ||
const contributorModalOpen = ref(false); | ||
</script> | ||
<template> | ||
<footer class="bg-cyan-600 font-sans text-sm text-white"> | ||
|
@@ -37,7 +39,7 @@ const slackModalOpen = ref(false); | |
<div class="mb-4 ml-0 flex-grow sm:mb-0 sm:ml-6"> | ||
<h4 class="mb-2 font-work-sans text-lg font-bold capitalize not-italic text-white">The Creators</h4> | ||
<ul class="list-none"> | ||
<li class="py-1"><router-link to="/events" class="decoration-pink-600 decoration-2 underline-offset-4 hover:underline">About Us</router-link></li> | ||
<li class="py-1"><span @click="contributorModalOpen = true" class="cursor-pointer decoration-pink-600 decoration-2 underline-offset-4 hover:underline">Contributors</span></li> | ||
<li class="py-1"><a href="mailto:[email protected]" class="decoration-pink-600 decoration-2 underline-offset-4 hover:underline">Email Us</a></li> | ||
<li class="py-1"><a href="https://github.com/php-school" target="_blank" class="decoration-pink-600 decoration-2 underline-offset-4 hover:underline">GitHub</a></li> | ||
</ul> | ||
|
@@ -67,5 +69,6 @@ const slackModalOpen = ref(false); | |
</div> | ||
</div> | ||
<JoinSlack :open="slackModalOpen" @close="slackModalOpen = false" /> | ||
<Contributors v-if="contributorModalOpen" :open="contributorModalOpen" @close="contributorModalOpen = false" /> | ||
</footer> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace PhpSchool\Website\Action; | ||
|
||
use Psr\Http\Message\ResponseInterface as Response; | ||
use Psr\Http\Message\ServerRequestInterface as Request; | ||
|
||
class Contributors | ||
{ | ||
use JsonUtils; | ||
public function __invoke(Request $request, Response $response): Response | ||
{ | ||
/** @var array<string, array{username: string, contributions: int, profilePic: string, profile: string}> $data */ | ||
$data = json_decode((string) file_get_contents(__DIR__ . '/../../var/contributors.json')); | ||
return $this->withJson($data, $response); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace PhpSchool\Website\Command; | ||
|
||
use Psr\Log\LoggerInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
|
||
class SyncContributors | ||
{ | ||
private const CONTRIBUTORS_FILE_LOCATION = __DIR__ . '/../../var/contributors.json'; | ||
|
||
public function __construct(private \Github\Client $client, private LoggerInterface $logger) {} | ||
|
||
public function __invoke(OutputInterface $output): void | ||
{ | ||
try { | ||
$contributors = $this->downloadContributors(); | ||
} catch (\Exception $e) { | ||
$this->logger->error('Could not download contributors. Error: ' . $e->getMessage()); | ||
return; | ||
} | ||
|
||
file_put_contents(self::CONTRIBUTORS_FILE_LOCATION, json_encode($contributors, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR)); | ||
|
||
$output->writeln('<info>Contributors synced</info>'); | ||
} | ||
|
||
/** | ||
* @return array<int, array{ | ||
* username: string, | ||
* contributions: int, | ||
* profilePic: string, | ||
* profile: string | ||
* }> | ||
*/ | ||
private function downloadContributors(): array | ||
{ | ||
$repositories = $this->client->user()->repositories('php-school'); | ||
|
||
$contributors = []; | ||
|
||
foreach ($repositories as $repository) { | ||
$result = $this->client->repositories()->contributors('php-school', $repository['name']); | ||
|
||
if (!is_array($result)) { | ||
continue; | ||
} | ||
|
||
foreach ($result as $contributor) { | ||
if (!isset($contributors[$contributor['login']])) { | ||
$contributors[$contributor['login']] = [ | ||
'username' => $contributor['login'], | ||
'contributions' => (int) $contributor['contributions'], | ||
'profilePic' => $contributor['avatar_url'], | ||
'profile' => $contributor['html_url'], | ||
]; | ||
} else { | ||
$contributors[$contributor['login']]['contributions'] += (int) $contributor['contributions']; | ||
} | ||
} | ||
} | ||
|
||
usort($contributors, fn(array $a, array $b) => $b['contributions'] <=> $a['contributions']); | ||
|
||
return $contributors; | ||
} | ||
} |