fix: listScripts include description with opt-out query arg (#7210)

* description jobs

* all
This commit is contained in:
Ruben Fiszel
2025-11-24 09:37:55 +01:00
committed by GitHub
parent 6021c5a011
commit 7bb68a5d73
17 changed files with 153 additions and 151 deletions
+39 -24
View File
@@ -5180,6 +5180,14 @@ paths:
Accepts multiple values as a comma-separated list.
schema:
type: string
- name: without_description
in: query
description: |
(default false)
If true, the description field will be omitted from the response.
schema:
type: boolean
responses:
"200":
description: All scripts
@@ -6463,6 +6471,13 @@ paths:
in: query
schema:
type: boolean
- name: without_description
in: query
description: |
(default false)
If true, the description field will be omitted from the response.
schema:
type: boolean
responses:
"200":
description: All flow
@@ -11999,32 +12014,32 @@ paths:
schema:
type: boolean
/w/{workspace}/email_triggers/setenabled/{path}:
post:
summary: enable/disable email trigger
operationId: setEmailTriggerEnabled
tags:
- email_trigger
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/Path"
requestBody:
required: true
post:
summary: enable/disable email trigger
operationId: setEmailTriggerEnabled
tags:
- email_trigger
parameters:
- $ref: "#/components/parameters/WorkspaceId"
- $ref: "#/components/parameters/Path"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
enabled:
type: boolean
required:
- enabled
responses:
"200":
description: email trigger enable/disable
content:
application/json:
text/plain:
schema:
type: object
properties:
enabled:
type: boolean
required:
- enabled
responses:
"200":
description: email trigger enable/disable
content:
text/plain:
schema:
type: string
type: string
/groups/list:
get:
+5 -1
View File
@@ -133,7 +133,11 @@ async fn list_flows(
"o.workspace_id",
"o.path",
"summary",
"description",
if !lq.without_description.unwrap_or(false) {
"description"
} else {
"NULL as description"
},
"fv.created_by as edited_by",
"fv.created_at as edited_at",
"archived",
+5
View File
@@ -228,6 +228,11 @@ async fn list_scripts(
"COALESCE(draft.created_at, o.created_at) as created_at",
"archived",
"extra_perms",
if !lq.without_description.unwrap_or(false) {
"description"
} else {
"NULL as description"
},
"CASE WHEN lock_error_logs IS NOT NULL THEN true ELSE false END as has_deploy_errors",
"language",
"favorite.path IS NOT NULL as starred",
+3 -1
View File
@@ -78,7 +78,8 @@ pub struct ListableFlow {
pub workspace_id: String,
pub path: String,
pub summary: String,
pub description: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub edited_by: Option<String>,
pub edited_at: Option<chrono::DateTime<chrono::Utc>>,
pub archived: bool,
@@ -1122,6 +1123,7 @@ where
#[derive(Deserialize)]
pub struct ListFlowQuery {
pub without_description: Option<bool>,
pub path_start: Option<String>,
pub path_exact: Option<String>,
pub edited_by: Option<String>,
+3
View File
@@ -353,6 +353,8 @@ pub struct ListableScript {
pub starred: bool,
pub tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_draft: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub draft_only: Option<bool>,
@@ -492,6 +494,7 @@ where
#[derive(Debug, Deserialize)]
pub struct ListScriptQuery {
pub without_description: Option<bool>,
pub path_start: Option<String>,
pub path_exact: Option<String>,
pub created_by: Option<String>,
@@ -57,15 +57,19 @@
async function loadItems(): Promise<void> {
if (itemKind == 'flow') {
items = (await FlowService.listFlows({ workspace: $workspaceStore! })).map((flow) => ({
items = (
await FlowService.listFlows({ workspace: $workspaceStore!, withoutDescription: true })
).map((flow) => ({
value: flow.path,
label: `${flow.path}${flow.summary ? ` | ${truncate(flow.summary, 20)}` : ''}`
label: `${flow.path}${flow.summary ? ` | ${truncate(flow.summary, 20)}` : ''}`,
withoutDescription: true
}))
} else if (itemKind == 'script') {
items = (
await ScriptService.listScripts({
workspace: $workspaceStore!,
kinds: kinds.join(',')
kinds: kinds.join(','),
withoutDescription: true
})
).map((script) => ({
value: script.path,
@@ -27,7 +27,8 @@
async function loadFlow(): Promise<void> {
const loadedFlows = await FlowService.listFlows({
workspace: $workspaceStore!,
perPage: 300
perPage: 300,
withoutDescription: true
})
flows = loadedFlows
@@ -27,7 +27,8 @@
async function loadScripts(): Promise<void> {
const loadedScripts = await ScriptService.listScripts({
workspace: $workspaceStore!,
perPage: 300
perPage: 300,
withoutDescription: true
})
scripts = loadedScripts
@@ -374,7 +374,7 @@ class WorkspaceScriptsSearch {
private async init(workspace: string) {
this.scripts = await ScriptService.listScripts({
workspace
workspace,
})
this.workspace = workspace
}
@@ -6,28 +6,38 @@
import { workspaceStore } from '$lib/stores'
import { emptyString } from '$lib/utils'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, untrack } from 'svelte'
import { flip } from 'svelte/animate'
import { fade } from 'svelte/transition'
interface Props {
children?: import('svelte').Snippet
}
let { children }: Props = $props()
// export let failureModule: boolean
const dispatch = createEventDispatcher()
let items: Flow[] | undefined = undefined
let filteredItems: (Flow & { marked?: string })[] | undefined = undefined
let filter = ''
$: $workspaceStore && loadFlows()
let items = $state(undefined) as Flow[] | undefined
let filteredItems = $state(undefined) as (Flow & { marked?: string })[] | undefined
let filter = $state('')
let ownerFilter: string | undefined = undefined
$: prefilteredItems = ownerFilter ? items?.filter((x) => x.path.startsWith(ownerFilter!)) : items
$: owners = Array.from(
new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? [])
).sort()
let ownerFilter: string | undefined = $state(undefined)
async function loadFlows() {
items = await FlowService.listFlows({ workspace: $workspaceStore! })
items = await FlowService.listFlows({ workspace: $workspaceStore!, withoutDescription: true })
}
$effect(() => {
$workspaceStore && untrack(() => loadFlows())
})
let prefilteredItems = $derived(
ownerFilter ? items?.filter((x) => x.path.startsWith(ownerFilter!)) : items
)
let owners = $derived(
Array.from(
new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? [])
).sort()
)
</script>
<SearchItems
@@ -39,7 +49,7 @@
<div class="flex flex-col min-h-0 p-4">
<h3 class="mb-4">Pick a Workspace Flow</h3>
<div class="w-full flex mt-1 items-center gap-2 mb-3">
<slot />
{@render children?.()}
<input
type="text"
@@ -78,7 +88,7 @@
<li class="flex flex-row w-full">
<button
class="p-4 gap-1 flex flex-row grow hover:bg-surface-hover bg-surface transition-all text-primary"
on:click={() => {
onclick={() => {
dispatch('pick', { path })
}}
>
@@ -1,73 +0,0 @@
<script lang="ts">
import { Skeleton } from '$lib/components/common'
import SearchItems from '$lib/components/SearchItems.svelte'
import { FlowService, type Flow } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { emptyString } from '$lib/utils'
import BarsStaggered from '$lib/components/icons/BarsStaggered.svelte'
import { createEventDispatcher } from 'svelte'
// export let failureModule: boolean
const dispatch = createEventDispatcher()
let items: Flow[] | undefined = undefined
let filteredItems: (Flow & { marked?: string })[] | undefined = undefined
export let filter = ''
$: $workspaceStore && loadFlows()
let ownerFilter: string | undefined = undefined
$: prefilteredItems = ownerFilter ? items?.filter((x) => x.path.startsWith(ownerFilter!)) : items
export let owners: string[] = []
$: owners = Array.from(
new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? [])
).sort()
async function loadFlows() {
items = await FlowService.listFlows({ workspace: $workspaceStore! })
}
</script>
<SearchItems
{filter}
items={prefilteredItems}
bind:filteredItems
f={(x) => (emptyString(x.summary) ? x.path : x.summary + ' (' + x.path + ')')}
/>
<div class="flex flex-col min-h-0">
{#if filteredItems}
{#if filter.length > 0 && filteredItems.length == 0}
<div class="text-2xs text-tercary font-extralight text-center py-2 px-3 items-center">
No items found.
</div>
{/if}
<ul class="overflow-auto">
{#each filteredItems as { path, summary, marked }}
<li class="flex flex-row w-full">
<button
class="px-3 py-2 gap-2 flex flex-row w-full hover:bg-surface-hover bg-surface transition-all items-center rounded-md text-left text-2xs text-primary font-normal"
on:click={async () => {
dispatch('pickFlow', {
path,
summary
})
}}
>
<BarsStaggered size={14} />
<span class="grow truncate">
{#if marked}
{@html marked}
{:else}
{!summary || summary.length == 0 ? path : summary}
{/if}
</span>
</button>
</li>
{/each}
</ul>
{:else}
{#each Array(10).fill(0) as _}
<Skeleton layout={[0.5, [1.5]]} />
{/each}
{/if}
</div>
@@ -1,6 +1,6 @@
<script lang="ts">
import { workspaceStore } from '$lib/stores'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, untrack } from 'svelte'
import { ScriptService } from '$lib/gen'
import SearchItems from '$lib/components/SearchItems.svelte'
import { Badge, Skeleton } from '$lib/components/common'
@@ -11,10 +11,6 @@
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
import TextInput from '$lib/components/text_input/TextInput.svelte'
export let kind: 'script' | 'trigger' | 'approval' | 'failure' = 'script'
export let isTemplate: boolean | undefined = undefined
export let displayLock = false
type Item = {
path: string
summary?: string
@@ -22,33 +18,54 @@
hash?: string
}
let items: Item[] | undefined = undefined
let items = $state(undefined) as Item[] | undefined
let filteredItems: (Item & { marked?: string })[] | undefined = undefined
export let filter = ''
let filteredItems = $state(undefined) as (Item & { marked?: string })[] | undefined
interface Props {
kind?: 'script' | 'trigger' | 'approval' | 'failure'
isTemplate?: boolean | undefined
displayLock?: boolean
filter?: string
children?: import('svelte').Snippet
}
$: $workspaceStore && kind && loadItems()
let {
kind = 'script',
isTemplate = undefined,
displayLock = false,
filter = $bindable(''),
children
}: Props = $props()
async function loadItems(): Promise<void> {
items = await ScriptService.listScripts({
workspace: $workspaceStore!,
kinds: kind,
isTemplate
isTemplate,
withoutDescription: true
})
}
let ownerFilter: string | undefined = undefined
$: if ($workspaceStore) {
ownerFilter = undefined
}
$: prefilteredItems = ownerFilter ? items?.filter((x) => x.path.startsWith(ownerFilter!)) : items
$: owners = Array.from(
new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? [])
).sort()
let ownerFilter: string | undefined = $state(undefined)
const dispatch = createEventDispatcher()
let lockHash = false
let lockHash = $state(false)
$effect(() => {
$workspaceStore && kind && untrack(() => loadItems())
})
$effect(() => {
if ($workspaceStore) {
ownerFilter = undefined
}
})
let prefilteredItems = $derived(
ownerFilter ? items?.filter((x) => x.path.startsWith(ownerFilter!)) : items
)
let owners = $derived(
Array.from(
new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? [])
).sort()
)
</script>
<SearchItems
@@ -59,7 +76,7 @@
/>
<div class="flex flex-col min-h-0">
<div class="w-full flex items-center gap-2 mb-3">
<slot />
{@render children?.()}
<TextInput
inputProps={{
@@ -109,7 +126,7 @@
<li class="flex flex-row w-full">
<button
class="p-4 gap-1 flex flex-row grow hover:bg-surface-hover bg-surface transition-all text-primary"
on:click={() => {
onclick={() => {
dispatch('pick', { path, hash: lockHash ? hash : undefined })
}}
>
@@ -13,8 +13,13 @@
}) =>
workspace && get(userStore)
? kind == 'flow'
? FlowService.listFlows({ workspace })
: ScriptService.listScripts({ workspace, kinds: kind, isTemplate })
? FlowService.listFlows({ workspace, withoutDescription: true })
: ScriptService.listScripts({
workspace,
kinds: kind,
isTemplate,
withoutDescription: true
})
: undefined,
initialWorkspace
? {
@@ -85,7 +85,8 @@
workspace: $workspaceStore!,
showArchived: archived ? true : undefined,
includeWithoutMain: includeWithoutMain ? true : undefined,
includeDraftOnly: true
includeDraftOnly: true,
withoutDescription: true
})
scripts = loadedScripts.map((script: Script) => {
@@ -102,7 +103,8 @@
await FlowService.listFlows({
workspace: $workspaceStore!,
showArchived: archived ? true : undefined,
includeDraftOnly: true
includeDraftOnly: true,
withoutDescription: true
})
).map((x: Flow) => {
return {
@@ -484,10 +484,12 @@
async function fetchCombinedItems() {
const scripts = await ScriptService.listScripts({
workspace: $workspaceStore!
workspace: $workspaceStore!,
withoutDescription: true
})
const flows = await FlowService.listFlows({
workspace: $workspaceStore!
workspace: $workspaceStore!,
withoutDescription: true
})
const apps = await AppService.listApps({ workspace: $workspaceStore! })
const raw_apps = await RawAppService.listRawApps({ workspace: $workspaceStore! })
@@ -202,7 +202,8 @@
const scripts = await ScriptService.listScripts({
starredOnly: favoriteOnly,
workspace,
pathStart
pathStart,
withoutDescription: true
})
return scripts.map((x) => x.path)
}
@@ -219,7 +220,8 @@
const flows = await FlowService.listFlows({
starredOnly: favoriteOnly,
workspace,
pathStart
pathStart,
withoutDescription: true
})
return flows.map((x) => x.path)
}
@@ -155,11 +155,13 @@
const scripts = await ScriptService.listScripts({
workspace: $workspaceStore ?? '',
starredOnly: true,
includeWithoutMain: true
includeWithoutMain: true,
withoutDescription: true
})
const flows = await FlowService.listFlows({
workspace: $workspaceStore ?? '',
starredOnly: true
starredOnly: true,
withoutDescription: true
})
const apps = await AppService.listApps({
workspace: $workspaceStore ?? '',