mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-11 21:11:48 +01:00
Started on environment edit dialog
This commit is contained in:
@@ -343,6 +343,22 @@ async fn create_workspace(
|
||||
emit_and_return(&window, "created_model", created_workspace)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn create_environment(
|
||||
workspace_id: &str,
|
||||
name: &str,
|
||||
window: Window<Wry>,
|
||||
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<models::Environment, String> {
|
||||
let pool = &*db_instance.lock().await;
|
||||
let data: HashMap<String, JsonValue> = HashMap::new();
|
||||
let created_environment = models::create_environment(workspace_id, name, data, pool)
|
||||
.await
|
||||
.expect("Failed to create environment");
|
||||
|
||||
emit_and_return(&window, "created_model", created_environment)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn create_request(
|
||||
workspace_id: &str,
|
||||
@@ -639,6 +655,7 @@ fn main() {
|
||||
})
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
create_environment,
|
||||
create_request,
|
||||
create_workspace,
|
||||
delete_all_responses,
|
||||
|
||||
@@ -5,7 +5,6 @@ import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import { AppRouter } from './AppRouter';
|
||||
import { DialogProvider } from './DialogContext';
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
logger: undefined,
|
||||
@@ -24,12 +23,10 @@ export function App() {
|
||||
<MotionConfig transition={{ duration: 0.1 }}>
|
||||
<HelmetProvider>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<DialogProvider>
|
||||
<Suspense>
|
||||
<AppRouter />
|
||||
{/*<ReactQueryDevtools initialIsOpen={false} />*/}
|
||||
</Suspense>
|
||||
</DialogProvider>
|
||||
</DndProvider>
|
||||
</HelmetProvider>
|
||||
</MotionConfig>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { GlobalHooks } from './GlobalHooks';
|
||||
import RouteError from './RouteError';
|
||||
import Workspace from './Workspace';
|
||||
import Workspaces from './Workspaces';
|
||||
import { DialogProvider } from './DialogContext';
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@@ -59,9 +60,9 @@ function WorkspaceOrRedirect() {
|
||||
|
||||
function Layout() {
|
||||
return (
|
||||
<>
|
||||
<DialogProvider>
|
||||
<Outlet />
|
||||
<GlobalHooks />
|
||||
</>
|
||||
</DialogProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { createContext, useContext, useMemo, useState } from 'react';
|
||||
import type { DialogProps } from './core/Dialog';
|
||||
import { Dialog } from './core/Dialog';
|
||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||
import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
|
||||
|
||||
type DialogEntry = {
|
||||
id: string;
|
||||
@@ -54,9 +56,11 @@ export const DialogProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
function DialogInstance({ id, render, ...props }: DialogEntry) {
|
||||
const { actions } = useContext(DialogContext);
|
||||
const children = render({ hide: () => actions.hide(id) });
|
||||
console.log("ACITEV WORKSPAXCE ID 2", useActiveWorkspaceId());
|
||||
return (
|
||||
<Dialog open onClose={() => actions.hide(id)} {...props}>
|
||||
{render({ hide: () => actions.hide(id) })}
|
||||
{children}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
69
src-web/components/EnvironmentEditDialog.tsx
Normal file
69
src-web/components/EnvironmentEditDialog.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { useState } from 'react';
|
||||
import { useCreateEnvironment } from '../hooks/useCreateEnvironment';
|
||||
import { useEnvironments } from '../hooks/useEnvironments';
|
||||
import { usePrompt } from '../hooks/usePrompt';
|
||||
import { useUpdateEnvironment } from '../hooks/useUpdateEnvironment';
|
||||
import type { Environment } from '../lib/models';
|
||||
import { Button } from './core/Button';
|
||||
import { Editor } from './core/Editor';
|
||||
import classnames from 'classnames';
|
||||
|
||||
export const EnvironmentEditDialog = function () {
|
||||
const prompt = usePrompt();
|
||||
const environments = useEnvironments();
|
||||
const createEnvironment = useCreateEnvironment();
|
||||
const [activeEnvironment, setActiveEnvironment] = useState<Environment | null>(null);
|
||||
|
||||
return (
|
||||
<div className="h-full grid gap-3 grid-cols-[auto_minmax(0,1fr)]">
|
||||
<aside className="h-full min-w-[120px] pr-3 border-r border-gray-200">
|
||||
{environments.map((e) => (
|
||||
<Button
|
||||
className={classnames('w-full', activeEnvironment?.id === e.id && 'bg-highlight')}
|
||||
justify="start"
|
||||
key={e.id}
|
||||
onClick={() => {
|
||||
setActiveEnvironment(e);
|
||||
}}
|
||||
>
|
||||
{e.name}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
color="gray"
|
||||
onClick={async () => {
|
||||
const name = await prompt({
|
||||
title: 'Environment Name',
|
||||
defaultValue: 'My Env',
|
||||
label: 'Name',
|
||||
name: 'environment',
|
||||
});
|
||||
createEnvironment.mutate({ name });
|
||||
}}
|
||||
>
|
||||
Create Environment
|
||||
</Button>
|
||||
</aside>
|
||||
{activeEnvironment != null && <EnvironmentEditor environment={activeEnvironment} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const EnvironmentEditor = function ({ environment }: { environment: Environment }) {
|
||||
const updateEnvironment = useUpdateEnvironment(environment.id);
|
||||
return (
|
||||
<Editor
|
||||
contentType="application/json"
|
||||
className="w-full min-h-[40px] !bg-gray-50"
|
||||
defaultValue={JSON.stringify(environment.data, null, 2)}
|
||||
forceUpdateKey={environment.id}
|
||||
onChange={(data) => {
|
||||
try {
|
||||
updateEnvironment.mutate({ data: JSON.parse(data) });
|
||||
} catch (err) {
|
||||
// That's okay
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -40,7 +40,7 @@ export function Overlay({ zIndex = 30, open, onClose, portalName, children }: Pr
|
||||
{children}
|
||||
</motion.div>
|
||||
</FocusTrap>
|
||||
)}
|
||||
)}
|
||||
</Portal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,17 +9,13 @@ import { SidebarActions } from './SidebarActions';
|
||||
import { WorkspaceActionsDropdown } from './WorkspaceActionsDropdown';
|
||||
import { Button } from './core/Button';
|
||||
import { useDialog } from './DialogContext';
|
||||
import { useEnvironments } from '../hooks/useEnvironments';
|
||||
import type { Environment } from '../lib/models';
|
||||
import { Editor } from './core/Editor';
|
||||
import { useUpdateEnvironment } from '../hooks/useUpdateEnvironment';
|
||||
import { EnvironmentEditDialog } from './EnvironmentEditDialog';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) {
|
||||
const environments = useEnvironments();
|
||||
const activeRequest = useActiveRequest();
|
||||
const dialog = useDialog();
|
||||
|
||||
@@ -35,14 +31,8 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
|
||||
<Button onClick={() => {
|
||||
dialog.show({
|
||||
title: 'Environments',
|
||||
render: () => <div>
|
||||
{environments.map(e => (
|
||||
<EnvironmentList
|
||||
key={e.id}
|
||||
environment={e}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
size: 'full',
|
||||
render: () => <EnvironmentEditDialog />,
|
||||
})
|
||||
}}>
|
||||
Environments
|
||||
@@ -66,28 +56,3 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
|
||||
</HStack>
|
||||
);
|
||||
});
|
||||
|
||||
interface EnvironmentListProps {
|
||||
environment: Environment;
|
||||
}
|
||||
|
||||
const EnvironmentList = function({ environment }: EnvironmentListProps) {
|
||||
const updateEnvironment = useUpdateEnvironment(environment.id)
|
||||
return (
|
||||
<div>
|
||||
<h1>{environment.name}</h1>
|
||||
<Editor
|
||||
contentType="application/json"
|
||||
className='w-full h-[400px] !bg-gray-50'
|
||||
defaultValue={JSON.stringify(environment.data, null, 2)}
|
||||
onChange={data => {
|
||||
try {
|
||||
updateEnvironment.mutate({ data: JSON.parse(data) });
|
||||
} catch (err) {
|
||||
// That's okay
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -54,11 +54,11 @@ export function Dialog({
|
||||
className={classnames(
|
||||
className,
|
||||
'relative bg-gray-50 pointer-events-auto',
|
||||
'max-h-[80vh] p-5 rounded-lg overflow-auto',
|
||||
'p-5 rounded-lg overflow-auto',
|
||||
'dark:border border-highlight shadow shadow-black/10',
|
||||
size === 'sm' && 'w-[25rem]',
|
||||
size === 'md' && 'w-[45rem]',
|
||||
size === 'full' && 'w-[80vw]',
|
||||
size === 'sm' && 'w-[25rem] max-h-[80vh]',
|
||||
size === 'md' && 'w-[45rem] max-h-[80vh]',
|
||||
size === 'full' && 'w-[calc(100vw-8em)] h-[calc(100vh-8em)]',
|
||||
size === 'dynamic' && 'min-w-[30vw] max-w-[80vw]',
|
||||
)}
|
||||
>
|
||||
@@ -66,7 +66,7 @@ export function Dialog({
|
||||
{title}
|
||||
</Heading>
|
||||
{description && <p id={descriptionId}>{description}</p>}
|
||||
<div className="mt-4">{children}</div>
|
||||
<div className="h-full w-full mt-4">{children}</div>
|
||||
|
||||
{/*Put close at the end so that it's the last thing to be tabbed to*/}
|
||||
{!hideX && (
|
||||
|
||||
22
src-web/hooks/useCreateEnvironment.ts
Normal file
22
src-web/hooks/useCreateEnvironment.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import type { Environment } from '../lib/models';
|
||||
import { environmentsQueryKey } from './useEnvironments';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
|
||||
export function useCreateEnvironment() {
|
||||
const workspaceId = useActiveWorkspaceId();
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<Environment, unknown, Pick<Environment, 'name'>>({
|
||||
mutationFn: (patch) => {
|
||||
return invoke('create_environment', { ...patch, workspaceId });
|
||||
},
|
||||
onSuccess: async (environment) => {
|
||||
if (workspaceId == null) return;
|
||||
queryClient.setQueryData<Environment[]>(environmentsQueryKey({ workspaceId }), (environments) => [
|
||||
...(environments ?? []),
|
||||
environment,
|
||||
]);
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user