feat: test auth

This commit is contained in:
thomas
2024-03-29 21:29:52 +01:00
parent 73a81f4831
commit 18b1dc0a70
18 changed files with 1749 additions and 386 deletions

View File

@@ -6,6 +6,7 @@ import { getEntry } from 'astro:content';
const { lang } = Astro.props;
const { data } = await getEntry('i18n', lang);
---
<div class="action-footer">
@@ -37,7 +38,6 @@ const { data } = await getEntry('i18n', lang);
text-decoration: none;
font-size: var(--sl-text-sm) !important;
border: 1px solid;
font-size: var(--sl-text-base);
padding: 0.4rem 0.8rem;
}

View File

@@ -1,67 +0,0 @@
<script>
import { onMount } from 'svelte';
let error = false;
let loading = true;
let stargazersCount = 0;
let forksCount = 0;
async function fetchStats() {
try {
const response = await fetch(`https://api.github.com/repos/tomalaforge/angular-challenges`);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const { stargazers_count, forks } = await response.json();
stargazersCount = stargazers_count;
forksCount = forks;
} catch (e) {
error = true;
} finally {
loading = false;
}
}
onMount(() => {
fetchStats();
});
</script>
{#if !error && !loading}
<div class="github">
<a class="category" href="https://github.com/tomalaforge/angular-challenges" target="_blank">
<slot name="star"/>
<div>{stargazersCount}</div>
</a>
<a class="category" href="https://github.com/tomalaforge/angular-challenges/fork" target="_blank">
<slot name="fork"/>
<div>{forksCount}</div>
</a>
</div>
{/if}
<style>
.github {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-left: var(--sl-nav-gap);
}
.category {
display: flex;
align-items: center;
font-size: 12px;
gap: 0.25rem;
color: var(--sl-color-text);
text-decoration: none;
}
.category:hover {
color: var(--sl-color-accent-high);
}
</style>

View File

@@ -1,19 +1,20 @@
---
import Default from '@astrojs/starlight/components/SiteTitle.astro';
import GitHubStats from './GitHubStats.svelte';
import MyIcon from './MyIcon.astro';
import SignUp from './github/SignUp.svelte';
import { Icon } from '@astrojs/starlight/components';
---
<Default {...Astro.props}>
<slot />
</Default>
<SignUp client:load />
<!--<GitHubStats client:load >-->
<!-- <MyIcon name="star" slot="star" />-->
<!-- <MyIcon name="fork" viewBox="0 0 16 16" slot="fork"/>-->
<!--</GitHubStats>-->
<SignUp client:only="svelte" >
<Icon name="github" slot="github" />
<MyIcon name="fullStar" slot="fullStar" viewBox="0 0 16 16" fill="#e3b341"/>
<MyIcon name="star" slot="star" viewBox="0 0 16 16"/>
<MyIcon name="fork" viewBox="0 0 16 16" slot="fork"/>
</SignUp>

View File

@@ -1,18 +1,27 @@
<script>
import { onMount } from 'svelte';
import { data, error, isLoaded, isLoading, token, totalCount } from './github-store';
export let challengeNumber;
let page = 1;
token.subscribe(token => {
if (token) {
fetchTotalCount();
}
})
async function fetchTotalCount() {
isLoading.set(true);
try {
while (true) {
const response = await fetch(`https://api.github.com/search/issues?q=repo:tomalaforge/angular-challenges+is:pr+label:"${challengeNumber}"+label:"answer"&per_page=100&page=${page}`);
const response = await fetch(`https://api.github.com/search/issues?q=repo:tomalaforge/angular-challenges+is:pr+label:"${challengeNumber}"+label:"answer"&per_page=100&page=${page}`, {
headers: {
Authorization: `Bearer ${$token}`,
},
});
if (!response.ok) {
throw new Error('Network response was not ok');
throw new Error('Failed to fetch data');
}
const { items: new_items, total_count } = await response.json();
if (!new_items || new_items.length === 0) break;
@@ -30,13 +39,8 @@
}
}
onMount(() => {
fetchTotalCount();
});
</script>
token: {$token}
{#if $isLoaded}
<div class="solution-container" id="answers">
<div>Answered by</div>

View File

@@ -0,0 +1,144 @@
<script>
import { token } from './github-store';
let error = false;
let loading = true;
let loadingStar = true;
let stargazersCount = 0;
let forksCount = 0;
let isStarByUser = false;
token.subscribe(token => {
if (token) {
fetchStats();
isStar();
}
});
async function starRepo() {
try {
const response = await fetch(`https://api.github.com/user/starred/tomalaforge/angular-challenges`, {
method: 'PUT',
headers: {
Authorization: `token ${$token}`
}
});
if (response.ok) {
isStarByUser = !isStarByUser;
console.log('Starred', isStarByUser);
}
} catch (e) {
console.error(e);
}
}
async function isStar() {
try {
const response = await fetch(`https://api.github.com/user/starred/tomalaforge/angular-challenges`, {
method: 'GET',
headers: {
Authorization: `token ${$token}`
}
});
if (response.ok && response.status === 204) {
isStarByUser = true;
}
} catch (e) {
console.error(e);
} finally {
loadingStar = false;
}
}
async function fetchStats() {
try {
const response = await fetch(`https://api.github.com/repos/tomalaforge/angular-challenges`);
if (!response.ok) {
if (response.status === 401) {
const refresh = await fetch('/auth/refresh');
if (refresh.ok) {
const data = await refresh.json();
token.set(data.token);
return;
}
} else {
throw new Error('Failed to fetch data');
}
}
const { stargazers_count, forks } = await response.json();
stargazersCount = stargazers_count;
forksCount = forks;
} catch (e) {
error = true;
} finally {
loading = false;
}
}
</script>
{#if !error && !loading && !loadingStar}
<div class="github">
{#if isStarByUser}
<div class="category starred">
<slot name="fullStar" />
<span>{stargazersCount}</span>
</div>
{:else}
<button class="button-star link" on:click={starRepo}>
<slot name="star" />
<span>{stargazersCount}</span>
</button>
{/if}
<a class="category link" href="https://github.com/tomalaforge/angular-challenges/fork" target="_blank">
<slot name="fork" />
<div>{forksCount}</div>
</a>
</div>
{/if}
<style>
.github {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-left: var(--sl-nav-gap);
}
.button-star {
display: flex !important;
justify-content: center;
gap: 0.5em;
align-items: center;
border-radius: 999rem;
color: var(--sl-color-white) !important;
background-color: transparent;
line-height: 1.1875;
text-decoration: none;
font-size: var(--sl-text-xs);
border: 1px solid;
padding: 0.2rem 0.4rem;
margin-left: -6px
}
.category {
display: flex;
align-items: center;
font-size: 12px;
gap: 0.25rem;
color: var(--sl-color-text);
text-decoration: none;
}
.link:hover {
color: var(--sl-color-accent-high);
}
.starred {
color: #e3b341;
}
</style>

View File

@@ -1,38 +1,61 @@
<script>
import { loadToken, test } from './github-store';
import GitHubStats from './GitHubStats.svelte';
import { loadToken, token } from './github-store';
import { onMount } from 'svelte';
// Function to redirect the user to GitHub's signup page
async function redirectToGitHubSignup() {
// token.set('test-token');
window.location.href = `/auth/authorize`;
// await fetch(`/auth/authorize?redirect_uri=${window.location.href}&state=jsqhd&client_id=Iv1.711903007f608691`)
}
onMount(() => {
loadToken();
const searchParams = new URLSearchParams(window.location.search);
const t = searchParams.get('token');
if(t) {
token.set(t);
window.location.href = `${window.location.origin}${window.location.pathname}`;
} else {
loadToken();
}
});
</script>
{$test}
<button on:click={redirectToGitHubSignup}>
Sign Up for GitHub
</button>
{#if !$token}
<a href={`/auth/authorize?redirect_uri=${window.location.href}`}>
<slot name="github"/>
<span class="github-sign-in">Sign in</span>
</a>
{:else}
<GitHubStats>
<slot name="fullStar" slot="fullStar"/>
<slot name="star" slot="star"/>
<slot name="fork" slot="fork"/>
</GitHubStats>
{/if}
<style>
button {
background-color: #2ea44f;
a {
background-color: #238636;
display: flex;
gap: 0.25rem;
text-decoration: none;
color: white;
border: none;
padding: 10px 20px;
padding: 8px 8px;
cursor: pointer;
font-size: 16px;
border-radius: 5px;
align-items: center;
height: fit-content;
font-size:14px;
line-height: 14px;
margin-left: var(--sl-nav-gap);
}
button:hover {
a:hover {
background-color: #218838;
}
@media (width < 450px) {
.github-sign-in {
display: none;
}
}
</style>

View File

@@ -15,20 +15,18 @@ export const isLoaded = derived(
const TOKEN_KEY = 'TOKEN';
export function loadToken() {
// Get the current value from localStorage if it exists, otherwise use the startValue
const persistedValue = localStorage.getItem(TOKEN_KEY);
if (persistedValue) {
token.set(JSON.parse(persistedValue));
return;
const persistedToken = localStorage.getItem(TOKEN_KEY);
if (persistedToken) {
token.set(JSON.parse(persistedToken));
}
token.set('API call');
}
token.subscribe((value) => {
if (value) {
if (value === 'delete') {
localStorage.removeItem(TOKEN_KEY);
return;
}
localStorage.setItem(TOKEN_KEY, JSON.stringify(value));
}
});
export const test = writable('test');

View File

@@ -0,0 +1,45 @@
export function tooltip(element) {
let div;
let title;
function mouseOver(event) {
// NOTE: remove the `title` attribute, to prevent showing the default browser tooltip
// remember to set it back on `mouseleave`
title = element.getAttribute('title');
element.removeAttribute('title');
div = document.createElement('div');
div.textContent = title;
div.style = `
border: 1px solid #ddd;
box-shadow: 1px 1px 1px #ddd;
background: white;
border-radius: 4px;
padding: 4px;
position: absolute;
top: ${event.pageX + 5}px;
left: ${event.pageY + 5}px;
`;
document.body.appendChild(div);
}
function mouseMove(event) {
div.style.left = `${event.pageX + 5}px`;
div.style.top = `${event.pageY + 5}px`;
}
function mouseLeave() {
document.body.removeChild(div);
// NOTE: restore the `title` attribute
element.setAttribute('title', title);
}
element.addEventListener('mouseover', mouseOver);
element.addEventListener('mouseleave', mouseLeave);
element.addEventListener('mousemove', mouseMove);
return {
destroy() {
element.removeEventListener('mouseover', mouseOver);
element.removeEventListener('mouseleave', mouseLeave);
element.removeEventListener('mousemove', mouseMove);
}
}
}

View File

@@ -1,6 +1,8 @@
export const Icons = {
heart:
'<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path>',
star: '<path d="M22 9.67a1 1 0 0 0-.86-.67l-5.69-.83L12.9 3a1 1 0 0 0-1.8 0L8.55 8.16 2.86 9a1 1 0 0 0-.81.68 1 1 0 0 0 .25 1l4.13 4-1 5.68a1 1 0 0 0 1.45 1.07L12 18.76l5.1 2.68c.14.08.3.12.46.12a1 1 0 0 0 .99-1.19l-1-5.68 4.13-4A1 1 0 0 0 22 9.67Zm-6.15 4a1 1 0 0 0-.29.89l.72 4.19-3.76-2a1 1 0 0 0-.94 0l-3.76 2 .72-4.19a1 1 0 0 0-.29-.89l-3-3 4.21-.61a1 1 0 0 0 .76-.55L12 5.7l1.88 3.82a1 1 0 0 0 .76.55l4.21.61-3 2.99Z"/>',
star: '<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"/>',
fullStar:
'<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"/>',
fork: '<path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"/>',
};