mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-23 01:49:13 +01:00
Add folder model
This commit is contained in:
4
Makefile
4
Makefile
@@ -1,4 +1,4 @@
|
||||
.PHONY: sqlx-prepare, dev
|
||||
.PHONY: sqlx-prepare, dev, migrate, build
|
||||
|
||||
sqlx-prepare:
|
||||
cd src-tauri && cargo sqlx prepare --database-url 'sqlite://db.sqlite'
|
||||
@@ -6,6 +6,8 @@ sqlx-prepare:
|
||||
dev:
|
||||
npm run tauri-dev
|
||||
|
||||
migrate:
|
||||
cd src-tauri && cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
|
||||
|
||||
build:
|
||||
./node_modules/.bin/tauri build
|
||||
|
||||
19
src-tauri/migrations/20231103142807_folders.sql
Normal file
19
src-tauri/migrations/20231103142807_folders.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
CREATE TABLE folders
|
||||
(
|
||||
id TEXT NOT NULL
|
||||
PRIMARY KEY,
|
||||
model TEXT DEFAULT 'folder' NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
deleted_at DATETIME,
|
||||
workspace_id TEXT NOT NULL
|
||||
REFERENCES workspaces
|
||||
ON DELETE CASCADE,
|
||||
folder_id TEXT NULL
|
||||
REFERENCES folders
|
||||
ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
sort_priority REAL DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE http_requests ADD COLUMN folder_id TEXT REFERENCES folders(id) ON DELETE CASCADE;
|
||||
@@ -1,5 +1,15 @@
|
||||
{
|
||||
"db": "SQLite",
|
||||
"02506ad41cc94cd937422ef1977a97174431f008a9fb4ce39667d587a858b876": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"nullable": [],
|
||||
"parameters": {
|
||||
"Right": 5
|
||||
}
|
||||
},
|
||||
"query": "\n INSERT INTO folders (\n id,\n workspace_id,\n folder_id,\n name,\n sort_priority\n )\n VALUES (?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n folder_id = excluded.folder_id,\n sort_priority = excluded.sort_priority\n "
|
||||
},
|
||||
"06aaf8f4a17566f1d25da2a60f0baf4b5fc28c3cf0c001a84e25edf9eab3c7e3": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
@@ -58,6 +68,126 @@
|
||||
},
|
||||
"query": "\n DELETE FROM http_responses\n WHERE id = ?\n "
|
||||
},
|
||||
"1428d25b6aa3d6ec55742a968571fa951da0406d7bb32408883c584eae7dd53c": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "model",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "workspace_id",
|
||||
"ordinal": 2,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"ordinal": 3,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "updated_at",
|
||||
"ordinal": 4,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "folder_id",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "sort_priority",
|
||||
"ordinal": 7,
|
||||
"type_info": "Float"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"query": "\n SELECT\n id,\n model,\n workspace_id,\n created_at,\n updated_at,\n folder_id,\n name,\n sort_priority\n FROM folders\n WHERE id = ?\n "
|
||||
},
|
||||
"1517b0f86c841b5f1247bd40c3a9b38ab001d846a410b6e3cd36f9e844d50ddb": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "model",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "workspace_id",
|
||||
"ordinal": 2,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"ordinal": 3,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "updated_at",
|
||||
"ordinal": 4,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "folder_id",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "sort_priority",
|
||||
"ordinal": 7,
|
||||
"type_info": "Float"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"query": "\n SELECT\n id,\n model,\n workspace_id,\n created_at,\n updated_at,\n folder_id,\n name,\n sort_priority\n FROM folders\n WHERE workspace_id = ?\n "
|
||||
},
|
||||
"26072725d536c3cfdffd9a681d17c0ee2f246ca98e0459630a2430236d3bbdd2": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
@@ -400,7 +530,17 @@
|
||||
},
|
||||
"query": "\n SELECT\n id,\n model,\n workspace_id,\n created_at,\n updated_at,\n name,\n variables AS \"variables!: sqlx::types::Json<Vec<EnvironmentVariable>>\"\n FROM environments\n WHERE id = ?\n "
|
||||
},
|
||||
"6f0cb5a6d1e8dbc8cdfcc3c7e7944b2c83c22cb795b9d6b98fe067dabec9680b": {
|
||||
"84be2b954870ab181738656ecd4d03fca2ff21012947014c79626abfce8e999b": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"nullable": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"query": "\n DELETE FROM workspaces\n WHERE id = ?\n "
|
||||
},
|
||||
"854536c80af3f86bb9a63b8ce059ad724374b545cb23481bb3b2ce07d7414220": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -419,58 +559,63 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"name": "folder_id",
|
||||
"ordinal": 3,
|
||||
"type_info": "Datetime"
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "updated_at",
|
||||
"name": "created_at",
|
||||
"ordinal": 4,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"name": "updated_at",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "url",
|
||||
"name": "name",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "method",
|
||||
"name": "url",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"name": "method",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "body_type",
|
||||
"name": "body",
|
||||
"ordinal": 9,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||
"name": "body_type",
|
||||
"ordinal": 10,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "authentication_type",
|
||||
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "sort_priority",
|
||||
"name": "authentication_type",
|
||||
"ordinal": 12,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "sort_priority",
|
||||
"ordinal": 13,
|
||||
"type_info": "Float"
|
||||
},
|
||||
{
|
||||
"name": "headers!: sqlx::types::Json<Vec<HttpRequestHeader>>",
|
||||
"ordinal": 13,
|
||||
"ordinal": 14,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
@@ -478,6 +623,7 @@
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
@@ -494,17 +640,7 @@
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"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 "
|
||||
},
|
||||
"84be2b954870ab181738656ecd4d03fca2ff21012947014c79626abfce8e999b": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"nullable": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"query": "\n DELETE FROM workspaces\n WHERE id = ?\n "
|
||||
"query": "\n SELECT\n id,\n model,\n workspace_id,\n folder_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 id = ?\n "
|
||||
},
|
||||
"8947a2a90478277c42fe9b06bc1fa98197642a4d281a3dbc101be2c9c1fec36c": {
|
||||
"describe": {
|
||||
@@ -516,6 +652,118 @@
|
||||
},
|
||||
"query": "\n INSERT INTO http_responses (\n id,\n request_id,\n workspace_id,\n elapsed,\n url,\n status,\n status_reason,\n content_length,\n body,\n body_path,\n headers\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\n "
|
||||
},
|
||||
"93aea3881dffb70a82325263740a0bb6477e78f27991ce7456b394e84383acb6": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"nullable": [],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"query": "\n DELETE FROM folders\n WHERE id = ?\n "
|
||||
},
|
||||
"a558e182f40286fe52bed5f03b2dc367b7229ab6bd9cda0a7ce219a438ccd5fd": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "model",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "workspace_id",
|
||||
"ordinal": 2,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "folder_id",
|
||||
"ordinal": 3,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"ordinal": 4,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "updated_at",
|
||||
"ordinal": 5,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "url",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "method",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"ordinal": 9,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "body_type",
|
||||
"ordinal": 10,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "authentication_type",
|
||||
"ordinal": 12,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "sort_priority",
|
||||
"ordinal": 13,
|
||||
"type_info": "Float"
|
||||
},
|
||||
{
|
||||
"name": "headers!: sqlx::types::Json<Vec<HttpRequestHeader>>",
|
||||
"ordinal": 14,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"query": "\n SELECT\n id,\n model,\n workspace_id,\n folder_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 "
|
||||
},
|
||||
"aeb0712785a9964d516dc8939bc54aa8206ad852e608b362d014b67a0f21b0ed": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
@@ -526,16 +774,6 @@
|
||||
},
|
||||
"query": "\n DELETE FROM environments\n WHERE id = ?\n "
|
||||
},
|
||||
"b19c275180909a39342b13c3cdcf993781636913ae590967f5508c46a56dc961": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"nullable": [],
|
||||
"parameters": {
|
||||
"Right": 11
|
||||
}
|
||||
},
|
||||
"query": "\n INSERT INTO http_requests (\n id,\n workspace_id,\n name,\n url,\n method,\n body,\n body_type,\n authentication,\n authentication_type,\n headers,\n sort_priority\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n method = excluded.method,\n headers = excluded.headers,\n body = excluded.body,\n body_type = excluded.body_type,\n authentication = excluded.authentication,\n authentication_type = excluded.authentication_type,\n url = excluded.url,\n sort_priority = excluded.sort_priority\n "
|
||||
},
|
||||
"ba2b34a77723f24f86e4c3c45274dbfec6ca130e16e592f948844c037bdc0593": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
@@ -692,102 +930,6 @@
|
||||
},
|
||||
"query": "\n SELECT id, model, workspace_id, request_id, updated_at, created_at, url,\n status, status_reason, content_length, body, body_path, elapsed, error,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE id = ?\n "
|
||||
},
|
||||
"ced098adb79c0ee64e223b6e02371ef253920a2c342275de0fa9c181529a4adc": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "model",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "workspace_id",
|
||||
"ordinal": 2,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"ordinal": 3,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "updated_at",
|
||||
"ordinal": 4,
|
||||
"type_info": "Datetime"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"ordinal": 5,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "url",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "method",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "body_type",
|
||||
"ordinal": 9,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "authentication!: Json<HashMap<String, JsonValue>>",
|
||||
"ordinal": 10,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "authentication_type",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "sort_priority",
|
||||
"ordinal": 12,
|
||||
"type_info": "Float"
|
||||
},
|
||||
{
|
||||
"name": "headers!: sqlx::types::Json<Vec<HttpRequestHeader>>",
|
||||
"ordinal": 13,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
}
|
||||
},
|
||||
"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 id = ?\n "
|
||||
},
|
||||
"d80c09497771e3641022e73ec6c6a87e73a551f88a948a5445d754922b82b50b": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
@@ -861,5 +1003,15 @@
|
||||
}
|
||||
},
|
||||
"query": "\n INSERT INTO environments (\n id,\n workspace_id,\n name,\n variables\n )\n VALUES (?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n variables = excluded.variables\n "
|
||||
},
|
||||
"e5b410442b00ee354bb58eb0e8fb2af06e9dea4bb24763d717c72a840450a759": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"nullable": [],
|
||||
"parameters": {
|
||||
"Right": 12
|
||||
}
|
||||
},
|
||||
"query": "\n INSERT INTO http_requests (\n id,\n workspace_id,\n folder_id,\n name,\n url,\n method,\n body,\n body_type,\n authentication,\n authentication_type,\n headers,\n sort_priority\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n folder_id = excluded.folder_id,\n method = excluded.method,\n headers = excluded.headers,\n body = excluded.body,\n body_type = excluded.body_type,\n authentication = excluded.authentication,\n authentication_type = excluded.authentication_type,\n url = excluded.url,\n sort_priority = excluded.sort_priority\n "
|
||||
}
|
||||
}
|
||||
@@ -492,6 +492,69 @@ async fn delete_request(
|
||||
emit_and_return(&window, "deleted_model", req)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn list_folders(
|
||||
workspace_id: &str,
|
||||
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<Vec<models::Folder>, String> {
|
||||
let pool = &*db_instance.lock().await;
|
||||
models::find_folders(workspace_id, pool)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn create_folder(
|
||||
workspace_id: &str,
|
||||
name: &str,
|
||||
sort_priority: f64,
|
||||
folder_id: Option<&str>,
|
||||
window: Window<Wry>,
|
||||
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<models::Folder, String> {
|
||||
let pool = &*db_instance.lock().await;
|
||||
let created_request = models::upsert_folder(
|
||||
pool,
|
||||
models::Folder {
|
||||
workspace_id: workspace_id.to_string(),
|
||||
name: name.to_string(),
|
||||
folder_id: folder_id.map(|s| s.to_string()),
|
||||
sort_priority,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create folder");
|
||||
|
||||
emit_and_return(&window, "created_model", created_request)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn update_folder(
|
||||
folder: models::Folder,
|
||||
window: Window<Wry>,
|
||||
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<models::Folder, String> {
|
||||
let pool = &*db_instance.lock().await;
|
||||
let updated_folder = models::upsert_folder(pool, folder)
|
||||
.await
|
||||
.expect("Failed to update request");
|
||||
emit_and_return(&window, "updated_model", updated_folder)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn delete_folder(
|
||||
window: Window<Wry>,
|
||||
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
folder_id: &str,
|
||||
) -> Result<models::Folder, String> {
|
||||
let pool = &*db_instance.lock().await;
|
||||
let req = models::delete_folder(folder_id, pool)
|
||||
.await
|
||||
.expect("Failed to delete folder");
|
||||
emit_and_return(&window, "deleted_model", req)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn delete_environment(
|
||||
window: Window<Wry>,
|
||||
@@ -529,6 +592,17 @@ async fn list_environments(
|
||||
Ok(environments)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_folder(
|
||||
id: &str,
|
||||
db_instance: State<'_, Mutex<Pool<Sqlite>>>,
|
||||
) -> Result<models::Folder, String> {
|
||||
let pool = &*db_instance.lock().await;
|
||||
models::get_folder(id, pool)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_request(
|
||||
id: &str,
|
||||
@@ -705,20 +779,24 @@ fn main() {
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
create_environment,
|
||||
create_folder,
|
||||
create_request,
|
||||
create_workspace,
|
||||
delete_all_responses,
|
||||
delete_environment,
|
||||
delete_folder,
|
||||
delete_request,
|
||||
delete_response,
|
||||
delete_workspace,
|
||||
duplicate_request,
|
||||
get_key_value,
|
||||
get_environment,
|
||||
get_folder,
|
||||
get_request,
|
||||
get_workspace,
|
||||
import_data,
|
||||
list_environments,
|
||||
list_folders,
|
||||
list_requests,
|
||||
list_responses,
|
||||
list_workspaces,
|
||||
@@ -727,6 +805,7 @@ fn main() {
|
||||
send_request,
|
||||
set_key_value,
|
||||
update_environment,
|
||||
update_folder,
|
||||
update_request,
|
||||
update_workspace,
|
||||
])
|
||||
|
||||
@@ -64,6 +64,7 @@ pub struct HttpRequest {
|
||||
pub updated_at: NaiveDateTime,
|
||||
pub id: String,
|
||||
pub workspace_id: String,
|
||||
pub folder_id: Option<String>,
|
||||
pub model: String,
|
||||
pub sort_priority: f64,
|
||||
pub name: String,
|
||||
@@ -77,6 +78,19 @@ pub struct HttpRequest {
|
||||
pub headers: Json<Vec<HttpRequestHeader>>,
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow, Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
pub struct Folder {
|
||||
pub created_at: NaiveDateTime,
|
||||
pub updated_at: NaiveDateTime,
|
||||
pub id: String,
|
||||
pub workspace_id: String,
|
||||
pub folder_id: Option<String>,
|
||||
pub model: String,
|
||||
pub name: String,
|
||||
pub sort_priority: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
pub struct HttpResponseHeader {
|
||||
@@ -292,6 +306,103 @@ pub async fn get_environment(id: &str, pool: &Pool<Sqlite>) -> Result<Environmen
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_folder(id: &str, pool: &Pool<Sqlite>) -> Result<Folder, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Folder,
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
model,
|
||||
workspace_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
folder_id,
|
||||
name,
|
||||
sort_priority
|
||||
FROM folders
|
||||
WHERE id = ?
|
||||
"#,
|
||||
id,
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_folders(
|
||||
workspace_id: &str,
|
||||
pool: &Pool<Sqlite>,
|
||||
) -> Result<Vec<Folder>, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
Folder,
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
model,
|
||||
workspace_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
folder_id,
|
||||
name,
|
||||
sort_priority
|
||||
FROM folders
|
||||
WHERE workspace_id = ?
|
||||
"#,
|
||||
workspace_id,
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_folder(id: &str, pool: &Pool<Sqlite>) -> Result<Folder, sqlx::Error> {
|
||||
let env = get_folder(id, pool).await?;
|
||||
let _ = sqlx::query!(
|
||||
r#"
|
||||
DELETE FROM folders
|
||||
WHERE id = ?
|
||||
"#,
|
||||
id,
|
||||
)
|
||||
.execute(pool)
|
||||
.await;
|
||||
|
||||
Ok(env)
|
||||
}
|
||||
|
||||
pub async fn upsert_folder(pool: &Pool<Sqlite>, r: Folder) -> Result<Folder, sqlx::Error> {
|
||||
let id = match r.id.as_str() {
|
||||
"" => generate_id(Some("fl")),
|
||||
_ => r.id.to_string(),
|
||||
};
|
||||
let trimmed_name = r.name.trim();
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO folders (
|
||||
id,
|
||||
workspace_id,
|
||||
folder_id,
|
||||
name,
|
||||
sort_priority
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
updated_at = CURRENT_TIMESTAMP,
|
||||
name = excluded.name,
|
||||
folder_id = excluded.folder_id,
|
||||
sort_priority = excluded.sort_priority
|
||||
"#,
|
||||
id,
|
||||
r.workspace_id,
|
||||
r.folder_id,
|
||||
trimmed_name,
|
||||
r.sort_priority,
|
||||
)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
get_folder(&id, pool).await
|
||||
}
|
||||
|
||||
pub async fn duplicate_request(id: &str, pool: &Pool<Sqlite>) -> Result<HttpRequest, sqlx::Error> {
|
||||
let mut request = get_request(id, pool).await?.clone();
|
||||
request.id = "".to_string();
|
||||
@@ -315,6 +426,7 @@ pub async fn upsert_request(
|
||||
INSERT INTO http_requests (
|
||||
id,
|
||||
workspace_id,
|
||||
folder_id,
|
||||
name,
|
||||
url,
|
||||
method,
|
||||
@@ -325,10 +437,11 @@ pub async fn upsert_request(
|
||||
headers,
|
||||
sort_priority
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
updated_at = CURRENT_TIMESTAMP,
|
||||
name = excluded.name,
|
||||
folder_id = excluded.folder_id,
|
||||
method = excluded.method,
|
||||
headers = excluded.headers,
|
||||
body = excluded.body,
|
||||
@@ -340,6 +453,7 @@ pub async fn upsert_request(
|
||||
"#,
|
||||
id,
|
||||
r.workspace_id,
|
||||
r.folder_id,
|
||||
trimmed_name,
|
||||
r.url,
|
||||
r.method,
|
||||
@@ -367,6 +481,7 @@ pub async fn find_requests(
|
||||
id,
|
||||
model,
|
||||
workspace_id,
|
||||
folder_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
name,
|
||||
@@ -395,6 +510,7 @@ pub async fn get_request(id: &str, pool: &Pool<Sqlite>) -> Result<HttpRequest, s
|
||||
id,
|
||||
model,
|
||||
workspace_id,
|
||||
folder_id,
|
||||
created_at,
|
||||
updated_at,
|
||||
name,
|
||||
|
||||
@@ -154,11 +154,7 @@ export const Sidebar = memo(function Sidebar({ className }: Props) {
|
||||
|
||||
return (
|
||||
<div aria-hidden={hidden} className="h-full">
|
||||
<VStack
|
||||
as="ul"
|
||||
role="menu"
|
||||
aria-orientation="vertical"
|
||||
dir="ltr"
|
||||
<aside
|
||||
ref={sidebarRef}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
@@ -175,7 +171,7 @@ export const Sidebar = memo(function Sidebar({ className }: Props) {
|
||||
onSelect={handleSelect}
|
||||
onClearSelected={handleClearSelected}
|
||||
/>
|
||||
</VStack>
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -242,7 +238,7 @@ function SidebarItems({
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<VStack as="ul" role="menu" aria-orientation="vertical" dir="ltr">
|
||||
{requests.map((r, i) => (
|
||||
<Fragment key={r.id}>
|
||||
{hoveredIndex === i && <DropMarker />}
|
||||
@@ -259,7 +255,25 @@ function SidebarItems({
|
||||
</Fragment>
|
||||
))}
|
||||
{hoveredIndex === requests.length && <DropMarker />}
|
||||
</>
|
||||
<VStack as="ul" role="menu" aria-orientation="vertical" dir="ltr" className="pl-3">
|
||||
{requests.slice(0, 1).map((r, i) => (
|
||||
<Fragment key={r.id}>
|
||||
{hoveredIndex === i && <DropMarker />}
|
||||
<DraggableSidebarItem
|
||||
key={r.id}
|
||||
selected={selectedIndex === i}
|
||||
requestId={r.id}
|
||||
requestName={r.name}
|
||||
onMove={handleMove}
|
||||
onEnd={handleEnd}
|
||||
useProminentStyles={focused}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
</Fragment>
|
||||
))}
|
||||
{hoveredIndex === requests.length && <DropMarker />}
|
||||
</VStack>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
22
src-web/hooks/useFolders.ts
Normal file
22
src-web/hooks/useFolders.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import type { Folder, HttpRequest } from '../lib/models';
|
||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||
|
||||
export function foldersQueryKey({ workspaceId }: { workspaceId: string }) {
|
||||
return ['folders', { workspaceId }];
|
||||
}
|
||||
|
||||
export function useFolders() {
|
||||
const workspaceId = useActiveWorkspaceId();
|
||||
return (
|
||||
useQuery({
|
||||
enabled: workspaceId != null,
|
||||
queryKey: foldersQueryKey({ workspaceId: workspaceId ?? 'n/a' }),
|
||||
queryFn: async () => {
|
||||
if (workspaceId == null) return [];
|
||||
return (await invoke('list_folders', { workspaceId })) as Folder[];
|
||||
},
|
||||
}).data ?? []
|
||||
);
|
||||
}
|
||||
@@ -29,6 +29,14 @@ export interface EnvironmentVariable {
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface Folder extends BaseModel {
|
||||
readonly workspaceId: string;
|
||||
readonly model: 'folder';
|
||||
folderId: string | null;
|
||||
sortPriority: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Environment extends BaseModel {
|
||||
readonly workspaceId: string;
|
||||
readonly model: 'environment';
|
||||
@@ -45,6 +53,7 @@ export interface HttpHeader {
|
||||
export interface HttpRequest extends BaseModel {
|
||||
readonly workspaceId: string;
|
||||
readonly model: 'http_request';
|
||||
folderId: string | null;
|
||||
sortPriority: number;
|
||||
name: string;
|
||||
url: string;
|
||||
|
||||
Reference in New Issue
Block a user