Migrations and initial data stuff

This commit is contained in:
Gregory Schier
2023-02-25 16:39:18 -08:00
parent ba3b899115
commit 93105a3e89
17 changed files with 1082 additions and 129 deletions

View File

@@ -9,6 +9,7 @@ import { Sidebar } from './components/Sidebar';
import { UrlBar } from './components/UrlBar';
import { Grid } from './components/Grid';
import { motion } from 'framer-motion';
import { useRequests, useWorkspace, useWorkspaces } from './hooks/useWorkspaces';
interface Response {
url: string;
@@ -21,6 +22,8 @@ interface Response {
}
function App() {
const { data } = useWorkspace();
console.log('DATA', data);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [response, setResponse] = useState<Response | null>(null);
@@ -31,6 +34,19 @@ function App() {
value: 'GET',
});
useEffect(() => {
const listener = async (e: KeyboardEvent) => {
if (e.metaKey && (e.key === 'Enter' || e.key === 'r')) {
await sendRequest();
}
};
document.documentElement.addEventListener('keypress', listener);
return () => document.documentElement.removeEventListener('keypress', listener);
}, []);
if (!data) return null;
const { requests, workspace } = data;
async function sendRequest() {
setLoading(true);
setError(null);
@@ -54,20 +70,10 @@ function App() {
const contentType = response?.headers['content-type']?.split(';')[0] ?? 'text/plain';
useEffect(() => {
const listener = async (e: KeyboardEvent) => {
if (e.metaKey && (e.key === 'Enter' || e.key === 'r')) {
await sendRequest();
}
};
document.documentElement.addEventListener('keypress', listener);
return () => document.documentElement.removeEventListener('keypress', listener);
}, []);
return (
<>
<div className="grid grid-cols-[auto_1fr] h-full text-gray-900">
<Sidebar />
<Sidebar requests={requests ?? []} workspaceId={workspace.id} />
<Grid cols={2}>
<VStack className="w-full">
<HStack as={WindowDragRegion} items="center" className="pl-3 pr-1.5">

View File

@@ -5,10 +5,15 @@ import { Button } from './Button';
import useTheme from '../hooks/useTheme';
import { HStack } from './Stacks';
import { WindowDragRegion } from './WindowDragRegion';
import { Request } from '../hooks/useWorkspaces';
import { invoke } from '@tauri-apps/api';
type Props = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
workspaceId: string;
requests: Request[];
}
export function Sidebar({ className, ...props }: Props) {
export function Sidebar({ className, workspaceId, requests, ...props }: Props) {
const { toggleTheme } = useTheme();
return (
<div
@@ -17,16 +22,28 @@ export function Sidebar({ className, ...props }: Props) {
>
<HStack as={WindowDragRegion} items="center" className="pr-1" justify="end">
<IconButton size="sm" icon="sun" onClick={toggleTheme} />
<IconButton
size="sm"
icon="camera"
onClick={async () => {
const req = await invoke('upsert_request', {
workspaceId,
id: null,
name: 'Test Request',
});
console.log('UPSERTED', req);
}}
/>
</HStack>
<ul className="mx-2 py-2">
{['Test Request', 'Another Request', 'Something else', 'And Another'].map((v, i) => (
<li key={v}>
{requests.map((r) => (
<li key={r.id}>
<Button
className={classnames('w-full', i === 0 && 'bg-gray-50')}
className={classnames('w-full', false && 'bg-gray-50')}
size="sm"
justify="start"
>
{v}
{r.name}
</Button>
</li>
))}

View File

@@ -0,0 +1,62 @@
import { invoke } from '@tauri-apps/api';
import { useQuery, UseQueryResult } from 'react-query';
interface BaseModel {
id: string;
createdAt: Date;
updatedAt: Date;
deletedAt: Date | null;
}
export interface Request extends BaseModel {
name: string;
url: string;
body: string | null;
method: string;
}
export interface Workspace extends BaseModel {
name: string;
description: string;
}
export function useWorkspaces(): UseQueryResult<Workspace[]> {
return useQuery('workspaces', async () => {
const workspaces = (await invoke('workspaces')) as Workspace[];
return workspaces.map(convertDates);
});
}
export function useRequests(): UseQueryResult<Request[]> {
return useQuery('requests', async () => {
const workspaces = (await invoke('workspaces')) as Workspace[];
const requests = (await invoke('requests', { workspaceId: workspaces[0].id })) as Request[];
return requests.map(convertDates);
});
}
export function useWorkspace(): UseQueryResult<{ workspace: Workspace; requests: Request[] }> {
return useQuery('workspace', async () => {
const workspaces = (await invoke('workspaces')) as Workspace[];
const requests = (await invoke('requests', { workspaceId: workspaces[0].id })) as Request[];
return {
workspace: convertDates(workspaces[0]),
requests: requests.map(convertDates),
};
});
}
function convertDates<T extends BaseModel>(m: T): T {
return {
...m,
createdAt: convertDate(m.createdAt),
updatedAt: convertDate(m.updatedAt),
deletedAt: m.deletedAt ? convertDate(m.deletedAt) : null,
};
}
function convertDate(d: string | Date): Date {
const date = new Date(d);
const userTimezoneOffset = date.getTimezoneOffset() * 60000;
return new Date(date.getTime() - userTimezoneOffset);
}

View File

@@ -8,6 +8,7 @@ import { invoke } from '@tauri-apps/api';
import { setTheme } from './lib/theme';
import './main.css';
import { QueryClient, QueryClientProvider } from 'react-query';
setTheme();
@@ -15,12 +16,16 @@ await init();
greet();
await invoke('load_db');
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<MotionConfig transition={{ duration: 0.15 }}>
<HelmetProvider>
<App />
</HelmetProvider>
</MotionConfig>
<QueryClientProvider client={queryClient}>
<MotionConfig transition={{ duration: 0.15 }}>
<HelmetProvider>
<App />
</HelmetProvider>
</MotionConfig>
</QueryClientProvider>
</React.StrictMode>,
);