diff --git a/bun.lock b/bun.lock index dbf9901..1d75457 100644 --- a/bun.lock +++ b/bun.lock @@ -43,7 +43,8 @@ "date-fns": "^4.1.0", "drizzle-orm": "^0.41.0", "lucide-react": "^0.536.0", - "next": "^16.0.3", + "minio": "^8.0.6", + "next": "^16.0.10", "next-auth": "^5.0.0-beta.29", "postgres": "^3.4.4", "react": "^19.0.0", @@ -339,25 +340,25 @@ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], - "@next/env": ["@next/env@16.0.3", "", {}, "sha512-IqgtY5Vwsm14mm/nmQaRMmywCU+yyMIYfk3/MHZ2ZTJvwVbBn3usZnjMi1GacrMVzVcAxJShTCpZlPs26EdEjQ=="], + "@next/env": ["@next/env@16.0.10", "", {}, "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang=="], "@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.4.5", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-YhbrlbEt0m4jJnXHMY/cCUDBAWgd5SaTa5mJjzOt82QwflAFfW/h3+COp2TfVSzhmscIZ5sg2WXt3MLziqCSCw=="], - "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MOnbd92+OByu0p6QBAzq1ahVWzF6nyfiH07dQDez4/Nku7G249NjxDVyEfVhz8WkLiOEU+KFVnqtgcsfP2nLXg=="], + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg=="], - "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-i70C4O1VmbTivYdRlk+5lj9xRc2BlK3oUikt3yJeHT1unL4LsNtN7UiOhVanFdc7vDAgZn1tV/9mQwMkWOJvHg=="], + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw=="], - "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-O88gCZ95sScwD00mn/AtalyCoykhhlokxH/wi1huFK+rmiP5LAYVs/i2ruk7xST6SuXN4NI5y4Xf5vepb2jf6A=="], + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw=="], - "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-CEErFt78S/zYXzFIiv18iQCbRbLgBluS8z1TNDQoyPi8/Jr5qhR3e8XHAIxVxPBjDbEMITprqELVc5KTfFj0gg=="], + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw=="], - "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Tc3i+nwt6mQ+Dwzcri/WNDj56iWdycGVh5YwwklleClzPzz7UpfaMw1ci7bLl6GRYMXhWDBfe707EXNjKtiswQ=="], + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.10", "", { "os": "linux", "cpu": "x64" }, "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA=="], - "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-zTh03Z/5PBBPdTurgEtr6nY0vI9KR9Ifp/jZCcHlODzwVOEKcKRBtQIGrkc7izFgOMuXDEJBmirwpGqdM/ZixA=="], + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.10", "", { "os": "linux", "cpu": "x64" }, "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g=="], - "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-Jc1EHxtZovcJcg5zU43X3tuqzl/sS+CmLgjRP28ZT4vk869Ncm2NoF8qSTaL99gh6uOzgM99Shct06pSO6kA6g=="], + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg=="], - "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-N7EJ6zbxgIYpI/sWNzpVKRMbfEGgsWuOIvzkML7wxAAZhPk1Msxuo/JDu1PKjWGrAoOLaZcIX5s+/pF5LIbBBg=="], + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.10", "", { "os": "win32", "cpu": "x64" }, "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -697,6 +698,8 @@ "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], + "@zxing/text-encoding": ["@zxing/text-encoding@0.9.0", "", {}, "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA=="], + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], @@ -731,6 +734,8 @@ "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], @@ -747,14 +752,20 @@ "bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="], + "block-stream2": ["block-stream2@2.1.0", "", { "dependencies": { "readable-stream": "^3.4.0" } }, "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg=="], + "bowser": ["bowser@2.11.0", "", {}, "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="], "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "browser-or-node": ["browser-or-node@2.1.1", "", {}, "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg=="], + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + "buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], @@ -813,6 +824,8 @@ "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="], + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], @@ -895,6 +908,8 @@ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "execa": ["execa@7.2.0", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", "human-signals": "^4.3.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^3.0.7", "strip-final-newline": "^3.0.0" } }, "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -905,7 +920,7 @@ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - "fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], + "fast-xml-parser": ["fast-xml-parser@4.5.3", "", { "dependencies": { "strnum": "^1.1.1" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig=="], "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], @@ -917,6 +932,8 @@ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="], + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], @@ -989,6 +1006,10 @@ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + "ipaddr.js": ["ipaddr.js@2.3.0", "", {}, "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg=="], + + "is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="], + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], @@ -1109,6 +1130,8 @@ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], "log-symbols": ["log-symbols@5.1.0", "", { "dependencies": { "chalk": "^5.0.0", "is-unicode-supported": "^1.1.0" } }, "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA=="], @@ -1127,12 +1150,18 @@ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + "minio": ["minio@8.0.6", "", { "dependencies": { "async": "^3.2.4", "block-stream2": "^2.1.0", "browser-or-node": "^2.1.1", "buffer-crc32": "^1.0.0", "eventemitter3": "^5.0.1", "fast-xml-parser": "^4.4.1", "ipaddr.js": "^2.0.1", "lodash": "^4.17.21", "mime-types": "^2.1.35", "query-string": "^7.1.3", "stream-json": "^1.8.0", "through2": "^4.0.2", "web-encoding": "^1.1.5", "xml2js": "^0.5.0 || ^0.6.2" } }, "sha512-sOeh2/b/XprRmEtYsnNRFtOqNRTPDvYtMWh+spWlfsuCV/+IdxNeKVUMKLqI7b5Dr07ZqCPuaRGU/rB9pZYVdQ=="], + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="], @@ -1147,7 +1176,7 @@ "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - "next": ["next@16.0.3", "", { "dependencies": { "@next/env": "16.0.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.3", "@next/swc-darwin-x64": "16.0.3", "@next/swc-linux-arm64-gnu": "16.0.3", "@next/swc-linux-arm64-musl": "16.0.3", "@next/swc-linux-x64-gnu": "16.0.3", "@next/swc-linux-x64-musl": "16.0.3", "@next/swc-win32-arm64-msvc": "16.0.3", "@next/swc-win32-x64-msvc": "16.0.3", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-Ka0/iNBblPFcIubTA1Jjh6gvwqfjrGq1Y2MTI5lbjeLIAfmC+p5bQmojpRZqgHHVu5cG4+qdIiwXiBSm/8lZ3w=="], + "next": ["next@16.0.10", "", { "dependencies": { "@next/env": "16.0.10", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.10", "@next/swc-darwin-x64": "16.0.10", "@next/swc-linux-arm64-gnu": "16.0.10", "@next/swc-linux-arm64-musl": "16.0.10", "@next/swc-linux-x64-gnu": "16.0.10", "@next/swc-linux-x64-musl": "16.0.10", "@next/swc-win32-arm64-msvc": "16.0.10", "@next/swc-win32-x64-msvc": "16.0.10", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA=="], "next-auth": ["next-auth@5.0.0-beta.29", "", { "dependencies": { "@auth/core": "0.40.0" }, "peerDependencies": { "@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/server": "^9.0.2", "next": "^14.0.0-0 || ^15.0.0-0", "nodemailer": "^6.6.5", "react": "^18.2.0 || ^19.0.0-0" }, "optionalPeers": ["@simplewebauthn/browser", "@simplewebauthn/server", "nodemailer"] }, "sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A=="], @@ -1221,6 +1250,8 @@ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="], @@ -1265,6 +1296,8 @@ "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + "sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], + "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], @@ -1305,12 +1338,20 @@ "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="], + "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], "stdin-discarder": ["stdin-discarder@0.1.0", "", { "dependencies": { "bl": "^5.0.0" } }, "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ=="], "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], + "stream-chain": ["stream-chain@2.2.5", "", {}, "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA=="], + + "stream-json": ["stream-json@1.9.1", "", { "dependencies": { "stream-chain": "^2.2.5" } }, "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw=="], + + "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="], + "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="], "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], @@ -1333,7 +1374,7 @@ "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - "strnum": ["strnum@2.1.1", "", {}, "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw=="], + "strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="], "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], @@ -1351,6 +1392,8 @@ "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], + "through2": ["through2@4.0.2", "", { "dependencies": { "readable-stream": "3" } }, "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw=="], + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], @@ -1395,12 +1438,16 @@ "use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="], + "util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="], + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], + "web-encoding": ["web-encoding@1.1.5", "", { "dependencies": { "util": "^0.12.3" }, "optionalDependencies": { "@zxing/text-encoding": "0.9.0" } }, "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA=="], + "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], @@ -1417,6 +1464,10 @@ "ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], + "xml2js": ["xml2js@0.6.2", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA=="], + + "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], + "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], @@ -1431,6 +1482,8 @@ "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + "@aws-sdk/core/fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], + "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -1507,6 +1560,8 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + "@aws-sdk/core/fast-xml-parser/strnum": ["strnum@2.1.1", "", {}, "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw=="], + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], diff --git a/docker-compose.yml b/docker-compose.yml index e063a86..c57b270 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,18 +17,18 @@ services: timeout: 5s retries: 5 - # minio: - # image: minio/minio - # ports: - # - "9000:9000" # API - # - "9001:9001" # Console - # environment: - # MINIO_ROOT_USER: minioadmin - # MINIO_ROOT_PASSWORD: minioadmin - # volumes: - # - minio_data:/data - # command: server --console-address ":9001" /data + minio: + image: minio/minio + ports: + - "9000:9000" # API + - "9001:9001" # Console + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + volumes: + - minio_data:/data + command: server --console-address ":9001" /data volumes: postgres_data: - # minio_data: + minio_data: diff --git a/package.json b/package.json index 97edc06..bc01768 100755 --- a/package.json +++ b/package.json @@ -62,7 +62,8 @@ "date-fns": "^4.1.0", "drizzle-orm": "^0.41.0", "lucide-react": "^0.536.0", - "next": "^16.0.3", + "minio": "^8.0.6", + "next": "^16.0.10", "next-auth": "^5.0.0-beta.29", "postgres": "^3.4.4", "react": "^19.0.0", diff --git a/plugin_dump.json b/plugin_dump.json new file mode 100644 index 0000000..09249bb --- /dev/null +++ b/plugin_dump.json @@ -0,0 +1,927 @@ + jsonb_pretty +--------------------------------------------------------------------------------------- + [ + + { + + "id": "walk_velocity", + + "icon": "navigation", + + "name": "Walk with Velocity", + + "ros2": { + + "qos": { + + "depth": 1, + + "history": "keep_last", + + "durability": "volatile", + + "reliability": "reliable" + + }, + + "topic": "/cmd_vel", + + "messageType": "geometry_msgs/msg/Twist", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "transformToTwist" + + } + + }, + + "timeout": 5000, + + "category": "movement", + + "retryable": true, + + "description": "Control robot walking with linear and angular velocities", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "linear", + + "angular" + + ], + + "properties": { + + "linear": { + + "type": "number", + + "default": 0, + + "maximum": 0.55, + + "minimum": -0.55, + + "description": "Forward velocity in m/s" + + }, + + "angular": { + + "type": "number", + + "default": 0, + + "maximum": 2, + + "minimum": -2, + + "description": "Angular velocity in rad/s" + + } + + } + + } + + }, + + { + + "id": "walk_forward", + + "icon": "arrow-up", + + "name": "Walk Forward", + + "ros2": { + + "topic": "/cmd_vel", + + "messageType": "geometry_msgs/msg/Twist", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "linear": { + + "x": "{{speed}}", + + "y": 0, + + "z": 0 + + }, + + "angular": { + + "x": 0, + + "y": 0, + + "z": 0 + + } + + } + + } + + }, + + "timeout": 30000, + + "category": "movement", + + "retryable": true, + + "description": "Make the robot walk forward at specified speed", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "speed" + + ], + + "properties": { + + "speed": { + + "type": "number", + + "default": 0.1, + + "maximum": 0.3, + + "minimum": 0.01, + + "description": "Walking speed in m/s" + + }, + + "duration": { + + "type": "number", + + "default": 0, + + "maximum": 30, + + "minimum": 0, + + "description": "Duration to walk in seconds (0 = indefinite)" + + } + + } + + } + + }, + + { + + "id": "walk_backward", + + "icon": "arrow-down", + + "name": "Walk Backward", + + "ros2": { + + "topic": "/cmd_vel", + + "messageType": "geometry_msgs/msg/Twist", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "linear": { + + "x": "-{{speed}}", + + "y": 0, + + "z": 0 + + }, + + "angular": { + + "x": 0, + + "y": 0, + + "z": 0 + + } + + } + + } + + }, + + "timeout": 30000, + + "category": "movement", + + "retryable": true, + + "description": "Make the robot walk backward at specified speed", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "speed" + + ], + + "properties": { + + "speed": { + + "type": "number", + + "default": 0.1, + + "maximum": 0.3, + + "minimum": 0.01, + + "description": "Walking speed in m/s" + + }, + + "duration": { + + "type": "number", + + "default": 0, + + "maximum": 30, + + "minimum": 0, + + "description": "Duration to walk in seconds (0 = indefinite)" + + } + + } + + } + + }, + + { + + "id": "turn_left", + + "icon": "rotate-ccw", + + "name": "Turn Left", + + "ros2": { + + "topic": "/cmd_vel", + + "messageType": "geometry_msgs/msg/Twist", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "linear": { + + "x": 0, + + "y": 0, + + "z": 0 + + }, + + "angular": { + + "x": 0, + + "y": 0, + + "z": "{{speed}}" + + } + + } + + } + + }, + + "timeout": 30000, + + "category": "movement", + + "retryable": true, + + "description": "Make the robot turn left at specified angular speed", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "speed" + + ], + + "properties": { + + "speed": { + + "type": "number", + + "default": 0.3, + + "maximum": 1, + + "minimum": 0.1, + + "description": "Angular speed in rad/s" + + }, + + "duration": { + + "type": "number", + + "default": 0, + + "maximum": 30, + + "minimum": 0, + + "description": "Duration to turn in seconds (0 = indefinite)" + + } + + } + + } + + }, + + { + + "id": "turn_right", + + "icon": "rotate-cw", + + "name": "Turn Right", + + "ros2": { + + "topic": "/cmd_vel", + + "messageType": "geometry_msgs/msg/Twist", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "linear": { + + "x": 0, + + "y": 0, + + "z": 0 + + }, + + "angular": { + + "x": 0, + + "y": 0, + + "z": "-{{speed}}" + + } + + } + + } + + }, + + "timeout": 30000, + + "category": "movement", + + "retryable": true, + + "description": "Make the robot turn right at specified angular speed", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "speed" + + ], + + "properties": { + + "speed": { + + "type": "number", + + "default": 0.3, + + "maximum": 1, + + "minimum": 0.1, + + "description": "Angular speed in rad/s" + + }, + + "duration": { + + "type": "number", + + "default": 0, + + "maximum": 30, + + "minimum": 0, + + "description": "Duration to turn in seconds (0 = indefinite)" + + } + + } + + } + + }, + + { + + "id": "stop_walking", + + "icon": "square", + + "name": "Stop Walking", + + "ros2": { + + "qos": { + + "depth": 1, + + "history": "keep_last", + + "durability": "volatile", + + "reliability": "reliable" + + }, + + "topic": "/cmd_vel", + + "messageType": "geometry_msgs/msg/Twist", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "linear": { + + "x": 0, + + "y": 0, + + "z": 0 + + }, + + "angular": { + + "x": 0, + + "y": 0, + + "z": 0 + + } + + } + + } + + }, + + "timeout": 3000, + + "category": "movement", + + "retryable": false, + + "description": "Immediately stop robot movement", + + "parameterSchema": { + + "type": "object", + + "required": [ + + ], + + "properties": { + + } + + } + + }, + + { + + "id": "say_text", + + "icon": "volume-2", + + "name": "Say Text", + + "ros2": { + + "qos": { + + "durability": "volatile", + + "reliability": "reliable" + + }, + + "topic": "/speech", + + "messageType": "std_msgs/msg/String", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "transformToStringMessage" + + } + + }, + + "timeout": 15000, + + "category": "interaction", + + "retryable": true, + + "description": "Make the robot speak using text-to-speech", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "text" + + ], + + "properties": { + + "text": { + + "type": "string", + + "default": "Hello from NAO!", + + "description": "Text to speak" + + } + + } + + } + + }, + + { + + "id": "say_with_emotion", + + "icon": "heart", + + "name": "Say Text with Emotion", + + "ros2": { + + "topic": "/speech", + + "messageType": "std_msgs/msg/String", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "data": "\\rspd={{speed}}\\\\rst={{emotion}}\\{{text}}" + + } + + } + + }, + + "timeout": 15000, + + "category": "interaction", + + "retryable": true, + + "description": "Speak text with emotional expression using SSML-like markup",+ + "parameterSchema": { + + "type": "object", + + "required": [ + + "text" + + ], + + "properties": { + + "text": { + + "type": "string", + + "default": "Hello! I'm feeling great today!", + + "description": "Text for the robot to speak" + + }, + + "speed": { + + "type": "number", + + "default": 1, + + "maximum": 2, + + "minimum": 0.5, + + "description": "Speech speed multiplier" + + }, + + "emotion": { + + "enum": [ + + "neutral", + + "happy", + + "sad", + + "excited", + + "calm" + + ], + + "type": "string", + + "default": "neutral", + + "description": "Emotional tone for speech" + + } + + } + + } + + }, + + { + + "id": "set_volume", + + "icon": "volume-x", + + "name": "Set Volume", + + "ros2": { + + "topic": "/audio_volume", + + "messageType": "std_msgs/msg/Float32", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "data": "{{volume}}" + + } + + } + + }, + + "timeout": 5000, + + "category": "interaction", + + "retryable": true, + + "description": "Adjust the robot's audio volume level", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "volume" + + ], + + "properties": { + + "volume": { + + "type": "number", + + "default": 0.5, + + "maximum": 1, + + "minimum": 0, + + "description": "Volume level (0.0 = silent, 1.0 = maximum)" + + } + + } + + } + + }, + + { + + "id": "set_language", + + "icon": "globe", + + "name": "Set Language", + + "ros2": { + + "topic": "/set_language", + + "messageType": "std_msgs/msg/String", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "data": "{{language}}" + + } + + } + + }, + + "timeout": 5000, + + "category": "interaction", + + "retryable": true, + + "description": "Change the robot's speech language", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "language" + + ], + + "properties": { + + "language": { + + "enum": [ + + "en-US", + + "en-GB", + + "fr-FR", + + "de-DE", + + "es-ES", + + "it-IT", + + "ja-JP", + + "ko-KR", + + "zh-CN" + + ], + + "type": "string", + + "default": "en-US", + + "description": "Speech language" + + } + + } + + } + + }, + + { + + "id": "move_head", + + "icon": "eye", + + "name": "Move Head", + + "ros2": { + + "topic": "/joint_angles", + + "messageType": "naoqi_bridge_msgs/msg/JointAnglesWithSpeed", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "speed": "{{speed}}", + + "joint_names": [ + + "HeadYaw", + + "HeadPitch" + + ], + + "joint_angles": [ + + "{{yaw}}", + + "{{pitch}}" + + ] + + } + + } + + }, + + "timeout": 10000, + + "category": "movement", + + "retryable": true, + + "description": "Control head orientation (yaw and pitch)", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "yaw", + + "pitch" + + ], + + "properties": { + + "yaw": { + + "type": "number", + + "default": 0, + + "maximum": 2.09, + + "minimum": -2.09, + + "description": "Head yaw angle in radians" + + }, + + "pitch": { + + "type": "number", + + "default": 0, + + "maximum": 0.51, + + "minimum": -0.67, + + "description": "Head pitch angle in radians" + + }, + + "speed": { + + "type": "number", + + "default": 0.3, + + "maximum": 1, + + "minimum": 0.1, + + "description": "Movement speed (0.1 = slow, 1.0 = fast)" + + } + + } + + } + + }, + + { + + "id": "move_arm", + + "icon": "hand", + + "name": "Move Arm", + + "ros2": { + + "topic": "/joint_angles", + + "messageType": "naoqi_bridge_msgs/msg/JointAnglesWithSpeed", + + "payloadMapping": { + + "type": "static", + + "payload": { + + "speed": "{{speed}}", + + "joint_names": [ + + "{{arm === 'left' ? 'L' : 'R'}}ShoulderPitch", + + "{{arm === 'left' ? 'L' : 'R'}}ShoulderRoll", + + "{{arm === 'left' ? 'L' : 'R'}}ElbowYaw", + + "{{arm === 'left' ? 'L' : 'R'}}ElbowRoll" + + ], + + "joint_angles": [ + + "{{shoulder_pitch}}", + + "{{shoulder_roll}}", + + "{{elbow_yaw}}", + + "{{elbow_roll}}" + + ] + + } + + } + + }, + + "timeout": 10000, + + "category": "movement", + + "retryable": true, + + "description": "Control arm joint positions", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "arm", + + "shoulder_pitch", + + "shoulder_roll", + + "elbow_yaw", + + "elbow_roll" + + ], + + "properties": { + + "arm": { + + "enum": [ + + "left", + + "right" + + ], + + "type": "string", + + "default": "right", + + "description": "Which arm to control" + + }, + + "speed": { + + "type": "number", + + "default": 0.3, + + "maximum": 1, + + "minimum": 0.1, + + "description": "Movement speed (0.1 = slow, 1.0 = fast)" + + }, + + "elbow_yaw": { + + "type": "number", + + "default": 0, + + "maximum": 2.09, + + "minimum": -2.09, + + "description": "Elbow yaw angle in radians" + + }, + + "elbow_roll": { + + "type": "number", + + "default": -0.5, + + "maximum": -0.03, + + "minimum": -1.54, + + "description": "Elbow roll angle in radians" + + }, + + "shoulder_roll": { + + "type": "number", + + "default": 0.2, + + "maximum": 1.33, + + "minimum": -0.31, + + "description": "Shoulder roll angle in radians" + + }, + + "shoulder_pitch": { + + "type": "number", + + "default": 1.4, + + "maximum": 2.09, + + "minimum": -2.09, + + "description": "Shoulder pitch angle in radians" + + } + + } + + } + + }, + + { + + "id": "set_joint_angle", + + "icon": "settings", + + "name": "Set Joint Angle", + + "ros2": { + + "topic": "/joint_angles", + + "messageType": "naoqi_bridge_msgs/msg/JointAnglesWithSpeed", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "transformToJointAngles" + + } + + }, + + "timeout": 10000, + + "category": "movement", + + "retryable": true, + + "description": "Control individual joint angles", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "joint_name", + + "angle" + + ], + + "properties": { + + "angle": { + + "type": "number", + + "default": 0, + + "maximum": 3.14159, + + "minimum": -3.14159, + + "description": "Target angle in radians" + + }, + + "speed": { + + "type": "number", + + "default": 0.2, + + "maximum": 1, + + "minimum": 0.01, + + "description": "Movement speed (fraction of max)" + + }, + + "joint_name": { + + "enum": [ + + "HeadYaw", + + "HeadPitch", + + "LShoulderPitch", + + "LShoulderRoll", + + "LElbowYaw", + + "LElbowRoll", + + "LWristYaw", + + "RShoulderPitch", + + "RShoulderRoll", + + "RElbowYaw", + + "RElbowRoll", + + "RWristYaw", + + "LHipYawPitch", + + "LHipRoll", + + "LHipPitch", + + "LKneePitch", + + "LAnklePitch", + + "LAnkleRoll", + + "RHipRoll", + + "RHipPitch", + + "RKneePitch", + + "RAnklePitch", + + "RAnkleRoll" + + ], + + "type": "string", + + "default": "HeadYaw", + + "description": "Joint to control" + + } + + } + + } + + }, + + { + + "id": "turn_head", + + "icon": "rotate-ccw", + + "name": "Turn Head", + + "ros2": { + + "topic": "/joint_angles", + + "messageType": "naoqi_bridge_msgs/msg/JointAnglesWithSpeed", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "transformToHeadMovement" + + } + + }, + + "timeout": 8000, + + "category": "movement", + + "retryable": true, + + "description": "Control head orientation", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "yaw", + + "pitch" + + ], + + "properties": { + + "yaw": { + + "type": "number", + + "default": 0, + + "maximum": 2.0857, + + "minimum": -2.0857, + + "description": "Head yaw angle in radians (left-right)" + + }, + + "pitch": { + + "type": "number", + + "default": 0, + + "maximum": 0.5149, + + "minimum": -0.672, + + "description": "Head pitch angle in radians (up-down)" + + }, + + "speed": { + + "type": "number", + + "default": 0.3, + + "maximum": 1, + + "minimum": 0.1, + + "description": "Movement speed fraction" + + } + + } + + } + + }, + + { + + "id": "get_camera_image", + + "icon": "camera", + + "name": "Get Camera Image", + + "ros2": { + + "qos": { + + "durability": "volatile", + + "reliability": "reliable" + + }, + + "topic": "/camera/{camera}/image_raw", + + "messageType": "sensor_msgs/msg/Image", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getCameraImage" + + } + + }, + + "timeout": 5000, + + "category": "sensors", + + "retryable": true, + + "description": "Capture image from front or bottom camera", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "camera" + + ], + + "properties": { + + "camera": { + + "enum": [ + + "front", + + "bottom" + + ], + + "type": "string", + + "default": "front", + + "description": "Camera to use" + + } + + } + + } + + }, + + { + + "id": "get_joint_states", + + "icon": "activity", + + "name": "Get Joint States", + + "ros2": { + + "qos": { + + "durability": "volatile", + + "reliability": "reliable" + + }, + + "topic": "/joint_states", + + "messageType": "sensor_msgs/msg/JointState", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getJointStates" + + } + + }, + + "timeout": 3000, + + "category": "sensors", + + "retryable": true, + + "description": "Read current joint positions and velocities", + + "parameterSchema": { + + "type": "object", + + "required": [ + + ], + + "properties": { + + } + + } + + }, + + { + + "id": "get_imu_data", + + "icon": "compass", + + "name": "Get IMU Data", + + "ros2": { + + "qos": { + + "durability": "volatile", + + "reliability": "reliable" + + }, + + "topic": "/imu/torso", + + "messageType": "sensor_msgs/msg/Imu", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getImuData" + + } + + }, + + "timeout": 3000, + + "category": "sensors", + + "retryable": true, + + "description": "Read inertial measurement unit data from torso", + + "parameterSchema": { + + "type": "object", + + "required": [ + + ], + + "properties": { + + } + + } + + }, + + { + + "id": "get_bumper_status", + + "icon": "zap", + + "name": "Get Bumper Status", + + "ros2": { + + "topic": "/bumper", + + "messageType": "naoqi_bridge_msgs/msg/Bumper", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getBumperStatus" + + } + + }, + + "timeout": 3000, + + "category": "sensors", + + "retryable": true, + + "description": "Read foot bumper contact sensors", + + "parameterSchema": { + + "type": "object", + + "required": [ + + ], + + "properties": { + + } + + } + + }, + + { + + "id": "get_touch_sensors", + + "icon": "hand", + + "name": "Get Touch Sensors", + + "ros2": { + + "topic": "/{sensor_type}_touch", + + "messageType": "naoqi_bridge_msgs/msg/HandTouch", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getTouchSensors" + + } + + }, + + "timeout": 3000, + + "category": "sensors", + + "retryable": true, + + "description": "Read hand and head touch sensor states", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "sensor_type" + + ], + + "properties": { + + "sensor_type": { + + "enum": [ + + "hand", + + "head" + + ], + + "type": "string", + + "default": "hand", + + "description": "Touch sensor type to read" + + } + + } + + } + + }, + + { + + "id": "get_sonar_range", + + "icon": "radio", + + "name": "Get Sonar Range", + + "ros2": { + + "topic": "/sonar/{sensor}", + + "messageType": "sensor_msgs/msg/Range", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getSonarRange" + + } + + }, + + "timeout": 3000, + + "category": "sensors", + + "retryable": true, + + "description": "Read ultrasonic range sensor data", + + "parameterSchema": { + + "type": "object", + + "required": [ + + "sensor" + + ], + + "properties": { + + "sensor": { + + "enum": [ + + "left", + + "right", + + "both" + + ], + + "type": "string", + + "default": "both", + + "description": "Sonar sensor to read" + + } + + } + + } + + }, + + { + + "id": "get_robot_info", + + "icon": "info", + + "name": "Get Robot Info", + + "ros2": { + + "topic": "/info", + + "messageType": "naoqi_bridge_msgs/msg/RobotInfo", + + "payloadMapping": { + + "type": "transform", + + "transformFn": "getRobotInfo" + + } + + }, + + "timeout": 3000, + + "category": "sensors", + + "retryable": true, + + "description": "Read general robot information and status", + + "parameterSchema": { + + "type": "object", + + "required": [ + + ], + + "properties": { + + } + + } + + } + + ] +(1 row) + diff --git a/src/app/(dashboard)/analytics/page.tsx b/src/app/(dashboard)/analytics/page.tsx deleted file mode 100755 index b964747..0000000 --- a/src/app/(dashboard)/analytics/page.tsx +++ /dev/null @@ -1,64 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; -import { AlertCircle, ArrowRight } from "lucide-react"; -import { Button } from "~/components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "~/components/ui/card"; -import { useStudyContext } from "~/lib/study-context"; - -export default function AnalyticsRedirect() { - const router = useRouter(); - const { selectedStudyId } = useStudyContext(); - - useEffect(() => { - // If user has a selected study, redirect to study analytics - if (selectedStudyId) { - router.replace(`/studies/${selectedStudyId}/analytics`); - } - }, [selectedStudyId, router]); - - return ( -
- - -
- -
- Analytics Moved - - Analytics are now organized by study for better data insights. - -
- -
-

To view analytics, please:

-
    -
  • • Select a study from your studies list
  • -
  • • Navigate to that study's analytics page
  • -
  • • Get study-specific insights and data
  • -
-
-
- - -
-
-
-
- ); -} diff --git a/src/app/(dashboard)/experiments/[id]/edit/page.tsx b/src/app/(dashboard)/experiments/[id]/edit/page.tsx deleted file mode 100755 index 3087a0c..0000000 --- a/src/app/(dashboard)/experiments/[id]/edit/page.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ExperimentForm } from "~/components/experiments/ExperimentForm"; - -interface EditExperimentPageProps { - params: Promise<{ - id: string; - }>; -} - -export default async function EditExperimentPage({ - params, -}: EditExperimentPageProps) { - const { id } = await params; - - return ; -} diff --git a/src/app/(dashboard)/experiments/[id]/page.tsx b/src/app/(dashboard)/experiments/[id]/page.tsx deleted file mode 100755 index ce68a09..0000000 --- a/src/app/(dashboard)/experiments/[id]/page.tsx +++ /dev/null @@ -1,459 +0,0 @@ -"use client"; - -import { formatDistanceToNow } from "date-fns"; -import { Calendar, Clock, Edit, Play, Settings, Users } from "lucide-react"; -import Link from "next/link"; -import { notFound } from "next/navigation"; -import { useEffect, useState } from "react"; -import { Badge } from "~/components/ui/badge"; -import { Button } from "~/components/ui/button"; -import { - EntityView, - EntityViewHeader, - EntityViewSection, - EmptyState, - InfoGrid, - QuickActions, - StatsGrid, -} from "~/components/ui/entity-view"; -import { useBreadcrumbsEffect } from "~/components/ui/breadcrumb-provider"; -import { api } from "~/trpc/react"; -import { useSession } from "next-auth/react"; - -interface ExperimentDetailPageProps { - params: Promise<{ id: string }>; -} - -const statusConfig = { - draft: { - label: "Draft", - variant: "secondary" as const, - icon: "FileText" as const, - }, - testing: { - label: "Testing", - variant: "outline" as const, - icon: "TestTube" as const, - }, - ready: { - label: "Ready", - variant: "default" as const, - icon: "CheckCircle" as const, - }, - deprecated: { - label: "Deprecated", - variant: "destructive" as const, - icon: "AlertTriangle" as const, - }, -}; - -type Experiment = { - id: string; - name: string; - description: string | null; - status: string; - createdAt: Date; - updatedAt: Date; - study: { id: string; name: string }; - robot: { id: string; name: string; description: string | null } | null; - protocol?: { blocks: unknown[] } | null; - visualDesign?: unknown; - studyId: string; - createdBy: string; - robotId: string | null; - version: number; -}; - -type Trial = { - id: string; - status: string; - createdAt: Date; - duration: number | null; - participant: { - id: string; - participantCode: string; - name?: string | null; - } | null; - experiment: { name: string } | null; - participantId: string | null; - experimentId: string; - startedAt: Date | null; - completedAt: Date | null; - notes: string | null; - updatedAt: Date; - canAccess: boolean; - userRole: string; -}; - -export default function ExperimentDetailPage({ - params, -}: ExperimentDetailPageProps) { - const { data: session } = useSession(); - const [experiment, setExperiment] = useState(null); - const [trials, setTrials] = useState([]); - const [loading, setLoading] = useState(true); - const [resolvedParams, setResolvedParams] = useState<{ id: string } | null>( - null, - ); - - useEffect(() => { - const resolveParams = async () => { - const resolved = await params; - setResolvedParams(resolved); - }; - void resolveParams(); - }, [params]); - - const experimentQuery = api.experiments.get.useQuery( - { id: resolvedParams?.id ?? "" }, - { enabled: !!resolvedParams?.id }, - ); - - const trialsQuery = api.trials.list.useQuery( - { experimentId: resolvedParams?.id ?? "" }, - { enabled: !!resolvedParams?.id }, - ); - - useEffect(() => { - if (experimentQuery.data) { - setExperiment(experimentQuery.data); - } - }, [experimentQuery.data]); - - useEffect(() => { - if (trialsQuery.data) { - setTrials(trialsQuery.data); - } - }, [trialsQuery.data]); - - useEffect(() => { - if (experimentQuery.isLoading || trialsQuery.isLoading) { - setLoading(true); - } else { - setLoading(false); - } - }, [experimentQuery.isLoading, trialsQuery.isLoading]); - - // Set breadcrumbs - useBreadcrumbsEffect([ - { - label: "Dashboard", - href: "/", - }, - { - label: "Studies", - href: "/studies", - }, - { - label: experiment?.study?.name ?? "Unknown Study", - href: `/studies/${experiment?.study?.id}`, - }, - { - label: "Experiments", - href: `/studies/${experiment?.study?.id}/experiments`, - }, - { - label: experiment?.name ?? "Experiment", - }, - ]); - - if (loading) return
Loading...
; - if (experimentQuery.error) return notFound(); - if (!experiment) return notFound(); - - const displayName = experiment.name ?? "Untitled Experiment"; - const description = experiment.description; - - // Check if user can edit this experiment - const userRoles = session?.user?.roles?.map((r) => r.role) ?? []; - const canEdit = - userRoles.includes("administrator") || userRoles.includes("researcher"); - - const statusInfo = - statusConfig[experiment.status as keyof typeof statusConfig]; - - return ( - - - - - - - ) : undefined - } - /> - -
-
- {/* Basic Information */} - - - {experiment.study.name} - - ) : ( - "No study assigned" - ), - }, - { - label: "Status", - value: statusInfo?.label ?? "Unknown", - }, - { - label: "Created", - value: formatDistanceToNow(experiment.createdAt, { - addSuffix: true, - }), - }, - { - label: "Last Updated", - value: formatDistanceToNow(experiment.updatedAt, { - addSuffix: true, - }), - }, - ]} - /> - - - {/* Protocol Section */} - - - - Edit Protocol - - - ) - } - > - {experiment.protocol && - typeof experiment.protocol === "object" && - experiment.protocol !== null ? ( -
-
- Protocol contains{" "} - {Array.isArray( - (experiment.protocol as { blocks: unknown[] }).blocks, - ) - ? (experiment.protocol as { blocks: unknown[] }).blocks - .length - : 0}{" "} - blocks -
-
- ) : ( - - - Open Designer - - - ) - } - /> - )} -
- - {/* Recent Trials */} - - - View All - - - } - > - {trials.length > 0 ? ( -
- {trials.slice(0, 5).map((trial) => ( -
-
- - Trial #{trial.id.slice(-6)} - - - {trial.status.charAt(0).toUpperCase() + - trial.status.slice(1).replace("_", " ")} - -
-
- - - {formatDistanceToNow(trial.createdAt, { - addSuffix: true, - })} - - {trial.duration && ( - - - {Math.round(trial.duration / 60)} min - - )} - {trial.participant && ( - - - {trial.participant.name ?? - trial.participant.participantCode} - - )} -
-
- ))} -
- ) : ( - - - Start Trial - - - ) - } - /> - )} -
-
- -
- {/* Statistics */} - - t.status === "completed").length, - }, - { - label: "In Progress", - value: trials.filter((t) => t.status === "in_progress") - .length, - }, - ]} - /> - - - {/* Robot Information */} - {experiment.robot && ( - - - - )} - - {/* Quick Actions */} - - - -
-
-
- ); -} diff --git a/src/app/(dashboard)/experiments/page.tsx b/src/app/(dashboard)/experiments/page.tsx deleted file mode 100755 index 1427e40..0000000 --- a/src/app/(dashboard)/experiments/page.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; -import { FlaskConical, ArrowRight } from "lucide-react"; -import { Button } from "~/components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "~/components/ui/card"; -import { useStudyContext } from "~/lib/study-context"; - -export default function ExperimentsRedirect() { - const router = useRouter(); - const { selectedStudyId } = useStudyContext(); - - useEffect(() => { - // If user has a selected study, redirect to study experiments - if (selectedStudyId) { - router.replace(`/studies/${selectedStudyId}/experiments`); - } - }, [selectedStudyId, router]); - - return ( -
- - -
- -
- Experiments Moved - - Experiment management is now organized by study for better - workflow organization. - -
- -
-

To manage experiments:

-
    -
  • • Select a study from your studies list
  • -
  • • Navigate to that study's experiments page
  • -
  • • Create and manage experiment protocols for that specific study
  • -
-
-
- - -
-
-
-
- ); -} diff --git a/src/app/(dashboard)/participants/page.tsx b/src/app/(dashboard)/participants/page.tsx deleted file mode 100755 index 3e081b9..0000000 --- a/src/app/(dashboard)/participants/page.tsx +++ /dev/null @@ -1,65 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; -import { Users, ArrowRight } from "lucide-react"; -import { Button } from "~/components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "~/components/ui/card"; -import { useStudyContext } from "~/lib/study-context"; - -export default function ParticipantsRedirect() { - const router = useRouter(); - const { selectedStudyId } = useStudyContext(); - - useEffect(() => { - // If user has a selected study, redirect to study participants - if (selectedStudyId) { - router.replace(`/studies/${selectedStudyId}/participants`); - } - }, [selectedStudyId, router]); - - return ( -
- - -
- -
- Participants Moved - - Participant management is now organized by study for better - organization. - -
- -
-

To manage participants:

-
    -
  • • Select a study from your studies list
  • -
  • • Navigate to that study's participants page
  • -
  • • Add and manage participants for that specific study
  • -
-
-
- - -
-
-
-
- ); -} diff --git a/src/app/(dashboard)/plugins/browse/page.tsx b/src/app/(dashboard)/plugins/browse/page.tsx deleted file mode 100755 index ac75859..0000000 --- a/src/app/(dashboard)/plugins/browse/page.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; -import { ArrowRight, Store } from "lucide-react"; -import { Button } from "~/components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "~/components/ui/card"; -import { useStudyContext } from "~/lib/study-context"; - -export default function PluginBrowseRedirect() { - const router = useRouter(); - const { selectedStudyId } = useStudyContext(); - - useEffect(() => { - // If user has a selected study, redirect to study plugin browse - if (selectedStudyId) { - router.replace(`/studies/${selectedStudyId}/plugins/browse`); - } - }, [selectedStudyId, router]); - - return ( -
- - -
- -
- Plugin Store Moved - - Plugin browsing is now organized by study for better robot - capability management. - -
- -
-

To browse and install plugins:

-
    -
  • • Select a study from your studies list
  • -
  • • Navigate to that study's plugin store
  • -
  • - • Browse and install robot capabilities for that specific study -
  • -
-
-
- - -
-
-
-
- ); -} diff --git a/src/app/(dashboard)/plugins/page.tsx b/src/app/(dashboard)/plugins/page.tsx deleted file mode 100755 index 43cc54b..0000000 --- a/src/app/(dashboard)/plugins/page.tsx +++ /dev/null @@ -1,68 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; -import { Puzzle, ArrowRight } from "lucide-react"; -import { Button } from "~/components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "~/components/ui/card"; -import { useStudyContext } from "~/lib/study-context"; - -export default function PluginsRedirect() { - const router = useRouter(); - const { selectedStudyId } = useStudyContext(); - - useEffect(() => { - // If user has a selected study, redirect to study plugins - if (selectedStudyId) { - router.replace(`/studies/${selectedStudyId}/plugins`); - } - }, [selectedStudyId, router]); - - return ( -
- - -
- -
- Plugins Moved - - Plugin management is now organized by study for better robot - capability management. - -
- -
-

To manage plugins:

-
    -
  • • Select a study from your studies list
  • -
  • • Navigate to that study's plugins page
  • -
  • - • Install and configure robot capabilities for that specific - study -
  • -
-
-
- - -
-
-
-
- ); -} diff --git a/src/app/(dashboard)/studies/[id]/experiments/[experimentId]/edit/experiment-form.tsx b/src/app/(dashboard)/studies/[id]/experiments/[experimentId]/edit/experiment-form.tsx new file mode 100644 index 0000000..e242051 --- /dev/null +++ b/src/app/(dashboard)/studies/[id]/experiments/[experimentId]/edit/experiment-form.tsx @@ -0,0 +1,170 @@ +"use client"; + +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import { Button } from "~/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "~/components/ui/form"; +import { Input } from "~/components/ui/input"; +import { Textarea } from "~/components/ui/textarea"; + +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "~/components/ui/select"; +import { toast } from "sonner"; +import { api } from "~/trpc/react"; +import { useRouter } from "next/navigation"; +import { type Experiment } from "~/lib/experiments/types"; + +const formSchema = z.object({ + name: z.string().min(2, { + message: "Name must be at least 2 characters.", + }), + description: z.string().optional(), + status: z.enum([ + "draft", + "ready", + "data_collection", + "analysis", + "completed", + "archived", + ]), +}); + +interface ExperimentFormProps { + experiment: Experiment; +} + +export function ExperimentForm({ experiment }: ExperimentFormProps) { + const router = useRouter(); + const updateExperiment = api.experiments.update.useMutation({ + onSuccess: () => { + toast.success("Experiment updated successfully"); + router.refresh(); + router.push(`/studies/${experiment.studyId}/experiments/${experiment.id}`); + }, + onError: (error) => { + toast.error(`Error updating experiment: ${error.message}`); + }, + }); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + name: experiment.name, + description: experiment.description ?? "", + status: experiment.status, + }, + }); + + function onSubmit(values: z.infer) { + updateExperiment.mutate({ + id: experiment.id, + name: values.name, + description: values.description, + status: values.status, + }); + } + + return ( +
+ + ( + + Name + + + + + The name of your experiment. + + + + )} + /> + + ( + + Description + +