Skip to content

Commit

Permalink
feat(frontend): unify all triggers UX and simplify flow settings (#4259)
Browse files Browse the repository at this point in the history
* feat(frontend): added list of triggers in the flow graph

* feat(frontend): added list of triggers in the flow graph

* feat(frontend): clean up

* feat(frontend): improve UX

* feat(frontend): triggers

* feat(frontend): triggers

* feat(frontend): done

* feat(frontend): fix trigger when position when a preprocessor is presetn

* Glm/rework flow settings v2 (#4497)

* fat(frontend): simplify flow settings menu

* improve scroll

* changing mute toggle

* Add advanced settings badge

* Add nord theme colors

* Add bage for advanced options

* fix minor issue

* fix minor issue

* Add triggers menu to flow settings

* Add quick trigger access

* remove triggers in flow settings

* fix minor issue

* Move triggers settings to flow right panel

* polishing

* fix unset store

* remove save up to for triggers

* fix padding

* reset default tag color

* remove custom select component

* revert path change

* revert section modif

* Revert unused feature

---------

Co-authored-by: Guilhem <[email protected]>

* Connect top bar cron to schedules settings

* Turn copilot into node

* fix copilot placement

* remove useless import

* fix center copilot

* fix binding

* remove copilot on top of preprocessor

* render copilot node on condition

* quickfix

* remove copilot node

* fix minor issues

* fix route count update

* fix schedule sync

* harmonize colors

* fix alignment and add edges

* recenter node summary

* fix schedules sync

* Add id title

* all

* all

* all

* iteration

* all

* all

* done

* fix

* more fixes

---------

Co-authored-by: Guilhem <[email protected]>
Co-authored-by: Guilhem <[email protected]>
Co-authored-by: Ruben Fiszel <[email protected]>
Co-authored-by: Ruben Fiszel <[email protected]>
  • Loading branch information
5 people committed Oct 16, 2024
1 parent f38b3d1 commit 1ec8d63
Show file tree
Hide file tree
Showing 75 changed files with 2,438 additions and 1,400 deletions.
96 changes: 96 additions & 0 deletions backend/windmill-api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4020,6 +4020,42 @@ paths:
schema:
$ref: "#/components/schemas/Script"

/w/{workspace}/scripts/get_triggers_count/{path}:
get:
summary: get triggers count of script
operationId: getTriggersCountOfScript
tags:
- script
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
responses:
"200":
description: triggers count
content:
application/json:
schema:
$ref: "#/components/schemas/TriggersCount"

/w/{workspace}/scripts/list_tokens/{path}:
get:
summary: get tokens with script scope
operationId: listTokensOfScript
tags:
- script
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
responses:
"200":
description: tokens list
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/TruncatedToken"

/w/{workspace}/scripts/get/draft/{path}:
get:
summary: get script by path with draft
Expand Down Expand Up @@ -4624,6 +4660,43 @@ paths:
schema:
$ref: "#/components/schemas/Flow"

/w/{workspace}/flows/get_triggers_count/{path}:
get:
summary: get triggers count of flow
operationId: getTriggersCountOfFlow
tags:
- flow
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
responses:
"200":
description: triggers count
content:
application/json:
schema:
$ref: "#/components/schemas/TriggersCount"

/w/{workspace}/flows/list_tokens/{path}:
get:
summary: get tokens with flow scope
operationId: listTokensOfFlow
tags:
- flow
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/ScriptPath"
responses:
"200":
description: tokens list
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/TruncatedToken"


/w/{workspace}/flows/toggle_workspace_error_handler/{path}:
post:
summary: Toggle ON and OFF the workspace error handler for a given flow
Expand Down Expand Up @@ -10254,6 +10327,8 @@ components:
type: array
items:
type: string
email:
type: string
required:
- token_prefix
- created_at
Expand All @@ -10271,6 +10346,8 @@ components:
type: array
items:
type: string
workspace_id:
type: string

NewTokenImpersonate:
type: object
Expand All @@ -10282,6 +10359,8 @@ components:
format: date-time
impersonate_email:
type: string
workspace_id:
type: string
required:
- impersonate_email

Expand Down Expand Up @@ -11118,6 +11197,23 @@ components:
- requires_auth
- http_method

TriggersCount:
type: object
properties:
primary_schedule:
type: object
properties:
schedule:
type: string
schedule_count:
type: number
http_routes_count:
type: number
webhook_count:
type: number
email_count:
type: number

Group:
type: object
properties:
Expand Down
21 changes: 21 additions & 0 deletions backend/windmill-api/src/flows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use std::collections::HashMap;

use crate::db::ApiAuthed;
use crate::triggers::{
get_triggers_count_internal, list_tokens_internal, TriggersCount, TruncatedTokenWithEmail,
};
use crate::utils::WithStarredInfoQuery;
use crate::{
db::DB,
Expand Down Expand Up @@ -53,6 +56,8 @@ pub fn workspaced_service() -> Router {
.route("/update/*path", post(update_flow))
.route("/archive/*path", post(archive_flow_by_path))
.route("/delete/*path", delete(delete_flow_by_path))
.route("/get_triggers_count/*path", get(get_triggers_count))
.route("/list_tokens/*path", get(list_tokens))
.route("/get/*path", get(get_flow_by_path))
.route("/get/draft/*path", get(get_flow_by_path_w_draft))
.route("/exists/*path", get(exists_flow_by_path))
Expand Down Expand Up @@ -874,6 +879,22 @@ async fn update_flow(
Ok(nf.path.to_string())
}

async fn get_triggers_count(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<TriggersCount> {
let path = path.to_path();
get_triggers_count_internal(&db, &w_id, &path, true).await
}

async fn list_tokens(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<Vec<TruncatedTokenWithEmail>> {
let path = path.to_path();
list_tokens_internal(&db, &w_id, &path, true).await
}

async fn get_flow_by_path(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Expand Down
1 change: 1 addition & 0 deletions backend/windmill-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub mod smtp_server_ee;
mod static_assets;
mod stripe_ee;
mod tracing_init;
mod triggers;
mod users;
mod utils;
mod variables;
Expand Down
21 changes: 21 additions & 0 deletions backend/windmill-api/src/scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use crate::{
db::{ApiAuthed, DB},
schedule::clear_schedule,
triggers::{
get_triggers_count_internal, list_tokens_internal, TriggersCount, TruncatedTokenWithEmail,
},
users::{maybe_refresh_folders, require_owner_of_path, AuthCache},
utils::WithStarredInfoQuery,
webhook_util::{WebhookMessage, WebhookShared},
Expand Down Expand Up @@ -132,6 +135,8 @@ pub fn workspaced_service() -> Router {
.route("/archive/p/*path", post(archive_script_by_path))
.route("/get/draft/*path", get(get_script_by_path_w_draft))
.route("/get/p/*path", get(get_script_by_path))
.route("/get_triggers_count/*path", get(get_triggers_count))
.route("/list_tokens/*path", get(list_tokens))
.route("/raw/p/*path", get(raw_script_by_path))
.route("/raw_unpinned/p/*path", get(raw_script_by_path_unpinned))
.route("/exists/p/*path", get(exists_script_by_path))
Expand Down Expand Up @@ -874,6 +879,22 @@ async fn get_script_by_path(
Ok(Json(script))
}

async fn list_tokens(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<Vec<TruncatedTokenWithEmail>> {
let path = path.to_path();
list_tokens_internal(&db, &w_id, &path, false).await
}

async fn get_triggers_count(
Extension(db): Extension<DB>,
Path((w_id, path)): Path<(String, StripPath)>,
) -> JsonResult<TriggersCount> {
let path = path.to_path();
get_triggers_count_internal(&db, &w_id, &path, false).await
}

async fn get_script_by_path_w_draft(
authed: ApiAuthed,
Extension(user_db): Extension<UserDB>,
Expand Down
131 changes: 131 additions & 0 deletions backend/windmill-api/src/triggers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use axum::Json;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use windmill_common::error::JsonResult;

use crate::db::DB;

#[derive(Serialize, Deserialize, Debug)]
pub struct TriggerPrimarySchedule {
schedule: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct TriggersCount {
primary_schedule: Option<TriggerPrimarySchedule>,
schedule_count: i64,
http_routes_count: i64,
webhook_count: i64,
email_count: i64,
}
pub(crate) async fn get_triggers_count_internal(
db: &DB,
w_id: &str,
path: &str,
is_flow: bool,
) -> JsonResult<TriggersCount> {
let primary_schedule = sqlx::query_scalar!(
"SELECT schedule FROM schedule WHERE path = $1 AND script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_optional(db)
.await?;

let schedule_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM schedule WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);

let http_routes_count = sqlx::query_scalar!(
"SELECT COUNT(*) FROM http_trigger WHERE script_path = $1 AND is_flow = $2 AND workspace_id = $3",
path,
is_flow,
w_id
)
.fetch_one(db)
.await?
.unwrap_or(0);

let webhook_count = (if is_flow {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]",
w_id,
path,
)

} else {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'webhook-%' AND workspace_id = $1 AND scopes @> ARRAY['run:' || $2]::text[]",
w_id,
path,
)
}).fetch_one(db)
.await?
.unwrap_or(0);

let email_count = (if is_flow {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]",
w_id,
path,
)

} else {
sqlx::query_scalar!(
"SELECT COUNT(*) FROM token WHERE label LIKE 'email-%' AND workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]",
w_id,
path,
)
}).fetch_one(db)
.await?
.unwrap_or(0);

Ok(Json(TriggersCount {
primary_schedule: primary_schedule.map(|s| TriggerPrimarySchedule { schedule: s }),
schedule_count,
http_routes_count,
webhook_count,
email_count,
}))
}

#[derive(FromRow, Serialize)]
pub struct TruncatedTokenWithEmail {
pub label: Option<String>,
pub token_prefix: Option<String>,
pub expiration: Option<chrono::DateTime<chrono::Utc>>,
pub created_at: chrono::DateTime<chrono::Utc>,
pub last_used_at: chrono::DateTime<chrono::Utc>,
pub scopes: Option<Vec<String>>,
pub email: Option<String>,
}

pub async fn list_tokens_internal(
db: &DB,
w_id: &str,
path: &str,
is_flow: bool,
) -> JsonResult<Vec<TruncatedTokenWithEmail>> {
let tokens = if is_flow {
sqlx::query_as!(
TruncatedTokenWithEmail,
"SELECT label, concat(substring(token for 10)) as token_prefix, expiration, created_at, last_used_at, scopes, email FROM token WHERE workspace_id = $1 AND scopes @> ARRAY['run:flow/' || $2]::text[]",
w_id, path).fetch_all(db)
.await?
} else {
sqlx::query_as!(
TruncatedTokenWithEmail,
"SELECT label, concat(substring(token for 10)) as token_prefix, expiration, created_at, last_used_at, scopes, email FROM token WHERE workspace_id = $1 AND scopes @> ARRAY['run:script/' || $2]::text[]",
w_id, path)
.fetch_all(db)
.await?
};
Ok(Json(tokens))
}
Loading

0 comments on commit 1ec8d63

Please sign in to comment.