mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 16:02:14 +00:00
feat: add delete flows
This commit is contained in:
@@ -2716,6 +2716,23 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/flows/delete/{path}:
|
||||
delete:
|
||||
summary: delete flow by path
|
||||
operationId: deleteFlowByPath
|
||||
tags:
|
||||
- flow
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/ScriptPath"
|
||||
responses:
|
||||
"200":
|
||||
description: flow delete
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/apps/list:
|
||||
get:
|
||||
summary: list all available apps
|
||||
|
||||
@@ -11,7 +11,7 @@ use sql_builder::prelude::*;
|
||||
|
||||
use axum::{
|
||||
extract::{Extension, Path, Query},
|
||||
routing::{get, post},
|
||||
routing::{delete, get, post},
|
||||
Json, Router,
|
||||
};
|
||||
use sql_builder::SqlBuilder;
|
||||
@@ -41,6 +41,7 @@ pub fn workspaced_service() -> Router {
|
||||
.route("/create", post(create_flow))
|
||||
.route("/update/*path", post(update_flow))
|
||||
.route("/archive/*path", post(archive_flow_by_path))
|
||||
.route("/delete/*path", delete(delete_flow_by_path))
|
||||
.route("/get/*path", get(get_flow_by_path))
|
||||
.route("/exists/*path", get(exists_flow_by_path))
|
||||
.route("/list_paths", get(list_paths))
|
||||
@@ -446,8 +447,7 @@ async fn exists_flow_by_path(
|
||||
let path = path.to_path();
|
||||
|
||||
let exists = sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM flow WHERE path = $1 AND (workspace_id = $2 OR workspace_id \
|
||||
= 'starter'))",
|
||||
"SELECT EXISTS(SELECT 1 FROM flow WHERE path = $1 AND workspace_id = $2)",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
@@ -494,6 +494,42 @@ async fn archive_flow_by_path(
|
||||
Ok(format!("Flow {path} archived"))
|
||||
}
|
||||
|
||||
async fn delete_flow_by_path(
|
||||
authed: Authed,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Extension(webhook): Extension<WebhookShared>,
|
||||
Path((w_id, path)): Path<(String, StripPath)>,
|
||||
) -> Result<String> {
|
||||
let path = path.to_path();
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
sqlx::query!(
|
||||
"DELETE FROM flow WHERE path = $1 AND workspace_id = $2",
|
||||
path,
|
||||
&w_id
|
||||
)
|
||||
.execute(&mut tx)
|
||||
.await?;
|
||||
|
||||
audit_log(
|
||||
&mut tx,
|
||||
&authed.username,
|
||||
"flows.delete",
|
||||
ActionKind::Delete,
|
||||
&w_id,
|
||||
Some(path),
|
||||
Some([("workspace", w_id.as_str())].into()),
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
webhook.send_message(
|
||||
w_id.clone(),
|
||||
WebhookMessage::DeleteFlow { workspace: w_id, path: path.to_owned() },
|
||||
);
|
||||
|
||||
Ok(format!("Flow {path} deleted"))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ pub enum WebhookMessage {
|
||||
CreateFlow { workspace: String, path: String },
|
||||
UpdateFlow { workspace: String, old_path: String, new_path: String },
|
||||
ArchiveFlow { workspace: String, path: String },
|
||||
DeleteFlow { workspace: String, path: String },
|
||||
CreateFolder { workspace: String, name: String },
|
||||
UpdateFolder { workspace: String, name: String },
|
||||
DeleteFolder { workspace: String, name: String },
|
||||
|
||||
@@ -25,7 +25,6 @@ use axum::{
|
||||
routing::{delete, get, post},
|
||||
Json, Router,
|
||||
};
|
||||
use serde_json::to_string_pretty;
|
||||
use stripe::CustomerId;
|
||||
use windmill_audit::{audit_log, ActionKind};
|
||||
use windmill_common::{
|
||||
|
||||
+1
-4
@@ -48,10 +48,6 @@ export class FlowFile implements Resource, PushDiffs {
|
||||
path: remotePath,
|
||||
})
|
||||
) {
|
||||
console.log({
|
||||
workspace: workspace,
|
||||
path: remotePath,
|
||||
})
|
||||
console.log(
|
||||
colors.bold.yellow(
|
||||
`Applying ${diffs.length} diffs to existing flow... ${remotePath}`,
|
||||
@@ -126,6 +122,7 @@ export class FlowFile implements Resource, PushDiffs {
|
||||
path: remotePath,
|
||||
});
|
||||
} catch {
|
||||
|
||||
remote = undefined;
|
||||
}
|
||||
await this.pushDiffs(
|
||||
|
||||
@@ -511,7 +511,6 @@ async function push(opts: GlobalOptions & { raw: boolean, yes: boolean }) {
|
||||
remotePath = parts[0];
|
||||
}
|
||||
}
|
||||
console.log(diffs)
|
||||
return file.pushDiffs(workspace, remotePath, diffs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
faFileExport,
|
||||
faList,
|
||||
faPlay,
|
||||
faShare
|
||||
faShare,
|
||||
faTrashAlt
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { MoreVertical } from 'lucide-svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@@ -43,6 +44,16 @@
|
||||
sendUserToast(`Could not archive this flow ${err.body}`, true)
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFlow(path: string): Promise<void> {
|
||||
try {
|
||||
await FlowService.deleteFlowByPath({ workspace: $workspaceStore!, path })
|
||||
dispatch('change')
|
||||
sendUserToast(`Deleted flow ${path}`)
|
||||
} catch (err) {
|
||||
sendUserToast(`Could not delete this flow ${err.body}`, true)
|
||||
}
|
||||
}
|
||||
let scheduleEditor: ScheduleEditor
|
||||
</script>
|
||||
|
||||
@@ -166,6 +177,15 @@
|
||||
},
|
||||
type: 'delete',
|
||||
disabled: !canWrite
|
||||
},
|
||||
{
|
||||
displayName: 'Delete',
|
||||
icon: faTrashAlt,
|
||||
action: () => {
|
||||
path ? deleteFlow(path) : null
|
||||
},
|
||||
type: 'delete',
|
||||
disabled: !canWrite
|
||||
}
|
||||
]}
|
||||
>
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
faCodeFork,
|
||||
faClipboard,
|
||||
faChevronUp,
|
||||
faChevronDown
|
||||
faChevronDown,
|
||||
faTrash
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
@@ -85,6 +86,12 @@
|
||||
loadFlow()
|
||||
}
|
||||
|
||||
async function deleteFlow(): Promise<void> {
|
||||
await FlowService.deleteFlowByPath({ workspace: $workspaceStore!, path })
|
||||
sendUserToast('Flow deleted')
|
||||
goto('/')
|
||||
}
|
||||
|
||||
async function setScheduleEnabled(path: string, enabled: boolean): Promise<void> {
|
||||
try {
|
||||
await ScheduleService.setScheduleEnabled({
|
||||
@@ -416,6 +423,16 @@
|
||||
>
|
||||
Archive
|
||||
</Button>
|
||||
<Button
|
||||
on:click={() => flow?.path && deleteFlow()}
|
||||
variant="border"
|
||||
color="red"
|
||||
size="md"
|
||||
startIcon={{ icon: faTrash }}
|
||||
disabled={flow.archived || !can_write}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user