From 4011a4bf8a392500cf2b6325a145f1db484da7cb Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 10:29:05 -0600 Subject: [PATCH 01/60] add tailwind --- frontend/package-lock.json | 1018 +++++++++++++++++++++++++++- frontend/package.json | 3 + frontend/postcss.config.js | 6 + frontend/src/app.css | 3 + frontend/src/routes/+layout.svelte | 10 + frontend/src/routes/+page.svelte | 3 +- frontend/tailwind.config.js | 8 + 7 files changed, 1048 insertions(+), 3 deletions(-) create mode 100644 frontend/postcss.config.js create mode 100644 frontend/src/app.css create mode 100644 frontend/src/routes/+layout.svelte create mode 100644 frontend/tailwind.config.js diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f137a6bce7..e68bf36666 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,20 +14,36 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@types/eslint": "^9.6.0", + "autoprefixer": "^10.4.20", "eslint": "^9.0.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.36.0", "globals": "^15.0.0", + "postcss": "^8.4.47", "prettier": "^3.1.1", "prettier-plugin-svelte": "^3.1.2", "svelte": "^5.0.0-next.1", "svelte-check": "^4.0.0", + "tailwindcss": "^3.4.13", "typescript": "^5.0.0", "typescript-eslint": "^8.0.0", "vite": "^5.0.3", "vitest": "^2.0.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -595,6 +611,53 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -686,6 +749,17 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@playwright/test": { "version": "1.47.2", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", @@ -1480,6 +1554,13 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -1507,6 +1588,13 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1534,6 +1622,44 @@ "node": ">=12" } }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -1588,6 +1714,39 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -1608,6 +1767,37 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001663", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", + "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chai": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", @@ -1710,6 +1900,16 @@ "dev": true, "license": "MIT" }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1807,6 +2007,41 @@ "dev": true, "license": "MIT" }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz", + "integrity": "sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -1846,6 +2081,16 @@ "@esbuild/win32-x64": "0.21.5" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2248,6 +2493,37 @@ "dev": true, "license": "ISC" }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -2263,6 +2539,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -2273,6 +2559,27 @@ "node": "*" } }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2286,6 +2593,32 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "15.9.0", "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", @@ -2330,6 +2663,19 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2391,6 +2737,22 @@ "node": ">=8" } }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2401,6 +2763,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -2451,6 +2823,32 @@ "dev": true, "license": "ISC" }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2536,6 +2934,13 @@ "node": ">=10" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", @@ -2576,6 +2981,13 @@ "get-func-name": "^2.0.1" } }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/magic-string": { "version": "0.30.11", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", @@ -2636,7 +3048,17 @@ "node": "*" } }, - "node_modules/mri": { + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", @@ -2663,6 +3085,18 @@ "dev": true, "license": "MIT" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -2689,6 +3123,13 @@ "dev": true, "license": "MIT" }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2699,6 +3140,36 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2749,6 +3220,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2782,6 +3260,30 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", @@ -2821,6 +3323,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/playwright": { "version": "1.47.2", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", @@ -2882,6 +3404,44 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, "node_modules/postcss-load-config": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", @@ -2912,6 +3472,32 @@ } } }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-safe-parser": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", @@ -2970,6 +3556,13 @@ "node": ">=4" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3038,6 +3631,16 @@ ], "license": "MIT" }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3064,6 +3667,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3215,6 +3836,19 @@ "dev": true, "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sirv": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", @@ -3254,6 +3888,76 @@ "dev": true, "license": "MIT" }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3267,6 +3971,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3280,6 +3998,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3293,6 +4034,19 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/svelte": { "version": "5.0.0-next.258", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.0.0-next.258.tgz", @@ -3418,6 +4172,106 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/tailwindcss": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3425,6 +4279,29 @@ "dev": true, "license": "MIT" }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", @@ -3516,6 +4393,13 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3567,6 +4451,37 @@ } } }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3808,6 +4723,107 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 20535997cb..d3cf7e3ac3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,14 +21,17 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@types/eslint": "^9.6.0", + "autoprefixer": "^10.4.20", "eslint": "^9.0.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.36.0", "globals": "^15.0.0", + "postcss": "^8.4.47", "prettier": "^3.1.1", "prettier-plugin-svelte": "^3.1.2", "svelte": "^5.0.0-next.1", "svelte-check": "^4.0.0", + "tailwindcss": "^3.4.13", "typescript": "^5.0.0", "typescript-eslint": "^8.0.0", "vite": "^5.0.3", diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000000..2e7af2b7f1 --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/src/app.css b/frontend/src/app.css new file mode 100644 index 0000000000..b5c61c9567 --- /dev/null +++ b/frontend/src/app.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte new file mode 100644 index 0000000000..352d286739 --- /dev/null +++ b/frontend/src/routes/+layout.svelte @@ -0,0 +1,10 @@ + + +
+ {@render children()} +
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 5982b0ae37..98ce1d09cb 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,2 +1 @@ -

Welcome to SvelteKit

-

Visit kit.svelte.dev to read the documentation

+
hello world
\ No newline at end of file diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js new file mode 100644 index 0000000000..bfe0bc28f2 --- /dev/null +++ b/frontend/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{html,js,svelte,ts}'], + theme: { + extend: {} + }, + plugins: [] +}; From f46c568b00f28e4c5cd34f158215aedaa6879909 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 10:51:38 -0600 Subject: [PATCH 02/60] format code w/ prettier --- frontend/postcss.config.js | 10 +++++----- frontend/src/routes/+layout.svelte | 2 +- frontend/src/routes/+page.svelte | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index 2e7af2b7f1..0f7721681d 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -1,6 +1,6 @@ export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 352d286739..e48bc059f0 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -6,5 +6,5 @@
- {@render children()} + {@render children()}
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 98ce1d09cb..4c389ace55 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1 +1 @@ -
hello world
\ No newline at end of file +
hello world
From 6a05ff70fc60599d21f9f0838639e02e7b6f621c Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 11:04:37 -0600 Subject: [PATCH 03/60] add shadcn --- frontend/components.json | 14 ++++ frontend/package-lock.json | 157 +++++++++--------------------------- frontend/package.json | 7 +- frontend/src/app.css | 75 +++++++++++++++++ frontend/src/lib/utils.ts | 62 ++++++++++++++ frontend/tailwind.config.js | 64 ++++++++++++++- 6 files changed, 257 insertions(+), 122 deletions(-) create mode 100644 frontend/components.json create mode 100644 frontend/src/lib/utils.ts diff --git a/frontend/components.json b/frontend/components.json new file mode 100644 index 0000000000..59f9db1d55 --- /dev/null +++ b/frontend/components.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "style": "new-york", + "tailwind": { + "config": "tailwind.config.js", + "css": "src/app.css", + "baseColor": "neutral" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils" + }, + "typescript": true +} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e68bf36666..a63e80d699 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7,6 +7,11 @@ "": { "name": "frontend", "version": "0.0.1", + "dependencies": { + "clsx": "^2.1.1", + "tailwind-merge": "^2.5.2", + "tailwind-variants": "^0.2.1" + }, "devDependencies": { "@playwright/test": "^1.28.1", "@sveltejs/adapter-auto": "^3.0.0", @@ -35,7 +40,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -615,7 +619,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -633,7 +636,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -646,7 +648,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -662,7 +663,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -677,7 +677,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -687,7 +686,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -697,14 +695,12 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -715,7 +711,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -729,7 +724,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -739,7 +733,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -753,7 +746,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -1532,7 +1524,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1542,7 +1533,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1558,14 +1548,12 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -1579,7 +1567,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -1592,7 +1579,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -1674,14 +1660,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1705,7 +1689,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -1771,7 +1754,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -1846,7 +1828,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -1871,7 +1852,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -1880,11 +1860,19 @@ "node": ">= 6" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1897,14 +1885,12 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -1931,7 +1917,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -1946,7 +1931,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -2011,21 +1995,18 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, "license": "Apache-2.0" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, "license": "MIT" }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, "license": "MIT" }, "node_modules/electron-to-chromium": { @@ -2039,7 +2020,6 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, "license": "MIT" }, "node_modules/esbuild": { @@ -2364,7 +2344,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2381,7 +2360,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -2408,7 +2386,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -2446,7 +2423,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -2497,7 +2473,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", @@ -2528,7 +2503,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -2543,7 +2517,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2563,7 +2536,6 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -2584,7 +2556,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -2597,7 +2568,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -2607,7 +2577,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -2667,7 +2636,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -2728,7 +2696,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -2741,7 +2708,6 @@ "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -2757,7 +2723,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2767,7 +2732,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2777,7 +2741,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -2790,7 +2753,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -2820,14 +2782,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -2843,7 +2803,6 @@ "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -2928,7 +2887,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -2938,7 +2896,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, "license": "MIT" }, "node_modules/locate-character": { @@ -2985,7 +2942,6 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, "license": "ISC" }, "node_modules/magic-string": { @@ -3002,7 +2958,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -3012,7 +2967,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -3026,7 +2980,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -3052,7 +3005,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -3089,7 +3041,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0", @@ -3101,7 +3052,6 @@ "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, "funding": [ { "type": "github", @@ -3134,7 +3084,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3154,7 +3103,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3164,7 +3112,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -3224,7 +3171,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/parent-module": { @@ -3254,7 +3200,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3264,14 +3209,12 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -3305,7 +3248,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -3327,7 +3269,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3337,7 +3278,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -3379,7 +3319,6 @@ "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3408,7 +3347,6 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", @@ -3426,7 +3364,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" @@ -3476,7 +3413,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3546,7 +3482,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -3560,7 +3495,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, "license": "MIT" }, "node_modules/prelude-ls": { @@ -3614,7 +3548,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -3635,7 +3568,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^2.3.0" @@ -3645,7 +3577,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -3658,7 +3589,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -3671,7 +3601,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", @@ -3699,7 +3628,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -3753,7 +3681,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -3810,7 +3737,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -3823,7 +3749,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3840,7 +3765,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -3868,7 +3792,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -3892,7 +3815,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -3911,7 +3833,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -3926,14 +3847,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3946,7 +3865,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -3962,7 +3880,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -3976,7 +3893,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -4002,7 +3918,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -4038,7 +3953,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4172,11 +4086,36 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/tailwind-merge": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz", + "integrity": "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwind-variants": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-0.2.1.tgz", + "integrity": "sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw==", + "license": "MIT", + "dependencies": { + "tailwind-merge": "^2.2.0" + }, + "engines": { + "node": ">=16.x", + "pnpm": ">=7.x" + }, + "peerDependencies": { + "tailwindcss": "*" + } + }, "node_modules/tailwindcss": { "version": "3.4.13", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", - "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -4214,7 +4153,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4250,7 +4188,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, "license": "MIT", "engines": { "node": ">=14" @@ -4263,7 +4200,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -4283,7 +4219,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0" @@ -4293,7 +4228,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -4361,7 +4295,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -4397,7 +4330,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, "license": "Apache-2.0" }, "node_modules/type-check": { @@ -4496,7 +4428,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/vite": { @@ -4684,7 +4615,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -4727,7 +4657,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -4746,7 +4675,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -4764,14 +4692,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -4786,7 +4712,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4799,7 +4724,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4812,7 +4736,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" diff --git a/frontend/package.json b/frontend/package.json index d3cf7e3ac3..9883e04ab9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -37,5 +37,10 @@ "vite": "^5.0.3", "vitest": "^2.0.0" }, - "type": "module" + "type": "module", + "dependencies": { + "clsx": "^2.1.1", + "tailwind-merge": "^2.5.2", + "tailwind-variants": "^0.2.1" + } } diff --git a/frontend/src/app.css b/frontend/src/app.css index b5c61c9567..8524b77712 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,3 +1,78 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 0% 3.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 0% 83.1%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts new file mode 100644 index 0000000000..88712453a4 --- /dev/null +++ b/frontend/src/lib/utils.ts @@ -0,0 +1,62 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import { cubicOut } from "svelte/easing"; +import type { TransitionConfig } from "svelte/transition"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +type FlyAndScaleParams = { + y?: number; + x?: number; + start?: number; + duration?: number; +}; + +export const flyAndScale = ( + node: Element, + params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 } +): TransitionConfig => { + const style = getComputedStyle(node); + const transform = style.transform === "none" ? "" : style.transform; + + const scaleConversion = ( + valueA: number, + scaleA: [number, number], + scaleB: [number, number] + ) => { + const [minA, maxA] = scaleA; + const [minB, maxB] = scaleB; + + const percentage = (valueA - minA) / (maxA - minA); + const valueB = percentage * (maxB - minB) + minB; + + return valueB; + }; + + const styleToString = ( + style: Record + ): string => { + return Object.keys(style).reduce((str, key) => { + if (style[key] === undefined) return str; + return str + `${key}:${style[key]};`; + }, ""); + }; + + return { + duration: params.duration ?? 200, + delay: 0, + css: (t) => { + const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]); + const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]); + const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]); + + return styleToString({ + transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`, + opacity: t + }); + }, + easing: cubicOut + }; +}; \ No newline at end of file diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index bfe0bc28f2..fa1cb36b68 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,8 +1,64 @@ +import { fontFamily } from "tailwindcss/defaultTheme"; + /** @type {import('tailwindcss').Config} */ -export default { - content: ['./src/**/*.{html,js,svelte,ts}'], +const config = { + darkMode: ["class"], + content: ["./src/**/*.{html,js,svelte,ts}"], + safelist: ["dark"], theme: { - extend: {} + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px" + } + }, + extend: { + colors: { + border: "hsl(var(--border) / )", + input: "hsl(var(--input) / )", + ring: "hsl(var(--ring) / )", + background: "hsl(var(--background) / )", + foreground: "hsl(var(--foreground) / )", + primary: { + DEFAULT: "hsl(var(--primary) / )", + foreground: "hsl(var(--primary-foreground) / )" + }, + secondary: { + DEFAULT: "hsl(var(--secondary) / )", + foreground: "hsl(var(--secondary-foreground) / )" + }, + destructive: { + DEFAULT: "hsl(var(--destructive) / )", + foreground: "hsl(var(--destructive-foreground) / )" + }, + muted: { + DEFAULT: "hsl(var(--muted) / )", + foreground: "hsl(var(--muted-foreground) / )" + }, + accent: { + DEFAULT: "hsl(var(--accent) / )", + foreground: "hsl(var(--accent-foreground) / )" + }, + popover: { + DEFAULT: "hsl(var(--popover) / )", + foreground: "hsl(var(--popover-foreground) / )" + }, + card: { + DEFAULT: "hsl(var(--card) / )", + foreground: "hsl(var(--card-foreground) / )" + } + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)" + }, + fontFamily: { + sans: [...fontFamily.sans] + } + } }, - plugins: [] }; + +export default config; From 2a9aad1483d2caa9cb80ad7f58c6d5faa5dd35ee Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 11:07:18 -0600 Subject: [PATCH 04/60] add shadcn button --- frontend/package-lock.json | 139 ++++++++++++++++-- frontend/package.json | 1 + .../lib/components/ui/button/button.svelte | 25 ++++ .../src/lib/components/ui/button/index.ts | 50 +++++++ 4 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 frontend/src/lib/components/ui/button/button.svelte create mode 100644 frontend/src/lib/components/ui/button/index.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a63e80d699..5f5fdbc5bb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend", "version": "0.0.1", "dependencies": { + "bits-ui": "^0.21.15", "clsx": "^2.1.1", "tailwind-merge": "^2.5.2", "tailwind-variants": "^0.2.1" @@ -52,7 +53,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -587,6 +587,31 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", + "license": "MIT" + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -615,6 +640,15 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@internationalized/date": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.5.tgz", + "integrity": "sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1095,6 +1129,15 @@ "vite": "^5.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", @@ -1117,7 +1160,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { @@ -1474,7 +1516,6 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1497,7 +1538,6 @@ "version": "1.4.13", "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz", "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==", - "dev": true, "license": "MIT", "peerDependencies": { "acorn": ">=8.9.0" @@ -1592,7 +1632,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -1650,7 +1689,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -1674,6 +1712,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bits-ui": { + "version": "0.21.15", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.21.15.tgz", + "integrity": "sha512-+m5WSpJnFdCcNdXSTIVC1WYBozipO03qRh03GFWgrdxoHiolCfwW71EYG4LPCWYPG6KcTZV0Cj6iHSiZ7cdKdg==", + "license": "MIT", + "dependencies": { + "@internationalized/date": "^3.5.1", + "@melt-ui/svelte": "0.76.2", + "nanoid": "^5.0.5" + }, + "funding": { + "url": "https://github.com/sponsors/huntabyte" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.118" + } + }, + "node_modules/bits-ui/node_modules/@melt-ui/svelte": { + "version": "0.76.2", + "resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.76.2.tgz", + "integrity": "sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.3.1", + "@floating-ui/dom": "^1.4.5", + "@internationalized/date": "^3.5.0", + "dequal": "^2.0.3", + "focus-trap": "^7.5.2", + "nanoid": "^5.0.4" + }, + "peerDependencies": { + "svelte": ">=3 <5" + } + }, + "node_modules/bits-ui/node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1984,6 +2074,15 @@ "node": ">=0.10.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/devalue": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.0.0.tgz", @@ -2245,7 +2344,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==", - "dev": true, "license": "MIT" }, "node_modules/espree": { @@ -2283,7 +2381,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.2.2.tgz", "integrity": "sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", @@ -2469,6 +2566,15 @@ "dev": true, "license": "ISC" }, + "node_modules/focus-trap": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.0.tgz", + "integrity": "sha512-1td0l3pMkWJLFipobUcGaf+5DTY4PLDDrcqoSaKP8ediO/CoWCCYk/fT/Y2A4e6TNB+Sh6clRJCjOPPnKoNHnQ==", + "license": "MIT", + "dependencies": { + "tabbable": "^6.2.0" + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -2772,7 +2878,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "*" @@ -2902,7 +3007,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "dev": true, "license": "MIT" }, "node_modules/locate-path": { @@ -2948,7 +3052,6 @@ "version": "0.30.11", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -3965,7 +4068,6 @@ "version": "5.0.0-next.258", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.0.0-next.258.tgz", "integrity": "sha512-kkIXBIhYRaywZtch4bWfdVlE4uq1SYYHQo05qNlUJzyWemRyVA5jpoA3ezzXN5+ph6rf40IVRHE5jyr7ic6Hdg==", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -4086,6 +4188,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "license": "MIT" + }, "node_modules/tailwind-merge": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz", @@ -4332,6 +4440,12 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "license": "Apache-2.0" }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4774,7 +4888,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", - "dev": true, "license": "MIT" } } diff --git a/frontend/package.json b/frontend/package.json index 9883e04ab9..0fa8bbce30 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -39,6 +39,7 @@ }, "type": "module", "dependencies": { + "bits-ui": "^0.21.15", "clsx": "^2.1.1", "tailwind-merge": "^2.5.2", "tailwind-variants": "^0.2.1" diff --git a/frontend/src/lib/components/ui/button/button.svelte b/frontend/src/lib/components/ui/button/button.svelte new file mode 100644 index 0000000000..86827f32d3 --- /dev/null +++ b/frontend/src/lib/components/ui/button/button.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/frontend/src/lib/components/ui/button/index.ts b/frontend/src/lib/components/ui/button/index.ts new file mode 100644 index 0000000000..f0f4612434 --- /dev/null +++ b/frontend/src/lib/components/ui/button/index.ts @@ -0,0 +1,50 @@ +import type { Button as ButtonPrimitive } from "bits-ui"; +import { type VariantProps, tv } from "tailwind-variants"; +import Root from "./button.svelte"; + +const buttonVariants = tv({ + base: "focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50", + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90 shadow", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm", + outline: + "border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +type Variant = VariantProps["variant"]; +type Size = VariantProps["size"]; + +type Props = ButtonPrimitive.Props & { + variant?: Variant; + size?: Size; +}; + +type Events = ButtonPrimitive.Events; + +export { + Root, + type Props, + type Events, + // + Root as Button, + type Props as ButtonProps, + type Events as ButtonEvents, + buttonVariants, +}; From f96c4fe090efd6daaf1edab4574b675c990cce1f Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 11:07:28 -0600 Subject: [PATCH 05/60] use button on home page for simple counter --- frontend/src/routes/+page.svelte | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 4c389ace55..2cabfe5d39 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1 +1,11 @@ -
hello world
+ + + From 570ba5dd2c32dc443340dac2180e2d3b6f83463b Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 11:11:26 -0600 Subject: [PATCH 06/60] npm run format --- frontend/components.json | 2 +- frontend/src/app.css | 144 +++++++++--------- .../lib/components/ui/button/button.svelte | 14 +- .../src/lib/components/ui/button/index.ts | 43 +++--- frontend/src/lib/utils.ts | 24 ++- frontend/tailwind.config.js | 58 +++---- 6 files changed, 139 insertions(+), 146 deletions(-) diff --git a/frontend/components.json b/frontend/components.json index 59f9db1d55..47ab5b7ec3 100644 --- a/frontend/components.json +++ b/frontend/components.json @@ -11,4 +11,4 @@ "utils": "$lib/utils" }, "typescript": true -} \ No newline at end of file +} diff --git a/frontend/src/app.css b/frontend/src/app.css index 8524b77712..5cd56fc4cf 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,78 +1,78 @@ @tailwind base; @tailwind components; @tailwind utilities; - + @layer base { - :root { - --background: 0 0% 100%; - --foreground: 0 0% 3.9%; - - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - - --destructive: 0 72.2% 50.6%; - --destructive-foreground: 0 0% 98%; - - --ring: 0 0% 3.9%; - - --radius: 0.5rem; - } - - .dark { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - - --ring: 0 0% 83.1%; - } + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 0% 3.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 0% 83.1%; + } } - + @layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} \ No newline at end of file + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/frontend/src/lib/components/ui/button/button.svelte b/frontend/src/lib/components/ui/button/button.svelte index 86827f32d3..f578a575ba 100644 --- a/frontend/src/lib/components/ui/button/button.svelte +++ b/frontend/src/lib/components/ui/button/button.svelte @@ -1,15 +1,15 @@ diff --git a/frontend/src/lib/components/ui/button/index.ts b/frontend/src/lib/components/ui/button/index.ts index f0f4612434..1d095eb1f6 100644 --- a/frontend/src/lib/components/ui/button/index.ts +++ b/frontend/src/lib/components/ui/button/index.ts @@ -1,35 +1,34 @@ -import type { Button as ButtonPrimitive } from "bits-ui"; -import { type VariantProps, tv } from "tailwind-variants"; -import Root from "./button.svelte"; +import type { Button as ButtonPrimitive } from 'bits-ui'; +import { type VariantProps, tv } from 'tailwind-variants'; +import Root from './button.svelte'; const buttonVariants = tv({ - base: "focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50", + base: 'focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50', variants: { variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90 shadow", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm", + default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow', + destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm', outline: - "border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm", - secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", + 'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline' }, size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-md px-3 text-xs", - lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", - }, + default: 'h-9 px-4 py-2', + sm: 'h-8 rounded-md px-3 text-xs', + lg: 'h-10 rounded-md px-8', + icon: 'h-9 w-9' + } }, defaultVariants: { - variant: "default", - size: "default", - }, + variant: 'default', + size: 'default' + } }); -type Variant = VariantProps["variant"]; -type Size = VariantProps["size"]; +type Variant = VariantProps['variant']; +type Size = VariantProps['size']; type Props = ButtonPrimitive.Props & { variant?: Variant; @@ -46,5 +45,5 @@ export { Root as Button, type Props as ButtonProps, type Events as ButtonEvents, - buttonVariants, + buttonVariants }; diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index 88712453a4..eba19d86ab 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -1,7 +1,7 @@ -import { type ClassValue, clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; -import { cubicOut } from "svelte/easing"; -import type { TransitionConfig } from "svelte/transition"; +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; +import { cubicOut } from 'svelte/easing'; +import type { TransitionConfig } from 'svelte/transition'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); @@ -19,13 +19,9 @@ export const flyAndScale = ( params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 } ): TransitionConfig => { const style = getComputedStyle(node); - const transform = style.transform === "none" ? "" : style.transform; + const transform = style.transform === 'none' ? '' : style.transform; - const scaleConversion = ( - valueA: number, - scaleA: [number, number], - scaleB: [number, number] - ) => { + const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => { const [minA, maxA] = scaleA; const [minB, maxB] = scaleB; @@ -35,13 +31,11 @@ export const flyAndScale = ( return valueB; }; - const styleToString = ( - style: Record - ): string => { + const styleToString = (style: Record): string => { return Object.keys(style).reduce((str, key) => { if (style[key] === undefined) return str; return str + `${key}:${style[key]};`; - }, ""); + }, ''); }; return { @@ -59,4 +53,4 @@ export const flyAndScale = ( }, easing: cubicOut }; -}; \ No newline at end of file +}; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index fa1cb36b68..38fb24ef2a 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,64 +1,64 @@ -import { fontFamily } from "tailwindcss/defaultTheme"; +import { fontFamily } from 'tailwindcss/defaultTheme'; /** @type {import('tailwindcss').Config} */ const config = { - darkMode: ["class"], - content: ["./src/**/*.{html,js,svelte,ts}"], - safelist: ["dark"], + darkMode: ['class'], + content: ['./src/**/*.{html,js,svelte,ts}'], + safelist: ['dark'], theme: { container: { center: true, - padding: "2rem", + padding: '2rem', screens: { - "2xl": "1400px" + '2xl': '1400px' } }, extend: { colors: { - border: "hsl(var(--border) / )", - input: "hsl(var(--input) / )", - ring: "hsl(var(--ring) / )", - background: "hsl(var(--background) / )", - foreground: "hsl(var(--foreground) / )", + border: 'hsl(var(--border) / )', + input: 'hsl(var(--input) / )', + ring: 'hsl(var(--ring) / )', + background: 'hsl(var(--background) / )', + foreground: 'hsl(var(--foreground) / )', primary: { - DEFAULT: "hsl(var(--primary) / )", - foreground: "hsl(var(--primary-foreground) / )" + DEFAULT: 'hsl(var(--primary) / )', + foreground: 'hsl(var(--primary-foreground) / )' }, secondary: { - DEFAULT: "hsl(var(--secondary) / )", - foreground: "hsl(var(--secondary-foreground) / )" + DEFAULT: 'hsl(var(--secondary) / )', + foreground: 'hsl(var(--secondary-foreground) / )' }, destructive: { - DEFAULT: "hsl(var(--destructive) / )", - foreground: "hsl(var(--destructive-foreground) / )" + DEFAULT: 'hsl(var(--destructive) / )', + foreground: 'hsl(var(--destructive-foreground) / )' }, muted: { - DEFAULT: "hsl(var(--muted) / )", - foreground: "hsl(var(--muted-foreground) / )" + DEFAULT: 'hsl(var(--muted) / )', + foreground: 'hsl(var(--muted-foreground) / )' }, accent: { - DEFAULT: "hsl(var(--accent) / )", - foreground: "hsl(var(--accent-foreground) / )" + DEFAULT: 'hsl(var(--accent) / )', + foreground: 'hsl(var(--accent-foreground) / )' }, popover: { - DEFAULT: "hsl(var(--popover) / )", - foreground: "hsl(var(--popover-foreground) / )" + DEFAULT: 'hsl(var(--popover) / )', + foreground: 'hsl(var(--popover-foreground) / )' }, card: { - DEFAULT: "hsl(var(--card) / )", - foreground: "hsl(var(--card-foreground) / )" + DEFAULT: 'hsl(var(--card) / )', + foreground: 'hsl(var(--card-foreground) / )' } }, borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)" + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' }, fontFamily: { sans: [...fontFamily.sans] } } - }, + } }; export default config; From 2b2bddc0a41105ccca7d06e4837164ec0126c87c Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 11:26:23 -0600 Subject: [PATCH 07/60] modify typescript rules to ignore specific errors in shadcn components --- frontend/eslint.config.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 62dbd03c71..a17fd44c9b 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -25,6 +25,15 @@ export default [ parserOptions: { parser: ts.parser } + }, + rules: { + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^\\$\\$(Props|Events|Slots|Generic)$' + } + ] } }, { From 53e759ebfc3988f1370a793a6ad4c5e66eb0da40 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 24 Sep 2024 13:06:17 -0600 Subject: [PATCH 08/60] configure tailwind typography --- frontend/package-lock.json | 45 ++++++++++++++++++++++++++++++ frontend/package.json | 1 + frontend/src/routes/+layout.svelte | 4 ++- frontend/tailwind.config.js | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5f5fdbc5bb..c6301f4729 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,6 +19,7 @@ "@sveltejs/adapter-static": "^3.0.5", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", + "@tailwindcss/typography": "^0.5.15", "@types/eslint": "^9.6.0", "autoprefixer": "^10.4.20", "eslint": "^9.0.0", @@ -1138,6 +1139,36 @@ "tslib": "^2.4.0" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz", + "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" + } + }, + "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", @@ -3025,6 +3056,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 0fa8bbce30..a4bdce8ca5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "@sveltejs/adapter-static": "^3.0.5", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", + "@tailwindcss/typography": "^0.5.15", "@types/eslint": "^9.6.0", "autoprefixer": "^10.4.20", "eslint": "^9.0.0", diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index e48bc059f0..e1773f5545 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -6,5 +6,7 @@
- {@render children()} +
+ {@render children()} +
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 38fb24ef2a..5a6bde4dd6 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,7 +1,9 @@ import { fontFamily } from 'tailwindcss/defaultTheme'; +import typography from '@tailwindcss/typography'; /** @type {import('tailwindcss').Config} */ const config = { + plugins: [typography], darkMode: ['class'], content: ['./src/**/*.{html,js,svelte,ts}'], safelist: ['dark'], From 71895c7d8b289188c0caeeee4051d5961fb517dd Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Wed, 25 Sep 2024 09:20:02 -0600 Subject: [PATCH 09/60] basic dark mode config --- frontend/src/routes/+layout.svelte | 7 +++++-- frontend/src/routes/+page.svelte | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index e1773f5545..04bddcecf7 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -3,10 +3,13 @@ import type { Snippet } from 'svelte'; let { children }: { children: Snippet } = $props(); + const darkMode = true;
-
- {@render children()} +
+
+ {@render children()} +
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 2cabfe5d39..ebef627909 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -4,6 +4,7 @@ let count = $state(0); +

hello world

+ + + +
+ +
From 201dc8e32a9a44a468762784bb2659554d877ea8 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 26 Sep 2024 16:04:51 -0600 Subject: [PATCH 17/60] install echarts --- frontend/package-lock.json | 48 ++++++++++++++++++++++++++++++++++++++ frontend/package.json | 2 ++ 2 files changed, 50 insertions(+) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c6301f4729..bc1d38038d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,8 +8,10 @@ "name": "frontend", "version": "0.0.1", "dependencies": { + "@types/echarts": "^4.9.22", "bits-ui": "^0.21.15", "clsx": "^2.1.1", + "echarts": "^5.5.1", "tailwind-merge": "^2.5.2", "tailwind-variants": "^0.2.1" }, @@ -1176,6 +1178,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/echarts": { + "version": "4.9.22", + "resolved": "https://registry.npmjs.org/@types/echarts/-/echarts-4.9.22.tgz", + "integrity": "sha512-7Fo6XdWpoi8jxkwP7BARUOM7riq8bMhmsCtSG8gzUcJmFhLo387tihoBYS/y5j7jl3PENT5RxeWZdN9RiwO7HQ==", + "license": "MIT", + "dependencies": { + "@types/zrender": "*" + } + }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -1200,6 +1211,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/zrender": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/zrender/-/zrender-4.0.6.tgz", + "integrity": "sha512-1jZ9bJn2BsfmYFPBHtl5o3uV+ILejAtGrDcYSpT4qaVKEI/0YY+arw3XHU04Ebd8Nca3SQ7uNcLaqiL+tTFVMg==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", @@ -2139,6 +2156,22 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "license": "MIT" }, + "node_modules/echarts": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.5.1.tgz", + "integrity": "sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.6.0" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/electron-to-chromium": { "version": "1.5.28", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz", @@ -4934,6 +4967,21 @@ "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", "license": "MIT" + }, + "node_modules/zrender": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz", + "integrity": "sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" } } } diff --git a/frontend/package.json b/frontend/package.json index d81de7511c..aeb99921ab 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -43,8 +43,10 @@ }, "type": "module", "dependencies": { + "@types/echarts": "^4.9.22", "bits-ui": "^0.21.15", "clsx": "^2.1.1", + "echarts": "^5.5.1", "tailwind-merge": "^2.5.2", "tailwind-variants": "^0.2.1" } From 251a052d80a5fe12bd4ab1bc91a958b107b20bdd Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 26 Sep 2024 16:04:58 -0600 Subject: [PATCH 18/60] fix type issues --- frontend/src/lib/components/EChart/EChart.svelte | 6 +++--- frontend/src/routes/observability/+page.svelte | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/src/lib/components/EChart/EChart.svelte b/frontend/src/lib/components/EChart/EChart.svelte index 15d1902566..e6d007817b 100644 --- a/frontend/src/lib/components/EChart/EChart.svelte +++ b/frontend/src/lib/components/EChart/EChart.svelte @@ -1,9 +1,9 @@ + + + + + + + + Close + + + diff --git a/frontend/src/lib/components/ui/sheet/sheet-description.svelte b/frontend/src/lib/components/ui/sheet/sheet-description.svelte new file mode 100644 index 0000000000..3d3d49403d --- /dev/null +++ b/frontend/src/lib/components/ui/sheet/sheet-description.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/frontend/src/lib/components/ui/sheet/sheet-footer.svelte b/frontend/src/lib/components/ui/sheet/sheet-footer.svelte new file mode 100644 index 0000000000..329304a8f2 --- /dev/null +++ b/frontend/src/lib/components/ui/sheet/sheet-footer.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/frontend/src/lib/components/ui/sheet/sheet-header.svelte b/frontend/src/lib/components/ui/sheet/sheet-header.svelte new file mode 100644 index 0000000000..434c29c978 --- /dev/null +++ b/frontend/src/lib/components/ui/sheet/sheet-header.svelte @@ -0,0 +1,13 @@ + + +
+ +
diff --git a/frontend/src/lib/components/ui/sheet/sheet-overlay.svelte b/frontend/src/lib/components/ui/sheet/sheet-overlay.svelte new file mode 100644 index 0000000000..bc59703d06 --- /dev/null +++ b/frontend/src/lib/components/ui/sheet/sheet-overlay.svelte @@ -0,0 +1,21 @@ + + + diff --git a/frontend/src/lib/components/ui/sheet/sheet-portal.svelte b/frontend/src/lib/components/ui/sheet/sheet-portal.svelte new file mode 100644 index 0000000000..7f62f70905 --- /dev/null +++ b/frontend/src/lib/components/ui/sheet/sheet-portal.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/frontend/src/lib/components/ui/sheet/sheet-title.svelte b/frontend/src/lib/components/ui/sheet/sheet-title.svelte new file mode 100644 index 0000000000..271c31f574 --- /dev/null +++ b/frontend/src/lib/components/ui/sheet/sheet-title.svelte @@ -0,0 +1,16 @@ + + + + + From 6d3a1e956452f4f50e56954e5373795f2b55261d Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Fri, 27 Sep 2024 08:42:24 -0600 Subject: [PATCH 20/60] use resizeobserver on my echart --- frontend/src/lib/components/EChart/EChart.svelte | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/components/EChart/EChart.svelte b/frontend/src/lib/components/EChart/EChart.svelte index e6d007817b..03398c552c 100644 --- a/frontend/src/lib/components/EChart/EChart.svelte +++ b/frontend/src/lib/components/EChart/EChart.svelte @@ -7,6 +7,7 @@ let chartDiv: HTMLDivElement; let chartInstance: echarts.ECharts; + let resizeObserver: ResizeObserver; const dispatch = createEventDispatcher(); // Function to initialize the chart @@ -33,13 +34,19 @@ onMount(() => { initChart(); - window.addEventListener('resize', handleResize); + + resizeObserver = new ResizeObserver(handleResize); + if (chartDiv) { + resizeObserver.observe(chartDiv); + } }); onDestroy(() => { if (chartInstance) { chartInstance.dispose(); - window.removeEventListener('resize', handleResize); + } + if (resizeObserver) { + resizeObserver.disconnect(); } }); From 7462ed42ecb1555766d508c4c8b9e07fc840544d Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Fri, 27 Sep 2024 08:46:33 -0600 Subject: [PATCH 21/60] refactor echart for clarity --- .../src/lib/components/EChart/EChart.svelte | 58 +++++-------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/frontend/src/lib/components/EChart/EChart.svelte b/frontend/src/lib/components/EChart/EChart.svelte index 03398c552c..fe9526d9de 100644 --- a/frontend/src/lib/components/EChart/EChart.svelte +++ b/frontend/src/lib/components/EChart/EChart.svelte @@ -4,65 +4,39 @@ import type { EChartOption, ECElementEvent } from 'echarts'; const { option }: { option: EChartOption } = $props(); + const dispatch = createEventDispatcher(); let chartDiv: HTMLDivElement; let chartInstance: echarts.ECharts; let resizeObserver: ResizeObserver; - const dispatch = createEventDispatcher(); - // Function to initialize the chart - const initChart = () => { - if (chartDiv) { - if (chartInstance) { - chartInstance.dispose(); - } - chartInstance = echarts.init(chartDiv); - chartInstance.setOption(option); + function initChart() { + if (!chartDiv) return; - chartInstance.on('click', function (params: ECElementEvent) { - dispatch('click', params); - }); - } - }; + chartInstance?.dispose(); + chartInstance = echarts.init(chartDiv); + chartInstance.setOption(option); + chartInstance.on('click', (params: ECElementEvent) => dispatch('click', params)); + } - // Function to resize the chart - const handleResize = () => { - if (chartInstance) { - chartInstance.resize(); - } - }; + function handleResize() { + chartInstance?.resize(); + } onMount(() => { initChart(); - resizeObserver = new ResizeObserver(handleResize); - if (chartDiv) { - resizeObserver.observe(chartDiv); - } + resizeObserver.observe(chartDiv); }); onDestroy(() => { - if (chartInstance) { - chartInstance.dispose(); - } - if (resizeObserver) { - resizeObserver.disconnect(); - } + chartInstance?.dispose(); + resizeObserver?.disconnect(); }); - // Watch for changes to option prop and update the chart accordingly $effect(() => { - if (chartInstance) { - chartInstance.setOption(option, true); // true indicates that the update should be merged - } + chartInstance?.setOption(option, true); }); -
- - +
From b2270f6d6ba0f8e559104ed2df87f4c4d09820c3 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Fri, 27 Sep 2024 09:14:26 -0600 Subject: [PATCH 22/60] use proper type --- frontend/src/lib/components/EChart/EChart.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/lib/components/EChart/EChart.svelte b/frontend/src/lib/components/EChart/EChart.svelte index fe9526d9de..8e492de762 100644 --- a/frontend/src/lib/components/EChart/EChart.svelte +++ b/frontend/src/lib/components/EChart/EChart.svelte @@ -1,7 +1,7 @@ + +
+
+ {@render main()} +
+ {#if sidebarOpen} +
+ + +
+ {@render sidebar()} +
+
+ {/if} +
From db3250820959408ba3f2b740b6a918d8aa0ef7f3 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Fri, 27 Sep 2024 12:39:38 -0600 Subject: [PATCH 25/60] use SplitView to show heatmap/sidebar --- .../src/routes/observability/+page.svelte | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/frontend/src/routes/observability/+page.svelte b/frontend/src/routes/observability/+page.svelte index f23a20cd1b..68e35d96e0 100644 --- a/frontend/src/routes/observability/+page.svelte +++ b/frontend/src/routes/observability/+page.svelte @@ -1,5 +1,6 @@
- - + +
-
- -
+ + {#snippet main()} +
+ +
+ {/snippet} + + {#snippet sidebar()} +
+
Cell Details
+
Information about the clicked cell
+ {#if clickedCellData} +
+

X: {Array.isArray(clickedCellData) ? clickedCellData[0] : ''}

+

Y: {Array.isArray(clickedCellData) ? clickedCellData[1] : ''}

+

Value: {Array.isArray(clickedCellData) ? clickedCellData[2] : ''}

+
+ {/if} +
+ {/snippet} +
From fffd0edab595e24ab6e2968acdb1850ac742c87d Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 12:37:44 -0600 Subject: [PATCH 26/60] add table component --- .../lib/components/ui/table/table-body.svelte | 13 +++++++++++ .../components/ui/table/table-caption.svelte | 13 +++++++++++ .../lib/components/ui/table/table-cell.svelte | 21 +++++++++++++++++ .../components/ui/table/table-footer.svelte | 13 +++++++++++ .../lib/components/ui/table/table-head.svelte | 19 +++++++++++++++ .../components/ui/table/table-header.svelte | 14 +++++++++++ .../lib/components/ui/table/table-row.svelte | 23 +++++++++++++++++++ .../src/lib/components/ui/table/table.svelte | 15 ++++++++++++ 8 files changed, 131 insertions(+) create mode 100644 frontend/src/lib/components/ui/table/table-body.svelte create mode 100644 frontend/src/lib/components/ui/table/table-caption.svelte create mode 100644 frontend/src/lib/components/ui/table/table-cell.svelte create mode 100644 frontend/src/lib/components/ui/table/table-footer.svelte create mode 100644 frontend/src/lib/components/ui/table/table-head.svelte create mode 100644 frontend/src/lib/components/ui/table/table-header.svelte create mode 100644 frontend/src/lib/components/ui/table/table-row.svelte create mode 100644 frontend/src/lib/components/ui/table/table.svelte diff --git a/frontend/src/lib/components/ui/table/table-body.svelte b/frontend/src/lib/components/ui/table/table-body.svelte new file mode 100644 index 0000000000..f2109d676d --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-body.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/frontend/src/lib/components/ui/table/table-caption.svelte b/frontend/src/lib/components/ui/table/table-caption.svelte new file mode 100644 index 0000000000..b838270867 --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-caption.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/frontend/src/lib/components/ui/table/table-cell.svelte b/frontend/src/lib/components/ui/table/table-cell.svelte new file mode 100644 index 0000000000..4df6326020 --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-cell.svelte @@ -0,0 +1,21 @@ + + +[role=checkbox]]:translate-y-[2px]", + className + )} + {...$$restProps} + on:click + on:keydown +> + + diff --git a/frontend/src/lib/components/ui/table/table-footer.svelte b/frontend/src/lib/components/ui/table/table-footer.svelte new file mode 100644 index 0000000000..c6c1570d90 --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-footer.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/frontend/src/lib/components/ui/table/table-head.svelte b/frontend/src/lib/components/ui/table/table-head.svelte new file mode 100644 index 0000000000..636499426a --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-head.svelte @@ -0,0 +1,19 @@ + + +[role=checkbox]]:translate-y-[2px]", + className + )} + {...$$restProps} +> + + diff --git a/frontend/src/lib/components/ui/table/table-header.svelte b/frontend/src/lib/components/ui/table/table-header.svelte new file mode 100644 index 0000000000..a3e59eed87 --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-header.svelte @@ -0,0 +1,14 @@ + + + + + + diff --git a/frontend/src/lib/components/ui/table/table-row.svelte b/frontend/src/lib/components/ui/table/table-row.svelte new file mode 100644 index 0000000000..731c5d5a61 --- /dev/null +++ b/frontend/src/lib/components/ui/table/table-row.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/frontend/src/lib/components/ui/table/table.svelte b/frontend/src/lib/components/ui/table/table.svelte new file mode 100644 index 0000000000..788d4ee335 --- /dev/null +++ b/frontend/src/lib/components/ui/table/table.svelte @@ -0,0 +1,15 @@ + + +
+ + +
+
From ea0cd3c8c1c57966e17a5b1e6828f09e3fdb91f6 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 12:51:45 -0600 Subject: [PATCH 27/60] index to export table elements --- frontend/src/lib/components/ui/table/index.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 frontend/src/lib/components/ui/table/index.ts diff --git a/frontend/src/lib/components/ui/table/index.ts b/frontend/src/lib/components/ui/table/index.ts new file mode 100644 index 0000000000..14695c8154 --- /dev/null +++ b/frontend/src/lib/components/ui/table/index.ts @@ -0,0 +1,28 @@ +import Root from "./table.svelte"; +import Body from "./table-body.svelte"; +import Caption from "./table-caption.svelte"; +import Cell from "./table-cell.svelte"; +import Footer from "./table-footer.svelte"; +import Head from "./table-head.svelte"; +import Header from "./table-header.svelte"; +import Row from "./table-row.svelte"; + +export { + Root, + Body, + Caption, + Cell, + Footer, + Head, + Header, + Row, + // + Root as Table, + Body as TableBody, + Caption as TableCaption, + Cell as TableCell, + Footer as TableFooter, + Head as TableHead, + Header as TableHeader, + Row as TableRow, +}; From fd3702be552e8e04f2c05bb9ef575f1b6904adf5 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 12:51:51 -0600 Subject: [PATCH 28/60] add basic api --- frontend/src/lib/api/api.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 frontend/src/lib/api/api.ts diff --git a/frontend/src/lib/api/api.ts b/frontend/src/lib/api/api.ts new file mode 100644 index 0000000000..afd129d830 --- /dev/null +++ b/frontend/src/lib/api/api.ts @@ -0,0 +1,19 @@ +import { error } from '@sveltejs/kit'; + +const base = 'http://localhost:9000/api/v1'; + +async function send({ method, path }: { method: string; path: string }) { + const opts = { method, headers: {} }; + + const res = await fetch(`${base}/${path}`, opts); + if (res.ok) { + const text = await res.text(); + return text ? JSON.parse(text) : {}; + } + + error(res.status); +} + +export function get(path: string) { + return send({ method: 'GET', path }); +} From 7eb1bea7035241599544c08423144555e9a3ed47 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 12:51:56 -0600 Subject: [PATCH 29/60] type for model --- frontend/src/lib/types/Model.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 frontend/src/lib/types/Model.ts diff --git a/frontend/src/lib/types/Model.ts b/frontend/src/lib/types/Model.ts new file mode 100644 index 0000000000..b50c0fee78 --- /dev/null +++ b/frontend/src/lib/types/Model.ts @@ -0,0 +1,10 @@ +export type Model = { + name: string; + id: string; + online: boolean; + production: boolean; + team: string; + modelType: string; + createTime: number; + lastUpdated: number; +}; From 00f380716daca34732ff307ea4a89c7687ce8730 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 12:52:32 -0600 Subject: [PATCH 30/60] format code --- frontend/src/lib/components/ui/table/index.ts | 18 +++++++++--------- .../lib/components/ui/table/table-body.svelte | 8 ++++---- .../components/ui/table/table-caption.svelte | 8 ++++---- .../lib/components/ui/table/table-cell.svelte | 8 ++++---- .../components/ui/table/table-footer.svelte | 8 ++++---- .../lib/components/ui/table/table-head.svelte | 8 ++++---- .../components/ui/table/table-header.svelte | 8 ++++---- .../lib/components/ui/table/table-row.svelte | 10 +++++----- .../src/lib/components/ui/table/table.svelte | 8 ++++---- 9 files changed, 42 insertions(+), 42 deletions(-) diff --git a/frontend/src/lib/components/ui/table/index.ts b/frontend/src/lib/components/ui/table/index.ts index 14695c8154..99239aeead 100644 --- a/frontend/src/lib/components/ui/table/index.ts +++ b/frontend/src/lib/components/ui/table/index.ts @@ -1,11 +1,11 @@ -import Root from "./table.svelte"; -import Body from "./table-body.svelte"; -import Caption from "./table-caption.svelte"; -import Cell from "./table-cell.svelte"; -import Footer from "./table-footer.svelte"; -import Head from "./table-head.svelte"; -import Header from "./table-header.svelte"; -import Row from "./table-row.svelte"; +import Root from './table.svelte'; +import Body from './table-body.svelte'; +import Caption from './table-caption.svelte'; +import Cell from './table-cell.svelte'; +import Footer from './table-footer.svelte'; +import Head from './table-head.svelte'; +import Header from './table-header.svelte'; +import Row from './table-row.svelte'; export { Root, @@ -24,5 +24,5 @@ export { Footer as TableFooter, Head as TableHead, Header as TableHeader, - Row as TableRow, + Row as TableRow }; diff --git a/frontend/src/lib/components/ui/table/table-body.svelte b/frontend/src/lib/components/ui/table/table-body.svelte index f2109d676d..47bf50e85a 100644 --- a/frontend/src/lib/components/ui/table/table-body.svelte +++ b/frontend/src/lib/components/ui/table/table-body.svelte @@ -1,13 +1,13 @@ - + diff --git a/frontend/src/lib/components/ui/table/table-caption.svelte b/frontend/src/lib/components/ui/table/table-caption.svelte index b838270867..0a655a69c7 100644 --- a/frontend/src/lib/components/ui/table/table-caption.svelte +++ b/frontend/src/lib/components/ui/table/table-caption.svelte @@ -1,13 +1,13 @@ - + diff --git a/frontend/src/lib/components/ui/table/table-cell.svelte b/frontend/src/lib/components/ui/table/table-cell.svelte index 4df6326020..d284623ac8 100644 --- a/frontend/src/lib/components/ui/table/table-cell.svelte +++ b/frontend/src/lib/components/ui/table/table-cell.svelte @@ -1,16 +1,16 @@ [role=checkbox]]:translate-y-[2px]", + 'p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]', className )} {...$$restProps} diff --git a/frontend/src/lib/components/ui/table/table-footer.svelte b/frontend/src/lib/components/ui/table/table-footer.svelte index c6c1570d90..997119e895 100644 --- a/frontend/src/lib/components/ui/table/table-footer.svelte +++ b/frontend/src/lib/components/ui/table/table-footer.svelte @@ -1,13 +1,13 @@ - + diff --git a/frontend/src/lib/components/ui/table/table-head.svelte b/frontend/src/lib/components/ui/table/table-head.svelte index 636499426a..cb7ce2009f 100644 --- a/frontend/src/lib/components/ui/table/table-head.svelte +++ b/frontend/src/lib/components/ui/table/table-head.svelte @@ -1,16 +1,16 @@ [role=checkbox]]:translate-y-[2px]", + 'text-muted-foreground h-10 px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]', className )} {...$$restProps} diff --git a/frontend/src/lib/components/ui/table/table-header.svelte b/frontend/src/lib/components/ui/table/table-header.svelte index a3e59eed87..980b2a74b8 100644 --- a/frontend/src/lib/components/ui/table/table-header.svelte +++ b/frontend/src/lib/components/ui/table/table-header.svelte @@ -1,14 +1,14 @@ - + diff --git a/frontend/src/lib/components/ui/table/table-row.svelte b/frontend/src/lib/components/ui/table/table-row.svelte index 731c5d5a61..ad9e636cd6 100644 --- a/frontend/src/lib/components/ui/table/table-row.svelte +++ b/frontend/src/lib/components/ui/table/table-row.svelte @@ -1,18 +1,18 @@ - import type { HTMLTableAttributes } from "svelte/elements"; - import { cn } from "$lib/utils.js"; + import type { HTMLTableAttributes } from 'svelte/elements'; + import { cn } from '$lib/utils.js'; type $$Props = HTMLTableAttributes; - let className: $$Props["class"] = undefined; + let className: $$Props['class'] = undefined; export { className as class };
- +
From dc76a037f069e7d32cbece9e368f84e970ec6ea3 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 13:04:23 -0600 Subject: [PATCH 31/60] add ModelsResponse --- frontend/src/lib/types/Model.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/lib/types/Model.ts b/frontend/src/lib/types/Model.ts index b50c0fee78..d8361601f4 100644 --- a/frontend/src/lib/types/Model.ts +++ b/frontend/src/lib/types/Model.ts @@ -8,3 +8,8 @@ export type Model = { createTime: number; lastUpdated: number; }; + +export type ModelsResponse = { + offset: number; + items: Model[]; +}; From 998956aa0859a2497b67a3475e7f728d80f1bce1 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 13:07:47 -0600 Subject: [PATCH 32/60] render a basic table with models data --- frontend/src/routes/+page.server.ts | 9 +++++++ frontend/src/routes/+page.svelte | 42 ++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 frontend/src/routes/+page.server.ts diff --git a/frontend/src/routes/+page.server.ts b/frontend/src/routes/+page.server.ts new file mode 100644 index 0000000000..c686a4a9db --- /dev/null +++ b/frontend/src/routes/+page.server.ts @@ -0,0 +1,9 @@ +import type { PageServerLoad } from './$types'; +import type { ModelsResponse } from '$lib/types/Model'; +import * as api from '$lib/api/api'; + +export const load: PageServerLoad = async (): Promise<{ models: ModelsResponse }> => { + return { + models: await api.get('models') + }; +}; diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index ebef627909..05666b0d06 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,12 +1,36 @@ - -

hello world

- + + + + + Name + Team + + + + {#each models as model} + + + + {model.name} + + + {model.team} + + {/each} + +
Models
From 7ab1d5d6dcf5d88eca98c181ce8214a733e3fca1 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 13:07:55 -0600 Subject: [PATCH 33/60] change route structure --- frontend/src/routes/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 05666b0d06..e4a8142b5d 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -25,7 +25,7 @@ {#each models as model} - + {model.name} From 79268dfc9075d0e77ab3cb4a23fc6a8676296e58 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 13:25:28 -0600 Subject: [PATCH 34/60] add preview of timeseries data --- frontend/src/lib/types/Model.ts | 11 +++++++++++ .../models/[slug]/observability/+page.server.ts | 14 ++++++++++++++ .../models/[slug]/observability/+page.svelte | 8 ++++++++ 3 files changed, 33 insertions(+) create mode 100644 frontend/src/routes/models/[slug]/observability/+page.server.ts create mode 100644 frontend/src/routes/models/[slug]/observability/+page.svelte diff --git a/frontend/src/lib/types/Model.ts b/frontend/src/lib/types/Model.ts index d8361601f4..b6346ae8dc 100644 --- a/frontend/src/lib/types/Model.ts +++ b/frontend/src/lib/types/Model.ts @@ -13,3 +13,14 @@ export type ModelsResponse = { offset: number; items: Model[]; }; + +export type TimeSeriesItem = { + value: number; + ts: number; + label: string | null; +}; + +export type TimeSeriesResponse = { + id: string; + items: TimeSeriesItem[]; +}; diff --git a/frontend/src/routes/models/[slug]/observability/+page.server.ts b/frontend/src/routes/models/[slug]/observability/+page.server.ts new file mode 100644 index 0000000000..9f499bf751 --- /dev/null +++ b/frontend/src/routes/models/[slug]/observability/+page.server.ts @@ -0,0 +1,14 @@ +import type { PageServerLoad } from './$types'; +import * as api from '$lib/api/api'; +import type { TimeSeriesResponse } from '$lib/types/Model'; + +export const load: PageServerLoad = async ({ + params +}): Promise<{ timeseries: TimeSeriesResponse }> => { + // todo pass params dynamically + return { + timeseries: await api.get( + `model/${params.slug}/timeseries?startTs=1725926400000&endTs=1726106400000&offset=10h&algorithm=psi` + ) + }; +}; diff --git a/frontend/src/routes/models/[slug]/observability/+page.svelte b/frontend/src/routes/models/[slug]/observability/+page.svelte new file mode 100644 index 0000000000..a7d2c3b56c --- /dev/null +++ b/frontend/src/routes/models/[slug]/observability/+page.svelte @@ -0,0 +1,8 @@ + + +
Observability for Model {timeseries.id}
+ +
{JSON.stringify(timeseries, null, 2)}
From 8e9327c74f8581139ed1c12e86c441bbdd5b3db0 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 14:47:44 -0600 Subject: [PATCH 35/60] add avatar --- .../ui/avatar/avatar-fallback.svelte | 16 ++++++++++++++++ .../components/ui/avatar/avatar-image.svelte | 18 ++++++++++++++++++ .../src/lib/components/ui/avatar/avatar.svelte | 18 ++++++++++++++++++ frontend/src/lib/components/ui/avatar/index.ts | 13 +++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 frontend/src/lib/components/ui/avatar/avatar-fallback.svelte create mode 100644 frontend/src/lib/components/ui/avatar/avatar-image.svelte create mode 100644 frontend/src/lib/components/ui/avatar/avatar.svelte create mode 100644 frontend/src/lib/components/ui/avatar/index.ts diff --git a/frontend/src/lib/components/ui/avatar/avatar-fallback.svelte b/frontend/src/lib/components/ui/avatar/avatar-fallback.svelte new file mode 100644 index 0000000000..bb603de840 --- /dev/null +++ b/frontend/src/lib/components/ui/avatar/avatar-fallback.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/frontend/src/lib/components/ui/avatar/avatar-image.svelte b/frontend/src/lib/components/ui/avatar/avatar-image.svelte new file mode 100644 index 0000000000..95cf424671 --- /dev/null +++ b/frontend/src/lib/components/ui/avatar/avatar-image.svelte @@ -0,0 +1,18 @@ + + + diff --git a/frontend/src/lib/components/ui/avatar/avatar.svelte b/frontend/src/lib/components/ui/avatar/avatar.svelte new file mode 100644 index 0000000000..6f59cd66d3 --- /dev/null +++ b/frontend/src/lib/components/ui/avatar/avatar.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/frontend/src/lib/components/ui/avatar/index.ts b/frontend/src/lib/components/ui/avatar/index.ts new file mode 100644 index 0000000000..9585f8ad6b --- /dev/null +++ b/frontend/src/lib/components/ui/avatar/index.ts @@ -0,0 +1,13 @@ +import Root from './avatar.svelte'; +import Image from './avatar-image.svelte'; +import Fallback from './avatar-fallback.svelte'; + +export { + Root, + Image, + Fallback, + // + Root as Avatar, + Image as AvatarImage, + Fallback as AvatarFallback +}; From 1855d2e1665d4e761878f07df14ab00a7017482f Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 14:47:50 -0600 Subject: [PATCH 36/60] zipline logo --- frontend/static/logo.webp | Bin 0 -> 4360 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 frontend/static/logo.webp diff --git a/frontend/static/logo.webp b/frontend/static/logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..0f12637589a2e5af746cb0ccafa5abfe79374477 GIT binary patch literal 4360 zcmV+j5%=y=Nk&Eh5dZ*JMM6+kP&iEU5C8x#$G|ZV35RXlND?9i_hq*Kg69jaf{6Z4 zKy+sY*~}`=CsuGYXybKM8?FwG;I-pKgCllKxm>YPxnaSSH%uz8J2KU1;id9wQJ+3u zE$Zm`s@S3qwLvwisv;s9_WVW72X(SM$W8P%>YO!jP- z07tfMRnfv7F76UC|M3t~gznw1Ucqf7$&nln15RX55``9D{Qge>)R{p62oPrn0ED6d zhXNeHA$|gY+5T4`2;z#O=-63TaOY0G0B~L0Fsq3hV)rBgr~ttX1FUvG8;0~-Y?TA< zCo}tRjb+afu(HR|kh~vF1iW^KFaO2FybvemmO`>LO94#|(OF7@S!(kx(&U;Pu=ooA z1fi(#acl@TOCh~`R*KD182+~l0M`|^dL#sOPzQ#BwvC*IKkOgv4FD0Lz-=34%!jYg z2m);zEP!_?2@a|ikW|n^d4N!p=v(-UJ^5C z%qsw>vdAQ{xB|gTWY*T&%-Xgs?;QbV<}rFPYc%zJrw6c#4< z+Q%agLhEcg2x)Z$TC20@*0$|xPv*M6yvr52iWEtZ(E=T4Pzxay5P47N3i0-BIf4KX zU~{pJ$#{Tmdv#K*ZePF$Wa?*BB%k>2O_1_0RNyZK z{sPn~l$IF$#gVE0jRO9(4gRD#^tRyJWBeOS=7x~`#Zi$V6XJU~{lmLyd*{C%n`&07 zTOhyy4gi3S0T{q80AK(c0C3>|8~_6VE)0xg$$<;Na9DByTmVD%!(f1ea{&OOA;A)4 z1Hhr=#5g250|VS;$$3vK|0fy;t}14b$U0ES&km6u$&l-K|xX&g%k z&XkI zxB+aI0E=u&L$Lu%t`g8uGGQ>lH=tA$Q`%V)Ea^)yHw+02mblWmZZI08N-dUv4$ZTq zmg+63HLX;!)JoF=hUQsn$uu&J(CYN!CLe;@IOp~2a_%-`X%N5wV7S1I>ZtTl>6`ch z2q00Aheg5f7S4L}Ui9w$_dcK6CF4LDm24cC$vS2V0DQ)E2L3g0?)!H;vF$!#V5@8f z3f#ofO{JsKN2QM=72vOFJ=|%)X@g)BfB*!{m>eMS#JavY|1W63l#2q9;@VE|$RB5F z10))Ni5l{PjrrYR0|-R~0Icc{Va)H-*MJQ$S3_F-*4F?ITSTz3i)gF`E{NjlPR^L$ z>ucGJP}W!&+q>2WS_Bls0INX^qp2fiI52?G&=IrQGRAXsbi^e-n|f$eK3D3l_Pk0WJ-b-=oc+uGKPG<&l91O~uV$|xIP zWP!!avi&GAY^w7hhUNqHFjL0KRSq|dQj5}_TgJrFkO%+$hv@%DYznl4G492!)Q)ygTd)ojq}x=>dKqi8AS&pT($?~Z5vJKiGC}OM0TBDTt=6X(QtW#k z03^{dNp;wa{mx(dFGTd(^E?nKS#B4sZZp+?odHo>;ED=5wFSw6N#(W(1i(Bgo#$^= zSQ|MAsvH?7S`oB>L+yS-BPr1I!$}Q<>W2_-4WP9z$O^vjQbN259O!7KlahShp8^z>1A+$sjlx~78qMD z@!6uSdTCE{2n+x)-|7dQ{9GP={*n~R?tpd>ZGc%G$WMNK;*IkOfN|6Q{=RQ8(y|h& zI%DtVPkz-o5_-+?@eW8}7mO05oCE-XyIF%{oGwq#2E!_0q9&bWz_EOaUKH^(^p-ln zGVXem2yjQ%g(vvq|9`UYMU#W?EFy9pS?BZZvwPqD|K$p%4HF6kz-W_lFfZBfzkhEU zgQYRGfQ2~OQF)M)OMLlz-~4td49P0(?E(oo_}55?hMe<(yvRSlpO*j({qh;&XebB~ zDLFaD_y2#s{r#O1gRVa;?VzmVFwxT<+?Ee?s7#fAEK$cLRm-I8;l<(R1A_e5+y*Gt zs+4qza#lh|;~Cji-6uU128}F~bYRbco6~B^vt~z%B48aA4+;XJfRm^R3A?UcN`N6# z-ZtT+12zX1q$Z^23Jl=-bx8#R4qLsQk&jc{({rB%MLJD3ZK8l(Fxqrjxn|ES2~dQp z8VES9iAYB#P(TQv4%aIfC96`ZHeYRA6ZWgR}$*9zMhnOpD!d+`B~5Cy>lFjZ8c_l0a5M=QYq^3xyud| zgGFx}idm2wQq+B<@`|247XS?FX?r$b?u6YDG1s04@*odF^-T?zH&Q59G>Awd5X+67 znIQwo|GiQO0TgfnL?kk?lGd9Rj?NnE-1=Y=Y9b8RHDtkbn}YXA0hGWM5j9c2wUN4G ziKFU!;a6_j!z459Qg5pUD1uY}_e_U!OGM;4c#wwO(smheas86-g%Ch?4dXYfAPrY8 zO8|;ddhclkas-ay>uMTK!L$D+6N+d$z84aNvYGojtkLBrbO1o21GnuSaezTGdv$F4 zB{{E`(4J@3)1T{yBBAEn$^y`IK@LTCyL)*ZEQ-mk`g?NS^zUlu%LOHkP}Y-r;~Q5n z)$-S$v>?Gvb&MC}@Xqz*0Tg{#-?;mOji|USKB5EAp?d#w0*V*~A6@SLU{jKuEl4Sk zpL-6VXrBpCP}X@EL?ngh_~3iTM6pEeS9I-D@jj<8#E@n&zFN0f0S29d^TnUw5dUW* zB@$r1uXko79Yt85{k!rj_i|{~A|m2Qz)GLTCE?=w{`vf`r3C9>+M87r>8ai}3sT_35j8OAvdXSw z){R@I+Z(tULLd-D+!mOuGZ`)uiY>L=R&Pq&|467HE^z-F@4EIjLLHc?A^J^LZp3S9 zVMurdaI(g07z>JBnr0gmaPWFZ(t&6Z`P~V@c3(#q4L5&idN-#F`kjKvyGTti4xmW$ z=cEB@6!fi#I3gFc-L=Ysqkd)tiBd}378oycMW#hP_ws#To|*AfZ|xsV0D>SqB`%5g zm3mfDSk&#kdiZUbQ5Q!O6p;%Mm)=YTP|VA-ebaFOFlFj6@Z}kgmx4m8w!Jxi?ZALo z#^o{z7q^S?=|ro8jyU5-(U!2BTpk&jqDXWe1q4m(*INzCmF3m%KgFdJEllg|Q@0nO zFq7DxQXX+U4+^7dW*wLFw3;M>lBB)2Yk*>YngBo{^=Kq03mIyFi!uGYWeT0Z?XvHY zhMi4{J+pYkLt*Wb}0Ho3gMZ^(u&ZN1&?QmQ1Ga;)(2Ot1~ zNrYr1V`f3ILKnM&fP&iKK|m7eev39P_tB?5hf!tRP?c3J#=~O3CPGFoTUK@}s_58m zKsNCZ7k3+j-#%v*<>GT9B_Ms73!vDpiZsVUIYcC0K?l?vLmaiXRM7ySrXU<=MbdVO9N$5{2oK*cz`81GYRuhmt!OoO&sF94~B zjhNofBkPDL#;dpVLI>1?B7$H9W+bKn!&X{s4G1Wy!30on#3EU~wi@mRxe2_FECHnE zKZ zbR(fvb+g31y0yB8wtGvuOnW7_1nFltk&`>QY-0 zEC7NVW*3uK&I?ck)YO2&P{f_sM-bwGb8yu~Wo<_)V-Rr!xo&2$YS+30;r`LQ4^VpC z5UJEeoydveuA&QCTuMVkQqq{10K*ZU;XFX?P9($XiU}3*xR*QXK!H4v5`t89uu*{F zLOsPo>nCh?i0ER<4HJxn2jYb0Rf5?mA@9tu@hhbj03|0 zFn|REFkk@`OORWy+)%pvU(qm|mGZP?aTujZ;$Hp`rVjARou{wk$LRfiEb3%*{4E4f zzc~$u^5CntK)>?~3dR>bAP<_ql>1(N0E}?*E}0B^>jiEBAnMffP^sCj+smH^M49wF z^9U8pBt`RUM<9>v2^GKz4J2)BS z(lPC@vv3!3{U*51{#Tq=r|WPjGC>T{WEz(u>_xq4e}{4AksuSj{VOutR2Ys65y}|X zaUvK9Leo>$viC}gV2T|Nlj;vjuBYG_kYE&hx-DetG3(D<^1$+Us352nIqA}X0h7elnw=0eELNAH7~z!6JOO%WAmal#%=2gJuhi`|x`WWm9PY@ZWf0*}3VTouCQ$ ze(3S4!^|};#ZJRG1g@7Xn2iA}0D}wQi~|EO0Dc(H&?V=P-Pg_5i16)~UwwRR_n$4= zaWlg*ot=Qy0{_Kff!KEORVv!2}+e1M-v Date: Mon, 30 Sep 2024 16:53:44 -0400 Subject: [PATCH 37/60] Wire up Play frontend + server in docker setup --- docker-init/Dockerfile | 31 ++++++++++++++++------ docker-init/README.md | 14 +++++++--- docker-init/compose.yaml | 23 +++++++++++++--- docker-init/start.sh | 3 ++- hub/conf/application.conf | 24 +++++++---------- hub/conf/logback.xml | 55 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 30 deletions(-) create mode 100644 hub/conf/logback.xml diff --git a/docker-init/Dockerfile b/docker-init/Dockerfile index 62d27eedee..c33f397db6 100644 --- a/docker-init/Dockerfile +++ b/docker-init/Dockerfile @@ -1,19 +1,34 @@ +# Use the first Dockerfile to set up the build environment +FROM base_image:latest AS build_env + +# Copy your application source code +COPY . /app + +# Build the frontend and play app +RUN sbt dist + +# Start a new stage for the runtime image FROM amazoncorretto:17 # Install python deps -COPY requirements.txt . +COPY docker-init/requirements.txt . RUN yum install -y python3 +RUN yum install -y unzip RUN pip3 install --upgrade pip; pip3 install -r requirements.txt RUN mkdir -p /app -COPY generate_anomalous_data.py /app/ -COPY start.sh /start.sh +COPY docker-init/generate_anomalous_data.py /app/ +COPY docker-init/start.sh /start.sh RUN chmod +x /start.sh WORKDIR /app -ENV DYNAMO_ENDPOINT="http://localhost:8000" -ENV AWS_DEFAULT_REGION="fakeregion" -ENV AWS_ACCESS_KEY_ID="fakeaccesskey" -ENV AWS_SECRET_ACCESS_KEY="fakesecretkey" +# Copy frontend + play zipped dist and set up app directory structure +COPY --from=build_env /app/hub/target/universal/hub-0.1.0-SNAPSHOT.zip /app +RUN unzip hub-0.1.0-SNAPSHOT.zip -d /app/hub +RUN rm hub-0.1.0-SNAPSHOT.zip +RUN cp -r hub/hub-0.1.0-SNAPSHOT/* hub/. +RUN rm -rf hub/hub-0.1.0-SNAPSHOT + +EXPOSE 9000 -ENTRYPOINT ["/start.sh"] \ No newline at end of file +ENTRYPOINT ["/start.sh"] diff --git a/docker-init/README.md b/docker-init/README.md index ded0a89767..d50137db9a 100644 --- a/docker-init/README.md +++ b/docker-init/README.md @@ -2,10 +2,18 @@ This directory holds code to setup docker containers for dynamoDB, a spark master, and a spark worker. It also creates a container which contains a parquet table with example data containing anomolies. To start, run: -```docker-compose up``` +``` +$ cd chronon +$ docker-compose -f docker-init/compose.yaml up --build +... +app-1 | [info] 2024-09-30 20:47:56,448 [main] INFO play.api.Play - Application started (Prod) (no global state) +app-1 | [info] 2024-09-30 20:47:56,665 [main] INFO play.core.server.PekkoHttpServer - Listening for HTTP on /[0:0:0:0:0:0:0:0]:9000 +``` -To access the parquet table, from another terminal run: +You can now pull up the web-server on http://localhost:9000 + +You can also access the parquet anomaly data table. To do so, from another terminal run: ```docker-compose exec app bash``` -The parquet is available as data.parquet \ No newline at end of file +The parquet is available in the /app/data directory. diff --git a/docker-init/compose.yaml b/docker-init/compose.yaml index a512ef5b8d..eca82a5a71 100644 --- a/docker-init/compose.yaml +++ b/docker-init/compose.yaml @@ -1,4 +1,4 @@ -version: '3.8' +name: 'Hub - Monitoring Demo' services: dynamo: command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data" @@ -37,11 +37,28 @@ services: - SPARK_SSL_ENABLED=no - SPARK_USER=spark + base: + build: + context: .. + dockerfile: .github/image/Dockerfile + image: base_image:latest + app: - build: . - command: tail -F nothing + build: + context: .. + dockerfile: docker-init/Dockerfile environment: - DYNAMO_ENDPOINT=http://dynamo:8000 - AWS_DEFAULT_REGION=fakeregion - AWS_ACCESS_KEY_ID=fakeaccesskey - AWS_SECRET_ACCESS_KEY=fakesecretkey + - PLAY_HTTP_SECRET_KEY=my_fake_chronon_monitoring_hub_http_secret_key # needs to be long to make Play happy + - JAVA_OPTS=-Xms1g -Xmx1g + ports: + - '9000:9000' + healthcheck: + interval: 1s + retries: 5 + start_period: 60s + test: curl -sS --fail http://app:${APP_PORT:-9000}/api/v1/ping + timeout: 5s diff --git a/docker-init/start.sh b/docker-init/start.sh index 1a6fb74f97..463e86bab7 100644 --- a/docker-init/start.sh +++ b/docker-init/start.sh @@ -3,4 +3,5 @@ if ! python3 generate_anomalous_data.py; then echo "Error: Failed to generate anomalous data" >&2 exit 1 fi -exec "$@" \ No newline at end of file + +exec "./hub/bin/hub" diff --git a/hub/conf/application.conf b/hub/conf/application.conf index 815f0dfdb3..bf648f7c36 100644 --- a/hub/conf/application.conf +++ b/hub/conf/application.conf @@ -4,18 +4,12 @@ play.http.secret.key = ${?PLAY_HTTP_SECRET_KEY} play.i18n.langs = ["en"] -# Database configuration -# ~~~~~ -# You can declare as many datasources as you want. -# By convention, the default datasource is named `default` -# -# db.default.driver=org.h2.Driver -# db.default.url="jdbc:h2:mem:play" - -# Evolutions -# ~~~~~ -# You can disable evolutions if needed -# play.evolutions.enabled=false - -# You can disable evolutions for a specific datasource if necessary -# play.evolutions.db.default.enabled=false +# HTTP configuration +# Cap the request body accepted and stored in mem by Play +play.http.parser.maxMemoryBuffer=512K +play.http.parser.maxDiskBuffer=10M + +play.filters.hosts { + # Allow requests to localhost:9000 and "app" for now + allowed = ["localhost:9000", ".app"] +} diff --git a/hub/conf/logback.xml b/hub/conf/logback.xml new file mode 100644 index 0000000000..f8c219ca53 --- /dev/null +++ b/hub/conf/logback.xml @@ -0,0 +1,55 @@ + + + + + + + %coloredLevel %date{ISO8601} [%thread] %-5level %logger{36} - %msg%n%xException{10} + + + INFO + + + + + ${LOG_DIR}/chronon-hub.log + + ${LOG_DIR}/chronon-hub.%d{yyyy-dd-MM}-%i.log + + 100MB + + 10GB + + 30 + + + INFO + + + %date{ISO8601} [%thread] %-5level %logger{36} - %msg%n%xException + + + + + + + 512 + 0 + true + + + + + 512 + 0 + true + + + + + + + + + + \ No newline at end of file From c3f728aa2a911d5f120ad446bd47ead6fee18703 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 15:26:12 -0600 Subject: [PATCH 38/60] create a layout for the app w/ top and left bar --- frontend/src/routes/+layout.svelte | 56 ++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 0e3063cdf3..a5ec757eb8 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,10 +1,60 @@ -
- {@render children()} -
+
+ +
+
+ Zipline Logo +
+
+ {user.name} + + + + + + +
+
+ +
+ + + + +
+ {@render children()} +
+
+
From 578ed5bc8586902f9304c6bb636f509d86b5915b Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 15:28:46 -0600 Subject: [PATCH 39/60] move model code to model route --- frontend/src/routes/+page.svelte | 37 +------------------ .../src/routes/{ => models}/+page.server.ts | 0 frontend/src/routes/models/+page.svelte | 36 ++++++++++++++++++ 3 files changed, 37 insertions(+), 36 deletions(-) rename frontend/src/routes/{ => models}/+page.server.ts (100%) create mode 100644 frontend/src/routes/models/+page.svelte diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index e4a8142b5d..8e3f87428d 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,36 +1 @@ - - - - - - - Name - Team - - - - {#each models as model} - - - - {model.name} - - - {model.team} - - {/each} - -
Models
+
todo / route
diff --git a/frontend/src/routes/+page.server.ts b/frontend/src/routes/models/+page.server.ts similarity index 100% rename from frontend/src/routes/+page.server.ts rename to frontend/src/routes/models/+page.server.ts diff --git a/frontend/src/routes/models/+page.svelte b/frontend/src/routes/models/+page.svelte new file mode 100644 index 0000000000..e4a8142b5d --- /dev/null +++ b/frontend/src/routes/models/+page.svelte @@ -0,0 +1,36 @@ + + + + + + + Name + Team + + + + {#each models as model} + + + + {model.name} + + + {model.team} + + {/each} + +
Models
From a284edb6fbc5d5e003873db5e4b71251e415401e Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Mon, 30 Sep 2024 15:49:35 -0600 Subject: [PATCH 40/60] add loading indication on nav --- frontend/src/routes/+layout.svelte | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index a5ec757eb8..4d56d8bb60 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -4,6 +4,9 @@ import { Avatar, AvatarFallback, AvatarImage } from '$lib/components/ui/avatar'; import { Button } from '$lib/components/ui/button'; import { Person } from 'svelte-radix'; + import { navigating } from '$app/stores'; + import { expoOut } from 'svelte/easing'; + import { slide } from 'svelte/transition'; let { children }: { children: Snippet } = $props(); @@ -22,6 +25,12 @@
+ {#if $navigating} +
+ {/if}
From 7e7d69768c33a61b26d41339aab2698a5251aa12 Mon Sep 17 00:00:00 2001 From: Piyush Narang Date: Mon, 30 Sep 2024 18:35:45 -0400 Subject: [PATCH 41/60] Fix based on coder rabbit suggestions --- docker-init/Dockerfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docker-init/Dockerfile b/docker-init/Dockerfile index c33f397db6..b17a8b77b5 100644 --- a/docker-init/Dockerfile +++ b/docker-init/Dockerfile @@ -12,8 +12,7 @@ FROM amazoncorretto:17 # Install python deps COPY docker-init/requirements.txt . -RUN yum install -y python3 -RUN yum install -y unzip +RUN yum install -y python3 unzip RUN pip3 install --upgrade pip; pip3 install -r requirements.txt RUN mkdir -p /app @@ -24,10 +23,9 @@ WORKDIR /app # Copy frontend + play zipped dist and set up app directory structure COPY --from=build_env /app/hub/target/universal/hub-0.1.0-SNAPSHOT.zip /app -RUN unzip hub-0.1.0-SNAPSHOT.zip -d /app/hub -RUN rm hub-0.1.0-SNAPSHOT.zip -RUN cp -r hub/hub-0.1.0-SNAPSHOT/* hub/. -RUN rm -rf hub/hub-0.1.0-SNAPSHOT +RUN unzip hub-0.1.0-SNAPSHOT.zip -d /app/hub && \ + cp -r hub/hub-0.1.0-SNAPSHOT/* hub/. && \ + rm -rf hub/hub-0.1.0-SNAPSHOT hub-0.1.0-SNAPSHOT.zip EXPOSE 9000 From 557555bbdda49df8787dcd36ca81e22f376c78da Mon Sep 17 00:00:00 2001 From: Piyush Narang Date: Tue, 1 Oct 2024 10:28:47 -0400 Subject: [PATCH 42/60] Address feedback --- docker-init/compose.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-init/compose.yaml b/docker-init/compose.yaml index eca82a5a71..049e05f59b 100644 --- a/docker-init/compose.yaml +++ b/docker-init/compose.yaml @@ -1,4 +1,4 @@ -name: 'Hub - Monitoring Demo' +name: 'hub-monitoring-demo' services: dynamo: command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data" @@ -47,6 +47,8 @@ services: build: context: .. dockerfile: docker-init/Dockerfile + depends_on: + - base environment: - DYNAMO_ENDPOINT=http://dynamo:8000 - AWS_DEFAULT_REGION=fakeregion From 34da3a4a41d2557d55a73feaa42d790880554398 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 13:46:13 -0600 Subject: [PATCH 43/60] configure frontend to build using nodejs --- docker-init/compose.yaml | 25 ++++- docker-init/frontend/Dockerfile | 24 +++++ frontend/package-lock.json | 184 ++++++++++++++++++++++++++++++++ frontend/package.json | 1 + frontend/src/lib/api/api.ts | 2 +- frontend/src/routes/+layout.ts | 2 - frontend/svelte.config.js | 2 +- hub/conf/routes | 3 - 8 files changed, 232 insertions(+), 11 deletions(-) create mode 100644 docker-init/frontend/Dockerfile delete mode 100644 frontend/src/routes/+layout.ts diff --git a/docker-init/compose.yaml b/docker-init/compose.yaml index 049e05f59b..7c0986bca1 100644 --- a/docker-init/compose.yaml +++ b/docker-init/compose.yaml @@ -1,4 +1,4 @@ -name: 'hub-monitoring-demo' +name: "hub-monitoring-demo" services: dynamo: command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data" @@ -21,8 +21,8 @@ services: - SPARK_SSL_ENABLED=no - SPARK_USER=spark ports: - - '8080:8080' - - '7077:7077' + - "8080:8080" + - "7077:7077" spark-worker: image: bitnami/spark:3.5.2 @@ -57,10 +57,27 @@ services: - PLAY_HTTP_SECRET_KEY=my_fake_chronon_monitoring_hub_http_secret_key # needs to be long to make Play happy - JAVA_OPTS=-Xms1g -Xmx1g ports: - - '9000:9000' + - "9000:9000" healthcheck: interval: 1s retries: 5 start_period: 60s test: curl -sS --fail http://app:${APP_PORT:-9000}/api/v1/ping timeout: 5s + + # todo: set env variable + frontend: + build: + context: .. + dockerfile: docker-init/frontend/Dockerfile + depends_on: + - base + - app + ports: + - "3000:3000" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s diff --git a/docker-init/frontend/Dockerfile b/docker-init/frontend/Dockerfile new file mode 100644 index 0000000000..fb9000e89f --- /dev/null +++ b/docker-init/frontend/Dockerfile @@ -0,0 +1,24 @@ +FROM base_image:latest AS build_env + +# Copy the entire project directory into the container +COPY . /app + +# Install Node.js and npm +RUN apk add --update nodejs npm + +# Build the frontend using SBT +RUN sbt "project frontend" buildFrontend + +FROM node:18-alpine + +# Copy the built frontend from the previous stage to the new container +COPY --from=build_env app/frontend /app/frontend + +# Set the working directory for subsequent commands +WORKDIR /app/frontend + +# Expose port 3000 for the SvelteKit app +EXPOSE 3000 + +# Specify the command to run when the container starts +CMD ["node", "build/index.js"] diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1d79a5d434..2f3defc4a4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,6 +19,7 @@ "devDependencies": { "@playwright/test": "^1.28.1", "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-node": "^5.2.5", "@sveltejs/adapter-static": "^3.0.5", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", @@ -813,6 +814,152 @@ "dev": true, "license": "MIT" }, + "node_modules/@rollup/plugin-commonjs": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.0.tgz", + "integrity": "sha512-BJcu+a+Mpq476DMXG+hevgPSl56bkUoi88dKT8t3RyUp8kGuOh+2bU8Gs7zXDlu+fyZggnJ+iOBGrb/O1SorYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "fdir": "^6.1.1", + "is-reference": "1.2.1", + "magic-string": "^0.30.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-commonjs/node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", + "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.22.4", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", @@ -1050,6 +1197,22 @@ "@sveltejs/kit": "^2.0.0" } }, + "node_modules/@sveltejs/adapter-node": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-5.2.5.tgz", + "integrity": "sha512-FVeysFqeIlKFpDF1Oj38gby34f6uA9FuXnV330Z0RHmSyOR9JzJs70/nFKy1Ue3fWtf7S0RemOrP66Vr9Jcmew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-commonjs": "^28.0.0", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.3.0", + "rollup": "^4.9.5" + }, + "peerDependencies": { + "@sveltejs/kit": "^2.4.0" + } + }, "node_modules/@sveltejs/adapter-static": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.5.tgz", @@ -1212,6 +1375,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/zrender": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/zrender/-/zrender-4.0.6.tgz", @@ -2035,6 +2205,13 @@ "node": ">= 6" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2920,6 +3097,13 @@ "node": ">=0.10.0" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 3b2d5b2f7e..c40f5d5300 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "devDependencies": { "@playwright/test": "^1.28.1", "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-node": "^5.2.5", "@sveltejs/adapter-static": "^3.0.5", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", diff --git a/frontend/src/lib/api/api.ts b/frontend/src/lib/api/api.ts index afd129d830..5a988783e1 100644 --- a/frontend/src/lib/api/api.ts +++ b/frontend/src/lib/api/api.ts @@ -1,6 +1,6 @@ import { error } from '@sveltejs/kit'; -const base = 'http://localhost:9000/api/v1'; +const base = 'http://app:9000/api/v1'; // todo env variable async function send({ method, path }: { method: string; path: string }) { const opts = { method, headers: {} }; diff --git a/frontend/src/routes/+layout.ts b/frontend/src/routes/+layout.ts deleted file mode 100644 index 6d6325368d..0000000000 --- a/frontend/src/routes/+layout.ts +++ /dev/null @@ -1,2 +0,0 @@ -// This can be false if you're using a fallback (i.e. SPA mode) -export const prerender = true; diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js index f4db4888eb..d6a6445a8d 100644 --- a/frontend/svelte.config.js +++ b/frontend/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from '@sveltejs/adapter-static'; +import adapter from '@sveltejs/adapter-node'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */ diff --git a/hub/conf/routes b/hub/conf/routes index a8dcdf7c4e..58a12fc327 100644 --- a/hub/conf/routes +++ b/hub/conf/routes @@ -8,6 +8,3 @@ GET /api/v1/join/:name/timeseries controllers.TimeSeriesC GET /api/v1/join/:name/timeseries/slice/:sliceId controllers.TimeSeriesController.fetchJoinSlice(name: String, sliceId: String, startTs: Long, endTs: Long, metricType: String, metrics: String, offset: Option[String], algorithm: Option[String]) GET /api/v1/feature/:name/timeseries controllers.TimeSeriesController.fetchFeature(name: String, startTs: Long, endTs: Long, metricType: String, metrics: String, granularity: String, offset: Option[String], algorithm: Option[String]) GET /api/v1/feature/:name/timeseries/slice/:sliceId controllers.TimeSeriesController.fetchFeatureSlice(name: String, sliceId: String, startTs: Long, endTs: Long, metricType: String, metrics: String, granularity: String, offset: Option[String], algorithm: Option[String]) -# Serve SvelteKit static assets -GET / controllers.Assets.at(path="/public", file="index.html") -GET /*file controllers.Assets.at(path="/public", file) From 811cb658192c5e2aa91482002d8076456a45cbfb Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 14:45:28 -0600 Subject: [PATCH 44/60] create a custom build for docker to use that env file --- build.sbt | 3 ++- docker-init/compose.yaml | 1 - frontend/package-lock.json | 31 +++++++++++++++++++++++++++++++ frontend/package.json | 3 +++ frontend/src/lib/api/api.ts | 3 ++- frontend/vite.config.ts | 6 ++++++ 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 5601d73951..0b71ae7bb3 100644 --- a/build.sbt +++ b/build.sbt @@ -193,7 +193,7 @@ lazy val frontend = (project in file("frontend")) } println("Building frontend...") - val buildResult = Process("npm run build", file("frontend")).! + val buildResult = Process("npm run build:docker", file("frontend")).! if (buildResult == 0) { println("Copying frontend assets to /hub/public...") @@ -211,6 +211,7 @@ lazy val frontend = (project in file("frontend")) } ) +// todo remove stuff here lazy val hub = (project in file("hub")) .enablePlugins(PlayScala) .settings( diff --git a/docker-init/compose.yaml b/docker-init/compose.yaml index 7c0986bca1..19b2028e43 100644 --- a/docker-init/compose.yaml +++ b/docker-init/compose.yaml @@ -65,7 +65,6 @@ services: test: curl -sS --fail http://app:${APP_PORT:-9000}/api/v1/ping timeout: 5s - # todo: set env variable frontend: build: context: .. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 2f3defc4a4..135a8b8657 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,7 @@ "@types/echarts": "^4.9.22", "bits-ui": "^0.21.15", "clsx": "^2.1.1", + "dotenv": "^16.4.5", "echarts": "^5.5.1", "svelte-radix": "^1.1.1", "tailwind-merge": "^2.5.2", @@ -25,6 +26,7 @@ "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@tailwindcss/typography": "^0.5.15", "@types/eslint": "^9.6.0", + "@types/node": "^22.7.4", "autoprefixer": "^10.4.20", "eslint": "^9.0.0", "eslint-config-prettier": "^9.1.0", @@ -1375,6 +1377,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -2328,6 +2340,18 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "license": "MIT" }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4769,6 +4793,13 @@ } } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index c40f5d5300..7231a13e96 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -5,6 +5,7 @@ "scripts": { "dev": "vite dev", "build": "vite build", + "build:docker": "APP_ENV=docker vite build", "preview": "vite preview", "test": "npm run test:integration:once && npm run test:unit:once", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", @@ -26,6 +27,7 @@ "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6", "@tailwindcss/typography": "^0.5.15", "@types/eslint": "^9.6.0", + "@types/node": "^22.7.4", "autoprefixer": "^10.4.20", "eslint": "^9.0.0", "eslint-config-prettier": "^9.1.0", @@ -47,6 +49,7 @@ "@types/echarts": "^4.9.22", "bits-ui": "^0.21.15", "clsx": "^2.1.1", + "dotenv": "^16.4.5", "echarts": "^5.5.1", "svelte-radix": "^1.1.1", "tailwind-merge": "^2.5.2", diff --git a/frontend/src/lib/api/api.ts b/frontend/src/lib/api/api.ts index 5a988783e1..7102bc0354 100644 --- a/frontend/src/lib/api/api.ts +++ b/frontend/src/lib/api/api.ts @@ -1,6 +1,7 @@ import { error } from '@sveltejs/kit'; +const API_BASE_URL = import.meta.env.VITE_API_BASE_URL; -const base = 'http://app:9000/api/v1'; // todo env variable +const base = `${API_BASE_URL}/api/v1`; async function send({ method, path }: { method: string; path: string }) { const opts = { method, headers: {} }; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 331e6293b0..aea5cbb8a4 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,5 +1,11 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vitest/config'; +import dotenv from 'dotenv'; + +// Load .env.docker when the build is run with "docker" mode +if (process.env.APP_ENV === 'docker') { + dotenv.config({ path: '.env.docker' }); +} export default defineConfig({ plugins: [sveltekit()], From 6b27bd3c1931684a838d03e4041e9f800f4240b6 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:00:02 -0600 Subject: [PATCH 45/60] add a quick coming soon to the / route --- frontend/src/routes/+page.svelte | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 8e3f87428d..10b27a3e5e 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1 +1,5 @@ -
todo / route
+

Coming Soon

+

+ This page is under construction. In the meantime, check out our the "Models" tab in your sidebar + to see the models. +

From 115faa378b8feb40fde7249faffa4165b7e88b91 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:02:26 -0600 Subject: [PATCH 46/60] zipline logo routes to / route --- frontend/src/routes/+layout.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 4d56d8bb60..37c443907c 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -34,7 +34,9 @@
- Zipline Logo +
{user.name} From 9e636296930219f128447b43e8e2d83704fb76ae Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:05:56 -0600 Subject: [PATCH 47/60] quick header for timeseries data --- frontend/src/routes/models/[slug]/observability/+page.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/routes/models/[slug]/observability/+page.svelte b/frontend/src/routes/models/[slug]/observability/+page.svelte index a7d2c3b56c..72f7e8c696 100644 --- a/frontend/src/routes/models/[slug]/observability/+page.svelte +++ b/frontend/src/routes/models/[slug]/observability/+page.svelte @@ -4,5 +4,6 @@
Observability for Model {timeseries.id}
+
Timeseries below (to be replaced with a line chart)
{JSON.stringify(timeseries, null, 2)}
From cf2e418fd086ebfc303cb1b9ed38666a7ba70865 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:28:39 -0600 Subject: [PATCH 48/60] remove old frontend stuff from build.sbt --- build.sbt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.sbt b/build.sbt index 0b71ae7bb3..825d8cdb55 100644 --- a/build.sbt +++ b/build.sbt @@ -211,7 +211,6 @@ lazy val frontend = (project in file("frontend")) } ) -// todo remove stuff here lazy val hub = (project in file("hub")) .enablePlugins(PlayScala) .settings( @@ -225,9 +224,6 @@ lazy val hub = (project in file("hub")) "io.circe" %% "circe-generic" % circeVersion, "io.circe" %% "circe-parser" % circeVersion ), - // Ensure hub depends on frontend build - Compile / run := ((Compile / run) dependsOn (frontend / buildFrontend)).evaluated, - Compile / stage := ((Compile / stage) dependsOn (frontend / buildFrontend)).value ) ThisBuild / assemblyMergeStrategy := { From 463eefef94cb6206663e8aa0ff0589483716e294 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:28:46 -0600 Subject: [PATCH 49/60] update docker readme --- docker-init/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker-init/README.md b/docker-init/README.md index d50137db9a..729b9eb27c 100644 --- a/docker-init/README.md +++ b/docker-init/README.md @@ -10,10 +10,12 @@ app-1 | [info] 2024-09-30 20:47:56,448 [main] INFO play.api.Play - Ap app-1 | [info] 2024-09-30 20:47:56,665 [main] INFO play.core.server.PekkoHttpServer - Listening for HTTP on /[0:0:0:0:0:0:0:0]:9000 ``` -You can now pull up the web-server on http://localhost:9000 +The **backend** is served at: http://localhost:9000 + +The **frontend** is served at: http://localhost:3000 You can also access the parquet anomaly data table. To do so, from another terminal run: -```docker-compose exec app bash``` +`docker-compose exec app bash` The parquet is available in the /app/data directory. From 5ade424a6cabd90073ea9d70eb030a90c348bf88 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:31:50 -0600 Subject: [PATCH 50/60] format --- docker-init/compose.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-init/compose.yaml b/docker-init/compose.yaml index 42da5cf26d..19b2028e43 100644 --- a/docker-init/compose.yaml +++ b/docker-init/compose.yaml @@ -1,4 +1,4 @@ -name: 'hub-monitoring-demo' +name: "hub-monitoring-demo" services: dynamo: command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data" @@ -57,7 +57,7 @@ services: - PLAY_HTTP_SECRET_KEY=my_fake_chronon_monitoring_hub_http_secret_key # needs to be long to make Play happy - JAVA_OPTS=-Xms1g -Xmx1g ports: - - '9000:9000' + - "9000:9000" healthcheck: interval: 1s retries: 5 @@ -79,4 +79,4 @@ services: interval: 30s timeout: 10s retries: 3 - start_period: 40s \ No newline at end of file + start_period: 40s From b26c67207cb19ab4d095f85ef4a14eff148aeb4b Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Tue, 1 Oct 2024 15:51:06 -0600 Subject: [PATCH 51/60] add link to the heatmap preview --- frontend/src/routes/+page.svelte | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 10b27a3e5e..b022ec4248 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,5 +1,20 @@ -

Coming Soon

-

- This page is under construction. In the meantime, check out our the "Models" tab in your sidebar - to see the models. +

Home Page

+

+ Eventually this will have our home page content. For now, I'll leave a few links.

+ +
+

Models

+

+ Visit the Models page for a (basic) list + of models +

+
+ +
+

Observability

+

+ Visit the Observability page for + a preview of a reusable echarts heatmap component. +

+
From 6a756117360b5c69974de5bcf9c70066825c4d9b Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Wed, 2 Oct 2024 09:54:58 -0600 Subject: [PATCH 52/60] add instructions for how to start the backend server first for dev work --- frontend/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/README.md b/frontend/README.md index 0cd17a55ce..3ce37bd098 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -33,6 +33,15 @@ The frontend for Chronon. To start the development server: +1. First, start the backend project: + +```bash +# Run this command in the root directory +sbt "project hub" run +``` + +2. Then, start the development server: + ```bash npm run dev ``` From f84133a6e143027c9eb60395ec2ca7e205913556 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Wed, 2 Oct 2024 13:48:48 -0600 Subject: [PATCH 53/60] add tests for core api functionality --- frontend/src/lib/api/api.test.ts | 62 ++++++++++++++++++++++++++++ frontend/src/test/unit/index.test.ts | 7 ---- frontend/vite.config.ts | 2 +- 3 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 frontend/src/lib/api/api.test.ts delete mode 100644 frontend/src/test/unit/index.test.ts diff --git a/frontend/src/lib/api/api.test.ts b/frontend/src/lib/api/api.test.ts new file mode 100644 index 0000000000..f5dc4d4323 --- /dev/null +++ b/frontend/src/lib/api/api.test.ts @@ -0,0 +1,62 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { get } from './api'; +import { error } from '@sveltejs/kit'; + +// Mock the fetch function +const mockFetch = vi.fn(); +global.fetch = mockFetch; + +// Mock the error function from @sveltejs/kit +vi.mock('@sveltejs/kit', () => ({ + error: vi.fn() +})); + +describe('API module', () => { + beforeEach(() => { + vi.resetAllMocks(); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('get function', () => { + it('should make a GET request and return parsed JSON data', async () => { + const mockResponse = { data: 'test data' }; + mockFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(JSON.stringify(mockResponse)) + }); + + const result = await get('test-path'); + + expect(mockFetch).toHaveBeenCalledWith( + `${import.meta.env.VITE_API_BASE_URL}/api/v1/test-path`, + { method: 'GET', headers: {} } + ); + expect(result).toEqual(mockResponse); + }); + + it('should return an empty object if the response is empty', async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve('') + }); + + const result = await get('empty-path'); + + expect(result).toEqual({}); + }); + + it('should throw an error if the response is not ok', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + status: 404 + }); + + await get('error-path'); + + expect(error).toHaveBeenCalledWith(404); + }); + }); +}); diff --git a/frontend/src/test/unit/index.test.ts b/frontend/src/test/unit/index.test.ts deleted file mode 100644 index e07cbbd725..0000000000 --- a/frontend/src/test/unit/index.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { - expect(1 + 2).toBe(3); - }); -}); diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index aea5cbb8a4..05c63b8e54 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -10,6 +10,6 @@ if (process.env.APP_ENV === 'docker') { export default defineConfig({ plugins: [sveltekit()], test: { - include: ['./src/test/unit/**/*.{test,spec}.{js,ts}'] + include: ['./src/**/*.{test,spec}.{js,ts}'] } }); From 6c52f28999df3e8cc60ab9c47c9fe96c5b919d34 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Wed, 2 Oct 2024 14:15:45 -0600 Subject: [PATCH 54/60] .env files were ignored in the .gitignore - remove this --- .gitignore | 6 ------ frontend/.env | 1 + frontend/.env.docker | 1 + 3 files changed, 2 insertions(+), 6 deletions(-) create mode 100644 frontend/.env create mode 100644 frontend/.env.docker diff --git a/.gitignore b/.gitignore index 4587f6a762..943b4747c3 100644 --- a/.gitignore +++ b/.gitignore @@ -60,12 +60,6 @@ releases /frontend/.DS_Store /frontend/Thumbs.db -# Frontend Env -/frontend/.env -/frontend/.env.* -!/frontend/.env.example -!/frontend/.env.test - # Frontend Vite /frontend/vite.config.js.timestamp-* /frontend/vite.config.ts.timestamp-* diff --git a/frontend/.env b/frontend/.env new file mode 100644 index 0000000000..09530054de --- /dev/null +++ b/frontend/.env @@ -0,0 +1 @@ +VITE_API_BASE_URL=http://localhost:9000 diff --git a/frontend/.env.docker b/frontend/.env.docker new file mode 100644 index 0000000000..8a4314521a --- /dev/null +++ b/frontend/.env.docker @@ -0,0 +1 @@ +VITE_API_BASE_URL=http://app:9000 From 47501369a9d251d92e10d3eef4707327c37e70e4 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Wed, 2 Oct 2024 14:22:30 -0600 Subject: [PATCH 55/60] cleaner way to run docker build --- frontend/package.json | 2 +- frontend/vite.config.ts | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 7231a13e96..4a8c97edd6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -5,7 +5,7 @@ "scripts": { "dev": "vite dev", "build": "vite build", - "build:docker": "APP_ENV=docker vite build", + "build:docker": "vite build --mode docker", "preview": "vite preview", "test": "npm run test:integration:once && npm run test:unit:once", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index aea5cbb8a4..331e6293b0 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,11 +1,5 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vitest/config'; -import dotenv from 'dotenv'; - -// Load .env.docker when the build is run with "docker" mode -if (process.env.APP_ENV === 'docker') { - dotenv.config({ path: '.env.docker' }); -} export default defineConfig({ plugins: [sveltekit()], From eb11d7b7841054fd3b16a802ea9311193878ccc1 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 3 Oct 2024 10:00:20 -0600 Subject: [PATCH 56/60] create tests that verify backend types for model --- frontend/README.md | 2 + frontend/src/lib/types/Model/Model.test.ts | 77 +++++++++++++++++++ frontend/src/lib/types/{ => Model}/Model.ts | 0 frontend/src/routes/models/+page.server.ts | 2 +- .../[slug]/observability/+page.server.ts | 2 +- 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 frontend/src/lib/types/Model/Model.test.ts rename frontend/src/lib/types/{ => Model}/Model.ts (100%) diff --git a/frontend/README.md b/frontend/README.md index 3ce37bd098..c529053d80 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -68,6 +68,8 @@ npm run preview ### Running Tests +> **Important:** You must start the backend before running tests. In the future, we can add scripts to automatically start the backend before any tests are run. + #### All Tests To run both unit and integration tests together: diff --git a/frontend/src/lib/types/Model/Model.test.ts b/frontend/src/lib/types/Model/Model.test.ts new file mode 100644 index 0000000000..4b23c15a44 --- /dev/null +++ b/frontend/src/lib/types/Model/Model.test.ts @@ -0,0 +1,77 @@ +import { describe, it, expect } from 'vitest'; +import * as api from '$lib/api/api'; +import type { ModelsResponse, TimeSeriesResponse, Model } from '$lib/types/Model/Model'; + +describe('Model types', () => { + // Test for ModelsResponse + it('should match ModelsResponse type', async () => { + const result = (await api.get('models')) as ModelsResponse; + + const expectedKeys = ['offset', 'items']; + expect(Object.keys(result)).toEqual(expect.arrayContaining(expectedKeys)); + + // Log a warning if there are additional fields + const additionalKeys = Object.keys(result).filter((key) => !expectedKeys.includes(key)); + if (additionalKeys.length > 0) { + console.warn(`Additional fields found in ModelsResponse: ${additionalKeys.join(', ')}`); + } + + expect(Array.isArray(result.items)).toBe(true); + + if (result.items.length > 0) { + const model = result.items[0]; + const expectedModelKeys: (keyof Model)[] = [ + 'name', + 'id', + 'online', + 'production', + 'team', + 'modelType', + 'createTime', + 'lastUpdated' + ]; + expect(Object.keys(model)).toEqual(expect.arrayContaining(expectedModelKeys)); + + // Log a warning if there are additional fields + const additionalModelKeys = Object.keys(model).filter( + (key) => !expectedModelKeys.includes(key as keyof Model) + ); + if (additionalModelKeys.length > 0) { + console.warn(`Additional fields found in Model: ${additionalModelKeys.join(', ')}`); + } + } + }); + + // Test for TimeSeriesResponse + it('should match TimeSeriesResponse type', async () => { + const modelId = '0'; + const result = (await api.get( + `model/${modelId}/timeseries?startTs=1725926400000&endTs=1726106400000&offset=10h&algorithm=psi` + )) as TimeSeriesResponse; + + const expectedKeys = ['id', 'items']; + expect(Object.keys(result)).toEqual(expect.arrayContaining(expectedKeys)); + + // Log a warning if there are additional fields + const additionalKeys = Object.keys(result).filter((key) => !expectedKeys.includes(key)); + if (additionalKeys.length > 0) { + console.warn(`Additional fields found in TimeSeriesResponse: ${additionalKeys.join(', ')}`); + } + + expect(Array.isArray(result.items)).toBe(true); + + if (result.items.length > 0) { + const item = result.items[0]; + const expectedItemKeys = ['value', 'ts', 'label']; + expect(Object.keys(item)).toEqual(expect.arrayContaining(expectedItemKeys)); + + // Log a warning if there are additional fields + const additionalItemKeys = Object.keys(item).filter((key) => !expectedItemKeys.includes(key)); + if (additionalItemKeys.length > 0) { + console.warn( + `Additional fields found in TimeSeriesResponse item: ${additionalItemKeys.join(', ')}` + ); + } + } + }); +}); diff --git a/frontend/src/lib/types/Model.ts b/frontend/src/lib/types/Model/Model.ts similarity index 100% rename from frontend/src/lib/types/Model.ts rename to frontend/src/lib/types/Model/Model.ts diff --git a/frontend/src/routes/models/+page.server.ts b/frontend/src/routes/models/+page.server.ts index c686a4a9db..7740a05d27 100644 --- a/frontend/src/routes/models/+page.server.ts +++ b/frontend/src/routes/models/+page.server.ts @@ -1,5 +1,5 @@ import type { PageServerLoad } from './$types'; -import type { ModelsResponse } from '$lib/types/Model'; +import type { ModelsResponse } from '$lib/types/Model/Model'; import * as api from '$lib/api/api'; export const load: PageServerLoad = async (): Promise<{ models: ModelsResponse }> => { diff --git a/frontend/src/routes/models/[slug]/observability/+page.server.ts b/frontend/src/routes/models/[slug]/observability/+page.server.ts index 9f499bf751..7a4d0fc598 100644 --- a/frontend/src/routes/models/[slug]/observability/+page.server.ts +++ b/frontend/src/routes/models/[slug]/observability/+page.server.ts @@ -1,6 +1,6 @@ import type { PageServerLoad } from './$types'; import * as api from '$lib/api/api'; -import type { TimeSeriesResponse } from '$lib/types/Model'; +import type { TimeSeriesResponse } from '$lib/types/Model/Model'; export const load: PageServerLoad = async ({ params From a6b1a47580949a591669a1d3c1e99ec94cfd27a9 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 3 Oct 2024 10:03:07 -0600 Subject: [PATCH 57/60] remove comments --- frontend/src/lib/types/Model/Model.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/src/lib/types/Model/Model.test.ts b/frontend/src/lib/types/Model/Model.test.ts index 4b23c15a44..8e93d6bd31 100644 --- a/frontend/src/lib/types/Model/Model.test.ts +++ b/frontend/src/lib/types/Model/Model.test.ts @@ -3,7 +3,6 @@ import * as api from '$lib/api/api'; import type { ModelsResponse, TimeSeriesResponse, Model } from '$lib/types/Model/Model'; describe('Model types', () => { - // Test for ModelsResponse it('should match ModelsResponse type', async () => { const result = (await api.get('models')) as ModelsResponse; @@ -42,7 +41,6 @@ describe('Model types', () => { } }); - // Test for TimeSeriesResponse it('should match TimeSeriesResponse type', async () => { const modelId = '0'; const result = (await api.get( From 5eb7ccb8be4e4b02e5a28bf39c01ea08d6129711 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 3 Oct 2024 10:07:30 -0600 Subject: [PATCH 58/60] delete old test file --- frontend/src/test/unit/index.test.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 frontend/src/test/unit/index.test.ts diff --git a/frontend/src/test/unit/index.test.ts b/frontend/src/test/unit/index.test.ts deleted file mode 100644 index e69de29bb2..0000000000 From 2c58662adba4923ee4814ea0f2fced1b3329d5c6 Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 3 Oct 2024 10:21:34 -0600 Subject: [PATCH 59/60] delete old model file --- frontend/src/lib/types/Model.ts | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 frontend/src/lib/types/Model.ts diff --git a/frontend/src/lib/types/Model.ts b/frontend/src/lib/types/Model.ts deleted file mode 100644 index b6346ae8dc..0000000000 --- a/frontend/src/lib/types/Model.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type Model = { - name: string; - id: string; - online: boolean; - production: boolean; - team: string; - modelType: string; - createTime: number; - lastUpdated: number; -}; - -export type ModelsResponse = { - offset: number; - items: Model[]; -}; - -export type TimeSeriesItem = { - value: number; - ts: number; - label: string | null; -}; - -export type TimeSeriesResponse = { - id: string; - items: TimeSeriesItem[]; -}; From 83f97d6d5c00b8acc8ee6b5d6121b6f08a8bd09b Mon Sep 17 00:00:00 2001 From: ken-zlai Date: Thu, 3 Oct 2024 10:25:17 -0600 Subject: [PATCH 60/60] fix import --- frontend/src/routes/models/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/routes/models/+page.svelte b/frontend/src/routes/models/+page.svelte index e4a8142b5d..d9b701d120 100644 --- a/frontend/src/routes/models/+page.svelte +++ b/frontend/src/routes/models/+page.svelte @@ -1,5 +1,5 @@