Browse page, UI redesign, Websockets, Navigation, and more!

This commit is contained in:
scarlett kadan 2024-03-26 23:32:01 -04:00
parent 81d13a70db
commit 0ca513e976
25 changed files with 1160 additions and 108 deletions

682
package-lock.json generated
View File

@ -13,10 +13,15 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.0",
"react-router-dom": "^6.22.3",
"react-scripts": "^5.0.1",
"sass": "^1.70.0",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"stylelint": "^16.3.1",
"stylelint-config-standard-scss": "^13.0.0",
"stylelint-scss": "^6.2.1"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@ -2127,6 +2132,70 @@
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="
},
"node_modules/@csstools/css-parser-algorithms": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz",
"integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"engines": {
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
"@csstools/css-tokenizer": "^2.2.4"
}
},
"node_modules/@csstools/css-tokenizer": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz",
"integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"engines": {
"node": "^14 || ^16 || >=18"
}
},
"node_modules/@csstools/media-query-list-parser": {
"version": "2.1.9",
"resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz",
"integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"engines": {
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
"@csstools/css-parser-algorithms": "^2.6.1",
"@csstools/css-tokenizer": "^2.2.4"
}
},
"node_modules/@csstools/normalize.css": {
"version": "12.1.1",
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz",
@ -2397,6 +2466,16 @@
"postcss-selector-parser": "^6.0.10"
}
},
"node_modules/@dual-bundle/import-meta-resolve": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
"integrity": "sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@ -3538,9 +3617,9 @@
}
},
"node_modules/@remix-run/router": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz",
"integrity": "sha512-HOil5aFtme37dVQTB6M34G95kPM3MMuqSmIRVCC52eKV+Y/tGSqw9P3rWhlAx6A+mz+MoX+XxsGsNJbaI5qCgQ==",
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==",
"engines": {
"node": ">=14.0.0"
}
@ -5152,6 +5231,15 @@
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
"integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="
},
"node_modules/astral-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/async": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
@ -6239,6 +6327,15 @@
"postcss": "^8.0.9"
}
},
"node_modules/css-functions-list": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz",
"integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==",
"dev": true,
"engines": {
"node": ">=12 || >=16"
}
},
"node_modules/css-has-pseudo": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz",
@ -7069,6 +7166,15 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -8038,6 +8144,15 @@
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
},
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
"integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
"dev": true,
"engines": {
"node": ">= 4.9.1"
}
},
"node_modules/fastq": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
@ -8659,6 +8774,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/globjoin": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
"integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
"dev": true
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@ -8888,6 +9009,18 @@
"node": ">=12"
}
},
"node_modules/html-tags": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
"integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/html-webpack-plugin": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz",
@ -9457,6 +9590,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@ -11803,6 +11945,12 @@
"node": ">= 8"
}
},
"node_modules/known-css-properties": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz",
"integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==",
"dev": true
},
"node_modules/language-subtag-registry": {
"version": "0.3.22",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
@ -11921,6 +12069,12 @@
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
},
"node_modules/lodash.truncate": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
"dev": true
},
"node_modules/lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -11999,6 +12153,16 @@
"tmpl": "1.0.5"
}
},
"node_modules/mathml-tag-names": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
"integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
"dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/mdn-data": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@ -12023,6 +12187,18 @@
"node": ">= 4.0.0"
}
},
"node_modules/meow": {
"version": "13.2.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
"integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
"dev": true,
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -12931,9 +13107,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.33",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
"integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"funding": [
{
"type": "opencollective",
@ -12951,7 +13127,7 @@
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
@ -13479,6 +13655,12 @@
"postcss": "^8.1.0"
}
},
"node_modules/postcss-media-query-parser": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
"integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
"dev": true
},
"node_modules/postcss-merge-longhand": {
"version": "5.1.7",
"resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz",
@ -14006,6 +14188,64 @@
"postcss": "^8.0.3"
}
},
"node_modules/postcss-resolve-nested-selector": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
"integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==",
"dev": true
},
"node_modules/postcss-safe-parser": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz",
"integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"engines": {
"node": ">=18.0"
},
"peerDependencies": {
"postcss": "^8.4.31"
}
},
"node_modules/postcss-scss": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz",
"integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss-scss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"engines": {
"node": ">=12.0"
},
"peerDependencies": {
"postcss": "^8.4.29"
}
},
"node_modules/postcss-selector-not": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz",
@ -14025,9 +14265,9 @@
}
},
"node_modules/postcss-selector-parser": {
"version": "6.0.15",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz",
"integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==",
"version": "6.0.16",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
"integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@ -14468,11 +14708,11 @@
}
},
"node_modules/react-router": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz",
"integrity": "sha512-q2yemJeg6gw/YixRlRnVx6IRJWZD6fonnfZhN1JIOhV2iJCPeRNSH3V1ISwHf+JWcESzLC3BOLD1T07tmO5dmg==",
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
"dependencies": {
"@remix-run/router": "1.15.0"
"@remix-run/router": "1.15.3"
},
"engines": {
"node": ">=14.0.0"
@ -14482,12 +14722,12 @@
}
},
"node_modules/react-router-dom": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz",
"integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==",
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz",
"integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==",
"dependencies": {
"@remix-run/router": "1.15.0",
"react-router": "6.22.0"
"@remix-run/router": "1.15.3",
"react-router": "6.22.3"
},
"engines": {
"node": ">=14.0.0"
@ -15404,6 +15644,23 @@
"node": ">=8"
}
},
"node_modules/slice-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
"integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"astral-regex": "^2.0.0",
"is-fullwidth-code-point": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
"node_modules/sockjs": {
"version": "0.3.24",
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
@ -15428,9 +15685,9 @@
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"engines": {
"node": ">=0.10.0"
}
@ -15888,6 +16145,341 @@
"postcss": "^8.2.15"
}
},
"node_modules/stylelint": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.3.1.tgz",
"integrity": "sha512-/JOwQnBvxEKOT2RtNgGpBVXnCSMBgKOL2k7w0K52htwCyJls4+cHvc4YZgXlVoAZS9QJd2DgYAiRnja96pTgxw==",
"dev": true,
"dependencies": {
"@csstools/css-parser-algorithms": "^2.6.1",
"@csstools/css-tokenizer": "^2.2.4",
"@csstools/media-query-list-parser": "^2.1.9",
"@csstools/selector-specificity": "^3.0.2",
"@dual-bundle/import-meta-resolve": "^4.0.0",
"balanced-match": "^2.0.0",
"colord": "^2.9.3",
"cosmiconfig": "^9.0.0",
"css-functions-list": "^3.2.1",
"css-tree": "^2.3.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"fastest-levenshtein": "^1.0.16",
"file-entry-cache": "^8.0.0",
"global-modules": "^2.0.0",
"globby": "^11.1.0",
"globjoin": "^0.1.4",
"html-tags": "^3.3.1",
"ignore": "^5.3.1",
"imurmurhash": "^0.1.4",
"is-plain-object": "^5.0.0",
"known-css-properties": "^0.30.0",
"mathml-tag-names": "^2.1.3",
"meow": "^13.2.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"picocolors": "^1.0.0",
"postcss": "^8.4.38",
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-safe-parser": "^7.0.0",
"postcss-selector-parser": "^6.0.16",
"postcss-value-parser": "^4.2.0",
"resolve-from": "^5.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^7.1.0",
"supports-hyperlinks": "^3.0.0",
"svg-tags": "^1.0.0",
"table": "^6.8.1",
"write-file-atomic": "^5.0.1"
},
"bin": {
"stylelint": "bin/stylelint.mjs"
},
"engines": {
"node": ">=18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/stylelint"
}
},
"node_modules/stylelint-config-recommended": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz",
"integrity": "sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==",
"dev": true,
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"stylelint": "^16.0.0"
}
},
"node_modules/stylelint-config-recommended-scss": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.0.0.tgz",
"integrity": "sha512-HDvpoOAQ1RpF+sPbDOT2Q2/YrBDEJDnUymmVmZ7mMCeNiFSdhRdyGEimBkz06wsN+HaFwUh249gDR+I9JR7Onw==",
"dev": true,
"dependencies": {
"postcss-scss": "^4.0.9",
"stylelint-config-recommended": "^14.0.0",
"stylelint-scss": "^6.0.0"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"postcss": "^8.3.3",
"stylelint": "^16.0.2"
},
"peerDependenciesMeta": {
"postcss": {
"optional": true
}
}
},
"node_modules/stylelint-config-standard": {
"version": "36.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz",
"integrity": "sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==",
"dev": true,
"dependencies": {
"stylelint-config-recommended": "^14.0.0"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"stylelint": "^16.1.0"
}
},
"node_modules/stylelint-config-standard-scss": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-13.0.0.tgz",
"integrity": "sha512-WaLvkP689qSYUpJQPCo30TFJSSc3VzvvoWnrgp+7PpVby5o8fRUY1cZcP0sePZfjrFl9T8caGhcKg0GO34VDiQ==",
"dev": true,
"dependencies": {
"stylelint-config-recommended-scss": "^14.0.0",
"stylelint-config-standard": "^36.0.0"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"postcss": "^8.3.3",
"stylelint": "^16.1.0"
},
"peerDependenciesMeta": {
"postcss": {
"optional": true
}
}
},
"node_modules/stylelint-scss": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.2.1.tgz",
"integrity": "sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw==",
"dev": true,
"dependencies": {
"known-css-properties": "^0.29.0",
"postcss-media-query-parser": "^0.2.3",
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-selector-parser": "^6.0.15",
"postcss-value-parser": "^4.2.0"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"stylelint": "^16.0.2"
}
},
"node_modules/stylelint-scss/node_modules/known-css-properties": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz",
"integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==",
"dev": true
},
"node_modules/stylelint/node_modules/@csstools/selector-specificity": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.2.tgz",
"integrity": "sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"engines": {
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
"postcss-selector-parser": "^6.0.13"
}
},
"node_modules/stylelint/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/stylelint/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/stylelint/node_modules/balanced-match": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
"integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
"dev": true
},
"node_modules/stylelint/node_modules/cosmiconfig": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
"dev": true,
"dependencies": {
"env-paths": "^2.2.1",
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"parse-json": "^5.2.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/d-fischer"
},
"peerDependencies": {
"typescript": ">=4.9.5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/stylelint/node_modules/css-tree": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
"dev": true,
"dependencies": {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/stylelint/node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
"dependencies": {
"flat-cache": "^4.0.0"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/stylelint/node_modules/flat-cache": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
"dependencies": {
"flatted": "^3.2.9",
"keyv": "^4.5.4"
},
"engines": {
"node": ">=16"
}
},
"node_modules/stylelint/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/stylelint/node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
"dev": true
},
"node_modules/stylelint/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,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/stylelint/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,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/stylelint/node_modules/supports-hyperlinks": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
"integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0",
"supports-color": "^7.0.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/stylelint/node_modules/write-file-atomic": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
"integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
"dev": true,
"dependencies": {
"imurmurhash": "^0.1.4",
"signal-exit": "^4.0.1"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@ -15999,6 +16591,12 @@
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ=="
},
"node_modules/svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
"integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
"dev": true
},
"node_modules/svgo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@ -16140,6 +16738,44 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
},
"node_modules/table": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz",
"integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==",
"dev": true,
"dependencies": {
"ajv": "^8.0.1",
"lodash.truncate": "^4.4.2",
"slice-ansi": "^4.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/table/node_modules/ajv": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/table/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/tailwindcss": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",

View File

@ -8,7 +8,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.0",
"react-router-dom": "^6.22.3",
"react-scripts": "^5.0.1",
"sass": "^1.70.0",
"web-vitals": "^2.1.4"
@ -17,7 +17,8 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"lint:scss": "stylelint \"src/assets/stylesheets/**/*.scss\" --fix"
},
"eslintConfig": {
"extends": [
@ -36,5 +37,33 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"stylelint": "^16.3.1",
"stylelint-config-standard-scss": "^13.0.0",
"stylelint-scss": "^6.2.1"
},
"stylelint": {
"extends": [
"stylelint-config-standard",
"stylelint-config-recommended-scss"
],
"plugins": [
"stylelint-scss"
],
"rules": {
"scss/load-no-partial-leading-underscore": true,
"scss/no-duplicate-dollar-variables": true,
"declaration-block-no-duplicate-properties": [
true,
{
"ignore": [
"consecutive-duplicates-with-different-values"
]
}
],
"block-no-empty": null,
"color-no-invalid-hex": true
}
}
}

View File

@ -24,10 +24,10 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Belden Jukebox</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<noscript>Belden Jukebox UI</noscript>
<div id="root"></div>
<!--
This HTML file is a template.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,28 @@
export default class socketHandler {
constructor(socket) {
this.socket = socket;
this.socket.addEventListener("message", (event) => {
try {
console.log("Message from server", event.data);
let messages = document.getElementById("messages");
let message = document.createElement("li");
message.textContent = "Received: " + event.data;
messages.appendChild(message);
} catch (error) {
console.log("Error", error);
}
});
}
sendMessage(message) {
this.socket.send(message);
console.log("Message sent", message);
}
ping() {
let message = `{ "call": "send", "type": "log", "data": "This is a ping!!" }`;
this.socket.send(message);
console.log("Message sent", message);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
src/assets/images/part.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,125 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import DefaultPartImg from "../assets/images/part.png";
import "../assets/stylesheets/browse.scss";
class cable {
constructor(
part_number,
position,
name,
brand,
description,
short_description,
image
) {
this.part_number = part_number;
this.position = position;
this.name = name;
this.brand = brand;
this.description = description;
this.short_description = short_description;
if (image === undefined) {
this.image = DefaultPartImg;
} else {
this.image = image;
}
}
returnDiv() {
return (
<div className="browse-cable">
<img className="browse-cable-image" src={this.image} alt="Cable" />
<div className="browse-cable-label">
<div className="browse-cable-name">{this.name}</div>
<div className="browse-cable-brand">
<span style={{ color: "#007cbe" }}>Brand: </span>
{this.brand}
</div>
<div className="browse-cable-description">
<span style={{ color: "#007cbe" }}>About: </span>
{this.description}
</div>
</div>
<span className="browse-cable-arrow">{">"}</span>
</div>
);
}
}
export default class BrowseComponent extends Component {
constructor(props) {
super(props);
this.state = {
cableList: [],
};
}
componentDidMount() {
this.props.socketHandler.sendMessage(
'{"type":"cable_map","call":"request","data":{}}'
);
this.props.socketHandler.socket.addEventListener(
"message",
this.handleMessage
);
}
handleMessage = (event) => {
try {
console.log("Message from server", event.data);
const message = JSON.parse(event.data);
const cableList = this.browseParse(message);
this.setState({ cableList });
} catch (error) {
console.error("Error parsing message from server:", error);
}
};
browseParse(message) {
let cableList = [];
let map = message.data.map;
for (let i = 0; i < map.length; i++) {
let part_number = map[i].part_number;
let position = map[i].position;
let name = map[i].name;
let brand = map[i].brand;
let description = map[i].description;
let short_description = map[i].short_description;
cableList.push(
new cable(
part_number,
position,
name,
brand,
description,
short_description
)
);
}
return cableList;
}
componentWillUnmount() {
this.props.socketHandler.socket.removeEventListener(
"message",
this.handleMessage
);
}
render() {
return (
<div className="browse">
<div className="browse-image">
<img src={BeldenLogo} alt="Belden" />
</div>
<div className="browse-fieldContainer">
{this.state.cableList.map((cableObj, index) => (
<React.Fragment key={index}>{cableObj.returnDiv()}</React.Fragment>
))}
</div>
</div>
);
}
}

View File

@ -1,12 +0,0 @@
import React, { Component } from "react";
import "../assets/stylesheets/home.scss";
export default class HomeComponent extends Component {
// constructor(props) {
// super(props);
// }
render() {
return <div className="home"></div>;
}
}

View File

@ -0,0 +1,14 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import "../assets/stylesheets/map.scss";
export default class MapComponent extends Component {
render() {
return (
<div className="map">
<img className="map-image" src={BeldenLogo} alt="Belden" />
<div className="map-fieldContainer"></div>
</div>
);
}
}

View File

@ -1,30 +1,57 @@
import React, { Component } from "react";
import { NavLink } from "react-router-dom";
import BeldenLogo from "../assets/images/belden-logo.png";
import "../assets/stylesheets/navbar.scss";
export default class NavBar extends Component {
constructor(props) {
super(props);
componentDidMount() {
let path = window.location.pathname;
if (path.includes("browse")) {
document.getElementById("browse").style.backgroundColor = "#007CBE";
document.getElementById("browse-s").style.color = "white";
} else if (path.includes("settings")) {
document.getElementById("settings").style.backgroundColor = "#007CBE";
document.getElementById("settings-s").style.color = "white";
} else if (path.includes("map")) {
document.getElementById("map").style.backgroundColor = "#007CBE";
document.getElementById("map-s").style.color = "white";
} else {
document.getElementById("home").style.backgroundColor = "#007CBE";
document.getElementById("home-s").style.color = "white";
}
}
render() {
return (
<div className="navbar">
<div className="navbar-top">
<img className="navbar-top-logo" src={BeldenLogo} alt="Belden" />
<div className="navbar-top-hamburger"></div>
<h1>Jukebox</h1>
<div className="navbar-search">
<input type="text" placeholder="Search" />
<button>🔍</button>
</div>
<ol className="navbar-list">
<NavLink
style={this.upper}
id="home"
className="navbar-list-item"
to="/"
>
<span id="home-s" style={this.lower}>
Summary
</span>
</NavLink>
<NavLink className="navbar-list-item" id="browse" to="/browse">
<span id="browse-s">🛍 Browse</span>
</NavLink>
<NavLink className="navbar-list-item" id="map" to="/map">
<span id="map-s">🗺 Map</span>
</NavLink>
<NavLink className="navbar-list-item" id="settings" to="/settings">
<span id="settings-s"> Settings</span>
</NavLink>
</ol>
</div>
<ol className="navbar-list">
<NavLink className="navbar-list-item" to="/">
<span className="navbar-list-item-label">Home</span>
</NavLink>
<NavLink className="navbar-list-item" to="/search">
<span className="navbar-list-item-label">Search</span>
</NavLink>
<NavLink className="navbar-list-item" to="/settings">
<span className="navbar-list-item-label">Settings</span>
</NavLink>
</ol>
</div>
);
}

View File

@ -0,0 +1,14 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import "../assets/stylesheets/settings.scss";
export default class SettingsComponent extends Component {
render() {
return (
<div className="settings">
<img className="settings-image" src={BeldenLogo} alt="Belden" />
<div className="settings-fieldContainer"></div>
</div>
);
}
}

View File

@ -0,0 +1,14 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import "../assets/stylesheets/summary.scss";
export default class SummaryComponent extends Component {
render() {
return (
<div className="summary">
<img className="summary-image" src={BeldenLogo} alt="Belden" />
<div className="summary-fieldContainer"></div>
</div>
);
}
}

View File

@ -1,57 +1,54 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import HomeRoute from "./routes/HomeRoute";
import SearchRoute from "./routes/SearchRoute";
import SummaryRoute from "./routes/SummaryRoute";
import BrowseRoute from "./routes/BrowseRoute";
import SettingsRoute from "./routes/SettingsRoute";
import SocketHandler from "./assets/classes/SocketHandler";
import MapRoute from "./routes/MapRoute";
// Root
const root = ReactDOM.createRoot(document.getElementById("root"));
const router = createBrowserRouter([
{
path: "/",
element: <HomeRoute></HomeRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/home",
element: <HomeRoute></HomeRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/search",
element: <SearchRoute></SearchRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/settings",
element: <SettingsRoute></SettingsRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
]);
// Socket handler
console.log("Connecting to WebSocket server.");
const socket = new WebSocket("ws://localhost:9000");
socket.addEventListener("open", function (event) {
console.log("Websocket connected.");
console.log("Welcome to Belden Jukebox!");
init();
});
root.render(
<React.StrictMode>
<RouterProvider router={router} />
// Initialize the app
const init = () => {
const socketHandler = new SocketHandler(socket);
<span
style={{
position: "absolute",
top: "95%",
left: "0%",
color: "red",
backgroundImage: "none",
width: "270px",
height: "30px",
backgroundColor: "white",
borderRadius: "20px",
textAlign: "center",
padding: "5px 0 0px 0",
outline: "solid black 1px",
}}
>
Jukebox Draft UI (not styled yet)
</span>
</React.StrictMode>
);
const router = createBrowserRouter([
{
path: "/",
element: <SummaryRoute socketHandler={socketHandler}></SummaryRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/browse",
element: <BrowseRoute socketHandler={socketHandler}></BrowseRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/settings",
element: <SettingsRoute socketHandler={socketHandler}></SettingsRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/map",
element: <MapRoute socketHandler={socketHandler}></MapRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
]);
root.render(
<div>
<RouterProvider router={router} />
</div>
);
};

20
src/routes/BrowseRoute.js Normal file
View File

@ -0,0 +1,20 @@
import React, { Component } from "react";
import NavBar from "../components/NavBar";
import BrowseComponent from "../components/BrowseComponent";
import "../assets/stylesheets/app.scss";
export default class BrowseRoute extends Component {
constructor(props) {
super(props);
document.title = "Browse";
}
render() {
return (
<div className="container">
<NavBar />
<BrowseComponent socketHandler={this.props.socketHandler} />
</div>
);
}
}

View File

@ -1,17 +1,19 @@
import React, { Component } from "react";
import NavBar from "../components/NavBar";
import MapComponent from "../components/MapComponent";
import "../assets/stylesheets/app.scss";
export default class SearchRoute extends Component {
export default class MapRoute extends Component {
constructor(props) {
super(props);
document.title = "ITR - Search";
document.title = "Map";
}
render() {
return (
<div className="container">
<NavBar />
<MapComponent socketHandler={this.props.socketHandler} />
</div>
);
}

View File

@ -1,17 +1,19 @@
import React, { Component } from "react";
import NavBar from "../components/NavBar";
import SettingsComponent from "../components/SettingsComponent";
import "../assets/stylesheets/app.scss";
export default class SettingsRoute extends Component {
constructor(props) {
super(props);
document.title = "ITR - Settings";
document.title = "Settings";
}
render() {
return (
<div className="container">
<NavBar />
<SettingsComponent socketHandler={this.props.socketHandler} />
</div>
);
}

View File

@ -1,19 +1,19 @@
import React, { Component } from "react";
import NavBar from "../components/NavBar";
import HomeComponent from "../components/HomeComponent";
import SummaryComponent from "../components/SummaryComponent";
import "../assets/stylesheets/app.scss";
export default class HomeRoute extends Component {
constructor(props) {
super(props);
document.title = "ITR - Home";
document.title = "Summary";
}
render() {
return (
<div className="container">
<NavBar />
<HomeComponent />
<SummaryComponent socketHandler={this.props.socketHandler} />
</div>
);
}

156
websocket_test.html Normal file
View File

@ -0,0 +1,156 @@
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Test</title>
<style>
footer {
background-color: #333;
color: #fff;
text-align: center;
padding: 10px 0;
position: fixed;
bottom: 0;
width: 100%;
display: flex;
justify-content: space-around;
}
.service-box {
width: 150px;
padding: 10px;
border-radius: 5px;
}
.service-up {
background-color: green;
}
.service-down {
background-color: red;
}
</style>
<script>
// class Service {
// constructor(name, status) {
// this.name = name
// this.status = status
// }
// }
var updatedTime = new Date();
// Initial status of services
// var serviceA = new Service("234234", 'down');
// var serviceBStatus = 'down';
// var serviceCStatus = 'down';
document.addEventListener("DOMContentLoaded", function () {
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:9000');
// Connection opened
socket.addEventListener('open', function (event) {
console.log("Connected to WebSocket server");
updatedTime = new Date();
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server', event.data);
let messages = document.getElementById('messages');
let message = document.createElement('li');
message.textContent = "Received: " + event.data;
messages.appendChild(message);
updatedTime = new Date();
});
// Send a message to the server
function sendMessage() {
let message = document.getElementById('messageInput').value;
socket.send(message);
console.log('Message sent', message);
}
// This function just sends a ping to make sure the server is there and it is able to responds
function ping() {
let message = `{ "call": "send", "type": "log", "data": "This is a ping!!" }`;
socket.send(message);
console.log('Message sent', message);
}
//setInterval(ping, 1500);
// setInterval(() => {
// updateServiceStatus('serviceA', 'down');
// }, 2000);
// Bind send message function to button click
document.getElementById('sendMessage').addEventListener('click', sendMessage);
});
</script>
</head>
<body>
<h2>WebSocket Test</h2>
<textarea rows="4" cols="50" id="messageInput" placeholder="Type a message..."> </textarea>
<button id="sendMessage">Send Message</button>
<p>Example JSON</p>
<p>{ "type": "cable_map", "call": "request", "data": { } }</p>
<p>{ "type": "log", "call": "send", "data": "123123" }</p>
<p>Messages/Logs</p>
<ul id="messages"></ul>
<footer>
<!-- <div id="serviceA" class="service-box"></div>
<div id="serviceB" class="service-box"></div>
<div id="serviceC" class="service-box"></div> -->
<div id="clock"></div>
</footer>
<script>
// // Function to update service status
// function updateServiceStatus(service) {
// // serviceId, status
// var serviceElement = document.getElementById(service.serviceId);
// // updateClock();
// if (service.status === 'up') {
// serviceElement.innerHTML = '<h3>' + service.serviceId + '</h3><p>Running</p>';
// serviceElement.classList.remove('service-down');
// serviceElement.classList.add('service-up');
// } else {
// serviceElement.innerHTML = '<h3>' + service.serviceId + '</h3><p>Down</p>';
// serviceElement.classList.remove('service-up');
// serviceElement.classList.add('service-down');
// }
// }
// // Update service statuses
// updateServiceStatus('node.js (for this page)', serviceAStatus);
// updateServiceStatus('Python WebSocket', serviceBStatus);
// updateServiceStatus('serviceC', serviceCStatus);
// Function to update clock
function updateClock() {
var now = new Date();
now = now.getTime() - updatedTime.getTime();
// console.log(now)
document.getElementById('clock').textContent = 'Milliseconds Since Update: ' + now.toString().padStart(6, '0');
}
// Update clock every second
setInterval(updateClock, 100);
</script>
</body>
</html>