diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index af6f5b6e95..fcc7fb3194 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -2337,6 +2337,13 @@ paths: in: query schema: type: string + - name: starred_only + description: | + (default false) + show only the starred items + in: query + schema: + type: boolean responses: "200": description: All available apps diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index 41808fa47e..98f5518a62 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -25,6 +25,7 @@ use sql_builder::{bind::Bind, SqlBuilder}; use sqlx::{types::Uuid, FromRow}; use windmill_audit::{audit_log, ActionKind}; use windmill_common::{ + apps::ListAppQuery, error::{to_anyhow, Error, JsonResult, Result}, users::owner_to_token_owner, utils::{not_found_if_none, paginate, Pagination, StripPath}, @@ -120,12 +121,13 @@ pub struct EditApp { async fn list_apps( authed: Authed, Query(pagination): Query, + Query(lq): Query, Extension(user_db): Extension, Path(w_id): Path, ) -> JsonResult> { let (per_page, offset) = paginate(pagination); - let sqlb = SqlBuilder::select_from("app") + let mut sqlb = SqlBuilder::select_from("app") .fields(&[ "app.id", "app.workspace_id", @@ -154,6 +156,11 @@ async fn list_apps( .offset(offset) .limit(per_page) .clone(); + + if lq.starred_only.unwrap_or(false) { + sqlb.and_where_is_not_null("favorite.path"); + } + let sql = sqlb.sql().map_err(|e| Error::InternalErr(e.to_string()))?; let mut tx = user_db.begin(&authed).await?; let rows = sqlx::query_as::<_, ListableApp>(&sql) diff --git a/backend/windmill-common/src/apps.rs b/backend/windmill-common/src/apps.rs new file mode 100644 index 0000000000..14d47dfdd4 --- /dev/null +++ b/backend/windmill-common/src/apps.rs @@ -0,0 +1,14 @@ +/* + * Author: Ruben Fiszel + * Copyright: Windmill Labs, Inc 2022 + * This file and its contents are licensed under the AGPLv3 License. + * Please see the included NOTICE for copyright information and + * LICENSE-AGPL for a copy of the license. + */ + +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct ListAppQuery { + pub starred_only: Option, +} diff --git a/backend/windmill-common/src/lib.rs b/backend/windmill-common/src/lib.rs index b9d27cdc0e..bbc2b1b80b 100644 --- a/backend/windmill-common/src/lib.rs +++ b/backend/windmill-common/src/lib.rs @@ -10,6 +10,7 @@ use std::net::SocketAddr; use error::Error; +pub mod apps; pub mod error; pub mod external_ip; pub mod flow_status; diff --git a/frontend/src/lib/components/ItemPicker.svelte b/frontend/src/lib/components/ItemPicker.svelte index 11ac70c86e..10f4d17ffa 100644 --- a/frontend/src/lib/components/ItemPicker.svelte +++ b/frontend/src/lib/components/ItemPicker.svelte @@ -8,7 +8,7 @@ export let pickCallback: (path: string, f: string) => void export let loadItems: () => Promise export let extraField: string = 'path' - export let extraField2: string | undefined + export let extraField2: string | undefined = undefined export let itemName: string export let closeOnClick = true /** Displayed if the load function returns no items. */ diff --git a/frontend/src/lib/components/ScriptBuilder.svelte b/frontend/src/lib/components/ScriptBuilder.svelte index 1e5e7d41d4..0821e7c739 100644 --- a/frontend/src/lib/components/ScriptBuilder.svelte +++ b/frontend/src/lib/components/ScriptBuilder.svelte @@ -88,6 +88,7 @@ } goto(`?step=${step}`) } + $: kind = script.kind as 'script' | 'trigger' | 'approval' | undefined @@ -290,7 +291,7 @@ bind:code={script.content} lang={script.language} {initialArgs} - kind={script.kind} + {kind} /> {:else if step === 3} diff --git a/frontend/src/lib/components/sidebar/FavoriteMenu.svelte b/frontend/src/lib/components/sidebar/FavoriteMenu.svelte new file mode 100644 index 0000000000..2a0edb6d7d --- /dev/null +++ b/frontend/src/lib/components/sidebar/FavoriteMenu.svelte @@ -0,0 +1,59 @@ + + + + + +
+ + {#each favoriteLinks ?? [] as favorite (favorite.href)} + + + + + + + {/each} +
+ {#if favorite.kind == 'script'} + + {:else if favorite.kind == 'flow'} + + {:else if favorite.kind == 'app'} + + {/if} + {favorite.label}
+
+ +
+
+
diff --git a/frontend/src/lib/components/sidebar/SidebarContent.svelte b/frontend/src/lib/components/sidebar/SidebarContent.svelte index a2f842b7bf..69592a53dc 100644 --- a/frontend/src/lib/components/sidebar/SidebarContent.svelte +++ b/frontend/src/lib/components/sidebar/SidebarContent.svelte @@ -9,7 +9,6 @@ faRobot, faUsersCog, faCog, - faStar, faDollarSign } from '@fortawesome/free-solid-svg-icons' import { faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons' @@ -23,8 +22,6 @@ { label: 'Resources', href: '/resources', icon: faCubes } ] - export let favoriteLinks = [] as { label: string; href: string }[] - $: secondaryMenuLinks = [ { label: 'Schedules', href: '/schedules', icon: faCalendar }, { label: 'Groups', href: '/groups', icon: faUsersCog }, @@ -51,21 +48,13 @@ export let isCollapsed: boolean = false -
+
@@ -155,7 +168,7 @@
-
superadminSettings.openDrawer()} {isCollapsed} /> +
- +