Compare commits
17 Commits
instructio
...
fix-cron-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
072f1777b5 | ||
|
|
55b7f982c2 | ||
|
|
2c401305bf | ||
|
|
a2594a7731 | ||
|
|
035bad5268 | ||
|
|
4db788b845 | ||
|
|
44926eb39e | ||
|
|
20e0427a13 | ||
|
|
c384387419 | ||
|
|
3de6d446f2 | ||
|
|
6fcd72c794 | ||
|
|
f5bed95ab1 | ||
|
|
4219377bfc | ||
|
|
ff1b4df1ac | ||
|
|
dc44b0841a | ||
|
|
18cf8faec1 | ||
|
|
2e8f2ec724 |
30
CHANGELOG.md
30
CHANGELOG.md
@@ -1,6 +1,36 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## [1.178.1](https://github.com/windmill-labs/windmill/compare/v1.178.0...v1.178.1) (2023-09-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve license key check ([035bad5](https://github.com/windmill-labs/windmill/commit/035bad5268d182af3f30915b5356defd7f6ccbc0))
|
||||
|
||||
## [1.178.0](https://github.com/windmill-labs/windmill/compare/v1.177.1...v1.178.0) (2023-09-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **frontend:** add app groups management ([#2347](https://github.com/windmill-labs/windmill/issues/2347)) ([20e0427](https://github.com/windmill-labs/windmill/commit/20e0427a1303c1c32f41b198cd2d0f7f28b5bd32))
|
||||
* **frontend:** add AppDrawer controls ([#2339](https://github.com/windmill-labs/windmill/issues/2339)) ([3de6d44](https://github.com/windmill-labs/windmill/commit/3de6d446f281dcaac288deee19342a08e0ccf9af))
|
||||
* **frontend:** Switch to component list when deleting a component ([#2346](https://github.com/windmill-labs/windmill/issues/2346)) ([6fcd72c](https://github.com/windmill-labs/windmill/commit/6fcd72c79453dd9d60ca869cd9996cc0c25971fa))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add env tags to default worker group ([#2348](https://github.com/windmill-labs/windmill/issues/2348)) ([f5bed95](https://github.com/windmill-labs/windmill/commit/f5bed95ab15bc397f822b06816c43b4b13a84af3))
|
||||
|
||||
## [1.177.1](https://github.com/windmill-labs/windmill/compare/v1.177.0...v1.177.1) (2023-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **frontend:** fix modal closing issues ([#2340](https://github.com/windmill-labs/windmill/issues/2340)) ([18cf8fa](https://github.com/windmill-labs/windmill/commit/18cf8faec16d496e4b327505b682459ed518a5b4))
|
||||
* **frontend:** fix overflow ([#2341](https://github.com/windmill-labs/windmill/issues/2341)) ([2e8f2ec](https://github.com/windmill-labs/windmill/commit/2e8f2ec724f6802170121f4f8aa73b697a39c9ee))
|
||||
* improve list component handling of non array data ([dc44b08](https://github.com/windmill-labs/windmill/commit/dc44b0841af17227160b9d56ec446e6646a8ab0d))
|
||||
|
||||
## [1.177.0](https://github.com/windmill-labs/windmill/compare/v1.176.0...v1.177.0) (2023-09-26)
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT script_path FROM completed_job WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "script_path",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "16be0560028361d46bf3b842a5fa07472994d8942c684f5b75339fe71ea23cdd"
|
||||
}
|
||||
@@ -67,6 +67,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
14
backend/.sqlx/query-6e6d781fe63602541f7cb4806d5ddde0792e1861ea8761b4875677c3d0594a86.json
generated
Normal file
14
backend/.sqlx/query-6e6d781fe63602541f7cb4806d5ddde0792e1861ea8761b4875677c3d0594a86.json
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO folder (workspace_id, name, display_name, owners, extra_perms) VALUES ($1, 'app_groups', 'App Groups', ARRAY[]::TEXT[], '{\"g/all\": false}') ON CONFLICT DO NOTHING",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Varchar"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6e6d781fe63602541f7cb4806d5ddde0792e1861ea8761b4875677c3d0594a86"
|
||||
}
|
||||
@@ -60,6 +60,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"bash",
|
||||
"postgresql",
|
||||
"nativets",
|
||||
"Nativets",
|
||||
"bun",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT hash FROM script WHERE path = $1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "hash",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "ef6795d93423f98eea82eb18e6332580dc7f7a9e5a67026f8c0b3077f371fc62"
|
||||
}
|
||||
121
backend/Cargo.lock
generated
121
backend/Cargo.lock
generated
@@ -321,7 +321,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde-aux",
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
@@ -378,7 +378,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_qs 0.9.2",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"smart-default",
|
||||
"smol_str",
|
||||
"thiserror",
|
||||
@@ -1891,13 +1891,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.10.14"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
|
||||
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
@@ -2574,9 +2573,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.0",
|
||||
@@ -3221,7 +3220,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"smallvec",
|
||||
"subprocess",
|
||||
"thiserror",
|
||||
@@ -3591,7 +3590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap 2.0.0",
|
||||
"indexmap 2.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3860,7 +3859,7 @@ dependencies = [
|
||||
"md-5 0.10.6",
|
||||
"memchr",
|
||||
"rand 0.8.5",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"stringprep",
|
||||
]
|
||||
|
||||
@@ -4506,7 +4505,7 @@ version = "7.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74"
|
||||
dependencies = [
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
@@ -4954,7 +4953,7 @@ version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"indexmap 2.0.0",
|
||||
"indexmap 2.0.1",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
@@ -5047,7 +5046,7 @@ version = "0.9.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
|
||||
dependencies = [
|
||||
"indexmap 2.0.0",
|
||||
"indexmap 2.0.1",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
@@ -5097,9 +5096,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.7"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
@@ -5108,9 +5107,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.4"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||
checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
@@ -5320,9 +5319,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e58421b6bc416714d5115a2ca953718f6c621a51b68e4f4922aea5a4391a721"
|
||||
checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33"
|
||||
dependencies = [
|
||||
"sqlx-core",
|
||||
"sqlx-macros",
|
||||
@@ -5333,9 +5332,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-core"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd4cef4251aabbae751a3710927945901ee1d97ee96d757f6880ebb9a79bfd53"
|
||||
checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d"
|
||||
dependencies = [
|
||||
"ahash 0.8.3",
|
||||
"atoi",
|
||||
@@ -5355,7 +5354,7 @@ dependencies = [
|
||||
"futures-util",
|
||||
"hashlink",
|
||||
"hex",
|
||||
"indexmap 2.0.0",
|
||||
"indexmap 2.0.1",
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
@@ -5365,7 +5364,7 @@ dependencies = [
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"smallvec",
|
||||
"sqlformat",
|
||||
"thiserror",
|
||||
@@ -5379,9 +5378,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "208e3165167afd7f3881b16c1ef3f2af69fa75980897aac8874a0696516d12c2"
|
||||
checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5392,9 +5391,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros-core"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a4a8336d278c62231d87f24e8a7a74898156e34c1c18942857be2acb29c7dfc"
|
||||
checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc"
|
||||
dependencies = [
|
||||
"dotenvy",
|
||||
"either",
|
||||
@@ -5405,7 +5404,7 @@ dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"sqlx-core",
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
@@ -5418,9 +5417,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-mysql"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ca69bf415b93b60b80dc8fda3cb4ef52b2336614d8da2de5456cc942a110482"
|
||||
checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.21.4",
|
||||
@@ -5451,7 +5450,7 @@ dependencies = [
|
||||
"rsa 0.9.2",
|
||||
"serde",
|
||||
"sha1",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"smallvec",
|
||||
"sqlx-core",
|
||||
"stringprep",
|
||||
@@ -5463,9 +5462,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-postgres"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0db2df1b8731c3651e204629dd55e52adbae0462fa1bdcbed56a2302c18181e"
|
||||
checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.21.4",
|
||||
@@ -5494,7 +5493,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"smallvec",
|
||||
"sqlx-core",
|
||||
"stringprep",
|
||||
@@ -5506,9 +5505,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-sqlite"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4c21bf34c7cae5b283efb3ac1bcc7670df7561124dc2f8bdc0b59be40f79a2"
|
||||
checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"chrono",
|
||||
@@ -6063,18 +6062,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.48"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||
checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.48"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||
checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -6330,7 +6329,7 @@ version = "0.19.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap 2.0.0",
|
||||
"indexmap 2.0.1",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@@ -7098,7 +7097,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windmill"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -7116,7 +7115,7 @@ dependencies = [
|
||||
"rsmq_async",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"tokio",
|
||||
"tokio-metrics",
|
||||
@@ -7132,7 +7131,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -7169,7 +7168,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"sql-builder",
|
||||
"sqlx",
|
||||
"tempfile",
|
||||
@@ -7192,7 +7191,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-api-client"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"base64 0.21.4",
|
||||
"chrono",
|
||||
@@ -7210,7 +7209,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-audit"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
@@ -7223,7 +7222,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-common"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -7239,7 +7238,7 @@ dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
@@ -7251,7 +7250,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -7259,7 +7258,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-bash"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -7270,7 +7269,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-go"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
@@ -7282,7 +7281,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-graphql"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -7293,7 +7292,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.11.0",
|
||||
@@ -7304,7 +7303,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-py-imports"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -7321,7 +7320,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-sql"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lazy_static",
|
||||
@@ -7332,7 +7331,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-ts"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"convert_case 0.6.0",
|
||||
@@ -7349,7 +7348,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-parser-wasm"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"getrandom 0.2.10",
|
||||
@@ -7367,7 +7366,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-queue"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -7397,7 +7396,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windmill-worker"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
@@ -7432,7 +7431,7 @@ dependencies = [
|
||||
"rust_decimal",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.7",
|
||||
"sha2 0.10.8",
|
||||
"sqlx",
|
||||
"tokio",
|
||||
"tokio-postgres",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "windmill"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
@@ -22,7 +22,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
-- Add down migration script here
|
||||
2
backend/migrations/20230927215813_add_app_groups.up.sql
Normal file
2
backend/migrations/20230927215813_add_app_groups.up.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
-- Add up migration script here
|
||||
INSERT INTO folder (workspace_id, name, display_name, owners, extra_perms) SELECT id, 'app_groups', 'App Groups', ARRAY[]::TEXT[], '{"g/all": false}' FROM workspace ON CONFLICT DO NOTHING;
|
||||
@@ -89,11 +89,9 @@ pub async fn initial_load(
|
||||
};
|
||||
|
||||
let reload_base_url_f = async {
|
||||
|
||||
if let Err(e) = reload_base_url_setting(db).await {
|
||||
tracing::error!("Error reloading base url: {:?}", e)
|
||||
}
|
||||
|
||||
if let Err(e) = reload_base_url_setting(db).await {
|
||||
tracing::error!("Error reloading base url: {:?}", e)
|
||||
}
|
||||
};
|
||||
|
||||
let reload_server_config_f = async {
|
||||
@@ -114,11 +112,9 @@ pub async fn initial_load(
|
||||
};
|
||||
|
||||
let reload_license_key_f = async {
|
||||
if server_mode {
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Err(e) = reload_license_key(&db).await {
|
||||
tracing::error!("Error reloading license key: {:?}", e)
|
||||
}
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Err(e) = reload_license_key(&db).await {
|
||||
tracing::error!("Error reloading license key: {:?}", e)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -323,12 +319,16 @@ pub async fn monitor_db<R: rsmq_async::RsmqConnection + Send + Sync + Clone + 's
|
||||
};
|
||||
|
||||
let verify_license_key_f = async {
|
||||
if server_mode {
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Err(e) = verify_license_key().await {
|
||||
tracing::error!("Error verifying license key: {:?}", e);
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Err(e) = verify_license_key().await {
|
||||
tracing::error!("Error verifying license key: {:?}", e);
|
||||
let mut l = LICENSE_KEY_VALID.write().await;
|
||||
*l = false;
|
||||
} else {
|
||||
let is_valid = LICENSE_KEY_VALID.read().await.clone();
|
||||
if !is_valid {
|
||||
let mut l = LICENSE_KEY_VALID.write().await;
|
||||
*l = false;
|
||||
*l = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.177.0
|
||||
version: 1.178.1
|
||||
title: Windmill API
|
||||
|
||||
contact:
|
||||
|
||||
@@ -958,6 +958,12 @@ async fn create_workspace(
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO folder (workspace_id, name, display_name, owners, extra_perms) VALUES ($1, 'app_groups', 'App Groups', ARRAY[]::TEXT[], '{\"g/all\": false}') ON CONFLICT DO NOTHING",
|
||||
nw.id,
|
||||
)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO resource (workspace_id, path, value, description, resource_type) VALUES ($1, 'f/app_themes/theme_0', '{\"name\": \"Default Theme\", \"value\": \"\"}', 'The default app theme', 'app_theme') ON CONFLICT DO NOTHING",
|
||||
|
||||
@@ -17,7 +17,11 @@ pub fn username_to_permissioned_as(user: &str) -> String {
|
||||
}
|
||||
|
||||
pub fn truncate_token(token: &str) -> String {
|
||||
let mut s = token[..10].to_owned();
|
||||
s.push_str("*****");
|
||||
s
|
||||
if token.len() > 10 {
|
||||
let mut s = token[..10].to_owned();
|
||||
s.push_str("*****");
|
||||
s
|
||||
} else {
|
||||
token.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,22 @@ pub async fn load_worker_config(db: &DB) -> error::Result<WorkerConfig> {
|
||||
WorkspacedPath { workspace_id: workspace.to_string(), path: script_path.to_string() }
|
||||
}
|
||||
});
|
||||
if *WORKER_GROUP == "default" {
|
||||
let mut all_tags = config
|
||||
.worker_tags
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.chain(
|
||||
std::env::var("WORKER_TAGS")
|
||||
.ok()
|
||||
.map(|x| x.split(',').map(|x| x.to_string()).collect_vec())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.sorted()
|
||||
.collect_vec();
|
||||
all_tags.dedup();
|
||||
config.worker_tags = Some(all_tags);
|
||||
}
|
||||
Ok(WorkerConfig {
|
||||
worker_tags: config
|
||||
.worker_tags
|
||||
|
||||
@@ -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.177.0";
|
||||
export const VERSION = "v1.178.1";
|
||||
|
||||
export async function login(email: string, password: string): Promise<string> {
|
||||
return await windmill.UserService.login({
|
||||
|
||||
@@ -31,7 +31,7 @@ addEventListener("error", (event) => {
|
||||
}
|
||||
});
|
||||
|
||||
export const VERSION = "v1.177.0";
|
||||
export const VERSION = "v1.178.1";
|
||||
|
||||
let command: any = new Command()
|
||||
.name("wmill")
|
||||
|
||||
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.177.0",
|
||||
"version": "1.178.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "windmill-components",
|
||||
"version": "1.177.0",
|
||||
"version": "1.178.1",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-js": "^4.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windmill-components",
|
||||
"version": "1.177.0",
|
||||
"version": "1.178.1",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { ScheduleService } from '$lib/gen'
|
||||
import { emptyString, formatCron } from '$lib/utils'
|
||||
import Badge from './Badge.svelte'
|
||||
|
||||
// @ts-ignore
|
||||
import Multiselect from 'svelte-multiselect'
|
||||
import TimezonePicker from 'svelte-timezone-picker'
|
||||
@@ -15,6 +14,11 @@
|
||||
export let disabled = false
|
||||
export let validCRON = true
|
||||
|
||||
// If the timezone is not a valid timezone, default to Europe/Paris
|
||||
$: if (!timezone.includes('/')) {
|
||||
timezone = 'Europe/Paris'
|
||||
}
|
||||
|
||||
let preview: string[] = []
|
||||
// If the user has already entered a cron string, switching to the basic tab will override it.
|
||||
let executeEvery: 'second' | 'minute' | 'hour' | 'day-month' | 'month' | 'day-week' = 'minute'
|
||||
|
||||
@@ -235,8 +235,14 @@
|
||||
let command: Disposable | undefined = undefined
|
||||
|
||||
let sqlSchemaCompletor: Disposable | undefined = undefined
|
||||
$: args &&
|
||||
(dbSchema = $dbSchemas[(lang === 'graphql' ? args.api : args.database)?.replace('$res:', '')])
|
||||
|
||||
function updateSchema(lang, args) {
|
||||
const schemaRes = lang === 'graphql' ? args.api : args.database
|
||||
if (schemaRes instanceof String) {
|
||||
dbSchema = $dbSchemas[schemaRes.replace('$res:', '')]
|
||||
}
|
||||
}
|
||||
$: args && updateSchema(lang, args)
|
||||
$: dbSchema && ['sql', 'graphql'].includes(lang) && addDBSchemaCompletions()
|
||||
$: (!dbSchema || lang !== 'sql') && sqlSchemaCompletor && sqlSchemaCompletor.dispose()
|
||||
$: (!dbSchema || lang !== 'graphql') && graphqlService && graphqlService.setSchemaConfig([])
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<input type="text" placeholder="name (optional)" bind:value={name} />
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" placeholder="password" bind:value={company} />
|
||||
<input type="text" placeholder="company (optional)" bind:value={company} />
|
||||
</div>
|
||||
<div class="text-xs text-tertiary grow text-right"> Email will be sent if SMTP configured </div>
|
||||
</div>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="text-sm text-secondary border p-2">
|
||||
Create a new OAuth 2.0 Client <a
|
||||
href="https://console.cloud.google.com/apis/credentials"
|
||||
target="_blank">in Google console</a
|
||||
target="_blank">in google console</a
|
||||
>
|
||||
and set the redirect URI to <code>BASE_URL/user/login_callback/google</code>
|
||||
where BASE_URL is what you configured as core BASE_URL
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="text-sm text-secondary border p-2">
|
||||
Create a new OAuth 2.0 Client <a
|
||||
href="https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade"
|
||||
target="_blank">in Microsoft portal</a
|
||||
target="_blank">in microsoft portal</a
|
||||
>
|
||||
and in the "Authentication" tab, set the redirect URI to
|
||||
<code>BASE_URL/user/login_callback/microsoft</code>, the logout channel to
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</ConfirmationModal>
|
||||
|
||||
<div class="flex gap-2 items-center"
|
||||
><h4 class="py-4 truncate w-40">{name}</h4>
|
||||
><h4 class="py-4 truncate w-40 text-primary">{name}</h4>
|
||||
{#if $superadmin}
|
||||
<Popup
|
||||
floatingConfig={{ strategy: 'absolute', placement: top ? 'top-start' : 'bottom-start' }}
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result', 'jobId']
|
||||
|
||||
const { app, worldStore, stateId } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, stateId, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result: undefined,
|
||||
@@ -42,6 +43,12 @@
|
||||
configuration
|
||||
)
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
wrapper?.setArgs(nvalue)
|
||||
}
|
||||
}
|
||||
|
||||
let runnableComponent: RunnableComponent
|
||||
let loading = false
|
||||
|
||||
@@ -50,6 +57,8 @@
|
||||
(componentInput?.type != 'runnable' || Object.keys(componentInput?.fields ?? {}).length == 0)
|
||||
|
||||
let css = initCss($app.css?.formcomponent, customCss)
|
||||
|
||||
let wrapper: RunnableWrapper
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['formcomponent'].initialData.configuration) as key (key)}
|
||||
@@ -74,6 +83,7 @@
|
||||
<RunnableWrapper
|
||||
{recomputeIds}
|
||||
{render}
|
||||
bind:this={wrapper}
|
||||
bind:runnableComponent
|
||||
bind:loading
|
||||
{componentInput}
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
|
||||
$runnableComponents = $runnableComponents
|
||||
|
||||
export function setArgs(value: any) {
|
||||
args = value
|
||||
}
|
||||
|
||||
let args: Record<string, any> | undefined = undefined
|
||||
let runnableInputValues: Record<string, any> = {}
|
||||
let executeTimeout: NodeJS.Timeout | undefined = undefined
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
| 'errorOverlay'
|
||||
| 'openModal'
|
||||
| 'closeModal'
|
||||
| 'open'
|
||||
| 'close'
|
||||
configuration: {
|
||||
gotoUrl: { url: string | undefined; newTab: boolean | undefined }
|
||||
setTab: {
|
||||
@@ -40,6 +42,12 @@
|
||||
closeModal?: {
|
||||
modalId: string | undefined
|
||||
}
|
||||
open?: {
|
||||
id: string | undefined
|
||||
}
|
||||
close?: {
|
||||
id: string | undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
| undefined
|
||||
@@ -69,6 +77,10 @@
|
||||
export let errorHandledByComponent: boolean = false
|
||||
export let hasChildrens: boolean = false
|
||||
|
||||
export function setArgs(value: any) {
|
||||
runnableComponent?.setArgs(value)
|
||||
}
|
||||
|
||||
const { staticExporter, noBackend, componentControl, runnableComponents } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -168,6 +180,22 @@
|
||||
$componentControl[modalId].closeModal?.()
|
||||
break
|
||||
}
|
||||
case 'open': {
|
||||
const id = sideEffect?.configuration?.open?.id
|
||||
|
||||
if (!id) return
|
||||
|
||||
$componentControl[id].open?.()
|
||||
break
|
||||
}
|
||||
case 'close': {
|
||||
const id = sideEffect?.configuration?.close?.id
|
||||
|
||||
if (!id) return
|
||||
|
||||
$componentControl[id].close?.()
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export function computeGlobalContext(world: World | undefined, extraContext: any
|
||||
|
||||
function create_context_function_template(eval_string: string, context, noReturn: boolean) {
|
||||
return `
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal) {
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close) {
|
||||
"use strict";
|
||||
${
|
||||
Object.keys(context).length > 0
|
||||
@@ -50,7 +50,9 @@ function make_context_evaluator(
|
||||
setValue,
|
||||
setSelectedIndex,
|
||||
openModal,
|
||||
closeModal
|
||||
closeModal,
|
||||
open,
|
||||
close
|
||||
) => Promise<any> {
|
||||
let template = create_context_function_template(eval_string, context, noReturn)
|
||||
let functor = Function(template)
|
||||
@@ -104,6 +106,8 @@ export async function eval_like(
|
||||
setSelectedIndex?: (index: number) => void
|
||||
openModal?: () => void
|
||||
closeModal?: () => void
|
||||
open?: () => void
|
||||
close?: () => void
|
||||
}
|
||||
>,
|
||||
worldStore: World | undefined,
|
||||
@@ -160,6 +164,12 @@ export async function eval_like(
|
||||
},
|
||||
(id) => {
|
||||
controlComponents[id]?.closeModal?.()
|
||||
},
|
||||
(id) => {
|
||||
controlComponents[id]?.open?.()
|
||||
},
|
||||
(id) => {
|
||||
controlComponents[id]?.close?.()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,8 +21,15 @@
|
||||
export let noWFull = false
|
||||
export let render: boolean
|
||||
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput, mode } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
const {
|
||||
app,
|
||||
focusedGrid,
|
||||
selectedComponent,
|
||||
worldStore,
|
||||
connectingInput,
|
||||
mode,
|
||||
componentControl
|
||||
} = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
components['drawercomponent'].initialData.configuration,
|
||||
@@ -32,6 +39,15 @@
|
||||
|
||||
let appDrawer: Drawer
|
||||
|
||||
$componentControl[id] = {
|
||||
open: () => {
|
||||
appDrawer?.openDrawer()
|
||||
},
|
||||
close: () => {
|
||||
appDrawer?.closeDrawer()
|
||||
}
|
||||
}
|
||||
|
||||
let css = initCss($app.css?.drawercomponent, customCss)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -69,17 +69,19 @@
|
||||
initialData: Array<any> | undefined = [],
|
||||
page: number = 0
|
||||
) {
|
||||
const sanitizedData = Array.isArray(initialData) ? initialData : []
|
||||
|
||||
if (mode === 'auto') {
|
||||
const pageSize: number = configuration.auto.pageSize ?? 0
|
||||
const data = initialData?.slice(0 + page * pageSize, pageSize + page * pageSize) ?? []
|
||||
const shouldDisplayPagination = pageSize < initialData?.length ?? false
|
||||
const total = Math.ceil(initialData?.length / pageSize ?? 0)
|
||||
const data = sanitizedData?.slice(0 + page * pageSize, pageSize + page * pageSize) ?? []
|
||||
const shouldDisplayPagination = pageSize < sanitizedData?.length ?? false
|
||||
const total = Math.ceil(sanitizedData.length / pageSize ?? 0)
|
||||
|
||||
return {
|
||||
data,
|
||||
shouldDisplayPagination,
|
||||
indexOffset: page * pageSize,
|
||||
disableNext: pageSize > 0 && (page + 1) * pageSize >= initialData?.length,
|
||||
disableNext: pageSize > 0 && (page + 1) * pageSize >= sanitizedData?.length,
|
||||
total: total
|
||||
}
|
||||
} else {
|
||||
@@ -88,7 +90,7 @@
|
||||
|
||||
return {
|
||||
shouldDisplayPagination: true,
|
||||
data: initialData ?? [],
|
||||
data: sanitizedData ?? [],
|
||||
indexOffset: 0,
|
||||
disableNext: page + 1 >= pageCount,
|
||||
total: total
|
||||
|
||||
@@ -64,6 +64,12 @@
|
||||
},
|
||||
closeModal: () => {
|
||||
open = false
|
||||
},
|
||||
open: () => {
|
||||
open = true
|
||||
},
|
||||
close: () => {
|
||||
open = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -148,7 +154,7 @@
|
||||
<div>{resolvedConfig.modalTitle}</div>
|
||||
<div class="w-8">
|
||||
<button
|
||||
on:click={() => {
|
||||
on:click|stopPropagation={() => {
|
||||
open = false
|
||||
}}
|
||||
class="hover:bg-surface-hover bg-surface-secondary rounded-full w-8 h-8 flex items-center justify-center transition-all"
|
||||
|
||||
@@ -168,7 +168,8 @@
|
||||
let selectedTab: 'insert' | 'settings' | 'css' = 'insert'
|
||||
|
||||
let befSelected: string | undefined = undefined
|
||||
$: if ($selectedComponent?.[0] != befSelected) {
|
||||
|
||||
$: if ($selectedComponent?.[0] != befSelected && $selectedComponent?.[0] != undefined) {
|
||||
befSelected = $selectedComponent?.[0]
|
||||
selectedTab = 'settings'
|
||||
|
||||
@@ -452,7 +453,7 @@
|
||||
)}
|
||||
style={$appStore.css?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<div class="absolute bottom-4 left-4 z-50">
|
||||
<div class="absolute bottom-2 left-4 z-50">
|
||||
<div class="flex flex-row gap-2 text-xs items-center">
|
||||
<Button
|
||||
color="light"
|
||||
@@ -465,7 +466,7 @@
|
||||
>
|
||||
<Minus size={14} />
|
||||
</Button>
|
||||
{$scale}
|
||||
{$scale}%
|
||||
<Button
|
||||
color="light"
|
||||
variant="border"
|
||||
@@ -569,7 +570,12 @@
|
||||
<div slot="content" class="h-full overflow-y-auto">
|
||||
<TabContent class="overflow-auto h-full" value="settings">
|
||||
{#if $selectedComponent !== undefined}
|
||||
<SettingsPanel />
|
||||
<SettingsPanel
|
||||
on:delete={() => {
|
||||
befSelected = undefined
|
||||
selectedTab = 'insert'
|
||||
}}
|
||||
/>
|
||||
<SecondaryMenu right />
|
||||
{:else}
|
||||
<div class="min-w-[150px] text-sm text-secondary text-center py-8 px-2">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import type { App, AppViewerContext } from '../types'
|
||||
import { BG_PREFIX, allItems } from '../utils'
|
||||
import { findComponentSettings, findGridItem } from './appUtils'
|
||||
@@ -32,11 +32,18 @@
|
||||
})
|
||||
.find((x) => x)
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
{#if componentSettings}
|
||||
{#key componentSettings?.item?.id}
|
||||
<ComponentPanel bind:componentSettings />
|
||||
<ComponentPanel
|
||||
bind:componentSettings
|
||||
onDelete={() => {
|
||||
dispatch('delete')
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{:else if tableActionSettings}
|
||||
{#key tableActionSettings?.item?.data?.id}
|
||||
|
||||
@@ -323,6 +323,55 @@ export function insertNewGridItem(
|
||||
return id
|
||||
}
|
||||
|
||||
export function copyComponent(
|
||||
app: App,
|
||||
item: GridItem,
|
||||
parentGrid: FocusedGrid | undefined,
|
||||
subgrids: Record<string, GridItem[]>,
|
||||
alreadyVisited: string[]
|
||||
) {
|
||||
if (alreadyVisited.includes(item.id)) {
|
||||
return
|
||||
} else {
|
||||
alreadyVisited.push(item.id)
|
||||
}
|
||||
const newItem = insertNewGridItem(
|
||||
app,
|
||||
(id) => {
|
||||
if (item.data.type === 'tablecomponent') {
|
||||
return {
|
||||
...item.data,
|
||||
id,
|
||||
actionButtons:
|
||||
item.data.actionButtons.map((x) => ({
|
||||
...x,
|
||||
id: x.id.replace(`${item.id}_`, `${id}_`)
|
||||
})) ?? []
|
||||
}
|
||||
} else {
|
||||
return { ...item.data, id }
|
||||
}
|
||||
},
|
||||
parentGrid,
|
||||
Object.fromEntries(gridColumns.map((column) => [column, item[column]]))
|
||||
)
|
||||
|
||||
for (let i = 0; i < (item?.data?.numberOfSubgrids ?? 0); i++) {
|
||||
subgrids[`${item.id}-${i}`].forEach((subgridItem) => {
|
||||
copyComponent(
|
||||
app,
|
||||
subgridItem,
|
||||
{ parentComponentId: newItem, subGridIndex: i },
|
||||
subgrids,
|
||||
alreadyVisited
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return newItem
|
||||
}
|
||||
|
||||
|
||||
export function getAllSubgridsAndComponentIds(
|
||||
app: App,
|
||||
component: AppComponent
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import {
|
||||
copyComponent,
|
||||
findGridItem,
|
||||
findGridItemParentGrid,
|
||||
getAllSubgridsAndComponentIds,
|
||||
insertNewGridItem
|
||||
} from '../appUtils'
|
||||
import type { AppEditorContext, AppViewerContext, FocusedGrid, GridItem } from '../../types'
|
||||
import type { AppEditorContext, AppViewerContext, GridItem } from '../../types'
|
||||
import { push } from '$lib/history'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { gridColumns } from '../../gridUtils'
|
||||
@@ -242,7 +243,7 @@
|
||||
} else if (copiedGridItems) {
|
||||
let nitems: string[] = []
|
||||
for (let copiedGridItem of copiedGridItems) {
|
||||
let newItem = copyComponent(copiedGridItem, $focusedGrid, subgrids, [])
|
||||
let newItem = copyComponent($app, copiedGridItem, $focusedGrid, subgrids, [])
|
||||
newItem && nitems.push(newItem)
|
||||
}
|
||||
$selectedComponent = nitems.map((x) => x)
|
||||
@@ -251,52 +252,6 @@
|
||||
$app = $app
|
||||
}
|
||||
|
||||
function copyComponent(
|
||||
item: GridItem,
|
||||
parentGrid: FocusedGrid | undefined,
|
||||
subgrids: Record<string, GridItem[]>,
|
||||
alreadyVisited: string[]
|
||||
) {
|
||||
if (alreadyVisited.includes(item.id)) {
|
||||
return
|
||||
} else {
|
||||
alreadyVisited.push(item.id)
|
||||
}
|
||||
const newItem = insertNewGridItem(
|
||||
$app,
|
||||
(id) => {
|
||||
if (item.data.type === 'tablecomponent') {
|
||||
return {
|
||||
...item.data,
|
||||
id,
|
||||
actionButtons:
|
||||
item.data.actionButtons.map((x) => ({
|
||||
...x,
|
||||
id: x.id.replace(`${item.id}_`, `${id}_`)
|
||||
})) ?? []
|
||||
}
|
||||
} else {
|
||||
return { ...item.data, id }
|
||||
}
|
||||
},
|
||||
parentGrid,
|
||||
Object.fromEntries(gridColumns.map((column) => [column, item[column]]))
|
||||
)
|
||||
|
||||
for (let i = 0; i < (item?.data?.numberOfSubgrids ?? 0); i++) {
|
||||
subgrids[`${item.id}-${i}`].forEach((subgridItem) => {
|
||||
copyComponent(
|
||||
subgridItem,
|
||||
{ parentComponentId: newItem, subGridIndex: i },
|
||||
subgrids,
|
||||
alreadyVisited
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return newItem
|
||||
}
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
// Ignore keydown events if the user is typing in monaco
|
||||
let classes = event.target?.['className']
|
||||
|
||||
@@ -297,8 +297,8 @@ const labels = {
|
||||
setTab: 'Set the tab of a tabs component',
|
||||
sendToast: 'Display a toast notification',
|
||||
sendErrorToast: 'Display an error toast notification',
|
||||
openModal: 'Open a modal',
|
||||
closeModal: 'Close a modal'
|
||||
open: 'Open a modal or a drawer',
|
||||
close: 'Close a modal or a drawer'
|
||||
}
|
||||
|
||||
const onSuccessClick = {
|
||||
@@ -356,6 +356,22 @@ const onSuccessClick = {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to open',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to close',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
} as const
|
||||
@@ -406,18 +422,18 @@ const onErrorClick = {
|
||||
value: true
|
||||
}
|
||||
},
|
||||
openModal: {
|
||||
modalId: {
|
||||
tooltip: 'The id of the modal to open',
|
||||
open: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to open',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: '',
|
||||
noVariablePicker: true
|
||||
}
|
||||
},
|
||||
closeModal: {
|
||||
modalId: {
|
||||
tooltip: 'The id of the modal to close',
|
||||
close: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to close',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: '',
|
||||
@@ -457,8 +473,7 @@ const paginationOneOf = {
|
||||
}
|
||||
} as const
|
||||
|
||||
const documentationBaseUrl =
|
||||
'https://www.windmill.dev/docs/apps/app_configuration_settings'
|
||||
const documentationBaseUrl = 'https://www.windmill.dev/docs/apps/app_configuration_settings'
|
||||
|
||||
export const components = {
|
||||
displaycomponent: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { AppEditorContext, AppViewerContext } from '../../types'
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
|
||||
import {
|
||||
components as componentsRecord,
|
||||
@@ -10,14 +10,28 @@
|
||||
type TypedComponent
|
||||
} from '../component'
|
||||
import ListItem from './ListItem.svelte'
|
||||
import { appComponentFromType, insertNewGridItem } from '../appUtils'
|
||||
import { appComponentFromType, copyComponent, insertNewGridItem } from '../appUtils'
|
||||
import { push } from '$lib/history'
|
||||
import { ClearableInput } from '../../../common'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { getGroup, listGroups } from './groupUtils'
|
||||
import { LayoutDashboard } from 'lucide-svelte'
|
||||
|
||||
const { app, selectedComponent, focusedGrid } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const { history } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let groups: Array<{
|
||||
name: string
|
||||
path: string
|
||||
}> = []
|
||||
|
||||
async function fetchGroups() {
|
||||
if ($workspaceStore) {
|
||||
groups = await listGroups($workspaceStore)
|
||||
}
|
||||
}
|
||||
|
||||
function addComponent(appComponentType: TypedComponent['type']): void {
|
||||
push(history, $app)
|
||||
|
||||
@@ -33,6 +47,25 @@
|
||||
$app = $app
|
||||
}
|
||||
|
||||
async function addGroup(group: { name: string; path: string }) {
|
||||
if (!$workspaceStore) return
|
||||
const res = await getGroup($workspaceStore, group.path)
|
||||
|
||||
console.log(res)
|
||||
if (!res) return
|
||||
|
||||
push(history, $app)
|
||||
|
||||
$dirtyStore = true
|
||||
|
||||
const id = copyComponent($app, res.value.item, $focusedGrid, res.value.subgrids, [])
|
||||
|
||||
if (id) {
|
||||
$selectedComponent = [id]
|
||||
$app = $app
|
||||
}
|
||||
}
|
||||
|
||||
function addPresetComponent(appComponentType: string): void {
|
||||
const preset = presetsRecord[appComponentType]
|
||||
|
||||
@@ -65,6 +98,10 @@
|
||||
return presetName.includes(search.toLowerCase())
|
||||
})
|
||||
}))
|
||||
|
||||
onMount(() => {
|
||||
fetchGroups()
|
||||
})
|
||||
</script>
|
||||
|
||||
<section class="p-2 sticky w-full z-10 top-0 bg-surface border-b">
|
||||
@@ -123,6 +160,29 @@
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
<ListItem title={'Groups'}>
|
||||
<div class="flex flex-wrap gap-3 py-2">
|
||||
{#if groups}
|
||||
{#each groups as group (group)}
|
||||
<div class="w-20">
|
||||
<button
|
||||
on:click={() => {
|
||||
addGroup(group)
|
||||
}}
|
||||
title={group.name}
|
||||
class="transition-all border w-20 shadow-sm h-16 p-2 flex flex-col gap-2 items-center
|
||||
justify-center bg-surface rounded-md hover:bg-blue-50 dark:hover:bg-blue-900 duration-200 hover:border-blue-500"
|
||||
>
|
||||
<LayoutDashboard class="text-secondary" />
|
||||
</button>
|
||||
<div class="text-xs text-center flex-wrap text-secondary mt-1">
|
||||
{group.name}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</ListItem>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
class="h-full"
|
||||
lang="css"
|
||||
bind:code={$app.theme.css}
|
||||
fixedOverflowWidgets={false}
|
||||
fixedOverflowWidgets={true}
|
||||
small
|
||||
automaticLayout
|
||||
bind:this={cssEditor}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
<script lang="ts">
|
||||
import { listGroups, type Group, createGroup } from './groupUtils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { onMount } from 'svelte'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import DataTable from '$lib/components/table/DataTable.svelte'
|
||||
import Head from '$lib/components/table/Head.svelte'
|
||||
import Cell from '$lib/components/table/Cell.svelte'
|
||||
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { ResourceService } from '$lib/gen'
|
||||
import GroupRow from './GroupRow.svelte'
|
||||
import Skeleton from '$lib/components/common/skeleton/Skeleton.svelte'
|
||||
|
||||
export let selectedGroup: object = {}
|
||||
|
||||
let groups: Array<{
|
||||
name: string
|
||||
path: string
|
||||
}> = []
|
||||
|
||||
let loading: boolean = false
|
||||
|
||||
async function getGroups() {
|
||||
loading = true
|
||||
groups = await listGroups($workspaceStore!)
|
||||
loading = false
|
||||
}
|
||||
|
||||
async function addGroup(nameField: string) {
|
||||
const groups = await ResourceService.listResourceNames({
|
||||
workspace: $workspaceStore!,
|
||||
name: 'app_group'
|
||||
})
|
||||
|
||||
const group: Group = {
|
||||
path: 'f/app_groups/group_' + groups.length,
|
||||
value: {
|
||||
value: selectedGroup,
|
||||
name: nameField
|
||||
}
|
||||
}
|
||||
|
||||
const message = await createGroup($workspaceStore!, group)
|
||||
|
||||
getGroups()
|
||||
|
||||
nameField = ''
|
||||
|
||||
sendUserToast('Group created:' + message)
|
||||
}
|
||||
|
||||
let nameField: string = ''
|
||||
|
||||
onMount(() => {
|
||||
getGroups()
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="p-2 flex flex-col items-start w-auto gap-2 relative">
|
||||
<div class="w-full flex flex-row gap-2 items-center">
|
||||
<input bind:value={nameField} placeholder={'Group name'} />
|
||||
<Button on:click={() => addGroup(nameField)} color="dark" size="xs">Create group</Button>
|
||||
</div>
|
||||
|
||||
{#if loading}
|
||||
<div class="flex flex-col w-full pt-12">
|
||||
{#each new Array(6) as _}
|
||||
<Skeleton layout={[[2], 0.5]} />
|
||||
{/each}
|
||||
</div>
|
||||
{:else if Array.isArray(groups) && groups.length > 0}
|
||||
<div class="w-full">
|
||||
<DataTable size="xs">
|
||||
<Head>
|
||||
<tr>
|
||||
<Cell first head>Path</Cell>
|
||||
<Cell last head />
|
||||
</tr>
|
||||
</Head>
|
||||
<tbody class="divide-y">
|
||||
{#if groups && groups.length > 0}
|
||||
{#each groups as row}
|
||||
{#key row}
|
||||
<GroupRow
|
||||
{row}
|
||||
on:reloadGroups={() => {
|
||||
getGroups()
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{/each}
|
||||
{:else}
|
||||
<tr>Loading...</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
</DataTable>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { Drawer, DrawerContent } from '$lib/components/common'
|
||||
import GroupList from './GroupList.svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppViewerContext, GridItem } from '../../types'
|
||||
import { getAllSubgridsAndComponentIds } from '../appUtils'
|
||||
|
||||
export let item: GridItem
|
||||
|
||||
const { app } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
$: subgrids = getSubgrids(item)
|
||||
|
||||
function getSubgrids(item: GridItem) {
|
||||
let allSubgrids = {}
|
||||
let subgrids = getAllSubgridsAndComponentIds($app, item.data)[0]
|
||||
for (let key of subgrids) {
|
||||
allSubgrids[key] = $app.subgrids?.[key]
|
||||
}
|
||||
return allSubgrids
|
||||
}
|
||||
|
||||
let codeDrawer: Drawer
|
||||
|
||||
export async function openDrawer() {
|
||||
codeDrawer.openDrawer()
|
||||
}
|
||||
</script>
|
||||
|
||||
<Drawer bind:this={codeDrawer}>
|
||||
<DrawerContent title="Group manager" on:close={codeDrawer.closeDrawer}>
|
||||
<GroupList
|
||||
selectedGroup={{
|
||||
item,
|
||||
subgrids
|
||||
}}
|
||||
/>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
@@ -0,0 +1,58 @@
|
||||
<script lang="ts">
|
||||
import { getGroup, updateGroup } from './groupUtils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
|
||||
import { Popup } from '$lib/components/common'
|
||||
import { Pen } from 'lucide-svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export let row: {
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
|
||||
let editedName = row.name
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<Popup
|
||||
floatingConfig={{ strategy: 'absolute', placement: 'bottom-end' }}
|
||||
containerClasses="border rounded-lg shadow-lg p-4 bg-surface"
|
||||
let:close
|
||||
>
|
||||
<svelte:fragment slot="button">
|
||||
<Button color="light" size="xs2" nonCaptureEvent={true}>
|
||||
<div class="flex flex-row gap-1 items-center">
|
||||
<Pen size={16} />
|
||||
</div>
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
<div class="flex flex-col w-80 gap-2">
|
||||
<div class="leading-6 font-semibold text-xs">Edit group name</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<input bind:value={editedName} />
|
||||
<Button
|
||||
color="dark"
|
||||
size="xs"
|
||||
on:click={async () => {
|
||||
if (!$workspaceStore) return
|
||||
const group = await getGroup($workspaceStore, row.path)
|
||||
await updateGroup($workspaceStore, row.path, {
|
||||
value: {
|
||||
...group,
|
||||
name: editedName
|
||||
}
|
||||
})
|
||||
dispatch('reloadGroups')
|
||||
close(null)
|
||||
sendUserToast('Group name updated:\n' + editedName)
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import { deleteGroup } from './groupUtils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import Cell from '$lib/components/table/Cell.svelte'
|
||||
|
||||
import { Trash } from 'lucide-svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import GroupNameEditor from './GroupNameEditor.svelte'
|
||||
|
||||
import ButtonDropdown from '$lib/components/common/button/ButtonDropdown.svelte'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { MenuItem } from '@rgossiaux/svelte-headlessui'
|
||||
|
||||
export let row: {
|
||||
name: string
|
||||
path: string
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function toggleDelete() {
|
||||
if ($workspaceStore) {
|
||||
await deleteGroup($workspaceStore, row.path)
|
||||
}
|
||||
dispatch('reloadGroups')
|
||||
sendUserToast('Group deleted:\n' + row.name)
|
||||
}
|
||||
</script>
|
||||
|
||||
<tr>
|
||||
<Cell first>
|
||||
<div class="flex flex-row gap-1 items-center">
|
||||
<GroupNameEditor on:reloadGroups {row} />
|
||||
{row.name}
|
||||
</div>
|
||||
</Cell>
|
||||
|
||||
<Cell last>
|
||||
<div class={twMerge('flex flex-row gap-1 justify-end ')}>
|
||||
<button on:pointerdown|stopPropagation>
|
||||
<ButtonDropdown hasPadding={false}>
|
||||
<svelte:fragment slot="items">
|
||||
<MenuItem on:click={toggleDelete}>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-red-600 flex flex-row items-center text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
<Trash size={16} />
|
||||
Delete
|
||||
</div>
|
||||
</MenuItem>
|
||||
</svelte:fragment>
|
||||
</ButtonDropdown>
|
||||
</button>
|
||||
</div>
|
||||
</Cell>
|
||||
</tr>
|
||||
@@ -14,20 +14,6 @@ const setTab = {
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#settab'
|
||||
}
|
||||
|
||||
const openModal = {
|
||||
title: 'openModal',
|
||||
description: 'Use the openModal function to open a modal.',
|
||||
example: 'openModal(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#openmodal'
|
||||
}
|
||||
|
||||
const closeModal = {
|
||||
title: 'closeModal',
|
||||
description: 'Use the closeModal function to close a modal.',
|
||||
example: 'closeModal(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#closemodal'
|
||||
}
|
||||
|
||||
const recompute = {
|
||||
title: 'recompute',
|
||||
description: 'Use the recompute function to recompute the value of a component.',
|
||||
@@ -57,6 +43,20 @@ const setSelectedIndex = {
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#setselectedindex'
|
||||
}
|
||||
|
||||
const open = {
|
||||
title: 'open',
|
||||
description: 'Use the open function to open a modal or a drawer.',
|
||||
example: 'open(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#open'
|
||||
}
|
||||
|
||||
const close = {
|
||||
title: 'close',
|
||||
description: 'Use the close function to close a modal or a drawer.',
|
||||
example: 'close(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#close'
|
||||
}
|
||||
|
||||
export function getComponentControl(type: keyof typeof components): Array<ComponentFunction> {
|
||||
switch (type) {
|
||||
case 'tabscomponent':
|
||||
@@ -70,7 +70,9 @@ export function getComponentControl(type: keyof typeof components): Array<Compon
|
||||
case 'steppercomponent':
|
||||
return [setTab]
|
||||
case 'modalcomponent':
|
||||
return [openModal, closeModal]
|
||||
return [open, close]
|
||||
case 'drawercomponent':
|
||||
return [open, close]
|
||||
case 'aggridcomponent':
|
||||
return [getAgGrid, setSelectedIndex]
|
||||
case 'displaycomponent':
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { ResourceService } from '$lib/gen'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export interface Group {
|
||||
path: string
|
||||
value: {
|
||||
value?: object
|
||||
name: string
|
||||
}
|
||||
}
|
||||
|
||||
export function createGroup(workspace: string, group: Group): Promise<string> {
|
||||
const createGroupRequest = {
|
||||
workspace,
|
||||
requestBody: {
|
||||
...group,
|
||||
resource_type: 'app_group',
|
||||
value: group.value || ''
|
||||
}
|
||||
}
|
||||
return ResourceService.createResource(createGroupRequest)
|
||||
}
|
||||
|
||||
export async function getGroup(
|
||||
workspace: string,
|
||||
path: string
|
||||
): Promise<{
|
||||
name: string,
|
||||
value: any
|
||||
}> {
|
||||
try {
|
||||
return ResourceService.getResourceValue({
|
||||
workspace,
|
||||
path
|
||||
})
|
||||
} catch (e) {
|
||||
sendUserToast(`Group not found ${path}`)
|
||||
return {
|
||||
value: '',
|
||||
name: 'Not found'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function updateGroup(workspace: string, path: string, updatedGroup: any): Promise<string> {
|
||||
const updateGroupRequest = {
|
||||
workspace,
|
||||
path,
|
||||
requestBody: updatedGroup
|
||||
}
|
||||
return ResourceService.updateResource(updateGroupRequest)
|
||||
}
|
||||
|
||||
export function deleteGroup(workspace: string, path: string): Promise<string> {
|
||||
const deleteGroupRequest = {
|
||||
workspace,
|
||||
path: path
|
||||
}
|
||||
return ResourceService.deleteResource(deleteGroupRequest)
|
||||
}
|
||||
|
||||
export async function listGroups(workspace: string): Promise<
|
||||
Array<{
|
||||
name: string
|
||||
path: string
|
||||
}>
|
||||
> {
|
||||
const listGroupsRequest = {
|
||||
workspace,
|
||||
name: 'app_group'
|
||||
}
|
||||
return ResourceService.listResourceNames(listGroupsRequest)
|
||||
}
|
||||
@@ -72,7 +72,10 @@
|
||||
const theme = $app.theme
|
||||
|
||||
if (theme?.type === 'path') {
|
||||
sendUserToast('Cannot migrate to CSS editor when using a theme by path', true)
|
||||
sendUserToast(
|
||||
'Cannot migrate to CSS editor when using a theme by path. Fork a global theme to edit CSS.',
|
||||
true
|
||||
)
|
||||
return
|
||||
} else if (theme?.type === 'inlined') {
|
||||
let cssString = theme.css
|
||||
|
||||
@@ -299,9 +299,8 @@
|
||||
{/if}
|
||||
{/key}
|
||||
</PanelSection>
|
||||
|
||||
{/if}
|
||||
|
||||
|
||||
<ComponentControl type={component.type} />
|
||||
|
||||
{#if componentSettings.item.data.type === 'tabscomponent'}
|
||||
@@ -320,7 +319,7 @@
|
||||
{:else if componentSettings.item.data.type === 'containercomponent'}
|
||||
<GridGroup
|
||||
bind:groupFields={componentSettings.item.data.groupFields}
|
||||
bind:component={componentSettings.item.data}
|
||||
item={componentSettings.item}
|
||||
/>
|
||||
{:else if componentSettings.item.data.type === 'conditionalwrapper'}
|
||||
<GridCondition
|
||||
@@ -434,6 +433,5 @@
|
||||
</div>
|
||||
</PanelSection>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
import type { RichConfigurations } from '../../types'
|
||||
import type { AppComponent } from '../component'
|
||||
import type { GridItem, RichConfigurations } from '../../types'
|
||||
import PanelSection from './common/PanelSection.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import InputsSpecsEditor from './InputsSpecsEditor.svelte'
|
||||
import GroupManagementDrawer from '../componentsPanel/GroupManagementDrawer.svelte'
|
||||
|
||||
export let groupFields: RichConfigurations | undefined
|
||||
export let item: GridItem
|
||||
|
||||
export let component: AppComponent
|
||||
let groupManagementDrawer: GroupManagementDrawer | undefined = undefined
|
||||
|
||||
// const { app, runnableComponents } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -48,6 +49,17 @@
|
||||
/>
|
||||
</div>
|
||||
{#if groupFields != undefined}
|
||||
<div class="p-2">
|
||||
<Button
|
||||
on:click={() => {
|
||||
groupManagementDrawer?.openDrawer()
|
||||
}}
|
||||
size="xs"
|
||||
color="light"
|
||||
>
|
||||
Save group to workspace
|
||||
</Button>
|
||||
</div>
|
||||
<PanelSection
|
||||
title={`Group Fields ${
|
||||
Object.keys(groupFields ?? {}).length > 0
|
||||
@@ -67,7 +79,7 @@
|
||||
delete groupFields[e.detail]
|
||||
groupFields = groupFields
|
||||
}}
|
||||
id={component.id}
|
||||
id={item.id}
|
||||
shouldCapitalize={false}
|
||||
displayType
|
||||
deletable
|
||||
@@ -101,3 +113,5 @@
|
||||
</div>
|
||||
</PanelSection>
|
||||
{/if}
|
||||
|
||||
<GroupManagementDrawer bind:this={groupManagementDrawer} {item} />
|
||||
|
||||
@@ -234,6 +234,8 @@ export type AppViewerContext = {
|
||||
setSelectedIndex?: (index: number) => void
|
||||
openModal?: () => void
|
||||
closeModal?: () => void
|
||||
open?: () => void
|
||||
close?: () => void
|
||||
}
|
||||
>
|
||||
>
|
||||
@@ -249,7 +251,7 @@ export type AppEditorContext = {
|
||||
pickVariableCallback: Writable<((path: string) => void) | undefined>
|
||||
selectedComponentInEditor: Writable<string | undefined>
|
||||
movingcomponents: Writable<string[] | undefined>
|
||||
jobsDrawerOpen: Writable<boolean>,
|
||||
jobsDrawerOpen: Writable<boolean>
|
||||
scale: Writable<number>
|
||||
}
|
||||
|
||||
|
||||
@@ -172,20 +172,65 @@ export function buildExtraLib(
|
||||
return `${cs}
|
||||
${
|
||||
goto
|
||||
? `declare async function goto(path: string, newTab?: boolean): Promise<void>;
|
||||
? `
|
||||
/** open a window or tab
|
||||
* @param path path/url to go to
|
||||
* @param open in a tab?
|
||||
*/
|
||||
declare async function goto(path: string, newTab?: boolean): Promise<void>;
|
||||
|
||||
/** set tab
|
||||
* @param id component's id
|
||||
* @param index index of the tab to set
|
||||
*/
|
||||
declare function setTab(id: string, index: string): void;
|
||||
|
||||
/** recompute a component's runnable or background runnable
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function recompute(id: string): void;
|
||||
|
||||
/** get the ag grid api from an AgGridTable
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function getAgGrid(id: string): {api: any, columnApi: any} | undefined;
|
||||
|
||||
|
||||
/** set value of a component
|
||||
* @param id component's id
|
||||
* @param value value to set
|
||||
*/
|
||||
declare function setValue(id: string, value: any): void;
|
||||
|
||||
/** set selected index of a table
|
||||
* @param id component's id
|
||||
* @param index index to set
|
||||
*/
|
||||
declare function setSelectedIndex(id: string, index: number): void;
|
||||
declare function openModal(id: string): void;
|
||||
declare function closeModal(id: string): void;
|
||||
|
||||
/** close a drawer or modal
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function open(id: string): void;
|
||||
|
||||
/** close a drawer or modal
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function close(id: string): void;
|
||||
`
|
||||
: ''
|
||||
}
|
||||
|
||||
/** The current's app state */
|
||||
declare const state: ${JSON.stringify(state)};
|
||||
|
||||
/** The iterator within the context of a list */
|
||||
declare const iter: {index: number, value: any};
|
||||
|
||||
/** The row within the context of a table */
|
||||
declare const row: Record<string, any>;
|
||||
|
||||
/** The group fields within the context of a container's group */
|
||||
declare const group: Record<string, any>;
|
||||
|
||||
`
|
||||
|
||||
@@ -104,7 +104,13 @@
|
||||
|
||||
$: !$generatedCode && hideDiff()
|
||||
|
||||
$: dbSchema = $dbSchemas[(lang === 'graphql' ? args.api : args.database)?.replace('$res:', '')]
|
||||
function updateSchema(lang, args) {
|
||||
const schemaRes = lang === 'graphql' ? args.api : args.database
|
||||
if (schemaRes instanceof String) {
|
||||
dbSchema = $dbSchemas[schemaRes.replace('$res:', '')]
|
||||
}
|
||||
}
|
||||
$: updateSchema(lang, args)
|
||||
</script>
|
||||
|
||||
{#if SUPPORTED_LANGUAGES.has(lang)}
|
||||
|
||||
@@ -146,7 +146,13 @@
|
||||
$: editor && setSelectionHandler()
|
||||
$: selection && (isEdit = !selection.isEmpty())
|
||||
|
||||
$: dbSchema = $dbSchemas[(lang === 'graphql' ? args.api : args.database)?.replace('$res:', '')]
|
||||
function updateSchema(lang, args) {
|
||||
const schemaRes = lang === 'graphql' ? args.api : args.database
|
||||
if (schemaRes instanceof String) {
|
||||
dbSchema = $dbSchemas[schemaRes.replace('$res:', '')]
|
||||
}
|
||||
}
|
||||
$: updateSchema(lang, args)
|
||||
</script>
|
||||
|
||||
{#if $generatedCode.length > 0 && !genLoading}
|
||||
|
||||
@@ -162,6 +162,18 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -207,6 +219,18 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -547,6 +571,18 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -592,6 +628,18 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,20 @@
|
||||
export let last: boolean = false
|
||||
export let numeric: boolean = false
|
||||
export let head: boolean = false
|
||||
export let shouldStopPropagation: boolean = false
|
||||
|
||||
let Tag = head ? 'th' : 'td'
|
||||
|
||||
const { size } = getContext<DatatableContext>('datatable')
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<svelte:element
|
||||
this={Tag}
|
||||
{...$$restProps}
|
||||
on:click={(e) => {
|
||||
if (shouldStopPropagation) e.stopPropagation()
|
||||
}}
|
||||
class={twMerge(
|
||||
'px-2 py-3.5 text-left text-xs text-primary font-normal whitespace-nowrap',
|
||||
first ? 'sm:pl-6' : '',
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
<FolderUsageInfo {name} tabular />
|
||||
|
||||
<Cell><FolderInfo members={computeMembers(owners, extra_perms)} /></Cell>
|
||||
<Cell>
|
||||
<Cell shouldStopPropagation>
|
||||
<Dropdown
|
||||
placement="bottom-end"
|
||||
dropdownItems={[
|
||||
|
||||
@@ -128,25 +128,28 @@
|
||||
</script>
|
||||
|
||||
<CenteredModal title="New Workspace">
|
||||
<label class="block pb-2 pt-4">
|
||||
<label class="block pb-4 pt-4">
|
||||
<span class="text-secondary text-sm">Workspace name</span>
|
||||
<input type="text" bind:value={name} />
|
||||
<span class="ml-4 text-tertiary text-xs">Displayable name</span>
|
||||
|
||||
<input autofocus type="text" bind:value={name} />
|
||||
</label>
|
||||
<label class="block pb-2">
|
||||
<label class="block pb-4">
|
||||
<span class="text-secondary text-sm">Workspace ID</span>
|
||||
<span class="ml-10 text-tertiary text-xs">Slug to uniquely identify your workspace</span>
|
||||
{#if errorId}
|
||||
<span class="text-red-500 text-xs">{errorId}</span>
|
||||
{/if}
|
||||
<input type="text" bind:value={id} class:input-error={errorId != ''} />
|
||||
</label>
|
||||
<label class="block pb-2">
|
||||
<label class="block pb-4">
|
||||
<span class="text-secondary text-sm">Your username in that workspace</span>
|
||||
<input type="text" bind:value={username} on:keyup={handleKeyUp} />
|
||||
{#if errorUser}
|
||||
<span class="text-red-500 text-xs">{errorUser}</span>
|
||||
{/if}
|
||||
</label>
|
||||
<label class="block pb-2">
|
||||
<label class="block pb-4">
|
||||
<span class="text-secondary text-sm"
|
||||
>OpenAI key for codegen<span class="text-2xs text-tertiary ml-2"
|
||||
>(optional but recommended)</span
|
||||
|
||||
@@ -4,8 +4,8 @@ verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
wmill = ">=1.177.0"
|
||||
wmill_pg = ">=1.177.0"
|
||||
wmill = ">=1.178.1"
|
||||
wmill_pg = ">=1.178.1"
|
||||
sendgrid = "*"
|
||||
mysql-connector-python = "*"
|
||||
pymongo = "*"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openapi: "3.0.3"
|
||||
|
||||
info:
|
||||
version: 1.177.0
|
||||
version: 1.178.1
|
||||
title: OpenFlow Spec
|
||||
contact:
|
||||
name: Ruben Fiszel
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
description = "A client library for accessing Windmill server wrapping the Windmill client API"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
@@ -16,7 +16,7 @@ include = ["wmill/py.typed"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.7"
|
||||
windmill-api = "^1.177.0"
|
||||
windmill-api = "^1.178.1"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=1.0.2", "poetry-dynamic-versioning"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "wmill-pg"
|
||||
version = "1.177.0"
|
||||
version = "1.178.1"
|
||||
description = "An extension client for the wmill client library focused on pg"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://windmill.dev"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "windmill-client",
|
||||
"description": "Windmill SDK client for browsers and Node.js",
|
||||
"version": "1.177.0",
|
||||
"version": "1.178.1",
|
||||
"author": "Ruben Fiszel",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.177.0
|
||||
1.178.1
|
||||
|
||||
Reference in New Issue
Block a user