diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 7721124438..76b57ced49 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -4297,6 +4297,17 @@ paths: operationId: getCustomTags tags: - worker + parameters: + - name: workspace + in: query + schema: + type: string + required: false + - name: show_workspace_restriction + in: query + schema: + type: boolean + required: false responses: "200": description: list of custom tags diff --git a/backend/windmill-api/src/workers.rs b/backend/windmill-api/src/workers.rs index 527b66296c..4c3334e511 100644 --- a/backend/windmill-api/src/workers.rs +++ b/backend/windmill-api/src/workers.rs @@ -19,7 +19,7 @@ use windmill_common::{ db::UserDB, error::JsonResult, utils::{paginate, Pagination}, - worker::{ALL_TAGS, DEFAULT_TAGS, DEFAULT_TAGS_PER_WORKSPACE}, + worker::{ALL_TAGS, CUSTOM_TAGS_PER_WORKSPACE, DEFAULT_TAGS, DEFAULT_TAGS_PER_WORKSPACE}, DB, }; @@ -133,8 +133,48 @@ async fn exists_worker_with_tag( Ok(Json(row.exists.unwrap_or(false))) } -async fn get_custom_tags() -> Json> { - Json(ALL_TAGS.read().await.clone().into()) +#[derive(Deserialize)] +struct CustomTagQuery { + workspace: Option, + show_workspace_restriction: Option, +} +async fn get_custom_tags(Query(query): Query) -> JsonResult> { + if query.show_workspace_restriction.is_some_and(|x| x) && query.workspace.is_some() { + return Err(windmill_common::error::Error::BadRequest( + "Cannot use both workspace and show_workspace_restriction".to_string(), + )); + } + if let Some(workspace) = query.workspace { + let tags_o = CUSTOM_TAGS_PER_WORKSPACE.read().await; + let workspace_tags = tags_o + .1 + .get(&workspace) + .map(|x| x.clone()) + .unwrap_or_default(); + let all_tags = tags_o.0.clone(); + return Ok(Json( + all_tags + .into_iter() + .chain(workspace_tags.into_iter()) + .collect(), + )); + } else if query.show_workspace_restriction.is_some_and(|x| x) { + let tags_o = CUSTOM_TAGS_PER_WORKSPACE.read().await; + let workspace_tags = tags_o + .1 + .iter() + .map(|(workspace, tags)| tags.iter().map(move |tag| format!("{tag}({workspace})"))) + .flatten() + .collect::>(); + let all_tags = tags_o.0.clone(); + return Ok(Json( + all_tags + .into_iter() + .chain(workspace_tags.into_iter()) + .collect(), + )); + } + Ok(Json(ALL_TAGS.read().await.clone().into())) } async fn get_default_tags_per_workspace() -> JsonResult { diff --git a/backend/windmill-common/src/worker.rs b/backend/windmill-common/src/worker.rs index c64184b484..81c3537c8a 100644 --- a/backend/windmill-common/src/worker.rs +++ b/backend/windmill-common/src/worker.rs @@ -87,7 +87,7 @@ lazy_static::lazy_static! { pub static ref ALL_TAGS: Arc>> = Arc::new(RwLock::new(vec![])); - static ref CUSTOM_TAG_REGEX: Regex = Regex::new(r"^(\w+)\(((?:\w+)\+?)+\)$").unwrap(); + static ref CUSTOM_TAG_REGEX: Regex = Regex::new(r"^([\w-]+)\(((?:[\w-])+\+?)+\)$").unwrap(); pub static ref DISABLE_BUNDLING: bool = std::env::var("DISABLE_BUNDLING") .ok() diff --git a/frontend/src/lib/components/AssignableTags.svelte b/frontend/src/lib/components/AssignableTags.svelte index 2326a0dd96..324728b32b 100644 --- a/frontend/src/lib/components/AssignableTags.svelte +++ b/frontend/src/lib/components/AssignableTags.svelte @@ -8,6 +8,7 @@ export let placement: 'bottom-end' | 'top-end' = 'bottom-end' export let color: 'nord' | 'dark' = 'dark' export let disabled = false + export let showWorkspaceRestriction = false - + diff --git a/frontend/src/lib/components/AssignableTagsInner.svelte b/frontend/src/lib/components/AssignableTagsInner.svelte index 19fff0a795..03f0254983 100644 --- a/frontend/src/lib/components/AssignableTagsInner.svelte +++ b/frontend/src/lib/components/AssignableTagsInner.svelte @@ -9,12 +9,16 @@ import { base } from '$lib/base' import { createEventDispatcher } from 'svelte' + export let showWorkspaceRestriction = false let newTag: string = '' let customTags: string[] | undefined = undefined async function loadCustomTags() { try { - customTags = (await WorkerService.getCustomTags()) ?? [] + customTags = + (await WorkerService.getCustomTags({ + showWorkspaceRestriction + })) ?? [] } catch (err) { sendUserToast(`Could not load global cache: ${err}`, true) } diff --git a/frontend/src/lib/components/WorkerTagSelect.svelte b/frontend/src/lib/components/WorkerTagSelect.svelte index 232b86b98f..c1c46d838a 100644 --- a/frontend/src/lib/components/WorkerTagSelect.svelte +++ b/frontend/src/lib/components/WorkerTagSelect.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/lib/components/runs/NoWorkerWithTagWarning.svelte b/frontend/src/lib/components/runs/NoWorkerWithTagWarning.svelte index 7af0d8f77d..070d5dd523 100644 --- a/frontend/src/lib/components/runs/NoWorkerWithTagWarning.svelte +++ b/frontend/src/lib/components/runs/NoWorkerWithTagWarning.svelte @@ -9,13 +9,16 @@ let timeout: NodeJS.Timeout | undefined = undefined + let visible = true async function lookForTag(): Promise { try { const existsWorkerWithTag = await WorkerService.existsWorkerWithTag({ tag }) noWorkerWithTag = !existsWorkerWithTag if (noWorkerWithTag) { timeout = setTimeout(() => { - lookForTag() + if (visible) { + lookForTag() + } }, 1000) } } catch (err) { @@ -26,6 +29,7 @@ lookForTag() onDestroy(() => { + visible = false if (timeout) { clearTimeout(timeout) } diff --git a/frontend/src/routes/(root)/(logged)/workers/+page.svelte b/frontend/src/routes/(root)/(logged)/workers/+page.svelte index 71b0ad0a69..c385420901 100644 --- a/frontend/src/routes/(root)/(logged)/workers/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workers/+page.svelte @@ -282,6 +282,7 @@
{ loadCustomTags() }}