Updating environments!

This commit is contained in:
Gregory Schier
2023-10-22 22:06:51 -07:00
parent 5cf59d7d70
commit 51f48d3883
12 changed files with 155 additions and 52 deletions

2
.nvmrc
View File

@@ -1 +1 @@
18
20

4
Makefile Normal file
View File

@@ -0,0 +1,4 @@
.PHONY: sqlx-prepare
sqlx-prepare:
cd src-tauri && cargo sqlx prepare --database-url 'sqlite://db.sqlite'

View File

@@ -378,6 +378,16 @@
},
"query": "\n SELECT\n id,\n model,\n workspace_id,\n created_at,\n updated_at,\n name,\n url,\n method,\n body,\n body_type,\n authentication AS \"authentication!: Json<HashMap<String, JsonValue>>\",\n authentication_type,\n sort_priority,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpRequestHeader>>\"\n FROM http_requests\n WHERE workspace_id = ?\n "
},
"80bc37d283b67a70919c7b03a106fe563829741fb2c2fbd34ae4d8f581ecb697": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 2
}
},
"query": "\n UPDATE environments\n SET (data, updated_at) = (?, CURRENT_TIMESTAMP)\n WHERE id = ?;\n "
},
"84be2b954870ab181738656ecd4d03fca2ff21012947014c79626abfce8e999b": {
"describe": {
"columns": [],

View File

@@ -396,6 +396,22 @@ async fn update_workspace(
emit_and_return(&window, "updated_model", updated_workspace)
}
#[tauri::command]
async fn update_environment(
environment: models::Environment,
window: Window<Wry>,
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
) -> Result<models::Environment, String> {
let pool = &*db_instance.lock().await;
let updated_environment =
models::update_environment(environment.id.as_str(), environment.data.0, pool)
.await
.expect("Failed to update request");
emit_and_return(&window, "updated_model", updated_environment)
}
#[tauri::command]
async fn update_request(
request: models::HttpRequest,
@@ -449,7 +465,7 @@ async fn delete_request(
}
#[tauri::command]
async fn requests(
async fn list_requests(
workspace_id: &str,
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
) -> Result<Vec<models::HttpRequest>, String> {
@@ -460,7 +476,7 @@ async fn requests(
}
#[tauri::command]
async fn environments(
async fn list_environments(
workspace_id: &str,
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
) -> Result<Vec<models::Environment>, String> {
@@ -493,6 +509,17 @@ async fn get_request(
.map_err(|e| e.to_string())
}
#[tauri::command]
async fn get_environment(
id: &str,
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
) -> Result<models::Environment, String> {
let pool = &*db_instance.lock().await;
models::get_environment(id, pool)
.await
.map_err(|e| e.to_string())
}
#[tauri::command]
async fn get_workspace(
id: &str,
@@ -505,7 +532,7 @@ async fn get_workspace(
}
#[tauri::command]
async fn responses(
async fn list_responses(
request_id: &str,
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
) -> Result<Vec<models::HttpResponse>, String> {
@@ -540,7 +567,7 @@ async fn delete_all_responses(
}
#[tauri::command]
async fn workspaces(
async fn list_workspaces(
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
) -> Result<Vec<models::Workspace>, String> {
let pool = &*db_instance.lock().await;
@@ -607,26 +634,28 @@ fn main() {
})
})
.invoke_handler(tauri::generate_handler![
workspaces,
environments,
requests,
responses,
new_window,
get_request,
send_request,
send_ephemeral_request,
duplicate_request,
create_request,
get_workspace,
create_workspace,
delete_workspace,
update_workspace,
update_request,
delete_request,
get_key_value,
set_key_value,
delete_response,
delete_all_responses,
delete_request,
delete_response,
delete_workspace,
duplicate_request,
get_key_value,
get_environment,
get_request,
get_workspace,
list_environments,
list_requests,
list_responses,
list_workspaces,
new_window,
send_ephemeral_request,
send_request,
set_key_value,
update_environment,
update_request,
update_workspace,
])
.build(tauri::generate_context!())
.expect("error while running tauri application")

View File

@@ -252,6 +252,27 @@ pub async fn create_environment(
get_environment(&id, pool).await
}
pub async fn update_environment(
id: &str,
data: HashMap<String, JsonValue>,
pool: &Pool<Sqlite>,
) -> Result<Environment, sqlx::Error> {
println!("DATA: {}", data.clone().len());
let json_data = Json(data);
sqlx::query!(
r#"
UPDATE environments
SET (data, updated_at) = (?, CURRENT_TIMESTAMP)
WHERE id = ?;
"#,
json_data,
id,
)
.execute(pool)
.await?;
get_environment(id, pool).await
}
pub async fn get_environment(id: &str, pool: &Pool<Sqlite>) -> Result<Environment, sqlx::Error> {
sqlx::query_as!(
Environment,

View File

@@ -12,6 +12,7 @@ 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';
interface Props {
className?: string;
@@ -19,6 +20,7 @@ interface Props {
export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) {
const environments = useEnvironments();
const updateEnvironment = useUpdateEnvironment();
const activeRequest = useActiveRequest();
const dialog = useDialog();
@@ -34,12 +36,14 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
<Button onClick={() => {
dialog.show({
title: 'Environments',
render: () => <EnvironmentList
environments={environments}
onChange={data => {
console.log('data', data);
}}
render: () => <div>
{environments.map(e => (
<EnvironmentList
key={e.id}
environment={e}
/>
))}
</div>
})
}}>
Environments
@@ -65,25 +69,22 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
});
interface EnvironmentListProps {
environments: Environment[];
onChange: (data: string) => void;
environment: Environment;
}
const EnvironmentList = function({ environments, onChange }: EnvironmentListProps) {
// For some reason useActiveWorkspaceId() doesn't work in modals (?)
return <ul className="inline">
{environments.map(e => (
<li key={e.id}>
const EnvironmentList = function({ environment }: EnvironmentListProps) {
const updateEnvironment = useUpdateEnvironment(environment.id)
return (
<div>
{e.name}
</div>
<h1>{environment.name}</h1>
<Editor
contentType="application/json"
className='w-full h-[400px] !bg-gray-50'
defaultValue={JSON.stringify(e.data, null, 2)}
onChange={onChange}
defaultValue={JSON.stringify(environment.data, null, 2)}
onChange={data => {
updateEnvironment.mutate({ data: JSON.parse(data) });
}}
/>
</li>
))}
</ul>
</div>
);
};

View File

@@ -15,7 +15,7 @@ export function useEnvironments() {
queryKey: environmentsQueryKey({ workspaceId: workspaceId ?? 'n/a' }),
queryFn: async () => {
if (workspaceId == null) return [];
return (await invoke('environments', { workspaceId })) as Environment[];
return (await invoke('list_environments', { workspaceId })) as Environment[];
},
}).data ?? []
);

View File

@@ -15,7 +15,7 @@ export function useRequests() {
queryKey: requestsQueryKey({ workspaceId: workspaceId ?? 'n/a' }),
queryFn: async () => {
if (workspaceId == null) return [];
return (await invoke('requests', { workspaceId })) as HttpRequest[];
return (await invoke('list_requests', { workspaceId })) as HttpRequest[];
},
}).data ?? []
);

View File

@@ -13,7 +13,7 @@ export function useResponses(requestId: string | null) {
initialData: [],
queryKey: responsesQueryKey({ requestId: requestId ?? 'n/a' }),
queryFn: async () => {
return (await invoke('responses', {
return (await invoke('list_responses', {
requestId,
})) as HttpResponse[];
},

View File

@@ -0,0 +1,29 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { invoke } from '@tauri-apps/api';
import type { Environment } from '../lib/models';
import { getEnvironment } from '../lib/store';
import { environmentsQueryKey } from './useEnvironments';
export function useUpdateEnvironment(id: string | null) {
const queryClient = useQueryClient();
return useMutation<void, unknown, Partial<Environment> | ((r: Environment) => Environment)>({
mutationFn: async (v) => {
const environment = await getEnvironment(id);
if (environment == null) {
throw new Error("Can't update a null environment");
}
const newEnvironment = typeof v === 'function' ? v(environment) : { ...environment, ...v };
await invoke('update_environment', { environment: newEnvironment });
},
onMutate: async (v) => {
const environment = await getEnvironment(id);
if (environment === null) return;
const newEnvironment = typeof v === 'function' ? v(environment) : { ...environment, ...v };
queryClient.setQueryData<Environment[]>(environmentsQueryKey(environment), (environments) =>
(environments ?? []).map((r) => (r.id === newEnvironment.id ? newEnvironment : r)),
);
},
});
}

View File

@@ -10,7 +10,7 @@ export function workspacesQueryKey(_?: {}) {
export function useWorkspaces() {
return (
useQuery(workspacesQueryKey(), async () => {
return (await invoke('workspaces')) as Workspace[];
return (await invoke('list_workspaces')) as Workspace[];
}).data ?? []
);
}

View File

@@ -1,5 +1,5 @@
import { invoke } from '@tauri-apps/api';
import type { HttpRequest, Workspace } from './models';
import type { Environment, HttpRequest, Workspace } from './models';
export async function getRequest(id: string | null): Promise<HttpRequest | null> {
if (id === null) return null;
@@ -10,6 +10,15 @@ export async function getRequest(id: string | null): Promise<HttpRequest | null>
return request;
}
export async function getEnvironment(id: string | null): Promise<Environment | null> {
if (id === null) return null;
const environment: Environment = (await invoke('get_environment', { id })) ?? null;
if (environment == null) {
return null;
}
return environment;
}
export async function getWorkspace(id: string | null): Promise<Workspace | null> {
if (id === null) return null;
const workspace: Workspace = (await invoke('get_workspace', { id })) ?? null;