Skip to content

Commit

Permalink
feat: Add GitHubContext and GitHubStatus components for GitHub parame…
Browse files Browse the repository at this point in the history
…ter validation and status display
  • Loading branch information
szweibel committed Dec 18, 2024
1 parent 082dab8 commit 467a5e8
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 87 deletions.
6 changes: 3 additions & 3 deletions components/Editor/HTMLEditorComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export default function HTMLEditorComponent({
const parserOptions = {
replace: (domNode) => {
if (domNode.type === 'tag' && domNode.name === 'img') {
const props = { ...domNode.attribs, crossorigin: 'anonymous' };
const props = { ...domNode.attribs, crossOrigin: 'anonymous' };
return <img {...props} />;
}
}
Expand Down Expand Up @@ -178,7 +178,7 @@ export default function HTMLEditorComponent({
case 'img':
return <img
{...baseAttribs}
crossorigin="anonymous"
crossOrigin="anonymous"
loading="lazy"
referrerPolicy="no-referrer"
/>;
Expand All @@ -194,7 +194,7 @@ export default function HTMLEditorComponent({
case 'link':
return <link
{...baseAttribs}
crossorigin="anonymous"
crossOrigin="anonymous"
referrerPolicy="no-referrer"
/>;

Expand Down
69 changes: 69 additions & 0 deletions components/GitHubContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { createContext, useContext, useState, useEffect } from 'react';
import { getGitHubParamsFromURL, validateParams } from '../utils/github';
import { useRouter } from 'next/router';
import { GitHubStatus } from './GitHubStatus';

export const GitHubContext = createContext();

export function GitHubProvider({ children }) {
const router = useRouter();
const [loading, setLoading] = useState(true);
const [validationStatus, setValidationStatus] = useState({
isValid: false,
messages: [],
checks: []
});

useEffect(() => {
const checkParams = async () => {
if (!router.isReady) return;

setLoading(true);
try {
const params = getGitHubParamsFromURL();
const status = await validateParams(params);
setValidationStatus(status);
} catch (error) {
setValidationStatus({
isValid: false,
messages: [`Validation error: ${error.message}`],
checks: []
});
} finally {
setLoading(false);
}
};

checkParams();

// Cleanup
return () => {
setValidationStatus({
isValid: false,
messages: [],
checks: []
});
};
}, [router.isReady, router.query]);

const value = {
loading,
validationStatus,
setValidationStatus
};

return (
<GitHubContext.Provider value={value}>
{loading ? (
<div>Validating GitHub parameters...</div>
) : (
<>
<GitHubStatus validationStatus={validationStatus} />
{children}
</>
)}
</GitHubContext.Provider>
);
}

export const useGitHub = () => useContext(GitHubContext);
25 changes: 25 additions & 0 deletions components/GitHubStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Alert } from '@mui/material';

export function GitHubStatus({ validationStatus }) {
if (!validationStatus?.messages?.length) return null;

return (
<div style={{
position: 'fixed',
top: '1rem',
right: '1rem',
zIndex: 9999,
maxWidth: '400px'
}}>
{validationStatus.messages.map((message, i) => (
<Alert
key={i}
severity={validationStatus.isValid ? "success" : "error"}
sx={{ mb: 1 }}
>
{message}
</Alert>
))}
</div>
);
}
131 changes: 47 additions & 84 deletions pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import Header from '../components/Header';
import { StyledEngineProvider } from '@mui/material/styles';
import '../styles/styles.scss';
import '../node_modules/highlight.js/styles/obsidian.css';
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';
import Head from 'next/head';
// MUI styles first
import CssBaseline from '@mui/material/CssBaseline';
import { StyledEngineProvider } from '@mui/material/styles';

// Framework imports
import dynamic from 'next/dynamic';
import { ThemeProvider } from 'next-themes';
const Footer = dynamic(() => import('../components/Footer'))
import PyodideProvider from '../components/Wasm/PyodideProvider';
import { SWRConfig } from 'swr';
import { useRef } from 'react';
import NextNProgress from 'nextjs-progressbar';
import { useSWRConfig } from "swr";
import { SWRConfig, useSWRConfig } from 'swr';
import { useRouter } from 'next/router';
import { GitHubProvider } from '../components/GitHubContext';

function MyApp({ Component, pageProps }) {
// Custom styles after MUI
import 'allotment/dist/style.css';
import '../node_modules/highlight.js/styles/obsidian.css';
import '../styles/styles.scss';

const Footer = dynamic(() => import('../components/Footer'));

function MyApp({ Component, pageProps }) {
const [title, setTitle] = useState('');
const [workshopMode, setWorkshopMode] = useState(false);
const [gitUser, setGitUser] = useState(null);
Expand All @@ -25,11 +27,13 @@ function MyApp({ Component, pageProps }) {
const [instGitRepo, setInstGitRepo] = useState(null);
const [query, setQuery] = useState(null);
const [cacheCleared, setCacheCleared] = useState(false);
const { cache, mutate } = useSWRConfig()
const { cache, mutate } = useSWRConfig();
const router = useRouter();

const swrCacheProvider = useRef(new Map()).current;
const clearCache = () => {
cache.clear()
}
cache.clear();
};

useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
Expand Down Expand Up @@ -57,85 +61,44 @@ function MyApp({ Component, pageProps }) {
}
}, [router])

pageProps.query = query
pageProps.title = title
pageProps.setTitle = setTitle
pageProps.workshopMode = workshopMode
pageProps.setWorkshopMode = setWorkshopMode
pageProps.gitUser = gitUser
pageProps.setGitUser = setGitUser
pageProps.gitRepo = gitRepo
pageProps.setGitRepo = setGitRepo
pageProps.instGitUser = instGitUser
pageProps.setInstGitUser = setInstGitUser
pageProps.instGitRepo = instGitRepo
pageProps.setInstGitRepo = setInstGitRepo
pageProps.clearCache = clearCache

Object.assign(pageProps, {
title, setTitle, workshopMode, setWorkshopMode,
})

// useCacheProvider hook
function useCacheProvider() {
const cache = useRef(new Map());
useEffect(() => {
const currentDate = new Date();
const appCache = localStorage.getItem('app-cache');
if (appCache) {
// if at least a day has passed since the cache was set, clear it
if (localStorage.getItem('app-cache-time') && (currentDate - new Date(localStorage.getItem('app-cache-time'))) > 86400000) {
localStorage.removeItem('app-cache');
localStorage.removeItem('app-cache-time');
// cache.clear();
console.log('cache cleared')
return;
}
const map = new Map(JSON.parse(appCache));
map.forEach((value, key) => cache.current.set(key, value));
}

const saveCache = () => {
const appCache = JSON.stringify(Array.from(cache.current.entries()));
localStorage.setItem('app-cache', appCache);
const whenSet = new Date()
localStorage.setItem('app-cache-time', whenSet);
};

window.addEventListener('beforeunload', saveCache);
return () => window.removeEventListener('beforeunload', saveCache);
}, []);

return () => cache.current;
}


// use hook in SWRConfig
const provider = useCacheProvider();
pageProps = {
...pageProps,
query,
title,
setTitle,
workshopMode,
setWorkshopMode,
gitUser,
setGitUser,
gitRepo,
setGitRepo,
instGitUser,
setInstGitUser,
instGitRepo,
setInstGitRepo,
clearCache
};

return (
<>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<CssBaseline />
<ThemeProvider>
<StyledEngineProvider>
<StyledEngineProvider injectFirst>
<CssBaseline />
<ThemeProvider>
<main className='container'>
<SWRConfig value={{ provider }}>
<PyodideProvider>
<NextNProgress
options={{ easing: 'ease', speed: 200 }} />
<SWRConfig value={{ provider: () => swrCacheProvider }}>
<GitHubProvider>
<Component {...pageProps} />
</PyodideProvider>
</GitHubProvider>
</SWRConfig>
</main>
</StyledEngineProvider>
</ThemeProvider>
{!workshopMode &&
<Footer />}
</ThemeProvider>
{!workshopMode && <Footer />}
</StyledEngineProvider>
</>
)
);
}

export default MyApp
export default MyApp;
Loading

0 comments on commit 467a5e8

Please sign in to comment.