admin page

Changed files
+51 -21
atproto-notifications
+2 -3
atproto-notifications/src/App.tsx
··· 1 1 import { useCallback, useState, useEffect } from 'react'; 2 + import { Outlet } from 'react-router'; 2 3 import { useLocalStorage } from "@uidotdev/usehooks"; 3 4 import { GetJson } from './components/fetch'; 4 5 import { WhoAmI } from './components/WhoAmI'; 5 - import { Feed } from './components/Feed'; 6 6 import { WithFeatureChecks } from './components/setup/WithFeatureChecks'; 7 7 import { WithServiceWorker } from './components/setup/WithServiceWorker'; 8 8 import { WithServerHello } from './components/setup/WithServerHello'; 9 - import { UserContext } from './context'; 10 9 import { WithNotificationPermission } from './components/setup/WithNotificationPermission'; 11 10 import { WithPushSubscription } from './components/setup/WithPushSubscription'; 12 11 import { urlBase64ToUint8Array } from './utils'; ··· 22 21 <WithServiceWorker> 23 22 <WithNotificationPermission> 24 23 <WithPushSubscription> 25 - <Feed /> 24 + {children} 26 25 </WithPushSubscription> 27 26 </WithNotificationPermission> 28 27 </WithServiceWorker>
atproto-notifications/src/components/Feed.css atproto-notifications/src/pages/Feed.css
+2 -2
atproto-notifications/src/components/Feed.tsx atproto-notifications/src/pages/Feed.tsx
··· 1 1 import { useEffect, useState } from 'react'; 2 2 import { getNotifications, getSecondary } from '../db'; 3 - import { ButtonGroup } from './Buttons'; 4 - import { Notification } from './Notification'; 3 + import { ButtonGroup } from '../components/Buttons'; 4 + import { Notification } from '../components/Notification'; 5 5 import psl from 'psl'; 6 6 import lexicons from 'lexicons'; 7 7
+11 -2
atproto-notifications/src/components/setup/Chrome.tsx
··· 1 + import { Link } from 'react-router'; 1 2 import { Handle } from '../User'; 2 3 import './Chrome.css'; 3 4 ··· 7 8 return ( 8 9 <> 9 10 <header id="app-header"> 10 - <h1>spacedust notifications&nbsp;<span className="demo">demo!</span></h1> 11 + <h1> 12 + <Link to="/" className="inherit-font"> 13 + spacedust notifications&nbsp;<span className="demo">demo!</span> 14 + </Link> 15 + </h1> 11 16 {user && ( 12 17 <div className="current-user"> 13 18 <p> ··· 15 20 <Handle did={user.did} /> 16 21 {user.role !== 'public' && ( 17 22 <span className="chrome-role-tag"> 18 - {user.role} 23 + {user.role === 'admin' ? ( 24 + <Link to="/admin" className="inherit-font">{user.role}</Link> 25 + ) : ( 26 + <>{user.role}</> 27 + )} 19 28 </span> 20 29 )} 21 30 </span>
+7 -3
atproto-notifications/src/components/setup/WithServerHello.tsx
··· 1 1 import { useCallback, useEffect, useState } from 'react'; 2 - import { UserContext, PushServerContext } from '../../context'; 2 + import { RoleContext, PushServerContext } from '../../context'; 3 3 import { WhoAmI } from '../WhoAmI'; 4 4 import { SecretPassword } from '../SecretPassword'; 5 5 import { GetJson, PostJson } from '../Fetch'; ··· 71 71 ok={({ did, role, webPushPublicKey }) => ( 72 72 <Chrome user={{ did, role }} onLogout={handleLogout}> 73 73 <PushServerContext.Provider value={webPushPublicKey}> 74 - {childrenFor(did, role, children)} 74 + <RoleContext.Provider value={role}> 75 + {childrenFor(did, role, children)} 76 + </RoleContext.Provider> 75 77 </PushServerContext.Provider> 76 78 </Chrome> 77 79 )} ··· 81 83 return ( 82 84 <Chrome user={{ did, role }} onLogout={handleLogout}> 83 85 <PushServerContext.Provider value={webPushPublicKey}> 84 - {childrenFor(did, role, children)} 86 + <RoleContext.Provider value={role}> 87 + {childrenFor(did, role, children)} 88 + </RoleContext.Provider> 85 89 </PushServerContext.Provider> 86 90 </Chrome> 87 91 );
+1 -1
atproto-notifications/src/context.ts
··· 1 1 import { createContext } from 'react'; 2 2 3 - export const UserContext = createContext('light'); 3 + export const RoleContext = createContext('public'); 4 4 export const PushServerContext = createContext(null);
+5
atproto-notifications/src/index.css
··· 22 22 color: #535bf2; 23 23 } 24 24 25 + a.inherit-font { 26 + font: inherit; 27 + color: inherit; 28 + } 29 + 25 30 body { 26 31 margin: 0; 27 32 min-width: 320px;
+12 -10
atproto-notifications/src/main.tsx
··· 1 - import { StrictMode } from 'react' 2 - import { createRoot } from 'react-dom/client' 1 + import { StrictMode } from 'react'; 2 + import { createRoot } from 'react-dom/client'; 3 3 import { BrowserRouter, Routes, Route } from "react-router"; 4 - import './index.css' 5 - import { App } from './App.tsx' 4 + import './index.css'; 5 + import { App } from './App'; 6 + import { Feed } from './pages/Feed'; 7 + import { Admin } from './pages/Admin'; 6 8 7 9 createRoot(document.getElementById('root')!).render( 8 10 <StrictMode> 9 - <App> 10 - <BrowserRouter> 11 + <BrowserRouter> 12 + <App> 11 13 <Routes> 12 - {/*<Route index element={<Home />} />*/} 13 - {/*<Route path="/status" element={<Status />} />*/} 14 + <Route index element={<Feed />} /> 15 + <Route path="/admin" element={<Admin />} /> 14 16 </Routes> 15 - </BrowserRouter> 16 - </App> 17 + </App> 18 + </BrowserRouter> 17 19 </StrictMode>, 18 20 ); 19 21
+11
atproto-notifications/src/pages/Admin.tsx
··· 1 + import { useContext } from 'react'; 2 + import { RoleContext } from '../context'; 3 + 4 + export function Admin({}) { 5 + const role = useContext(RoleContext); 6 + if (role !== 'admin') { 7 + return <p>sorry, this page is admin-only</p> 8 + } 9 + 10 + return 'sup'; 11 + }