Files
windmill/backend/windmill-api/src/utils.rs
T
Ruben Fiszel 71b7135cf2 feat: multiple homepage sort orders via an efficient merged runnables endpoint (#10297)
Adds recently-updated / oldest / name A-Z / name Z-A sort orders to the homepage (WIN-2236), produced server-side by a new merged, index-backed, keyset-paginated GET /w/{workspace}/runnables/list so a chosen order is globally correct across scripts + flows + apps and stays efficient on large workspaces.

- Backend: UNION ALL of script/flow/app ordered by index (Merge Append + LIMIT); keyset (sort_key, path, kind, tiebreak) cursor; per-branch LIMIT bounds correlated projections; starred-first pinning; RLS + scope-token filters in SQL. Archived view returns the latest row per path. Migration adds time + lowered-name indexes (built CONCURRENTLY).
- Frontend: server-side sort/kind/owner filters + hybrid search (instant client + on-demand server pagination); file-explorer tree with every folder and your user namespace as lazy-loaded top-level nodes (per-owner "Load more", nested subfolders, bounded "expand all", in-place re-sort without collapse or flicker); the client sorts by the server fetch ordinal to reproduce the endpoint's exact order; empty state distinguishes an empty workspace from too-narrow filters.

Reviewed clean by Claude and Pi (good to merge) and Codex (mergeable).
2026-07-24 23:16:10 +02:00

49 lines
1.4 KiB
Rust

/*
* 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 axum::{body::Body, response::Response};
use serde::{Deserialize, Deserializer};
pub use windmill_api_auth::{
build_scope_path_filter, build_scope_path_predicate, check_scopes, require_devops_role,
require_super_admin, ScopePathFilter,
};
#[cfg(feature = "private")]
pub use windmill_common::usernames::generate_instance_wide_unique_username;
#[cfg(feature = "enterprise")]
pub use windmill_alerting::{
acknowledge_all_critical_alerts, acknowledge_critical_alert, get_critical_alerts,
AlertQueryParams,
};
pub fn content_plain(body: Body) -> Response {
use axum::http::header;
Response::builder()
.header(header::CONTENT_TYPE, "text/plain")
.body(body)
.unwrap()
}
#[allow(unused)]
pub fn non_empty_str<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let o: Option<String> = Option::deserialize(deserializer)?;
Ok(o.filter(|s| !s.trim().is_empty()))
}
#[cfg(feature = "http_trigger")]
pub use windmill_common::utils::ExpiringCacheEntry;
lazy_static::lazy_static! {
static ref DUCKLAKE_INSTANCE_PG_PASSWORD: std::sync::RwLock<Option<String>> = std::sync::RwLock::new(None);
}