From 38b06bf3a718d9dfd53cecbcd370c71d034c0cf5 Mon Sep 17 00:00:00 2001 From: centdix <40307056+centdix@users.noreply.github.com> Date: Wed, 18 Jun 2025 13:08:59 +0200 Subject: [PATCH 01/24] internal: add /updatesqlx as git command (#5969) * add flow to update sqlx * archive aider * fix * add comments --- ....yaml => aider-after-review.yaml.archived} | 0 ...r-common.yml => aider-common.yml.archived} | 0 ...rnal.yaml => aider-external.yaml.archived} | 0 .../{aider.yaml => aider.yaml.archived} | 0 .github/workflows/update-sqlx.yaml | 98 +++++++++++++++++++ backend/update_sqlx.sh | 18 +++- 6 files changed, 114 insertions(+), 2 deletions(-) rename .github/workflows/{aider-after-review.yaml => aider-after-review.yaml.archived} (100%) rename .github/workflows/{aider-common.yml => aider-common.yml.archived} (100%) rename .github/workflows/{aider-external.yaml => aider-external.yaml.archived} (100%) rename .github/workflows/{aider.yaml => aider.yaml.archived} (100%) create mode 100644 .github/workflows/update-sqlx.yaml diff --git a/.github/workflows/aider-after-review.yaml b/.github/workflows/aider-after-review.yaml.archived similarity index 100% rename from .github/workflows/aider-after-review.yaml rename to .github/workflows/aider-after-review.yaml.archived diff --git a/.github/workflows/aider-common.yml b/.github/workflows/aider-common.yml.archived similarity index 100% rename from .github/workflows/aider-common.yml rename to .github/workflows/aider-common.yml.archived diff --git a/.github/workflows/aider-external.yaml b/.github/workflows/aider-external.yaml.archived similarity index 100% rename from .github/workflows/aider-external.yaml rename to .github/workflows/aider-external.yaml.archived diff --git a/.github/workflows/aider.yaml b/.github/workflows/aider.yaml.archived similarity index 100% rename from .github/workflows/aider.yaml rename to .github/workflows/aider.yaml.archived diff --git a/.github/workflows/update-sqlx.yaml b/.github/workflows/update-sqlx.yaml new file mode 100644 index 0000000000..ddb9bb9e67 --- /dev/null +++ b/.github/workflows/update-sqlx.yaml @@ -0,0 +1,98 @@ +name: Update SQLx + +on: + issue_comment: + types: [created] + +jobs: + update-sqlx: + if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/update-sqlx') + runs-on: ubicloud-standard-8 + permissions: + contents: write + pull-requests: write + issues: write + + services: + postgres: + image: postgres:14 + env: + POSTGRES_PASSWORD: postgres + POSTGRES_USER: postgres + POSTGRES_DB: windmill + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Comment on PR - Starting + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Starting sqlx update...' + }) + + - name: Checkout repository + uses: actions/checkout@v3 + with: + ref: ${{ github.event.issue.pull_request.head.ref }} + fetch-depth: 0 + + - name: Checkout windmill-ee-private + uses: actions/checkout@v3 + with: + repository: windmill-labs/windmill-ee-private + path: windmill-ee-private + token: ${{ secrets.EE_PRIVATE_TOKEN }} + + - name: Install xmlsec build-time deps + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + pkg-config libxml2-dev libssl-dev \ + xmlsec1 libxmlsec1-dev libxmlsec1-openssl + + - name: Run update-sqlx script + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/windmill + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER=${{ github.event.issue.number }} + BRANCH_NAME=$(gh pr view $PR_NUMBER --json headRefName --jq .headRefName) + echo "Checking out PR branch: $BRANCH_NAME" + git checkout $BRANCH_NAME + cd backend + cargo install sqlx-cli + sqlx migrate run + ./update_sqlx.sh --dir ./windmill-ee-private + # Pass the branch name to the next step + echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV + + - name: Commit changes if any + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add backend/.sqlx + git commit -m "Update SQLx metadata" + git push origin ${{ env.BRANCH_NAME }} + + - name: Comment on PR - Completed + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Successfully ran sqlx update' + }) diff --git a/backend/update_sqlx.sh b/backend/update_sqlx.sh index 09824d9e24..6e64115ce0 100755 --- a/backend/update_sqlx.sh +++ b/backend/update_sqlx.sh @@ -1,4 +1,18 @@ -./substitute_ee_code.sh --dir ../windmill-ee-private +#!/bin/bash + +# Default directory +EE_DIR="../windmill-ee-private" + +# Parse arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --dir) EE_DIR="$2"; shift ;; + *) echo "Unknown parameter: $1"; exit 1 ;; + esac + shift +done + +./substitute_ee_code.sh --dir "$EE_DIR" # Check if running on macOS if [[ "$(uname)" == "Darwin" ]]; then @@ -18,4 +32,4 @@ if [[ "$(uname)" == "Darwin" ]]; then sed -i '' 's/^#samael = { version="0.0.14", features = \["xmlsec"\] }/samael = { version="0.0.14", features = ["xmlsec"] }/' Cargo.toml # Comment out the git-based samael dependency sed -i '' 's/^\(samael = { git="https:\/\/github.com\/njaremko\/samael", rev="464d015e3ae393e4b5dd00b4d6baa1b617de0dd6", features = \["xmlsec"\] }\)/# \1/' Cargo.toml -fi +fi \ No newline at end of file From 959280bf5ad6a55d8506929e13ba05e3e93656a7 Mon Sep 17 00:00:00 2001 From: centdix <40307056+centdix@users.noreply.github.com> Date: Wed, 18 Jun 2025 13:22:11 +0200 Subject: [PATCH 02/24] fix wrong typo (#5970) --- .github/workflows/update-sqlx.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-sqlx.yaml b/.github/workflows/update-sqlx.yaml index ddb9bb9e67..03ecba25b6 100644 --- a/.github/workflows/update-sqlx.yaml +++ b/.github/workflows/update-sqlx.yaml @@ -6,7 +6,7 @@ on: jobs: update-sqlx: - if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/update-sqlx') + if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/updatesqlx') runs-on: ubicloud-standard-8 permissions: contents: write @@ -52,7 +52,7 @@ jobs: with: repository: windmill-labs/windmill-ee-private path: windmill-ee-private - token: ${{ secrets.EE_PRIVATE_TOKEN }} + token: ${{ secrets.WINDMILL_EE_PRIVATE_ACCESS }} - name: Install xmlsec build-time deps run: | From be0c8ddae087fab89bc5c7aa70ff1367fa3c7077 Mon Sep 17 00:00:00 2001 From: Diego Imbert <70353967+diegoimbert@users.noreply.github.com> Date: Wed, 18 Jun 2025 14:25:55 +0200 Subject: [PATCH 03/24] prevent datatable from spamming loadMore on scroll to end (#5973) --- .../src/lib/components/table/DataTable.svelte | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/frontend/src/lib/components/table/DataTable.svelte b/frontend/src/lib/components/table/DataTable.svelte index 82b2f3f401..2fed249679 100644 --- a/frontend/src/lib/components/table/DataTable.svelte +++ b/frontend/src/lib/components/table/DataTable.svelte @@ -73,7 +73,7 @@ const hasScrollbar = tableContainer.scrollHeight > tableContainer.clientHeight if (!hasScrollbar && hasMore) { - dispatch('loadMore') + triggerLoadMore() } } @@ -92,11 +92,20 @@ if (!tableContainer) return const { scrollTop, scrollHeight, clientHeight } = tableContainer - if (scrollHeight - (scrollTop + clientHeight) < 50) { - dispatch('loadMore') + if (scrollHeight - (scrollTop + clientHeight) === 0) { + triggerLoadMore() } } + let lastLoadMoreDispatch: number | undefined = $state(undefined) + function triggerLoadMore() { + if (lastLoadMoreDispatch && Date.now() - lastLoadMoreDispatch < 1000) { + return + } + dispatch('loadMore') + lastLoadMoreDispatch = Date.now() + } + $effect(() => { if (tableContainer && hasMore && !loading) { untrack(() => checkScrollStatus()) @@ -170,7 +179,7 @@ diff --git a/frontend/src/routes/(root)/(logged)/workers/+page.svelte b/frontend/src/routes/(root)/(logged)/workers/+page.svelte index 749a17755d..139ee18e9b 100644 --- a/frontend/src/routes/(root)/(logged)/workers/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workers/+page.svelte @@ -19,6 +19,7 @@ import { enterpriseLicense, superadmin, + devopsRole, userStore, workspaceStore, userWorkspaces @@ -131,7 +132,7 @@ loadWorkers() loadWorkerGroups() loadCustomTags() - $: $superadmin && loadDefaultTagsPerWorkspace() + $: ($superadmin || $devopsRole) && loadDefaultTagsPerWorkspace() onDestroy(() => { if (intervalId) { @@ -271,7 +272,7 @@ } -{#if $superadmin} +{#if $superadmin || $devopsRole} {/if} @@ -331,7 +332,7 @@ tooltip="The workers are the dutiful servants that execute the jobs." documentationLink="https://www.windmill.dev/docs/core_concepts/worker_groups" > - {#if $superadmin} + {#if $superadmin || $devopsRole}
- {#if $superadmin} + {#if $superadmin || $devopsRole}
-
+
{ + // Prevent keyboard events from bubbling to SvelteFlow + e.stopPropagation() + }} + > {#if selectedNode}
@@ -92,6 +98,10 @@ renderCount++ }, 300)() }} + on:keydown={(e) => { + // Prevent keyboard events from bubbling to SvelteFlow + e.stopPropagation() + }} /> From 530a72ba83629a764d3a8b034ce9bb53e7c82b32 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Thu, 19 Jun 2025 00:58:56 +0200 Subject: [PATCH 18/24] chore(main): release 1.499.0 (#5990) * chore(main): release 1.499.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> --- CHANGELOG.md | 12 +++ backend/Cargo.lock | 86 +++++++++---------- backend/Cargo.toml | 4 +- backend/windmill-api/openapi.yaml | 2 +- benchmarks/lib.ts | 2 +- cli/main.ts | 2 +- frontend/package-lock.json | 4 +- frontend/package.json | 2 +- lsp/Pipfile | 4 +- openflow.openapi.yaml | 2 +- .../WindmillClient/WindmillClient.psd1 | 2 +- python-client/wmill/pyproject.toml | 2 +- python-client/wmill_pg/pyproject.toml | 2 +- typescript-client/jsr.json | 2 +- typescript-client/package.json | 2 +- version.txt | 2 +- 16 files changed, 72 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a496bda1b5..d52dfb4622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.499.0](https://github.com/windmill-labs/windmill/compare/v1.498.0...v1.499.0) (2025-06-18) + + +### Features + +* devOps role can edit worker groups ([#5984](https://github.com/windmill-labs/windmill/issues/5984)) ([b1c4f8b](https://github.com/windmill-labs/windmill/commit/b1c4f8b29d0fb4cad76853110b84a87892b54661)) + + +### Bug Fixes + +* prevent keypress events from bubbling in decision tree drawer ([#5993](https://github.com/windmill-labs/windmill/issues/5993)) ([2a33442](https://github.com/windmill-labs/windmill/commit/2a334421e85abf046784aab57522582439ef2901)) + ## [1.498.0](https://github.com/windmill-labs/windmill/compare/v1.497.2...v1.498.0) (2025-06-17) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 24fb8436bb..73a66bb231 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -741,9 +741,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-config" @@ -902,9 +902,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.74.0" +version = "1.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d440e1d368759bd10df0dbdddbfff6473d7cd73e9d9ef2363dc9995ac2d711" +checksum = "e3258fa707f2f585ee3049d9550954b959002abd59176975150a01d5cf38ae3f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -2303,9 +2303,9 @@ dependencies = [ [[package]] name = "croner" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38fd53511eaf0b00a185613875fee58b208dfce016577d0ad4bb548e1c4fb3ee" +checksum = "c344b0690c1ad1c7176fe18eb173e0c927008fdaaa256e40dfd43ddd149c0843" dependencies = [ "chrono", ] @@ -7188,9 +7188,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.173" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libduckdb-sys" @@ -10410,7 +10410,7 @@ dependencies = [ [[package]] name = "rmcp" version = "0.1.5" -source = "git+https://github.com/modelcontextprotocol/rust-sdk#d1884fe598cd4c524ff6e0101859a60d4b4c8b8f" +source = "git+https://github.com/modelcontextprotocol/rust-sdk#8a577659f01917289064c0a3c753392b44305ef4" dependencies = [ "base64 0.22.1", "bytes", @@ -10439,7 +10439,7 @@ dependencies = [ [[package]] name = "rmcp-macros" version = "0.1.5" -source = "git+https://github.com/modelcontextprotocol/rust-sdk#d1884fe598cd4c524ff6e0101859a60d4b4c8b8f" +source = "git+https://github.com/modelcontextprotocol/rust-sdk#8a577659f01917289064c0a3c753392b44305ef4" dependencies = [ "proc-macro2", "quote", @@ -11922,9 +11922,9 @@ dependencies = [ [[package]] name = "sse-stream" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f649a9f9e91db2ed32f3724516eac2bc09fab77fc33be8f670f5619b9dc6c3f" +checksum = "eb4dc4d33c68ec1f27d386b5610a351922656e1fdf5c05bbaad930cd1519479a" dependencies = [ "bytes", "futures-util", @@ -14564,7 +14564,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windmill" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "axum", @@ -14616,7 +14616,7 @@ dependencies = [ [[package]] name = "windmill-api" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "argon2", @@ -14727,7 +14727,7 @@ dependencies = [ [[package]] name = "windmill-api-client" -version = "1.498.0" +version = "1.499.0" dependencies = [ "base64 0.22.1", "chrono", @@ -14742,7 +14742,7 @@ dependencies = [ [[package]] name = "windmill-audit" -version = "1.498.0" +version = "1.499.0" dependencies = [ "chrono", "serde", @@ -14755,7 +14755,7 @@ dependencies = [ [[package]] name = "windmill-autoscaling" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "serde", @@ -14769,7 +14769,7 @@ dependencies = [ [[package]] name = "windmill-common" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "async-stream", @@ -14846,7 +14846,7 @@ dependencies = [ [[package]] name = "windmill-git-sync" -version = "1.498.0" +version = "1.499.0" dependencies = [ "regex", "serde", @@ -14860,7 +14860,7 @@ dependencies = [ [[package]] name = "windmill-indexer" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "bytes", @@ -14883,7 +14883,7 @@ dependencies = [ [[package]] name = "windmill-macros" -version = "1.498.0" +version = "1.499.0" dependencies = [ "itertools 0.14.0", "lazy_static", @@ -14895,7 +14895,7 @@ dependencies = [ [[package]] name = "windmill-parser" -version = "1.498.0" +version = "1.499.0" dependencies = [ "convert_case 0.6.0", "serde", @@ -14904,7 +14904,7 @@ dependencies = [ [[package]] name = "windmill-parser-bash" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "lazy_static", @@ -14916,7 +14916,7 @@ dependencies = [ [[package]] name = "windmill-parser-csharp" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "serde_json", @@ -14928,7 +14928,7 @@ dependencies = [ [[package]] name = "windmill-parser-go" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "gosyn", @@ -14940,7 +14940,7 @@ dependencies = [ [[package]] name = "windmill-parser-graphql" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "lazy_static", @@ -14952,7 +14952,7 @@ dependencies = [ [[package]] name = "windmill-parser-java" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "serde_json", @@ -14964,7 +14964,7 @@ dependencies = [ [[package]] name = "windmill-parser-nu" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "nu-parser", @@ -14975,7 +14975,7 @@ dependencies = [ [[package]] name = "windmill-parser-php" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "itertools 0.14.0", @@ -14986,7 +14986,7 @@ dependencies = [ [[package]] name = "windmill-parser-py" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "itertools 0.14.0", @@ -14997,7 +14997,7 @@ dependencies = [ [[package]] name = "windmill-parser-py-imports" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "async-recursion", @@ -15020,7 +15020,7 @@ dependencies = [ [[package]] name = "windmill-parser-rust" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -15037,7 +15037,7 @@ dependencies = [ [[package]] name = "windmill-parser-sql" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "lazy_static", @@ -15049,7 +15049,7 @@ dependencies = [ [[package]] name = "windmill-parser-ts" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "lazy_static", @@ -15067,7 +15067,7 @@ dependencies = [ [[package]] name = "windmill-parser-wasm" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "getrandom 0.2.16", @@ -15091,7 +15091,7 @@ dependencies = [ [[package]] name = "windmill-parser-yaml" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "serde_json", @@ -15101,7 +15101,7 @@ dependencies = [ [[package]] name = "windmill-queue" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "async-recursion", @@ -15134,7 +15134,7 @@ dependencies = [ [[package]] name = "windmill-sql-datatype-parser-wasm" -version = "1.498.0" +version = "1.499.0" dependencies = [ "wasm-bindgen", "wasm-bindgen-test", @@ -15144,7 +15144,7 @@ dependencies = [ [[package]] name = "windmill-worker" -version = "1.498.0" +version = "1.499.0" dependencies = [ "anyhow", "async-recursion", @@ -15865,18 +15865,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 1ac013b916..506f360852 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windmill" -version = "1.498.0" +version = "1.499.0" authors.workspace = true edition.workspace = true @@ -32,7 +32,7 @@ members = [ ] [workspace.package] -version = "1.498.0" +version = "1.499.0" authors = ["Ruben Fiszel "] edition = "2021" diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index a5e693277e..6922c98379 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.498.0 + version: 1.499.0 title: Windmill API contact: diff --git a/benchmarks/lib.ts b/benchmarks/lib.ts index 45de71358f..a988908588 100644 --- a/benchmarks/lib.ts +++ b/benchmarks/lib.ts @@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts"; import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts"; import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts"; -export const VERSION = "v1.498.0"; +export const VERSION = "v1.499.0"; export async function login(email: string, password: string): Promise { return await windmill.UserService.login({ diff --git a/cli/main.ts b/cli/main.ts index 3a505bbc18..f0ad23f8cf 100644 --- a/cli/main.ts +++ b/cli/main.ts @@ -63,7 +63,7 @@ export { // } // }); -export const VERSION = "1.498.0"; +export const VERSION = "1.499.0"; const command = new Command() .name("wmill") diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 02bb998500..e4b6658b41 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "windmill-components", - "version": "1.498.0", + "version": "1.499.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windmill-components", - "version": "1.498.0", + "version": "1.499.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index bee87418b0..9cf40edea3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "windmill-components", - "version": "1.498.0", + "version": "1.499.0", "scripts": { "dev": "vite dev", "build": "vite build", diff --git a/lsp/Pipfile b/lsp/Pipfile index bb3d094961..55e2072ce4 100644 --- a/lsp/Pipfile +++ b/lsp/Pipfile @@ -4,8 +4,8 @@ verify_ssl = true name = "pypi" [packages] -wmill = ">=1.498.0" -wmill_pg = ">=1.498.0" +wmill = ">=1.499.0" +wmill_pg = ">=1.499.0" sendgrid = "*" mysql-connector-python = "*" pymongo = "*" diff --git a/openflow.openapi.yaml b/openflow.openapi.yaml index a13eaee9be..a25dabb602 100644 --- a/openflow.openapi.yaml +++ b/openflow.openapi.yaml @@ -1,7 +1,7 @@ openapi: "3.0.3" info: - version: 1.498.0 + version: 1.499.0 title: OpenFlow Spec contact: name: Ruben Fiszel diff --git a/powershell-client/WindmillClient/WindmillClient.psd1 b/powershell-client/WindmillClient/WindmillClient.psd1 index e4c28508d1..4eaafc91e3 100644 --- a/powershell-client/WindmillClient/WindmillClient.psd1 +++ b/powershell-client/WindmillClient/WindmillClient.psd1 @@ -12,7 +12,7 @@ RootModule = 'WindmillClient.psm1' # Version number of this module. - ModuleVersion = '1.498.0' + ModuleVersion = '1.499.0' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/python-client/wmill/pyproject.toml b/python-client/wmill/pyproject.toml index c547216c76..2248094357 100644 --- a/python-client/wmill/pyproject.toml +++ b/python-client/wmill/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill" -version = "1.498.0" +version = "1.499.0" description = "A client library for accessing Windmill server wrapping the Windmill client API" license = "Apache-2.0" homepage = "https://windmill.dev" diff --git a/python-client/wmill_pg/pyproject.toml b/python-client/wmill_pg/pyproject.toml index a664711828..3847adc1c1 100644 --- a/python-client/wmill_pg/pyproject.toml +++ b/python-client/wmill_pg/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "wmill-pg" -version = "1.498.0" +version = "1.499.0" description = "An extension client for the wmill client library focused on pg" license = "Apache-2.0" homepage = "https://windmill.dev" diff --git a/typescript-client/jsr.json b/typescript-client/jsr.json index a8146e05ec..e5c9953a98 100644 --- a/typescript-client/jsr.json +++ b/typescript-client/jsr.json @@ -1,6 +1,6 @@ { "name": "@windmill/windmill", - "version": "1.498.0", + "version": "1.499.0", "exports": "./src/index.ts", "publish": { "exclude": ["!src", "./s3Types.ts", "./client.ts"] diff --git a/typescript-client/package.json b/typescript-client/package.json index e81d522a28..22838073f6 100644 --- a/typescript-client/package.json +++ b/typescript-client/package.json @@ -1,7 +1,7 @@ { "name": "windmill-client", "description": "Windmill SDK client for browsers and Node.js", - "version": "1.498.0", + "version": "1.499.0", "author": "Ruben Fiszel", "license": "Apache 2.0", "devDependencies": { diff --git a/version.txt b/version.txt index a54f0c9fdf..1c31ddf8a0 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.498.0 +1.499.0 From 054f2c134adf04fbae0a35efea0d1ab8665ac0e4 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Thu, 19 Jun 2025 08:07:03 +0200 Subject: [PATCH 19/24] improve decision tree builder --- .../components/layout/AppDecisionTree.svelte | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte b/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte index f92bbde678..d595a7d85a 100644 --- a/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte +++ b/frontend/src/lib/components/apps/components/layout/AppDecisionTree.svelte @@ -24,19 +24,29 @@ let { id, componentContainerHeight, customCss = undefined, render, nodes }: Props = $props() - let resolvedConditions = $state( - nodes.reduce((acc, node) => { + let resolvedConditions = $state(createResolvedConditions()) + + function createResolvedConditions() { + return nodes.reduce((acc, node) => { acc[node.id] = acc[node.id] || [] return acc }, {}) - ) + } - let resolvedNext = $state( - nodes.reduce((acc, node) => { + let resolvedNext = $state(createResolvedNext()) + + function createResolvedNext() { + return nodes.reduce((acc, node) => { acc[node.id] = acc[node.id] || false return acc }, {}) - ) + } + + $effect(() => { + nodes + resolvedConditions = untrack(() => createResolvedConditions()) + resolvedNext = untrack(() => createResolvedNext()) + }) let everRender = $state(render) $effect.pre(() => { From fa8d1b47db19e15fe854e01f9987c8f97cb45b44 Mon Sep 17 00:00:00 2001 From: Diego Imbert <70353967+diegoimbert@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:37:17 +0200 Subject: [PATCH 20/24] fix: new MultiSelect component (#5979) * rename all multiselects to Legacy * move Select * Separate SelectDropdown * fix click outside for select with portal * multiselect v0 * multiselect clear btn * move filterText logic to SelectDropdown * ui nits * console.log * draggable * Draggable multiselect * multiselect search * nit refacto * autofocus multiselect input * Replace in AppMultiSelectV2 * search icon * app multi select nits * arginput update multiselect * fix autofocus scrolling up * replace High priority tags multiselect * autoscaling config editor multiselect replace * fix clear btn not in border * replace multiselect in cron input * replace multiselect in savedinputs * replace EventHandlerItem multiselect * select dropdown shadow * more multiselect migration * hover opacity on drag * TokensTable UI fixes + replace multiselect * ai settings replace multiselect * DefaultTags Multiselect replace * prevent multiselect from opening on drag * nit * app multiselect css + simplify * console log * safeSelectItems cleanup * Remove svelte-multiselect * clip when wrap not allowed * hide duplicate app components * CSS works better with multiselect in app editor * allowOverflow * allowClear * fix custom createText messed up with search --- frontend/package-lock.json | 10 - frontend/package.json | 1 - frontend/src/lib/components/ArgEnum.svelte | 2 +- frontend/src/lib/components/ArgInput.svelte | 44 +- .../components/AutoscalingConfigEditor.svelte | 33 +- .../src/lib/components/ChannelSelector.svelte | 2 +- frontend/src/lib/components/CronInput.svelte | 35 +- .../src/lib/components/DBTableEditor.svelte | 5 +- .../src/lib/components/DefaultTags.svelte | 2 +- .../lib/components/DefaultTagsInner.svelte | 13 +- .../src/lib/components/FolderEditor.svelte | 5 +- .../src/lib/components/GroupEditor.svelte | 5 +- .../LightweightResourcePicker.svelte | 2 +- .../src/lib/components/ResourcePicker.svelte | 2 +- .../src/lib/components/SavedInputsV2.svelte | 9 +- .../src/lib/components/ScriptPicker.svelte | 2 +- frontend/src/lib/components/Select.svelte | 271 ------ .../lib/components/ServiceLogsInner.svelte | 5 +- frontend/src/lib/components/ShareModal.svelte | 9 +- .../src/lib/components/TagsToListenTo.svelte | 11 +- .../src/lib/components/TeamSelector.svelte | 2 +- .../src/lib/components/WorkerGroup.svelte | 41 +- frontend/src/lib/components/WorkerRepl.svelte | 2 +- .../src/lib/components/WorkerTagSelect.svelte | 5 +- .../apps/components/buttons/AppForm.svelte | 1 - .../components/inputs/AppDateSelect.svelte | 14 +- .../components/inputs/AppMultiSelect.svelte | 3 - .../components/inputs/AppMultiSelectV2.svelte | 240 ++--- .../apps/components/inputs/AppSelect.svelte | 2 +- .../components/apps/editor/AppEditor.svelte | 2 +- .../components/apps/editor/GridEditor.svelte | 1 + .../apps/editor/component/components.ts | 5 + .../components/apps/editor/component/sets.ts | 4 +- .../componentsPanel/CssHelperPanel.svelte | 4 +- .../apps/editor/componentsPanel/cssUtils.ts | 21 +- .../settingsPanel/EventHandlerItem.svelte | 16 +- .../inputEditor/DBTableSelect.svelte | 2 +- .../auditLogs/AuditLogsFilters.svelte | 5 +- .../lib/components/common/CloseButton.svelte | 1 + .../common/drawer/ConditionalPortal.svelte | 19 +- .../components/multiselect/MultiSelect.svelte | 828 ------------------ .../multiselect/MultiSelectWrapper.svelte | 130 --- .../src/lib/components/multiselect/types.ts | 47 - .../src/lib/components/multiselect/utils.ts | 64 -- .../src/lib/components/runs/RunsFilter.svelte | 15 +- .../schema/EditableSchemaWrapper.svelte | 5 +- .../search/GlobalSearchModal.svelte | 3 +- .../components/select/DraggableTags.svelte | 63 ++ .../lib/components/select/MultiSelect.svelte | 176 ++++ .../src/lib/components/select/Select.svelte | 156 ++++ .../components/select/SelectDropdown.svelte | 147 ++++ .../src/lib/components/select/utils.svelte.ts | 72 ++ .../components/settings/CreateToken.svelte | 5 +- .../components/settings/TokensTable.svelte | 14 +- .../gcp/GcpTriggerEditorConfigSection.svelte | 7 +- .../triggers/http/OpenAPISpecGenerator.svelte | 5 +- .../PostgresTriggerEditorInner.svelte | 41 +- .../postgres/PublicationPicker.svelte | 5 +- .../triggers/postgres/RelationPicker.svelte | 75 +- .../triggers/postgres/SlotPicker.svelte | 5 +- .../sqs/SqsTriggerEditorConfigSection.svelte | 28 +- .../workspaceSettings/AISettings.svelte | 15 +- frontend/src/lib/utils.ts | 37 +- .../(root)/(logged)/workers/+page.svelte | 26 +- 64 files changed, 969 insertions(+), 1858 deletions(-) delete mode 100644 frontend/src/lib/components/Select.svelte delete mode 100644 frontend/src/lib/components/multiselect/MultiSelect.svelte delete mode 100644 frontend/src/lib/components/multiselect/MultiSelectWrapper.svelte delete mode 100644 frontend/src/lib/components/multiselect/types.ts delete mode 100644 frontend/src/lib/components/multiselect/utils.ts create mode 100644 frontend/src/lib/components/select/DraggableTags.svelte create mode 100644 frontend/src/lib/components/select/MultiSelect.svelte create mode 100644 frontend/src/lib/components/select/Select.svelte create mode 100644 frontend/src/lib/components/select/SelectDropdown.svelte create mode 100644 frontend/src/lib/components/select/utils.svelte.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e4b6658b41..ce57c0026d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -132,7 +132,6 @@ "svelte-check": "^4.0.0", "svelte-floating-ui": "^1.5.8", "svelte-highlight": "^7.6.0", - "svelte-multiselect": "^11.0.0-rc.1", "svelte-popperjs": "^1.3.2", "svelte-preprocess": "^6.0.0", "svelte-range-slider-pips": "^2.3.1", @@ -11862,15 +11861,6 @@ "resolved": "https://registry.npmjs.org/svelte-infinite-loading/-/svelte-infinite-loading-1.4.0.tgz", "integrity": "sha512-Jo+f/yr/HmZQuIiiKKzAHVFXdAUWHW2RBbrcQTil8JVk1sCm/riy7KTJVzjBgQvHasrFQYKF84zvtc9/Y4lFYg==" }, - "node_modules/svelte-multiselect": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/svelte-multiselect/-/svelte-multiselect-11.1.0.tgz", - "integrity": "sha512-D93t6GlOV//gU7upR59uCd755Hq6OWhqv9ddhOXBDN/mEZj5XOAYHwDjUjePUKlE+bI+jry1BlZef8Mof2Y+YA==", - "dev": true, - "peerDependencies": { - "svelte": "^5.8.0" - } - }, "node_modules/svelte-popperjs": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/svelte-popperjs/-/svelte-popperjs-1.3.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 9cf40edea3..cab3c1d9a6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -57,7 +57,6 @@ "svelte-check": "^4.0.0", "svelte-floating-ui": "^1.5.8", "svelte-highlight": "^7.6.0", - "svelte-multiselect": "^11.0.0-rc.1", "svelte-popperjs": "^1.3.2", "svelte-preprocess": "^6.0.0", "svelte-range-slider-pips": "^2.3.1", diff --git a/frontend/src/lib/components/ArgEnum.svelte b/frontend/src/lib/components/ArgEnum.svelte index b1f94d39f0..d87d34ea33 100644 --- a/frontend/src/lib/components/ArgEnum.svelte +++ b/frontend/src/lib/components/ArgEnum.svelte @@ -1,7 +1,7 @@ diff --git a/frontend/src/lib/components/DefaultTagsInner.svelte b/frontend/src/lib/components/DefaultTagsInner.svelte index 5e4e824787..ab715770de 100644 --- a/frontend/src/lib/components/DefaultTagsInner.svelte +++ b/frontend/src/lib/components/DefaultTagsInner.svelte @@ -7,11 +7,12 @@ import { enterpriseLicense, superadmin } from '$lib/stores' import { DEFAULT_TAGS_PER_WORKSPACE_SETTING, DEFAULT_TAGS_WORKSPACES_SETTING } from '$lib/consts' import Toggle from './Toggle.svelte' - import MultiSelectWrapper from './multiselect/MultiSelectWrapper.svelte' + import MultiSelect from './select/MultiSelect.svelte' + import { safeSelectItems } from './select/utils.svelte' let defaultTags: string[] | undefined = undefined export let defaultTagPerWorkspace: boolean | undefined = undefined - export let defaultTagWorkspaces: string[] | undefined = undefined + export let defaultTagWorkspaces: string[] = [] let limitToWorkspaces = false let workspaces: string[] = [] @@ -62,7 +63,7 @@
{/each}
-
+
{#if limitToWorkspaces} - {/if} diff --git a/frontend/src/lib/components/FolderEditor.svelte b/frontend/src/lib/components/FolderEditor.svelte index 5ae36a7e24..38f980f042 100644 --- a/frontend/src/lib/components/FolderEditor.svelte +++ b/frontend/src/lib/components/FolderEditor.svelte @@ -18,7 +18,8 @@ import Label from './Label.svelte' import { sendUserToast } from '$lib/toast' import { createEventDispatcher } from 'svelte' - import Select from './Select.svelte' + import Select from './select/Select.svelte' + import { safeSelectItems } from './select/utils.svelte' export let name: string let can_write = false @@ -197,7 +198,7 @@ ownerKind === 'user' ? usernames.filter((x) => !perms?.map((y) => y.owner_name).includes('u/' + x)) : groups.filter((x) => !perms?.map((y) => y.owner_name).includes('g/' + x))} - {#if ownerKind == 'group'} diff --git a/frontend/src/lib/components/LightweightResourcePicker.svelte b/frontend/src/lib/components/LightweightResourcePicker.svelte index 50da38607b..87570466b4 100644 --- a/frontend/src/lib/components/LightweightResourcePicker.svelte +++ b/frontend/src/lib/components/LightweightResourcePicker.svelte @@ -8,7 +8,7 @@ import type { AppViewerContext } from './apps/types' import { sendUserToast } from '$lib/toast' import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted' - import Select from './Select.svelte' + import Select from './select/Select.svelte' const dispatch = createEventDispatcher() const dispatchIfMounted = createDispatcherIfMounted(dispatch) diff --git a/frontend/src/lib/components/ResourcePicker.svelte b/frontend/src/lib/components/ResourcePicker.svelte index a07596fc34..f136fd32a6 100644 --- a/frontend/src/lib/components/ResourcePicker.svelte +++ b/frontend/src/lib/components/ResourcePicker.svelte @@ -10,7 +10,7 @@ import { Pen, Plus, RotateCw } from 'lucide-svelte' import { sendUserToast } from '$lib/toast' import { isDbType } from './apps/components/display/dbtable/utils' - import Select from './Select.svelte' + import Select from './select/Select.svelte' import { createDispatcherIfMounted } from '$lib/createDispatcherIfMounted' const dispatch = createEventDispatcher() diff --git a/frontend/src/lib/components/SavedInputsV2.svelte b/frontend/src/lib/components/SavedInputsV2.svelte index 538f3ce05f..0fb4f89e58 100644 --- a/frontend/src/lib/components/SavedInputsV2.svelte +++ b/frontend/src/lib/components/SavedInputsV2.svelte @@ -10,7 +10,8 @@ import { ExternalLink, Search } from 'lucide-svelte' import { Popover } from './meltComponents' import SchemaForm from './SchemaForm.svelte' - import MultiSelect from './multiselect/MultiSelectWrapper.svelte' + import MultiSelect from './select/MultiSelect.svelte' + import { safeSelectItems } from './select/utils.svelte' const dispatch = createEventDispatcher() interface Props { @@ -142,7 +143,6 @@ {/snippet} {#snippet content()} -
Search by args
@@ -175,11 +175,10 @@
{#key filteredSchema} diff --git a/frontend/src/lib/components/ScriptPicker.svelte b/frontend/src/lib/components/ScriptPicker.svelte index 0bb0a9caca..c4fe27167a 100644 --- a/frontend/src/lib/components/ScriptPicker.svelte +++ b/frontend/src/lib/components/ScriptPicker.svelte @@ -5,7 +5,7 @@ import { base } from '$lib/base' import { createEventDispatcher, untrack } from 'svelte' - import Select from './Select.svelte' + import Select from './select/Select.svelte' import { getScriptByPath } from '$lib/scripts' import { Button, Drawer, DrawerContent } from './common' diff --git a/frontend/src/lib/components/Select.svelte b/frontend/src/lib/components/Select.svelte deleted file mode 100644 index 0afdf2cc32..0000000000 --- a/frontend/src/lib/components/Select.svelte +++ /dev/null @@ -1,271 +0,0 @@ - - - { - if (!open || !processedItems?.length) return - if (e.key === 'ArrowUp' && keyArrowPos !== undefined && processedItems.length > 0) { - keyArrowPos = keyArrowPos <= 0 ? undefined : keyArrowPos - 1 - } else if (e.key === 'ArrowDown') { - if (keyArrowPos === undefined) { - keyArrowPos = 0 - } else { - keyArrowPos = Math.min(processedItems.length - 1, keyArrowPos + 1) - } - } else if (e.key === 'Enter' && keyArrowPos !== undefined && processedItems?.[keyArrowPos]) { - setValue(processedItems[keyArrowPos]) - } else { - keyArrowPos = undefined - return - } - e.preventDefault() - }} -/> - -
(open = false) }} - onpointerdown={() => onFocus?.()} - onfocus={() => onFocus?.()} - onblur={() => onBlur?.()} -> - {#if loading} -
- -
- {:else if clearable && !disabled && value} -
- -
- {:else if RightIcon} -
- -
- {/if} - - filterText, (v) => (filterText = v)} - placeholder={loading ? 'Loading...' : (valueEntry?.label ?? placeholder)} - style={containerStyle} - class={twMerge( - '!bg-surface text-ellipsis', - open ? '' : 'cursor-pointer', - valueEntry && !loading ? '!placeholder-primary' : '', - (clearable || RightIcon) && !disabled && value ? '!pr-8' : '', - inputClass ?? '' - )} - autocomplete="off" - onpointerdown={() => (open = true)} - bind:this={inputEl} - /> - - - {#if open && !disabled} -
- {#if processedItems?.length === 0} -
No items
- {/if} - {#each processedItems ?? [] as item, itemIndex} - {#if (item.__select_group && itemIndex === 0) || processedItems?.[itemIndex - 1]?.__select_group !== item.__select_group} -
- {item.__select_group} -
- {/if} - - {/each} -
- {/if} -
-
diff --git a/frontend/src/lib/components/ServiceLogsInner.svelte b/frontend/src/lib/components/ServiceLogsInner.svelte index 4504d4e69d..b8b233bf6f 100644 --- a/frontend/src/lib/components/ServiceLogsInner.svelte +++ b/frontend/src/lib/components/ServiceLogsInner.svelte @@ -11,14 +11,13 @@ import { sendUserToast } from '$lib/toast' import { onDestroy, tick, untrack } from 'svelte' import { Loader2 } from 'lucide-svelte' - import { copyToClipboard, truncateRev } from '$lib/utils' + import { copyToClipboard, scroll_into_view_if_needed_polyfill, truncateRev } from '$lib/utils' import LogSnippetViewer from './LogSnippetViewer.svelte' import { Button, Drawer, DrawerContent } from './common' import ClipboardCopy from 'lucide-svelte/icons/clipboard-copy' import AnsiUp from 'ansi_up' - import { scroll_into_view_if_needed_polyfill } from './multiselect/utils' import SplitPanesOrColumnOnMobile from './splitPanes/SplitPanesOrColumnOnMobile.svelte' - import Select from './Select.svelte' + import Select from './select/Select.svelte' import { goto } from '$lib/navigation' import { page } from '$app/stores' diff --git a/frontend/src/lib/components/ShareModal.svelte b/frontend/src/lib/components/ShareModal.svelte index eac1b0fefd..a8eeeeb9d1 100644 --- a/frontend/src/lib/components/ShareModal.svelte +++ b/frontend/src/lib/components/ShareModal.svelte @@ -13,7 +13,8 @@ import { isOwner } from '$lib/utils' import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte' import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte' - import Select from './Select.svelte' + import Select from './select/Select.svelte' + import { safeSelectItems } from './select/utils.svelte' const dispatch = createEventDispatcher() @@ -138,9 +139,9 @@
{#key ownerKind} !worker_tags?.includes(x)) - .map((x) => ({ value: x, label: x }))} + items={safeSelectItems( + [...(customTags ?? []), ...createdTags, ...defaultTags, ...nativeTags].filter( + (x) => !worker_tags?.includes(x) + ) + )} {disabled} bind:value={newTag} onFocus={() => dispatch('focus')} diff --git a/frontend/src/lib/components/TeamSelector.svelte b/frontend/src/lib/components/TeamSelector.svelte index 638c30d22f..899314bb31 100644 --- a/frontend/src/lib/components/TeamSelector.svelte +++ b/frontend/src/lib/components/TeamSelector.svelte @@ -2,7 +2,7 @@ import { workspaceStore } from '$lib/stores' import { RefreshCcw } from 'lucide-svelte' import { WorkspaceService } from '$lib/gen' - import Select from './Select.svelte' + import Select from './select/Select.svelte' import { onMount } from 'svelte' interface TeamItem { diff --git a/frontend/src/lib/components/WorkerGroup.svelte b/frontend/src/lib/components/WorkerGroup.svelte index 2dd2bd08ef..403995db2c 100644 --- a/frontend/src/lib/components/WorkerGroup.svelte +++ b/frontend/src/lib/components/WorkerGroup.svelte @@ -1,7 +1,6 @@ -{#each Object.keys(components['multiselectcomponent'].initialData.configuration) as key (key)} +{#each Object.keys(components['multiselectcomponentv2'].initialData.configuration) as key (key)} {/each} @@ -193,74 +160,33 @@
{ + class={twMerge('w-full', resolvedConfig.allowOverflow ? '' : 'absolute inset-0')} + onpointerdown={(e) => { $selectedComponent = [id] - - if (!e.shiftKey) { - e.stopPropagation() - } + if (!e.shiftKey) e.stopPropagation() selectedComponent.set([id]) }} - use:floatingRef - bind:clientWidth={w} > - {#if !selectedItems || Array.isArray(selectedItems)} - { - if (event?.detail?.type === 'removeAll') { - outputs?.result.set([]) - setContextValue([]) - } else { - setResultsFromSelectedItems() + { + customItems.push(item) + selectedItems.push(item) + customItems = customItems + selectedItems = selectedItems } - }} - on:open={() => { - $selectedComponent = [id] - open = true - }} - on:close={() => { - open = false - }} - let:option - > - - -
{ - let newe = new MouseEvent('mouseup') - e.target?.['parentElement']?.dispatchEvent(newe) - }} - > - {typeof option == 'object' ? (option?.label ?? 'NO_LABEL') : option} -
-
- - - - {:else} - Value {selectedItems} is not an array - {/if} + : undefined} + onOpen={() => ($selectedComponent = [id])} + />
diff --git a/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte b/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte index 5c9fff9c35..4e7d7dc8fc 100644 --- a/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte +++ b/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte @@ -19,7 +19,7 @@ import { Bug } from 'lucide-svelte' import Popover from '$lib/components/Popover.svelte' import ResolveStyle from '../helpers/ResolveStyle.svelte' - import Select from '$lib/components/Select.svelte' + import Select from '$lib/components/select/Select.svelte' interface Props { id: string diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte index d7555b8460..75db79da69 100644 --- a/frontend/src/lib/components/apps/editor/AppEditor.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte @@ -1256,7 +1256,7 @@ {:else}
- Select a component to see the settings for it + Select a component to see the settings for it
{/if} diff --git a/frontend/src/lib/components/apps/editor/GridEditor.svelte b/frontend/src/lib/components/apps/editor/GridEditor.svelte index 01a725683b..faa5a321e8 100644 --- a/frontend/src/lib/components/apps/editor/GridEditor.svelte +++ b/frontend/src/lib/components/apps/editor/GridEditor.svelte @@ -127,6 +127,7 @@ } +
({ id, forceStyle: true, forceClass: true })) }, ...Object.entries(ccomponents) - .filter(([key]) => key !== 'quillcomponent') + .filter(([key]) => !['quillcomponent', ...Object.keys(DEPRECATED_COMPONENTS)].includes(key)) .map(([type, { name, icon, customCss }]) => ({ type: type as keyof typeof components, name, diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/cssUtils.ts b/frontend/src/lib/components/apps/editor/componentsPanel/cssUtils.ts index 4634959ac0..8545d0627c 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/cssUtils.ts +++ b/frontend/src/lib/components/apps/editor/componentsPanel/cssUtils.ts @@ -676,8 +676,8 @@ export const customisationByComponent: Customisation[] = [ comment: 'buttons to remove a single or all selected options at once' }, { - selector: '.multiselect > input[autocomplete]', - comment: 'input inside the top-level wrapper div' + selector: '.multiselect.dropdown', + comment: 'dropdown container' }, { selector: '.multiselect > ul.options', @@ -686,23 +686,6 @@ export const customisationByComponent: Customisation[] = [ { selector: '.multiselect > ul.options > li', comment: 'dropdown list items' - }, - { - selector: '.multiselect > ul.options > li.selected', - comment: 'selected options in the dropdown list' - }, - { - selector: '.multiselect > ul.options > li:not(.selected):hover', - comment: 'unselected but hovered options in the dropdown list' - }, - { - selector: '.multiselect > ul.options > li.active', - comment: - 'active item, navigated to with up/down arrow keys and ready to be selected by pressing enter' - }, - { - selector: '.multiselect > ul.options > li.disabled', - comment: 'options with disabled key set to true' } ], variables: [ diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/EventHandlerItem.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/EventHandlerItem.svelte index 83b05f5fd0..37697dec9d 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/EventHandlerItem.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/EventHandlerItem.svelte @@ -1,11 +1,16 @@ {#if condition} - + {@render children?.()} {:else} - + {@render children?.()} {/if} diff --git a/frontend/src/lib/components/multiselect/MultiSelect.svelte b/frontend/src/lib/components/multiselect/MultiSelect.svelte deleted file mode 100644 index 1e4f00c66d..0000000000 --- a/frontend/src/lib/components/multiselect/MultiSelect.svelte +++ /dev/null @@ -1,828 +0,0 @@ - - - - - - - diff --git a/frontend/src/lib/components/multiselect/MultiSelectWrapper.svelte b/frontend/src/lib/components/multiselect/MultiSelectWrapper.svelte deleted file mode 100644 index 685c9b0801..0000000000 --- a/frontend/src/lib/components/multiselect/MultiSelectWrapper.svelte +++ /dev/null @@ -1,130 +0,0 @@ - - - - -
- {#if !value || Array.isArray(value)} -
- [...(value ?? [])], - (newVal) => { - if (!deepEqual(value, newVal)) { - value = newVal - } - } - } - {placeholder} - options={items} - on:close={() => { - open = false - }} - on:open={() => { - open = true - }} - let:option - disableRemoveAll - > -
{ - e.stopPropagation() - }} - onpointerdown={(e) => { - e.stopPropagation() - let newe = new MouseEvent('mouseup') - e.target?.['parentElement']?.dispatchEvent(newe) - }} - aria-selected={value?.includes(option)} - > - {option} -
-
-
- - - - {:else} - Value {value} is not an array - {/if} -
diff --git a/frontend/src/lib/components/multiselect/types.ts b/frontend/src/lib/components/multiselect/types.ts deleted file mode 100644 index d3dc4d7cac..0000000000 --- a/frontend/src/lib/components/multiselect/types.ts +++ /dev/null @@ -1,47 +0,0 @@ -export type Option = string | number | ObjectOption - -// single CSS string or an object with keys 'option' and 'selected', each a string, -// which only apply to the dropdown list and list of selected options, respectively -export type OptionStyle = string | { option: string; selected: string } - -export type ObjectOption = { - label: string | number // user-displayed text - value?: unknown // associated value, can be anything incl. objects (defaults to label if undefined) - title?: string // on-hover tooltip - disabled?: boolean // make this option unselectable - preselected?: boolean // make this option selected on page load (before any user interaction) - disabledTitle?: string // override the default disabledTitle = 'This option is disabled' - selectedTitle?: string // tooltip to display when this option is selected and hovered - style?: OptionStyle - [key: string]: unknown // allow any other keys users might want -} - -export type DispatchEvents = { - add: { option: T } - create: { option: T } - remove: { option: T } - removeAll: { options: T[] } - change: { - option?: T - options?: T[] - type: 'add' | 'remove' | 'removeAll' - } - open: { event: Event } - close: { event: Event } -} - -export type MultiSelectEvents = { - [key in keyof DispatchEvents]: CustomEvent -} & { - blur: FocusEvent - click: MouseEvent - focus: FocusEvent - keydown: KeyboardEvent - keyup: KeyboardEvent - mouseenter: MouseEvent - mouseleave: MouseEvent - touchcancel: TouchEvent - touchend: TouchEvent - touchmove: TouchEvent - touchstart: TouchEvent -} diff --git a/frontend/src/lib/components/multiselect/utils.ts b/frontend/src/lib/components/multiselect/utils.ts deleted file mode 100644 index a9bcfcaa69..0000000000 --- a/frontend/src/lib/components/multiselect/utils.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { Option, OptionStyle } from './types' - -// get the label key from an option object or the option itself if it's a string or number -export const get_label = (opt: Option) => { - if (opt instanceof Object) { - if (opt.label === undefined) { - console.error(`MultiSelect option ${JSON.stringify(opt)} is an object but has no label key`) - } - return opt.label - } - return `${opt}` -} - -// this function is used extract CSS strings from a {selected, option} style object to be used in the style attribute of the option -// if the style is a string, it will be returned as is -export function get_style( - option: { style?: OptionStyle; [key: string]: unknown } | string | number, - key: 'selected' | 'option' | null = null -) { - let css_str = `` - if (![`selected`, `option`, null].includes(key)) { - console.error(`MultiSelect: Invalid key=${key} for get_style`) - } - if (typeof option == `object` && option.style) { - if (typeof option.style == `string`) { - css_str = option.style - } - if (typeof option.style == `object`) { - if (key && key in option.style) return option.style[key] ?? `` - else { - console.error(`Invalid style object for option=${JSON.stringify(option)}`) - } - } - } - // ensure css_str ends with a semicolon - if (css_str.trim() && !css_str.trim().endsWith(`;`)) css_str += `;` - return css_str -} - -// Firefox lacks support for scrollIntoViewIfNeeded (https://caniuse.com/scrollintoviewifneeded). -// See https://github.com/janosh/svelte-multiselect/issues/87 -// Polyfill copied from -// https://github.com/nuxodin/lazyfill/blob/a8e63/polyfills/Element/prototype/scrollIntoViewIfNeeded.js -// exported for testing -export function scroll_into_view_if_needed_polyfill(elem: Element, centerIfNeeded: boolean = true) { - const observer = new IntersectionObserver(function ([entry]) { - const ratio = entry.intersectionRatio - if (ratio < 1) { - const place = ratio <= 0 && centerIfNeeded ? `center` : `nearest` - elem.scrollIntoView({ - block: place, - inline: place - }) - } - observer.disconnect() - }, { - root: null, // or specify a scrolling parent if needed - rootMargin: '0px 1000px', // Essentially making horizontal checks irrelevant - threshold: 0.1 // Adjust threshold to control when observer should trigger -}) - observer.observe(elem) - - return observer // return for testing -} diff --git a/frontend/src/lib/components/runs/RunsFilter.svelte b/frontend/src/lib/components/runs/RunsFilter.svelte index 6fd0b0ed03..77ab068bfe 100644 --- a/frontend/src/lib/components/runs/RunsFilter.svelte +++ b/frontend/src/lib/components/runs/RunsFilter.svelte @@ -12,7 +12,8 @@ import { createEventDispatcher, untrack } from 'svelte' import ToggleButtonMore from '../common/toggleButton-v2/ToggleButtonMore.svelte' import Popover from '$lib/components/meltComponents/Popover.svelte' - import Select from '../Select.svelte' + import Select from '../select/Select.svelte' + import { safeSelectItems } from '../select/utils.svelte' interface Props { // Filters @@ -174,7 +175,7 @@
User ({ label: p, value: p }))} + items={safeSelectItems(folders)} bind:value={() => folder ?? undefined, (v) => (folder = v ?? null)} clearable onClear={() => ((folder = null), dispatch('reset'))} @@ -203,7 +204,7 @@
Path ({ label: p, value: p }))} + items={safeSelectItems(usernames)} bind:value={() => user ?? undefined, (v) => (user = v ?? null)} clearable onClear={() => ((user = null), dispatch('reset'))} @@ -575,7 +576,7 @@
+ {/if} + {/snippet} + +
diff --git a/frontend/src/lib/components/select/Select.svelte b/frontend/src/lib/components/select/Select.svelte new file mode 100644 index 0000000000..ec0a4dcc47 --- /dev/null +++ b/frontend/src/lib/components/select/Select.svelte @@ -0,0 +1,156 @@ + + +
(open = false) }} + onpointerdown={() => onFocus?.()} + onfocus={() => onFocus?.()} + onblur={() => onBlur?.()} +> + {#if loading} +
+ +
+ {:else if clearable && !disabled && value} +
+ +
+ {:else if RightIcon} +
+ +
+ {/if} + + filterText, (v) => (filterText = v)} + placeholder={loading ? 'Loading...' : (valueEntry?.label ?? placeholder)} + style={containerStyle} + class={twMerge( + '!bg-surface text-ellipsis', + open ? '' : 'cursor-pointer', + valueEntry && !loading ? '!placeholder-primary' : '', + (clearable || RightIcon) && !disabled && value ? '!pr-8' : '', + inputClass ?? '' + )} + autocomplete="off" + onpointerdown={() => (open = true)} + bind:this={inputEl} + /> + inputEl!.getBoundingClientRect())} + {listAutoWidth} + {noItemsMsg} + /> +
diff --git a/frontend/src/lib/components/select/SelectDropdown.svelte b/frontend/src/lib/components/select/SelectDropdown.svelte new file mode 100644 index 0000000000..7780828a70 --- /dev/null +++ b/frontend/src/lib/components/select/SelectDropdown.svelte @@ -0,0 +1,147 @@ + + + { + if (!open || !processedItems?.length) return + if (e.key === 'ArrowUp' && keyArrowPos !== undefined && processedItems.length > 0) { + keyArrowPos = keyArrowPos <= 0 ? undefined : keyArrowPos - 1 + } else if (e.key === 'ArrowDown') { + if (keyArrowPos === undefined) { + keyArrowPos = 0 + } else { + keyArrowPos = Math.min(processedItems.length - 1, keyArrowPos + 1) + } + } else if (e.key === 'Enter' && keyArrowPos !== undefined && processedItems?.[keyArrowPos]) { + onSelectValue(processedItems[keyArrowPos]) + } else { + keyArrowPos = undefined + return + } + e.preventDefault() + }} +/> + + + {#if open && !disabled} +
+ {@render header?.()} + {#if processedItems?.length === 0} +
{noItemsMsg}
+ {/if} +
    + {#each processedItems ?? [] as item, itemIndex} + {#if (item.__select_group && itemIndex === 0) || processedItems?.[itemIndex - 1]?.__select_group !== item.__select_group} +
  • + {item.__select_group} +
  • + {/if} +
  • + +
  • + {/each} +
+
+ {/if} +
diff --git a/frontend/src/lib/components/select/utils.svelte.ts b/frontend/src/lib/components/select/utils.svelte.ts new file mode 100644 index 0000000000..f3d43b40c1 --- /dev/null +++ b/frontend/src/lib/components/select/utils.svelte.ts @@ -0,0 +1,72 @@ +export function processItems({ + items, + filterText, + groupBy, + sortBy, + onCreateItem, + createText +}: { + items?: Item[] + filterText?: string + groupBy?: (item: Item) => string + sortBy?: (a: Item, b: Item) => number + onCreateItem?: (value: string) => void + createText?: string +}): ProcessedItem[] { + let items2 = + items?.map((item) => ({ + ...item, + label: getLabel(item) + })) ?? [] + if (groupBy) { + items2 = + items2?.map((item) => ({ + ...item, + __select_group: groupBy(item) + })) ?? [] + } + if (sortBy) { + items2 = items2?.sort(sortBy) + } + if (onCreateItem && filterText && !items2.some((item) => item.label === filterText)) { + items2.push({ + label: createText ?? `Add new: "${filterText}"`, + value: filterText, + __is_create: true + } as any) + } + return items2 +} + +export type ProcessedItem = { + __select_group?: string + __is_create?: true + label: string + value: T +} + +export function getLabel(item: { label?: string; value: T } | undefined): string { + if (!item) return '' + if (item.label) return item.label + if (typeof item.value === 'string') return item.value + if (typeof item.value == 'number' || typeof item.value == 'boolean') return item.value.toString() + + return JSON.stringify(item.value) +} + +export function safeSelectItems( + list: (T | { value: T; label?: string } | undefined | null)[] | undefined | null +): { value: T; label?: string }[] { + if (!list) return [] + return list + .filter((item) => item !== undefined && item !== null) + .map((item) => { + if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') { + return { value: item } + } + if (typeof item === 'object' && 'value' in item) { + return item + } + return { value: null as any, label: 'UNKNOWN_ITEM' } + }) +} diff --git a/frontend/src/lib/components/settings/CreateToken.svelte b/frontend/src/lib/components/settings/CreateToken.svelte index dd25ca2da9..70c60e2aca 100644 --- a/frontend/src/lib/components/settings/CreateToken.svelte +++ b/frontend/src/lib/components/settings/CreateToken.svelte @@ -3,7 +3,6 @@ import { Button } from '../common' import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte' import ToggleButtonGroup from '../common/toggleButton-v2/ToggleButtonGroup.svelte' - import MultiSelectWrapper from '../multiselect/MultiSelectWrapper.svelte' import TriggerableByAI from '../TriggerableByAI.svelte' import Toggle from '../Toggle.svelte' import { UserService, type NewToken } from '$lib/gen' @@ -39,7 +38,7 @@ let newMcpScope = $state('favorites') let loadingApps = $state(false) let errorFetchApps = $state(false) - let allApps = $state([]) + // let allApps = $state([]) function handleCopyClick() { copyToClipboard(newToken ?? '') @@ -205,7 +204,7 @@ {:else if errorFetchApps}
Error fetching apps
{:else} - + {/if}
diff --git a/frontend/src/lib/components/settings/TokensTable.svelte b/frontend/src/lib/components/settings/TokensTable.svelte index 9601b92f67..d66e6c2df1 100644 --- a/frontend/src/lib/components/settings/TokensTable.svelte +++ b/frontend/src/lib/components/settings/TokensTable.svelte @@ -12,8 +12,9 @@ import Toggle from '../Toggle.svelte' import ClipboardPanel from '../details/ClipboardPanel.svelte' import { sendUserToast } from '$lib/toast' - import MultiSelectWrapper from '../multiselect/MultiSelectWrapper.svelte' import TriggerableByAI from '../TriggerableByAI.svelte' + import MultiSelect from '../select/MultiSelect.svelte' + import { safeSelectItems } from '../select/utils.svelte' // --- Props --- interface Props { @@ -306,10 +307,11 @@ {:else if errorFetchApps}
Error fetching apps
{:else} - {/if}
@@ -319,7 +321,7 @@ +
{#if !mcpCreationMode} @@ -339,7 +341,7 @@ Expires In (optional) - diff --git a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte index 83aa8633ce..60751a4595 100644 --- a/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte +++ b/frontend/src/lib/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte @@ -23,7 +23,8 @@ import { RefreshCw } from 'lucide-svelte' import Alert from '$lib/components/common/alert/Alert.svelte' import TestingBadge from '../testingBadge.svelte' - import Select from '$lib/components/Select.svelte' + import Select from '$lib/components/select/Select.svelte' + import { safeSelectItems } from '$lib/components/select/utils.svelte' let topic_items: string[] = $state([]) let subscription_items: string[] = $state([]) @@ -176,7 +177,7 @@ loadAllSubscriptionFromGooglePubSubTopic() } } - items={topic_items.map((value) => ({ value }))} + items={safeSelectItems(topic_items)} placeholder="Choose a topic" /> - {/if} -
- {/each} -
- -{#if $superadmin} -
-