Add terrible gallery page.

pull/217/head
Atul Varma 2021-08-22 10:10:31 -04:00
rodzic 22ae85c512
commit b0802f82ba
7 zmienionych plików z 136 dodań i 6 usunięć

Wyświetl plik

@ -1,6 +1,10 @@
import React, { useCallback, useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { FirebaseAppProvider, FirebaseGithubAuthProvider } from "./firebase";
import {
FirebaseAppProvider,
FirebaseGalleryProvider,
FirebaseGithubAuthProvider,
} from "./firebase";
import { PageContext, PAGE_QUERY_ARG } from "./page";
import { pageNames, Pages, toPageName, DEFAULT_PAGE } from "./pages";
@ -59,9 +63,11 @@ const App: React.FC<{}> = (props) => {
return (
<FirebaseAppProvider>
<FirebaseGithubAuthProvider>
<PageContext.Provider value={ctx}>
<PageComponent />
</PageContext.Provider>
<FirebaseGalleryProvider>
<PageContext.Provider value={ctx}>
<PageComponent />
</PageContext.Provider>
</FirebaseGalleryProvider>
</FirebaseGithubAuthProvider>
</FirebaseAppProvider>
);

Wyświetl plik

@ -8,8 +8,18 @@ import {
Auth,
User,
} from "firebase/auth";
import {
FirebaseFirestore,
getFirestore,
collection,
getDocs,
CollectionReference,
} from "firebase/firestore";
import React, { useCallback, useContext, useEffect, useState } from "react";
import { AuthContext } from "./auth-context";
import { GalleryComposition, GalleryContext } from "./gallery-context";
const GALLERY_COLLECTION = "compositions";
const DEFAULT_APP_CONFIG: FirebaseOptions = {
apiKey: "AIzaSyAV1kkVvSKEicEa8rLke9o_BxYBu1rb8kw",
@ -25,6 +35,7 @@ type FirebaseAppContext = {
app: FirebaseApp;
auth: Auth;
provider: GithubAuthProvider;
db: FirebaseFirestore;
};
export const FirebaseAppContext =
@ -47,8 +58,9 @@ export const FirebaseAppProvider: React.FC<{ config?: FirebaseOptions }> = ({
const app = initializeApp(config || DEFAULT_APP_CONFIG);
const auth = getAuth(app);
const provider = new GithubAuthProvider();
const db = getFirestore(app);
setValue({ app, auth, provider });
setValue({ app, auth, provider, db });
}, [config]);
return <FirebaseAppContext.Provider value={value} children={children} />;
@ -90,3 +102,50 @@ export const FirebaseGithubAuthProvider: React.FC<{}> = ({ children }) => {
return <AuthContext.Provider value={context} children={children} />;
};
type FirebaseCompositionDocument = Omit<GalleryComposition, "id">;
function getGalleryCollection(appCtx: FirebaseAppContext) {
return collection(
appCtx.db,
GALLERY_COLLECTION
) as CollectionReference<FirebaseCompositionDocument>;
}
export const FirebaseGalleryProvider: React.FC<{}> = ({ children }) => {
const appCtx = useContext(FirebaseAppContext);
const [compositions, setCompositions] = useState<GalleryComposition[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | undefined>(undefined);
const handleError = (e: Error) => {
setIsLoading(false);
setError(e.message);
};
const context: GalleryContext = {
compositions,
isLoading,
error,
refresh: useCallback(() => {
if (!(appCtx && !isLoading)) return false;
setError(undefined);
setIsLoading(true);
getDocs(getGalleryCollection(appCtx))
.then((snapshot) => {
setIsLoading(false);
setCompositions(
snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}))
);
})
.catch(handleError);
return true;
}, [appCtx, isLoading]),
};
return <GalleryContext.Provider value={context} children={children} />;
};

Wyświetl plik

@ -0,0 +1,23 @@
import React from "react";
export type GalleryComposition = {
id: string;
kind: "creature" | "mandala";
owner: string;
ownerName: string;
title: string;
serializedValue: string;
};
export interface GalleryContext {
compositions: GalleryComposition[];
isLoading: boolean;
error?: string;
refresh(): boolean;
}
export const GalleryContext = React.createContext<GalleryContext>({
compositions: [],
isLoading: false,
refresh: () => true,
});

Wyświetl plik

@ -112,3 +112,7 @@ ul.navbar li:last-child {
margin-top: 10px;
margin-bottom: 10px;
}
.error {
color: red;
}

Wyświetl plik

@ -107,7 +107,7 @@ const AuthWidget: React.FC<{}> = () => {
<button onClick={ctx.login}>Login with {ctx.providerName}</button>
);
const error = ctx.error ? <p style={{ color: "red" }}>{ctx.error}</p> : null;
const error = ctx.error ? <p className="error">{ctx.error}</p> : null;
return (
<div className="thingy">

Wyświetl plik

@ -0,0 +1,36 @@
import React, { useContext, useEffect, useState } from "react";
import { GalleryComposition, GalleryContext } from "../gallery-context";
import { Page } from "../page";
const GalleryCompositionView: React.FC<GalleryComposition> = (props) => {
return <p>{props.title}</p>;
};
export const GalleryPage: React.FC<{}> = () => {
const ctx = useContext(GalleryContext);
const [refreshed, setRefreshed] = useState(false);
useEffect(() => {
if (!refreshed) {
if (ctx.refresh()) {
setRefreshed(true);
}
}
}, [ctx, refreshed]);
return (
<Page title="Gallery!">
<div className="sidebar">
<button onClick={() => setRefreshed(false)} disabled={ctx.isLoading}>
{ctx.isLoading ? "Loading\u2026" : "Refresh"}
</button>
{ctx.error && <p className="error">{ctx.error}</p>}
</div>
<div className="canvas scrollable">
{ctx.compositions.map((comp) => (
<GalleryCompositionView key={comp.id} {...comp} />
))}
</div>
</Page>
);
};

Wyświetl plik

@ -3,12 +3,14 @@ import { VocabularyPage } from "./vocabulary-page";
import { CreaturePage } from "./creature-page";
import { MandalaPage } from "./mandala-page";
import { DebugPage } from "./debug-page";
import { GalleryPage } from "./gallery-page";
export const Pages = {
vocabulary: VocabularyPage,
creature: CreaturePage,
waves: WavesPage,
mandala: MandalaPage,
gallery: GalleryPage,
debug: DebugPage,
};