Merge branch 'dev' into playground

This commit is contained in:
cristhianzl 2024-04-23 21:55:54 -03:00
commit 9055eb0bc9
18 changed files with 1268 additions and 47 deletions

View file

@ -35,7 +35,7 @@ fi
# Create a firewall rule to allow IAP traffic
firewall_iap_exists=$(gcloud compute firewall-rules list --filter="name=allow-iap" --format="value(name)")
if [[ -z "$firewall_iap_exists" ]]; then
gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443,tcp:22,:tcp:3389 --source-ranges 35.235.240.0/20 --direction INGRESS
gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443,tcp:22,tcp:3389 --source-ranges 35.235.240.0/20 --direction INGRESS
fi
# Define the startup script as a multiline Bash here-doc

View file

@ -28,3 +28,7 @@ yarn-error.log*
/playwright-report/
/blob-report/
/playwright/.cache/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

View file

@ -31,6 +31,7 @@
"@tailwindcss/line-clamp": "^0.4.4",
"@types/axios": "^0.14.0",
"ace-builds": "^1.24.1",
"ag-grid-react": "^31.2.1",
"ansi-to-html": "^0.7.2",
"axios": "^1.5.0",
"base64-js": "^1.5.1",
@ -40,11 +41,13 @@
"dompurify": "^3.0.5",
"dotenv": "^16.4.5",
"esbuild": "^0.17.19",
"file-saver": "^2.0.5",
"framer-motion": "^11.0.6",
"lodash": "^4.17.21",
"lucide-react": "^0.331.0",
"million": "^3.0.6",
"moment": "^2.29.4",
"openseadragon": "^4.1.1",
"playwright": "^1.42.0",
"react": "^18.2.0",
"react-ace": "^10.1.0",
@ -54,6 +57,7 @@
"react-icons": "^5.0.1",
"react-laag": "^2.0.5",
"react-markdown": "^8.0.7",
"react-pdf": "^7.7.1",
"react-router-dom": "^6.15.0",
"react-syntax-highlighter": "^15.5.0",
"react18-json-view": "^0.2.3",
@ -71,7 +75,7 @@
"zustand": "^4.4.7"
},
"devDependencies": {
"@playwright/test": "^1.42.0",
"@playwright/test": "^1.43.1",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.80",
"@tailwindcss/typography": "^0.5.9",
@ -1059,6 +1063,59 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
"optional": true,
"dependencies": {
"detect-libc": "^2.0.0",
"https-proxy-agent": "^5.0.0",
"make-dir": "^3.1.0",
"node-fetch": "^2.6.7",
"nopt": "^5.0.0",
"npmlog": "^5.0.1",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"tar": "^6.1.11"
},
"bin": {
"node-pre-gyp": "bin/node-pre-gyp"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"optional": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"optional": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
},
"node_modules/@million/lint": {
"version": "0.0.73",
"resolved": "https://registry.npmjs.org/@million/lint/-/lint-0.0.73.tgz",
@ -1759,12 +1816,12 @@
}
},
"node_modules/@playwright/test": {
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz",
"integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==",
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz",
"integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==",
"dev": true,
"dependencies": {
"playwright": "1.42.1"
"playwright": "1.43.1"
},
"bin": {
"playwright": "cli.js"
@ -4283,6 +4340,12 @@
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
"deprecated": "Use your platform's native atob() and btoa() methods instead"
},
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"optional": true
},
"node_modules/ace-builds": {
"version": "1.32.9",
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.9.tgz",
@ -4325,6 +4388,24 @@
"node": ">=0.4.0"
}
},
"node_modules/ag-grid-community": {
"version": "31.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-31.2.1.tgz",
"integrity": "sha512-D+gnUQ4dHZ/EQJmupQnDqcEKiCEeuK5ZxlsIpdPKgHg/23dmW+aEdivtB9nLpSc2IEK0RUpchcSxeUT37Boo5A=="
},
"node_modules/ag-grid-react": {
"version": "31.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-31.2.1.tgz",
"integrity": "sha512-9UH3xxXRwZfW97oz58KboyCJl4t+zdetopieeHVcttsXX1DvGFDUIEz7A1sQaG8e1DAXLMf3IxoIPrfWheH4XA==",
"dependencies": {
"ag-grid-community": "31.2.1",
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": "^16.3.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -4402,6 +4483,12 @@
"node": ">= 8"
}
},
"node_modules/aproba": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
"optional": true
},
"node_modules/arch": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
@ -4422,6 +4509,19 @@
}
]
},
"node_modules/are-we-there-yet": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
"optional": true,
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
@ -4907,6 +5007,21 @@
}
]
},
"node_modules/canvas": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
"integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.0",
"nan": "^2.17.0",
"simple-get": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/ccount": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
@ -4990,6 +5105,15 @@
"node": ">= 6"
}
},
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"optional": true,
"engines": {
"node": ">=10"
}
},
"node_modules/class-variance-authority": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.6.1.tgz",
@ -5095,6 +5219,15 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
"node_modules/color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
"optional": true,
"bin": {
"color-support": "bin.js"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -5128,7 +5261,13 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
"devOptional": true
},
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
"optional": true
},
"node_modules/content-disposition": {
"version": "0.5.4",
@ -5583,6 +5722,12 @@
"node": ">=0.4.0"
}
},
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
"optional": true
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@ -5591,6 +5736,15 @@
"node": ">=6"
}
},
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"optional": true,
"engines": {
"node": ">=8"
}
},
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
@ -6438,6 +6592,11 @@
"node": "^10.12.0 || >=12.0.0"
}
},
"node_modules/file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"node_modules/file-type": {
"version": "17.1.6",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz",
@ -6682,11 +6841,41 @@
"node": ">=14.14"
}
},
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"optional": true,
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/fs-minipass/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"optional": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fs-minipass/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
"devOptional": true
},
"node_modules/fsevents": {
"version": "2.3.2",
@ -6718,6 +6907,46 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gauge": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
"optional": true,
"dependencies": {
"aproba": "^1.0.3 || ^2.0.0",
"color-support": "^1.1.2",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.1",
"object-assign": "^4.1.1",
"signal-exit": "^3.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wide-align": "^1.1.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/gauge/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"optional": true
},
"node_modules/gauge/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"optional": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@ -6766,7 +6995,7 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"devOptional": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -6797,7 +7026,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"devOptional": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -6807,7 +7036,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"devOptional": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@ -6939,6 +7168,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
"optional": true
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@ -7244,7 +7479,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dev": true,
"devOptional": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@ -8253,6 +8488,37 @@
"lz-string": "bin/bin.js"
}
},
"node_modules/make-cancellable-promise": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.3.2.tgz",
"integrity": "sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww==",
"funding": {
"url": "https://github.com/wojtekmaj/make-cancellable-promise?sponsor=1"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"optional": true,
"dependencies": {
"semver": "^6.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-event-props": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.6.2.tgz",
"integrity": "sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA==",
"funding": {
"url": "https://github.com/wojtekmaj/make-event-props?sponsor=1"
}
},
"node_modules/markdown-table": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
@ -8501,6 +8767,22 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/merge-refs": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-1.2.2.tgz",
"integrity": "sha512-RwcT7GsQR3KbuLw1rRuodq4Nt547BKEBkliZ0qqsrpyNne9bGTFtsFIsIpx82huWhcl3kOlOlH4H0xkPk/DqVw==",
"funding": {
"url": "https://github.com/wojtekmaj/merge-refs?sponsor=1"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -9186,6 +9468,37 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"optional": true,
"dependencies": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/minizlib/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"optional": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minizlib/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
},
"node_modules/mj-context-menu": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
@ -9236,6 +9549,12 @@
"thenify-all": "^1.0.0"
}
},
"node_modules/nan": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz",
"integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==",
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
@ -9310,6 +9629,21 @@
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
},
"node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"optional": true,
"dependencies": {
"abbrev": "1"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@ -9360,6 +9694,18 @@
"node": ">=4"
}
},
"node_modules/npmlog": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
"optional": true,
"dependencies": {
"are-we-there-yet": "^2.0.0",
"console-control-strings": "^1.1.0",
"gauge": "^3.0.0",
"set-blocking": "^2.0.0"
}
},
"node_modules/nwsapi": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz",
@ -9437,7 +9783,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"devOptional": true,
"dependencies": {
"wrappy": "1"
}
@ -9456,6 +9802,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/openseadragon": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-4.1.1.tgz",
"integrity": "sha512-owU9gsasAcobLN+LM8lN58Xc2VDSDotY9mkrwS/NB6g9KX/PcusV4RZvhHng2RF/Q0pMziwldf62glwXoGnuzg==",
"funding": {
"url": "https://opencollective.com/openseadragon"
}
},
"node_modules/optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
@ -9685,7 +10039,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"devOptional": true,
"engines": {
"node": ">=0.10.0"
}
@ -9734,6 +10088,27 @@
"node": ">=8"
}
},
"node_modules/path2d-polyfill": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz",
"integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==",
"optional": true,
"engines": {
"node": ">=8"
}
},
"node_modules/pdfjs-dist": {
"version": "3.11.174",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
"integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"canvas": "^2.11.2",
"path2d-polyfill": "^2.0.1"
}
},
"node_modules/peek-readable": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
@ -9780,11 +10155,11 @@
}
},
"node_modules/playwright": {
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz",
"integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==",
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz",
"integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==",
"dependencies": {
"playwright-core": "1.42.1"
"playwright-core": "1.43.1"
},
"bin": {
"playwright": "cli.js"
@ -9797,9 +10172,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz",
"integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==",
"version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz",
"integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==",
"bin": {
"playwright-core": "cli.js"
},
@ -10544,6 +10919,43 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-pdf": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-7.7.1.tgz",
"integrity": "sha512-cbbf/PuRtGcPPw+HLhMI1f6NSka8OJgg+j/yPWTe95Owf0fK6gmVY7OXpTxMeh92O3T3K3EzfE0ML0eXPGwR5g==",
"dependencies": {
"clsx": "^2.0.0",
"dequal": "^2.0.3",
"make-cancellable-promise": "^1.3.1",
"make-event-props": "^1.6.0",
"merge-refs": "^1.2.1",
"pdfjs-dist": "3.11.174",
"prop-types": "^15.6.2",
"tiny-invariant": "^1.0.0",
"warning": "^4.0.0"
},
"funding": {
"url": "https://github.com/wojtekmaj/react-pdf?sponsor=1"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-pdf/node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"engines": {
"node": ">=6"
}
},
"node_modules/react-reconciler": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz",
@ -10967,7 +11379,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"devOptional": true,
"dependencies": {
"glob": "^7.1.3"
},
@ -11142,6 +11554,12 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"optional": true
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@ -11421,6 +11839,61 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"optional": true
},
"node_modules/simple-get": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
"optional": true,
"dependencies": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-get/node_modules/decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"optional": true,
"dependencies": {
"mimic-response": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/simple-get/node_modules/mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
"optional": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@ -11875,6 +12348,50 @@
"node": ">=4"
}
},
"node_modules/tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
"optional": true,
"dependencies": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^5.0.0",
"minizlib": "^2.1.1",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/tar/node_modules/minipass": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"optional": true,
"engines": {
"node": ">=8"
}
},
"node_modules/tar/node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"optional": true,
"bin": {
"mkdirp": "bin/cmd.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/tar/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
},
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -11900,6 +12417,11 @@
"node": ">=0.8"
}
},
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
},
"node_modules/tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
@ -12857,6 +13379,14 @@
"node": ">=14"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
@ -13018,6 +13548,35 @@
"resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
"integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw=="
},
"node_modules/wide-align": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"optional": true,
"dependencies": {
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
"node_modules/wide-align/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"optional": true
},
"node_modules/wide-align/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"optional": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
@ -13139,7 +13698,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
"devOptional": true
},
"node_modules/ws": {
"version": "8.16.0",

View file

@ -26,6 +26,7 @@
"@tailwindcss/line-clamp": "^0.4.4",
"@types/axios": "^0.14.0",
"ace-builds": "^1.24.1",
"ag-grid-react": "^31.2.1",
"ansi-to-html": "^0.7.2",
"axios": "^1.5.0",
"base64-js": "^1.5.1",
@ -35,11 +36,13 @@
"dompurify": "^3.0.5",
"dotenv": "^16.4.5",
"esbuild": "^0.17.19",
"file-saver": "^2.0.5",
"framer-motion": "^11.0.6",
"lodash": "^4.17.21",
"lucide-react": "^0.331.0",
"million": "^3.0.6",
"moment": "^2.29.4",
"openseadragon": "^4.1.1",
"playwright": "^1.42.0",
"react": "^18.2.0",
"react-ace": "^10.1.0",
@ -49,6 +52,7 @@
"react-icons": "^5.0.1",
"react-laag": "^2.0.5",
"react-markdown": "^8.0.7",
"react-pdf": "^7.7.1",
"react-router-dom": "^6.15.0",
"react-syntax-highlighter": "^15.5.0",
"react18-json-view": "^0.2.3",
@ -93,7 +97,7 @@
},
"proxy": "http://127.0.0.1:7860",
"devDependencies": {
"@playwright/test": "^1.42.0",
"@playwright/test": "^1.43.1",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.80",
"@tailwindcss/typography": "^0.5.9",

View file

@ -0,0 +1,141 @@
import { useEffect, useRef, useState } from "react";
import ForwardedIconComponent from "../genericIconComponent";
import useFlowStore from "../../stores/flowStore";
import OpenSeadragon from 'openseadragon';
import { Separator } from "../ui/separator";
import { saveAs } from 'file-saver'
import useAlertStore from "../../stores/alertStore";
import { IMGViewErrorMSG, IMGViewErrorTitle } from "../../constants/constants";
export default function ImageViewer({image }) {
const viewerRef = useRef(null);
const [errorDownloading, setErrordownloading] = useState(false)
const setErrorList = useAlertStore(state => state.setErrorData);
const [initialMsg, setInicialMsg] = useState("Please build your flow");
useEffect(() => {
try {
if (viewerRef.current) {
// Initialize OpenSeadragon viewer
const viewer = OpenSeadragon({
element: viewerRef.current,
prefixUrl: 'https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/images/', // Optional: Set the path to OpenSeadragon images
tileSources: {type: 'image', url: image},
defaultZoomLevel: 1,
maxZoomPixelRatio: 4,
showNavigationControl: false,
});
const zoomInButton = document.getElementById('zoom-in-button');
const zoomOutButton = document.getElementById('zoom-out-button');
const homeButton = document.getElementById('home-button');
const fullPageButton = document.getElementById('full-page-button');
zoomInButton!.addEventListener('click', () => viewer.viewport.zoomBy(1.2));
zoomOutButton!.addEventListener('click', () => viewer.viewport.zoomBy(0.8));
homeButton!.addEventListener('click', () => viewer.viewport.goHome());
fullPageButton!.addEventListener('click', () => viewer.setFullScreen(true));
// Optionally, you can set additional viewer options here
// Cleanup function
return () => {
viewer.destroy();
zoomInButton!.removeEventListener('click', () => viewer.viewport.zoomBy(1.2));
zoomOutButton!.removeEventListener('click', () => viewer.viewport.zoomBy(0.8));
homeButton!.removeEventListener('click', () => viewer.viewport.goHome());
fullPageButton!.removeEventListener('click', () => viewer.setFullScreen(true));
};
}
} catch (error) {
console.error('Error initializing OpenSeadragon:', error);
}
}, [image]);
function download() {
const imageUrl = image;
// Fetch the image data
fetch(imageUrl)
.then(response => response.blob())
.then(blob => {
// Save the image using FileSaver.js
saveAs(blob, 'image.jpg');
})
.catch(error => {
setErrorList({title: "There was an error downloading your image"})
console.error('Error downloading image:', error)
});
}
return (
image === "" ? (
<div className="w-full h-full bg-muted rounded-md flex align-center justify-center flex-col gap-5 border border-border">
<div className="flex gap-2 align-center justify-center ">
<ForwardedIconComponent
name="Image"
/>
{IMGViewErrorTitle}
</div>
<div className="flex align-center justify-center">
<div className="langflow-chat-desc flex align-center justify-center">
<div className="langflow-chat-desc-span">
{IMGViewErrorMSG}
</div>
</div>
</div>
</div>
) : (
<>
<div className="w-full flex align-center justify-center my-2 mb-4">
<div className="shadow-round-btn-shadow hover:shadow-round-btn-shadow flex items-center justify-center rounded-sm border bg-muted shadow-md transition-all w-[50%]">
<button id="zoom-in-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all w-full transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
<ForwardedIconComponent
name="ZoomIn"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</div>
<button id="zoom-out-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
<ForwardedIconComponent
name="ZoomOut"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</div>
<button id="home-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
<ForwardedIconComponent
name="RotateCcw"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</div>
<button id="full-page-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
<ForwardedIconComponent
name="Maximize2"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</div>
<button onClick={download} className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
<ForwardedIconComponent
name="ArrowDownToLine"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
</div>
</div>
<div id="canvas" ref={viewerRef} className={`w-full h-[90%] `} />
</>
)
);
}

View file

@ -0,0 +1,27 @@
export const convertCSVToData = (csvFile, csvSeparator: string) => {
const lines = csvFile.data.trim().split("\n");
const headers = lines[0].trim().split(csvSeparator);
const initialRowData: any = [];
const initialColDefs = headers.map((header) => ({
field: header.trim(),
wrapText: true,
autoHeight: true,
height: "100%",
}));
for (let i = 1; i < lines.length; i++) {
const data = lines[i].trim().split(csvSeparator);
const rowDataEntry: any = {};
for (let j = 0; j < headers.length; j++) {
const value = isNaN(data[j]) ? data[j] : parseFloat(data[j]);
rowDataEntry[headers[j].trim()] = value;
}
initialRowData.push(rowDataEntry);
}
return { rowData: initialRowData, colDefs: initialColDefs };
};

View file

@ -0,0 +1,182 @@
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid
import "ag-grid-community/styles/ag-theme-balham.css"; // Optional Theme applied to the grid
import { AgGridReact } from "ag-grid-react";
import { useCallback, useEffect, useMemo, useState } from "react";
import {
CSVError,
CSVNoDataError,
CSVViewErrorTitle,
} from "../../constants/constants";
import { useDarkStore } from "../../stores/darkStore";
import { FlowPoolObjectType } from "../../types/chat";
import { NodeType } from "../../types/flow";
import ForwardedIconComponent from "../genericIconComponent";
import Loading from "../ui/loading";
import { convertCSVToData } from "./helpers/convert-data-function";
function CsvOutputComponent({
csvNode,
flowPool,
}: {
csvNode: NodeType;
flowPool: FlowPoolObjectType;
}) {
const csvNodeArtifacts = flowPool?.data?.artifacts?.repr;
const jsonString = csvNodeArtifacts?.replace(/'/g, '"');
let file = null;
try {
file = JSON?.parse(jsonString) || "";
} catch (e) {
console.log("Error parsing JSON");
}
if (!file) {
return (
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex w-full justify-center gap-2">
<ForwardedIconComponent name="Table" />
{CSVViewErrorTitle}
</div>
<div className="align-center flex w-full justify-center">
<div className="langflow-chat-desc align-center flex justify-center px-6 py-8">
<div className="langflow-chat-desc-span">{CSVError}</div>
</div>
</div>
</div>
);
}
const separator = csvNode?.data?.node?.template?.separator?.value || ",";
const dark = useDarkStore.getState().dark;
const [rowData, setRowData] = useState([]);
const [colDefs, setColDefs] = useState([]);
const [status, setStatus] = useState("loading");
var currentRowHeight: number;
var minRowHeight = 25;
const defaultColDef = useMemo(() => {
return {
width: 200,
editable: true,
filter: true,
};
}, []);
useEffect(() => {
setStatus("loading");
if (file) {
const { rowData: data, colDefs: columns } = convertCSVToData(
file,
separator
);
setRowData(data);
setColDefs(columns);
setTimeout(() => {
setStatus("loaded");
}, 1000);
} else {
setStatus("nodata");
}
}, [separator]);
const getRowHeight = useCallback(() => {
return currentRowHeight;
}, []);
const onGridReady = useCallback((params: any) => {
minRowHeight = params.api.getSizesForCurrentTheme().rowHeight;
currentRowHeight = minRowHeight;
}, []);
const updateRowHeight = (params: { api: any }) => {
const bodyViewport = document.querySelector(".ag-body-viewport");
if (!bodyViewport) {
return;
}
var gridHeight = bodyViewport.clientHeight;
var renderedRowCount = params.api.getDisplayedRowCount();
if (renderedRowCount * minRowHeight >= gridHeight) {
if (currentRowHeight !== minRowHeight) {
currentRowHeight = minRowHeight;
params.api.resetRowHeights();
}
} else {
currentRowHeight = Math.floor(gridHeight / renderedRowCount);
params.api.resetRowHeights();
}
};
const onFirstDataRendered = useCallback(
(params: any) => {
updateRowHeight(params);
},
[updateRowHeight]
);
const onGridSizeChanged = useCallback(
(params: any) => {
updateRowHeight(params);
},
[updateRowHeight]
);
return (
<div className=" h-full rounded-md border bg-muted">
{status === "nodata" && (
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex w-full justify-center gap-2">
<ForwardedIconComponent name="Table" />
{CSVViewErrorTitle}
</div>
<div className="align-center flex w-full justify-center">
<div className="langflow-chat-desc align-center flex justify-center px-6 py-8">
<div className="langflow-chat-desc-span">{CSVNoDataError}</div>
</div>
</div>
</div>
)}
{status === "error" && (
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
<div className="align-center flex w-full justify-center gap-2">
<ForwardedIconComponent name="Table" />
{CSVViewErrorTitle}
</div>
<div className="align-center flex w-full justify-center">
<div className="langflow-chat-desc align-center flex justify-center px-6 py-8">
<div className="langflow-chat-desc-span">{CSVError}</div>
</div>
</div>
</div>
)}
{status === "loaded" && (
<div
className={`${dark ? "ag-theme-balham-dark" : "ag-theme-balham"}`}
style={{ height: "100%", width: "100%" }}
>
<AgGridReact
rowData={rowData}
columnDefs={colDefs}
defaultColDef={defaultColDef}
getRowHeight={getRowHeight}
onGridReady={onGridReady}
onFirstDataRendered={onFirstDataRendered}
onGridSizeChanged={onGridSizeChanged}
scrollbarWidth={8}
/>
</div>
)}
{status === "loading" && (
<div className=" flex h-full w-full items-center justify-center align-middle">
<Loading />
</div>
)}
</div>
);
}
export default CsvOutputComponent;

View file

@ -0,0 +1,23 @@
import { CHAT_FIRST_INITIAL_TEXT, CHAT_SECOND_INITIAL_TEXT, PDFCheckFlow, PDFLoadErrorTitle } from "../../../constants/constants";
import IconComponent from "../../genericIconComponent";
export default function Error(): JSX.Element {
return (
<div className="flex flex-col items-center justify-center h-full w-full bg-muted">
<div className="chat-alert-box">
<span className="flex gap-2">
<IconComponent name="FileX2" />
<span className="langflow-chat-span">{PDFLoadErrorTitle}</span>
</span>
<br />
<div className="langflow-chat-desc">
<span className="langflow-chat-desc-span">
{PDFCheckFlow}{" "}
</span>
</div>
</div>
</div>
);
}

View file

@ -0,0 +1,155 @@
import { useEffect, useRef, useState } from "react";
import { Document, Page, pdfjs } from "react-pdf";
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "react-pdf/dist/esm/Page/TextLayer.css";
import IconComponent from "../genericIconComponent";
import Loading from "../ui/loading";
import Error from "./Error";
import NoDataPdf from "./noData";
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;
export default function PdfViewer({ pdf }: { pdf: string }): JSX.Element {
const [numPages, setNumPages] = useState(-1);
const [pageNumber, setPageNumber] = useState(1);
const [scale, setScale] = useState(1);
const [width, setWidth] = useState<number | undefined>(undefined);
const [showControl, setShowControl] = useState(false);
const container = useRef<null | HTMLDivElement>(null);
//shortcuts to change page
useEffect(() => {
function handleKeyDown(event: KeyboardEvent) {
if (event.key === "ArrowLeft") {
if (pageNumber > 1) previousPage();
} else if (event.key === "ArrowRight") {
if (pageNumber < numPages) nextPage();
}
}
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, [pageNumber]);
function onDocumentLoadSuccess({ numPages }) {
setNumPages(numPages);
setPageNumber(1);
}
function changePage(offset) {
setPageNumber((prevPageNumber) => prevPageNumber + offset);
}
function previousPage() {
changePage(-1);
}
function nextPage() {
changePage(1);
}
//set handle scale in % to real number
function handleScaleChange(e) {
//check if e is a number
if (isNaN(e) || e < 0.1) return;
// round to 2 decimal places
e = Math.round(e * 10) / 10;
setScale(e);
}
function zoomIn() {
handleScaleChange(scale + 0.1);
}
function zoomOut() {
if (scale > 0.1) handleScaleChange(scale - 0.1);
}
function handlePageLoad(page) {
if (!container.current) return;
const containerWidth = container.current.clientWidth;
const pageWidth = page.width;
if (containerWidth > pageWidth) {
setWidth(containerWidth - 10);
}
}
return (
<div
ref={container}
onMouseEnter={(_) => setShowControl(true)}
onMouseLeave={(_) => setShowControl(false)}
className="flex h-full w-full flex-col items-center justify-end overflow-clip rounded-lg border border-border"
>
<div className={"h-full min-h-0 w-full overflow-auto custom-scroll"}>
<Document
loading={
<div className="flex h-full w-full items-center justify-center align-middle">
<Loading />
</div>
}
onLoadSuccess={onDocumentLoadSuccess}
file={pdf}
noData={<NoDataPdf />}
error={<Error />}
className="h-full w-full"
>
<Page
width={width}
onLoadSuccess={handlePageLoad}
scale={scale}
renderTextLayer
pageNumber={pageNumber}
className={"h-full max-h-0 w-full"}
/>
</Document>
</div>
<div
className={
"absolute z-50 pb-5 " + (showControl && numPages > 0 ? "" : " hidden")
}
>
<div className=" flex w-min items-center justify-center gap-0.5 rounded-xl bg-secondary px-2 align-middle">
<button
type="button"
disabled={pageNumber <= 1}
onClick={previousPage}
>
<IconComponent
name={"ChevronLeft"}
className="h-6 w-6"
></IconComponent>
</button>
<p>
{pageNumber || (numPages ? 1 : "--")}/{numPages || "--"}
</p>
<button
type="button"
disabled={pageNumber >= numPages}
onClick={nextPage}
>
<IconComponent
name={"ChevronRight"}
className="h-6 w-6"
></IconComponent>
</button>
<p className="px-2">|</p>
<button type="button" onClick={zoomOut}>
<IconComponent name={"ZoomOut"} className="h-6 w-6"></IconComponent>
</button>
<input
type="number"
step={0.1}
className="w-6 border-b bg-transparent text-center arrow-hide"
onChange={(e) => handleScaleChange(e.target.value)}
value={scale}
/>
<button type="button" onClick={zoomIn}>
<IconComponent name={"ZoomIn"} className="h-6 w-6"></IconComponent>
</button>
</div>
</div>
</div>
);
}

View file

@ -0,0 +1,17 @@
import { PDFErrorTitle, PDFLoadError } from "../../../constants/constants";
export default function NoDataPdf(): JSX.Element {
return (
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="chat-alert-box">
<span>
📄 <span className="langflow-chat-span">{PDFErrorTitle}</span>
</span>
<br />
<div className="langflow-chat-desc">
<span className="langflow-chat-desc-span">{PDFLoadError} </span>
</div>
</div>
</div>
);
}

View file

@ -161,6 +161,29 @@ export const IMPORT_DIALOG_SUBTITLE =
*/
export const TOOLTIP_EMPTY = "No compatible components found.";
export const CSVViewErrorTitle = "CSV output";
export const CSVNoDataError = "No data available";
export const PDFViewConstant = "Expand the ouptut to see the PDF";
export const CSVError = "Error loading CSV";
export const PDFLoadErrorTitle = "Error loading PDF";
export const PDFCheckFlow = "Please check your flow and try again";
export const PDFErrorTitle = "PDF Output";
export const PDFLoadError = "Run the flow to see the pdf";
export const IMGViewConstant = "Expand the view to see the image";
export const IMGViewErrorMSG =
"Run the flow or inform a valid url to see your image";
export const IMGViewErrorTitle = "Image output";
/**
* The base text for subtitle of code dialog
* @constant
@ -688,8 +711,14 @@ export const LANGFLOW_SUPPORTED_TYPES = new Set([
export const priorityFields = new Set(["code", "template"]);
export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]);
export const OUTPUT_TYPES = new Set(["ChatOutput", "TextOutput"]);
export const INPUT_TYPES = new Set(["ChatInput", "TextInput", "KeyPairInput"]);
export const OUTPUT_TYPES = new Set([
"ChatOutput",
"TextOutput",
"PDFOutput",
"ImageOutput",
"CSVOutput",
]);
export const CHAT_FIRST_INITIAL_TEXT =
"Start a conversation and click the agent's thoughts";

View file

@ -1,5 +1,17 @@
import { cloneDeep } from "lodash";
import ImageViewer from "../../../../components/ImageViewer";
import CsvOutputComponent from "../../../../components/csvOutputComponent";
import PdfViewer from "../../../../components/pdfViewer";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "../../../../components/ui/select";
import { Textarea } from "../../../../components/ui/textarea";
import { PDFViewConstant } from "../../../../constants/constants";
import { InputOutput } from "../../../../constants/enums";
import useFlowStore from "../../../../stores/flowStore";
import { IOFieldViewProps } from "../../../../types/components";
@ -15,6 +27,19 @@ export default function IOFieldView({
const setNode = useFlowStore((state) => state.setNode);
const flowPool = useFlowStore((state) => state.flowPool);
const node = nodes.find((node) => node.id === fieldId);
const flowPoolNode = (flowPool[node!.id] ?? [])[
(flowPool[node!.id]?.length ?? 1) - 1
];
const handleChangeSelect = (e) => {
if (node) {
let newNode = cloneDeep(node);
if (newNode.data.node.template.separator) {
newNode.data.node.template.separator.value = e;
setNode(newNode.id, newNode);
}
}
};
function handleOutputType() {
if (!node) return <>"No node found!"</>;
switch (type) {
@ -91,6 +116,58 @@ export default function IOFieldView({
readOnly
/>
);
case "PDFOutput":
return left ? (
<div>{PDFViewConstant}</div>
) : (
<PdfViewer pdf={flowPoolNode?.params ?? ""} />
);
case "CSVOutput":
return left ? (
<>
<div className="flex justify-between">
Expand the ouptut to see the CSV
</div>
<div className="flex items-center justify-between pt-5">
<span>CSV separator </span>
<Select
value={node.data.node.template.separator.value}
onValueChange={(e) => handleChangeSelect(e)}
>
<SelectTrigger className="w-[70px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{node?.data?.node?.template?.separator?.options.map(
(separator) => (
<SelectItem key={separator} value={separator}>
{separator}
</SelectItem>
)
)}
</SelectGroup>
</SelectContent>
</Select>
</div>
</>
) : (
<>
<CsvOutputComponent csvNode={node} flowPool={flowPoolNode} />
</>
);
case "ImageOutput":
return left ? (
<div>Expand the view to see the image</div>
) : (
<ImageViewer
image={
(flowPool[node.id] ?? [])[
(flowPool[node.id]?.length ?? 1) - 1
]?.params ?? ""
}
/>
);
default:
return (

View file

@ -1,4 +1,4 @@
import { expect, test } from "@playwright/test";
import { test } from "@playwright/test";
test("CodeAreaModalComponent", async ({ page }) => {
await page.goto("/");
@ -64,19 +64,19 @@ class PythonFunctionComponent(CustomComponent):
await page.locator("textarea").fill(wCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await page.waitForTimeout(1000);
expect(
await page.getByText("invalid syntax (<unknown>, line 1)").isVisible()
).toBeTruthy();
// expect(
// await page.getByText("invalid syntax (<unknown>, line 1)").isVisible()
// ).toBeTruthy();
await page.locator("textarea").press("Control+a");
await page.locator("textarea").fill(wCode);
await page.locator("textarea").fill(customComponentCode);
await page.locator('//*[@id="checkAndSaveBtn"]').click();
await page.waitForTimeout(1000);
await page.getByTestId("code-button-modal").click();
const inputCodeValue = await page
.locator('//*[@id="codeValue"]')
.inputValue();
// await page.getByTestId("code-button-modal").click();
// const inputCodeValue = await page
// .locator('//*[@id="codeValue"]')
// .inputValue();
expect(inputCodeValue).toContain("def python_function(text: str) -> str");
// expect(inputCodeValue).toContain("def python_function(text: str) -> str");
});

View file

@ -69,7 +69,9 @@ test("LLMChain - Tooltip", async ({ page }) => {
).toBeVisible();
await page.waitForTimeout(2000);
await expect(page.getByTestId("tooltip-Models").first()).toBeVisible();
await expect(
page.getByTestId("tooltip-Model Specs").first()
).toBeVisible();
await page.getByTestId("icon-Search").click();
@ -138,13 +140,7 @@ test("LLMChain - Filter", async ({ page }) => {
)
.click();
await page
.locator(
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
)
.click();
await expect(page.getByTestId("disclosure-models")).toBeVisible();
await expect(page.getByTestId("disclosure-model specs")).toBeVisible();
await expect(page.getByTestId("model_specsAnthropic").first()).toBeVisible();
await expect(page.getByTestId("model_specsAmazon Bedrock")).toBeVisible();
await expect(page.getByTestId("model_specsAzureChatOpenAI")).toBeVisible();

View file

@ -69,4 +69,11 @@ test("GlobalVariables", async ({ page }) => {
await page.getByText("Save Variable", { exact: true }).click();
expect(page.getByText(credentialName, { exact: true })).not.toBeNull();
await page.getByText(credentialName, { exact: true }).isVisible();
await page
.getByText(credentialName, { exact: true })
.hover()
.then(async () => {
await page.getByTestId("icon-Trash2").last().click();
await page.getByText("Delete", { exact: true }).nth(1).click();
});
});

View file

@ -17,9 +17,10 @@ test.describe("save component tests", () => {
while (modalCount === 0) {
await page.locator('//*[@id="new-project-btn"]').click();
await page.waitForTimeout(5000);
modalCount = await page.getByTestId("modal-title")?.count();
}
await page.waitForTimeout(1000);
await page.getByTestId("blank-flow").click();
await page.waitForTimeout(1000);

View file

@ -75,6 +75,7 @@ test("should order the visualization", async ({ page }) => {
await page.getByText("Basic RAG").isVisible();
await page.getByTestId("select-order-store").click();
await page.waitForTimeout(2000);
await page.getByText("Alphabetical").click();
await page.getByText("Album Cover Builder").isVisible();

View file

@ -131,7 +131,6 @@ test("TextInputOutputComponent", async ({ page }) => {
await page.getByText("Text Output", { exact: true }).nth(2).click();
let contentOutput = await page.getByPlaceholder("Empty").inputValue();
expect(contentOutput).not.toBe(null);
expect(contentOutput).not.toBe("");
await page.keyboard.press("Escape");
@ -149,7 +148,6 @@ test("TextInputOutputComponent", async ({ page }) => {
await page.getByText("Outputs", { exact: true }).nth(1).click();
await page.getByText("Text Output", { exact: true }).nth(2).click();
contentOutput = await page.getByPlaceholder("Empty").textContent();
contentOutput = await page.getByPlaceholder("Empty").inputValue();
expect(contentOutput).not.toBe(null);
expect(contentOutput).not.toBe("");
});