Compare commits

..

47 Commits

Author SHA1 Message Date
03ed1f22e8 qr code added 2024-08-20 00:18:20 -04:00
b0c6bf37b8 possible fix for arm? :P 2024-08-19 12:43:14 -04:00
52199477d5 possible fix for arm? :P 2024-08-19 12:38:10 -04:00
2798c9d759 Settings page revamp 2024-08-16 21:45:46 -04:00
d27071dbd3 Co-authored-by: Lucas Ferguson <LucasFerguson@users.noreply.github.com>
Co-authored-by: Dustin Thomas <stdio@cptlobster.dev>
2024-08-16 20:01:38 -04:00
9dcebb9d88 Arm in motion modal 2024-08-16 18:21:34 -04:00
08eebd400b bug fix 2024-07-29 21:55:24 -04:00
2b0216488d change wording 2024-07-29 14:41:24 -05:00
16cd3989a7 Rename to highlight 2024-07-29 14:16:48 -05:00
4b5cb19bd8 Remove restart button, double click 2024-07-29 14:00:55 -05:00
98ff934797 Just kidding, put it back 2024-07-29 13:29:48 -05:00
8d363088eb Remove "show" button 2024-07-29 13:20:33 -05:00
d2371c85ff Add datasheet popup 2024-07-29 13:10:53 -05:00
5a3943ae46 Fix Browse page not loading 2024-07-29 12:03:39 -05:00
a2e94baadc fixed sizes 2024-05-14 19:50:56 -04:00
bdcc1d7613 fixed modal sizes 2024-05-14 19:45:16 -04:00
359778be51 Fix browse page image URL 2024-05-14 17:37:06 -05:00
3781e9adcf v1 2024-05-14 17:52:39 -04:00
2e57253ac0 v1 2024-05-14 17:50:06 -04:00
9a8efb5418 v1 2024-05-14 17:49:12 -04:00
1bdc2b1438 Try to guess hostname for websocket 2024-05-14 16:05:57 -05:00
8fe33095dd v1? 2024-05-13 02:34:27 -04:00
5a8abf08bd animations, loading, yadayada 2024-05-12 21:09:25 -04:00
8824070547 sizing change 2024-05-12 19:35:32 -04:00
8964afe3cf bye bye hover effect 😭 2024-05-12 19:29:31 -04:00
c3c5348370 search added 2024-05-12 19:16:57 -04:00
107858c363 map done 2024-05-12 18:00:01 -04:00
67cb5f82a9 fixed statistics 2024-05-10 12:56:39 -04:00
0d650bbcc0 remove my init :) init(); 2024-05-10 11:47:50 -05:00
9de494d6ae Adding Statists Page! 2024-05-10 11:18:41 -05:00
e784bbfa64 Adding graphs 2024-05-10 09:57:32 -05:00
ac94ad837f local push 2024-05-10 01:50:18 -04:00
fa8f1441c8 summary start 2024-05-10 00:02:25 -04:00
bc4d6a6ced Merge branch 'main' of https://git.myitr.org/Jukebox/jukebox-web 2024-05-09 23:40:22 -04:00
51f50d59fe Merge branch 'main' of https://git.myitr.org/Jukebox/jukebox-web 2024-05-09 22:40:15 -05:00
0642af3c4d browse page is functional now 2024-05-09 23:40:11 -04:00
132afabf73 Grid and Full Dashboard is working 2024-05-09 22:40:09 -05:00
a883b0b206 current 2024-05-09 15:16:28 -04:00
ecf56bd1ee tables done (i think) 2024-05-08 22:46:20 -04:00
8cbc7e451a Merge branch 'main' of https://git.myitr.org/Jukebox/jukebox-web 2024-05-08 21:57:59 -04:00
6a5aecdc4d test tables 2024-05-08 21:57:40 -04:00
3db7609bd5 Grid of Graphs with a gap I can not remove 2024-05-08 20:21:12 -05:00
ee0ab01355 Grid of Graphs is not working 2024-05-08 16:44:39 -05:00
c82ef2e7af getcable 2024-05-08 17:04:24 -04:00
6656e3ba43 getcable 2024-05-08 17:01:33 -04:00
e55c7b5b5a Small changes to the Summary Page 2024-05-08 15:49:06 -05:00
4cea1b0832 Updates 2024-05-07 21:53:49 -04:00
40 changed files with 2784 additions and 359 deletions

158
package-lock.json generated
View File

@ -11,17 +11,20 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"animate.css": "^4.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3",
"react-keep-alive": "^2.5.2",
"react-modal": "^3.16.1",
"react-router-dom": "^6.25.1",
"react-scripts": "^5.0.1",
"sass": "^1.70.0",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"stylelint": "^16.3.1",
"stylelint": "^16.5.0",
"stylelint-config-standard-scss": "^13.0.0",
"stylelint-scss": "^6.2.1"
"stylelint-scss": "^6.3.0"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@ -3617,9 +3620,10 @@
}
},
"node_modules/@remix-run/router": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==",
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz",
"integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@ -4266,6 +4270,12 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/@types/js-md5": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@types/js-md5/-/js-md5-0.4.3.tgz",
"integrity": "sha512-BIga/WEqTi35ccnGysOuO4RmwVnpajv9oDB/sDQSY2b7/Ac7RyYR30bv7otZwByMvOJV9Vqq6/O1DFAnOzE4Pg==",
"license": "MIT"
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@ -4969,6 +4979,11 @@
"ajv": "^6.9.1"
}
},
"node_modules/animate.css": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz",
"integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ=="
},
"node_modules/ansi-escapes": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
@ -6328,9 +6343,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==",
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz",
"integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==",
"dev": true,
"engines": {
"node": ">=12 || >=16"
@ -8026,6 +8041,11 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
},
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -8907,6 +8927,21 @@
"he": "bin/he"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"license": "BSD-3-Clause",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@ -11749,6 +11784,12 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/js-md5": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.7.3.tgz",
"integrity": "sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==",
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -14699,6 +14740,45 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/react-keep-alive": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/react-keep-alive/-/react-keep-alive-2.5.2.tgz",
"integrity": "sha512-CoEsY5xE6rT31Z4p4UGZ/Crp0nZN+CY61ZflKzBGKB3D315jQMe2l8G5OrSEJ86V4stua7lSeFDIeG3DCuY2Rg==",
"license": "MIT",
"dependencies": {
"@types/js-md5": "^0.4.2",
"hoist-non-react-statics": "^3.3.0",
"js-md5": "^0.7.3"
},
"peerDependencies": {
"react": ">=16.3.0",
"react-dom": ">=16.3.0",
"react-router-dom": ">=5.0.0"
}
},
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"node_modules/react-modal": {
"version": "3.16.1",
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz",
"integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==",
"dependencies": {
"exenv": "^1.2.0",
"prop-types": "^15.7.2",
"react-lifecycles-compat": "^3.0.0",
"warning": "^4.0.3"
},
"engines": {
"node": ">=8"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18",
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18"
}
},
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@ -14708,11 +14788,12 @@
}
},
"node_modules/react-router": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
"version": "6.25.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz",
"integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.15.3"
"@remix-run/router": "1.18.0"
},
"engines": {
"node": ">=14.0.0"
@ -14722,12 +14803,13 @@
}
},
"node_modules/react-router-dom": {
"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==",
"version": "6.25.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz",
"integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.15.3",
"react-router": "6.22.3"
"@remix-run/router": "1.18.0",
"react-router": "6.25.1"
},
"engines": {
"node": ">=14.0.0"
@ -16146,20 +16228,20 @@
}
},
"node_modules/stylelint": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.3.1.tgz",
"integrity": "sha512-/JOwQnBvxEKOT2RtNgGpBVXnCSMBgKOL2k7w0K52htwCyJls4+cHvc4YZgXlVoAZS9QJd2DgYAiRnja96pTgxw==",
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.5.0.tgz",
"integrity": "sha512-IlCBtVrG+qTy3v+tZTk50W8BIomjY/RUuzdrDqdnlCYwVuzXtPbiGfxYqtyYAyOMcb+195zRsuHn6tgfPmFfbw==",
"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",
"@csstools/selector-specificity": "^3.0.3",
"@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-functions-list": "^3.2.2",
"css-tree": "^2.3.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
@ -16188,7 +16270,7 @@
"strip-ansi": "^7.1.0",
"supports-hyperlinks": "^3.0.0",
"svg-tags": "^1.0.0",
"table": "^6.8.1",
"table": "^6.8.2",
"write-file-atomic": "^5.0.1"
},
"bin": {
@ -16275,12 +16357,12 @@
}
},
"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==",
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.3.0.tgz",
"integrity": "sha512-8OSpiuf1xC7f8kllJsBOFAOYp/mR/C1FXMVeOFjtJPw+AFvEmC93FaklHt7MlOqU4poxuQ1TkYMyfI0V+1SxjA==",
"dev": true,
"dependencies": {
"known-css-properties": "^0.29.0",
"known-css-properties": "^0.30.0",
"postcss-media-query-parser": "^0.2.3",
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-selector-parser": "^6.0.15",
@ -16293,16 +16375,10 @@
"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==",
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz",
"integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==",
"dev": true,
"funding": [
{
@ -17467,6 +17543,14 @@
"makeerror": "1.0.12"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",

View File

@ -6,9 +6,12 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"animate.css": "^4.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3",
"react-keep-alive": "^2.5.2",
"react-modal": "^3.16.1",
"react-router-dom": "^6.25.1",
"react-scripts": "^5.0.1",
"sass": "^1.70.0",
"web-vitals": "^2.1.4"
@ -39,9 +42,9 @@
]
},
"devDependencies": {
"stylelint": "^16.3.1",
"stylelint": "^16.5.0",
"stylelint-config-standard-scss": "^13.0.0",
"stylelint-scss": "^6.2.1"
"stylelint-scss": "^6.3.0"
},
"stylelint": {
"extends": [

View File

@ -5,39 +5,27 @@
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
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>Belden Jukebox</title>
</head>
<body>
<noscript>Belden Jukebox UI</noscript>
<noscript>
<p>
<b>Belden Jukebox Error:</b><br />
JavaScript is required to run this application.<br />
Please enable JavaScript in your browser.<br /><br />
<a
href="https://www.enable-javascript.com/"
target="_blank"
rel="noopener noreferrer"
>
Here are the instructions how to enable JavaScript in your web
browser!
</a>
</p>
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -11,7 +11,7 @@ $white: #fff;
180deg,
rgb(0 37 84 / 100%) 0%,
rgb(0 124 190 / 100%) 50%,
rgb(255, 255, 255) 100%
rgb(255 255 255) 100%
);
background-color: transparent;
overflow-y: visible;
@ -35,6 +35,7 @@ $white: #fff;
width: auto;
height: 200px;
background-color: transparent;
margin-top: 50px;
}
.browse-fieldContainer {
@ -48,65 +49,142 @@ $white: #fff;
overflow: hidden;
background-color: transparent;
margin-bottom: 50px;
animation: fadeInUp;
animation-duration: 0.5s;
}
.browse-title {
width: 80%;
height: auto;
font-size: 32px;
font-weight: bold;
color: $white;
font-family: "Gotham Medium";
margin: 10px;
background-color: transparent;
margin-bottom: 20px;
text-align: left;
}
.browse-cable {
width: 80%;
height: 100px;
background: $white;
height: 150px;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: row;
border-radius: 20px;
border: 1px solid $gray;
padding: 25px;
margin-bottom: 5px;
margin-top: 5px;
transition: all 0.3s ease-in-out;
cursor: pointer;
text-decoration: none;
}
.browse-cable:hover {
transform: translate3d(-5px, -5px, 0);
background-color: transparent;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
}
.browse-cable-image {
width: auto;
height: 100%;
background-color: transparent;
margin-right: 10px;
height: 75%;
margin-right: 25px;
margin-left: 20px;
background-color: white;
border: $gray solid 1px;
border-radius: 10px;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
aspect-ratio: 1/1;
}
.browse-cable-label {
width: 90%;
width: 83%;
height: auto;
background-color: transparent;
}
.browse-cable-arrow {
width: auto;
height: auto;
font-size: 45px;
font-family: "Gotham Light";
transform:scaleY(2);
color: $gray;
font-size: 35px;
margin-right: 20px;
transform: scaleY(2);
font-family: "Gotham Book";
color: $medium-blue;
background-color: transparent;
}
.browse-cable-name, .browse-cable-brand, .browse-cable-description, .browse-cable-short {
.browse-cable-name {
background-color: transparent;
font-size: 20px;
color: $medium-blue;
width: auto;
height: auto;
font-family: "Gotham Bold";
margin-bottom: 2px;
}
.browse-cable-description {
background-color: transparent;
font-size: 18px;
color: $medium-blue;
width: auto;
height: auto;
font-family: "Gotham Medium";
margin-bottom: 10px;
}
.browse-cable-name {
padding-bottom: 10px;
.browse-cable-brand,
.browse-cable-short,
.browse-cable-position,
.browse-cable-category {
background-color: transparent;
font-size: 15px;
margin-bottom: 2px;
color: $light-blue;
width: auto;
font-family: "Gotham Medium";
height: auto;
}
.browse-cable-brand, .browse-cable-description, .browse-cable-short {
color: $black;
font-size: 16px;
}
.browse-search {
width: 80%;
height: 50px;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: row;
border-radius: 20px;
border: 1px solid $gray;
margin-bottom: 5px;
margin-top: 5px;
transition: all 0.3s ease-in-out;
text-decoration: none;
background-color: transparent;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
}
.browse-search input {
width: 100%;
height: 50px;
border-radius: 20px 0 0 20px;
background-color: transparent;
outline: none;
box-shadow: none;
font-size: 18px;
font-family: "Gotham Medium";
color: $dark-blue;
border: none;
border-right: none;
padding-left: 20px;
padding-top: 2px;
}

View File

@ -11,7 +11,7 @@ $white: #fff;
180deg,
rgb(0 37 84 / 100%) 0%,
rgb(0 124 190 / 100%) 50%,
rgb(255, 255, 255) 100%
rgb(255 255 255) 100%
);
background-color: transparent;
overflow-y: visible;
@ -35,6 +35,7 @@ $white: #fff;
width: auto;
height: 200px;
background-color: transparent;
margin-top: 50px;
}
.cable-fieldContainer {
@ -47,4 +48,328 @@ $white: #fff;
flex-direction: column;
overflow: hidden;
background-color: transparent;
}
animation: fadeInUp;
animation-duration: 0.5s;
}
.cable-main {
width: 80%;
height: 200px;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
border-radius: 20px;
border: 1px solid $gray;
padding: 25px;
margin-bottom: 5px;
margin-top: 5px;
transition: all 0.3s ease-in-out;
text-decoration: none;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
}
.cable-actions {
width: calc(80% + 50px);
height: 60px;
background-color: transparent;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin-bottom: 25px;
margin-top: 5px;
transition: all 0.3s ease-in-out;
text-decoration: none;
overflow: visible;
}
.cable-actions-button,
.cable-actions-back,
.cable-tables-div {
width: 32%;
height: 100%;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
border-radius: 20px;
border: 1px solid $gray;
transition: all 0.3s ease-in-out;
text-decoration: none;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
cursor: pointer;
overflow: visible;
}
.cable-actions-back {
width: auto;
background: linear-gradient(
-30deg,
rgb(187 194 236) 0%,
rgb(255 255 255 / 100%) 100%
);
}
.cable-actions-button span,
.cable-actions-back span {
text-align: center;
font-family: "Gotham Medium";
font-size: 20px;
text-decoration: none;
color: $medium-blue;
width: auto;
height: auto;
margin: 20px;
background-color: transparent;
}
.cable-main-image,
.cable-main-imageqr {
aspect-ratio: 1/1;
width: auto;
height: 100%;
object-fit: cover;
background-color: white;
margin-right: 25px;
border: $gray solid 1px;
border-radius: 10px;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
}
.cable-main-imageqr {
margin-right: 0;
margin-left: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.cable-main-imageqr img {
width: 80%;
height: 80%;
object-fit: cover;
background-color: white;
border: $gray solid 1px;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
}
.cable-main-label {
width: 60%;
height: 100%;
background-color: transparent;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.cable-main-name {
background-color: transparent;
font-size: 32px;
color: $medium-blue;
width: auto;
height: auto;
font-family: "Gotham Bold";
margin-bottom: 5px;
}
.cable-main-description {
background-color: transparent;
font-size: 18px;
color: $medium-blue;
width: auto;
height: auto;
font-family: "Gotham Medium";
margin-bottom: 30px;
}
.cable-main-brand,
.cable-main-short,
.cable-main-position,
.cable-main-category {
background-color: transparent;
font-size: 16px;
color: $light-blue;
width: auto;
height: auto;
font-family: "Gotham Medium";
}
.cable-tables {
width: calc(80% + 70px);
height: auto;
background-color: transparent;
display: flex;
flex-flow: row wrap;
align-items: stretch;
flex-grow: 1;
justify-content: space-between;
margin-bottom: 50px;
margin-top: 5px;
text-decoration: none;
overflow: visible;
box-sizing: border-box;
}
.cable-tables-div {
width: 31%;
height: auto;
cursor: default;
display: flex;
justify-content: flex-start;
align-items: center;
padding-top: 20px;
padding-bottom: 20px;
flex-direction: column;
box-sizing: border-box;
flex-grow: 1;
margin: 13px;
}
.cable-tables-div table {
display: inline-table;
width: 90%;
height: auto;
background-color: transparent;
border: $light-blue solid 2px;
border-radius: 20px;
table-layout: fixed;
border-spacing: 0;
}
.row,
.head,
.body {
width: auto;
height: auto;
background-color: transparent;
padding: 10px;
text-align: center;
outline: $light-blue solid 1px;
}
.head {
font-family: "Gotham Bold";
font-size: 18px;
color: $medium-blue;
border-top: none;
}
.body {
font-family: "Gotham Medium";
font-size: 16px;
color: $medium-blue;
}
.thead {
width: auto;
height: auto;
background-color: transparent;
}
.tbody {
width: auto;
height: auto;
background-color: transparent;
}
td:first-child,
th:first-child {
border-left: none;
}
.cable-tables-div-title {
width: 90%;
height: auto;
background-color: transparent;
font-family: "Gotham Bold";
font-size: 24px;
color: $dark-blue;
margin-bottom: 15px;
margin-top: 15px;
padding-left: 10px;
}
.modal-container {
width: 100%;
height: 100%;
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.modal-title,
.modal-body,
.modal-close {
width: auto;
height: auto;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
flex-direction: column;
}
.modal-datasheet {
width: 1000px;
height: 700px;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
flex-direction: column;
margin-top: 10px;
margin-bottom: 10px;
}
.modal-title span {
width: auto;
height: auto;
font-family: "Gotham Bold";
font-size: 32px;
color: $dark-blue;
background-color: transparent;
margin-bottom: 5px;
}
.modal-body span {
width: auto;
height: auto;
background-color: transparent;
font-family: "Gotham Medium";
font-size: 18px;
color: $medium-blue;
margin-top: 10px;
margin-bottom: 30px;
}
.modal-close span {
width: auto;
height: auto;
background-color: transparent;
font-family: "Gotham Medium";
font-size: 18px;
color: $dark-blue;
}
.modal-close {
cursor: pointer;
padding: 15px 35px;
border-radius: 20px;
background-color: $gray;
box-shadow: 0 4px 4px rgb(0 0 0 / 25%);
transition: all 0.3s ease-in-out;
}

View File

@ -10,34 +10,265 @@ $white: #fff;
background: linear-gradient(
180deg,
rgb(0 37 84 / 100%) 0%,
rgb(0 124 190 / 100%) 26%,
rgb(255 255 255) 39%,
rgb(255 255 255 / 100%) 100%
rgb(0 124 190 / 100%) 50%,
rgb(255 255 255) 100%
);
background-color: transparent;
overflow-y: visible;
width: calc(100% - 300px);
height: auto;
overflow-y: visible;
display: flex;
align-items: center;
display: block;
justify-content: center;
flex-direction: column;
overflow: visible;
align-items: center;
}
.map-image {
width: auto;
height: 250px;
width: 100%;
height: 200px;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
}
.map-image img {
width: auto;
height: 200px;
background-color: transparent;
margin-top: 50px;
}
.map-fieldContainer {
width: 100%;
min-height: calc(100% - 250px);
min-height: calc(100% - 200px);
height: auto;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
overflow: visible;
background-color: transparent;
animation: fadeInUp;
animation-duration: 0.5s;
}
.map-title {
width: 80%;
height: auto;
font-size: 32px;
font-weight: bold;
color: $white;
font-family: "Gotham Medium";
margin: 10px;
background-color: transparent;
margin-bottom: 25px;
}
.map-boxContainer {
width: 80%;
height: auto;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
background-color: transparent;
overflow: visible;
}
.map-box,
.map-details {
height: 68vh;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
border-radius: 20px;
border: 1px solid $gray;
transition: all 0.3s ease-in-out;
text-decoration: none;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
overflow: visible;
}
.map-box {
width: 60%;
}
.map-details {
width: 38%;
justify-content: space-between;
}
.map-box-row {
width: 100%;
height: 60px;
background-color: transparent;
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
overflow: visible;
}
.map-box-circle,
.map-box-spacer {
width: 60px;
height: 60px;
aspect-ratio: 1/1;
border-radius: 50%;
background: linear-gradient(
15deg,
rgb(223 223 223) 0%,
rgb(255 255 255) 100%
);
margin-left: 3px;
margin-right: 3px;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease-in-out;
}
.map-box-circle {
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
cursor: pointer;
}
.map-box-spacer {
background-color: transparent;
box-shadow: 0 2px 2px rgb(0 0 0 / 0%);
border: 1px solid transparent;
background: transparent;
}
.map-box-circle-inner {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: transparent;
display: flex;
align-items: flex-start;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
.map-box-circle-inner span {
width: auto;
height: auto;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
font-size: 16px;
font-weight: bold;
color: $dark-blue;
margin-top: 2px;
font-family: "Gotham Bold";
}
.map-cable-image {
width: auto;
height: 35%;
aspect-ratio: 1/1;
border: $gray solid 1px;
border-radius: 20px;
background-color: white;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
margin-bottom: 30px;
margin-top: 30px;
}
.map-cable-label {
width: 90%;
height: 80%;
background-color: transparent;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
overflow: hidden;
}
.map-cable-name {
background-color: transparent;
font-size: 28px;
color: $medium-blue;
width: 100%;
text-align: left;
height: auto;
font-family: "Gotham Bold";
margin-bottom: 3px;
}
.map-cable-shortdescription {
background-color: transparent;
font-size: 18px;
color: $medium-blue;
width: 100%;
text-align: left;
height: auto;
font-family: "Gotham Medium";
margin-bottom: 15px;
}
.map-cable-description {
background-color: transparent;
font-size: 16px;
color: $black;
width: 100%;
text-align: left;
height: auto;
font-family: "Gotham Medium";
margin-bottom: 15px;
}
.map-cable-brand,
.map-cable-short,
.map-cable-position,
.map-cable-category {
background-color: transparent;
font-size: 15px;
margin-bottom: 5px;
color: $light-blue;
width: 100%;
text-align: left;
height: auto;
font-family: "Gotham Medium";
}
.map-cable-moreinfo {
width: 200px;
height: 50px;
border-radius: 20px;
background: linear-gradient(
15deg,
rgb(223 223 223) 0%,
rgb(255 255 255) 100%
);
margin-left: 3px;
margin-right: 3px;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease-in-out;
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
cursor: pointer;
margin-bottom: 40px;
text-decoration: none;
}
.map-cable-moreinfo span {
width: auto;
height: auto;
font-size: 20px;
margin-top: 2px;
color: $medium-blue;
font-family: "Gotham Bold";
background-color: transparent;
}

View File

@ -8,16 +8,17 @@ $white: #fff;
.navbar {
width: 300px;
height: 100%;
height: auto;
display: flex;
flex-direction: column;
align-items: center;
border-right: $gray solid 1px;
justify-content: space-between;
}
.navbar-top {
width: 90%;
height: 100%;
height: auto;
display: flex;
align-items: left;
justify-content: flex-start;
@ -25,6 +26,22 @@ $white: #fff;
background-color: transparent;
}
.navbar-top-container {
width: 100%;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
padding-top: 20px;
}
.navbar-top-secret {
width: 40px;
height: 40px;
background-color: transparent;
}
.navbar-top-hamburger {
width: 45px;
height: 45px;
@ -35,10 +52,9 @@ $white: #fff;
justify-content: left;
padding-left: 4px;
text-align: center;
margin-top: 20px;
margin-bottom: 15px;
color: $light-blue;
color: $medium-blue;
background-color: transparent;
margin-left: 2px;
}
.navbar-top h1 {
@ -53,49 +69,8 @@ $white: #fff;
transition: all 0.3s ease-in-out;
}
.navbar-top h1:hover {
color: $light-blue;
}
.navbar-search {
width: 100%;
height: auto;
display: flex;
border-radius: 15px;
padding: 0;
margin: 0;
}
.navbar-search input {
width: 80%;
height: auto;
padding: 10px;
border-radius: 15px 0 0 15px;
background-color: $white;
outline: none;
box-shadow: none;
font-size: 16px;
font-family: "Gotham Medium";
color: $dark-blue;
border: solid $light-blue 2px;
border-right: none;
}
.navbar-search button {
width: 20%;
height: auto;
border-radius: 0 15px 15px 0;
background-color: $white;
outline: none;
box-shadow: none;
font-size: 16px;
font-family: "Gotham Medium";
border: solid $light-blue 2px;
cursor: pointer;
}
.navbar-list {
margin-top: 20px;
margin-top: 10px;
width: 100%;
height: auto;
display: flex;
@ -104,7 +79,9 @@ $white: #fff;
flex-direction: column;
}
.navbar-list-item {
.navbar-list-item,
.navbar-return,
.navbar-settings {
width: 100%;
height: 50px;
margin: 0 0 3px;
@ -118,11 +95,9 @@ $white: #fff;
cursor: pointer;
}
.navbar-list-item:hover {
background-color: $hover-blue;
}
.navbar-list-item span {
.navbar-list-item span,
.navbar-return span,
.navbar-settings span {
background-color: transparent;
width: auto;
height: auto;
@ -131,3 +106,124 @@ $white: #fff;
color: $dark-blue;
margin-left: 10px;
}
.navbar-settings {
width: 40px;
height: 40px;
justify-content: center;
align-items: center;
margin: 0;
background-color: $medium-blue;
}
.navbar-settings span {
margin: 0;
}
.navbar-return {
width: 90%;
align-items: center;
justify-content: center;
background-color: $medium-blue;
margin-bottom: 15px;
}
.navbar-return span {
color: $white;
margin-left: 0;
}
.modal-container {
width: 100%;
height: 100%;
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.modal-title,
.modal-body,
.modal-close,
.modal-closeX,
.modal-return {
width: auto;
height: auto;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
flex-direction: column;
}
.modal-title span {
width: auto;
height: auto;
font-family: "Gotham Bold";
font-size: 32px;
color: $dark-blue;
background-color: transparent;
margin-bottom: 5px;
}
.modal-body span {
width: auto;
height: auto;
background-color: transparent;
font-family: "Gotham Medium";
font-size: 18px;
color: $medium-blue;
margin-top: 10px;
margin-bottom: 30px;
}
.modal-tray {
width: auto;
height: auto;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: transparent;
margin-bottom: 20px;
overflow: visible;
}
.modal-close,
.modal-return,
.modal-closeX {
cursor: pointer;
padding: 15px 35px;
border-radius: 20px;
background-color: $gray;
box-shadow: 0 4px 4px rgb(0 0 0 / 25%);
transition: all 0.3s ease-in-out;
margin-bottom: 10px;
}
.modal-close span,
.modal-return span,
.modal-closeX span {
width: auto;
height: auto;
background-color: transparent;
font-family: "Gotham Medium";
font-size: 18px;
margin-top: 3px;
color: $dark-blue;
}
.modal-closeX {
background-color: rgb(255, 152, 152);
box-shadow: 0 4px 4px rgba(94, 1, 1, 0.25);
}
.modal-return {
width: auto;
height: auto;
align-items: center;
justify-content: center;
margin-left: 10px;
margin-right: 10px;
}

View File

@ -10,34 +10,307 @@ $white: #fff;
background: linear-gradient(
180deg,
rgb(0 37 84 / 100%) 0%,
rgb(0 124 190 / 100%) 26%,
rgb(255 255 255) 39%,
rgb(255 255 255 / 100%) 100%
rgb(0 124 190 / 100%) 50%,
rgb(255 255 255) 100%
);
background-color: transparent;
overflow-y: visible;
width: calc(100% - 300px);
height: auto;
overflow-y: visible;
display: flex;
align-items: center;
display: block;
justify-content: center;
flex-direction: column;
overflow: visible;
align-items: center;
}
.settings-image {
width: auto;
height: 250px;
width: 100%;
height: 200px;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
}
.settings-image img {
width: auto;
height: 200px;
background-color: transparent;
margin-top: 50px;
}
.settings-fieldContainer {
width: 100%;
min-height: calc(100% - 250px);
min-height: calc(100% - 200px);
height: auto;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
overflow: hidden;
background-color: transparent;
margin-bottom: 50px;
animation: fadeInUp;
animation-duration: 0.5s;
}
.settings-title {
width: 80%;
height: auto;
font-size: 32px;
font-weight: bold;
color: $white;
font-family: "Gotham Medium";
margin: 10px;
background-color: transparent;
margin-bottom: 20px;
text-align: left;
}
.settings-grid,
.settings-creditsContainer {
width: 80%;
height: auto;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: flex-start;
justify-content: center;
flex-wrap: wrap;
flex-direction: column;
border-radius: 20px;
border: 1px solid $gray;
margin-bottom: 5px;
margin-top: 5px;
transition: all 0.3s ease-in-out;
text-decoration: none;
background-color: transparent;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
}
.settings-gridInner {
width: 100%;
height: auto;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
padding: 15px 0px 15px 0px;
background-color: transparent;
}
.settings-grid h2 {
width: 100%;
height: auto;
font-size: 24px;
font-weight: bold;
color: $dark-blue;
font-family: "Gotham Medium";
text-align: left;
padding: 20px 10px 0px 10px;
background-color: transparent;
}
.settings-creditsContainer {
height: 500px;
display: flex;
justify-content: center;
align-items: center;
}
.settings-button {
width: auto;
height: 40px;
border-radius: 15px;
background: linear-gradient(
15deg,
rgb(223 223 223) 0%,
rgb(255 255 255) 100%
);
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease-in-out;
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
cursor: pointer;
text-decoration: none;
margin-right: 10px;
margin-left: 10px;
}
.settings-button span {
width: auto;
height: auto;
font-size: 16px;
color: $medium-blue;
font-family: "Gotham Bold";
background-color: transparent;
padding: 10px;
}
.settings-form {
width: 100%;
height: auto;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
background-color: transparent;
}
// text box
#sendobject {
width: 90%;
height: 20px;
border-radius: 15px;
background-color: $white;
display: flex;
justify-content: flex-start;
align-items: flex-start;
transition: all 0.3s ease-in-out;
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
text-decoration: none;
margin-right: 10px;
margin-left: 10px;
padding: 10px;
margin-top: 10px;
margin-bottom: 10px;
border: 1px solid rgb(199, 199, 199);
text-align: left;
}
#sendobject:focus {
outline: none;
}
#sendobjectButton {
width: 10%;
height: 40px;
border-radius: 15px;
background: linear-gradient(
15deg,
rgb(223 223 223) 0%,
rgb(255 255 255) 100%
);
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease-in-out;
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
cursor: pointer;
text-decoration: none;
margin-right: 10px;
margin-left: 10px;
margin-top: 10px;
margin-bottom: 10px;
}
#creditsgrid {
width: 100%;
height: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
//background-color: red;
}
.entry {
width: 48%;
height: 150px;
border-radius: 15px;
background: linear-gradient(
15deg,
rgb(223 223 223) 0%,
rgb(255 255 255) 100%
);
display: flex;
justify-content: center;
align-items: center;
transition: all 0.3s ease-in-out;
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
text-decoration: none;
margin: 10px 10px 10px 10px;
}
.entry-image {
width: auto;
height: auto;
display: flex;
background-color: transparent;
}
.entry-img,
.entry-qr {
width: 110px;
height: 110px;
background: linear-gradient(
15deg,
rgb(223 223 223) 0%,
rgb(255 255 255) 100%
);
display: flex;
justify-content: center;
align-items: center;
border-radius: 15px;
margin: 10px;
filter: drop-shadow(5px 5px 2px rgb(0 0 0 / 15%));
border: 1px solid $gray;
}
.entry-qr {
margin: 0px;
padding: 8px;
width: 40px;
height: 40px;
border-radius: 50px;
background: white;
position: fixed;
bottom: 5px;
margin-left: 90px;
}
.entry-qr img {
border-radius: 0px;
width: auto;
height: auto;
background: red;
}
.entry-title {
width: 70%;
height: 50%;
margin-left: 30px;
display: flex;
align-items: flex-start;
justify-content: center;
flex-direction: column;
background-color: transparent;
}
.entry-title h2,
.entry-title h3 {
width: auto;
height: auto;
font-size: 24px;
font-weight: bold;
color: $dark-blue;
font-family: "Gotham Medium";
text-align: left;
background-color: transparent;
text-align: start;
margin: 0px;
padding: 0px;
}
.entry-title h2 {
margin-bottom: 5px;
}
.entry-title h3 {
font-size: 16px;
font-weight: normal;
color: $light-blue;
}

View File

@ -0,0 +1,112 @@
$dark-blue: #002554;
$medium-blue: #004990;
$light-blue: #007cbe;
$hover-blue: #25b3ff;
$black: #000;
$gray: #bdbdbd;
$white: #fff;
.statistics {
background: linear-gradient(
180deg,
rgb(0 37 84 / 100%) 0%,
rgb(0 124 190 / 100%) 50%,
rgb(255 255 255) 100%
);
background-color: transparent;
overflow-y: visible;
width: calc(100% - 300px);
height: auto;
display: block;
justify-content: center;
align-items: center;
}
.statistics-image {
width: 100%;
height: 200px;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
}
.statistics-image img {
width: auto;
height: 200px;
background-color: transparent;
margin-top: 50px;
}
.statistics-fieldContainer {
width: 100%;
min-height: calc(100% - 200px);
height: auto;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
overflow: hidden;
background-color: transparent;
margin-bottom: 50px;
animation: fadeInUp;
animation-duration: 0.5s;
}
.statistics-title {
width: 80%;
height: auto;
font-size: 32px;
font-weight: bold;
color: $white;
font-family: "Gotham Medium";
margin: 10px;
background-color: transparent;
margin-bottom: 25px;
}
.statistics-grid {
width: 80%;
height: auto;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: flex-start;
background-color: transparent;
overflow: visible;
}
.statistics-grid-container {
width: calc(((100% / 3)) - (12px));
height: 270px;
background: linear-gradient(
-30deg,
rgb(187 208 236) 0%,
rgb(255 255 255 / 100%) 100%
);
display: flex;
align-items: center;
justify-content: center;
border-radius: 20px;
border: 1px solid $gray;
transition: all 0.3s ease-in-out;
text-decoration: none;
filter: drop-shadow(0 4px 4px rgb(0 0 0 / 25%));
cursor: pointer;
overflow: visible;
margin-bottom: 15px;
}
.statistics-grid-container:nth-child(3n + 1) {
margin-right: 15px;
}
.statistics-grid-container:nth-child(3n) {
margin-left: 15px;
}
.statistics-iframe {
width: 95%;
height: 95%;
border-radius: 20px;
}

View File

@ -1,43 +0,0 @@
$dark-blue: #002554;
$medium-blue: #004990;
$light-blue: #007cbe;
$hover-blue: #25b3ff;
$black: #000;
$gray: #bdbdbd;
$white: #fff;
.summary {
background: linear-gradient(
180deg,
rgb(0 37 84 / 100%) 0%,
rgb(0 124 190 / 100%) 26%,
rgb(255 255 255) 39%,
rgb(255 255 255 / 100%) 100%
);
background-color: transparent;
width: calc(100% - 300px);
height: auto;
overflow-y: visible;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
overflow: visible;
}
.summary-image {
width: auto;
height: 250px;
background: transparent;
}
.summary-fieldContainer {
width: 100%;
min-height: calc(100% - 250px);
height: auto;
background-color: transparent;
display: flex;
align-items: flex-start;
justify-content: center;
flex-wrap: wrap;
}

View File

@ -1,75 +1,31 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import DefaultPartImg from "../assets/images/part.png";
import { NavLink } from "react-router-dom";
import cable from "../utils/Cable";
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 (
<NavLink className="browse-cable" to={"/cable/" + this.part_number}>
<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>
</NavLink>
);
}
}
export default class BrowseComponent extends Component {
constructor(props) {
super(props);
this.state = {
cableList: [],
isLoading: true,
};
}
componentDidMount() {
this.props.socket.send('{"type":"cable_map","call":"request","data":{}}');
this.props.socket.addEventListener("message", this.handleMessage);
setTimeout(() => {
this.setState({ isLoading: false });
}, 500);
}
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);
}
} catch (error) {}
};
browseParse(message) {
@ -77,11 +33,14 @@ export default class BrowseComponent extends Component {
let map = message.data.map;
for (let i = 0; i < map.length; i++) {
let part_number = map[i].part_number;
let image = map[i].image;
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;
let category = map[i].category;
let application = map[i].application;
cableList.push(
new cable(
part_number,
@ -89,7 +48,10 @@ export default class BrowseComponent extends Component {
name,
brand,
description,
short_description
short_description,
image,
category,
application
)
);
}
@ -100,6 +62,28 @@ export default class BrowseComponent extends Component {
this.props.socket.removeEventListener("message", this.handleMessage);
}
searchUpdate = () => {
let value = document.querySelector(".browse-search input").value;
this.props.socket.send(
`{"type":"cable_search","call":"request","data":{"string":"${value}"}}`
);
};
returnPlaceholder() {
return (
<div className="browse-cable">
<div className="browse-cable-image" />
<div className="browse-cable-label">
<div className="browse-cable-name"></div>
<div className="browse-cable-description"></div>
<div className="browse-cable-brand"></div>
<div className="browse-cable-position"></div>
</div>
<span className="browse-cable-arrow">{">"}</span>
</div>
);
}
render() {
return (
<div className="browse">
@ -107,9 +91,30 @@ export default class BrowseComponent extends Component {
<img src={BeldenLogo} alt="Belden" />
</div>
<div className="browse-fieldContainer">
{this.state.cableList.map((cableObj, index) => (
<React.Fragment key={index}>{cableObj.returnDiv()}</React.Fragment>
))}
<h1 className="browse-title">🛍 Browse</h1>
<div className="browse-search">
<input
type="text"
onChange={() => this.searchUpdate()}
placeholder="🔎 Start typing to search..."
/>
</div>
{this.state.isLoading ? (
<React.Fragment>
{this.returnPlaceholder()}
{this.returnPlaceholder()}
{this.returnPlaceholder()}
{this.returnPlaceholder()}
{this.returnPlaceholder()}
{this.returnPlaceholder()}
</React.Fragment>
) : (
this.state.cableList.map((cableObj, index) => (
<React.Fragment key={index}>
{cableObj.returnDiv()}
</React.Fragment>
))
)}
</div>
</div>
);

View File

@ -1,39 +1,442 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import DefaultPartImg from "../assets/images/part.png";
import DefaultQRImg from "../assets/images/default_qr.png";
import { NavLink } from "react-router-dom";
import Modal from "react-modal";
import "../assets/stylesheets/cabledetail.scss";
Modal.setAppElement("#root");
const hostname = window.location.hostname; // Get the hostname from the URL bar
class Cable {
constructor(cableData) {
this.partnum = cableData.partnum;
this.id = cableData.id;
this.brand = cableData.brand;
this.position = cableData.position;
this.image = cableData.image
? `http://${hostname}${cableData.image}`
: DefaultPartImg;
this.datasheet = `http://${hostname}${cableData.datasheet}`;
this.dynamicProps = {};
this.horizontal = [];
this.vertical = [];
this.orderedKeys = [];
this.description = cableData.description;
this.short_description = cableData.short_description;
this.application = cableData.application;
this.category = cableData.category;
this.qrcode = cableData.qrcode
? `http://${hostname}${cableData.qrcode}`
: DefaultQRImg;
if (this.description === undefined) {
if (this.short_description !== undefined) {
this.description = this.short_description;
} else if (this.application !== undefined) {
this.description = this.application;
} else if (this.category !== undefined) {
this.description = this.category;
} else {
this.description = "";
}
}
if (this.description !== undefined) {
this.description =
this.description.charAt(0).toUpperCase() + this.description.slice(1);
if (this.description.length > 200) {
this.description = this.description.substring(0, 200) + "...";
}
}
Object.keys(cableData).forEach((key) => {
if (
![
"partnum",
"id",
"brand",
"position",
"image",
"short_description",
"description",
"application",
"category",
"datasheet",
"qrcode",
].includes(key)
) {
this.dynamicProps[key] = cableData[key];
}
});
for (let key in this.dynamicProps) {
let data = this.dynamicProps[key];
let first = Object.keys(data)[0];
if (typeof data[first] === "object") {
this.horizontal.push(key);
} else {
this.vertical.push(key);
}
}
this.orderedKeys = this.orderedKeys.concat(this.vertical);
this.orderedKeys = this.orderedKeys.concat(this.horizontal);
for (let i = 0; i < this.orderedKeys.length; i++) {
let key = this.orderedKeys[i];
if (!isNaN(key)) {
this.orderedKeys.splice(i, 1);
i--;
}
try {
let data = this.dynamicProps[key];
let first = Object.keys(data)[0];
if (data[first] !== undefined) {
if (typeof data[first] === "string") {
if (first === "" || data[first] === "") {
this.orderedKeys.splice(i, 1);
i--;
}
}
}
} catch (error) {}
}
}
}
export default class CableDetailComponent extends Component {
constructor(props) {
super(props);
this.state = {
cableDetails: null,
modalOpen_show: false,
modalOpen_datasheet: false,
modalOpacity: 0,
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
}
// componentDidMount() {
// this.props.socket.send('{"type":"cable_map","call":"request","data":{}}');
// this.props.socket.addEventListener("message", this.handleMessage);
// }
openModal = (modal) => {
this.setState({ [modal]: true }, () => {
setTimeout(() => this.setState({ modalOpacity: 1 }), 10);
});
// handleMessage = (event) => {
// try {
// console.log("Message from server", event.data);
// const message = JSON.parse(event.data);
// } catch (error) {
// console.error("Error parsing message from server:", error);
// }
// };
if (modal === "modalOpen_show") {
this.props.socket.send(
`{"type": "cable_get","call": "request","data": {"position": ${this.state.cableDetails.position}}}`
);
}
};
// componentWillUnmount() {
// this.props.socket.removeEventListener("message", this.handleMessage);
// }
closeModal = (modal) => {
this.setState({ modalOpacity: 0 }, () => {
setTimeout(() => this.setState({ [modal]: false }), 300);
});
};
dispense() {
this.props.socket.send(
`{"type": "cable_get","call": "send","data": {"position": ${this.state.cableDetails.position}}}`
);
}
componentDidMount() {
const cablePos = window.location.href.split("/").pop();
this.props.socket.send(
`{"type":"cable_details","call":"request","data":{"position":["${cablePos}"]}}`
);
this.props.socket.addEventListener("message", this.handleMessage);
}
handleMessage = (event) => {
try {
const message = JSON.parse(event.data);
const cableDetails = new Cable(message.data.cables[0]);
this.setState({ cableDetails });
} catch (error) {}
};
componentWillUnmount() {
this.props.socket.removeEventListener("message", this.handleMessage);
}
renderHorizontalTable(title, object) {
let data;
try {
data = JSON.parse(object);
} catch (error) {
return <div>Error loading data...</div>;
}
const validKeys = Object.keys(data).filter((key) =>
Array.isArray(data[key])
);
const maxRows = Math.max(...validKeys.map((key) => data[key].length));
const rows = Array.from({ length: maxRows }).map((_, rowIndex) => {
return (
<tr className="row" key={rowIndex}>
{validKeys.map((key, index) => (
<td className="body" key={index}>
{data[key][rowIndex] || ""}
</td>
))}
</tr>
);
});
return (
<div className="cable-tables-div" style={{ width: "100%" }}>
<span className="cable-tables-div-title">{title}</span>
<table>
<thead className="thead">
<tr className="row">
{validKeys.map((key, index) => (
<th className="head" key={index}>
{key}
</th>
))}
</tr>
</thead>
<tbody className="tbody">{rows}</tbody>
</table>
</div>
);
}
renderVerticalTable(title, object) {
let data;
try {
data = JSON.parse(object);
} catch (error) {
console.error("Error parsing JSON data:", error);
return <div>Error loading data...</div>;
}
return (
<div className="cable-tables-div">
<span className="cable-tables-div-title">{title}</span>
<table>
{Object.entries(data).map(([key, value], index) => (
<tr className="row" key={index}>
<th className="head">{key}</th>
<td className="body">{value}</td>
</tr>
))}
</table>
</div>
);
}
render() {
const { modalOpen_show, modalOpen_datasheet, modalOpacity, cableDetails } =
this.state;
const modalStyle = {
content: {
opacity: modalOpacity,
transition: "opacity 300ms ease-in-out",
top: "50%",
left: "50%",
right: "auto",
bottom: "auto",
marginRight: "-50%",
width: "auto",
height: "auto",
transform: "translate(-50%, -50%)",
overflow: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
borderRadius: "20px",
background:
"linear-gradient(-30deg, rgb(187, 194, 236) 0%, rgba(255, 255, 255, 1) 100%)",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.5)",
minWidth: "30%",
minHeight: "30%",
},
overlay: {
opacity: modalOpacity,
transition: "opacity 300ms ease-in-out",
backgroundColor: "rgba(255, 255, 255, 0.15)",
backdropFilter: "blur(5px)",
},
};
return (
<div className="cable">
<div className="cable-image">
<img src={BeldenLogo} alt="Belden" />
</div>
<div className="cable-fieldContainer">
<div className="cable-actions">
{window.location.href.includes("browse") ? (
<NavLink to="/browse" className="cable-actions-back">
<span> Back</span>
</NavLink>
) : (
<NavLink to="/map" className="cable-actions-back">
<span> Back</span>
</NavLink>
)}
</div>
{cableDetails ? (
<div className="cable-main">
<img
className="cable-main-image"
src={cableDetails.image}
alt="Cable"
/>
<div className="cable-main-label">
<div className="cable-main-name">{cableDetails.partnum}</div>
<div className="cable-main-description">
{cableDetails.description}
</div>
{cableDetails.category ? (
<div className="cable-main-category">
<span
style={{ color: "black", backgroundColor: "transparent" }}
>
Category:{" "}
</span>
{cableDetails.category}
</div>
) : null}
<div className="cable-main-brand">
<span
style={{ color: "black", backgroundColor: "transparent" }}
>
Brand:{" "}
</span>
{cableDetails.brand}
</div>
<div className="cable-main-position">
<span
style={{ color: "black", backgroundColor: "transparent" }}
>
Position:{" "}
</span>
{parseInt(cableDetails.position) + 1}
</div>
</div>
{cableDetails.qrcode !== DefaultQRImg ? (
<div className="cable-main-imageqr">
<img src={cableDetails.qrcode} alt="" />
</div>
) : (
<div
className="cable-main-imageqr"
src={cableDetails.qrcode}
alt=""
style={{ visibility: "hidden" }}
/>
)}
</div>
) : (
<div className="cable-main"></div>
)}
<div className="cable-actions">
<div
className="cable-actions-button"
onClick={() => this.openModal("modalOpen_datasheet")}
>
<span> Datasheet</span>
<span></span>
</div>
<Modal
isOpen={modalOpen_datasheet}
onRequestClose={() => this.closeModal("modalOpen_datasheet")}
contentLabel="show"
style={modalStyle}
>
<div className="modal-container">
<div className="modal-title">
<span></span>
<span>Datasheet</span>
</div>
<div className="modal-datasheet">
{cableDetails ? (
<iframe
src={cableDetails.datasheet}
height="70%"
width="70%"
></iframe>
) : (
<div className="datasheet"></div>
)}
</div>
<div
className="modal-close"
onClick={() => this.closeModal("modalOpen_datasheet")}
>
<span>Close</span>
</div>
</div>
</Modal>
<div
className="cable-actions-button"
onClick={() => this.openModal("modalOpen_show")}
>
<span> Highlight</span>
<span>💡</span>
</div>
<Modal
isOpen={modalOpen_show}
onRequestClose={() => this.closeModal("modalOpen_show")}
contentLabel="show"
style={modalStyle}
>
<div className="modal-container">
<div className="modal-title">
<span>💡</span>
<span>Highlighting Item</span>
</div>
<div className="modal-body">
<span>The sample will now be illuminated.</span>
</div>
<div
className="modal-close"
onClick={() => this.closeModal("modalOpen_show")}
>
<span>Close</span>
</div>
</div>
</Modal>
<div
className="cable-actions-button"
onClick={() => this.dispense()}
>
<span> Dispense</span>
<span>🔽</span>
</div>
</div>
{cableDetails ? (
<div className="cable-tables">
{cableDetails.orderedKeys.map((key, index) => {
if (cableDetails.horizontal.includes(key)) {
return this.renderHorizontalTable(
key,
JSON.stringify(cableDetails.dynamicProps[key])
);
} else {
return this.renderVerticalTable(
key,
JSON.stringify(cableDetails.dynamicProps[key])
);
}
})}
</div>
) : (
<div className="cable-tables"></div>
)}
</div>
</div>
);

View File

@ -1,13 +1,277 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import cable from "../utils/Cable";
import "../assets/stylesheets/map.scss";
import { NavLink } from "react-router-dom";
import "animate.css";
export default class MapComponent extends Component {
constructor(props) {
super(props);
this.state = {
cableList: [],
selected: "0",
cable: new cable(
"...",
"0",
"...",
"...",
"...",
"...",
"...",
"...",
"..."
),
};
}
componentDidMount() {
this.props.socket.send('{"type":"cable_map","call":"request","data":{}}');
this.props.socket.addEventListener("message", this.handleMessage);
}
handleMessage = (event) => {
try {
const message = JSON.parse(event.data);
const list = this.browseParse(message);
this.setState({ cableList: list });
setTimeout(() => {
this.select("0");
this.updateSelection();
}, 50);
} catch (error) {}
};
updateSelection() {
const cableList = this.state.cableList;
for (let i = 0; i < 54; i++) {
let cable = cableList[i];
if (cable === undefined) {
try {
document.getElementById("inner-" + i).style.border =
"#bdbdbd 4px solid";
document.getElementById("text-" + i).style.color = "#bdbdbd";
} catch (error) {
console.error("Error updating selection:", 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 image = map[i].image;
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;
let category = map[i].category;
let application = map[i].application;
cableList.push(
new cable(
part_number,
position,
name,
brand,
description,
short_description,
image,
category,
application
)
);
}
return cableList;
}
componentWillUnmount() {
this.props.socket.removeEventListener("message", this.handleMessage);
}
renderCircle(id, color) {
return (
<div
className="map-box-circle"
id={"circle-" + id}
onClick={() => this.select(id)}
>
<div
className="map-box-circle-inner"
id={"inner-" + id}
style={{ border: `${color} 4px solid` }}
>
<span id={"text-" + id}>{parseInt(id) + 1}</span>
</div>
</div>
);
}
select = (id) => {
let cable = this.state.cableList[id];
if (cable === undefined) {
return;
}
let { selected } = this.state;
try {
document.getElementById("inner-" + selected).style.border =
"#004990 4px solid";
document.getElementById("text-" + selected).style.color = "#004990";
this.setState({ selected: id });
document.getElementById("inner-" + id).style.border = "#007cbe 4px solid";
document.getElementById("text-" + id).style.color = "#007cbe";
} catch (error) {
console.error("Error selecting cable:", error);
}
let cab = this.state.cableList[id];
this.setState({ cable: cab });
};
render() {
let { cable } = this.state;
return (
<div className="map">
<img className="map-image" src={BeldenLogo} alt="Belden" />
<div className="map-fieldContainer"></div>
<div className="map-image">
<img src={BeldenLogo} alt="Belden" />
</div>
<div className="map-fieldContainer">
<h1 className="map-title">🗺 Map</h1>
<div className="map-boxContainer">
<div className="map-box">
<div className="map-box-row" id="row-1">
{this.renderCircle("0", "#004990")}
{this.renderCircle("1", "#004990")}
{this.renderCircle("2", "#004990")}
{this.renderCircle("3", "#004990")}
{this.renderCircle("4", "#004990")}
</div>
<div className="map-box-row" id="row-2">
{this.renderCircle("5", "#004990")}
{this.renderCircle("6", "#004990")}
{this.renderCircle("7", "#004990")}
{this.renderCircle("8", "#004990")}
{this.renderCircle("9", "#004990")}
{this.renderCircle("10", "#004990")}
</div>
<div className="map-box-row" id="row-3">
{this.renderCircle("11", "#004990")}
{this.renderCircle("12", "#004990")}
{this.renderCircle("13", "#004990")}
{this.renderCircle("14", "#004990")}
{this.renderCircle("15", "#004990")}
{this.renderCircle("16", "#004990")}
{this.renderCircle("17", "#004990")}
</div>
<div className="map-box-row" id="row-4">
{this.renderCircle("18", "#004990")}
{this.renderCircle("19", "#004990")}
{this.renderCircle("20", "#004990")}
<div className="map-box-spacer"></div>
<div className="map-box-spacer"></div>
{this.renderCircle("21", "#004990")}
{this.renderCircle("22", "#004990")}
{this.renderCircle("23", "#004990")}
</div>
<div className="map-box-row" id="row-5">
{this.renderCircle("24", "#004990")}
{this.renderCircle("25", "#004990")}
{this.renderCircle("26", "#004990")}
<div className="map-box-spacer"></div>
<div className="map-box-spacer"></div>
<div className="map-box-spacer"></div>
{this.renderCircle("27", "#004990")}
{this.renderCircle("28", "#004990")}
{this.renderCircle("29", "#004990")}
</div>
<div className="map-box-row" id="row-6">
{this.renderCircle("30", "#004990")}
{this.renderCircle("31", "#004990")}
{this.renderCircle("32", "#004990")}
<div className="map-box-spacer"></div>
<div className="map-box-spacer"></div>
{this.renderCircle("33", "#004990")}
{this.renderCircle("34", "#004990")}
{this.renderCircle("35", "#004990")}
</div>
<div className="map-box-row" id="row-7">
{this.renderCircle("36", "#004990")}
{this.renderCircle("37", "#004990")}
{this.renderCircle("38", "#004990")}
{this.renderCircle("39", "#004990")}
{this.renderCircle("40", "#004990")}
{this.renderCircle("41", "#004990")}
{this.renderCircle("42", "#004990")}
</div>
<div className="map-box-row" id="row-8">
{this.renderCircle("43", "#004990")}
{this.renderCircle("44", "#004990")}
{this.renderCircle("45", "#004990")}
{this.renderCircle("46", "#004990")}
{this.renderCircle("47", "#004990")}
{this.renderCircle("48", "#004990")}
</div>
<div className="map-box-row" id="row-9">
{this.renderCircle("49", "#004990")}
{this.renderCircle("50", "#004990")}
{this.renderCircle("51", "#004990")}
{this.renderCircle("52", "#004990")}
{this.renderCircle("53", "#004990")}
</div>
</div>
<div className="map-details">
<div className="map-cable-label">
<img
className="map-cable-image"
src={cable.image}
alt="Cable"
/>
<div className="map-cable-name">{cable.name}</div>
<div className="map-cable-shortdescription">
{cable.short_description}
</div>
<div className="map-cable-description">{cable.description}</div>
{cable.category ? (
<div className="map-cable-category">
<span
style={{ color: "black", backgroundColor: "transparent" }}
>
Category:{" "}
</span>
{cable.category}
</div>
) : null}
<div className="map-cable-brand">
<span
style={{ color: "black", backgroundColor: "transparent" }}
>
Brand:{" "}
</span>
{cable.brand}
</div>
<div className="map-cable-position">
<span
style={{ color: "black", backgroundColor: "transparent" }}
>
Position:{" "}
</span>
{parseInt(cable.position) + 1}
</div>
</div>
<NavLink
to={"/map/cable/" + cable.position}
className="map-cable-moreinfo"
>
<span>More Info</span>
</NavLink>
</div>
</div>
</div>
</div>
);
}

View File

@ -1,60 +1,178 @@
import React, { Component } from "react";
import { NavLink } from "react-router-dom";
import Modal from "react-modal";
import "../assets/stylesheets/navbar.scss";
Modal.setAppElement("#root");
export default class NavBar extends Component {
constructor(props) {
super(props);
this.state = {
modalOpen_activeArm: false,
modalOpacity: 0,
mode: "idle",
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
}
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";
if (path.includes("statistics")) {
document.getElementById("statistics").style.backgroundColor = "#007CBE";
document.getElementById("statistics-s").style.color = "white";
} else if (path.includes("map")) {
document.getElementById("map").style.backgroundColor = "#007CBE";
document.getElementById("map-s").style.color = "white";
} else if (path.includes("cable")) {
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 {
document.getElementById("home").style.backgroundColor = "#007CBE";
document.getElementById("home-s").style.color = "white";
document.getElementById("browse").style.backgroundColor = "#007CBE";
document.getElementById("browse-s").style.color = "white";
}
this.props.socket.addEventListener("message", this.handleMessage);
}
componentWillUnmount() {
this.props.socket.removeEventListener("message", this.handleMessage);
}
handleMessage = (event) => {
try {
const message = JSON.parse(event.data);
if (message.type === "mode") {
let currentMode = JSON.parse(message.data).mode.toLowerCase();
this.setState({ mode: currentMode });
console.log("Current Mode: " + currentMode);
if (currentMode === "idle") {
setTimeout(() => {
console.log("State Mode: " + this.state.mode);
if (this.state.mode === "idle") {
this.closeModal("modalOpen_activeArm");
}
}, 1500);
} else {
this.openModal("modalOpen_activeArm");
}
}
} catch (error) {
console.error("");
}
};
openModal = (modal) => {
this.setState({ [modal]: true }, () => {
setTimeout(() => this.setState({ modalOpacity: 1 }), 10);
});
};
closeModal = (modal) => {
this.setState({ modalOpacity: 0 }, () => {
setTimeout(() => this.setState({ [modal]: false }), 300);
});
};
returnCable = () => {
this.props.socket.send(
`{"type": "cable_get","call": "send","data": {"tray": 0}}`
);
};
cancelAction = () => {
this.props.socket.send(
`{"type": "cancel_action","call": "request","data": {}}`
);
};
render() {
const { modalOpen_activeArm, modalOpacity } = this.state;
const modalStyle = {
content: {
opacity: modalOpacity,
transition: "opacity 300ms ease-in-out",
top: "50%",
left: "50%",
right: "auto",
bottom: "auto",
marginRight: "-50%",
width: "auto",
height: "auto",
transform: "translate(-50%, -50%)",
overflow: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
borderRadius: "20px",
background:
"linear-gradient(-30deg, rgb(187, 194, 236) 0%, rgba(255, 255, 255, 1) 100%)",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.5)",
minWidth: "30%",
minHeight: "30%",
},
overlay: {
opacity: modalOpacity,
transition: "opacity 300ms ease-in-out",
backgroundColor: "rgba(255, 255, 255, 0.15)",
backdropFilter: "blur(5px)",
},
};
return (
<div className="navbar">
<div className="navbar-top">
<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>
<div className="navbar-top-container">
<div className="navbar-top-hamburger"></div>
<NavLink className="navbar-settings" id="settings" to="/settings">
<span id="settings-s"></span>
</NavLink>
</div>
<h1>Jukebox</h1>
<ol className="navbar-list">
<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
className="navbar-list-item"
id="statistics"
to="/statistics"
>
<span id="statistics-s">📊 Statistics</span>
</NavLink>
</ol>
</div>
<div className="navbar-return" onClick={() => this.returnCable()}>
<span id="browse-s">Return Cable</span>
</div>
<Modal
isOpen={modalOpen_activeArm}
contentLabel="show"
style={modalStyle}
>
<div className="modal-container">
<div className="modal-title">
<span></span>
<span>Arm in Motion</span>
</div>
<div className="modal-body">
<span>Please stay clear of the arm.</span>
</div>
<div className="modal-closeX" onClick={() => this.cancelAction()}>
<span>Cancel Action</span>
</div>
</div>
</Modal>
</div>
);
}

View File

@ -1,13 +1,342 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import Modal from "react-modal";
import "../assets/stylesheets/settings.scss";
Modal.setAppElement("#root");
export default class SettingsComponent extends Component {
constructor(props) {
super(props);
this.state = {
modalOpen_quickAction: false,
modalOpacity: 0,
action: "",
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
}
quickAction = (action, requirePrompt) => {
if (requirePrompt) {
this.openModal("modalOpen_quickAction", action);
} else {
this.quickActionPerform(action);
}
};
quickActionPerform = (action) => {
switch (action) {
case "shutdown":
console.log("Shutting down...");
this.props.socket.send(
'{"type":"shutdown","call":"request","data":{}}'
);
break;
case "restart":
console.log("Restarting...");
this.props.socket.send('{"type":"restart","call":"request","data":{}}');
break;
case "home":
console.log("Homing...");
this.props.socket.send('{"type":"home","call":"request","data":{}}');
break;
default:
console.log("Invalid action");
break;
}
};
openModal = (modal, action) => {
this.setState({ [modal]: true }, () => {
setTimeout(() => this.setState({ modalOpacity: 1 }), 100);
});
this.setState({ action });
};
closeModal = (modal) => {
this.setState({ modalOpacity: 0 }, () => {
setTimeout(() => this.setState({ [modal]: false }), 300);
});
};
performActionCloseModal = () => {
console.log("Performing action: " + this.state.action);
this.quickActionPerform(this.state.action);
this.closeModal("modalOpen_quickAction");
};
sendObject = () => {
const object = document.getElementById("sendobject").value;
console.log("Sending object: " + object);
this.props.socket.send
? this.props.socket.send(object)
: console.log("No socket connection");
};
render() {
const { modalOpen_quickAction, modalOpacity } = this.state;
const modalStyle = {
content: {
opacity: modalOpacity,
transition: "opacity 300ms ease-in-out",
top: "50%",
left: "50%",
right: "auto",
bottom: "auto",
marginRight: "-50%",
width: "auto",
height: "auto",
transform: "translate(-50%, -50%)",
overflow: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
borderRadius: "20px",
background:
"linear-gradient(-30deg, rgb(187, 194, 236) 0%, rgba(255, 255, 255, 1) 100%)",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.5)",
minWidth: "30%",
minHeight: "30%",
},
overlay: {
opacity: modalOpacity,
transition: "opacity 300ms ease-in-out",
backgroundColor: "rgba(255, 255, 255, 0.15)",
backdropFilter: "blur(5px)",
},
};
return (
<div className="settings">
<img className="settings-image" src={BeldenLogo} alt="Belden" />
<div className="settings-fieldContainer"></div>
<div className="settings-image">
<img src={BeldenLogo} alt="Belden" />
</div>
<div className="settings-fieldContainer">
<h1 className="settings-title"> Settings</h1>
<div className="settings-grid">
<h2>Quick Actions:</h2>
<div className="settings-gridInner">
<div
className="settings-button"
onClick={() => this.quickAction("shutdown", true)}
>
<span>🔴 Power Off</span>
</div>
<div
className="settings-button"
onClick={() => this.quickAction("restart", false)}
>
<span>🟠 Restart</span>
</div>
<div
className="settings-button"
onClick={() => this.quickAction("home", false)}
>
<span>🏠 Home Arm</span>
</div>
</div>
</div>
<div className="settings-grid">
<h2>💻Send Object:</h2>
<div className="settings-gridInner">
<form className="settings-form">
<input
id="sendobject"
type="text"
name="sendobject"
placeholder={`{"type":"cable_map","call":"request","data":{}}`}
/>
<div
className="settings-button"
id="sendobjectButton"
onClick={() => this.sendObject()}
>
<span>Send</span>
</div>
</form>
</div>
</div>
<div className="settings-grid">
<h2>Credits:</h2>
<div id="creditsgrid" className="settings-gridInner">
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_cole.jpg")}
alt="Cole Deck"
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_cole.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Cole Deck</h2>
<h3>Project Lead</h3>
</div>
</div>
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_scarlett.jpg")}
alt="Scarlett Kadan"
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_scarlett.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Scarlett Kadan</h2>
<h3>Lead Front-End Dev, UI/UX Designer</h3>
</div>
</div>
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_natorion.jpg")}
alt="Natorion Johnson"
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_natorion.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Natorion Johnson</h2>
<h3>Lead PCB assembler</h3>
</div>
</div>
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_fannie.jpeg")}
alt="Fannie Yu"
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_fannie.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Fannie Yu</h2>
<h3>CAD Design, Fabrication Planner</h3>
</div>
</div>
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_elias.jpg")}
alt="Elias Reschly"
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_elias.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Elias Reschly</h2>
<h3>Mechanical Design, Fabrication</h3>
</div>
</div>
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_lucas.jpg")}
alt="Lucas Ferguson"
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_lucas.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Lucas Ferguson</h2>
<h3>Front-End Dev</h3>
</div>
</div>
<div className="entry">
<div className="entry-image">
<img
className="entry-img"
src={require("../assets/images/pic_dustin.jpg")}
alt=""
/>
<div className="entry-qr">
<img
src={require("../assets/images/qr_dustin.png")}
alt="QR"
/>
</div>
</div>
<div className="entry-title">
<h2>Dustin Thomas</h2>
<h3>Back-End Dev</h3>
</div>
</div>
</div>
</div>
</div>
<Modal
isOpen={modalOpen_quickAction}
contentLabel="show"
onRequestClose={() => this.closeModal("modalOpen_quickAction")}
style={modalStyle}
>
<div className="modal-container">
<div className="modal-title">
<span></span>
<span>Warning</span>
</div>
<div className="modal-body">
<span>Are you sure you want to perform this quick action?</span>
</div>
<div className="modal-tray">
<div
className="modal-return"
onClick={() =>
this.performActionCloseModal("modalOpen_quickAction")
}
>
<span>Continue</span>
</div>
<div
className="modal-return"
onClick={() => this.closeModal("modalOpen_quickAction")}
>
<span>Cancel</span>
</div>
</div>
</div>
</Modal>
</div>
);
}

View File

@ -0,0 +1,62 @@
import React, { Component } from "react";
import BeldenLogo from "../assets/images/belden-white.png";
import "../assets/stylesheets/statistics.scss";
export default class StatisticsComponent extends Component {
render() {
return (
<div className="statistics">
<div className="statistics-image">
<img src={BeldenLogo} alt="Belden" />
</div>
<div className="statistics-fieldContainer">
<h1 className="statistics-title">📊 Statistics</h1>
<div className="statistics-grid">
<div className="statistics-grid-container">
<iframe
src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=1s&theme=light&panelId=8"
title="Belden"
className="statistics-iframe"
/>
</div>
<div className="statistics-grid-container">
<iframe
src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=1s&theme=light&panelId=3"
title="Belden"
className="statistics-iframe"
/>
</div>
<div className="statistics-grid-container">
<iframe
src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=1s&theme=light&panelId=7"
title="Belden"
className="statistics-iframe"
/>
</div>
<div className="statistics-grid-container">
<iframe
src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=1s&theme=light&panelId=6"
title="Belden"
className="statistics-iframe"
/>
</div>
<div className="statistics-grid-container">
<iframe
src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=1s&theme=light&panelId=4"
title="Belden"
className="statistics-iframe"
/>
</div>
<div className="statistics-grid-container">
<iframe
src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=1s&theme=light&panelId=2"
title="Belden"
className="statistics-iframe"
/>
</div>
</div>
</div>
</div>
);
}
}

View File

@ -1,14 +0,0 @@
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,10 +1,10 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import SummaryRoute from "./routes/SummaryRoute";
import BrowseRoute from "./routes/BrowseRoute";
import SettingsRoute from "./routes/SettingsRoute";
import MapRoute from "./routes/MapRoute";
import StatisticsRoute from "./routes/StatisticsRoute";
import CableDetailRoute from "./routes/CableDetailRoute";
// Root
@ -12,7 +12,9 @@ const root = ReactDOM.createRoot(document.getElementById("root"));
// Socket handler
console.log("Connecting to WebSocket server.");
const socket = new WebSocket("ws://localhost:9000");
const hostname = window.location.hostname; // Get the hostname from the URL bar
const wsPort = "9000";
const socket = new WebSocket(`ws://${hostname}:${wsPort}`);
socket.addEventListener("open", function (event) {
console.log("Websocket connected.");
console.log("Welcome to Belden Jukebox!");
@ -24,7 +26,7 @@ const init = () => {
const router = createBrowserRouter([
{
path: "/",
element: <SummaryRoute socket={socket}></SummaryRoute>,
element: <BrowseRoute socket={socket}></BrowseRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
@ -43,7 +45,17 @@ const init = () => {
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/cable/:cableId",
path: "/statistics",
element: <StatisticsRoute socket={socket}></StatisticsRoute>,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/browse/cable/:cablePos",
element: <CableDetailRoute socket={socket} />,
// errorElement: <ErrorRoute></ErrorRoute>,
},
{
path: "/map/cable/:cablePos",
element: <CableDetailRoute socket={socket} />,
// errorElement: <ErrorRoute></ErrorRoute>,
},

View File

@ -12,7 +12,7 @@ export default class BrowseRoute extends Component {
render() {
return (
<div className="container">
<NavBar />
<NavBar socket={this.props.socket} />
<BrowseComponent socket={this.props.socket} />
</div>
);

View File

@ -12,8 +12,8 @@ export default class CableDetailRoute extends Component {
render() {
return (
<div className="container">
<NavBar />
<CableDetailComponent />
<NavBar socket={this.props.socket} />
<CableDetailComponent socket={this.props.socket} />
</div>
);
}

View File

@ -12,8 +12,8 @@ export default class MapRoute extends Component {
render() {
return (
<div className="container">
<NavBar />
<MapComponent socketHandler={this.props.socket} />
<NavBar socket={this.props.socket} />
<MapComponent socket={this.props.socket} />
</div>
);
}

View File

@ -12,8 +12,8 @@ export default class SettingsRoute extends Component {
render() {
return (
<div className="container">
<NavBar />
<SettingsComponent socketHandler={this.props.socket} />
<NavBar socket={this.props.socket} />
<SettingsComponent socket={this.props.socket} />
</div>
);
}

View File

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

View File

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

99
src/utils/Cable.js Normal file
View File

@ -0,0 +1,99 @@
import React from "react";
import DefaultPartImg from "../assets/images/part.png";
import DefaultQRImg from "../assets/images/default_qr.png";
import { NavLink } from "react-router-dom";
import "../assets/stylesheets/browse.scss";
const hostname = window.location.hostname; // Get the hostname from the URL bar
export default class cable {
constructor(
part_number,
position,
name,
brand,
description,
short_description,
image,
category,
application,
qrcode
) {
this.part_number = part_number;
this.position = position;
this.name = name;
this.brand = brand;
this.image = image ? `http://${hostname}${image}` : DefaultPartImg;
this.category = category;
this.application = application;
this.short_description = short_description;
this.description = description;
this.qrcode = qrcode ? `http://${hostname}${qrcode}` : DefaultQRImg;
if (short_description === undefined) {
if (this.description !== undefined) {
this.short_description = this.description;
} else if (this.application !== undefined) {
this.short_description = this.application;
} else if (this.category !== undefined) {
this.short_description = this.category;
} else {
this.short_description = "";
}
}
if (this.short_description !== undefined) {
this.short_description =
this.short_description.charAt(0).toUpperCase() +
this.short_description.slice(1);
if (this.short_description.length > 80) {
this.short_description =
this.short_description.substring(0, 80) + "...";
}
}
if (this.description !== undefined) {
if (this.description.length > 200) {
this.description = this.description.substring(0, 200) + "...";
}
}
}
returnDiv() {
return (
<NavLink className="browse-cable" to={"/browse/cable/" + this.position}>
<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-description">
<span style={{ color: "#007cbe" }}></span>
{this.short_description}
</div>
{this.category ? (
<div className="browse-cable-category">
<span style={{ color: "black", backgroundColor: "transparent" }}>
Category:{" "}
</span>
{this.category}
</div>
) : null}
<div className="browse-cable-brand">
<span style={{ color: "black", backgroundColor: "transparent" }}>
Brand:{" "}
</span>
{this.brand}
</div>
<div className="browse-cable-position">
<span style={{ color: "black", backgroundColor: "transparent" }}>
Position:{" "}
</span>
{parseInt(this.position) + 1}
</div>
</div>
<span className="browse-cable-arrow">{">"}</span>
</NavLink>
);
}
}