Compare commits
7 Commits
c607f672c9
...
c14b43f9ab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c14b43f9ab | ||
|
|
6fb9ba126f | ||
|
|
509d11443d | ||
|
|
04fe00412a | ||
|
|
71315eb719 | ||
|
|
436eb16c32 | ||
|
|
a94271c790 |
@@ -1 +1,2 @@
|
||||
heroku/nodejs
|
||||
https://github.com/heroku/heroku-buildpack-python#archive/v210
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -164,4 +164,7 @@ cython_debug/
|
||||
**/*.sql
|
||||
|
||||
# Exclude experimental juypter notebooks
|
||||
**/*.ipynb
|
||||
**/*.ipynb
|
||||
|
||||
# Exclude node_modules
|
||||
node_modules
|
||||
748
bun.lock
Normal file
748
bun.lock
Normal file
@@ -0,0 +1,748 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "workout-tracker",
|
||||
"devDependencies": {
|
||||
"@mermaid-js/mermaid-cli": "^11.12.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||
|
||||
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||
|
||||
"@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="],
|
||||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
|
||||
|
||||
"@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.1", "", {}, "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw=="],
|
||||
|
||||
"@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@11.0.3", "", { "dependencies": { "@chevrotain/gast": "11.0.3", "@chevrotain/types": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ=="],
|
||||
|
||||
"@chevrotain/gast": ["@chevrotain/gast@11.0.3", "", { "dependencies": { "@chevrotain/types": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q=="],
|
||||
|
||||
"@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.0.3", "", {}, "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA=="],
|
||||
|
||||
"@chevrotain/types": ["@chevrotain/types@11.0.3", "", {}, "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ=="],
|
||||
|
||||
"@chevrotain/utils": ["@chevrotain/utils@11.0.3", "", {}, "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ=="],
|
||||
|
||||
"@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="],
|
||||
|
||||
"@floating-ui/dom": ["@floating-ui/dom@1.7.5", "", { "dependencies": { "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg=="],
|
||||
|
||||
"@floating-ui/react": ["@floating-ui/react@0.27.17", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.7", "@floating-ui/utils": "^0.2.10", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=17.0.0", "react-dom": ">=17.0.0" } }, "sha512-LGVZKHwmWGg6MRHjLLgsfyaX2y2aCNgnD1zT/E6B+/h+vxg+nIJUqHPAlTzsHDyqdgEpJ1Np5kxWuFEErXzoGg=="],
|
||||
|
||||
"@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.7", "", { "dependencies": { "@floating-ui/dom": "^1.7.5" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg=="],
|
||||
|
||||
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
|
||||
|
||||
"@headlessui/react": ["@headlessui/react@2.2.9", "", { "dependencies": { "@floating-ui/react": "^0.26.16", "@react-aria/focus": "^3.20.2", "@react-aria/interactions": "^3.25.0", "@tanstack/react-virtual": "^3.13.9", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ=="],
|
||||
|
||||
"@headlessui/tailwindcss": ["@headlessui/tailwindcss@0.2.2", "", { "peerDependencies": { "tailwindcss": "^3.0 || ^4.0" } }, "sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw=="],
|
||||
|
||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||
|
||||
"@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||
|
||||
"@mermaid-js/mermaid-cli": ["@mermaid-js/mermaid-cli@11.12.0", "", { "dependencies": { "@mermaid-js/mermaid-zenuml": "^0.2.0", "chalk": "^5.0.1", "commander": "^14.0.0", "import-meta-resolve": "^4.1.0", "mermaid": "^11.0.2" }, "peerDependencies": { "puppeteer": "^23" }, "bin": { "mmdc": "src/cli.js" } }, "sha512-a0swOS6PByXKi0dZnLQQIhbtUEu7ubc6bojmIqXqvUPq7mIJukCNEvVBTv6IAbuEWqB3Ti8QntupoGdz3ej+kg=="],
|
||||
|
||||
"@mermaid-js/mermaid-zenuml": ["@mermaid-js/mermaid-zenuml@0.2.2", "", { "dependencies": { "@zenuml/core": "^3.35.2" }, "peerDependencies": { "mermaid": "^10 || ^11" } }, "sha512-sUjwk4NWUpy9uaHypYSIGJDks10ZaZo5CHH9lx9xcmyqv9w7yvd4vecUmlUQxmlHStYO+aqSkYKX5/gFjDfypw=="],
|
||||
|
||||
"@mermaid-js/parser": ["@mermaid-js/parser@0.6.3", "", { "dependencies": { "langium": "3.3.1" } }, "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA=="],
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
||||
|
||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
|
||||
"@puppeteer/browsers": ["@puppeteer/browsers@2.6.1", "", { "dependencies": { "debug": "^4.4.0", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg=="],
|
||||
|
||||
"@react-aria/focus": ["@react-aria/focus@3.21.3", "", { "dependencies": { "@react-aria/interactions": "^3.26.0", "@react-aria/utils": "^3.32.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw=="],
|
||||
|
||||
"@react-aria/interactions": ["@react-aria/interactions@3.26.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-aria/utils": "^3.32.0", "@react-stately/flags": "^3.1.2", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q=="],
|
||||
|
||||
"@react-aria/ssr": ["@react-aria/ssr@3.9.10", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ=="],
|
||||
|
||||
"@react-aria/utils": ["@react-aria/utils@3.32.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg=="],
|
||||
|
||||
"@react-stately/flags": ["@react-stately/flags@3.1.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg=="],
|
||||
|
||||
"@react-stately/utils": ["@react-stately/utils@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw=="],
|
||||
|
||||
"@react-types/shared": ["@react-types/shared@3.32.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w=="],
|
||||
|
||||
"@swc/helpers": ["@swc/helpers@0.5.18", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ=="],
|
||||
|
||||
"@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.18", "", { "dependencies": { "@tanstack/virtual-core": "3.13.18" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-dZkhyfahpvlaV0rIKnvQiVoWPyURppl6w4m9IwMDpuIjcJ1sD9YGWrt0wISvgU7ewACXx2Ct46WPgI6qAD4v6A=="],
|
||||
|
||||
"@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.18", "", {}, "sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg=="],
|
||||
|
||||
"@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
|
||||
|
||||
"@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="],
|
||||
|
||||
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
|
||||
|
||||
"@types/d3-axis": ["@types/d3-axis@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="],
|
||||
|
||||
"@types/d3-brush": ["@types/d3-brush@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="],
|
||||
|
||||
"@types/d3-chord": ["@types/d3-chord@3.0.6", "", {}, "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="],
|
||||
|
||||
"@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
|
||||
|
||||
"@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="],
|
||||
|
||||
"@types/d3-delaunay": ["@types/d3-delaunay@6.0.4", "", {}, "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="],
|
||||
|
||||
"@types/d3-dispatch": ["@types/d3-dispatch@3.0.7", "", {}, "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="],
|
||||
|
||||
"@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="],
|
||||
|
||||
"@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="],
|
||||
|
||||
"@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="],
|
||||
|
||||
"@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="],
|
||||
|
||||
"@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="],
|
||||
|
||||
"@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="],
|
||||
|
||||
"@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="],
|
||||
|
||||
"@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="],
|
||||
|
||||
"@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
|
||||
|
||||
"@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
|
||||
|
||||
"@types/d3-polygon": ["@types/d3-polygon@3.0.2", "", {}, "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="],
|
||||
|
||||
"@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="],
|
||||
|
||||
"@types/d3-random": ["@types/d3-random@3.0.3", "", {}, "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="],
|
||||
|
||||
"@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
|
||||
|
||||
"@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="],
|
||||
|
||||
"@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="],
|
||||
|
||||
"@types/d3-shape": ["@types/d3-shape@3.1.8", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="],
|
||||
|
||||
"@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
|
||||
|
||||
"@types/d3-time-format": ["@types/d3-time-format@4.0.3", "", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="],
|
||||
|
||||
"@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
|
||||
|
||||
"@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="],
|
||||
|
||||
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
|
||||
|
||||
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
|
||||
|
||||
"@types/node": ["@types/node@25.1.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA=="],
|
||||
|
||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||
|
||||
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
|
||||
|
||||
"@zenuml/core": ["@zenuml/core@3.45.4", "", { "dependencies": { "@floating-ui/react": "^0.27.16", "@headlessui/react": "^2.2.9", "@headlessui/tailwindcss": "^0.2.2", "antlr4": "~4.11.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "color-string": "^2.1.4", "dompurify": "^3.3.1", "highlight.js": "^10.7.3", "html-to-image": "^1.11.13", "immer": "^10.2.0", "jotai": "^2.16.1", "lodash": "^4.17.21", "marked": "^4.3.0", "pako": "^2.1.0", "pino": "^8.21.0", "radash": "^12.1.1", "ramda": "^0.28.0", "react": "^19.2.3", "react-dom": "^19.2.3", "tailwind-merge": "^3.4.0", "tailwindcss": "^3.4.19" } }, "sha512-y2s6F0urvcnzB/Rx5oPVLUn9zlq+cnwTMXAlEH46tdItQtqU8fTRYqrGGOuJVIKZcbZwgtpFzpSzzcC0YtjLqQ=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
|
||||
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"antlr4": ["antlr4@4.11.0", "", {}, "sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w=="],
|
||||
|
||||
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
|
||||
|
||||
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
|
||||
|
||||
"arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"ast-types": ["ast-types@0.13.4", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w=="],
|
||||
|
||||
"atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="],
|
||||
|
||||
"b4a": ["b4a@1.7.3", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q=="],
|
||||
|
||||
"bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="],
|
||||
|
||||
"bare-fs": ["bare-fs@4.5.3", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-9+kwVx8QYvt3hPWnmb19tPnh38c6Nihz8Lx3t0g9+4GoIf3/fTgYwM4Z6NxgI+B9elLQA7mLE9PpqcWtOMRDiQ=="],
|
||||
|
||||
"bare-os": ["bare-os@3.6.2", "", {}, "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A=="],
|
||||
|
||||
"bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="],
|
||||
|
||||
"bare-stream": ["bare-stream@2.7.0", "", { "dependencies": { "streamx": "^2.21.0" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A=="],
|
||||
|
||||
"bare-url": ["bare-url@2.3.2", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw=="],
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"basic-ftp": ["basic-ftp@5.1.0", "", {}, "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw=="],
|
||||
|
||||
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
||||
|
||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||
|
||||
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
||||
|
||||
"buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
|
||||
|
||||
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
|
||||
|
||||
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
|
||||
|
||||
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||
|
||||
"chevrotain": ["chevrotain@11.0.3", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.0.3", "@chevrotain/gast": "11.0.3", "@chevrotain/regexp-to-ast": "11.0.3", "@chevrotain/types": "11.0.3", "@chevrotain/utils": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw=="],
|
||||
|
||||
"chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="],
|
||||
|
||||
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
||||
|
||||
"chromium-bidi": ["chromium-bidi@0.11.0", "", { "dependencies": { "mitt": "3.0.1", "zod": "3.23.8" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA=="],
|
||||
|
||||
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
|
||||
|
||||
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
|
||||
|
||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="],
|
||||
|
||||
"color-string": ["color-string@2.1.4", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg=="],
|
||||
|
||||
"commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="],
|
||||
|
||||
"confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
||||
|
||||
"cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="],
|
||||
|
||||
"cosmiconfig": ["cosmiconfig@9.0.0", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg=="],
|
||||
|
||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||
|
||||
"cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="],
|
||||
|
||||
"cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],
|
||||
|
||||
"cytoscape-fcose": ["cytoscape-fcose@2.2.0", "", { "dependencies": { "cose-base": "^2.2.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ=="],
|
||||
|
||||
"d3": ["d3@7.9.0", "", { "dependencies": { "d3-array": "3", "d3-axis": "3", "d3-brush": "3", "d3-chord": "3", "d3-color": "3", "d3-contour": "4", "d3-delaunay": "6", "d3-dispatch": "3", "d3-drag": "3", "d3-dsv": "3", "d3-ease": "3", "d3-fetch": "3", "d3-force": "3", "d3-format": "3", "d3-geo": "3", "d3-hierarchy": "3", "d3-interpolate": "3", "d3-path": "3", "d3-polygon": "3", "d3-quadtree": "3", "d3-random": "3", "d3-scale": "4", "d3-scale-chromatic": "3", "d3-selection": "3", "d3-shape": "3", "d3-time": "3", "d3-time-format": "4", "d3-timer": "3", "d3-transition": "3", "d3-zoom": "3" } }, "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA=="],
|
||||
|
||||
"d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
|
||||
|
||||
"d3-axis": ["d3-axis@3.0.0", "", {}, "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="],
|
||||
|
||||
"d3-brush": ["d3-brush@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "3", "d3-transition": "3" } }, "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ=="],
|
||||
|
||||
"d3-chord": ["d3-chord@3.0.1", "", { "dependencies": { "d3-path": "1 - 3" } }, "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="],
|
||||
|
||||
"d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
|
||||
|
||||
"d3-contour": ["d3-contour@4.0.2", "", { "dependencies": { "d3-array": "^3.2.0" } }, "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="],
|
||||
|
||||
"d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="],
|
||||
|
||||
"d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="],
|
||||
|
||||
"d3-drag": ["d3-drag@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" } }, "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="],
|
||||
|
||||
"d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="],
|
||||
|
||||
"d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
|
||||
|
||||
"d3-fetch": ["d3-fetch@3.0.1", "", { "dependencies": { "d3-dsv": "1 - 3" } }, "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="],
|
||||
|
||||
"d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="],
|
||||
|
||||
"d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="],
|
||||
|
||||
"d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="],
|
||||
|
||||
"d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="],
|
||||
|
||||
"d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
|
||||
|
||||
"d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
|
||||
|
||||
"d3-polygon": ["d3-polygon@3.0.1", "", {}, "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="],
|
||||
|
||||
"d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="],
|
||||
|
||||
"d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="],
|
||||
|
||||
"d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="],
|
||||
|
||||
"d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
|
||||
|
||||
"d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="],
|
||||
|
||||
"d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="],
|
||||
|
||||
"d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
|
||||
|
||||
"d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
|
||||
|
||||
"d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
|
||||
|
||||
"d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
|
||||
|
||||
"d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="],
|
||||
|
||||
"d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="],
|
||||
|
||||
"dagre-d3-es": ["dagre-d3-es@7.0.13", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q=="],
|
||||
|
||||
"data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="],
|
||||
|
||||
"dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"degenerator": ["degenerator@5.0.1", "", { "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", "esprima": "^4.0.1" } }, "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ=="],
|
||||
|
||||
"delaunator": ["delaunator@5.0.1", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw=="],
|
||||
|
||||
"devtools-protocol": ["devtools-protocol@0.0.1367902", "", {}, "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg=="],
|
||||
|
||||
"didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
|
||||
|
||||
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
|
||||
|
||||
"dompurify": ["dompurify@3.3.1", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
||||
|
||||
"env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
|
||||
|
||||
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="],
|
||||
|
||||
"esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
|
||||
|
||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||
|
||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||
|
||||
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
||||
|
||||
"events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="],
|
||||
|
||||
"extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="],
|
||||
|
||||
"fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="],
|
||||
|
||||
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||
|
||||
"fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="],
|
||||
|
||||
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||
|
||||
"fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
|
||||
|
||||
"get-uri": ["get-uri@6.0.5", "", { "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4" } }, "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg=="],
|
||||
|
||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||
|
||||
"hachure-fill": ["hachure-fill@0.5.2", "", {}, "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="],
|
||||
|
||||
"html-to-image": ["html-to-image@1.11.13", "", {}, "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg=="],
|
||||
|
||||
"http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
|
||||
|
||||
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"immer": ["immer@10.2.0", "", {}, "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw=="],
|
||||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="],
|
||||
|
||||
"internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="],
|
||||
|
||||
"ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||
|
||||
"is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
|
||||
|
||||
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="],
|
||||
|
||||
"jotai": ["jotai@2.17.0", "", { "peerDependencies": { "@babel/core": ">=7.0.0", "@babel/template": ">=7.0.0", "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@babel/core", "@babel/template", "@types/react", "react"] }, "sha512-DBPT7Vx7E7R/ZJL7Uq7yUA9+LLR0IRiRM+Bw5ugVwv8L8++RjlXVXZ2//ccucypc5lcyuHOW09rYcW77RurduQ=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||
|
||||
"katex": ["katex@0.16.28", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg=="],
|
||||
|
||||
"khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="],
|
||||
|
||||
"langium": ["langium@3.3.1", "", { "dependencies": { "chevrotain": "~11.0.3", "chevrotain-allstar": "~0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.0.8" } }, "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w=="],
|
||||
|
||||
"layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
|
||||
|
||||
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
||||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
|
||||
|
||||
"lodash-es": ["lodash-es@4.17.23", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="],
|
||||
|
||||
"lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
|
||||
|
||||
"marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
|
||||
|
||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||
|
||||
"mermaid": ["mermaid@11.12.2", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", "@mermaid-js/parser": "^0.6.3", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.13", "dayjs": "^1.11.18", "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", "lodash-es": "^4.17.21", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w=="],
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
|
||||
|
||||
"mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"netmask": ["netmask@2.0.2", "", {}, "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="],
|
||||
|
||||
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="],
|
||||
|
||||
"on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"pac-proxy-agent": ["pac-proxy-agent@7.2.0", "", { "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.5" } }, "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA=="],
|
||||
|
||||
"pac-resolver": ["pac-resolver@7.0.1", "", { "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" } }, "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg=="],
|
||||
|
||||
"package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="],
|
||||
|
||||
"pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="],
|
||||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
||||
|
||||
"path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="],
|
||||
|
||||
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
|
||||
|
||||
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
|
||||
|
||||
"pino": ["pino@8.21.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^1.2.0", "pino-std-serializers": "^6.0.0", "process-warning": "^3.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^3.7.0", "thread-stream": "^2.6.0" }, "bin": { "pino": "bin.js" } }, "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q=="],
|
||||
|
||||
"pino-abstract-transport": ["pino-abstract-transport@1.2.0", "", { "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q=="],
|
||||
|
||||
"pino-std-serializers": ["pino-std-serializers@6.2.2", "", {}, "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="],
|
||||
|
||||
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
|
||||
|
||||
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||
|
||||
"points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
||||
|
||||
"points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="],
|
||||
|
||||
"postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="],
|
||||
|
||||
"postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="],
|
||||
|
||||
"postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
|
||||
|
||||
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
|
||||
|
||||
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
|
||||
|
||||
"process-warning": ["process-warning@3.0.0", "", {}, "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="],
|
||||
|
||||
"progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
|
||||
|
||||
"proxy-agent": ["proxy-agent@6.5.0", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "http-proxy-agent": "^7.0.1", "https-proxy-agent": "^7.0.6", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.1.0", "proxy-from-env": "^1.1.0", "socks-proxy-agent": "^8.0.5" } }, "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
|
||||
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
|
||||
|
||||
"puppeteer": ["puppeteer@23.11.1", "", { "dependencies": { "@puppeteer/browsers": "2.6.1", "chromium-bidi": "0.11.0", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1367902", "puppeteer-core": "23.11.1", "typed-query-selector": "^2.12.0" }, "bin": { "puppeteer": "lib/cjs/puppeteer/node/cli.js" } }, "sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw=="],
|
||||
|
||||
"puppeteer-core": ["puppeteer-core@23.11.1", "", { "dependencies": { "@puppeteer/browsers": "2.6.1", "chromium-bidi": "0.11.0", "debug": "^4.4.0", "devtools-protocol": "0.0.1367902", "typed-query-selector": "^2.12.0", "ws": "^8.18.0" } }, "sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
"quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="],
|
||||
|
||||
"radash": ["radash@12.1.1", "", {}, "sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA=="],
|
||||
|
||||
"ramda": ["ramda@0.28.0", "", {}, "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA=="],
|
||||
|
||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
||||
|
||||
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
|
||||
|
||||
"readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
|
||||
|
||||
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
||||
|
||||
"real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
|
||||
|
||||
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
||||
|
||||
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
|
||||
|
||||
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||
|
||||
"robust-predicates": ["robust-predicates@3.0.2", "", {}, "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="],
|
||||
|
||||
"roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
"rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
||||
|
||||
"socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
|
||||
|
||||
"socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"sonic-boom": ["sonic-boom@3.8.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg=="],
|
||||
|
||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||
|
||||
"streamx": ["streamx@2.23.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="],
|
||||
|
||||
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="],
|
||||
|
||||
"sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
|
||||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
|
||||
|
||||
"tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="],
|
||||
|
||||
"tar-fs": ["tar-fs@3.1.1", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg=="],
|
||||
|
||||
"tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="],
|
||||
|
||||
"text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="],
|
||||
|
||||
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
|
||||
|
||||
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
|
||||
|
||||
"thread-stream": ["thread-stream@2.7.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw=="],
|
||||
|
||||
"through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="],
|
||||
|
||||
"tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||
|
||||
"ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="],
|
||||
|
||||
"ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"typed-query-selector": ["typed-query-selector@2.12.0", "", {}, "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg=="],
|
||||
|
||||
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
|
||||
|
||||
"unbzip2-stream": ["unbzip2-stream@1.4.3", "", { "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" } }, "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
|
||||
|
||||
"vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
|
||||
|
||||
"vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="],
|
||||
|
||||
"vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="],
|
||||
|
||||
"vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="],
|
||||
|
||||
"vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="],
|
||||
|
||||
"vscode-uri": ["vscode-uri@3.0.8", "", {}, "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
|
||||
|
||||
"yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
|
||||
|
||||
"zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||
|
||||
"@chevrotain/cst-dts-gen/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
||||
|
||||
"@chevrotain/gast/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
||||
|
||||
"@headlessui/react/@floating-ui/react": ["@floating-ui/react@0.26.28", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw=="],
|
||||
|
||||
"@zenuml/core/marked": ["marked@4.3.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A=="],
|
||||
|
||||
"chevrotain/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
||||
|
||||
"chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
|
||||
|
||||
"d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
||||
|
||||
"d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="],
|
||||
|
||||
"d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="],
|
||||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
|
||||
|
||||
"readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
||||
|
||||
"sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
||||
|
||||
"tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="],
|
||||
|
||||
"d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="],
|
||||
}
|
||||
}
|
||||
2
db.py
2
db.py
@@ -10,6 +10,7 @@ from features.people_graphs import PeopleGraphs
|
||||
from features.person_overview import PersonOverview
|
||||
from features.stats import Stats
|
||||
from features.dashboard import Dashboard
|
||||
from features.schema import Schema
|
||||
from utils import get_exercise_graph_model
|
||||
|
||||
|
||||
@@ -20,6 +21,7 @@ class DataBase():
|
||||
self.person_overview = PersonOverview(self.execute)
|
||||
self.people_graphs = PeopleGraphs(self.execute)
|
||||
self.dashboard = Dashboard(self.execute)
|
||||
self.schema = Schema(self.execute)
|
||||
|
||||
db_url = urlparse(os.environ['DATABASE_URL'])
|
||||
# if db_url is null then throw error
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import polars as pl
|
||||
from utils import get_distinct_colors
|
||||
from datetime import datetime
|
||||
|
||||
class PeopleGraphs:
|
||||
def __init__(self, db_connection_method):
|
||||
@@ -7,10 +8,9 @@ class PeopleGraphs:
|
||||
|
||||
def get(self, selected_people_ids=None, min_date=None, max_date=None, selected_exercise_ids=None):
|
||||
"""
|
||||
Fetch workout topsets, calculate Estimated1RM in Polars,
|
||||
Fetch workout topsets, calculate Estimated1RM and graph data in Polars,
|
||||
then generate weekly workout & PR graphs.
|
||||
"""
|
||||
# Build query (no in-SQL 1RM calculation).
|
||||
query = """
|
||||
SELECT
|
||||
P.person_id AS "PersonId",
|
||||
@@ -42,267 +42,155 @@ class PeopleGraphs:
|
||||
query += f" AND E.exercise_id IN ({', '.join(['%s'] * len(selected_exercise_ids))})"
|
||||
params.extend(selected_exercise_ids)
|
||||
|
||||
# Execute and convert to DataFrame
|
||||
raw_data = self.execute(query, params)
|
||||
if not raw_data:
|
||||
# Return empty graphs if no data at all
|
||||
return [
|
||||
self.get_graph_model("Workouts per week", {}),
|
||||
self.get_graph_model("PRs per week", {})
|
||||
self._empty_graph("Workouts per week"),
|
||||
self._empty_graph("PRs per week")
|
||||
]
|
||||
|
||||
# Explicitly specify schema to ensure correct types
|
||||
schema_overrides = {
|
||||
"Weight": pl.Float64,
|
||||
"Repetitions": pl.Int64,
|
||||
"StartDate": pl.Date # Or pl.Datetime depending on DB driver, but usually Date for dates
|
||||
"StartDate": pl.Date
|
||||
}
|
||||
|
||||
# Depending on how 'self.execute' returns data (list of dicts usually),
|
||||
# Polars can infer schema. For robustness with DB types:
|
||||
try:
|
||||
df = pl.DataFrame(raw_data, schema_overrides=schema_overrides, infer_schema_length=1000)
|
||||
df = pl.DataFrame(raw_data, schema_overrides=schema_overrides, infer_schema_length=10000)
|
||||
except:
|
||||
# Fallback if specific schema injection fails due to mismatched input types
|
||||
df = pl.DataFrame(raw_data)
|
||||
|
||||
# Force StartDate to Date type and filter nulls
|
||||
df = df.with_columns(pl.col("StartDate").cast(pl.Date)).filter(pl.col("StartDate").is_not_null())
|
||||
|
||||
# Calculate Estimated1RM in Polars
|
||||
# Formula: round((100 * int(weight)) / (101.3 - 2.67123 * repetitions), 0)
|
||||
# Handle division by zero implicitly by filter or usage?
|
||||
# The original code only avoided div by zero if Repetitions == 0.
|
||||
# Polars handles nulls/NaNs usually, but let's replicate logic.
|
||||
|
||||
if df.is_empty():
|
||||
return [
|
||||
self._empty_graph("Workouts per week"),
|
||||
self._empty_graph("PRs per week")
|
||||
]
|
||||
|
||||
# Calculate Estimated1RM
|
||||
# SQL cast Weight::integer rounds to nearest. Matching that here.
|
||||
df = df.with_columns(
|
||||
pl.when(pl.col("Repetitions") == 0)
|
||||
.then(0)
|
||||
.otherwise(
|
||||
(pl.lit(100) * pl.col("Weight")) / (pl.lit(101.3) - pl.lit(2.67123) * pl.col("Repetitions"))
|
||||
(pl.lit(100) * pl.col("Weight").round(0).cast(pl.Int64)) / (pl.lit(101.3) - pl.lit(2.67123) * pl.col("Repetitions"))
|
||||
)
|
||||
.round(0)
|
||||
.cast(pl.Int64)
|
||||
.alias("Estimated1RM")
|
||||
)
|
||||
|
||||
# Build the weekly data models
|
||||
weekly_counts = self.get_workout_counts(df, period='week')
|
||||
weekly_pr_counts = self.count_prs_over_time(df, period='week')
|
||||
# Prepare period-truncated column
|
||||
df = df.with_columns(
|
||||
pl.col("StartDate").dt.truncate("1w").alias("Period")
|
||||
)
|
||||
|
||||
return [
|
||||
self.get_graph_model("Workouts per week", weekly_counts),
|
||||
self.get_graph_model("PRs per week", weekly_pr_counts)
|
||||
]
|
||||
|
||||
def _prepare_period_column(self, df: pl.DataFrame, period='week'):
|
||||
"""
|
||||
Convert StartDate to proper date type and add a Period column
|
||||
represented as the start date of that period.
|
||||
"""
|
||||
# Ensure StartDate is Date/Datetime
|
||||
if df["StartDate"].dtype == pl.String:
|
||||
df = df.with_columns(pl.col("StartDate").str.strptime(pl.Date, "%Y-%m-%d")) # Adjust format if needed
|
||||
elif df["StartDate"].dtype == pl.Object:
|
||||
# If it's python datetime objects
|
||||
df = df.with_columns(pl.col("StartDate").cast(pl.Date))
|
||||
|
||||
# Truncate to week or month
|
||||
if period == 'week':
|
||||
# Polars doesn't have a direct 'to_period' like Pandas.
|
||||
# We can use dt.truncate("1w") which floors to start of week (Monday usually)
|
||||
# Postgres/standard weeks usually start Monday.
|
||||
df = df.with_columns(
|
||||
pl.col("StartDate").dt.truncate("1w").alias("Period")
|
||||
)
|
||||
else: # month
|
||||
df = df.with_columns(
|
||||
pl.col("StartDate").dt.truncate("1mo").alias("Period")
|
||||
)
|
||||
|
||||
return df
|
||||
|
||||
def get_workout_counts(self, df: pl.DataFrame, period='week'):
|
||||
"""
|
||||
Returns workout counts per person per period.
|
||||
"""
|
||||
df = self._prepare_period_column(df, period)
|
||||
|
||||
# Ensure Period is string for consistent pivoting
|
||||
df = df.with_columns(pl.col("Period").dt.strftime("%Y-%m-%d"))
|
||||
|
||||
# Count unique workouts per (PersonId, PersonName, Period)
|
||||
grp = (
|
||||
# 1. Workouts per week
|
||||
workout_counts = (
|
||||
df.group_by(['PersonId', 'PersonName', 'Period'])
|
||||
.agg(pl.col('WorkoutId').n_unique().alias('Count'))
|
||||
)
|
||||
|
||||
return self._pivot_to_graph_dict(
|
||||
grp,
|
||||
index_col='PersonId',
|
||||
name_col='PersonName',
|
||||
period_col='Period',
|
||||
value_col='Count'
|
||||
)
|
||||
|
||||
def count_prs_over_time(self, df: pl.DataFrame, period='week'):
|
||||
"""
|
||||
Returns number of PRs hit per person per period.
|
||||
"""
|
||||
df = self._prepare_period_column(df, period)
|
||||
|
||||
# Max 1RM per (Person, Exercise, Period) - 'PeriodMax'
|
||||
grouped = (
|
||||
# 2. PRs per week
|
||||
grouped_prs = (
|
||||
df.group_by(['PersonId', 'PersonName', 'ExerciseId', 'Period'])
|
||||
.agg(pl.col('Estimated1RM').max().alias('PeriodMax'))
|
||||
.sort(['PersonId', 'ExerciseId', 'Period'])
|
||||
)
|
||||
|
||||
# Sort so we can track "all-time max"
|
||||
grouped = grouped.sort(by=['PersonId', 'ExerciseId', 'Period'])
|
||||
|
||||
# Calculate AllTimeMax representing the max UP TO the previous row.
|
||||
grouped = grouped.with_columns(
|
||||
grouped_prs = grouped_prs.with_columns(
|
||||
pl.col("PeriodMax")
|
||||
.cum_max()
|
||||
.over(['PersonId', 'ExerciseId'])
|
||||
.shift(1)
|
||||
.fill_null(0)
|
||||
.alias("AllTimeMax")
|
||||
)
|
||||
|
||||
grouped = grouped.with_columns(
|
||||
pl.col("AllTimeMax").fill_null(0)
|
||||
)
|
||||
|
||||
grouped = grouped.with_columns(
|
||||
grouped_prs = grouped_prs.with_columns(
|
||||
(pl.col("PeriodMax") > pl.col("AllTimeMax")).cast(pl.Int64).alias("IsPR")
|
||||
)
|
||||
|
||||
# Ensure Period is string for consistent pivoting
|
||||
grouped = grouped.with_columns(pl.col("Period").dt.strftime("%Y-%m-%d"))
|
||||
|
||||
# Sum PRs across exercises for (Person, Period)
|
||||
pr_counts = (
|
||||
grouped.group_by(['PersonId', 'PersonName', 'Period'])
|
||||
grouped_prs.group_by(['PersonId', 'PersonName', 'Period'])
|
||||
.agg(pl.col('IsPR').sum().alias('Count'))
|
||||
)
|
||||
|
||||
return [
|
||||
self._build_graph_model("Workouts per week", workout_counts),
|
||||
self._build_graph_model("PRs per week", pr_counts)
|
||||
]
|
||||
|
||||
def _empty_graph(self, title):
|
||||
return {
|
||||
'title': title,
|
||||
'vb_width': 200,
|
||||
'vb_height': 75,
|
||||
'plots': []
|
||||
}
|
||||
|
||||
def _build_graph_model(self, title, df: pl.DataFrame):
|
||||
if df.is_empty():
|
||||
return self._empty_graph(title)
|
||||
|
||||
# 1. Scaling stats from the sparse data (to find global span and max value)
|
||||
stats = df.select([
|
||||
pl.col("Period").min().alias("min_date"),
|
||||
pl.col("Period").max().alias("max_date"),
|
||||
pl.col("Count").max().alias("max_val")
|
||||
])
|
||||
min_date = stats.get_column("min_date")[0]
|
||||
max_date = stats.get_column("max_date")[0]
|
||||
max_val = stats.get_column("max_val")[0]
|
||||
|
||||
return self._pivot_to_graph_dict(
|
||||
pr_counts,
|
||||
index_col='PersonId',
|
||||
name_col='PersonName',
|
||||
period_col='Period',
|
||||
value_col='Count'
|
||||
date_span = max((max_date - min_date).days, 1)
|
||||
val_range = max(max_val, 1)
|
||||
vb_width, vb_height = 200, 75
|
||||
|
||||
# 2. Make data "dense" so lines connect to 0 for missing weeks
|
||||
# This replicates the behavior of the original pivot().fill_null(0)
|
||||
all_periods = df.select("Period").unique().sort("Period")
|
||||
all_people = df.select(["PersonId", "PersonName"]).unique(subset=["PersonId"])
|
||||
dense_df = all_people.join(all_periods, how="cross")
|
||||
|
||||
df = dense_df.join(df.select(["PersonId", "Period", "Count"]), on=["PersonId", "Period"], how="left").with_columns(
|
||||
pl.col("Count").fill_null(0)
|
||||
)
|
||||
|
||||
def _pivot_to_graph_dict(self, df: pl.DataFrame, index_col, name_col, period_col, value_col):
|
||||
"""
|
||||
Convert Polars DataFrame to the nested dict structure expected by visualization.
|
||||
"""
|
||||
if df.is_empty():
|
||||
return {}
|
||||
# 3. Vectorized coordinate calculation and label formatting
|
||||
df = df.with_columns([
|
||||
(((pl.col("Period") - min_date).dt.total_days() / date_span)).alias("x_norm"),
|
||||
((pl.col("Count") / val_range) * vb_height).alias("y_scaled"),
|
||||
(
|
||||
pl.col("Count").cast(pl.String) +
|
||||
" for " + pl.col("PersonName") +
|
||||
" at " + pl.col("Period").dt.strftime("%d %b %y")
|
||||
).alias("msg")
|
||||
]).sort(["PersonId", "Period"])
|
||||
|
||||
# Pivot
|
||||
pivoted = df.pivot(
|
||||
values=value_col,
|
||||
index=[index_col, name_col],
|
||||
columns=period_col,
|
||||
aggregate_function="sum"
|
||||
).fill_null(0)
|
||||
# 4. Group by person to build the 'plots' structure
|
||||
distinct_people = df.select("PersonId").unique(maintain_order=True).get_column("PersonId").to_list()
|
||||
colors = get_distinct_colors(len(distinct_people))
|
||||
color_map = {pid: colors[i] for i, pid in enumerate(distinct_people)}
|
||||
|
||||
rows = pivoted.to_dicts()
|
||||
date_cols = [c for c in pivoted.columns if c not in [index_col, name_col]]
|
||||
|
||||
result = {}
|
||||
for row in rows:
|
||||
pid = row[index_col]
|
||||
pname = row[name_col]
|
||||
|
||||
period_counts = {}
|
||||
for dc in date_cols:
|
||||
val = row[dc]
|
||||
# If val is 0, we can skip if sparse behavior is desired,
|
||||
# but let's keep it to match original behavior exactly if possible.
|
||||
# Only adding if val > 0 or if we want full zeros?
|
||||
# Original Pandas pivot keeps all columns (dates) for all rows, filling NaNs (0).
|
||||
# The iteration later in 'get_graph_model' determines what to plot.
|
||||
|
||||
# Parse date string back to date object
|
||||
try:
|
||||
d_obj = datetime.strptime(str(dc), "%Y-%m-%d").date()
|
||||
period_counts[d_obj] = val
|
||||
except ValueError:
|
||||
# Should not happen if we controlled the format
|
||||
print(f"Warning: Could not parse date column {dc}")
|
||||
period_counts[dc] = val
|
||||
|
||||
result[pid] = {
|
||||
'PersonName': pname,
|
||||
'PRCounts': period_counts
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def get_graph_model(self, title, data_dict):
|
||||
"""
|
||||
Builds a line-graph model from the dictionary.
|
||||
This part remains mostly standard Python as it manipulates dicts.
|
||||
"""
|
||||
if not data_dict:
|
||||
return {
|
||||
'title': title,
|
||||
'vb_width': 200,
|
||||
'vb_height': 75,
|
||||
'plots': []
|
||||
}
|
||||
|
||||
# Gather all dates & values
|
||||
all_dates = []
|
||||
all_values = []
|
||||
for user_data in data_dict.values():
|
||||
all_dates.extend(user_data['PRCounts'].keys())
|
||||
all_values.extend(user_data['PRCounts'].values())
|
||||
|
||||
if not all_dates:
|
||||
return {
|
||||
'title': title,
|
||||
'vb_width': 200,
|
||||
'vb_height': 75,
|
||||
'plots': []
|
||||
}
|
||||
|
||||
min_date = min(all_dates)
|
||||
max_date = max(all_dates)
|
||||
|
||||
# Ensure min_date/max_date are comparable types.
|
||||
# If they are strings vs dates, that's an issue.
|
||||
# We tried to enforce conversion in _pivot_to_graph_dict.
|
||||
|
||||
date_span = max((max_date - min_date).days, 1)
|
||||
|
||||
max_val = max(all_values)
|
||||
min_val = 0
|
||||
val_range = max_val - min_val if max_val != min_val else 1
|
||||
|
||||
vb_width, vb_height = 200, 75
|
||||
colors = get_distinct_colors(len(data_dict))
|
||||
plots = []
|
||||
|
||||
for i, (pid, user_data) in enumerate(data_dict.items()):
|
||||
name = user_data['PersonName']
|
||||
pr_counts = user_data['PRCounts']
|
||||
# Sort by date so points are in chronological order
|
||||
sorted_pr = sorted(pr_counts.items(), key=lambda x: x[0])
|
||||
|
||||
points = []
|
||||
labels = []
|
||||
for d, val in sorted_pr:
|
||||
# Scale x,y to fit [0..1], then we multiply y by vb_height
|
||||
x = (d - min_date).days / date_span
|
||||
y = (val - min_val) / val_range * vb_height
|
||||
points.append((y, x))
|
||||
labels.append((y, x, f'{val} for {name} at {d.strftime("%d %b %y")}'))
|
||||
for pid in distinct_people:
|
||||
person_df = df.filter(pl.col("PersonId") == pid)
|
||||
if person_df.is_empty():
|
||||
continue
|
||||
|
||||
name = person_df.get_column("PersonName")[0]
|
||||
|
||||
y_vals = person_df.get_column("y_scaled").to_list()
|
||||
x_norms = person_df.get_column("x_norm").to_list()
|
||||
msgs = person_df.get_column("msg").to_list()
|
||||
|
||||
points = list(zip(y_vals, x_norms))
|
||||
labels = list(zip(y_vals, x_norms, msgs))
|
||||
|
||||
plots.append({
|
||||
'label': name,
|
||||
'color': colors[i],
|
||||
'color': color_map[pid],
|
||||
'points': points,
|
||||
'plot_labels': labels
|
||||
})
|
||||
@@ -313,5 +201,3 @@ class PeopleGraphs:
|
||||
'vb_height': vb_height,
|
||||
'plots': plots
|
||||
}
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
114
features/schema.py
Normal file
114
features/schema.py
Normal file
@@ -0,0 +1,114 @@
|
||||
class Schema:
|
||||
def __init__(self, db_connection_method):
|
||||
self.execute = db_connection_method
|
||||
|
||||
def get_schema_info(self, schema='public'):
|
||||
"""Fetches schema information directly."""
|
||||
tables_result = self.execute("""
|
||||
SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = %s AND table_type = 'BASE TABLE';
|
||||
""", [schema])
|
||||
tables = [row['table_name'] for row in tables_result]
|
||||
|
||||
schema_info = {}
|
||||
for table in tables:
|
||||
columns_result = self.execute("""
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = %s AND table_name = %s
|
||||
ORDER BY ordinal_position;
|
||||
""", [schema, table])
|
||||
columns = [(row['column_name'], row['data_type']) for row in columns_result]
|
||||
|
||||
primary_keys_result = self.execute("""
|
||||
SELECT kcu.column_name
|
||||
FROM information_schema.table_constraints tc
|
||||
JOIN information_schema.key_column_usage kcu
|
||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
||||
WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = %s AND tc.table_name = %s;
|
||||
""", [schema, table])
|
||||
primary_keys = [row['column_name'] for row in primary_keys_result]
|
||||
|
||||
foreign_keys_result = self.execute("""
|
||||
SELECT kcu.column_name AS fk_column, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column
|
||||
FROM information_schema.table_constraints AS tc
|
||||
JOIN information_schema.key_column_usage AS kcu
|
||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
||||
JOIN information_schema.constraint_column_usage AS ccu
|
||||
ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema = %s AND tc.table_name = %s;
|
||||
""", [schema, table])
|
||||
foreign_keys = [(row['fk_column'], row['referenced_table'], row['referenced_column']) for row in foreign_keys_result]
|
||||
|
||||
schema_info[table] = {
|
||||
'columns': columns,
|
||||
'primary_keys': primary_keys,
|
||||
'foreign_keys': foreign_keys
|
||||
}
|
||||
return schema_info
|
||||
|
||||
def _map_data_type_for_sql(self, postgres_type):
|
||||
"""Maps PostgreSQL types to standard SQL types (simplified)."""
|
||||
return {
|
||||
'character varying': 'VARCHAR', 'varchar': 'VARCHAR', 'text': 'TEXT',
|
||||
'integer': 'INTEGER', 'bigint': 'BIGINT', 'boolean': 'BOOLEAN',
|
||||
'timestamp without time zone': 'TIMESTAMP', 'timestamp with time zone': 'TIMESTAMPTZ',
|
||||
'numeric': 'NUMERIC', 'real': 'REAL', 'date': 'DATE'
|
||||
}.get(postgres_type, postgres_type.upper())
|
||||
|
||||
def _map_data_type(self, postgres_type):
|
||||
"""Maps PostgreSQL types to Mermaid ER diagram types."""
|
||||
type_mapping = {
|
||||
'integer': 'int', 'bigint': 'int', 'smallint': 'int',
|
||||
'character varying': 'string', 'varchar': 'string', 'text': 'string',
|
||||
'date': 'date', 'timestamp without time zone': 'datetime',
|
||||
'timestamp with time zone': 'datetime', 'boolean': 'bool',
|
||||
'numeric': 'float', 'real': 'float'
|
||||
}
|
||||
return type_mapping.get(postgres_type, 'string')
|
||||
|
||||
def generate_mermaid_er(self, schema_info):
|
||||
"""Generates Mermaid ER diagram code from schema info."""
|
||||
mermaid_lines = ["erDiagram"]
|
||||
for table, info in schema_info.items():
|
||||
mermaid_lines.append(f" {table} {{")
|
||||
for column_name, data_type in info['columns']:
|
||||
mermaid_data_type = self._map_data_type(data_type)
|
||||
pk_marker = " PK" if column_name in info.get('primary_keys', []) else ""
|
||||
mermaid_lines.append(f" {mermaid_data_type} {column_name}{pk_marker}")
|
||||
mermaid_lines.append(" }")
|
||||
|
||||
for table, info in schema_info.items():
|
||||
for fk_column, referenced_table, referenced_column in info['foreign_keys']:
|
||||
relation = f" {table} }}|--|| {referenced_table} : \"{fk_column} to {referenced_column}\""
|
||||
mermaid_lines.append(relation)
|
||||
return "\n".join(mermaid_lines)
|
||||
|
||||
def generate_create_script(self, schema_info):
|
||||
"""Generates SQL CREATE TABLE scripts from schema info."""
|
||||
lines = []
|
||||
for table, info in schema_info.items():
|
||||
columns = info['columns']
|
||||
pks = info.get('primary_keys', [])
|
||||
fks = info['foreign_keys']
|
||||
column_defs = []
|
||||
for column_name, data_type in columns:
|
||||
sql_type = self._map_data_type_for_sql(data_type)
|
||||
column_defs.append(f' "{column_name}" {sql_type}')
|
||||
if pks:
|
||||
pk_columns = ", ".join(f'"{pk}"' for pk in pks)
|
||||
column_defs.append(f' PRIMARY KEY ({pk_columns})')
|
||||
|
||||
columns_sql = ",\n".join(column_defs)
|
||||
create_stmt = f'CREATE TABLE "{table}" (\n{columns_sql}\n);'
|
||||
lines.append(create_stmt)
|
||||
|
||||
for fk_column, ref_table, ref_col in fks:
|
||||
alter_stmt = (
|
||||
f'ALTER TABLE "{table}" ADD CONSTRAINT "fk_{table}_{fk_column}" '
|
||||
f'FOREIGN KEY ("{fk_column}") REFERENCES "{ref_table}" ("{ref_col}");'
|
||||
)
|
||||
lines.append(alter_stmt)
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "workout-tracker",
|
||||
"version": "1.0.0",
|
||||
"description": "Workout Tracker application",
|
||||
"main": "app.py",
|
||||
"scripts": {
|
||||
"generate-schema": "python scripts/generate_schema.py",
|
||||
"build": "npx tailwindcss -i ./static/src/input.css -o ./static/css/tailwind.css --minify",
|
||||
"watch": "npx tailwindcss -i ./static/src/input.css -o ./static/css/tailwind.css --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mermaid-js/mermaid-cli": "^11.12.0",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
}
|
||||
@@ -137,6 +137,3 @@ Here are some ideas for new features and improvements that could be added to the
|
||||
|
||||
(Details on how to contribute to the project, if applicable. e.g., coding standards, pull request process)
|
||||
|
||||
## License
|
||||
|
||||
(Specify the license for the project, e.g., MIT, GPL)
|
||||
|
||||
@@ -10,7 +10,6 @@ jinja2-fragments==0.3.0
|
||||
Werkzeug==2.2.2
|
||||
numpy==1.19.5
|
||||
python-dotenv==1.0.1
|
||||
plotly==5.24.1
|
||||
wtforms==3.2.1
|
||||
flask-wtf==1.2.2
|
||||
Flask-Login==0.6.3
|
||||
|
||||
@@ -10,116 +10,7 @@ from utils import prepare_svg_plot_data # Will be created for SVG data prep
|
||||
sql_explorer_bp = Blueprint('sql_explorer', __name__, url_prefix='/sql')
|
||||
htmx = HTMX()
|
||||
|
||||
def _get_schema_info(schema='public'):
|
||||
"""Fetches schema information directly."""
|
||||
tables_result = db.execute("""
|
||||
SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = %s AND table_type = 'BASE TABLE';
|
||||
""", [schema])
|
||||
tables = [row['table_name'] for row in tables_result]
|
||||
|
||||
schema_info = {}
|
||||
for table in tables:
|
||||
columns_result = db.execute("""
|
||||
SELECT column_name, data_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = %s AND table_name = %s
|
||||
ORDER BY ordinal_position;
|
||||
""", [schema, table])
|
||||
columns = [(row['column_name'], row['data_type']) for row in columns_result]
|
||||
|
||||
primary_keys_result = db.execute("""
|
||||
SELECT kcu.column_name
|
||||
FROM information_schema.table_constraints tc
|
||||
JOIN information_schema.key_column_usage kcu
|
||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
||||
WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = %s AND tc.table_name = %s;
|
||||
""", [schema, table])
|
||||
primary_keys = [row['column_name'] for row in primary_keys_result]
|
||||
|
||||
foreign_keys_result = db.execute("""
|
||||
SELECT kcu.column_name AS fk_column, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column
|
||||
FROM information_schema.table_constraints AS tc
|
||||
JOIN information_schema.key_column_usage AS kcu
|
||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
||||
JOIN information_schema.constraint_column_usage AS ccu
|
||||
ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema = %s AND tc.table_name = %s;
|
||||
""", [schema, table])
|
||||
foreign_keys = [(row['fk_column'], row['referenced_table'], row['referenced_column']) for row in foreign_keys_result]
|
||||
|
||||
schema_info[table] = {
|
||||
'columns': columns,
|
||||
'primary_keys': primary_keys,
|
||||
'foreign_keys': foreign_keys
|
||||
}
|
||||
return schema_info
|
||||
|
||||
def _map_data_type_for_sql(postgres_type):
|
||||
"""Maps PostgreSQL types to standard SQL types (simplified)."""
|
||||
return {
|
||||
'character varying': 'VARCHAR', 'varchar': 'VARCHAR', 'text': 'TEXT',
|
||||
'integer': 'INTEGER', 'bigint': 'BIGINT', 'boolean': 'BOOLEAN',
|
||||
'timestamp without time zone': 'TIMESTAMP', 'timestamp with time zone': 'TIMESTAMPTZ',
|
||||
'numeric': 'NUMERIC', 'real': 'REAL', 'date': 'DATE'
|
||||
}.get(postgres_type, postgres_type.upper())
|
||||
|
||||
def _map_data_type(postgres_type):
|
||||
"""Maps PostgreSQL types to Mermaid ER diagram types."""
|
||||
type_mapping = {
|
||||
'integer': 'int', 'bigint': 'int', 'smallint': 'int',
|
||||
'character varying': 'string', 'varchar': 'string', 'text': 'string',
|
||||
'date': 'date', 'timestamp without time zone': 'datetime',
|
||||
'timestamp with time zone': 'datetime', 'boolean': 'bool',
|
||||
'numeric': 'float', 'real': 'float'
|
||||
}
|
||||
return type_mapping.get(postgres_type, 'string')
|
||||
|
||||
def _generate_mermaid_er(schema_info):
|
||||
"""Generates Mermaid ER diagram code from schema info."""
|
||||
mermaid_lines = ["erDiagram"]
|
||||
for table, info in schema_info.items():
|
||||
mermaid_lines.append(f" {table} {{")
|
||||
for column_name, data_type in info['columns']:
|
||||
mermaid_data_type = _map_data_type(data_type)
|
||||
pk_marker = " PK" if column_name in info.get('primary_keys', []) else ""
|
||||
mermaid_lines.append(f" {mermaid_data_type} {column_name}{pk_marker}")
|
||||
mermaid_lines.append(" }")
|
||||
|
||||
for table, info in schema_info.items():
|
||||
for fk_column, referenced_table, referenced_column in info['foreign_keys']:
|
||||
relation = f" {table} }}|--|| {referenced_table} : \"{fk_column} to {referenced_column}\""
|
||||
mermaid_lines.append(relation)
|
||||
return "\n".join(mermaid_lines)
|
||||
|
||||
def _generate_create_script(schema_info):
|
||||
"""Generates SQL CREATE TABLE scripts from schema info."""
|
||||
lines = []
|
||||
for table, info in schema_info.items():
|
||||
columns = info['columns']
|
||||
pks = info.get('primary_keys', [])
|
||||
fks = info['foreign_keys']
|
||||
column_defs = []
|
||||
for column_name, data_type in columns:
|
||||
sql_type = _map_data_type_for_sql(data_type)
|
||||
column_defs.append(f' "{column_name}" {sql_type}')
|
||||
if pks:
|
||||
pk_columns = ", ".join(f'"{pk}"' for pk in pks)
|
||||
column_defs.append(f' PRIMARY KEY ({pk_columns})')
|
||||
|
||||
columns_sql = ",\n".join(column_defs)
|
||||
create_stmt = f'CREATE TABLE "{table}" (\n{columns_sql}\n);'
|
||||
lines.append(create_stmt)
|
||||
|
||||
for fk_column, ref_table, ref_col in fks:
|
||||
alter_stmt = (
|
||||
f'ALTER TABLE "{table}" ADD CONSTRAINT "fk_{table}_{fk_column}" '
|
||||
f'FOREIGN KEY ("{fk_column}") REFERENCES "{ref_table}" ("{ref_col}");'
|
||||
)
|
||||
lines.append(alter_stmt)
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _execute_sql(query):
|
||||
@@ -272,10 +163,9 @@ def delete_sql_query(query_id):
|
||||
|
||||
@sql_explorer_bp.route("/schema", methods=['GET'])
|
||||
def sql_schema():
|
||||
schema_info = _get_schema_info()
|
||||
mermaid_code = _generate_mermaid_er(schema_info)
|
||||
create_sql = _generate_create_script(schema_info)
|
||||
return render_template('partials/sql_explorer/schema.html', mermaid_code=mermaid_code, create_sql=create_sql)
|
||||
schema_info = db.schema.get_schema_info()
|
||||
create_sql = db.schema.generate_create_script(schema_info)
|
||||
return render_template('partials/sql_explorer/schema.html', create_sql=create_sql)
|
||||
|
||||
@sql_explorer_bp.route("/plot/<int:query_id>", methods=['GET'])
|
||||
def plot_query(query_id):
|
||||
|
||||
80
scripts/generate_schema.py
Normal file
80
scripts/generate_schema.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Add the project root to sys.path so we can import 'features'
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
import subprocess
|
||||
import tempfile
|
||||
import psycopg2
|
||||
from psycopg2.extras import RealDictCursor
|
||||
from urllib.parse import urlparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Import Schema logic
|
||||
from features.schema import Schema
|
||||
|
||||
def main():
|
||||
# Load environment variables from .env
|
||||
load_dotenv()
|
||||
|
||||
database_url = os.environ.get('DATABASE_URL')
|
||||
if not database_url:
|
||||
print("Error: DATABASE_URL not set in environment.")
|
||||
return
|
||||
|
||||
# Connect to the database
|
||||
db_url = urlparse(database_url)
|
||||
conn = psycopg2.connect(
|
||||
database=db_url.path[1:],
|
||||
user=db_url.username,
|
||||
password=db_url.password,
|
||||
host=db_url.hostname,
|
||||
port=db_url.port
|
||||
)
|
||||
|
||||
def execute_func(query, args=()):
|
||||
cur = conn.cursor(cursor_factory=RealDictCursor)
|
||||
cur.execute(query, args)
|
||||
rv = None
|
||||
if cur.description is not None:
|
||||
rv = cur.fetchall()
|
||||
cur.close()
|
||||
return rv
|
||||
|
||||
# Initialize Schema logic
|
||||
schema_logic = Schema(execute_func)
|
||||
|
||||
print("Fetching schema information...")
|
||||
schema_info = schema_logic.get_schema_info()
|
||||
|
||||
print("Generating Mermaid code...")
|
||||
mermaid_code = schema_logic.generate_mermaid_er(schema_info)
|
||||
|
||||
print("Rendering SVG via mermaid-cli...")
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
input_file = os.path.join(tmpdir, "input.mmd")
|
||||
output_file = os.path.join(tmpdir, "schema.svg")
|
||||
|
||||
# Destination path
|
||||
target_file = os.path.abspath(os.path.join("static", "img", "schema.svg"))
|
||||
os.makedirs(os.path.dirname(target_file), exist_ok=True)
|
||||
|
||||
with open(input_file, "w") as f:
|
||||
f.write(mermaid_code)
|
||||
|
||||
# Run mmdc
|
||||
subprocess.run(
|
||||
["bun", "x", "mmdc", "-i", input_file, "-o", target_file],
|
||||
check=True
|
||||
)
|
||||
print(f"Successfully generated {target_file}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during SVG generation: {e}")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
429
static/css/tail.select.min.css
vendored
429
static/css/tail.select.min.css
vendored
@@ -1,429 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
| tail.select - The vanilla solution to make your HTML select fields AWESOME!
|
||||
| @file ./css/bootstrap4/tail.select-default.css
|
||||
| @author SamBrishes <sam@pytes.net>
|
||||
| @version 0.5.15 - Beta
|
||||
|
|
||||
| @website https://github.com/pytesNET/tail.select
|
||||
| @license X11 / MIT License
|
||||
| @copyright Copyright © 2014 - 2019 SamBrishes, pytesNET <info@pytes.net>
|
||||
*/
|
||||
|
||||
/* @start GENERAL */
|
||||
.tail-select, .tail-select *, .tail-select *:before, .tail-select *:after{
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
.tail-select, .tail-select *{
|
||||
outline: none;
|
||||
user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.tail-select{
|
||||
width: 100%;
|
||||
margin: 1px 0px 0px 0px;
|
||||
padding: 0px 8px 0px 0px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
font-size: 1rem;
|
||||
line-height: 1.8;
|
||||
border-radius: 0.5rem;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
}
|
||||
.tail-select mark{
|
||||
color: white;
|
||||
background-color: #0088CC;
|
||||
}
|
||||
.tail-select button{
|
||||
outline: none;
|
||||
}
|
||||
.tail-select button.tail-all, .tail-select button.tail-none{
|
||||
height: auto;
|
||||
margin: 0 2px;
|
||||
padding: 2px 6px;
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
text-shadow: none;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
vertical-align: top;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
border-radius: 3px;
|
||||
box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
transition: color 142ms linear, border 142ms linear, background 142ms linear;
|
||||
-webkit-transition: color 142ms linear, border 142ms linear, background 142ms linear;
|
||||
}
|
||||
.tail-select button.tail-all{
|
||||
color: #AAAAAA;
|
||||
border-color: #CCCCCC;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select button.tail-all:hover{
|
||||
color: #62C462;
|
||||
border-color: #62C462;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select button.tail-none{
|
||||
color: #AAAAAA;
|
||||
border-color: #CCCCCC;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select button.tail-none:hover{
|
||||
color: #EE5F5B;
|
||||
border-color: #EE5F5B;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select.disabled button.tail-all{
|
||||
color: #CCCCCC;
|
||||
border-color: #CCCCCC;
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
.tail-select.disabled button.tail-none{
|
||||
color: #CCCCCC;
|
||||
border-color: #CCCCCC;
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
.tail-select input[type="text"]{
|
||||
color: #343a40;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
margin: 0;
|
||||
padding: 0.25rem 0.5rem;
|
||||
display: inline-block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
vertical-align: middle;
|
||||
background-color: transparent;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #CCCCCC;
|
||||
border-radius: 0.2rem;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
transition: border 142ms linear, box-shadow 142ms linear;
|
||||
-webkit-transition: border 142ms linear, box-shadow 142ms linear;
|
||||
}
|
||||
.tail-select input[type="text"]:hover{
|
||||
color: #343a40;
|
||||
border-color: #b3b3b3;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select input[type="text"]:focus{
|
||||
color: #0088CC;
|
||||
border-color: #0088CC;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select.disabled input[type="text"]{
|
||||
color: #e6e6e6;
|
||||
border-color: #CCCCCC;
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.tail-select-container{
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
text-align: left;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.tail-select-container .select-handle{
|
||||
width: auto;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
margin: 1px;
|
||||
padding: 0.2em 0.6em 0.3em;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
font-size: 11.844px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
vertical-align: top;
|
||||
background-color: #0088CC;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
border-radius: 3px;
|
||||
transition: background 142ms linear;
|
||||
-webkit-transition: background 142ms linear;
|
||||
}
|
||||
.tail-select-container .select-handle:hover{
|
||||
color: white;
|
||||
background-color: #005580;
|
||||
}
|
||||
.tail-select-container.select-label .select-handle{
|
||||
margin: 5px 3px;
|
||||
}
|
||||
/* @end GENERAL */
|
||||
|
||||
/* @start LABEL */
|
||||
.tail-select .select-label{
|
||||
cursor: pointer;
|
||||
color: #343A40;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0 30px 0 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
background-color: white;
|
||||
background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A//www.w3.org/2000/svg'%20viewBox%3D'0%200%204%205'%3E%3Cpath%20fill%3D'%23343A40'%20d%3D'M2%200L0%202h4zm0%205L0%203h4z'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right 0.75rem;
|
||||
background-size: 8px 10px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #CCCCCC;
|
||||
border-radius: 3px;
|
||||
transition: border 142ms linear, background 142ms linear, box-shadow 142ms linear;
|
||||
-webkit-transition: border 142ms linear, background 142ms linear, box-shadow 142ms linear;
|
||||
}
|
||||
.tail-select .select-label:hover{
|
||||
color: #343A40;
|
||||
border-color: #b9b9b9;
|
||||
background-color: #ececec;
|
||||
}
|
||||
.tail-select .select-label .label-count, .tail-select .select-label .label-inner{
|
||||
width: auto;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
.tail-select .select-label .label-count{
|
||||
float: left;
|
||||
color: white;
|
||||
margin: 10px -3px 0 9px;
|
||||
padding: 0.25em 0.4em;
|
||||
display: inline-block;
|
||||
font-size: 75%;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
text-shadow: none;
|
||||
white-space: nowrap;
|
||||
border-radius: 0.25rem;
|
||||
background-color: #343A40;
|
||||
}
|
||||
.tail-select .select-label .label-inner{
|
||||
margin: 0;
|
||||
padding: 0.375rem 0.75rem;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.tail-select.active .select-label{
|
||||
color: #343A40;
|
||||
border-color: #0088CC;
|
||||
background-color: #ececec;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 136, 204, 0.35);
|
||||
-webkit-box-shadow: 0 0 0 0.2rem rgba(0, 136, 204, 0.35);
|
||||
}
|
||||
/* @end LABEL */
|
||||
|
||||
/* @start DROPDOWN */
|
||||
.tail-select .select-dropdown{
|
||||
top: 100%;
|
||||
left: 0;
|
||||
color: #343a40;
|
||||
width: 100%;
|
||||
margin: 0.125rem 0 0;
|
||||
padding: 0;
|
||||
z-index: 27;
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.25rem;
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
}
|
||||
.tail-select .select-dropdown .dropdown-search{
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
border-width: 0 0 1px 0;
|
||||
border-style: solid;
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
.tail-select .select-dropdown .dropdown-inner{
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 1px 0;
|
||||
display: block;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.tail-select .select-dropdown .dropdown-empty{
|
||||
margin: 0;
|
||||
padding: 1.25rem 1.75rem;
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.tail-select .select-dropdown .dropdown-action{
|
||||
top: 8px;
|
||||
right: 15px;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 7px 0;
|
||||
z-index: 35;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.tail-select .select-dropdown ul, .tail-select .select-dropdown ul li{
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
list-style: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
.tail-select .select-dropdown ul li{
|
||||
color: #343a40;
|
||||
padding: 0.25rem 1.75rem;
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
.tail-select .select-dropdown ul li:first-of-type{
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.tail-select .select-dropdown ul li:last-of-type{
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.optgroup-title{
|
||||
color: rgba(52, 58, 64, 0.7);
|
||||
cursor: default;
|
||||
margin: 0;
|
||||
padding: 0.5rem 1.5rem;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
text-shadow: none;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.optgroup-title b{
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.2;
|
||||
text-shadow: none;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.optgroup-title button{
|
||||
float: right;
|
||||
opacity: 0;
|
||||
}
|
||||
.tail-select .select-dropdown ul:hover li button{
|
||||
opacity: 1;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option{
|
||||
cursor: pointer;
|
||||
color: #343a40;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option:before{
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 30px;
|
||||
height: 33px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 21;
|
||||
display: inline-block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
vertical-align: top;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option .option-description{
|
||||
color: rgba(52, 58, 64, 0.7);
|
||||
width: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
text-align: left;
|
||||
line-height: 14px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.tail-select.hide-selected .select-dropdown ul li.selected,
|
||||
.tail-select.hide-disabled .select-dropdown ul li.disabled{
|
||||
display: none;
|
||||
}
|
||||
/* Selected */
|
||||
.tail-select .select-dropdown ul li.dropdown-option.selected{
|
||||
color: #0088CC;
|
||||
background-color: transparent;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option.selected:before{
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC\
|
||||
9zdmciIHdpZHRoPSIxMiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDEyIDE2Ij48cGF0aCBkPSJNMTIgNWwtOCA4LTQtN\
|
||||
CAxLjUtMS41TDQgMTBsNi41LTYuNUwxMiA1eiIvPjwvc3ZnPg==");
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option.selected .option-description{
|
||||
color: rgba(52, 58, 64, 0.7);
|
||||
}
|
||||
/* Unselect */
|
||||
.tail-select.deselect .select-dropdown ul li.dropdown-option.selected:hover:before,
|
||||
.tail-select.multiple .select-dropdown ul li.dropdown-option.selected:hover:before,
|
||||
.tail-select.deselect .select-dropdown ul li.dropdown-option.selected.hover:before,
|
||||
.tail-select.multiple .select-dropdown ul li.dropdown-option.selected.hover:before{
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC\
|
||||
9zdmciIHdpZHRoPSIxMiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDEyIDE2Ij48cGF0aCBkPSJNNy40OCA4bDMuNzUgM\
|
||||
y43NS0xLjQ4IDEuNDhMNiA5LjQ4bC0zLjc1IDMuNzUtMS40OC0xLjQ4TDQuNTIgOCAuNzcgNC4yNWwxLjQ4LTEuNDhMNiA2\
|
||||
LjUybDMuNzUtMy43NSAxLjQ4IDEuNDhMNy40OCA4eiIvPjwvc3ZnPg==");
|
||||
}
|
||||
/* Hover */
|
||||
.tail-select .select-dropdown ul li.dropdown-option{
|
||||
transition: all 0.3s ease-in;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option:hover,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.hover{
|
||||
transition: all 0.4s ease;
|
||||
color: #343a40;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.tail-select .select-dropdown ul li.dropdown-option:hover .option-description,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.hover .option-description{
|
||||
color: rgba(52, 58, 64, 0.7);
|
||||
}
|
||||
/* Disabled */
|
||||
.tail-select.disabled .select-dropdown ul li.dropdown-option,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.disabled{
|
||||
cursor: not-allowed;
|
||||
color: rgba(52, 58, 64, 0.35);
|
||||
text-shadow: 0px 1px 0px rgba(122, 135, 147, 0.1), 0px -1px 0px rgba(0, 0, 0, 0.1);
|
||||
background-color: rgba(52, 58, 64, 0.02);
|
||||
}
|
||||
.tail-select.disabled .select-dropdown ul li.dropdown-option .option-description,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.disabled .option-description{
|
||||
text-shadow: 0px 1px 0px rgba(63, 71, 78, 0.05), 0px -1px 0px rgba(41, 45, 50, 0.05);
|
||||
}
|
||||
.tail-select.disabled .select-dropdown ul li.dropdown-option .option-description,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.disabled .option-description,
|
||||
.tail-select.disabled .select-dropdown ul li.dropdown-option:hover .option-description,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.disabled:hover .option-description,
|
||||
.tail-select.disabled .select-dropdown ul li.dropdown-option.hover .option-description,
|
||||
.tail-select .select-dropdown ul li.dropdown-option.disabled.hover .option-description{
|
||||
color: rgba(52, 58, 64, 0.7);
|
||||
}
|
||||
/* @end DROPDOWN */
|
||||
|
||||
/*# sourceMappingURL=tail.select-default.map */
|
||||
1
static/css/tailwind.css
Normal file
1
static/css/tailwind.css
Normal file
File diff suppressed because one or more lines are too long
1
static/img/schema.svg
Normal file
1
static/img/schema.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 135 KiB |
13
static/js/tail.select.min.js
vendored
13
static/js/tail.select.min.js
vendored
File diff suppressed because one or more lines are too long
3
static/src/input.css
Normal file
3
static/src/input.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
13
tailwind.config.js
Normal file
13
tailwind.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./templates/**/*.html",
|
||||
"./static/js/**/*.js",
|
||||
"./features/**/*.py",
|
||||
"./routes/**/*.py"
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
@@ -11,26 +11,12 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,900&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="https://cdn.rawgit.com/dreampulse/computer-modern-web-font/master/fonts.css">
|
||||
<link type="text/css" rel="stylesheet" href="/static/css/tail.select.min.css">
|
||||
<script src="/static/js/tail.select.min.js"></script>
|
||||
<script src="/static/js/tailwindcss@3.2.4.js"></script>
|
||||
<link href="/static/css/tailwind.css" rel="stylesheet">
|
||||
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
<script src="/static/js/htmx.min.js" defer></script>
|
||||
<script src="/static/js/hyperscript.min.js"></script>
|
||||
<script src="/static/js/sweetalert2@11.js" defer></script>
|
||||
<!-- Mermaid -->
|
||||
<script src="/static/js/mermaid.min.js"></script>
|
||||
<script>
|
||||
// Initialize Mermaid with startOnLoad set to false
|
||||
mermaid.initialize({
|
||||
startOnLoad: false, // Prevent automatic rendering
|
||||
theme: 'neutral',
|
||||
er: {
|
||||
diagramPadding: 20,
|
||||
layoutDirection: 'TB',
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -40,14 +40,22 @@
|
||||
</div>
|
||||
|
||||
<div class="mr-4">
|
||||
<select name="view" hx-get="{{ url_for('calendar.get_calendar', person_id=person_id) }}"
|
||||
hx-target="#container" hx-vals='{"date": "{{ date }}"}' hx-push-url="true"
|
||||
_="init js(me) tail.select(me, {}) end" class="h-10 invisible">
|
||||
<option value="month" {% if view=='month' %}selected{% endif %}>Month</option>
|
||||
<option value="year" {% if view=='year' %}selected{% endif %}>Year</option>
|
||||
<option value="notes">Notes</option>
|
||||
<option value="overview">Overview</option>
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='view',
|
||||
options=[
|
||||
{'id': 'month', 'name': 'Month', 'selected': (view == 'month')},
|
||||
{'id': 'year', 'name': 'Year', 'selected': (view == 'year')},
|
||||
{'id': 'notes', 'name': 'Notes', 'selected': (view == 'notes')},
|
||||
{'id': 'overview', 'name': 'Overview', 'selected': (view == 'overview')}
|
||||
],
|
||||
multiple=false,
|
||||
search=false,
|
||||
placeholder='View',
|
||||
hx_get=url_for('calendar.get_calendar', person_id=person_id),
|
||||
hx_target='#container',
|
||||
hx_vals='{"date": "' + date.strftime('%Y-%m-%d') + '"}',
|
||||
hx_push_url=true)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -10,21 +10,17 @@
|
||||
<div class="mb-3 w-full"><label
|
||||
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
|
||||
for="grid-city">People</label>
|
||||
<select class="bg-gray-50 border border-gray-300 h-10 invisible"
|
||||
hx-get="{{ url_for('dashboard') }}"
|
||||
hx-include="[name='min_date'],[name='max_date'],[name='exercise_id']" hx-push-url="true"
|
||||
hx-target="#container" multiple="" name="person_id" _="init js(me)
|
||||
tail.select(me, {
|
||||
multiple: true,
|
||||
search: true,
|
||||
placeholder: 'Filter people',
|
||||
})
|
||||
end">
|
||||
{% for person in people %}
|
||||
<option value="{{ person.id }}" {% if person.selected %}selected{% endif %}>{{ person.name
|
||||
}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='person_id',
|
||||
options=people,
|
||||
multiple=true,
|
||||
search=true,
|
||||
placeholder='Filter people',
|
||||
hx_get=url_for('dashboard'),
|
||||
hx_include="input[name='min_date'],input[name='max_date'],#select-exercise_id",
|
||||
hx_target='#container',
|
||||
hx_push_url=true)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -35,21 +31,17 @@
|
||||
<div class="mb-3 w-full"><label
|
||||
class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
|
||||
for="grid-city">Exercises</label>
|
||||
<select class="bg-gray-50 border border-gray-300 h-10 invisible"
|
||||
hx-get="{{ url_for('dashboard') }}"
|
||||
hx-include="[name='min_date'],[name='max_date'],[name='person_id']" hx-push-url="true"
|
||||
hx-target="#container" multiple="" name="exercise_id" _="init js(me)
|
||||
tail.select(me, {
|
||||
multiple: true,
|
||||
search: true,
|
||||
placeholder: 'Filter exercises',
|
||||
})
|
||||
end">
|
||||
{% for exercise in exercises %}
|
||||
<option value="{{ exercise.id }}" {% if exercise.selected %}selected{% endif %}>
|
||||
{{ exercise.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='exercise_id',
|
||||
options=exercises,
|
||||
multiple=true,
|
||||
search=true,
|
||||
placeholder='Filter exercises',
|
||||
hx_get=url_for('dashboard'),
|
||||
hx_include="input[name='min_date'],input[name='max_date'],#select-person_id",
|
||||
hx_target='#container',
|
||||
hx_push_url=true)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,7 +60,7 @@
|
||||
</svg></div><input
|
||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 w-full"
|
||||
hx-get="{{ url_for('dashboard') }}"
|
||||
hx-include="[name='min_date'],[name='max_date'],[name='person_id'],[name='exercise_id']"
|
||||
hx-include="input[name='min_date'],input[name='max_date'],#select-person_id,#select-exercise_id"
|
||||
hx-push-url="true" hx-target="#container" hx-trigger="change" name="min_date" type="date"
|
||||
value="{{ min_date }}">
|
||||
</div>
|
||||
@@ -98,7 +90,7 @@
|
||||
</div>
|
||||
|
||||
<div class="hidden" hx-get="{{ url_for('get_people_graphs') }}"
|
||||
hx-include="[name='exercise_id'],[name='min_date'],[name='max_date'],[name='person_id']" hx-trigger="load"
|
||||
hx-include="#select-exercise_id,input[name='min_date'],input[name='max_date'],#select-person_id" hx-trigger="load"
|
||||
hx-target="this" hx-swap="outerHTML">
|
||||
</div>
|
||||
|
||||
@@ -195,7 +187,7 @@
|
||||
|
||||
|
||||
<div class="hidden" hx-get="{{ url_for('get_stats') }}"
|
||||
hx-include="[name='exercise_id'],[name='min_date'],[name='max_date'],[name='person_id']" hx-trigger="load"
|
||||
hx-include="#select-exercise_id,input[name='min_date'],input[name='max_date'],#select-person_id" hx-trigger="load"
|
||||
hx-target="#stats" hx-swap="innerHTML">
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,13 +12,21 @@
|
||||
</div>
|
||||
|
||||
<div class="mr-4">
|
||||
<select name="view" hx-get="{{ url_for('calendar.get_calendar', person_id=person_id) }}"
|
||||
hx-target="#container" x-push-url="true" _="init js(me) tail.select(me, {}) end" class="h-10 invisible">
|
||||
<option value="month">Month</option>
|
||||
<option value="year">Year</option>
|
||||
<option value="notes" selected>Notes</option>
|
||||
<option value="overview">Overview</option>
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='view',
|
||||
options=[
|
||||
{'id': 'month', 'name': 'Month'},
|
||||
{'id': 'year', 'name': 'Year'},
|
||||
{'id': 'notes', 'name': 'Notes', 'selected': true},
|
||||
{'id': 'overview', 'name': 'Overview'}
|
||||
],
|
||||
multiple=false,
|
||||
search=false,
|
||||
placeholder='View',
|
||||
hx_get=url_for('calendar.get_calendar', person_id=person_id),
|
||||
hx_target='#container',
|
||||
hx_push_url=true)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
196
templates/partials/custom_select.html
Normal file
196
templates/partials/custom_select.html
Normal file
@@ -0,0 +1,196 @@
|
||||
<div class="relative w-full custom-select-container" data-multiple="{{ 'true' if multiple else 'false' }}"
|
||||
data-placeholder="{{ placeholder|default('Select options') }}">
|
||||
|
||||
<!-- Display area -->
|
||||
<button type="button"
|
||||
class="toggle-btn w-full bg-gray-50 border border-gray-300 rounded-lg p-2.5 text-sm text-gray-900 flex justify-between items-center focus:ring-blue-500 focus:border-blue-500">
|
||||
<span class="selected-label truncate border-none outline-none">
|
||||
{% set ns = namespace(selected_count=0, selected_name='') %}
|
||||
{% for option in options %}
|
||||
{% set opt_selected = option.selected if option.selected is defined else (option.is_selected if
|
||||
option.is_selected is defined else false) %}
|
||||
{% if opt_selected %}
|
||||
{% set ns.selected_count = ns.selected_count + 1 %}
|
||||
{% set opt_name = option.name if option.name is defined else (option.tag_name if option.tag_name is defined
|
||||
else (option.exercise_name if option.exercise_name is defined else option.label)) %}
|
||||
{% set ns.selected_name = opt_name %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if multiple %}
|
||||
<span class="bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">{{
|
||||
ns.selected_count }}</span>
|
||||
{{ placeholder|default('Select options') }}
|
||||
{% else %}
|
||||
{{ ns.selected_name if ns.selected_count > 0 else (placeholder|default('Select an option')) }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<svg class="w-4 h-4 ml-2 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Hidden native select for HTMX/Form submission -->
|
||||
<select name="{{ name }}" id="select-{{ name }}" {% if multiple %}multiple{% endif %} class="hidden native-select"
|
||||
{% if hx_get %}hx-get="{{ hx_get }}" {% endif %} {% if hx_post %}hx-post="{{ hx_post }}" {% endif %} {% if
|
||||
hx_include %}hx-include="{{ hx_include }}" {% endif %} {% if hx_target %}hx-target="{{ hx_target }}" {% endif %}
|
||||
{% if hx_push_url is sameas true %}hx-push-url="true" {% elif hx_push_url %}hx-push-url="{{ hx_push_url }}" {%
|
||||
endif %} {% if hx_vals %}hx-vals='{{ hx_vals|safe }}' {% endif %} {% if hx_swap %}hx-swap="{{ hx_swap }}" {%
|
||||
endif %}>
|
||||
{% for option in options %}
|
||||
{% set opt_id = option.id if option.id is defined else (option.tag_id if option.tag_id is defined else
|
||||
(option.exercise_id if option.exercise_id is defined else option.value)) %}
|
||||
{% set opt_name = option.name if option.name is defined else (option.tag_name if option.tag_name is defined else
|
||||
(option.exercise_name if option.exercise_name is defined else option.label)) %}
|
||||
{% set opt_selected = option.selected if option.selected is defined else (option.is_selected if
|
||||
option.is_selected is defined else false) %}
|
||||
<option value="{{ opt_id }}" {% if opt_selected %}selected{% endif %}>{{ opt_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<!-- Dropdown -->
|
||||
<div
|
||||
class="dropdown-menu hidden absolute z-40 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden">
|
||||
{% if search %}
|
||||
<div class="p-2 border-b bg-gray-50">
|
||||
<input type="text" placeholder="Search..."
|
||||
class="search-input w-full p-2 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
{% endif %}
|
||||
<ul class="options-list max-h-60 overflow-y-auto p-1">
|
||||
{% for option in options %}
|
||||
{% set opt_id = option.id if option.id is defined else (option.tag_id if option.tag_id is defined else
|
||||
(option.exercise_id if option.exercise_id is defined else option.value)) %}
|
||||
{% set opt_name = option.name if option.name is defined else (option.tag_name if option.tag_name is defined
|
||||
else (option.exercise_name if option.exercise_name is defined else option.label)) %}
|
||||
{% set opt_selected = option.selected if option.selected is defined else (option.is_selected if
|
||||
option.is_selected is defined else false) %}
|
||||
<li class="option flex items-center p-2 hover:bg-gray-100 cursor-pointer rounded-md {% if opt_selected %}bg-blue-50{% endif %}"
|
||||
data-index="{{ loop.index0 }}" data-value="{{ opt_id }}">
|
||||
{% if multiple %}
|
||||
<input type="checkbox" class="mr-2 pointer-events-none" {% if opt_selected %}checked{% endif %}>
|
||||
{% endif %}
|
||||
<span class="truncate opt-text">{{ opt_name }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
function initSelect(container) {
|
||||
if (container.dataset.initialized) return;
|
||||
container.dataset.initialized = 'true';
|
||||
|
||||
const toggleBtn = container.querySelector('.toggle-btn');
|
||||
const dropdown = container.querySelector('.dropdown-menu');
|
||||
const searchInput = container.querySelector('.search-input');
|
||||
const nativeSelect = container.querySelector('.native-select');
|
||||
const label = container.querySelector('.selected-label');
|
||||
const options = container.querySelectorAll('.option');
|
||||
const isMultiple = container.dataset.multiple === 'true';
|
||||
const placeholder = container.dataset.placeholder;
|
||||
|
||||
function refreshUI() {
|
||||
if (isMultiple) {
|
||||
let count = 0;
|
||||
for (let i = 0; i < nativeSelect.options.length; i++) {
|
||||
if (nativeSelect.options[i].selected) count++;
|
||||
}
|
||||
label.innerHTML = `<span class="bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">${count}</span> ${placeholder}`;
|
||||
} else {
|
||||
const selectedOpt = nativeSelect.options[nativeSelect.selectedIndex];
|
||||
label.textContent = selectedOpt ? selectedOpt.text : placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle dropdown
|
||||
toggleBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const isOpen = dropdown.classList.toggle('hidden');
|
||||
if (!isOpen) { // is now Open
|
||||
container.style.zIndex = '50';
|
||||
if (searchInput) searchInput.focus();
|
||||
} else {
|
||||
container.style.zIndex = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Close on click outside
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!container.contains(e.target)) {
|
||||
dropdown.classList.add('hidden');
|
||||
container.style.zIndex = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Search functionality
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const val = e.target.value.toLowerCase();
|
||||
options.forEach(opt => {
|
||||
const text = opt.querySelector('.opt-text').textContent.toLowerCase();
|
||||
opt.style.display = text.includes(val) ? 'flex' : 'none';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Selection logic
|
||||
options.forEach(opt => {
|
||||
opt.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const index = parseInt(opt.dataset.index);
|
||||
const nativeOption = nativeSelect.options[index];
|
||||
|
||||
if (isMultiple) {
|
||||
const checkbox = opt.querySelector('input[type="checkbox"]');
|
||||
const newState = !nativeOption.selected;
|
||||
|
||||
nativeOption.selected = newState;
|
||||
if (newState) nativeOption.setAttribute('selected', '');
|
||||
else nativeOption.removeAttribute('selected');
|
||||
|
||||
checkbox.checked = newState;
|
||||
opt.classList.toggle('bg-blue-50', newState);
|
||||
refreshUI();
|
||||
} else {
|
||||
// Single select
|
||||
options.forEach(o => o.classList.remove('bg-blue-50'));
|
||||
for (let i = 0; i < nativeSelect.options.length; i++) {
|
||||
nativeSelect.options[i].selected = false;
|
||||
nativeSelect.options[i].removeAttribute('selected');
|
||||
}
|
||||
|
||||
nativeOption.selected = true;
|
||||
nativeOption.setAttribute('selected', '');
|
||||
opt.classList.add('bg-blue-50');
|
||||
refreshUI();
|
||||
dropdown.classList.add('hidden');
|
||||
container.style.zIndex = '';
|
||||
}
|
||||
|
||||
// Trigger HTMX
|
||||
nativeSelect.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
});
|
||||
|
||||
// Initial UI refresh to match server state
|
||||
refreshUI();
|
||||
}
|
||||
|
||||
// Run on load and HTMX swaps
|
||||
if (window.htmx) {
|
||||
htmx.onLoad(function (content) {
|
||||
if (!content) return;
|
||||
const selects = content.querySelectorAll ? content.querySelectorAll('.custom-select-container') : [];
|
||||
selects.forEach(initSelect);
|
||||
if (content.classList && content.classList.contains('custom-select-container')) {
|
||||
initSelect(content);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
document.querySelectorAll('.custom-select-container').forEach(initSelect);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -15,11 +15,9 @@
|
||||
<span>Copy SQL</span>
|
||||
</button>
|
||||
|
||||
<div class="overflow-auto" style="max-height: 80vh;">
|
||||
<div class="mermaid" style="opacity: 0;" _="on load
|
||||
mermaid.init(undefined, this)
|
||||
set me.style.opacity to '1'">
|
||||
{{ mermaid_code }}
|
||||
<div class="overflow-auto border rounded-xl bg-slate-50 p-4" style="max-height: 80vh;">
|
||||
<div class="flex justify-center">
|
||||
<img src="/static/img/schema.svg" alt="Database Schema Diagram" class="max-w-full h-auto">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -46,7 +46,9 @@
|
||||
_="on htmx:afterRequest toggle .hidden on #show-add-tag-form-btn then toggle .hidden on me then set me.tag_name.value to ''">
|
||||
{# Hide form, show button, clear input after submit #}
|
||||
|
||||
<input type="hidden" name="person_id" value="{{ person_id | default('', true) }}">
|
||||
{% if person_id %}
|
||||
<input type="hidden" name="person_id" value="{{ person_id }}">
|
||||
{% endif %}
|
||||
<input type="hidden" name="current_filter" value="{{ request.query_string.decode() | default('', true) }}">
|
||||
{# Pass
|
||||
context
|
||||
|
||||
@@ -21,19 +21,13 @@
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="w-full">
|
||||
<select name="exercise_id"
|
||||
class="block appearance-none w-full bg-gray-200 border border-gray-200 text-gray-700 py-3 px-4 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
|
||||
_="init js(me)
|
||||
tail.select(me, {
|
||||
search: true,
|
||||
placeholder: 'Filter exercises',
|
||||
})
|
||||
end">
|
||||
{% for exercise in exercises|default([], true) %}
|
||||
<option value="{{ exercise.exercise_id }}" {% if exercise.exercise_id==exercise_id %}selected{% endif
|
||||
%}>{{ exercise.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='exercise_id',
|
||||
options=exercises|default([], true),
|
||||
multiple=false,
|
||||
search=true,
|
||||
placeholder='Filter exercises')
|
||||
}}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
@@ -34,24 +34,15 @@
|
||||
</label>
|
||||
<div class="relative">
|
||||
<div class="w-full">
|
||||
<select multiple name="tag_id"
|
||||
hx-post="{{ url_for('tags.add_tag_to_workout', workout_id=workout_id) }}"
|
||||
hx-target="#tag-wrapper-w-{{ workout_id }}"
|
||||
class="block appearance-none w-full bg-gray-200 border border-gray-200 text-gray-700 py-3 px-4 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
|
||||
_="init js(me)
|
||||
tail.select(me, {
|
||||
search: true,
|
||||
multiple: true,
|
||||
placeholder: 'Select tags',
|
||||
})
|
||||
end">
|
||||
{% for tag in tags %}
|
||||
<option value="{{ tag.tag_id }}" {% if tag.is_selected %}selected{% endif %}>
|
||||
{{
|
||||
tag.tag_name
|
||||
}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='tag_id',
|
||||
options=tags,
|
||||
multiple=true,
|
||||
search=true,
|
||||
placeholder='Select tags',
|
||||
hx_post=url_for('tags.add_tag_to_workout', workout_id=workout_id),
|
||||
hx_target='#tag-wrapper-w-' + workout_id|string)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,14 +12,21 @@
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<select name="view" hx-get="{{ url_for('calendar.get_calendar', person_id=person_id) }}"
|
||||
hx-target="#container" hx-push-url="true" _="init js(me) tail.select(me, {}) end"
|
||||
class="h-10 invisible">
|
||||
<option value="month">Month</option>
|
||||
<option value="year">Year</option>
|
||||
<option value="notes">Notes</option>
|
||||
<option value="overview" selected>Overview</option>
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='view',
|
||||
options=[
|
||||
{'id': 'month', 'name': 'Month'},
|
||||
{'id': 'year', 'name': 'Year'},
|
||||
{'id': 'notes', 'name': 'Notes'},
|
||||
{'id': 'overview', 'name': 'Overview', 'selected': true}
|
||||
],
|
||||
multiple=false,
|
||||
search=false,
|
||||
placeholder='View',
|
||||
hx_get=url_for('calendar.get_calendar', person_id=person_id),
|
||||
hx_target='#container',
|
||||
hx_push_url=true)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,22 +37,17 @@
|
||||
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-city">
|
||||
Exercises
|
||||
</label>
|
||||
<select data-te-select-filter="true" data-te-select-size="lg" name="exercise_id"
|
||||
class="bg-gray-50 border border-gray-300 " multiple
|
||||
hx-get="{{ url_for('person_overview', person_id=person_id) }}"
|
||||
hx-include="[name='exercise_id'],[name='min_date'],[name='max_date'],[name='graph_axis']"
|
||||
hx-target="#container" hx-push-url="true" _="init js(me)
|
||||
tail.select(me, {
|
||||
multiple: true,
|
||||
search: true,
|
||||
placeholder: 'Filter exercises',
|
||||
})
|
||||
end">
|
||||
{% for exercise in exercises %}
|
||||
<option value="{{ exercise.id }}" {% if exercise.selected %}selected{% endif %}>
|
||||
{{ exercise.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='exercise_id',
|
||||
options=exercises,
|
||||
multiple=true,
|
||||
search=true,
|
||||
placeholder='Filter exercises',
|
||||
hx_get=url_for('person_overview', person_id=person_id),
|
||||
hx_include="[name='exercise_id'],[name='min_date'],[name='max_date'],[name='graph_axis']",
|
||||
hx_target='#container',
|
||||
hx_push_url=true)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full md:w-1/3 px-2 md:px-3 mb-6 md:mb-0">
|
||||
|
||||
@@ -97,17 +97,14 @@
|
||||
{# Nested Template for a single exercise row within a session #}
|
||||
<template id="exercise-row-template">
|
||||
<div class="exercise-row flex items-center space-x-2">
|
||||
{# Wrapper div for tail.select - Added position: relative #}
|
||||
<div class="flex-grow relative">
|
||||
{# Note: tail.select might hide the original select, apply styling to its container if needed #}
|
||||
<select name="exercises_SESSION_INDEX_PLACEHOLDER" required class="exercise-select-original w-full"> {#
|
||||
Keep original select for form submission, tail.select will enhance it #}
|
||||
<option value="">Select Exercise...</option>
|
||||
{# Render options directly here using the exercises passed to the main template #}
|
||||
{% for exercise in exercises %}
|
||||
<option value="{{ exercise.exercise_id }}">{{ exercise.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ render_partial('partials/custom_select.html',
|
||||
name='exercises_SESSION_INDEX_PLACEHOLDER',
|
||||
options=exercises,
|
||||
multiple=false,
|
||||
search=true,
|
||||
placeholder='Select Exercise...')
|
||||
}}
|
||||
</div>
|
||||
<button type="button" class="remove-exercise-btn text-red-500 hover:text-red-700 flex-shrink-0"
|
||||
title="Remove Exercise">
|
||||
@@ -182,33 +179,14 @@
|
||||
// --- Function to add an exercise select row to a specific session ---
|
||||
function addExerciseSelect(container, sessionIndex) {
|
||||
const newExFragment = exerciseTemplate.content.cloneNode(true);
|
||||
const originalSelect = newExFragment.querySelector('.exercise-select-original');
|
||||
const nativeSelect = newExFragment.querySelector('.native-select');
|
||||
const removeBtn = newExFragment.querySelector('.remove-exercise-btn');
|
||||
|
||||
if (!originalSelect || !removeBtn) {
|
||||
console.error("Failed to find original select or remove button in exercise template clone.");
|
||||
return;
|
||||
if (nativeSelect) {
|
||||
nativeSelect.name = `exercises_${sessionIndex}`;
|
||||
}
|
||||
|
||||
// Set the name attribute correctly for getlist
|
||||
originalSelect.name = `exercises_${sessionIndex}`;
|
||||
|
||||
container.appendChild(newExFragment);
|
||||
|
||||
// Find the newly added select element *after* appending
|
||||
const newSelectElement = container.querySelector('.exercise-row:last-child .exercise-select-original');
|
||||
|
||||
// Initialize tail.select on the new element
|
||||
if (newSelectElement && typeof tail !== 'undefined' && tail.select) {
|
||||
tail.select(newSelectElement, {
|
||||
search: true,
|
||||
placeholder: 'Select Exercise...',
|
||||
// classNames: "w-full" // Add tailwind classes if needed for the generated dropdown
|
||||
});
|
||||
} else {
|
||||
console.warn("tail.select library not found or new select element not found. Using standard select.");
|
||||
}
|
||||
|
||||
// Attach remove listener to the new exercise row's button
|
||||
attachExerciseRemoveListener(removeBtn);
|
||||
}
|
||||
@@ -274,7 +252,7 @@
|
||||
}
|
||||
|
||||
// Update names for the exercise selects within this session
|
||||
const exerciseSelects = row.querySelectorAll('.exercise-select-original'); // Target original selects
|
||||
const exerciseSelects = row.querySelectorAll('.native-select'); // Target hidden selects
|
||||
exerciseSelects.forEach(select => {
|
||||
select.name = `exercises_${newIndex}`;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user