mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-05 08:47:05 +02:00
Import from Curl
This commit is contained in:
@@ -5,56 +5,57 @@ extern crate objc;
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
use std::fs::{create_dir_all, read_to_string, File};
|
use std::fs;
|
||||||
|
use std::fs::{create_dir_all, File, read_to_string};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use ::http::uri::InvalidUri;
|
|
||||||
use ::http::Uri;
|
use ::http::Uri;
|
||||||
|
use ::http::uri::InvalidUri;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use fern::colors::ColoredLevelConfig;
|
use fern::colors::ColoredLevelConfig;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use rand::random;
|
use rand::random;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use sqlx::{Pool, Sqlite, SqlitePool};
|
||||||
use sqlx::migrate::Migrator;
|
use sqlx::migrate::Migrator;
|
||||||
use sqlx::sqlite::SqliteConnectOptions;
|
use sqlx::sqlite::SqliteConnectOptions;
|
||||||
use sqlx::types::Json;
|
use sqlx::types::Json;
|
||||||
use sqlx::{Pool, Sqlite, SqlitePool};
|
use tauri::{AppHandle, RunEvent, State, WebviewUrl, WebviewWindow};
|
||||||
|
use tauri::{Manager, WindowEvent};
|
||||||
use tauri::path::BaseDirectory;
|
use tauri::path::BaseDirectory;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use tauri::TitleBarStyle;
|
use tauri::TitleBarStyle;
|
||||||
use tauri::{AppHandle, RunEvent, State, WebviewUrl, WebviewWindow};
|
|
||||||
use tauri::{Manager, WindowEvent};
|
|
||||||
use tauri_plugin_log::{fern, Target, TargetKind};
|
use tauri_plugin_log::{fern, Target, TargetKind};
|
||||||
use tauri_plugin_shell::ShellExt;
|
use tauri_plugin_shell::ShellExt;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
use ::grpc::{Code, deserialize_message, serialize_message, ServiceDefinition};
|
||||||
use ::grpc::manager::{DynamicMessage, GrpcHandle};
|
use ::grpc::manager::{DynamicMessage, GrpcHandle};
|
||||||
use ::grpc::{deserialize_message, serialize_message, Code, ServiceDefinition};
|
|
||||||
use window_ext::TrafficLightWindowExt;
|
use window_ext::TrafficLightWindowExt;
|
||||||
|
|
||||||
use crate::analytics::{AnalyticsAction, AnalyticsResource};
|
use crate::analytics::{AnalyticsAction, AnalyticsResource};
|
||||||
use crate::grpc::metadata_to_map;
|
use crate::grpc::metadata_to_map;
|
||||||
use crate::http::send_http_request;
|
use crate::http::send_http_request;
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
cancel_pending_grpc_connections, cancel_pending_responses, create_http_response,
|
cancel_pending_grpc_connections, cancel_pending_responses, CookieJar,
|
||||||
delete_all_grpc_connections, delete_all_http_responses, delete_cookie_jar, delete_environment,
|
create_http_response, delete_all_grpc_connections, delete_all_http_responses, delete_cookie_jar,
|
||||||
delete_folder, delete_grpc_connection, delete_grpc_request, delete_http_request,
|
delete_environment, delete_folder, delete_grpc_connection, delete_grpc_request,
|
||||||
delete_http_response, delete_workspace, duplicate_grpc_request, duplicate_http_request,
|
delete_http_request, delete_http_response, delete_workspace, duplicate_grpc_request,
|
||||||
generate_model_id, get_cookie_jar, get_environment, get_folder, get_grpc_connection,
|
duplicate_http_request, Environment, EnvironmentVariable, Folder, generate_model_id,
|
||||||
|
get_cookie_jar, get_environment, get_folder, get_grpc_connection,
|
||||||
get_grpc_request, get_http_request, get_http_response, get_key_value_raw,
|
get_grpc_request, get_http_request, get_http_response, get_key_value_raw,
|
||||||
get_or_create_settings, get_workspace, get_workspace_export_resources, list_cookie_jars,
|
get_or_create_settings, get_workspace, get_workspace_export_resources, GrpcConnection, GrpcEvent,
|
||||||
list_environments, list_folders, list_grpc_connections, list_grpc_events, list_grpc_requests,
|
GrpcEventType, GrpcRequest, HttpRequest, HttpRequestHeader, HttpResponse,
|
||||||
list_http_requests, list_responses, list_workspaces, set_key_value_raw, update_response_if_id,
|
KeyValue, list_cookie_jars, list_environments, list_folders, list_grpc_connections,
|
||||||
update_settings, upsert_cookie_jar, upsert_environment, upsert_folder, upsert_grpc_connection,
|
list_grpc_events, list_grpc_requests, list_http_requests, list_responses, list_workspaces,
|
||||||
upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_workspace, CookieJar,
|
ModelType, set_key_value_raw, Settings, update_response_if_id, update_settings, upsert_cookie_jar,
|
||||||
Environment, EnvironmentVariable, Folder, GrpcConnection, GrpcEvent, GrpcEventType,
|
upsert_environment, upsert_folder, upsert_grpc_connection, upsert_grpc_event, upsert_grpc_request, upsert_http_request, upsert_workspace,
|
||||||
GrpcRequest, HttpRequest, HttpRequestHeader, HttpResponse, KeyValue, ModelType, Settings,
|
|
||||||
Workspace, WorkspaceExportResources,
|
Workspace, WorkspaceExportResources,
|
||||||
};
|
};
|
||||||
use crate::plugin::{run_plugin_export_curl, ImportResult};
|
use crate::plugin::{ImportResult, run_plugin_export_curl, run_plugin_import};
|
||||||
use crate::render::render_request;
|
use crate::render::render_request;
|
||||||
use crate::updates::{update_mode_from_str, UpdateMode, YaakUpdater};
|
use crate::updates::{update_mode_from_str, UpdateMode, YaakUpdater};
|
||||||
use crate::window_menu::app_menu;
|
use crate::window_menu::app_menu;
|
||||||
@@ -736,8 +737,11 @@ async fn cmd_import_data(
|
|||||||
"importer-postman",
|
"importer-postman",
|
||||||
"importer-curl",
|
"importer-curl",
|
||||||
];
|
];
|
||||||
|
let file = fs::read_to_string(file_path)
|
||||||
|
.unwrap_or_else(|_| panic!("Unable to read file {}", file_path));
|
||||||
|
let file_contents = file.as_str();
|
||||||
for plugin_name in plugins {
|
for plugin_name in plugins {
|
||||||
let v = plugin::run_plugin_import(&w.app_handle(), plugin_name, file_path)
|
let v = plugin::run_plugin_import(&w.app_handle(), plugin_name, file_contents)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
if let Some(r) = v {
|
if let Some(r) = v {
|
||||||
@@ -874,6 +878,32 @@ async fn cmd_request_to_curl(
|
|||||||
Ok(run_plugin_export_curl(&app, &rendered)?)
|
Ok(run_plugin_export_curl(&app, &rendered)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn cmd_curl_to_request(
|
||||||
|
app: AppHandle,
|
||||||
|
command: &str,
|
||||||
|
workspace_id: &str,
|
||||||
|
) -> Result<HttpRequest, String> {
|
||||||
|
let v = run_plugin_import(&app, "importer-curl", command)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string());
|
||||||
|
match v {
|
||||||
|
Ok(Some(r)) => r
|
||||||
|
.resources
|
||||||
|
.http_requests
|
||||||
|
.get(0)
|
||||||
|
.ok_or("No curl command found".to_string())
|
||||||
|
.map(|r| {
|
||||||
|
let mut request = r.clone();
|
||||||
|
request.workspace_id = workspace_id.into();
|
||||||
|
request.id = "".to_string();
|
||||||
|
request
|
||||||
|
}),
|
||||||
|
Ok(None) => Err("Did not find curl request".to_string()),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_export_data(
|
async fn cmd_export_data(
|
||||||
window: WebviewWindow,
|
window: WebviewWindow,
|
||||||
@@ -1585,6 +1615,7 @@ pub fn run() {
|
|||||||
cmd_create_grpc_request,
|
cmd_create_grpc_request,
|
||||||
cmd_create_http_request,
|
cmd_create_http_request,
|
||||||
cmd_create_workspace,
|
cmd_create_workspace,
|
||||||
|
cmd_curl_to_request,
|
||||||
cmd_delete_all_grpc_connections,
|
cmd_delete_all_grpc_connections,
|
||||||
cmd_delete_all_http_responses,
|
cmd_delete_all_http_responses,
|
||||||
cmd_delete_cookie_jar,
|
cmd_delete_cookie_jar,
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
use std::fs;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use boa_engine::builtins::promise::PromiseState;
|
|
||||||
use boa_engine::{
|
use boa_engine::{
|
||||||
js_string, module::SimpleModuleLoader, property::Attribute, Context, JsNativeError, JsValue,
|
Context, js_string, JsNativeError, JsValue, Module, module::SimpleModuleLoader,
|
||||||
Module, Source,
|
property::Attribute, Source,
|
||||||
};
|
};
|
||||||
|
use boa_engine::builtins::promise::PromiseState;
|
||||||
use boa_runtime::Console;
|
use boa_runtime::Console;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tauri::path::BaseDirectory;
|
|
||||||
use tauri::{AppHandle, Manager};
|
use tauri::{AppHandle, Manager};
|
||||||
|
use tauri::path::BaseDirectory;
|
||||||
|
|
||||||
use crate::models::{HttpRequest, WorkspaceExportResources};
|
use crate::models::{HttpRequest, WorkspaceExportResources};
|
||||||
|
|
||||||
@@ -68,11 +67,8 @@ pub fn run_plugin_export_curl(
|
|||||||
pub async fn run_plugin_import(
|
pub async fn run_plugin_import(
|
||||||
app_handle: &AppHandle,
|
app_handle: &AppHandle,
|
||||||
plugin_name: &str,
|
plugin_name: &str,
|
||||||
file_path: &str,
|
file_contents: &str,
|
||||||
) -> Result<Option<ImportResult>, String> {
|
) -> Result<Option<ImportResult>, String> {
|
||||||
let file = fs::read_to_string(file_path)
|
|
||||||
.unwrap_or_else(|_| panic!("Unable to read file {}", file_path));
|
|
||||||
let file_contents = file.as_str();
|
|
||||||
let result_json = run_plugin(
|
let result_json = run_plugin(
|
||||||
app_handle,
|
app_handle,
|
||||||
plugin_name,
|
plugin_name,
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ import { GraphQLEditor } from './GraphQLEditor';
|
|||||||
import { HeadersEditor } from './HeadersEditor';
|
import { HeadersEditor } from './HeadersEditor';
|
||||||
import { UrlBar } from './UrlBar';
|
import { UrlBar } from './UrlBar';
|
||||||
import { UrlParametersEditor } from './UrlParameterEditor';
|
import { UrlParametersEditor } from './UrlParameterEditor';
|
||||||
|
import { useCurlToRequest } from '../hooks/useCurlToRequest';
|
||||||
|
import { useConfirm } from '../hooks/useConfirm';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
style: CSSProperties;
|
style: CSSProperties;
|
||||||
@@ -227,6 +229,9 @@ export const RequestPane = memo(function RequestPane({
|
|||||||
[updateRequest],
|
[updateRequest],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const importCurl = useCurlToRequest();
|
||||||
|
const confirm = useConfirm();
|
||||||
|
|
||||||
const isLoading = useIsResponseLoading(activeRequestId ?? null);
|
const isLoading = useIsResponseLoading(activeRequestId ?? null);
|
||||||
const { updateKey } = useRequestUpdateKey(activeRequestId ?? null);
|
const { updateKey } = useRequestUpdateKey(activeRequestId ?? null);
|
||||||
|
|
||||||
@@ -241,6 +246,22 @@ export const RequestPane = memo(function RequestPane({
|
|||||||
url={activeRequest.url}
|
url={activeRequest.url}
|
||||||
method={activeRequest.method}
|
method={activeRequest.method}
|
||||||
placeholder="https://example.com"
|
placeholder="https://example.com"
|
||||||
|
onPaste={async (command) => {
|
||||||
|
if (!command.startsWith('curl ')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
await confirm({
|
||||||
|
id: 'paste-curl',
|
||||||
|
title: 'Import from Curl?',
|
||||||
|
description:
|
||||||
|
'Do you want to overwrite the current request with the Curl command?',
|
||||||
|
confirmText: 'Overwrite',
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
importCurl.mutate({ requestId: activeRequestId, command });
|
||||||
|
}
|
||||||
|
}}
|
||||||
onSend={handleSend}
|
onSend={handleSend}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onMethodChange={handleMethodChange}
|
onMethodChange={handleMethodChange}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type Props = Pick<HttpRequest, 'url'> & {
|
|||||||
placeholder: string;
|
placeholder: string;
|
||||||
onSend: () => void;
|
onSend: () => void;
|
||||||
onUrlChange: (url: string) => void;
|
onUrlChange: (url: string) => void;
|
||||||
|
onPaste?: (v: string) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
submitIcon?: IconProps['icon'] | null;
|
submitIcon?: IconProps['icon'] | null;
|
||||||
onMethodChange?: (method: string) => void;
|
onMethodChange?: (method: string) => void;
|
||||||
@@ -31,6 +32,7 @@ export const UrlBar = memo(function UrlBar({
|
|||||||
onSend,
|
onSend,
|
||||||
onCancel,
|
onCancel,
|
||||||
onMethodChange,
|
onMethodChange,
|
||||||
|
onPaste,
|
||||||
submitIcon = 'sendHorizontal',
|
submitIcon = 'sendHorizontal',
|
||||||
isLoading,
|
isLoading,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
@@ -66,6 +68,7 @@ export const UrlBar = memo(function UrlBar({
|
|||||||
forceUpdateKey={forceUpdateKey}
|
forceUpdateKey={forceUpdateKey}
|
||||||
onFocus={() => setIsFocused(true)}
|
onFocus={() => setIsFocused(true)}
|
||||||
onBlur={() => setIsFocused(false)}
|
onBlur={() => setIsFocused(false)}
|
||||||
|
onPaste={onPaste}
|
||||||
containerClassName="shadow shadow-gray-100 dark:shadow-gray-50"
|
containerClassName="shadow shadow-gray-100 dark:shadow-gray-50"
|
||||||
onChange={onUrlChange}
|
onChange={onUrlChange}
|
||||||
defaultValue={url}
|
defaultValue={url}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export interface EditorProps {
|
|||||||
tooltipContainer?: HTMLElement;
|
tooltipContainer?: HTMLElement;
|
||||||
useTemplating?: boolean;
|
useTemplating?: boolean;
|
||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
|
onPaste?: (value: string) => void;
|
||||||
onFocus?: () => void;
|
onFocus?: () => void;
|
||||||
onBlur?: () => void;
|
onBlur?: () => void;
|
||||||
onKeyDown?: (e: KeyboardEvent) => void;
|
onKeyDown?: (e: KeyboardEvent) => void;
|
||||||
@@ -69,6 +70,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
defaultValue,
|
defaultValue,
|
||||||
forceUpdateKey,
|
forceUpdateKey,
|
||||||
onChange,
|
onChange,
|
||||||
|
onPaste,
|
||||||
onFocus,
|
onFocus,
|
||||||
onBlur,
|
onBlur,
|
||||||
onKeyDown,
|
onKeyDown,
|
||||||
@@ -91,25 +93,31 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
const cm = useRef<{ view: EditorView; languageCompartment: Compartment } | null>(null);
|
const cm = useRef<{ view: EditorView; languageCompartment: Compartment } | null>(null);
|
||||||
useImperativeHandle(ref, () => cm.current?.view);
|
useImperativeHandle(ref, () => cm.current?.view);
|
||||||
|
|
||||||
// Use ref so we can update the onChange handler without re-initializing the editor
|
// Use ref so we can update the handler without re-initializing the editor
|
||||||
const handleChange = useRef<EditorProps['onChange']>(onChange);
|
const handleChange = useRef<EditorProps['onChange']>(onChange);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleChange.current = onChange;
|
handleChange.current = onChange;
|
||||||
}, [onChange]);
|
}, [onChange]);
|
||||||
|
|
||||||
// Use ref so we can update the onChange handler without re-initializing the editor
|
// Use ref so we can update the handler without re-initializing the editor
|
||||||
|
const handlePaste = useRef<EditorProps['onPaste']>(onPaste);
|
||||||
|
useEffect(() => {
|
||||||
|
handlePaste.current = onPaste;
|
||||||
|
}, [onPaste]);
|
||||||
|
|
||||||
|
// Use ref so we can update the handler without re-initializing the editor
|
||||||
const handleFocus = useRef<EditorProps['onFocus']>(onFocus);
|
const handleFocus = useRef<EditorProps['onFocus']>(onFocus);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleFocus.current = onFocus;
|
handleFocus.current = onFocus;
|
||||||
}, [onFocus]);
|
}, [onFocus]);
|
||||||
|
|
||||||
// Use ref so we can update the onChange handler without re-initializing the editor
|
// Use ref so we can update the handler without re-initializing the editor
|
||||||
const handleBlur = useRef<EditorProps['onBlur']>(onBlur);
|
const handleBlur = useRef<EditorProps['onBlur']>(onBlur);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleBlur.current = onBlur;
|
handleBlur.current = onBlur;
|
||||||
}, [onBlur]);
|
}, [onBlur]);
|
||||||
|
|
||||||
// Use ref so we can update the onChange handler without re-initializing the editor
|
// Use ref so we can update the handler without re-initializing the editor
|
||||||
const handleKeyDown = useRef<EditorProps['onKeyDown']>(onKeyDown);
|
const handleKeyDown = useRef<EditorProps['onKeyDown']>(onKeyDown);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleKeyDown.current = onKeyDown;
|
handleKeyDown.current = onKeyDown;
|
||||||
@@ -187,6 +195,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
readOnly,
|
readOnly,
|
||||||
singleLine,
|
singleLine,
|
||||||
onChange: handleChange,
|
onChange: handleChange,
|
||||||
|
onPaste: handlePaste,
|
||||||
onFocus: handleFocus,
|
onFocus: handleFocus,
|
||||||
onBlur: handleBlur,
|
onBlur: handleBlur,
|
||||||
onKeyDown: handleKeyDown,
|
onKeyDown: handleKeyDown,
|
||||||
@@ -299,12 +308,14 @@ function getExtensions({
|
|||||||
readOnly,
|
readOnly,
|
||||||
singleLine,
|
singleLine,
|
||||||
onChange,
|
onChange,
|
||||||
|
onPaste,
|
||||||
onFocus,
|
onFocus,
|
||||||
onBlur,
|
onBlur,
|
||||||
onKeyDown,
|
onKeyDown,
|
||||||
}: Pick<EditorProps, 'singleLine' | 'readOnly'> & {
|
}: Pick<EditorProps, 'singleLine' | 'readOnly'> & {
|
||||||
container: HTMLDivElement | null;
|
container: HTMLDivElement | null;
|
||||||
onChange: MutableRefObject<EditorProps['onChange']>;
|
onChange: MutableRefObject<EditorProps['onChange']>;
|
||||||
|
onPaste: MutableRefObject<EditorProps['onPaste']>;
|
||||||
onFocus: MutableRefObject<EditorProps['onFocus']>;
|
onFocus: MutableRefObject<EditorProps['onFocus']>;
|
||||||
onBlur: MutableRefObject<EditorProps['onBlur']>;
|
onBlur: MutableRefObject<EditorProps['onBlur']>;
|
||||||
onKeyDown: MutableRefObject<EditorProps['onKeyDown']>;
|
onKeyDown: MutableRefObject<EditorProps['onKeyDown']>;
|
||||||
@@ -321,6 +332,7 @@ function getExtensions({
|
|||||||
focus: () => onFocus.current?.(),
|
focus: () => onFocus.current?.(),
|
||||||
blur: () => onBlur.current?.(),
|
blur: () => onBlur.current?.(),
|
||||||
keydown: (e) => onKeyDown.current?.(e),
|
keydown: (e) => onKeyDown.current?.(e),
|
||||||
|
paste: (e) => onPaste.current?.(e.clipboardData?.getData('text/plain') ?? ''),
|
||||||
}),
|
}),
|
||||||
tooltips({ parent }),
|
tooltips({ parent }),
|
||||||
keymap.of(singleLine ? defaultKeymap.filter((k) => k.key !== 'Enter') : defaultKeymap),
|
keymap.of(singleLine ? defaultKeymap.filter((k) => k.key !== 'Enter') : defaultKeymap),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { HStack } from './Stacks';
|
|||||||
|
|
||||||
export type InputProps = Omit<
|
export type InputProps = Omit<
|
||||||
HTMLAttributes<HTMLInputElement>,
|
HTMLAttributes<HTMLInputElement>,
|
||||||
'onChange' | 'onFocus' | 'onKeyDown'
|
'onChange' | 'onFocus' | 'onKeyDown' | 'onPaste'
|
||||||
> &
|
> &
|
||||||
Pick<
|
Pick<
|
||||||
EditorProps,
|
EditorProps,
|
||||||
@@ -33,6 +33,7 @@ export type InputProps = Omit<
|
|||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
onFocus?: () => void;
|
onFocus?: () => void;
|
||||||
onBlur?: () => void;
|
onBlur?: () => void;
|
||||||
|
onPaste?: (value: string) => void;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
leftSlot?: ReactNode;
|
leftSlot?: ReactNode;
|
||||||
rightSlot?: ReactNode;
|
rightSlot?: ReactNode;
|
||||||
@@ -59,6 +60,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
|
|||||||
onBlur,
|
onBlur,
|
||||||
onChange,
|
onChange,
|
||||||
onFocus,
|
onFocus,
|
||||||
|
onPaste,
|
||||||
placeholder,
|
placeholder,
|
||||||
require,
|
require,
|
||||||
rightSlot,
|
rightSlot,
|
||||||
@@ -172,6 +174,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
|
|||||||
forceUpdateKey={forceUpdateKey}
|
forceUpdateKey={forceUpdateKey}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onPaste={onPaste}
|
||||||
className={editorClassName}
|
className={editorClassName}
|
||||||
onFocus={handleFocus}
|
onFocus={handleFocus}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export interface ConfirmProps {
|
|||||||
onHide: () => void;
|
onHide: () => void;
|
||||||
onResult: (result: boolean) => void;
|
onResult: (result: boolean) => void;
|
||||||
variant?: 'delete' | 'confirm';
|
variant?: 'delete' | 'confirm';
|
||||||
|
confirmText?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const colors: Record<NonNullable<ConfirmProps['variant']>, ButtonProps['color']> = {
|
const colors: Record<NonNullable<ConfirmProps['variant']>, ButtonProps['color']> = {
|
||||||
@@ -18,7 +19,7 @@ const confirmButtonTexts: Record<NonNullable<ConfirmProps['variant']>, string> =
|
|||||||
confirm: 'Confirm',
|
confirm: 'Confirm',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Confirm({ onHide, onResult, variant = 'confirm' }: ConfirmProps) {
|
export function Confirm({ onHide, onResult, confirmText, variant = 'confirm' }: ConfirmProps) {
|
||||||
const handleHide = () => {
|
const handleHide = () => {
|
||||||
onResult(false);
|
onResult(false);
|
||||||
onHide();
|
onHide();
|
||||||
@@ -32,7 +33,7 @@ export function Confirm({ onHide, onResult, variant = 'confirm' }: ConfirmProps)
|
|||||||
return (
|
return (
|
||||||
<HStack space={2} justifyContent="start" className="mt-2 mb-4 flex-row-reverse">
|
<HStack space={2} justifyContent="start" className="mt-2 mb-4 flex-row-reverse">
|
||||||
<Button className="focus" color={colors[variant]} onClick={handleSuccess}>
|
<Button className="focus" color={colors[variant]} onClick={handleSuccess}>
|
||||||
{confirmButtonTexts[variant]}
|
{confirmText ?? confirmButtonTexts[variant]}
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="focus" color="gray" onClick={handleHide}>
|
<Button className="focus" color="gray" onClick={handleHide}>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ export function useConfirm() {
|
|||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
variant,
|
variant,
|
||||||
|
confirmText,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
title: DialogProps['title'];
|
title: DialogProps['title'];
|
||||||
description?: DialogProps['description'];
|
description?: DialogProps['description'];
|
||||||
variant: ConfirmProps['variant'];
|
variant?: ConfirmProps['variant'];
|
||||||
|
confirmText?: ConfirmProps['confirmText'];
|
||||||
}) =>
|
}) =>
|
||||||
new Promise((onResult: ConfirmProps['onResult']) => {
|
new Promise((onResult: ConfirmProps['onResult']) => {
|
||||||
dialog.show({
|
dialog.show({
|
||||||
@@ -23,7 +25,7 @@ export function useConfirm() {
|
|||||||
description,
|
description,
|
||||||
hideX: true,
|
hideX: true,
|
||||||
size: 'sm',
|
size: 'sm',
|
||||||
render: ({ hide }) => Confirm({ onHide: hide, variant, onResult }),
|
render: ({ hide }) => Confirm({ onHide: hide, variant, onResult, confirmText }),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
24
src-web/hooks/useCurlToRequest.ts
Normal file
24
src-web/hooks/useCurlToRequest.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||||
|
import { useRequestUpdateKey } from './useRequestUpdateKey';
|
||||||
|
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
|
||||||
|
|
||||||
|
export function useCurlToRequest() {
|
||||||
|
const workspaceId = useActiveWorkspaceId();
|
||||||
|
const updateRequest = useUpdateAnyHttpRequest();
|
||||||
|
const { wasUpdatedExternally } = useRequestUpdateKey(null);
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({ requestId, command }: { requestId: string; command: string }) => {
|
||||||
|
const request: Record<string, unknown> = await invoke('cmd_curl_to_request', {
|
||||||
|
command,
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
delete request.id;
|
||||||
|
await updateRequest.mutateAsync({ id: requestId, update: request });
|
||||||
|
wasUpdatedExternally(requestId);
|
||||||
|
console.log('FOO', request);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user