From 5ce3502c71c8d5469386b7422bee7675f1cc49b9 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 01:57:50 -0700 Subject: [PATCH 01/41] Progress on dark mode --- site/package-lock.json | 197 ++++++++++++++++++ site/package.json | 2 + site/src/App.tsx | 64 +++--- site/src/component/AppHeader/AppHeader.scss | 5 - site/src/component/PrereqTree/PrereqTree.tsx | 3 +- site/src/component/SideBar/SideBar.tsx | 36 +++- site/src/component/SideInfo/SideInfo.scss | 4 - site/src/pages/RoadmapPage/Quarter.scss | 2 - site/src/pages/RoadmapPage/Year.scss | 3 - site/src/pages/RoadmapPage/index.scss | 2 - .../src/pages/SearchPage/ProfessorHitItem.tsx | 2 +- site/src/style/globalStyle.ts | 78 +++++++ site/src/style/theme.ts | 43 ++++ 13 files changed, 388 insertions(+), 53 deletions(-) create mode 100644 site/src/style/globalStyle.ts create mode 100644 site/src/style/theme.ts diff --git a/site/package-lock.json b/site/package-lock.json index 5dfeb90e..7f544877 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -12,6 +12,7 @@ "@nivo/bar": "^0.69.1", "@nivo/pie": "^0.69.0", "@reduxjs/toolkit": "^1.6.1", + "@types/styled-components": "^5.1.26", "axios": "^0.21.1", "bootstrap": "^4.6.0", "html2canvas": "^1.0.0-rc.7", @@ -32,6 +33,7 @@ "react-transition-group": "^4.4.1", "react-twemoji": "^0.5.0", "semantic-ui-react": "^2.1.4", + "styled-components": "^5.3.11", "typescript": "^4.3.5", "websoc-fuzzy-search": "^0.8.0-rc.1" }, @@ -2248,6 +2250,29 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "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", @@ -6513,6 +6538,16 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "node_modules/@types/styled-components": { + "version": "5.1.26", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", + "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", + "dependencies": { + "@types/hoist-non-react-statics": "*", + "@types/react": "*", + "csstype": "^3.0.2" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", @@ -7805,6 +7840,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/babel-plugin-styled-components": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", + "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.21.4", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.21", + "picomatch": "^2.3.1" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, "node_modules/babel-plugin-syntax-trailing-function-commas": { "version": "7.0.0-beta.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", @@ -8356,6 +8411,14 @@ "node": ">= 6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -9082,6 +9145,14 @@ "tiny-invariant": "^1.0.6" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, "node_modules/css-declaration-sorter": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", @@ -9277,6 +9348,16 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -26121,6 +26202,35 @@ "webpack": "^5.0.0" } }, + "node_modules/styled-components": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", @@ -29872,6 +29982,29 @@ "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", "requires": {} }, + "@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "requires": { + "@emotion/memoize": "^0.8.1" + } + }, + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -33174,6 +33307,16 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "@types/styled-components": { + "version": "5.1.26", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", + "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", + "requires": { + "@types/hoist-non-react-statics": "*", + "@types/react": "*", + "csstype": "^3.0.2" + } + }, "@types/trusted-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", @@ -34112,6 +34255,23 @@ "@babel/helper-define-polyfill-provider": "^0.3.3" } }, + "babel-plugin-styled-components": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", + "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.21.4", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.21", + "picomatch": "^2.3.1" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, "babel-plugin-syntax-trailing-function-commas": { "version": "7.0.0-beta.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", @@ -34526,6 +34686,11 @@ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -35072,6 +35237,11 @@ "tiny-invariant": "^1.0.6" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, "css-declaration-sorter": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", @@ -35192,6 +35362,16 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -47662,6 +47842,23 @@ "integrity": "sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==", "requires": {} }, + "styled-components": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + } + }, "stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", diff --git a/site/package.json b/site/package.json index f6d86737..300cb66b 100644 --- a/site/package.json +++ b/site/package.json @@ -7,6 +7,7 @@ "@nivo/bar": "^0.69.1", "@nivo/pie": "^0.69.0", "@reduxjs/toolkit": "^1.6.1", + "@types/styled-components": "^5.1.26", "axios": "^0.21.1", "bootstrap": "^4.6.0", "html2canvas": "^1.0.0-rc.7", @@ -27,6 +28,7 @@ "react-transition-group": "^4.4.1", "react-twemoji": "^0.5.0", "semantic-ui-react": "^2.1.4", + "styled-components": "^5.3.11", "typescript": "^4.3.5", "websoc-fuzzy-search": "^0.8.0-rc.1" }, diff --git a/site/src/App.tsx b/site/src/App.tsx index 779ba6a0..5b05de40 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -22,40 +22,52 @@ import AdminPage from './pages/AdminPage'; import SideBar from './component/SideBar/SideBar'; import { useAppSelector } from './store/hooks'; +import { darkTheme, lightTheme } from './style/theme'; +import { ThemeProvider } from 'styled-components'; +import GlobalStyle from './style/globalStyle'; export default function App() { + const [darkMode, setDarkMode] = useState(localStorage.getItem('darkMode') === 'true' ? true : (localStorage.getItem('darkMode') === 'false' ? false : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches))); const sidebarOpen = useAppSelector(state => state.ui.sidebarOpen); const [isShown, setIsShown] = useState(false); + const toggleTheme = () => { + localStorage.setItem('darkMode', darkMode ? 'false' : 'true'); + setDarkMode(!darkMode); + } + return ( - -
-
- -
-
- - - - - - - - - - - - - - - - - - -
+ + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
+
-
+ ) } \ No newline at end of file diff --git a/site/src/component/AppHeader/AppHeader.scss b/site/src/component/AppHeader/AppHeader.scss index f8f96c7a..b8c645d3 100644 --- a/site/src/component/AppHeader/AppHeader.scss +++ b/site/src/component/AppHeader/AppHeader.scss @@ -79,7 +79,6 @@ ul { display: flex; flex-direction: row; align-items: center; - background-color: #f5f6fc; height: 60%; border-radius: 1rem; width: 12vw; @@ -92,10 +91,6 @@ ul { justify-content: center; align-items: center; border-radius: 1rem; - - a { - color: black; - } } .active { diff --git a/site/src/component/PrereqTree/PrereqTree.tsx b/site/src/component/PrereqTree/PrereqTree.tsx index 63c09dd7..ae957cda 100644 --- a/site/src/component/PrereqTree/PrereqTree.tsx +++ b/site/src/component/PrereqTree/PrereqTree.tsx @@ -154,10 +154,9 @@ const PrereqTree: FC = (props) => {
} */} -
diff --git a/site/src/component/SideBar/SideBar.tsx b/site/src/component/SideBar/SideBar.tsx index e8bf2569..2f20d2c3 100644 --- a/site/src/component/SideBar/SideBar.tsx +++ b/site/src/component/SideBar/SideBar.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { NavLink } from 'react-router-dom'; import { Icon } from 'semantic-ui-react'; import { XCircle } from 'react-bootstrap-icons'; @@ -10,8 +10,14 @@ import { Button } from 'react-bootstrap'; import { useAppSelector, useAppDispatch } from '../..//store/hooks'; import { setSidebarStatus } from '../../store/slices/uiSlice'; import axios, { AxiosResponse } from 'axios'; +import { ThemeConsumer } from 'styled-components'; -const SideBar: FC = ({ children }) => { +interface SideBarProps { + darkMode: boolean, + toggleTheme: () => void; +} + +const SideBar = ({ darkMode, toggleTheme }: SideBarProps) => { const dispatch = useAppDispatch(); const showSidebar = useAppSelector(state => state.ui.sidebarOpen); const [cookies, setCookie] = useCookies(['user']); @@ -67,6 +73,16 @@ const SideBar: FC = ({ children }) => { + {showSidebar &&
  • + +
    + +
    + + {darkMode ? 'Toggle Light Theme' : 'Toggle Dark Theme'} + +
    +
  • } {isAdmin && <>
  • @@ -127,12 +143,16 @@ const SideBar: FC = ({ children }) => { } {!isLoggedIn && - + + {theme => ( + + )} + }
  • diff --git a/site/src/component/SideInfo/SideInfo.scss b/site/src/component/SideInfo/SideInfo.scss index 9f9f7986..6467852f 100644 --- a/site/src/component/SideInfo/SideInfo.scss +++ b/site/src/component/SideInfo/SideInfo.scss @@ -79,9 +79,6 @@ .side-info-feature-name { font-weight: bold; font-size: 2em; - a { - color: black; - } } .side-info-feature-stats { @@ -90,7 +87,6 @@ } .side-info-feature-stat { - background-color: #ffffff; border-radius: var(--border-radius); padding: 0.5rem; width: 45%; diff --git a/site/src/pages/RoadmapPage/Quarter.scss b/site/src/pages/RoadmapPage/Quarter.scss index 2094feeb..d768027d 100644 --- a/site/src/pages/RoadmapPage/Quarter.scss +++ b/site/src/pages/RoadmapPage/Quarter.scss @@ -12,14 +12,12 @@ align-items: center; .quarter-title { - color: #202e47; font-weight: bold; font-size: 20px; padding: 1rem 0rem 0rem 2rem; } .edit-btn { - background-color: var(--ring-road-white); width: 5%; margin-top: 10px; margin-right: 1.5rem; diff --git a/site/src/pages/RoadmapPage/Year.scss b/site/src/pages/RoadmapPage/Year.scss index 36c28522..9487a8dc 100644 --- a/site/src/pages/RoadmapPage/Year.scss +++ b/site/src/pages/RoadmapPage/Year.scss @@ -29,7 +29,6 @@ .year-accordion, .year-accordion-content { border-radius: var(--border-radius); - background-color: var(--ring-road-white); display: flex; flex-wrap: wrap; } @@ -60,7 +59,6 @@ #year-title { font-size: 1.2rem; - color: black; } #year-accordion-icon { @@ -85,7 +83,6 @@ } .edit-btn { - background-color: var(--ring-road-white); width: 5%; margin-top: 10px; } diff --git a/site/src/pages/RoadmapPage/index.scss b/site/src/pages/RoadmapPage/index.scss index 0fa6bbc6..e1be90d3 100644 --- a/site/src/pages/RoadmapPage/index.scss +++ b/site/src/pages/RoadmapPage/index.scss @@ -20,12 +20,10 @@ } .sidebar-wrapper { - background: white; border-radius: var(--border-radius); margin-left: 1vw; width: 25%; height: 100%; - background-color: white; overflow-y: auto; } diff --git a/site/src/pages/SearchPage/ProfessorHitItem.tsx b/site/src/pages/SearchPage/ProfessorHitItem.tsx index 02834de6..98b7d5e1 100644 --- a/site/src/pages/SearchPage/ProfessorHitItem.tsx +++ b/site/src/pages/SearchPage/ProfessorHitItem.tsx @@ -47,7 +47,7 @@ const ProfessorHitItem: FC = (props: ProfessorHitItemProp {Object.keys(props.course_history).map((item: string, index: number) => { return {(index ? ', ' : '')} - + {item} diff --git a/site/src/style/globalStyle.ts b/site/src/style/globalStyle.ts new file mode 100644 index 00000000..40bfca7e --- /dev/null +++ b/site/src/style/globalStyle.ts @@ -0,0 +1,78 @@ +import { createGlobalStyle } from 'styled-components'; +import Theme from './theme'; + +const GlobalStyle = createGlobalStyle<{ theme: Theme }>` + body, + .search-bar, + .search-bar:focus, + .search-bar::selection, + .sidebar .sidebar-links ul li a, + .side-info-feature-name a, + .subreview-identifier a, + .table { + color: ${({ theme }) => theme.textColor}; + } + + + .navbar-toggle-item a, + .quarter-title, + #year-title { + color: ${({ theme }) => theme.quarterTitleColor} + } + + body, + .app-content { + background-color: ${({ theme }) => theme.backgroundColor}; + } + + .course, + .course-page-section, + .hit-item, + .modal-content, + .navbar, + .professor-page-section, + .search-bar, + .search-bar:focus, + .search-popup, + .search-popup-more, + .sidebar, + .sidebar-wrapper, + .side-info, + .side-info-feature-stat, + .subreview-detail, + .quarter, + .year { + background-color: ${({ theme }) => theme.overlay1Color}; + } + + .navbar { + box-shadow: ${({ theme }) => theme.navbarBoxShadow} + } + + .input-group-text { + color: ${({ theme }) => theme.inputGroupText}; + background-color: ${({ theme }) => theme.overlay2Color}; + } + + .navbar-toggle, + .prereq-text-box, + .search-popup-info, + .search-popup-block, + .side-info-feature, + .subreview { + background-color: ${({ theme }) => theme.overlay2Color}; + } + + .hit-item a, + .modal-content .close { + color: ${({ theme }) => theme.textColorDark}; + } + + .prereq .ui.button { + color: ${({ theme }) => theme.prereqNodeTextColor}; + background-color: ${({ theme }) => theme.prereqNodeBackgroundColor}; + } + + `; + + export default GlobalStyle; \ No newline at end of file diff --git a/site/src/style/theme.ts b/site/src/style/theme.ts new file mode 100644 index 00000000..90667f7e --- /dev/null +++ b/site/src/style/theme.ts @@ -0,0 +1,43 @@ +export const lightTheme: Theme = { + name: 'light', + textColor: '#212529', + textColorDark: '#000', + inputGroupText: '#495057', + backgroundColor: 'var(--peterportal-gray-blue)', + overlay1Color: 'var(--ring-road-white)', + overlay2Color: 'var(--peterportal-gray-blue)', + quarterTitleColor: '#202e47', + navbarBoxShadow: '0px 4px 24px rgba(196, 198, 209, 0.24)', + prereqNodeTextColor: 'rgba(0,0,0,.6)', + prereqNodeBackgroundColor: '#e0e1e2' +} + +export const darkTheme: Theme = { + name: 'dark', + textColor: '#fff', + textColorDark: '#fff', + inputGroupText: '#fff', + backgroundColor: '#121212', + overlay1Color: '#1E1E1E', + overlay2Color: '#292929', + quarterTitleColor: '#eee', + navbarBoxShadow: '0px 4px 24px rgba(0, 0, 0, 0.24)', + prereqNodeTextColor: '#fff', + prereqNodeBackgroundColor: '#292929' +} + +interface Theme { + name: string, + textColor: string, + textColorDark: string, + inputGroupText: string, + backgroundColor: string, + overlay1Color: string, + overlay2Color: string, + quarterTitleColor: string, + navbarBoxShadow: string, + prereqNodeTextColor: string, + prereqNodeBackgroundColor: string +} + +export default Theme; \ No newline at end of file From d304d39a17b1c41bbd75a1049e7c8a8fde3a8710 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:02:04 -0700 Subject: [PATCH 02/41] Dark mode seems to be working --- site/package-lock.json | 176 ------------------ site/package.json | 1 - site/public/searching.png | Bin 58212 -> 0 bytes site/src/App.scss | 7 +- site/src/App.tsx | 20 +- site/src/asset/searching.png | Bin 0 -> 79038 bytes site/src/component/AppHeader/AppHeader.scss | 162 ++-------------- site/src/component/AppHeader/AppHeader.tsx | 2 +- site/src/component/GradeDist/Chart.tsx | 84 +++++---- site/src/component/PrereqTree/PrereqTree.scss | 9 + site/src/component/ReportForm/ReportForm.scss | 58 +++--- site/src/component/Review/Review.scss | 6 +- site/src/component/ReviewForm/ReviewForm.scss | 5 +- site/src/component/ReviewForm/ReviewForm.tsx | 4 +- .../component/SearchModule/SearchModule.scss | 12 ++ .../component/SearchPopup/SearchPopup.scss | 8 +- .../src/component/SearchPopup/SearchPopup.tsx | 3 +- site/src/component/SideBar/SideBar.tsx | 55 +++--- site/src/component/SideBar/Sidebar.scss | 17 +- site/src/component/SideInfo/SideInfo.scss | 8 +- site/src/component/Verify/Verify.scss | 3 +- site/src/pages/CoursePage/CoursePage.scss | 2 +- .../pages/ProfessorPage/ProfessorPage.scss | 2 +- site/src/pages/RoadmapPage/Course.scss | 5 +- site/src/pages/RoadmapPage/Course.tsx | 11 +- site/src/pages/RoadmapPage/Quarter.scss | 7 +- site/src/pages/RoadmapPage/SearchSidebar.scss | 1 + site/src/pages/RoadmapPage/Year.scss | 4 +- site/src/pages/SearchPage/HitItem.scss | 6 +- site/src/style/globalStyle.ts | 78 -------- site/src/style/theme-context.ts | 8 + site/src/style/theme.scss | 68 +++++++ site/src/style/theme.ts | 43 ----- 33 files changed, 306 insertions(+), 569 deletions(-) delete mode 100644 site/public/searching.png create mode 100644 site/src/asset/searching.png delete mode 100644 site/src/style/globalStyle.ts create mode 100644 site/src/style/theme-context.ts create mode 100644 site/src/style/theme.scss delete mode 100644 site/src/style/theme.ts diff --git a/site/package-lock.json b/site/package-lock.json index 7f544877..9187cf27 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -33,7 +33,6 @@ "react-transition-group": "^4.4.1", "react-twemoji": "^0.5.0", "semantic-ui-react": "^2.1.4", - "styled-components": "^5.3.11", "typescript": "^4.3.5", "websoc-fuzzy-search": "^0.8.0-rc.1" }, @@ -2250,29 +2249,6 @@ "postcss-selector-parser": "^6.0.10" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", - "dependencies": { - "@emotion/memoize": "^0.8.1" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "node_modules/@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" - }, - "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, "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", @@ -7840,26 +7816,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-styled-components": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", - "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.21.4", - "babel-plugin-syntax-jsx": "^6.18.0", - "lodash": "^4.17.21", - "picomatch": "^2.3.1" - }, - "peerDependencies": { - "styled-components": ">= 2" - } - }, - "node_modules/babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" - }, "node_modules/babel-plugin-syntax-trailing-function-commas": { "version": "7.0.0-beta.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", @@ -8411,14 +8367,6 @@ "node": ">= 6" } }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -9145,14 +9093,6 @@ "tiny-invariant": "^1.0.6" } }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "engines": { - "node": ">=4" - } - }, "node_modules/css-declaration-sorter": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", @@ -9348,16 +9288,6 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -26202,35 +26132,6 @@ "webpack": "^5.0.0" } }, - "node_modules/styled-components": { - "version": "5.3.11", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", - "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", - "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^1.1.0", - "@emotion/stylis": "^0.8.4", - "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1.12.0", - "css-to-react-native": "^3.0.0", - "hoist-non-react-statics": "^3.0.0", - "shallowequal": "^1.1.0", - "supports-color": "^5.5.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" - }, - "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0", - "react-is": ">= 16.8.0" - } - }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", @@ -29982,29 +29883,6 @@ "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", "requires": {} }, - "@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", - "requires": { - "@emotion/memoize": "^0.8.1" - } - }, - "@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" - }, - "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -34255,23 +34133,6 @@ "@babel/helper-define-polyfill-provider": "^0.3.3" } }, - "babel-plugin-styled-components": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", - "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.21.4", - "babel-plugin-syntax-jsx": "^6.18.0", - "lodash": "^4.17.21", - "picomatch": "^2.3.1" - } - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" - }, "babel-plugin-syntax-trailing-function-commas": { "version": "7.0.0-beta.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", @@ -34686,11 +34547,6 @@ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" }, - "camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" - }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -35237,11 +35093,6 @@ "tiny-invariant": "^1.0.6" } }, - "css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" - }, "css-declaration-sorter": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz", @@ -35362,16 +35213,6 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, - "css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "requires": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, "css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -47842,23 +47683,6 @@ "integrity": "sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==", "requires": {} }, - "styled-components": { - "version": "5.3.11", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", - "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^1.1.0", - "@emotion/stylis": "^0.8.4", - "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1.12.0", - "css-to-react-native": "^3.0.0", - "hoist-non-react-statics": "^3.0.0", - "shallowequal": "^1.1.0", - "supports-color": "^5.5.0" - } - }, "stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", diff --git a/site/package.json b/site/package.json index 300cb66b..a6bb876a 100644 --- a/site/package.json +++ b/site/package.json @@ -28,7 +28,6 @@ "react-transition-group": "^4.4.1", "react-twemoji": "^0.5.0", "semantic-ui-react": "^2.1.4", - "styled-components": "^5.3.11", "typescript": "^4.3.5", "websoc-fuzzy-search": "^0.8.0-rc.1" }, diff --git a/site/public/searching.png b/site/public/searching.png deleted file mode 100644 index 9ab5b9727b2a65068add39557e32946f42f36029..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58212 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 state.ui.sidebarOpen); const [isShown, setIsShown] = useState(false); + useEffect(() => { + localStorage.setItem('darkMode', darkMode ? 'true' : 'false'); + document.querySelector('body')!.setAttribute('data-theme', darkMode ? 'dark' : 'light'); + }, [darkMode]) + const toggleTheme = () => { - localStorage.setItem('darkMode', darkMode ? 'false' : 'true'); setDarkMode(!darkMode); } return ( - - - + +
    - +
    @@ -67,7 +71,7 @@ export default function App() {
    -
    +
    ) } \ No newline at end of file diff --git a/site/src/asset/searching.png b/site/src/asset/searching.png new file mode 100644 index 0000000000000000000000000000000000000000..72a16dd85201e4506123806bab908036887587a2 GIT binary patch literal 79038 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

    J+)rfl;?Hj8J;)x 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 NG0-#Ct<`pn`9EQ#cme .icon-button { - background-color: #de5246; - i.icon { - color: #fff !important; - } -} - -.facebook-login:hover > .icon-button { - background-color: #3b5998; - i.icon { - color: #fff !important; - } -} - -.dark-mode:hover > .icon-button { - background-color: #9146ff; - i.icon { - color: #fff !important; - } -} - -.icon-button svg { - fill: var(--text-color); - width: 15px; - height: 15px; -} - -.settings-menu { - position: absolute; - top: 58px; - width: 300px; - transform: translateX(-45%); - background-color: var(--bg); - border: var(--border); - border-radius: var(--border-radius); - padding: 1rem; - overflow: hidden; -} - -.menu-item { - height: 50px; - display: flex; - align-items: center; - border-radius: var(--border-radius); - transition: background var(--speed); - padding: 0.5rem; - color: var(--text-color); - text-decoration: none; - transition: background-color 300ms; - .button-text { - padding-left: 12px; - } -} - -.menu-item:hover { - background-color: #f7f7f7; - cursor: pointer; - .icon-button { - filter: brightness(0.9); - } -} - -.icon-right { - margin-left: auto; -} - -.menu { - width: 100%; -} - -.menu-primary-enter { - position: absolute; - transform: translateX(-110%); -} - -.menu-primary-enter-active { - transform: translateX(0%); - transition: all var(--speed) ease; -} - -.menu-primary-exit { - position: absolute; -} - -.menu-primary-exit-active { - transform: translateX(-110%); - transition: all var(--speed) ease; -} - -.menu-secondary-enter { - transform: translateX(110%); -} - -.menu-secondary-enter-active { - transform: translateX(0%); - transition: all var(--speed) ease; -} - -.menu-secondary-exit { -} - -.menu-secondary-exit-active { - transform: translateX(110%); - transition: all var(--speed) ease; -} - -i.icon { - margin: -2px 0 0 0 !important; -} - .feedback { display: flex; flex-direction: row; @@ -325,3 +187,11 @@ i.icon { } } } + +[data-theme='dark'] .beta-popup .button { + background-color: var(--overlay3); +} + +[data-theme='dark'] .beta-popup .button:hover, [data-theme='dark'] .beta-popup .button:focus { + background-color: #CACBCD; +} \ No newline at end of file diff --git a/site/src/component/AppHeader/AppHeader.tsx b/site/src/component/AppHeader/AppHeader.tsx index bd44cfc4..4711c489 100644 --- a/site/src/component/AppHeader/AppHeader.tsx +++ b/site/src/component/AppHeader/AppHeader.tsx @@ -97,7 +97,7 @@ const AppHeader: FC<{}> = props => { {/* Week */}

    - betav1.1} flowing hoverable > + betav1.1} flowing hoverable >

    Beta Disclaimer

    diff --git a/site/src/component/GradeDist/Chart.tsx b/site/src/component/GradeDist/Chart.tsx index 2bbe6f87..66252203 100644 --- a/site/src/component/GradeDist/Chart.tsx +++ b/site/src/component/GradeDist/Chart.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { ResponsiveBar, BarTooltipDatum } from '@nivo/bar' import { GradeDistData } from '../../types/types'; +import ThemeContext from 'src/style/theme-context'; const colors = { 'A': '#60A3D1', 'B': '#81C284', 'C': '#F5D77F', 'D': '#ECAD6D', 'F': '#E8966D', 'P': '#EBEBEB', 'NP': '#EBEBEB' } const getColor = (bar: Bar) => colors[bar.id] @@ -30,14 +31,29 @@ export default class Chart extends React.Component { /* * Initialize the grade distribution chart on the webpage. */ - theme = { - tooltip: { - container: { - background: 'rgba(0,0,0,.87)', - color: '#ffffff', - fontSize: '1.2rem', - outline: 'none', - margin: 0, + + getTheme = (darkMode: boolean) => { + return { + tooltip: { + container: { + background: 'rgba(0,0,0,.87)', + color: '#ffffff', + fontSize: '1.2rem', + outline: 'none', + margin: 0, + } + }, + axis: { + ticks: { + text: { + fill: darkMode ? '#eee' : '#333' + } + }, + legend: { + text: { + fill: darkMode ? '#eee' : '#333' + } + } } } } @@ -132,30 +148,34 @@ export default class Chart extends React.Component { */ render() { return <> - + + {({ darkMode }) => + + } + } } diff --git a/site/src/component/PrereqTree/PrereqTree.scss b/site/src/component/PrereqTree/PrereqTree.scss index d7e2c3bc..76a54799 100644 --- a/site/src/component/PrereqTree/PrereqTree.scss +++ b/site/src/component/PrereqTree/PrereqTree.scss @@ -187,3 +187,12 @@ background-color: #f5f5f5; margin-top: 2em; } + +.prereq-text-box { + background-color: var(--overlay2); +} + +.prereq ul { + margin: 0; + padding: 0; +} \ No newline at end of file diff --git a/site/src/component/ReportForm/ReportForm.scss b/site/src/component/ReportForm/ReportForm.scss index 9427b4c2..b6a263a4 100644 --- a/site/src/component/ReportForm/ReportForm.scss +++ b/site/src/component/ReportForm/ReportForm.scss @@ -1,34 +1,41 @@ .report-form { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); + border-radius: var(--border-radius); + padding: 2rem; + display: flex; + grid-gap: 35px; + width: fit-content; + width: 40vw; + height: fit-content; + position: fixed; + top: 0; + right: 0; + left: 0; + bottom: 0; + margin: auto auto; + padding: 50px; + overflow-y: auto; + overflow-x: hidden; + + textarea { + color: var(--text); + background-color: var(--overlay3); border-radius: var(--border-radius); - padding: 2rem; - display: flex; - grid-gap: 35px; - width: fit-content; - width: 40vw; - height: fit-content; - position: fixed; - top: 0; - right: 0; - left: 0; - bottom: 0; - margin: auto auto; - padding: 50px; - overflow-y: auto; - overflow-x: hidden; + border: 2px solid #EAEBF2; + padding: 1rem; + resize: none; + width: 100%; + display: block; + } - textarea { - border-radius: var(--border-radius); - border: 2px solid #EAEBF2; - padding: 1rem; - resize: none; - width: 100%; - display: block; - } + textarea:focus { + color: var(--text); + background-color: var(--overlay3); + } } .report-form-review-content { - background-color: white; + background-color: var(--overlay3); border-radius: var(--border-radius); padding: 1rem; margin-bottom: 20px; @@ -50,7 +57,6 @@ .submitted-report-form { text-align: center; width: 100%; - margin-top: 15%; i { color: var(--peterportal-secondary-green); } diff --git a/site/src/component/Review/Review.scss b/site/src/component/Review/Review.scss index 2d15b3f2..919ac463 100644 --- a/site/src/component/Review/Review.scss +++ b/site/src/component/Review/Review.scss @@ -1,6 +1,6 @@ $avatarWidth: 65px; .subreview { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); border-radius: var(--border-radius); padding: 2rem; margin-bottom: 3vh; @@ -11,7 +11,7 @@ $avatarWidth: 65px; font-weight: bold; font-size: xx-large; a { - color: black; + color: var(--text); } } // content of review @@ -68,7 +68,7 @@ $avatarWidth: 65px; } .subreview-detail { border-radius: var(--border-radius); - background-color: #ffffff; + background-color: var(--overlay3); width: 45%; padding: 1rem; display: flex; diff --git a/site/src/component/ReviewForm/ReviewForm.scss b/site/src/component/ReviewForm/ReviewForm.scss index 0e344bee..26e7c29a 100644 --- a/site/src/component/ReviewForm/ReviewForm.scss +++ b/site/src/component/ReviewForm/ReviewForm.scss @@ -1,5 +1,5 @@ .review-form { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); border-radius: var(--border-radius); padding: 2rem; display: flex; @@ -48,7 +48,7 @@ margin-left: 1vw; } .review-form-section { - background-color: #ffffff; + background-color: var(--overlay3); border-radius: var(--border-radius); padding: 1rem; } @@ -88,7 +88,6 @@ .submitted-form { text-align: center; width: 100%; - margin-top: 15%; i { color: var(--peterportal-secondary-green); } diff --git a/site/src/component/ReviewForm/ReviewForm.tsx b/site/src/component/ReviewForm/ReviewForm.tsx index 8427d899..5d14efbe 100644 --- a/site/src/component/ReviewForm/ReviewForm.tsx +++ b/site/src/component/ReviewForm/ReviewForm.tsx @@ -359,7 +359,7 @@ const ReviewForm: FC = (props) => {
    - Refrain from using profanity, name-calling, or derogatory terms. Thank you for your contribution! + Refrain from using profanity, name-calling, or derogatory terms. Thank you for your contribution! @@ -392,7 +392,7 @@ const ReviewForm: FC = (props) => { - { diff --git a/site/src/component/SearchModule/SearchModule.scss b/site/src/component/SearchModule/SearchModule.scss index ae26fcce..bf831b22 100644 --- a/site/src/component/SearchModule/SearchModule.scss +++ b/site/src/component/SearchModule/SearchModule.scss @@ -1,4 +1,16 @@ .search-bar { border-color: #80bdff; padding: 2vh 2vh; +} + +[data-theme='dark'] { + .search-bar, + .search-module .input-group-text { + color: white; + background-color: var(--overlay1); + border-color: var(--overlay3); + } + .search-bar:focus { + border-color: #80bdff; + } } \ No newline at end of file diff --git a/site/src/component/SearchPopup/SearchPopup.scss b/site/src/component/SearchPopup/SearchPopup.scss index 96e201b0..3d39f864 100644 --- a/site/src/component/SearchPopup/SearchPopup.scss +++ b/site/src/component/SearchPopup/SearchPopup.scss @@ -11,7 +11,7 @@ } .search-popup { - background-color: #ffffff; + background-color: var(--overlay1); padding: 3rem; margin-left: 3vw; height: 85vh; @@ -36,11 +36,11 @@ } .search-popup-more { - background-color: #ffffff; + background-color: transparent; } .search-popup-block { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); border-radius: var(--border-radius); } @@ -62,7 +62,7 @@ } .search-popup-carousel { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); height: 100%; margin: 0 1vw; padding: 2vh 1vw; diff --git a/site/src/component/SearchPopup/SearchPopup.tsx b/site/src/component/SearchPopup/SearchPopup.tsx index a0a0d412..dc609b9c 100644 --- a/site/src/component/SearchPopup/SearchPopup.tsx +++ b/site/src/component/SearchPopup/SearchPopup.tsx @@ -3,6 +3,7 @@ import './SearchPopup.scss' import GradeDist from '../GradeDist/GradeDist'; import Button from 'react-bootstrap/Button'; import Carousel from "react-multi-carousel"; +import searching from '../../asset/searching.png'; import { useAppSelector } from '../../store/hooks'; import { selectCourse, selectProfessor } from '../../store/slices/popupSlice'; @@ -39,7 +40,7 @@ const SearchPopup: FC = (props) => { if (!selected) { return
    - searching + searching

    Click on a {props.searchType} card to view more information!

    diff --git a/site/src/component/SideBar/SideBar.tsx b/site/src/component/SideBar/SideBar.tsx index 2f20d2c3..b81ec864 100644 --- a/site/src/component/SideBar/SideBar.tsx +++ b/site/src/component/SideBar/SideBar.tsx @@ -11,13 +11,9 @@ import { useAppSelector, useAppDispatch } from '../..//store/hooks'; import { setSidebarStatus } from '../../store/slices/uiSlice'; import axios, { AxiosResponse } from 'axios'; import { ThemeConsumer } from 'styled-components'; +import ThemeContext from 'src/style/theme-context'; -interface SideBarProps { - darkMode: boolean, - toggleTheme: () => void; -} - -const SideBar = ({ darkMode, toggleTheme }: SideBarProps) => { +const SideBar = () => { const dispatch = useAppDispatch(); const showSidebar = useAppSelector(state => state.ui.sidebarOpen); const [cookies, setCookie] = useCookies(['user']); @@ -74,14 +70,19 @@ const SideBar = ({ darkMode, toggleTheme }: SideBarProps) => { {showSidebar &&
  • - -
    - -
    - - {darkMode ? 'Toggle Light Theme' : 'Toggle Dark Theme'} - -
    + + {({ darkMode, toggleTheme }) => + // eslint-disable-next-line jsx-a11y/anchor-is-valid + +
    + +
    + + Toggle Dark Mode + +
    + } +
  • } {isAdmin && <>
  • @@ -135,24 +136,28 @@ const SideBar = ({ darkMode, toggleTheme }: SideBarProps) => { {/* Login/Logout */}
  • diff --git a/site/src/component/SideBar/Sidebar.scss b/site/src/component/SideBar/Sidebar.scss index 890ef790..be6851d8 100644 --- a/site/src/component/SideBar/Sidebar.scss +++ b/site/src/component/SideBar/Sidebar.scss @@ -4,12 +4,18 @@ height: 100vh; top: 0; z-index: 400; - background-color: white; + background-color: var(--overlay1); display: flex; flex-direction: column; justify-content: space-between; align-items: center; + ul { + list-style: none; + margin: 0; + padding: 0; + } + .sidebar-close { padding: 2vw; width: 100%; @@ -48,7 +54,7 @@ ul li { a { - color: black; + color: var(--text); display: flex; grid-gap: 10px; padding: 10px; @@ -64,7 +70,7 @@ margin-bottom: 5vh; .sidebar-login-icon { - margin-right: 1vw; + margin-right: 0.4vw; } } } @@ -142,3 +148,8 @@ } } } + +.theme-toggle:hover { + cursor: pointer; + text-decoration: underline; +} \ No newline at end of file diff --git a/site/src/component/SideInfo/SideInfo.scss b/site/src/component/SideInfo/SideInfo.scss index 6467852f..b0b7adf0 100644 --- a/site/src/component/SideInfo/SideInfo.scss +++ b/site/src/component/SideInfo/SideInfo.scss @@ -2,7 +2,7 @@ width: 40vw; height: fit-content; max-height: 85vh; - background-color: #ffffff; + background-color: var(--overlay1); border-radius: var(--border-radius); padding: 3rem; position: sticky; @@ -62,7 +62,7 @@ } .side-info-feature { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); border-radius: var(--border-radius); padding: 2rem; width: 45%; @@ -79,6 +79,9 @@ .side-info-feature-name { font-weight: bold; font-size: 2em; + a { + color: var(--text); + } } .side-info-feature-stats { @@ -87,6 +90,7 @@ } .side-info-feature-stat { + background-color: var(--overlay3); border-radius: var(--border-radius); padding: 0.5rem; width: 45%; diff --git a/site/src/component/Verify/Verify.scss b/site/src/component/Verify/Verify.scss index 0d0b199a..cde2b20e 100644 --- a/site/src/component/Verify/Verify.scss +++ b/site/src/component/Verify/Verify.scss @@ -1,11 +1,10 @@ .verify-container { padding: 2rem; - background-color: white; + background-color: var(--overlay1); border-radius: var(--border-radius); } .verify { - background-color: white; border-radius: var(--border-radius); margin-bottom: 3vh; diff --git a/site/src/pages/CoursePage/CoursePage.scss b/site/src/pages/CoursePage/CoursePage.scss index 3ec650f9..d677a93b 100644 --- a/site/src/pages/CoursePage/CoursePage.scss +++ b/site/src/pages/CoursePage/CoursePage.scss @@ -8,7 +8,7 @@ .course-page-section { max-width: 42vw; - background-color: #ffffff; + background-color: var(--overlay1); border-radius: var(--border-radius); padding: 3rem; margin-bottom: 3vh; diff --git a/site/src/pages/ProfessorPage/ProfessorPage.scss b/site/src/pages/ProfessorPage/ProfessorPage.scss index 64683eba..786f1c90 100644 --- a/site/src/pages/ProfessorPage/ProfessorPage.scss +++ b/site/src/pages/ProfessorPage/ProfessorPage.scss @@ -8,7 +8,7 @@ .professor-page-section { max-width: 45vw; - background-color: #ffffff; + background-color: var(--overlay1); border-radius: var(--border-radius); padding: 3rem; margin-bottom: 3vh; diff --git a/site/src/pages/RoadmapPage/Course.scss b/site/src/pages/RoadmapPage/Course.scss index 9a20c955..7edb9b7f 100644 --- a/site/src/pages/RoadmapPage/Course.scss +++ b/site/src/pages/RoadmapPage/Course.scss @@ -1,6 +1,6 @@ .course { box-shadow: 0px 0px 4px #2484C6; - background: #FFFFFF; + background: var(--overlay1); border-radius: 15px; height: auto; font-size: 16px; @@ -58,12 +58,11 @@ } .course-popover { - background: #FFFFFF; padding: 5%; .popover-name { font-weight: bold; - color: black; + color: var(--text-dark); font-size: 16px; } diff --git a/site/src/pages/RoadmapPage/Course.tsx b/site/src/pages/RoadmapPage/Course.tsx index 5ed73a7d..b71f232d 100644 --- a/site/src/pages/RoadmapPage/Course.tsx +++ b/site/src/pages/RoadmapPage/Course.tsx @@ -6,6 +6,7 @@ import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; import Popover from 'react-bootstrap/Popover'; import { CourseGQLData } from '../../types/types'; +import ThemeContext from "src/style/theme-context"; interface CourseProps extends CourseGQLData { requiredCourses?: string[]; @@ -57,9 +58,13 @@ const Course: FC = (props) => {
    {onDelete && ( - + + {({ darkMode }) => + + } + )}
    {title}
    diff --git a/site/src/pages/RoadmapPage/Quarter.scss b/site/src/pages/RoadmapPage/Quarter.scss index d768027d..0e2433de 100644 --- a/site/src/pages/RoadmapPage/Quarter.scss +++ b/site/src/pages/RoadmapPage/Quarter.scss @@ -1,5 +1,9 @@ +[data-theme='dark'] .quarter .quarter-header .quarter-title { + color: #eee; +} + .quarter { - background-color: white; + background-color: var(--overlay1); border-radius: 10px; box-shadow: 0px 0px 4px #2484c6; flex: 1 1 30%; @@ -12,6 +16,7 @@ align-items: center; .quarter-title { + color: #202e47; font-weight: bold; font-size: 20px; padding: 1rem 0rem 0rem 2rem; diff --git a/site/src/pages/RoadmapPage/SearchSidebar.scss b/site/src/pages/RoadmapPage/SearchSidebar.scss index ffb37f42..f7ee8130 100644 --- a/site/src/pages/RoadmapPage/SearchSidebar.scss +++ b/site/src/pages/RoadmapPage/SearchSidebar.scss @@ -6,6 +6,7 @@ height: 100%; display: flex; flex-direction: column; + background-color: var(--overlay1); .close-icon { width: 5vh; diff --git a/site/src/pages/RoadmapPage/Year.scss b/site/src/pages/RoadmapPage/Year.scss index 9487a8dc..9cb3b5a1 100644 --- a/site/src/pages/RoadmapPage/Year.scss +++ b/site/src/pages/RoadmapPage/Year.scss @@ -9,7 +9,7 @@ margin: 1rem 0; padding: 1rem; align-items: center; - background-color: var(--ring-road-white); + background-color: var(--overlay1); border-radius: var(--border-radius); border-collapse: separate; display: inline-block; @@ -34,7 +34,6 @@ } .empty-quarter { - background-color: white; border-radius: 10px; box-shadow: 0px 0px 4px #2484c6; flex: 1 1 30%; @@ -58,6 +57,7 @@ } #year-title { + color: var(--text); font-size: 1.2rem; } diff --git a/site/src/pages/SearchPage/HitItem.scss b/site/src/pages/SearchPage/HitItem.scss index 6028f611..af0c766b 100644 --- a/site/src/pages/SearchPage/HitItem.scss +++ b/site/src/pages/SearchPage/HitItem.scss @@ -1,9 +1,13 @@ .hit-item { border-radius: var(--border-radius); - background-color: #ffffff; + background-color: var(--overlay1); padding: 2vh; margin-bottom: 2vh; cursor: pointer; + + a { + color: var(--text); + } } .course-hit-id { diff --git a/site/src/style/globalStyle.ts b/site/src/style/globalStyle.ts deleted file mode 100644 index 40bfca7e..00000000 --- a/site/src/style/globalStyle.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { createGlobalStyle } from 'styled-components'; -import Theme from './theme'; - -const GlobalStyle = createGlobalStyle<{ theme: Theme }>` - body, - .search-bar, - .search-bar:focus, - .search-bar::selection, - .sidebar .sidebar-links ul li a, - .side-info-feature-name a, - .subreview-identifier a, - .table { - color: ${({ theme }) => theme.textColor}; - } - - - .navbar-toggle-item a, - .quarter-title, - #year-title { - color: ${({ theme }) => theme.quarterTitleColor} - } - - body, - .app-content { - background-color: ${({ theme }) => theme.backgroundColor}; - } - - .course, - .course-page-section, - .hit-item, - .modal-content, - .navbar, - .professor-page-section, - .search-bar, - .search-bar:focus, - .search-popup, - .search-popup-more, - .sidebar, - .sidebar-wrapper, - .side-info, - .side-info-feature-stat, - .subreview-detail, - .quarter, - .year { - background-color: ${({ theme }) => theme.overlay1Color}; - } - - .navbar { - box-shadow: ${({ theme }) => theme.navbarBoxShadow} - } - - .input-group-text { - color: ${({ theme }) => theme.inputGroupText}; - background-color: ${({ theme }) => theme.overlay2Color}; - } - - .navbar-toggle, - .prereq-text-box, - .search-popup-info, - .search-popup-block, - .side-info-feature, - .subreview { - background-color: ${({ theme }) => theme.overlay2Color}; - } - - .hit-item a, - .modal-content .close { - color: ${({ theme }) => theme.textColorDark}; - } - - .prereq .ui.button { - color: ${({ theme }) => theme.prereqNodeTextColor}; - background-color: ${({ theme }) => theme.prereqNodeBackgroundColor}; - } - - `; - - export default GlobalStyle; \ No newline at end of file diff --git a/site/src/style/theme-context.ts b/site/src/style/theme-context.ts new file mode 100644 index 00000000..ea6e236d --- /dev/null +++ b/site/src/style/theme-context.ts @@ -0,0 +1,8 @@ +import React from "react"; + +const ThemeContext = React.createContext<{ darkMode: boolean, toggleTheme: () => void }>({ + darkMode: false, + toggleTheme: () => {} +}); + +export default ThemeContext; \ No newline at end of file diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss new file mode 100644 index 00000000..55c36378 --- /dev/null +++ b/site/src/style/theme.scss @@ -0,0 +1,68 @@ +// light theme vars +:root { + --background: var(--peterportal-gray-blue); // defined in index.css + --overlay1: #fff; + --overlay2: var(--peterportal-gray-blue); + --overlay3: #fff; + --text: #212529; // default bootstrap color + --text-dark: #000; + --text-light: #495057; +} + +// dark theme vars +// each overlay is about 5% brighter than the previous +// roughly following: https://m2.material.io/design/color/dark-theme.html +[data-theme='dark'] { + --background: #121212; + --overlay1: #1E1E1E; + --overlay2: #292929; + --overlay3: #363636; + --text: #fff; + --text-dark: #fff; + --text-light: #fff; +} + +// general bootstrap overwrites. bg color may need further customization per component +.table { + color: var(--text); +} + +.dropdown-menu, .dropdown-item, .form-control, .form-control:focus { + color: var(--text-light); + background-color: var(--overlay3); +} + +.popover-body { + background-color: var(--overlay1); + color: var(--text); +} + +.bs-popover-left>.arrow::after { + border-left-color: var(--overlay1); +} + +// general semantic-ui overwrites. bg color may need to be customized per component +[data-theme='dark'] .ui, [data-theme='dark'] .ui.popup:before { + color: var(--text); + background-color: var(--overlay2); + border-color: var(--overlay1); +} + +[data-theme='dark'] .ui.bottom.popup:before { + box-shadow: -1px -1px 0 0 var(--overlay1); +} + +[data-theme='dark'] .ui.dropdown, [data-theme='dark'] .ui.dropdown .menu { + color: white; + background-color: var(--overlay3); + border-color: var(--overlay2); +} + +[data-theme='dark'] .ui.selection.visible.dropdown>.text:not(.default), +[data-theme='dark'] .ui.dropdown .menu>.item { + color: white; +} + +[data-theme='dark'] .ui.dropdown:hover { + border-color: var(--overlay1); +} \ No newline at end of file diff --git a/site/src/style/theme.ts b/site/src/style/theme.ts deleted file mode 100644 index 90667f7e..00000000 --- a/site/src/style/theme.ts +++ /dev/null @@ -1,43 +0,0 @@ -export const lightTheme: Theme = { - name: 'light', - textColor: '#212529', - textColorDark: '#000', - inputGroupText: '#495057', - backgroundColor: 'var(--peterportal-gray-blue)', - overlay1Color: 'var(--ring-road-white)', - overlay2Color: 'var(--peterportal-gray-blue)', - quarterTitleColor: '#202e47', - navbarBoxShadow: '0px 4px 24px rgba(196, 198, 209, 0.24)', - prereqNodeTextColor: 'rgba(0,0,0,.6)', - prereqNodeBackgroundColor: '#e0e1e2' -} - -export const darkTheme: Theme = { - name: 'dark', - textColor: '#fff', - textColorDark: '#fff', - inputGroupText: '#fff', - backgroundColor: '#121212', - overlay1Color: '#1E1E1E', - overlay2Color: '#292929', - quarterTitleColor: '#eee', - navbarBoxShadow: '0px 4px 24px rgba(0, 0, 0, 0.24)', - prereqNodeTextColor: '#fff', - prereqNodeBackgroundColor: '#292929' -} - -interface Theme { - name: string, - textColor: string, - textColorDark: string, - inputGroupText: string, - backgroundColor: string, - overlay1Color: string, - overlay2Color: string, - quarterTitleColor: string, - navbarBoxShadow: string, - prereqNodeTextColor: string, - prereqNodeBackgroundColor: string -} - -export default Theme; \ No newline at end of file From dea82ddef99c45feb77430a384885ec24bdb0a50 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:04:29 -0700 Subject: [PATCH 03/41] Move body theme css to index.css --- site/src/App.scss | 5 ----- site/src/index.css | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/site/src/App.scss b/site/src/App.scss index 63302c21..3cfb29a3 100644 --- a/site/src/App.scss +++ b/site/src/App.scss @@ -1,8 +1,3 @@ -body { - color: var(--text); - background: var(--background); -} - .app-body { display: flex; height: 92vh; diff --git a/site/src/index.css b/site/src/index.css index 4fce0204..a0c12a81 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -6,6 +6,8 @@ body { font-family: "Open Sans", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + color: var(--text); + background: var(--background); } code { From b63419e84dbca51acecf28524efe55eac0f4f37f Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:06:39 -0700 Subject: [PATCH 04/41] Restore package lock back to before --- site/package-lock.json | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 9187cf27..5dfeb90e 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -12,7 +12,6 @@ "@nivo/bar": "^0.69.1", "@nivo/pie": "^0.69.0", "@reduxjs/toolkit": "^1.6.1", - "@types/styled-components": "^5.1.26", "axios": "^0.21.1", "bootstrap": "^4.6.0", "html2canvas": "^1.0.0-rc.7", @@ -6514,16 +6513,6 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, - "node_modules/@types/styled-components": { - "version": "5.1.26", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", - "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", - "dependencies": { - "@types/hoist-non-react-statics": "*", - "@types/react": "*", - "csstype": "^3.0.2" - } - }, "node_modules/@types/trusted-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", @@ -33185,16 +33174,6 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, - "@types/styled-components": { - "version": "5.1.26", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz", - "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==", - "requires": { - "@types/hoist-non-react-statics": "*", - "@types/react": "*", - "csstype": "^3.0.2" - } - }, "@types/trusted-types": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", From fb46dec9f2548df5b15a8c9920d7d0df06dbfd6c Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:07:43 -0700 Subject: [PATCH 05/41] Remove old/broken imports --- site/src/App.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/site/src/App.tsx b/site/src/App.tsx index a26b5cc9..12565806 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -9,7 +9,6 @@ import 'bootstrap/dist/css/bootstrap.min.css'; import 'react-bootstrap-range-slider/dist/react-bootstrap-range-slider.css'; import './style/theme.scss'; import './App.scss'; -import { Fade } from 'react-bootstrap'; import AppHeader from './component/AppHeader/AppHeader'; import Footer from './component/Footer/Footer'; @@ -23,8 +22,6 @@ import AdminPage from './pages/AdminPage'; import SideBar from './component/SideBar/SideBar'; import { useAppSelector } from './store/hooks'; -import { darkTheme, lightTheme } from './style/theme'; -import { ThemeProvider } from 'styled-components'; import ThemeContext from './style/theme-context'; export default function App() { From aa0c26921dd1762886a203495d053fc06c8cb419 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:09:04 -0700 Subject: [PATCH 06/41] Space for consistency --- site/src/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/App.tsx b/site/src/App.tsx index 12565806..d30ab688 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -41,10 +41,10 @@ export default function App() { return ( - +
    - +
    From 2c07f5c035716e8a9b50ca3b1464bfa71fca1070 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:11:14 -0700 Subject: [PATCH 07/41] Remove styled-components remnants --- site/package.json | 1 - site/src/component/SideBar/SideBar.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/site/package.json b/site/package.json index a6bb876a..f6d86737 100644 --- a/site/package.json +++ b/site/package.json @@ -7,7 +7,6 @@ "@nivo/bar": "^0.69.1", "@nivo/pie": "^0.69.0", "@reduxjs/toolkit": "^1.6.1", - "@types/styled-components": "^5.1.26", "axios": "^0.21.1", "bootstrap": "^4.6.0", "html2canvas": "^1.0.0-rc.7", diff --git a/site/src/component/SideBar/SideBar.tsx b/site/src/component/SideBar/SideBar.tsx index b81ec864..db93f9b8 100644 --- a/site/src/component/SideBar/SideBar.tsx +++ b/site/src/component/SideBar/SideBar.tsx @@ -10,7 +10,6 @@ import { Button } from 'react-bootstrap'; import { useAppSelector, useAppDispatch } from '../..//store/hooks'; import { setSidebarStatus } from '../../store/slices/uiSlice'; import axios, { AxiosResponse } from 'axios'; -import { ThemeConsumer } from 'styled-components'; import ThemeContext from 'src/style/theme-context'; const SideBar = () => { From 76d49c71a63a35fa0f072b97e1a0249d2e378ff0 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 17:14:13 -0700 Subject: [PATCH 08/41] Add theming to reports page --- site/src/component/Report/ReportGroup.scss | 4 ++-- site/src/component/Report/Reports.scss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site/src/component/Report/ReportGroup.scss b/site/src/component/Report/ReportGroup.scss index 070b75c2..cb3199be 100644 --- a/site/src/component/Report/ReportGroup.scss +++ b/site/src/component/Report/ReportGroup.scss @@ -1,5 +1,5 @@ .report-group { - background-color: var(--peterportal-gray-blue); + background-color: var(--overlay2); border-radius: var(--border-radius); padding: 2rem; margin-bottom: 3vh; @@ -34,7 +34,7 @@ } .report-group-subreports-container { - background-color: white; + background-color: var(--overlay3); border-radius: var(--border-radius); padding: 1rem; } diff --git a/site/src/component/Report/Reports.scss b/site/src/component/Report/Reports.scss index d0d132fd..adf1babe 100644 --- a/site/src/component/Report/Reports.scss +++ b/site/src/component/Report/Reports.scss @@ -1,5 +1,5 @@ .reports-container { padding: 2rem; - background-color: white; + background-color: var(--overlay1); border-radius: var(--border-radius); } \ No newline at end of file From d48e50ddeadd3269dbc7e180788ff7830d6bd225 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 23:07:03 -0700 Subject: [PATCH 09/41] Fix popover on theming --- site/src/style/theme.scss | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 55c36378..8e39609a 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -36,10 +36,18 @@ background-color: var(--overlay1); color: var(--text); } - +.bs-popover-top>.arrow::after { + border-top-color: var(--overlay1); +} +.bs-popover-bottom>.arrow::after { + border-bottom-color: var(--overlay1); +} .bs-popover-left>.arrow::after { border-left-color: var(--overlay1); } +.bs-popover-right>.arrow::after { + border-right-color: var(--overlay1); +} // general semantic-ui overwrites. bg color may need to be customized per component [data-theme='dark'] .ui, [data-theme='dark'] .ui.popup:before { From 7ec3b5df8a765854374bdbf55e9f80210f775b51 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sat, 27 May 2023 23:53:51 -0700 Subject: [PATCH 10/41] Dark mode looks done --- site/src/component/AppHeader/AppHeader.scss | 35 ++---- site/src/component/PrereqTree/PrereqTree.scss | 6 +- site/src/component/PrereqTree/PrereqTree.tsx | 2 +- .../component/SearchModule/SearchModule.scss | 2 +- site/src/component/SideBar/Sidebar.scss | 1 - site/src/index.css | 1 + .../src/pages/RoadmapPage/AddCoursePopup.scss | 1 - site/src/pages/RoadmapPage/Quarter.tsx | 42 ++++--- site/src/pages/RoadmapPage/Year.tsx | 112 ++++++++++-------- site/src/style/theme.scss | 61 ++++++---- 10 files changed, 142 insertions(+), 121 deletions(-) diff --git a/site/src/component/AppHeader/AppHeader.scss b/site/src/component/AppHeader/AppHeader.scss index 2502ce8a..e5988af0 100644 --- a/site/src/component/AppHeader/AppHeader.scss +++ b/site/src/component/AppHeader/AppHeader.scss @@ -3,21 +3,19 @@ height: 100%; } -.ui.segment { - // background: linear-gradient(90deg, $primary-color-1 0%, $primary-color-2 100%); - padding: 0 !important; - border: 0 !important; - box-shadow: none !important; -} -:root { - --border: 1px solid #eee; - --border-radius: 8px; - --speed: 500ms; -} +[data-theme='dark'] { + .beta-popup .button { + background-color: var(--overlay3); + } + + .beta-popup .button:hover, .beta-popup .button:focus { + background-color: #CACBCD; + } -[data-theme='dark'] .navbar { - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.24); + .navbar { + box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.24); + } } .navbar { @@ -70,7 +68,7 @@ } .navbar-toggle { - background-color: var(--background); + background-color: var(--overlay2); margin-left: 5vw; display: flex; flex-direction: row; @@ -132,7 +130,6 @@ display: flex; flex-direction: row; align-items: center; - background-color: #f5f6fc; height: 60%; border-radius: 1rem; width: 17vw; @@ -187,11 +184,3 @@ } } } - -[data-theme='dark'] .beta-popup .button { - background-color: var(--overlay3); -} - -[data-theme='dark'] .beta-popup .button:hover, [data-theme='dark'] .beta-popup .button:focus { - background-color: #CACBCD; -} \ No newline at end of file diff --git a/site/src/component/PrereqTree/PrereqTree.scss b/site/src/component/PrereqTree/PrereqTree.scss index 76a54799..1ba21ed0 100644 --- a/site/src/component/PrereqTree/PrereqTree.scss +++ b/site/src/component/PrereqTree/PrereqTree.scss @@ -182,13 +182,9 @@ } } -.missing-tree { +.missing-tree, .prereq-text-box { padding: 1em; - background-color: #f5f5f5; margin-top: 2em; -} - -.prereq-text-box { background-color: var(--overlay2); } diff --git a/site/src/component/PrereqTree/PrereqTree.tsx b/site/src/component/PrereqTree/PrereqTree.tsx index ae957cda..423873cb 100644 --- a/site/src/component/PrereqTree/PrereqTree.tsx +++ b/site/src/component/PrereqTree/PrereqTree.tsx @@ -84,7 +84,7 @@ const PrereqTree: FC = (props) => { if (props.id === undefined) return <>; else if (!hasPrereqs && !hasDependencies) return ( -
    +

    No Dependencies or Prerequisites!

    diff --git a/site/src/component/SearchModule/SearchModule.scss b/site/src/component/SearchModule/SearchModule.scss index bf831b22..41f62f3f 100644 --- a/site/src/component/SearchModule/SearchModule.scss +++ b/site/src/component/SearchModule/SearchModule.scss @@ -6,7 +6,7 @@ [data-theme='dark'] { .search-bar, .search-module .input-group-text { - color: white; + color: var(--text); background-color: var(--overlay1); border-color: var(--overlay3); } diff --git a/site/src/component/SideBar/Sidebar.scss b/site/src/component/SideBar/Sidebar.scss index be6851d8..a3e7bc1c 100644 --- a/site/src/component/SideBar/Sidebar.scss +++ b/site/src/component/SideBar/Sidebar.scss @@ -116,7 +116,6 @@ .sidebar { width: 100vw; z-index: 400; - background-color: white; display: flex; flex-direction: column; justify-content: space-between; diff --git a/site/src/index.css b/site/src/index.css index a0c12a81..906dad2c 100644 --- a/site/src/index.css +++ b/site/src/index.css @@ -31,6 +31,7 @@ code { --peterportal-mid-gray: #8d8d8d; --peterportal-uci-gold: #ffd200; --peterportal-gray-blue: #f5f6fc; + --border-radius: 8px; } ::-moz-selection { diff --git a/site/src/pages/RoadmapPage/AddCoursePopup.scss b/site/src/pages/RoadmapPage/AddCoursePopup.scss index 31dfb33b..84e4540f 100644 --- a/site/src/pages/RoadmapPage/AddCoursePopup.scss +++ b/site/src/pages/RoadmapPage/AddCoursePopup.scss @@ -1,5 +1,4 @@ .add-course-form { - background-color: var(--peterportal-gray-blue); border-radius: var(--border-radius); padding: 2rem; } \ No newline at end of file diff --git a/site/src/pages/RoadmapPage/Quarter.tsx b/site/src/pages/RoadmapPage/Quarter.tsx index db91a668..c498e4f6 100644 --- a/site/src/pages/RoadmapPage/Quarter.tsx +++ b/site/src/pages/RoadmapPage/Quarter.tsx @@ -10,6 +10,7 @@ import { Button, Overlay, Popover } from "react-bootstrap"; import { ThreeDots } from "react-bootstrap-icons"; +import ThemeContext from "src/style/theme-context"; interface QuarterProps { year: number; @@ -90,23 +91,30 @@ const Quarter: FC = ({ year, yearIndex, quarterIndex, data }) => { {quarterTitle} {year} - - - -
    - - -
    -
    -
    -
    + + {({ darkMode }) => { + let variant = darkMode ? 'dark' : 'light'; + return <> + + + +
    + + +
    +
    +
    +
    + ; + }} +
    {unitCount} {unitCount === 1 ? "unit" : "units"} diff --git a/site/src/pages/RoadmapPage/Year.tsx b/site/src/pages/RoadmapPage/Year.tsx index 3aafe29f..09c0c92b 100644 --- a/site/src/pages/RoadmapPage/Year.tsx +++ b/site/src/pages/RoadmapPage/Year.tsx @@ -11,6 +11,7 @@ import { useAppDispatch } from '../../store/hooks'; import { addQuarter, editYear, deleteYear, clearYear } from '../../store/slices/roadmapSlice'; import { PlannerYearData } from '../../types/types'; +import ThemeContext from "src/style/theme-context"; interface YearProps { yearIndex: number; @@ -104,58 +105,65 @@ const Year: FC = ({ yearIndex, data }) => { - - - -
    - - - - -
    -
    -
    -
    - - - -
    - {!data.quarters.map(quarter => quarter.name).includes("fall") && } - {!data.quarters.map(quarter => quarter.name).includes("winter") && } - {!data.quarters.map(quarter => quarter.name).includes("spring") && } - {!data.quarters.map(quarter => quarter.name).includes("summer I") && } - {!data.quarters.map(quarter => quarter.name).includes("summer II") && } - {!data.quarters.map(quarter => quarter.name).includes("summer 10 Week") && } -
    -
    -
    -
    + + {({ darkMode }) => { + let variant = darkMode ? 'dark' : 'light'; + return <> + + + +
    + + + + +
    +
    +
    +
    + + + +
    + {!data.quarters.map(quarter => quarter.name).includes("fall") && } + {!data.quarters.map(quarter => quarter.name).includes("winter") && } + {!data.quarters.map(quarter => quarter.name).includes("spring") && } + {!data.quarters.map(quarter => quarter.name).includes("summer I") && } + {!data.quarters.map(quarter => quarter.name).includes("summer II") && } + {!data.quarters.map(quarter => quarter.name).includes("summer 10 Week") && } +
    +
    +
    +
    + ; + }} +
    diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 8e39609a..d230ef96 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -27,11 +27,30 @@ color: var(--text); } +.form-control::selection { + color: var(--text-dark); +} + .dropdown-menu, .dropdown-item, .form-control, .form-control:focus { color: var(--text-light); background-color: var(--overlay3); } +[data-theme='dark'] { + .modal-content { + background-color: var(--overlay1); + + .form-control, .form-control:focus { + background-color: var(--overlay2); + } + + .close { + color: white; + text-shadow: none; + } + } +} + .popover-body { background-color: var(--overlay1); color: var(--text); @@ -50,27 +69,29 @@ } // general semantic-ui overwrites. bg color may need to be customized per component -[data-theme='dark'] .ui, [data-theme='dark'] .ui.popup:before { - color: var(--text); - background-color: var(--overlay2); - border-color: var(--overlay1); -} +[data-theme='dark'] { + .ui, .ui.popup:before { + color: var(--text); + background-color: var(--overlay2); + border-color: var(--overlay1); + } -[data-theme='dark'] .ui.bottom.popup:before { - box-shadow: -1px -1px 0 0 var(--overlay1); -} + .ui.bottom.popup:before { + box-shadow: -1px -1px 0 0 var(--overlay1); + } -[data-theme='dark'] .ui.dropdown, [data-theme='dark'] .ui.dropdown .menu { - color: white; - background-color: var(--overlay3); - border-color: var(--overlay2); -} + .ui.dropdown, .ui.dropdown .menu { + color: white; + background-color: var(--overlay3); + border-color: var(--overlay2); + } -[data-theme='dark'] .ui.selection.visible.dropdown>.text:not(.default), -[data-theme='dark'] .ui.dropdown .menu>.item { - color: white; -} + .ui.selection.visible.dropdown>.text:not(.default), + .ui.dropdown .menu>.item { + color: white; + } -[data-theme='dark'] .ui.dropdown:hover { - border-color: var(--overlay1); -} \ No newline at end of file + .ui.dropdown:hover { + border-color: var(--overlay1); + } +} From d3ec2ac52abca0ff2a5aba30c7794bfc935e1200 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 00:14:32 -0700 Subject: [PATCH 11/41] Few theming tweaks to roadmap page --- site/src/component/ReviewForm/ReviewForm.scss | 6 ++++++ site/src/pages/RoadmapPage/Quarter.scss | 2 +- site/src/pages/RoadmapPage/Transfer.scss | 1 + site/src/style/theme.scss | 6 +++++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/site/src/component/ReviewForm/ReviewForm.scss b/site/src/component/ReviewForm/ReviewForm.scss index 26e7c29a..e07b4b5a 100644 --- a/site/src/component/ReviewForm/ReviewForm.scss +++ b/site/src/component/ReviewForm/ReviewForm.scss @@ -1,3 +1,9 @@ +[data-theme='dark'] { + .review-form .form-control, .form-control:focus { + background-color: var(--overlay3); + } +} + .review-form { background-color: var(--overlay2); border-radius: var(--border-radius); diff --git a/site/src/pages/RoadmapPage/Quarter.scss b/site/src/pages/RoadmapPage/Quarter.scss index 0e2433de..92a0c071 100644 --- a/site/src/pages/RoadmapPage/Quarter.scss +++ b/site/src/pages/RoadmapPage/Quarter.scss @@ -45,6 +45,6 @@ padding: 0; } -.red-menu-btn { +.red-menu-btn, .red-menu-btn:hover { color: red; } \ No newline at end of file diff --git a/site/src/pages/RoadmapPage/Transfer.scss b/site/src/pages/RoadmapPage/Transfer.scss index 2b9dfbe3..eea2e061 100644 --- a/site/src/pages/RoadmapPage/Transfer.scss +++ b/site/src/pages/RoadmapPage/Transfer.scss @@ -10,6 +10,7 @@ .transfer .list-group .list-group-item { min-width: max-content; + background-color: var(--overlay3); } .entry { diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index d230ef96..ecb0f7d1 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -36,9 +36,13 @@ background-color: var(--overlay3); } +.list-group-item { + background-color: var(--overlay2); +} + [data-theme='dark'] { .modal-content { - background-color: var(--overlay1); + background-color: var(--overlay2); .form-control, .form-control:focus { background-color: var(--overlay2); From b5af43ea4e611b6f7bc209ca17f563da5cc1b11b Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 01:08:47 -0700 Subject: [PATCH 12/41] Remove unused css tag --- site/src/component/PrereqTree/PrereqTree.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/component/PrereqTree/PrereqTree.scss b/site/src/component/PrereqTree/PrereqTree.scss index 1ba21ed0..40702e07 100644 --- a/site/src/component/PrereqTree/PrereqTree.scss +++ b/site/src/component/PrereqTree/PrereqTree.scss @@ -182,7 +182,7 @@ } } -.missing-tree, .prereq-text-box { +.prereq-text-box { padding: 1em; margin-top: 2em; background-color: var(--overlay2); From a95db494d5d9412da3c052c8ad53dcc58b164052 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 15:36:45 -0700 Subject: [PATCH 13/41] Fix hidden overflow for search bar box shadow --- site/src/pages/SearchPage/SearchPage.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/site/src/pages/SearchPage/SearchPage.scss b/site/src/pages/SearchPage/SearchPage.scss index 2b1247a6..05d69782 100644 --- a/site/src/pages/SearchPage/SearchPage.scss +++ b/site/src/pages/SearchPage/SearchPage.scss @@ -15,7 +15,6 @@ display: flex; flex-direction: column; height: 85vh; - overflow-y: hidden; } #search-popup { From e808653d657bf1f44f7aa212a6d7cbdcc687d366 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 15:51:16 -0700 Subject: [PATCH 14/41] Recenter sidebar mini icons --- site/src/component/SideBar/Sidebar.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/src/component/SideBar/Sidebar.scss b/site/src/component/SideBar/Sidebar.scss index a3e7bc1c..2397d284 100644 --- a/site/src/component/SideBar/Sidebar.scss +++ b/site/src/component/SideBar/Sidebar.scss @@ -97,6 +97,10 @@ div { display: flex; justify-content: center; + + i.icon { + margin: 0; + } } span { From 445431f895e7a9361fbe4b5e6d4ea0ff7e811a4f Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 22:20:05 -0700 Subject: [PATCH 15/41] Fix styling with modals, bootstrap, and semantic --- site/src/component/AppHeader/AppHeader.scss | 2 +- site/src/component/ReportForm/ReportForm.scss | 7 +++- site/src/component/ReviewForm/ReviewForm.scss | 6 ++- .../component/SearchModule/SearchModule.scss | 1 + site/src/style/theme.scss | 40 +++++++++---------- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/site/src/component/AppHeader/AppHeader.scss b/site/src/component/AppHeader/AppHeader.scss index e5988af0..183bf63a 100644 --- a/site/src/component/AppHeader/AppHeader.scss +++ b/site/src/component/AppHeader/AppHeader.scss @@ -10,7 +10,7 @@ } .beta-popup .button:hover, .beta-popup .button:focus { - background-color: #CACBCD; + background-color: var(--hover); } .navbar { diff --git a/site/src/component/ReportForm/ReportForm.scss b/site/src/component/ReportForm/ReportForm.scss index b6a263a4..14bbcf5e 100644 --- a/site/src/component/ReportForm/ReportForm.scss +++ b/site/src/component/ReportForm/ReportForm.scss @@ -19,7 +19,6 @@ textarea { color: var(--text); - background-color: var(--overlay3); border-radius: var(--border-radius); border: 2px solid #EAEBF2; padding: 1rem; @@ -28,7 +27,11 @@ display: block; } - textarea:focus { + textarea.form-control { + background-color: var(--overlay3); + } + + textarea.form-control:focus { color: var(--text); background-color: var(--overlay3); } diff --git a/site/src/component/ReviewForm/ReviewForm.scss b/site/src/component/ReviewForm/ReviewForm.scss index e07b4b5a..a049ca90 100644 --- a/site/src/component/ReviewForm/ReviewForm.scss +++ b/site/src/component/ReviewForm/ReviewForm.scss @@ -1,6 +1,8 @@ [data-theme='dark'] { - .review-form .form-control, .form-control:focus { - background-color: var(--overlay3); + .review-form { + .form-control, .form-control:focus { + background-color: var(--overlay3); + } } } diff --git a/site/src/component/SearchModule/SearchModule.scss b/site/src/component/SearchModule/SearchModule.scss index 41f62f3f..4b32f3e1 100644 --- a/site/src/component/SearchModule/SearchModule.scss +++ b/site/src/component/SearchModule/SearchModule.scss @@ -5,6 +5,7 @@ [data-theme='dark'] { .search-bar, + .search-bar:focus, .search-module .input-group-text { color: var(--text); background-color: var(--overlay1); diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index ecb0f7d1..f837b46a 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -7,6 +7,7 @@ --text: #212529; // default bootstrap color --text-dark: #000; --text-light: #495057; + --hover: #CACBCD; // semantic-ui default } // dark theme vars @@ -20,6 +21,7 @@ --text: #fff; --text-dark: #fff; --text-light: #fff; + --hover: #CACBCD; } // general bootstrap overwrites. bg color may need further customization per component @@ -31,27 +33,23 @@ color: var(--text-dark); } -.dropdown-menu, .dropdown-item, .form-control, .form-control:focus { - color: var(--text-light); - background-color: var(--overlay3); -} - -.list-group-item { - background-color: var(--overlay2); -} [data-theme='dark'] { - .modal-content { + .list-group-item, + .modal-content, + .dropdown-menu, .dropdown-item, + .form-control, .form-control:focus { + color: var(--text); background-color: var(--overlay2); + } - .form-control, .form-control:focus { - background-color: var(--overlay2); - } + .dropdown-item:hover { + background-color: var(--overlay3); + } - .close { - color: white; - text-shadow: none; - } + .close { + color: var(--text); + text-shadow: none; } } @@ -85,17 +83,17 @@ } .ui.dropdown, .ui.dropdown .menu { - color: white; - background-color: var(--overlay3); - border-color: var(--overlay2); + color: var(--text); + background-color: var(--overlay2); + border-color: var(--overlay1); } .ui.selection.visible.dropdown>.text:not(.default), .ui.dropdown .menu>.item { - color: white; + color: var(--text); } .ui.dropdown:hover { - border-color: var(--overlay1); + border-color: var(--overlay3); } } From 5c6e6366ad6074edea49b3fdc85f18b8451d4b1a Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 22:22:06 -0700 Subject: [PATCH 16/41] Change semantic-ui dropdown item hover color (dark mode) --- site/src/style/theme.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index f837b46a..1fb40501 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -96,4 +96,7 @@ .ui.dropdown:hover { border-color: var(--overlay3); } + .ui.dropdown .menu>.item:hover { + background-color: var(--overlay3); + } } From 994edc237dcf1ee3bdeb5264019e9c9bf219ebf9 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 22:29:41 -0700 Subject: [PATCH 17/41] Change SideBar to use useContext for theme context --- site/src/component/SideBar/SideBar.tsx | 57 +++++++++++--------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/site/src/component/SideBar/SideBar.tsx b/site/src/component/SideBar/SideBar.tsx index db93f9b8..c7d7dcdd 100644 --- a/site/src/component/SideBar/SideBar.tsx +++ b/site/src/component/SideBar/SideBar.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { NavLink } from 'react-router-dom'; import { Icon } from 'semantic-ui-react'; import { XCircle } from 'react-bootstrap-icons'; @@ -19,6 +19,7 @@ const SideBar = () => { const [name, setName] = useState(''); const [picture, setPicture] = useState(''); const [isAdmin, setIsAdmin] = useState(false); + const { darkMode, toggleTheme } = useContext(ThemeContext); let isLoggedIn = cookies.hasOwnProperty('user'); @@ -69,19 +70,15 @@ const SideBar = () => { {showSidebar &&
  • - - {({ darkMode, toggleTheme }) => - // eslint-disable-next-line jsx-a11y/anchor-is-valid - -
    - -
    - - Toggle Dark Mode - -
    - } -
    + {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} + +
    + +
    + + Toggle Dark Mode + +
  • } {isAdmin && <>
  • @@ -135,28 +132,20 @@ const SideBar = () => { {/* Login/Logout */}
  • From 785df84b1f185d5eae40de6c5ff8e542d1b62ac3 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 22:59:16 -0700 Subject: [PATCH 18/41] Fix dropdown color in search popup --- site/src/component/SearchPopup/SearchPopup.scss | 16 ++++++++++++++++ site/src/style/theme.scss | 2 ++ 2 files changed, 18 insertions(+) diff --git a/site/src/component/SearchPopup/SearchPopup.scss b/site/src/component/SearchPopup/SearchPopup.scss index 3d39f864..b915a8dd 100644 --- a/site/src/component/SearchPopup/SearchPopup.scss +++ b/site/src/component/SearchPopup/SearchPopup.scss @@ -1,3 +1,19 @@ +[data-theme='dark'] { + .search-popup { + .dropdown, .dropdown .menu { + background-color: var(--overlay3); + border-color: var(--overlay2); + } + + .dropdown:hover { + border-color: var(--overlay4); + } + .ui.dropdown .menu>.item:hover { + background-color: var(--overlay4); + } + } +} + .search-popup-missing { display: flex; flex-direction: column; diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 1fb40501..40061696 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -4,6 +4,7 @@ --overlay1: #fff; --overlay2: var(--peterportal-gray-blue); --overlay3: #fff; + --overlay4: var(--peterportal-gray-blue); --text: #212529; // default bootstrap color --text-dark: #000; --text-light: #495057; @@ -18,6 +19,7 @@ --overlay1: #1E1E1E; --overlay2: #292929; --overlay3: #363636; + --overlay4: #404040; --text: #fff; --text-dark: #fff; --text-light: #fff; From 8cf5c3ffbbeb565c319e9c55aa47de0098baeb1b Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 28 May 2023 23:06:37 -0700 Subject: [PATCH 19/41] Update dark theme comments --- site/src/style/theme.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 40061696..ae6be8f4 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -26,7 +26,7 @@ --hover: #CACBCD; } -// general bootstrap overwrites. bg color may need further customization per component +// general bootstrap overwrites. bg/border color may need further customization per component .table { color: var(--text); } @@ -71,8 +71,9 @@ .bs-popover-right>.arrow::after { border-right-color: var(--overlay1); } +// end bootstrap overwrites -// general semantic-ui overwrites. bg color may need to be customized per component +// general semantic-ui overwrites. bg/border color may need to be customized per component [data-theme='dark'] { .ui, .ui.popup:before { color: var(--text); @@ -102,3 +103,4 @@ background-color: var(--overlay3); } } +// end semantic-ui overwrites From 6fb63409d8611eb44f02d63780aa985e2fac95a1 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Mon, 29 May 2023 00:00:00 -0700 Subject: [PATCH 20/41] Center report modal to hide floating border that appears on the top of the screen --- site/src/component/ReportForm/ReportForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/component/ReportForm/ReportForm.tsx b/site/src/component/ReportForm/ReportForm.tsx index b339592b..bd87f131 100644 --- a/site/src/component/ReportForm/ReportForm.tsx +++ b/site/src/component/ReportForm/ReportForm.tsx @@ -77,7 +77,7 @@ const ReportForm: FC = (props) => { ); return ( - +
    {reportSubmitted ? (
    From 8d26f60cc6dc472d2249fd7f03645505a70e6a10 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Mon, 29 May 2023 15:21:14 -0700 Subject: [PATCH 21/41] Fix sidebar link hover color on dark mode --- site/src/component/SideBar/Sidebar.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/site/src/component/SideBar/Sidebar.scss b/site/src/component/SideBar/Sidebar.scss index 2397d284..1af51a5b 100644 --- a/site/src/component/SideBar/Sidebar.scss +++ b/site/src/component/SideBar/Sidebar.scss @@ -1,3 +1,13 @@ +[data-theme='dark'] { + .sidebar { + .sidebar-links { + ul li a:hover { + background-color: var(--overlay2); + } + } + } +} + .sidebar { position: fixed; width: 20vw; From 5ff799db6474e2b51897afb3bf256db71887cf87 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Mon, 29 May 2023 15:27:34 -0700 Subject: [PATCH 22/41] Fix dropdown active color in dark mode --- site/src/component/SearchPopup/SearchPopup.scss | 8 ++++++-- site/src/style/theme.scss | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/site/src/component/SearchPopup/SearchPopup.scss b/site/src/component/SearchPopup/SearchPopup.scss index b915a8dd..2aa214b1 100644 --- a/site/src/component/SearchPopup/SearchPopup.scss +++ b/site/src/component/SearchPopup/SearchPopup.scss @@ -8,8 +8,12 @@ .dropdown:hover { border-color: var(--overlay4); } - .ui.dropdown .menu>.item:hover { - background-color: var(--overlay4); + + .ui.dropdown { + .menu>.item.active, + .menu>.item:hover { + background-color: var(--overlay4); + } } } } diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index ae6be8f4..0f3510f7 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -99,8 +99,11 @@ .ui.dropdown:hover { border-color: var(--overlay3); } - .ui.dropdown .menu>.item:hover { - background-color: var(--overlay3); + .ui.dropdown { + .menu>.item:hover, + .menu>.item.active{ + background-color: var(--overlay3); + } } } // end semantic-ui overwrites From 75643ff3b45891e5d7a6f5320b7774bfb2f95ba4 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Mon, 29 May 2023 22:32:04 -0700 Subject: [PATCH 23/41] Fix search bar border color on dark mode --- site/src/component/SearchModule/SearchModule.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/component/SearchModule/SearchModule.scss b/site/src/component/SearchModule/SearchModule.scss index 4b32f3e1..deed11d7 100644 --- a/site/src/component/SearchModule/SearchModule.scss +++ b/site/src/component/SearchModule/SearchModule.scss @@ -9,7 +9,7 @@ .search-module .input-group-text { color: var(--text); background-color: var(--overlay1); - border-color: var(--overlay3); + border-color: var(--overlay2); } .search-bar:focus { border-color: #80bdff; From 8ce4623e33ae454b3a147b76c52afe9497a87170 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Wed, 31 May 2023 14:53:54 -0700 Subject: [PATCH 24/41] Save user's theme preference to mongo --- api/src/controllers/users.ts | 49 ++++++++++++++++++++++++++++++++++++ api/src/helpers/mongo.ts | 3 ++- site/src/App.tsx | 33 +++++++++++++++++++++--- 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/api/src/controllers/users.ts b/api/src/controllers/users.ts index 29bf03cc..9f490972 100644 --- a/api/src/controllers/users.ts +++ b/api/src/controllers/users.ts @@ -4,6 +4,7 @@ import express, { Request, Response } from 'express'; import passport from 'passport'; +import { COLLECTION_NAMES, addDocument, getCollection, getDocuments, updateDocument } from '../helpers/mongo'; let router = express.Router(); @@ -14,6 +15,54 @@ router.get('/', function (req, res, next) { res.json(req.session) }); +router.get('/preferences', (req, res) => { + if (!req.session.passport) { + res.json({ error: 'Must be logged in to get preferences.'}); + return; + } + + const userID = req.session.passport.user.id; + + getDocuments(COLLECTION_NAMES.PREFERENCES, { _id: userID }).then(preferences => { + if (preferences.length > 0) { + res.json(preferences[0]); + } else { + res.json({ error: 'No preferences found' }); + } + }) +}); + +interface UserPreferences { + theme?: string; +} + +router.post('/preferences', async (req, res) => { + if (!req.session.passport) { + res.json({ error: 'Must be logged in to get preferences.'}); + return; + } + + const userID = req.session.passport.user.id; + + // make user's preference doc if it doesn't exist + const preferencesCollection = await getCollection(COLLECTION_NAMES.PREFERENCES); + if ((await preferencesCollection.find({ _id: userID }).count()) == 0) { + await addDocument(COLLECTION_NAMES.PREFERENCES, { _id: userID }); + } + + // grab valid preferences from request body + const preferences: UserPreferences = {}; + if (req.body.theme) { + preferences.theme = req.body.theme; + } + + // set the preferences + await updateDocument(COLLECTION_NAMES.PREFERENCES, { _id: userID }, { $set: preferences }); + + // echo back body + res.json(req.body); +}); + /** * Get whether or not a user is an admin */ diff --git a/api/src/helpers/mongo.ts b/api/src/helpers/mongo.ts index 4e664b8a..21a9a085 100644 --- a/api/src/helpers/mongo.ts +++ b/api/src/helpers/mongo.ts @@ -22,7 +22,8 @@ const COLLECTION_NAMES = { SCHEDULE: 'schedule', ROADMAPS: 'roadmaps', VOTES: 'votes', - REPORTS: 'reports' + REPORTS: 'reports', + PREFERENCES: 'preferences' } /** * Global reference to database diff --git a/site/src/App.tsx b/site/src/App.tsx index d30ab688..d67535ec 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -23,16 +23,43 @@ import SideBar from './component/SideBar/SideBar'; import { useAppSelector } from './store/hooks'; import ThemeContext from './style/theme-context'; +import axios from 'axios'; +import { useCookies } from 'react-cookie'; + export default function App() { - const [darkMode, setDarkMode] = useState(localStorage.getItem('darkMode') === 'true' ? true : (localStorage.getItem('darkMode') === 'false' ? false : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches))); + // default darkMode to local or system preferences + const [darkMode, setDarkMode] = useState(localStorage.getItem('theme') === 'dark' ? true : (localStorage.getItem('theme') === 'light' ? false : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches))); const sidebarOpen = useAppSelector(state => state.ui.sidebarOpen); const [isShown, setIsShown] = useState(false); + const [cookies, setCookies] = useCookies(['user']); + + useEffect(() => { + // if logged in, load user prefs (theme) from mongo + if (cookies.user) { + axios.get('/api/users/preferences').then(res => { + const { theme } = res.data; + if (theme === 'dark') { + setDarkMode(true); + } else if (theme === 'light') { + setDarkMode(false); + } else { // not defined or set to use local/system prefs + setDarkMode(localStorage.getItem('theme') === 'dark' ? true : (localStorage.getItem('theme') === 'light' ? false : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches))); + setDarkMode(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches); + } + }); + } + }, [cookies.user]); useEffect(() => { - localStorage.setItem('darkMode', darkMode ? 'true' : 'false'); document.querySelector('body')!.setAttribute('data-theme', darkMode ? 'dark' : 'light'); - }, [darkMode]) + if (cookies.user) { + axios.post('/api/users/preferences', { theme: darkMode ? 'dark' : 'light', bs: '123', hello: 'world' }).then(res => + console.log(res.data)); + } else { + localStorage.setItem('theme', darkMode ? 'dark' : 'light'); + } + }, [darkMode]); const toggleTheme = () => { setDarkMode(!darkMode); From fce09ae9ed1bd157a604337dc76b6bc0ca23f8ec Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Wed, 31 May 2023 16:26:50 -0700 Subject: [PATCH 25/41] Fix quarter and year menu button hover/focus colors --- site/src/pages/RoadmapPage/Quarter.scss | 12 +++++++++--- site/src/pages/RoadmapPage/Year.scss | 6 ++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/site/src/pages/RoadmapPage/Quarter.scss b/site/src/pages/RoadmapPage/Quarter.scss index 92a0c071..a20369a7 100644 --- a/site/src/pages/RoadmapPage/Quarter.scss +++ b/site/src/pages/RoadmapPage/Quarter.scss @@ -1,5 +1,11 @@ -[data-theme='dark'] .quarter .quarter-header .quarter-title { - color: #eee; +[data-theme='dark'] { + .quarter .quarter-header .quarter-title { + color: #eee; + } + + .quarter-menu-btn:hover, .quarter-menu-btn:focus, .popover-body .quarter-menu-btn:active { + background-color: var(--overlay2); + } } .quarter { @@ -45,6 +51,6 @@ padding: 0; } -.red-menu-btn, .red-menu-btn:hover { +.red-menu-btn, .red-menu-btn:hover, .red-menu-btn:focus, .popover-body .quarter-menu-btn.red-menu-btn:active { color: red; } \ No newline at end of file diff --git a/site/src/pages/RoadmapPage/Year.scss b/site/src/pages/RoadmapPage/Year.scss index 9cb3b5a1..59ea5f40 100644 --- a/site/src/pages/RoadmapPage/Year.scss +++ b/site/src/pages/RoadmapPage/Year.scss @@ -5,6 +5,12 @@ --petr-gray: #808080; } +[data-theme='dark'] { + .year-settings-btn:hover, .year-settings-btn:focus, .popover-body .year-settings-btn:active { + background-color: var(--overlay2); + } +} + .year { margin: 1rem 0; padding: 1rem; From c388e6c76c8f601a54da6a017f98f84fe36d134a Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Thu, 1 Jun 2023 20:52:09 -0700 Subject: [PATCH 26/41] Fix add year popup input dark theme color --- site/src/pages/RoadmapPage/AddYearPopup.scss | 8 ++++++++ site/src/pages/RoadmapPage/AddYearPopup.tsx | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/site/src/pages/RoadmapPage/AddYearPopup.scss b/site/src/pages/RoadmapPage/AddYearPopup.scss index b65a821d..7e555051 100644 --- a/site/src/pages/RoadmapPage/AddYearPopup.scss +++ b/site/src/pages/RoadmapPage/AddYearPopup.scss @@ -1,3 +1,11 @@ +[data-theme='dark'] { + .add-year-form { + .form-control, .form-control:focus { + background-color: var(--overlay1); + } + } +} + .add-year-btn { background-color: transparent; color: var(--petr-gray); diff --git a/site/src/pages/RoadmapPage/AddYearPopup.tsx b/site/src/pages/RoadmapPage/AddYearPopup.tsx index 147349b1..00f65283 100644 --- a/site/src/pages/RoadmapPage/AddYearPopup.tsx +++ b/site/src/pages/RoadmapPage/AddYearPopup.tsx @@ -31,7 +31,7 @@ const AddYearPopup: FC = ({ placeholderYear }) => {
    - + Start Year From e16a47f484dd7e96bf0662761e739bdbbec84a63 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 11 Jun 2023 00:34:32 -0700 Subject: [PATCH 27/41] Add dark mode to user reviews page --- site/src/component/UserReviews/UserReviews.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/src/component/UserReviews/UserReviews.scss b/site/src/component/UserReviews/UserReviews.scss index f02a2e5d..b2934175 100644 --- a/site/src/component/UserReviews/UserReviews.scss +++ b/site/src/component/UserReviews/UserReviews.scss @@ -1,11 +1,10 @@ .user-reviews-container { padding: 2rem; - background-color: white; + background-color: var(--overlay1); border-radius: var(--border-radius); } .user-reviews { - background-color: white; border-radius: var(--border-radius); margin-bottom: 3vh; From f4d8c6e628c111d005ab06a34636a10bb13e2783 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Thu, 22 Jun 2023 21:50:52 -0700 Subject: [PATCH 28/41] Use color-scheme css prop for dark mode --- site/src/style/theme.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 0f3510f7..3f755ea0 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -24,6 +24,8 @@ --text-dark: #fff; --text-light: #fff; --hover: #CACBCD; + + color-scheme: dark; } // general bootstrap overwrites. bg/border color may need further customization per component From 9b6ef23e66308eda162a2285ee3bf46a28f9b023 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 5 Nov 2023 19:22:27 -0800 Subject: [PATCH 29/41] Remove old search graphic --- site/src/asset/searching.png | Bin 79038 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 site/src/asset/searching.png diff --git a/site/src/asset/searching.png b/site/src/asset/searching.png deleted file mode 100644 index 72a16dd85201e4506123806bab908036887587a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79038 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

    J+)rfl;?Hj8J;)x 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 NG0-#Ct<`pn`9EQ#cme Date: Sat, 11 Nov 2023 18:37:15 -0800 Subject: [PATCH 30/41] Dark theme for recaptcha and verified review checkbox --- site/src/component/Review/Review.scss | 5 +++++ site/src/component/ReviewForm/ReviewForm.tsx | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/site/src/component/Review/Review.scss b/site/src/component/Review/Review.scss index a7205352..26cd5d05 100644 --- a/site/src/component/Review/Review.scss +++ b/site/src/component/Review/Review.scss @@ -199,8 +199,13 @@ $avatarWidth: 65px; display: flex; align-items: center; + .checkbox { + background: none; + } + label { margin-bottom: 0.25rem; + color: var(--text); } } } \ No newline at end of file diff --git a/site/src/component/ReviewForm/ReviewForm.tsx b/site/src/component/ReviewForm/ReviewForm.tsx index e202fde7..5e832919 100644 --- a/site/src/component/ReviewForm/ReviewForm.tsx +++ b/site/src/component/ReviewForm/ReviewForm.tsx @@ -1,4 +1,4 @@ -import React, { FC, FormEvent, ChangeEvent, useState, useEffect } from 'react' +import React, { FC, FormEvent, ChangeEvent, useState, useEffect, useContext } from 'react' import './ReviewForm.scss' import axios from 'axios' import { useCookies } from 'react-cookie'; @@ -16,6 +16,7 @@ import { addReview } from '../../store/slices/reviewSlice'; import { useAppDispatch, useAppSelector } from '../../store/hooks'; import { ReviewProps } from '../Review/Review'; import { ReviewData } from '../../types/types'; +import ThemeContext from 'src/style/theme-context'; interface ReviewFormProps extends ReviewProps { closeForm: () => void; @@ -57,6 +58,7 @@ const ReviewForm: FC = (props) => { const [cookies, setCookie] = useCookies(['user']); const [validated, setValidated] = useState(false); const showForm = useAppSelector(state => state.review.formOpen); + const { darkMode } = useContext(ThemeContext); useEffect(() => { // get user info from cookie @@ -395,6 +397,7 @@ const ReviewForm: FC = (props) => { { // if verified if (token) { From 1025aec05f571e65a62c74b16ab62ce2b608199a Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 21 Jan 2024 00:40:01 -0800 Subject: [PATCH 31/41] Fix merging on beta popup --- site/src/component/AppHeader/AppHeader.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/component/AppHeader/AppHeader.tsx b/site/src/component/AppHeader/AppHeader.tsx index 22bd1903..782221b3 100644 --- a/site/src/component/AppHeader/AppHeader.tsx +++ b/site/src/component/AppHeader/AppHeader.tsx @@ -85,6 +85,7 @@ const AppHeader: FC = () => {

    Date: Sun, 21 Jan 2024 01:30:48 -0800 Subject: [PATCH 32/41] Format --- api/src/config/passport.ts | 48 +- api/src/controllers/graphql.ts | 27 +- api/src/controllers/reports.ts | 65 +-- api/src/controllers/roadmap.ts | 56 +- api/src/helpers/mongo.ts | 498 +++++++++--------- site/src/App.scss | 30 +- site/src/component/AppHeader/AppHeader.scss | 4 +- site/src/component/Error/Error.scss | 28 +- site/src/component/Footer/Footer.scss | 60 +-- site/src/component/GradeDist/GradeDist.scss | 2 +- site/src/component/PrereqTree/PrereqTree.scss | 300 +++++------ site/src/component/Report/ReportGroup.scss | 59 +-- site/src/component/Report/Reports.scss | 8 +- site/src/component/Report/SubReport.scss | 18 +- site/src/component/ReportForm/ReportForm.scss | 26 +- site/src/component/Review/Review.scss | 4 +- site/src/component/ReviewForm/ReviewForm.scss | 7 +- .../SearchHitContainer.scss | 6 +- .../component/SearchModule/SearchModule.scss | 26 +- .../component/SearchPopup/SearchPopup.scss | 167 +++--- site/src/component/SideBar/Sidebar.scss | 6 +- site/src/component/SideInfo/SideInfo.scss | 204 +++---- .../component/UserReviews/UserReviews.scss | 22 +- site/src/component/Verify/Verify.scss | 22 +- site/src/hooks/firstRenderer.tsx | 12 +- site/src/pages/CoursePage/CoursePage.scss | 38 +- .../pages/ProfessorPage/ProfessorPage.scss | 38 +- .../src/pages/RoadmapPage/AddCoursePopup.scss | 6 +- site/src/pages/RoadmapPage/AddYearPopup.scss | 3 +- site/src/pages/RoadmapPage/Course.scss | 8 +- site/src/pages/RoadmapPage/Planner.scss | 3 +- site/src/pages/RoadmapPage/Quarter.scss | 13 +- site/src/pages/RoadmapPage/SearchSidebar.scss | 2 +- site/src/pages/RoadmapPage/Transfer.scss | 15 +- site/src/pages/RoadmapPage/Year.scss | 8 +- site/src/pages/RoadmapPage/index.scss | 4 +- site/src/pages/SearchPage/HitItem.scss | 20 +- site/src/pages/SearchPage/SearchPage.scss | 54 +- site/src/pages/SearchPage/width.config.scss | 2 +- site/src/store/hooks.ts | 8 +- site/src/store/slices/popupSlice.ts | 42 +- site/src/store/slices/reviewSlice.ts | 54 +- site/src/store/slices/uiSlice.ts | 42 +- site/src/store/store.ts | 22 +- site/src/style/theme-context.ts | 10 +- site/src/style/theme.scss | 35 +- sst.config.ts | 35 +- 47 files changed, 1087 insertions(+), 1080 deletions(-) diff --git a/api/src/config/passport.ts b/api/src/config/passport.ts index d64f2e08..5e35e751 100644 --- a/api/src/config/passport.ts +++ b/api/src/config/passport.ts @@ -3,43 +3,43 @@ */ import passport from 'passport'; -import { OAuth2Strategy as GoogleStrategy, VerifyOptions } from 'passport-google-oauth' +import { OAuth2Strategy as GoogleStrategy, VerifyOptions } from 'passport-google-oauth'; // var FacebookStrategy = require('passport-facebook').Strategy; // var GitHubStrategy = require('passport-github').Strategy; passport.serializeUser(function (user, done) { - done(null, user); + done(null, user); }); passport.deserializeUser(function (user: any, done) { - done(null, user); + done(null, user); }); /** * Configuration for Google Strategy */ passport.use( - new GoogleStrategy( - { - clientID: process.env.GOOGLE_CLIENT, - clientSecret: process.env.GOOGLE_SECRET, - callbackURL: process.env.PRODUCTION_DOMAIN + '/api/users/auth/google/callback', - }, - function (accessToken, refreshToken, profile, done) { - let email = ''; - // get the first registered email - if (profile.emails && profile.emails.length! > 0) { - email = profile.emails[0].value; - } - var userData = { - id: profile.id, - email: email, - name: profile.displayName, - picture: profile._json.picture - }; - done(null, userData); - } - ) + new GoogleStrategy( + { + clientID: process.env.GOOGLE_CLIENT, + clientSecret: process.env.GOOGLE_SECRET, + callbackURL: process.env.PRODUCTION_DOMAIN + '/api/users/auth/google/callback', + }, + function (accessToken, refreshToken, profile, done) { + let email = ''; + // get the first registered email + if (profile.emails && profile.emails.length! > 0) { + email = profile.emails[0].value; + } + var userData = { + id: profile.id, + email: email, + name: profile.displayName, + picture: profile._json.picture, + }; + done(null, userData); + }, + ), ); // passport.use(new FacebookStrategy({ diff --git a/api/src/controllers/graphql.ts b/api/src/controllers/graphql.ts index ec9efac6..afcaa95f 100644 --- a/api/src/controllers/graphql.ts +++ b/api/src/controllers/graphql.ts @@ -10,20 +10,19 @@ var router = express.Router(); * Graphql proxy */ router.post('/', function (req, res, next) { - let r = fetch(process.env.PUBLIC_API_GRAPHQL_URL, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(req.body) - }) + let r = fetch(process.env.PUBLIC_API_GRAPHQL_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(req.body), + }); - r.then((response) => response.json()) - .then((data) => { - res.send(data) - }) - .catch(err => console.log('Error:', err)) + r.then((response) => response.json()) + .then((data) => { + res.send(data); + }) + .catch((err) => console.log('Error:', err)); }); -export default router; \ No newline at end of file +export default router; diff --git a/api/src/controllers/reports.ts b/api/src/controllers/reports.ts index fb394a9c..5344739b 100644 --- a/api/src/controllers/reports.ts +++ b/api/src/controllers/reports.ts @@ -4,7 +4,14 @@ import express from 'express'; import { ObjectID } from 'mongodb'; -import { COLLECTION_NAMES, getCollection, addDocument, getDocuments, deleteDocument, deleteDocuments } from '../helpers/mongo'; +import { + COLLECTION_NAMES, + getCollection, + addDocument, + getDocuments, + deleteDocument, + deleteDocuments, +} from '../helpers/mongo'; import { GenericObject } from '../types/types'; var router = express.Router(); @@ -13,47 +20,45 @@ var router = express.Router(); * Get all reports */ router.get('/', async (req, res, next) => { - console.log('Getting all reports'); - - let reports = await getDocuments(COLLECTION_NAMES.REPORTS, {}); // get all reports in collection + console.log('Getting all reports'); - res.json(reports); + let reports = await getDocuments(COLLECTION_NAMES.REPORTS, {}); // get all reports in collection + + res.json(reports); }); /** * Add a report */ router.post('/', async (req, res, next) => { - console.log(`Adding Report: ${JSON.stringify(req.body)}`); + console.log(`Adding Report: ${JSON.stringify(req.body)}`); - await addDocument(COLLECTION_NAMES.REPORTS, req.body); + await addDocument(COLLECTION_NAMES.REPORTS, req.body); - res.json(req.body); + res.json(req.body); }); /** * Delete a report */ router.delete('/', async (req, res, next) => { - - let status; - if (req.body.id) { - console.log(`Deleting report ${req.body.id}`); - status = await deleteDocument(COLLECTION_NAMES.REPORTS, { - _id: new ObjectID(req.body.id) - }); - } - else { - console.log(`Deleting reports with reviewID ${req.body.reviewID}`); - let query: GenericObject = {}; - if (req.body.reviewID) query['reviewID'] = req.body.reviewID; - - if (Object.keys(query).length === 0) return; // avoid deleting all documents if no filters are specified - - status = await deleteDocuments(COLLECTION_NAMES.REPORTS, query); - } - - res.json(status); -}) - -export default router; \ No newline at end of file + let status; + if (req.body.id) { + console.log(`Deleting report ${req.body.id}`); + status = await deleteDocument(COLLECTION_NAMES.REPORTS, { + _id: new ObjectID(req.body.id), + }); + } else { + console.log(`Deleting reports with reviewID ${req.body.reviewID}`); + let query: GenericObject = {}; + if (req.body.reviewID) query['reviewID'] = req.body.reviewID; + + if (Object.keys(query).length === 0) return; // avoid deleting all documents if no filters are specified + + status = await deleteDocuments(COLLECTION_NAMES.REPORTS, query); + } + + res.json(status); +}); + +export default router; diff --git a/api/src/controllers/roadmap.ts b/api/src/controllers/roadmap.ts index ba1949a8..31483cc6 100644 --- a/api/src/controllers/roadmap.ts +++ b/api/src/controllers/roadmap.ts @@ -1,6 +1,13 @@ import express from 'express'; import { ObjectID } from 'mongodb'; -import { COLLECTION_NAMES, containsID, getCollection, addDocument, getDocuments, replaceDocument } from '../helpers/mongo'; +import { + COLLECTION_NAMES, + containsID, + getCollection, + addDocument, + getDocuments, + replaceDocument, +} from '../helpers/mongo'; var router = express.Router(); @@ -8,37 +15,34 @@ var router = express.Router(); * Get a roadmap */ router.get<{}, {}, {}, { id: string }>('/get', async function (req, res) { - getDocuments(COLLECTION_NAMES.ROADMAPS, { _id: req.query.id }) - .then(roadmaps => { - if (roadmaps.length > 0) { - res.json(roadmaps[0]); - } - else { - res.json({ error: 'No roadmap found!' }); - } - }) -}) + getDocuments(COLLECTION_NAMES.ROADMAPS, { _id: req.query.id }).then((roadmaps) => { + if (roadmaps.length > 0) { + res.json(roadmaps[0]); + } else { + res.json({ error: 'No roadmap found!' }); + } + }); +}); /** * Add a roadmap */ router.post<{}, {}, { _id: string }>('/', async function (req, res, next) { - if (!req.body._id) { - res.json({ error: 'Invalid input' }); - return; - } - console.log(`Adding Roadmap: ${JSON.stringify(req.body)}`) + if (!req.body._id) { + res.json({ error: 'Invalid input' }); + return; + } + console.log(`Adding Roadmap: ${JSON.stringify(req.body)}`); - if (await containsID(COLLECTION_NAMES.ROADMAPS, req.body._id)) { - // overwrite - await replaceDocument(COLLECTION_NAMES.ROADMAPS, { _id: req.body._id }, req.body) - } - else { - // add roadmap to mongo - await addDocument(COLLECTION_NAMES.ROADMAPS, req.body); - } + if (await containsID(COLLECTION_NAMES.ROADMAPS, req.body._id)) { + // overwrite + await replaceDocument(COLLECTION_NAMES.ROADMAPS, { _id: req.body._id }, req.body); + } else { + // add roadmap to mongo + await addDocument(COLLECTION_NAMES.ROADMAPS, req.body); + } - res.json({}) + res.json({}); }); -export default router; \ No newline at end of file +export default router; diff --git a/api/src/helpers/mongo.ts b/api/src/helpers/mongo.ts index 366e2f9b..645b1e28 100644 --- a/api/src/helpers/mongo.ts +++ b/api/src/helpers/mongo.ts @@ -2,8 +2,8 @@ @module MongoHelper */ -import { MongoClient, Db, Collection } from 'mongodb' -import { GenericObject } from '../types/types' +import { MongoClient, Db, Collection } from 'mongodb'; +import { GenericObject } from '../types/types'; /** * Client used to connect to mongo @@ -17,14 +17,14 @@ const DB_NAME = process.env.NODE_ENV == 'production' ? 'peterPortalDB' : 'peterP * Collection names that we are using */ const COLLECTION_NAMES = { - SESSIONS: 'sessions', - REVIEWS: 'reviews', - SCHEDULE: 'schedule', - ROADMAPS: 'roadmaps', - VOTES: 'votes', - REPORTS: 'reports', - PREFERENCES: 'preferences' -} + SESSIONS: 'sessions', + REVIEWS: 'reviews', + SCHEDULE: 'schedule', + ROADMAPS: 'roadmaps', + VOTES: 'votes', + REPORTS: 'reports', + PREFERENCES: 'preferences', +}; /** * Global reference to database */ @@ -35,39 +35,37 @@ let db: Db = undefined!; * @returns Mongo database object */ function getDB(): Promise { - return new Promise((resolve, reject) => { - // if not connected yet, initiate connection - if (!db) { - client.connect(async err => { - if (err) { - reject(err); - } - else { - db = client.db(DB_NAME); + return new Promise((resolve, reject) => { + // if not connected yet, initiate connection + if (!db) { + client.connect(async (err) => { + if (err) { + reject(err); + } else { + db = client.db(DB_NAME); - // get existing mongo collection - let collectionNames = Object.values(COLLECTION_NAMES); - let collections = await db.listCollections().toArray(); - let existingCollectionNames: string[] = []; - collections.forEach(collection => { - existingCollectionNames.push(collection['name']); - }) + // get existing mongo collection + let collectionNames = Object.values(COLLECTION_NAMES); + let collections = await db.listCollections().toArray(); + let existingCollectionNames: string[] = []; + collections.forEach((collection) => { + existingCollectionNames.push(collection['name']); + }); - // create collections that dont exist - for (let i = 0; i < collectionNames.length; ++i) { - let collectionName = collectionNames[i]; - if (!existingCollectionNames.includes(collectionName)) { - await db.createCollection(collectionName); - } - } - resolve(db); - } - }); - } - else { - resolve(db); + // create collections that dont exist + for (let i = 0; i < collectionNames.length; ++i) { + let collectionName = collectionNames[i]; + if (!existingCollectionNames.includes(collectionName)) { + await db.createCollection(collectionName); + } + } + resolve(db); } - }) + }); + } else { + resolve(db); + } + }); } /** @@ -76,61 +74,59 @@ function getDB(): Promise { * @returns Mongo collection object */ function getCollection(collectionName: string): Promise> { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - // check if collection exists - db.listCollections({ name: collectionName }) - .next(function (err, collection) { - if (err) reject(err); - if (collection) { - resolve(db.collection(collectionName)!); - } - else { - reject(`Collection ${collectionName} does not exist!`); - } - }); + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + // check if collection exists + db.listCollections({ name: collectionName }).next(function (err, collection) { + if (err) reject(err); + if (collection) { + resolve(db.collection(collectionName)!); + } else { + reject(`Collection ${collectionName} does not exist!`); + } }); + }); } /** * Checks if id exists in result collection * @param collectionName Name of collection * @param id ID of the document - * @returns True if document ID exists in the given collection + * @returns True if document ID exists in the given collection */ function containsID(collectionName: string, id: string): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - getCollection(collectionName) - .then(async (collection) => { - resolve(await collection.find({ - '_id': id - }).count() > 0); + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + getCollection(collectionName) + .then(async (collection) => { + resolve( + (await collection + .find({ + _id: id, }) - .catch(err => reject(err)); - }); + .count()) > 0, + ); + }) + .catch((err) => reject(err)); + }); } /** @@ -140,33 +136,29 @@ function containsID(collectionName: string, id: string): Promise { * @returns Promise that is resolved when document is added */ function addDocument(collectionName: string, document: GenericObject): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + // get collection + getCollection(collectionName).then(async (collection) => { + // Add the document + collection.insertOne(document, (error) => { + if (error) { + reject(error); + } else { + resolve(); } - // get collection - getCollection(collectionName) - .then(async (collection) => { - // Add the document - collection.insertOne(document, (error) => { - if (error) { - reject(error); - } - else { - resolve(); - } - }); - }); + }); }); + }); } /** @@ -176,28 +168,25 @@ function addDocument(collectionName: string, document: GenericObject): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - // get collection - getCollection(collectionName) - .then(async (collection) => { - // get document - let results = collection.find(query); - let documents = await results.toArray(); - resolve(documents); - }); - }) + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + // get collection + getCollection(collectionName).then(async (collection) => { + // get document + let results = collection.find(query); + let documents = await results.toArray(); + resolve(documents); + }); + }); } /** @@ -205,30 +194,27 @@ function getDocuments(collectionName: string, query: GenericObject): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - getCollection(collectionName) - .then(async (collection) => { - collection.updateOne(query, update, (err) => { - if (err) console.log(err) - }); - resolve(); - }) + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + getCollection(collectionName).then(async (collection) => { + collection.updateOne(query, update, (err) => { + if (err) console.log(err); + }); + resolve(); }); + }); } /** @@ -236,79 +222,72 @@ function updateDocument(collectionName: string, query: GenericObject, update: Ge * @param collectionName Name of collection * @param query Query object * @param update Update object - * @returns + * @returns */ function replaceDocument(collectionName: string, query: GenericObject, update: GenericObject): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - getCollection(collectionName) - .then(async (collection) => { - collection.replaceOne(query, update, (err) => { - if (err) console.log(err) - }); - resolve(); - }) + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + getCollection(collectionName).then(async (collection) => { + collection.replaceOne(query, update, (err) => { + if (err) console.log(err); + }); + resolve(); }); + }); } /** * Deletes a document from a collection * @param collectionName Name of collection * @param query Query object - * @returns + * @returns */ function deleteDocument(collectionName: string, query: GenericObject): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - getCollection(collectionName) - .then(async (collection) => { - await collection.deleteOne(query, (err) => { - if (err) console.log(err); - }); - resolve(); - }) - }) + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + getCollection(collectionName).then(async (collection) => { + await collection.deleteOne(query, (err) => { + if (err) console.log(err); + }); + resolve(); + }); + }); } /** * Deletes multiple documents from a collection * @param collectionName Name of collection * @param query Query object - * @returns + * @returns */ function deleteDocuments(collectionName: string, query: GenericObject): Promise { - return new Promise(async (resolve, reject) => { - await getDB(); - getCollection(collectionName) - .then(async (collection) => { - await collection.deleteMany(query, (err) => { - if (err) console.log(err); - }); - resolve(); - }) - }) + return new Promise(async (resolve, reject) => { + await getDB(); + getCollection(collectionName).then(async (collection) => { + await collection.deleteMany(query, (err) => { + if (err) console.log(err); + }); + resolve(); + }); + }); } /** @@ -318,29 +297,27 @@ function deleteDocuments(collectionName: string, query: GenericObject): Promise< * @returns Cached value */ async function getValue(cache: string, key: string): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - let value = await getDocuments(cache, { _id: key }); - // cache hit - if (value.length > 0) { - resolve(value[0]['value']); - } - // cache miss - else { - resolve(undefined); - } - }) + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + let value = await getDocuments(cache, { _id: key }); + // cache hit + if (value.length > 0) { + resolve(value[0]['value']); + } + // cache miss + else { + resolve(undefined); + } + }); } /** @@ -351,30 +328,41 @@ async function getValue(cache: string, key: string): Promise { * @returns Promise that is resolved when value is cached */ async function setValue(cache: string, key: string, value: any): Promise { - return new Promise(async (resolve, reject) => { - try { - await getDB(); - } - catch (e) { - if (process.env.NODE_ENV == 'production') { - reject(e); - } - else { - resolve(null!); - } - return; - } - // if already in cache, update doc - if (await containsID(cache, key)) { - await replaceDocument(cache, { _id: key }, { value: value }) - } - // if not in cache, add doc - else { - await addDocument(cache, { _id: key, value: value }) - } - resolve(); - }) + return new Promise(async (resolve, reject) => { + try { + await getDB(); + } catch (e) { + if (process.env.NODE_ENV == 'production') { + reject(e); + } else { + resolve(null!); + } + return; + } + // if already in cache, update doc + if (await containsID(cache, key)) { + await replaceDocument(cache, { _id: key }, { value: value }); + } + // if not in cache, add doc + else { + await addDocument(cache, { _id: key, value: value }); + } + resolve(); + }); } - -export { DB_NAME, COLLECTION_NAMES, getCollection, getDB, containsID, addDocument, getDocuments, updateDocument, replaceDocument, deleteDocument, deleteDocuments, setValue, getValue }; +export { + DB_NAME, + COLLECTION_NAMES, + getCollection, + getDB, + containsID, + addDocument, + getDocuments, + updateDocument, + replaceDocument, + deleteDocument, + deleteDocuments, + setValue, + getValue, +}; diff --git a/site/src/App.scss b/site/src/App.scss index 3cfb29a3..3f4380cf 100644 --- a/site/src/App.scss +++ b/site/src/App.scss @@ -1,19 +1,19 @@ .app-body { - display: flex; - height: 92vh; - overflow: hidden; + display: flex; + height: 92vh; + overflow: hidden; } .app-content { - display: flex; - flex-direction: column; - padding-top: 3vh; - padding-left: 3vw; - padding-right: 3vw; - width: 100%; - height: 100%; - overflow-y: auto; - overflow-x: hidden; - background-color: var(--background); - box-sizing: border-box; -} \ No newline at end of file + display: flex; + flex-direction: column; + padding-top: 3vh; + padding-left: 3vw; + padding-right: 3vw; + width: 100%; + height: 100%; + overflow-y: auto; + overflow-x: hidden; + background-color: var(--background); + box-sizing: border-box; +} diff --git a/site/src/component/AppHeader/AppHeader.scss b/site/src/component/AppHeader/AppHeader.scss index 183bf63a..44a09687 100644 --- a/site/src/component/AppHeader/AppHeader.scss +++ b/site/src/component/AppHeader/AppHeader.scss @@ -3,13 +3,13 @@ height: 100%; } - [data-theme='dark'] { .beta-popup .button { background-color: var(--overlay3); } - .beta-popup .button:hover, .beta-popup .button:focus { + .beta-popup .button:hover, + .beta-popup .button:focus { background-color: var(--hover); } diff --git a/site/src/component/Error/Error.scss b/site/src/component/Error/Error.scss index 843575b1..fc740f3c 100644 --- a/site/src/component/Error/Error.scss +++ b/site/src/component/Error/Error.scss @@ -1,20 +1,20 @@ .error { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; - h1 { - font-size: 5em; - } + h1 { + font-size: 5em; + } } @media only screen and (max-width: 600px) { - .error { - img { - width: 100%; - } + .error { + img { + width: 100%; } -} \ No newline at end of file + } +} diff --git a/site/src/component/Footer/Footer.scss b/site/src/component/Footer/Footer.scss index a36399ed..5f7a1bf0 100644 --- a/site/src/component/Footer/Footer.scss +++ b/site/src/component/Footer/Footer.scss @@ -1,37 +1,37 @@ .footer { - // background-color: #f9f9f9; - height: auto; - padding: 1rem 0; - display: flex; - align-items: center; - justify-content: center; + // background-color: #f9f9f9; + height: auto; + padding: 1rem 0; + display: flex; + align-items: center; + justify-content: center; - a { - margin-right: 16px; - color: gray; - font-weight: bold; - font-size: 12px; - } + a { + margin-right: 16px; + color: gray; + font-weight: bold; + font-size: 12px; + } - a:hover { - color: var(--peterportal-primary-color-1); - } + a:hover { + color: var(--peterportal-primary-color-1); + } - .links { - display: flex; - flex-wrap: wrap; - } - - .copyright { - margin-left: auto; + .links { + display: flex; + flex-wrap: wrap; + } + + .copyright { + margin-left: auto; - p { - font-size: 12px; - color: gray; - } + p { + font-size: 12px; + color: gray; + } - a { - margin-right: 0; - } + a { + margin-right: 0; } - } \ No newline at end of file + } +} diff --git a/site/src/component/GradeDist/GradeDist.scss b/site/src/component/GradeDist/GradeDist.scss index 13d6ad44..3fc916f2 100644 --- a/site/src/component/GradeDist/GradeDist.scss +++ b/site/src/component/GradeDist/GradeDist.scss @@ -9,7 +9,7 @@ } #grade-dist-label { - margin: "0"; + margin: '0'; width: 100%; } diff --git a/site/src/component/PrereqTree/PrereqTree.scss b/site/src/component/PrereqTree/PrereqTree.scss index 40702e07..a91bf880 100644 --- a/site/src/component/PrereqTree/PrereqTree.scss +++ b/site/src/component/PrereqTree/PrereqTree.scss @@ -1,194 +1,194 @@ .dependency-list-branch { - margin: auto; + margin: auto; } .prereq { - display: flex; - flex-direction: column; - overflow-x: auto; + display: flex; + flex-direction: column; + overflow-x: auto; } .prereq-clump { - display: flex; - position: relative; - margin-left: 20px; - &::before { - content: ''; - position: absolute; - background: var(--peterportal-mid-gray); - top: 50%; - left: -1.5rem; - width: 0.5rem; - height: 1px; - } + display: flex; + position: relative; + margin-left: 20px; + &::before { + content: ''; + position: absolute; + background: var(--peterportal-mid-gray); + top: 50%; + left: -1.5rem; + width: 0.5rem; + height: 1px; + } } .prereq-branch, .dependency-branch { - position: relative; - display: flex; - justify-content: center; - align-items: center; - padding: 0.125rem 0.25rem; - margin: 0 0.25rem 1px 0.25rem; - border-radius: 0.25rem; - flex: 0 0 auto; - border: 0; + position: relative; + display: flex; + justify-content: center; + align-items: center; + padding: 0.125rem 0.25rem; + margin: 0 0.25rem 1px 0.25rem; + border-radius: 0.25rem; + flex: 0 0 auto; + border: 0; } .dependency-needs { - &::before { - content: ''; - position: absolute; - background: var(--peterportal-mid-gray); - top: 50%; - left: -0.8rem; - width: 0.7rem; - height: 1px; - } - - &::after { - content: ''; - position: absolute; - background: var(--peterportal-mid-gray); - top: 50%; - right: -1rem; - width: 1rem; - height: 1px; - } + &::before { + content: ''; + position: absolute; + background: var(--peterportal-mid-gray); + top: 50%; + left: -0.8rem; + width: 0.7rem; + height: 1px; + } + + &::after { + content: ''; + position: absolute; + background: var(--peterportal-mid-gray); + top: 50%; + right: -1rem; + width: 1rem; + height: 1px; + } } .course-node { - margin: auto 1rem auto 0; + margin: auto 1rem auto 0; } .dependency-node { - position: relative; - display: flex; - width: fit-content; - margin: auto; - margin-right: 0; - - a { - background: blue; - } - - &:first-child:last-child { - &::after { - height: 0 !important; - } - } + position: relative; + display: flex; + width: fit-content; + margin: auto; + margin-right: 0; - &:first-child { - &::after { - width: 1px; - height: 50%; - right: -1rem; - content: ''; - background: var(--peterportal-mid-gray); - position: absolute; - bottom: 0; - top: auto; - } - } + a { + background: blue; + } - &:last-child { - &::after { - width: 1px; - height: 50%; - right: -1rem; - content: ''; - background: var(--peterportal-mid-gray); - position: absolute; - top: 0; - } + &:first-child:last-child { + &::after { + height: 0 !important; } + } + &:first-child { &::after { - width: 1px; - height: 100%; - right: -1rem; - content: ''; - background: var(--peterportal-mid-gray); - position: absolute; - top: 0; + width: 1px; + height: 50%; + right: -1rem; + content: ''; + background: var(--peterportal-mid-gray); + position: absolute; + bottom: 0; + top: auto; } + } - &::before { - content: ''; - position: absolute; - background: var(--peterportal-mid-gray); - top: 50%; - right: -1rem; - width: 1rem; - height: 1px; + &:last-child { + &::after { + width: 1px; + height: 50%; + right: -1rem; + content: ''; + background: var(--peterportal-mid-gray); + position: absolute; + top: 0; } + } + + &::after { + width: 1px; + height: 100%; + right: -1rem; + content: ''; + background: var(--peterportal-mid-gray); + position: absolute; + top: 0; + } + + &::before { + content: ''; + position: absolute; + background: var(--peterportal-mid-gray); + top: 50%; + right: -1rem; + width: 1rem; + height: 1px; + } } .prerequisite-node { - position: relative; - display: flex; - width: fit-content; - - &:first-child:last-child { - &::after { - height: 0 !important; - } - } - - &:first-child { - &::after { - width: 1px; - height: 50%; - left: -1rem; - content: ''; - background: var(--peterportal-mid-gray); - position: absolute; - bottom: 0; - top: auto; - } - } + position: relative; + display: flex; + width: fit-content; - &:last-child { - &::after { - width: 1px; - height: 50%; - left: -1rem; - content: ''; - background: var(--peterportal-mid-gray); - position: absolute; - top: 0; - } + &:first-child:last-child { + &::after { + height: 0 !important; } + } + &:first-child { &::after { - width: 1px; - height: 100%; - left: -1rem; - content: ''; - background: var(--peterportal-mid-gray); - position: absolute; - top: 0; + width: 1px; + height: 50%; + left: -1rem; + content: ''; + background: var(--peterportal-mid-gray); + position: absolute; + bottom: 0; + top: auto; } + } - &::before { - content: ''; - position: absolute; - background: var(--peterportal-mid-gray); - top: 50%; - left: -1rem; - width: 1rem; - height: 1px; + &:last-child { + &::after { + width: 1px; + height: 50%; + left: -1rem; + content: ''; + background: var(--peterportal-mid-gray); + position: absolute; + top: 0; } + } + + &::after { + width: 1px; + height: 100%; + left: -1rem; + content: ''; + background: var(--peterportal-mid-gray); + position: absolute; + top: 0; + } + + &::before { + content: ''; + position: absolute; + background: var(--peterportal-mid-gray); + top: 50%; + left: -1rem; + width: 1rem; + height: 1px; + } } .prereq-text-box { - padding: 1em; - margin-top: 2em; - background-color: var(--overlay2); + padding: 1em; + margin-top: 2em; + background-color: var(--overlay2); } .prereq ul { - margin: 0; - padding: 0; -} \ No newline at end of file + margin: 0; + padding: 0; +} diff --git a/site/src/component/Report/ReportGroup.scss b/site/src/component/Report/ReportGroup.scss index cb3199be..4569d144 100644 --- a/site/src/component/Report/ReportGroup.scss +++ b/site/src/component/Report/ReportGroup.scss @@ -1,48 +1,47 @@ .report-group { - background-color: var(--overlay2); - border-radius: var(--border-radius); - padding: 2rem; - margin-bottom: 3vh; + background-color: var(--overlay2); + border-radius: var(--border-radius); + padding: 2rem; + margin-bottom: 3vh; - label { - font-weight: bold; - } + label { + font-weight: bold; + } } .report-group-identifier { - margin: 0; - // font-weight: bold; - font-size: x-large; - // a { - // color: black; - // } + margin: 0; + // font-weight: bold; + font-size: x-large; + // a { + // color: black; + // } } .report-group-user-display { - font-size: medium; + font-size: medium; } .report-group-content { - margin: 1vh 0; - label { - font-weight: bold; - } - p { - font-style: italic; - margin-left: 1vw; - } + margin: 1vh 0; + label { + font-weight: bold; + } + p { + font-style: italic; + margin-left: 1vw; + } } .report-group-subreports-container { - background-color: var(--overlay3); - border-radius: var(--border-radius); - padding: 1rem; + background-color: var(--overlay3); + border-radius: var(--border-radius); + padding: 1rem; } .report-group-footer { - flex-direction: row; - width: 100%; - margin-top: 15px; - align-items: flex-end; + flex-direction: row; + width: 100%; + margin-top: 15px; + align-items: flex-end; } - diff --git a/site/src/component/Report/Reports.scss b/site/src/component/Report/Reports.scss index adf1babe..7ed9d638 100644 --- a/site/src/component/Report/Reports.scss +++ b/site/src/component/Report/Reports.scss @@ -1,5 +1,5 @@ .reports-container { - padding: 2rem; - background-color: var(--overlay1); - border-radius: var(--border-radius); -} \ No newline at end of file + padding: 2rem; + background-color: var(--overlay1); + border-radius: var(--border-radius); +} diff --git a/site/src/component/Report/SubReport.scss b/site/src/component/Report/SubReport.scss index 8cb151a0..50972a35 100644 --- a/site/src/component/Report/SubReport.scss +++ b/site/src/component/Report/SubReport.scss @@ -1,13 +1,13 @@ .subreport { - border-radius: var(--border-radius); + border-radius: var(--border-radius); } .subreport-content { - label { - font-weight: bold; - } - p { - font-style: italic; - margin-left: 1vw; - } -} \ No newline at end of file + label { + font-weight: bold; + } + p { + font-style: italic; + margin-left: 1vw; + } +} diff --git a/site/src/component/ReportForm/ReportForm.scss b/site/src/component/ReportForm/ReportForm.scss index 14bbcf5e..d39c55d0 100644 --- a/site/src/component/ReportForm/ReportForm.scss +++ b/site/src/component/ReportForm/ReportForm.scss @@ -20,7 +20,7 @@ textarea { color: var(--text); border-radius: var(--border-radius); - border: 2px solid #EAEBF2; + border: 2px solid #eaebf2; padding: 1rem; resize: none; width: 100%; @@ -58,17 +58,17 @@ } .submitted-report-form { - text-align: center; - width: 100%; - i { - color: var(--peterportal-secondary-green); - } - h1 { - margin: 15px 0; - } - p { - font-size: 1.25rem; - } + text-align: center; + width: 100%; + i { + color: var(--peterportal-secondary-green); + } + h1 { + margin: 15px 0; + } + p { + font-size: 1.25rem; + } } @media only screen and (max-width: 400px) { @@ -90,4 +90,4 @@ .report-form { width: 75vw; } -} \ No newline at end of file +} diff --git a/site/src/component/Review/Review.scss b/site/src/component/Review/Review.scss index 26cd5d05..9cec4d73 100644 --- a/site/src/component/Review/Review.scss +++ b/site/src/component/Review/Review.scss @@ -177,7 +177,7 @@ $avatarWidth: 65px; } @media only screen and (max-width: 1300px) and (min-width: 600px) { - .rating{ + .rating { width: 8vh; height: 8vh; } @@ -208,4 +208,4 @@ $avatarWidth: 65px; color: var(--text); } } -} \ No newline at end of file +} diff --git a/site/src/component/ReviewForm/ReviewForm.scss b/site/src/component/ReviewForm/ReviewForm.scss index a049ca90..df9a24bb 100644 --- a/site/src/component/ReviewForm/ReviewForm.scss +++ b/site/src/component/ReviewForm/ReviewForm.scss @@ -1,6 +1,7 @@ [data-theme='dark'] { .review-form { - .form-control, .form-control:focus { + .form-control, + .form-control:focus { background-color: var(--overlay3); } } @@ -41,7 +42,7 @@ } textarea { border-radius: var(--border-radius); - border: 2px solid #EAEBF2; + border: 2px solid #eaebf2; padding: 1rem; resize: none; width: 100%; @@ -140,4 +141,4 @@ .review-form-grade { margin-left: 0; } -} \ No newline at end of file +} diff --git a/site/src/component/SearchHitContainer/SearchHitContainer.scss b/site/src/component/SearchHitContainer/SearchHitContainer.scss index 37d70268..eeb59f5d 100644 --- a/site/src/component/SearchHitContainer/SearchHitContainer.scss +++ b/site/src/component/SearchHitContainer/SearchHitContainer.scss @@ -1,4 +1,4 @@ .search-hit-container { - padding-top: 2vh; - overflow-y: auto; -} \ No newline at end of file + padding-top: 2vh; + overflow-y: auto; +} diff --git a/site/src/component/SearchModule/SearchModule.scss b/site/src/component/SearchModule/SearchModule.scss index deed11d7..130e0dad 100644 --- a/site/src/component/SearchModule/SearchModule.scss +++ b/site/src/component/SearchModule/SearchModule.scss @@ -1,17 +1,17 @@ .search-bar { - border-color: #80bdff; - padding: 2vh 2vh; + border-color: #80bdff; + padding: 2vh 2vh; } [data-theme='dark'] { - .search-bar, - .search-bar:focus, - .search-module .input-group-text { - color: var(--text); - background-color: var(--overlay1); - border-color: var(--overlay2); - } - .search-bar:focus { - border-color: #80bdff; - } -} \ No newline at end of file + .search-bar, + .search-bar:focus, + .search-module .input-group-text { + color: var(--text); + background-color: var(--overlay1); + border-color: var(--overlay2); + } + .search-bar:focus { + border-color: #80bdff; + } +} diff --git a/site/src/component/SearchPopup/SearchPopup.scss b/site/src/component/SearchPopup/SearchPopup.scss index 2aa214b1..82f61777 100644 --- a/site/src/component/SearchPopup/SearchPopup.scss +++ b/site/src/component/SearchPopup/SearchPopup.scss @@ -1,130 +1,131 @@ [data-theme='dark'] { - .search-popup { - .dropdown, .dropdown .menu { - background-color: var(--overlay3); - border-color: var(--overlay2); - } - - .dropdown:hover { - border-color: var(--overlay4); - } - - .ui.dropdown { - .menu>.item.active, - .menu>.item:hover { - background-color: var(--overlay4); - } - } + .search-popup { + .dropdown, + .dropdown .menu { + background-color: var(--overlay3); + border-color: var(--overlay2); } + + .dropdown:hover { + border-color: var(--overlay4); + } + + .ui.dropdown { + .menu > .item.active, + .menu > .item:hover { + background-color: var(--overlay4); + } + } + } } .search-popup-missing { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - width: auto; - height: 100%; - text-align: center; - color: #9c9fac; - font-size: 1.5em; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: auto; + height: 100%; + text-align: center; + color: #9c9fac; + font-size: 1.5em; } .search-popup { - background-color: var(--overlay1); - padding: 3rem; - margin-left: 3vw; - height: 85vh; - overflow-y: auto; - border-radius: var(--border-radius); - max-width: 40vw; + background-color: var(--overlay1); + padding: 3rem; + margin-left: 3vw; + height: 85vh; + overflow-y: auto; + border-radius: var(--border-radius); + max-width: 40vw; } .search-popup-header { - margin-bottom: 3vh; + margin-bottom: 3vh; } .search-popup-id { - margin-bottom: 0.2rem; - font-size: 3rem; - display: flex; - justify-content: space-between; + margin-bottom: 0.2rem; + font-size: 3rem; + display: flex; + justify-content: space-between; } .search-popup-title { - margin: 0; + margin: 0; } .search-popup-more { - background-color: transparent; + background-color: transparent; } .search-popup-block { - background-color: var(--overlay2); - border-radius: var(--border-radius); + background-color: var(--overlay2); + border-radius: var(--border-radius); } .search-popup-infos { - display: flex; - flex-direction: row; - justify-content: space-between; + display: flex; + flex-direction: row; + justify-content: space-between; } .search-popup-info { - display: flex; - flex-direction: column; - padding: 2vh; - width: 45%; + display: flex; + flex-direction: column; + padding: 2vh; + width: 45%; } .search-popup-label { - margin: 2vh 0 1vh 0; + margin: 2vh 0 1vh 0; } .search-popup-carousel { - background-color: var(--overlay2); - height: 100%; - margin: 0 1vw; - padding: 2vh 1vw; + background-color: var(--overlay2); + height: 100%; + margin: 0 1vw; + padding: 2vh 1vw; - p { - font-weight: bold; - } + p { + font-weight: bold; + } - div { - display: flex; - } + div { + display: flex; + } - .search-popup-carousel-score { - font-size: 2em; - } + .search-popup-carousel-score { + font-size: 2em; + } - .search-popup-carousel-max-score { - margin-left: 0.5vw; - display: flex; - align-items: center; - color: var(--peterportal-mid-gray); - } + .search-popup-carousel-max-score { + margin-left: 0.5vw; + display: flex; + align-items: center; + color: var(--peterportal-mid-gray); + } } @media only screen and (max-width: 1300px) { - .search-popup-infos { - flex-direction: column; - } + .search-popup-infos { + flex-direction: column; + } - .search-popup-info:first-child { - margin-bottom: 3vh; - } + .search-popup-info:first-child { + margin-bottom: 3vh; + } - .search-popup-info { - width: 90%; - } + .search-popup-info { + width: 90%; + } - .search-popup-id { - flex-direction: column-reverse; + .search-popup-id { + flex-direction: column-reverse; - a { - margin-left: auto; - } + a { + margin-left: auto; } -} \ No newline at end of file + } +} diff --git a/site/src/component/SideBar/Sidebar.scss b/site/src/component/SideBar/Sidebar.scss index 1af51a5b..e2740d66 100644 --- a/site/src/component/SideBar/Sidebar.scss +++ b/site/src/component/SideBar/Sidebar.scss @@ -77,7 +77,7 @@ } .sidebar-login { - margin-bottom: 5vh; + margin-bottom: 5vh; .sidebar-login-icon { margin-right: 0.4vw; @@ -137,7 +137,7 @@ .sidebar-login { margin-top: -20vh; - margin-bottom: 35vh; + margin-bottom: 35vh; } } .sidebar.mini { @@ -165,4 +165,4 @@ .theme-toggle:hover { cursor: pointer; text-decoration: underline; -} \ No newline at end of file +} diff --git a/site/src/component/SideInfo/SideInfo.scss b/site/src/component/SideInfo/SideInfo.scss index b0b7adf0..8ae04c67 100644 --- a/site/src/component/SideInfo/SideInfo.scss +++ b/site/src/component/SideInfo/SideInfo.scss @@ -1,157 +1,157 @@ .side-info { - width: 40vw; - height: fit-content; - max-height: 85vh; - background-color: var(--overlay1); - border-radius: var(--border-radius); - padding: 3rem; - position: sticky; - top: 0; - overflow-y: auto; + width: 40vw; + height: fit-content; + max-height: 85vh; + background-color: var(--overlay1); + border-radius: var(--border-radius); + padding: 3rem; + position: sticky; + top: 0; + overflow-y: auto; } .side-info-data { - h1, - h2 { - font-weight: bold; - } + h1, + h2 { + font-weight: bold; + } } .side-info-ratings { - margin-top: 3vh; + margin-top: 3vh; - .side-info-buttons { - display: flex; - } + .side-info-buttons { + display: flex; + } - .side-info-buttons > * { - margin-right: 1vw; - } + .side-info-buttons > * { + margin-right: 1vw; + } } .side-info-selected-based { - margin-top: 1vh; - color: grey; + margin-top: 1vh; + color: grey; } .side-info-selected-rating { - display: flex; - justify-content: space-between; - margin: 1vh 0; + display: flex; + justify-content: space-between; + margin: 1vh 0; } .side-info-stat { - padding-bottom: 1rem; - width: 33%; - - .side-info-stat-label { - font-weight: bold; - font-size: 1.25em; - } - - .side-info-stat-value { - font-weight: bold; - line-height: 4rem; - font-size: 4rem; - } + padding-bottom: 1rem; + width: 33%; + + .side-info-stat-label { + font-weight: bold; + font-size: 1.25em; + } + + .side-info-stat-value { + font-weight: bold; + line-height: 4rem; + font-size: 4rem; + } } .side-info-featured { - display: flex; - justify-content: space-between; + display: flex; + justify-content: space-between; } .side-info-feature { - background-color: var(--overlay2); - border-radius: var(--border-radius); - padding: 2rem; - width: 45%; + background-color: var(--overlay2); + border-radius: var(--border-radius); + padding: 2rem; + width: 45%; - .side-info-feature-title { - font-weight: bold; - font-size: 1.25em; - } + .side-info-feature-title { + font-weight: bold; + font-size: 1.25em; + } - .side-info-feature-based { - color: grey; - } + .side-info-feature-based { + color: grey; + } - .side-info-feature-name { - font-weight: bold; - font-size: 2em; - a { - color: var(--text); - } + .side-info-feature-name { + font-weight: bold; + font-size: 2em; + a { + color: var(--text); } + } + + .side-info-feature-stats { + display: flex; + justify-content: space-between; + } + + .side-info-feature-stat { + background-color: var(--overlay3); + border-radius: var(--border-radius); + padding: 0.5rem; + width: 45%; + text-align: center; - .side-info-feature-stats { - display: flex; - justify-content: space-between; + .side-info-feature-stat-label { + color: grey; } - .side-info-feature-stat { - background-color: var(--overlay3); - border-radius: var(--border-radius); - padding: 0.5rem; - width: 45%; - text-align: center; - - .side-info-feature-stat-label { - color: grey; - } - - .side-info-feature-stat-value { - font-size: 2em; - font-weight: bold; - } + .side-info-feature-stat-value { + font-size: 2em; + font-weight: bold; } + } } .side-info-denominator { - color: grey; - font-size: 0.5em; + color: grey; + font-size: 0.5em; } @media only screen and (max-width: 400px) { - .side-info-denominator { - display: none; - } + .side-info-denominator { + display: none; + } } @media only screen and (max-width: 600px) and (min-width: 400px) { - .side-info-denominator { - display: inline; - } + .side-info-denominator { + display: inline; + } } @media only screen and (max-width: 600px) { - .side-info-selected-rating { - flex-direction: column; - } + .side-info-selected-rating { + flex-direction: column; + } - .side-info-stat { - width: 100%; - } + .side-info-stat { + width: 100%; + } - .side-info-featured { - flex-direction: column; + .side-info-featured { + flex-direction: column; - .side-info-feature { - width: 100%; - margin-bottom: 3vh; - } + .side-info-feature { + width: 100%; + margin-bottom: 3vh; } + } } @media only screen and (max-width: 1300px) { - .side-info { - width: 100%; - max-height: fit-content; - } + .side-info { + width: 100%; + max-height: fit-content; + } } @media only screen and (max-width: 1800px) and (min-width: 600px) { - .side-info-denominator { - display: none; - } + .side-info-denominator { + display: none; + } } diff --git a/site/src/component/UserReviews/UserReviews.scss b/site/src/component/UserReviews/UserReviews.scss index b2934175..aa84a6d7 100644 --- a/site/src/component/UserReviews/UserReviews.scss +++ b/site/src/component/UserReviews/UserReviews.scss @@ -1,16 +1,16 @@ .user-reviews-container { - padding: 2rem; - background-color: var(--overlay1); - border-radius: var(--border-radius); + padding: 2rem; + background-color: var(--overlay1); + border-radius: var(--border-radius); } .user-reviews { - border-radius: var(--border-radius); - margin-bottom: 3vh; + border-radius: var(--border-radius); + margin-bottom: 3vh; - .user-reviews-footer { - flex-direction: row; - width: 100%; - align-items: flex-end; - } -} \ No newline at end of file + .user-reviews-footer { + flex-direction: row; + width: 100%; + align-items: flex-end; + } +} diff --git a/site/src/component/Verify/Verify.scss b/site/src/component/Verify/Verify.scss index cde2b20e..59cd56bf 100644 --- a/site/src/component/Verify/Verify.scss +++ b/site/src/component/Verify/Verify.scss @@ -1,16 +1,16 @@ .verify-container { - padding: 2rem; - background-color: var(--overlay1); - border-radius: var(--border-radius); + padding: 2rem; + background-color: var(--overlay1); + border-radius: var(--border-radius); } .verify { - border-radius: var(--border-radius); - margin-bottom: 3vh; + border-radius: var(--border-radius); + margin-bottom: 3vh; - .verify-footer { - flex-direction: row; - width: 100%; - align-items: flex-end; - } -} \ No newline at end of file + .verify-footer { + flex-direction: row; + width: 100%; + align-items: flex-end; + } +} diff --git a/site/src/hooks/firstRenderer.tsx b/site/src/hooks/firstRenderer.tsx index c778541b..78fba2eb 100644 --- a/site/src/hooks/firstRenderer.tsx +++ b/site/src/hooks/firstRenderer.tsx @@ -3,11 +3,11 @@ import { useRef, useEffect } from 'react'; export function useFirstRender() { - const firstRender = useRef(true); + const firstRender = useRef(true); - useEffect(() => { - firstRender.current = false; - }, []); + useEffect(() => { + firstRender.current = false; + }, []); - return firstRender.current; -} \ No newline at end of file + return firstRender.current; +} diff --git a/site/src/pages/CoursePage/CoursePage.scss b/site/src/pages/CoursePage/CoursePage.scss index d677a93b..627ce693 100644 --- a/site/src/pages/CoursePage/CoursePage.scss +++ b/site/src/pages/CoursePage/CoursePage.scss @@ -1,34 +1,34 @@ .course-page { - display: flex; + display: flex; } .course-page-body { - margin-left: 4rem; + margin-left: 4rem; } .course-page-section { - max-width: 42vw; - background-color: var(--overlay1); - border-radius: var(--border-radius); - padding: 3rem; - margin-bottom: 3vh; + max-width: 42vw; + background-color: var(--overlay1); + border-radius: var(--border-radius); + padding: 3rem; + margin-bottom: 3vh; } .twemoji { - width: 3rem; + width: 3rem; } @media only screen and (max-width: 1300px) { - .course-page { - flex-direction: column; - } + .course-page { + flex-direction: column; + } - .course-page-body { - margin-left: 0; - margin-top: 3vh; - } + .course-page-body { + margin-left: 0; + margin-top: 3vh; + } - .course-page-section { - max-width: none; - } -} \ No newline at end of file + .course-page-section { + max-width: none; + } +} diff --git a/site/src/pages/ProfessorPage/ProfessorPage.scss b/site/src/pages/ProfessorPage/ProfessorPage.scss index 786f1c90..df7011ef 100644 --- a/site/src/pages/ProfessorPage/ProfessorPage.scss +++ b/site/src/pages/ProfessorPage/ProfessorPage.scss @@ -1,34 +1,34 @@ .professor-page { - display: flex; + display: flex; } .professor-page-body { - margin-left: 4rem; + margin-left: 4rem; } .professor-page-section { - max-width: 45vw; - background-color: var(--overlay1); - border-radius: var(--border-radius); - padding: 3rem; - margin-bottom: 3vh; + max-width: 45vw; + background-color: var(--overlay1); + border-radius: var(--border-radius); + padding: 3rem; + margin-bottom: 3vh; } .twemoji { - width: 3rem; + width: 3rem; } @media only screen and (max-width: 1300px) { - .professor-page { - flex-direction: column; - } + .professor-page { + flex-direction: column; + } - .professor-page-body { - margin-left: 0; - margin-top: 3vh; - } + .professor-page-body { + margin-left: 0; + margin-top: 3vh; + } - .professor-page-section { - max-width: none; - } -} \ No newline at end of file + .professor-page-section { + max-width: none; + } +} diff --git a/site/src/pages/RoadmapPage/AddCoursePopup.scss b/site/src/pages/RoadmapPage/AddCoursePopup.scss index 84e4540f..14812da3 100644 --- a/site/src/pages/RoadmapPage/AddCoursePopup.scss +++ b/site/src/pages/RoadmapPage/AddCoursePopup.scss @@ -1,4 +1,4 @@ .add-course-form { - border-radius: var(--border-radius); - padding: 2rem; -} \ No newline at end of file + border-radius: var(--border-radius); + padding: 2rem; +} diff --git a/site/src/pages/RoadmapPage/AddYearPopup.scss b/site/src/pages/RoadmapPage/AddYearPopup.scss index 7e555051..0332bbb0 100644 --- a/site/src/pages/RoadmapPage/AddYearPopup.scss +++ b/site/src/pages/RoadmapPage/AddYearPopup.scss @@ -1,6 +1,7 @@ [data-theme='dark'] { .add-year-form { - .form-control, .form-control:focus { + .form-control, + .form-control:focus { background-color: var(--overlay1); } } diff --git a/site/src/pages/RoadmapPage/Course.scss b/site/src/pages/RoadmapPage/Course.scss index 7edb9b7f..8e7fabbf 100644 --- a/site/src/pages/RoadmapPage/Course.scss +++ b/site/src/pages/RoadmapPage/Course.scss @@ -1,5 +1,5 @@ .course { - box-shadow: 0px 0px 4px #2484C6; + box-shadow: 0px 0px 4px #2484c6; background: var(--overlay1); border-radius: 15px; height: auto; @@ -9,7 +9,7 @@ .name { font-weight: bold; - color: #2484C6; + color: #2484c6; font-size: 18px; } @@ -82,6 +82,6 @@ padding-top: 5%; } .popover-detail-prefix { - font-weight: bold; + font-weight: bold; } -} \ No newline at end of file +} diff --git a/site/src/pages/RoadmapPage/Planner.scss b/site/src/pages/RoadmapPage/Planner.scss index e415792d..4a8386aa 100644 --- a/site/src/pages/RoadmapPage/Planner.scss +++ b/site/src/pages/RoadmapPage/Planner.scss @@ -1,3 +1,2 @@ .planner { - -} \ No newline at end of file +} diff --git a/site/src/pages/RoadmapPage/Quarter.scss b/site/src/pages/RoadmapPage/Quarter.scss index a20369a7..f6096e61 100644 --- a/site/src/pages/RoadmapPage/Quarter.scss +++ b/site/src/pages/RoadmapPage/Quarter.scss @@ -3,7 +3,9 @@ color: #eee; } - .quarter-menu-btn:hover, .quarter-menu-btn:focus, .popover-body .quarter-menu-btn:active { + .quarter-menu-btn:hover, + .quarter-menu-btn:focus, + .popover-body .quarter-menu-btn:active { background-color: var(--overlay2); } } @@ -14,7 +16,7 @@ box-shadow: 0px 0px 4px #2484c6; flex: 1 1 30%; height: fit-content; - margin: .75rem; + margin: 0.75rem; .quarter-header { display: flex; @@ -51,6 +53,9 @@ padding: 0; } -.red-menu-btn, .red-menu-btn:hover, .red-menu-btn:focus, .popover-body .quarter-menu-btn.red-menu-btn:active { +.red-menu-btn, +.red-menu-btn:hover, +.red-menu-btn:focus, +.popover-body .quarter-menu-btn.red-menu-btn:active { color: red; -} \ No newline at end of file +} diff --git a/site/src/pages/RoadmapPage/SearchSidebar.scss b/site/src/pages/RoadmapPage/SearchSidebar.scss index f7ee8130..fee7b5c8 100644 --- a/site/src/pages/RoadmapPage/SearchSidebar.scss +++ b/site/src/pages/RoadmapPage/SearchSidebar.scss @@ -37,4 +37,4 @@ .search-sidebar-search-module { margin: 2rem 2rem 0 2rem; -} \ No newline at end of file +} diff --git a/site/src/pages/RoadmapPage/Transfer.scss b/site/src/pages/RoadmapPage/Transfer.scss index eea2e061..b3a712bc 100644 --- a/site/src/pages/RoadmapPage/Transfer.scss +++ b/site/src/pages/RoadmapPage/Transfer.scss @@ -1,19 +1,18 @@ .transfer { - max-height: 75vh; - overflow-y: auto; + max-height: 75vh; + overflow-y: auto; } .list-group { - height: max-content; - overflow-x: scroll; + height: max-content; + overflow-x: scroll; } .transfer .list-group .list-group-item { - min-width: max-content; - background-color: var(--overlay3); + min-width: max-content; + background-color: var(--overlay3); } .entry { - margin-top: 1%; + margin-top: 1%; } - diff --git a/site/src/pages/RoadmapPage/Year.scss b/site/src/pages/RoadmapPage/Year.scss index 59ea5f40..58fb969f 100644 --- a/site/src/pages/RoadmapPage/Year.scss +++ b/site/src/pages/RoadmapPage/Year.scss @@ -6,7 +6,9 @@ } [data-theme='dark'] { - .year-settings-btn:hover, .year-settings-btn:focus, .popover-body .year-settings-btn:active { + .year-settings-btn:hover, + .year-settings-btn:focus, + .popover-body .year-settings-btn:active { background-color: var(--overlay2); } } @@ -43,7 +45,7 @@ border-radius: 10px; box-shadow: 0px 0px 4px #2484c6; flex: 1 1 30%; - margin: .75rem; + margin: 0.75rem; } .year-accordion-title { @@ -139,4 +141,4 @@ .year-accordion-content { flex-direction: column; } -} \ No newline at end of file +} diff --git a/site/src/pages/RoadmapPage/index.scss b/site/src/pages/RoadmapPage/index.scss index e1be90d3..93af9c4e 100644 --- a/site/src/pages/RoadmapPage/index.scss +++ b/site/src/pages/RoadmapPage/index.scss @@ -1,6 +1,6 @@ .roadmap-page { font-family: 'Open Sans', sans-serif; - height: calc(100vh - 4rem); + height: calc(100vh - 4rem); overflow: hidden; display: flex; width: 100%; @@ -31,4 +31,4 @@ width: 100%; margin: 0; } -} \ No newline at end of file +} diff --git a/site/src/pages/SearchPage/HitItem.scss b/site/src/pages/SearchPage/HitItem.scss index af0c766b..ee9cd445 100644 --- a/site/src/pages/SearchPage/HitItem.scss +++ b/site/src/pages/SearchPage/HitItem.scss @@ -1,15 +1,15 @@ .hit-item { - border-radius: var(--border-radius); - background-color: var(--overlay1); - padding: 2vh; - margin-bottom: 2vh; - cursor: pointer; + border-radius: var(--border-radius); + background-color: var(--overlay1); + padding: 2vh; + margin-bottom: 2vh; + cursor: pointer; - a { - color: var(--text); - } + a { + color: var(--text); + } } .course-hit-id { - display: flex; -} \ No newline at end of file + display: flex; +} diff --git a/site/src/pages/SearchPage/SearchPage.scss b/site/src/pages/SearchPage/SearchPage.scss index 05d69782..0cf7bc9f 100644 --- a/site/src/pages/SearchPage/SearchPage.scss +++ b/site/src/pages/SearchPage/SearchPage.scss @@ -7,39 +7,39 @@ // } #content-container { - display: flex; - flex-grow: 1; + display: flex; + flex-grow: 1; - #search-list { - width: 50vw; - display: flex; - flex-direction: column; - height: 85vh; - } + #search-list { + width: 50vw; + display: flex; + flex-direction: column; + height: 85vh; + } - #search-popup { - flex-grow: 1; - height: fit-content; - } + #search-popup { + flex-grow: 1; + height: fit-content; + } - .search-hit-container { - margin-top: 2vh; // use margin instead of padding so the scroll bar isn't offset/above the first hit item - padding-top: 0; + .search-hit-container { + margin-top: 2vh; // use margin instead of padding so the scroll bar isn't offset/above the first hit item + padding-top: 0; - .hit-item:last-child { - margin-bottom: 0; // so scroll bar doesn't extend past the last hit item - } + .hit-item:last-child { + margin-bottom: 0; // so scroll bar doesn't extend past the last hit item } + } } @media only screen and (max-width: 800px) { - #content-container { - #search-list { - width: 100%; - } - - #search-popup { - display: none; - } + #content-container { + #search-list { + width: 100%; + } + + #search-popup { + display: none; } -} \ No newline at end of file + } +} diff --git a/site/src/pages/SearchPage/width.config.scss b/site/src/pages/SearchPage/width.config.scss index 59486c02..bcae1fd9 100644 --- a/site/src/pages/SearchPage/width.config.scss +++ b/site/src/pages/SearchPage/width.config.scss @@ -1,3 +1,3 @@ $content-max-width: 800px; $content-min-width: 800px; -$content-width: 90%; \ No newline at end of file +$content-width: 90%; diff --git a/site/src/store/hooks.ts b/site/src/store/hooks.ts index f36eb5d0..520e84ed 100644 --- a/site/src/store/hooks.ts +++ b/site/src/store/hooks.ts @@ -1,6 +1,6 @@ -import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' -import type { RootState, AppDispatch } from './store' +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; +import type { RootState, AppDispatch } from './store'; // Use throughout your app instead of plain `useDispatch` and `useSelector` -export const useAppDispatch = () => useDispatch() -export const useAppSelector: TypedUseSelectorHook = useSelector \ No newline at end of file +export const useAppDispatch = () => useDispatch(); +export const useAppSelector: TypedUseSelectorHook = useSelector; diff --git a/site/src/store/slices/popupSlice.ts b/site/src/store/slices/popupSlice.ts index 715117d4..928c57bb 100644 --- a/site/src/store/slices/popupSlice.ts +++ b/site/src/store/slices/popupSlice.ts @@ -1,38 +1,38 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import type { RootState } from '../store' +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import type { RootState } from '../store'; import { CourseGQLData, ProfessorGQLData } from '../../types/types'; // Define a type for the slice state interface PopupState { - course: CourseGQLData; - professor: ProfessorGQLData; + course: CourseGQLData; + professor: ProfessorGQLData; } // Define the initial state using that type const initialState: PopupState = { - course: null!, - professor: null! -} + course: null!, + professor: null!, +}; export const reviewSlice = createSlice({ - name: 'popup', - // `createSlice` will infer the state type from the `initialState` argument - initialState, - reducers: { - // Use the PayloadAction type to declare the contents of `action.payload` - setCourse: (state, action: PayloadAction) => { - state.course = action.payload; - }, - setProfessor: (state, action: PayloadAction) => { - state.professor = action.payload; - } + name: 'popup', + // `createSlice` will infer the state type from the `initialState` argument + initialState, + reducers: { + // Use the PayloadAction type to declare the contents of `action.payload` + setCourse: (state, action: PayloadAction) => { + state.course = action.payload; + }, + setProfessor: (state, action: PayloadAction) => { + state.professor = action.payload; }, -}) + }, +}); -export const { setCourse, setProfessor } = reviewSlice.actions +export const { setCourse, setProfessor } = reviewSlice.actions; // Other code such as selectors can use the imported `RootState` type export const selectCourse = (state: RootState) => state.popup.course; export const selectProfessor = (state: RootState) => state.popup.professor; -export default reviewSlice.reducer \ No newline at end of file +export default reviewSlice.reducer; diff --git a/site/src/store/slices/reviewSlice.ts b/site/src/store/slices/reviewSlice.ts index 3854741c..2ecda09d 100644 --- a/site/src/store/slices/reviewSlice.ts +++ b/site/src/store/slices/reviewSlice.ts @@ -1,43 +1,43 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import type { RootState } from '../store' +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import type { RootState } from '../store'; import { ReviewData } from '../../types/types'; // Define a type for the slice state interface ReviewState { - reviews: ReviewData[]; - formOpen: boolean; + reviews: ReviewData[]; + formOpen: boolean; } // Define the initial state using that type const initialState: ReviewState = { - reviews: [], - formOpen: false -} + reviews: [], + formOpen: false, +}; export const reviewSlice = createSlice({ - name: 'review', - // `createSlice` will infer the state type from the `initialState` argument - initialState, - reducers: { - // Use the PayloadAction type to declare the contents of `action.payload` - addReview: (state, action: PayloadAction) => { - state.reviews.push(action.payload); - }, - setReviews: (state, action: PayloadAction) => { - state.reviews = action.payload; - }, - setFormStatus: (state, action: PayloadAction) => { - state.formOpen = action.payload; - }, - toggleFormStatus: (state) => { - state.formOpen = !state.formOpen; - } + name: 'review', + // `createSlice` will infer the state type from the `initialState` argument + initialState, + reducers: { + // Use the PayloadAction type to declare the contents of `action.payload` + addReview: (state, action: PayloadAction) => { + state.reviews.push(action.payload); + }, + setReviews: (state, action: PayloadAction) => { + state.reviews = action.payload; + }, + setFormStatus: (state, action: PayloadAction) => { + state.formOpen = action.payload; + }, + toggleFormStatus: (state) => { + state.formOpen = !state.formOpen; }, -}) + }, +}); -export const { addReview, setReviews, setFormStatus, toggleFormStatus } = reviewSlice.actions +export const { addReview, setReviews, setFormStatus, toggleFormStatus } = reviewSlice.actions; // Other code such as selectors can use the imported `RootState` type export const selectReviews = (state: RootState) => state.review.reviews; -export default reviewSlice.reducer \ No newline at end of file +export default reviewSlice.reducer; diff --git a/site/src/store/slices/uiSlice.ts b/site/src/store/slices/uiSlice.ts index 797a46ae..a5572261 100644 --- a/site/src/store/slices/uiSlice.ts +++ b/site/src/store/slices/uiSlice.ts @@ -1,36 +1,36 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import type { RootState } from '../store' +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import type { RootState } from '../store'; // Define a type for the slice state interface UIState { - sidebarOpen: boolean; - filterOpen: boolean; + sidebarOpen: boolean; + filterOpen: boolean; } // Define the initial state using that type const initialState: UIState = { - sidebarOpen: false, - filterOpen: false -} + sidebarOpen: false, + filterOpen: false, +}; export const reviewSlice = createSlice({ - name: 'ui', - // `createSlice` will infer the state type from the `initialState` argument - initialState, - reducers: { - // Use the PayloadAction type to declare the contents of `action.payload` - setSidebarStatus: (state, action: PayloadAction) => { - state.sidebarOpen = action.payload; - }, - setFilterStatus: (state, action: PayloadAction) => { - state.filterOpen = action.payload; - } + name: 'ui', + // `createSlice` will infer the state type from the `initialState` argument + initialState, + reducers: { + // Use the PayloadAction type to declare the contents of `action.payload` + setSidebarStatus: (state, action: PayloadAction) => { + state.sidebarOpen = action.payload; + }, + setFilterStatus: (state, action: PayloadAction) => { + state.filterOpen = action.payload; }, -}) + }, +}); -export const { setSidebarStatus, setFilterStatus } = reviewSlice.actions +export const { setSidebarStatus, setFilterStatus } = reviewSlice.actions; // Other code such as selectors can use the imported `RootState` type export const selectSidebarOpen = (state: RootState) => state.ui.sidebarOpen; -export default reviewSlice.reducer \ No newline at end of file +export default reviewSlice.reducer; diff --git a/site/src/store/store.ts b/site/src/store/store.ts index 870c140c..6fbde95d 100644 --- a/site/src/store/store.ts +++ b/site/src/store/store.ts @@ -1,4 +1,4 @@ -import { configureStore } from '@reduxjs/toolkit' +import { configureStore } from '@reduxjs/toolkit'; import reviewReducer from './slices/reviewSlice'; import uiReducer from './slices/uiSlice'; import popupReducer from './slices/popupSlice'; @@ -6,16 +6,16 @@ import roadmapReducer from './slices/roadmapSlice'; import searchReducer from './slices/searchSlice'; export const store = configureStore({ - reducer: { - review: reviewReducer, - ui: uiReducer, - popup: popupReducer, - roadmap: roadmapReducer, - search: searchReducer, - } -}) + reducer: { + review: reviewReducer, + ui: uiReducer, + popup: popupReducer, + roadmap: roadmapReducer, + search: searchReducer, + }, +}); // Infer the `RootState` and `AppDispatch` types from the store itself -export type RootState = ReturnType +export type RootState = ReturnType; // Inferred type -export type AppDispatch = typeof store.dispatch \ No newline at end of file +export type AppDispatch = typeof store.dispatch; diff --git a/site/src/style/theme-context.ts b/site/src/style/theme-context.ts index ea6e236d..448ff8a6 100644 --- a/site/src/style/theme-context.ts +++ b/site/src/style/theme-context.ts @@ -1,8 +1,8 @@ -import React from "react"; +import React from 'react'; -const ThemeContext = React.createContext<{ darkMode: boolean, toggleTheme: () => void }>({ - darkMode: false, - toggleTheme: () => {} +const ThemeContext = React.createContext<{ darkMode: boolean; toggleTheme: () => void }>({ + darkMode: false, + toggleTheme: () => {}, }); -export default ThemeContext; \ No newline at end of file +export default ThemeContext; diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 3f755ea0..818159c4 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -8,7 +8,7 @@ --text: #212529; // default bootstrap color --text-dark: #000; --text-light: #495057; - --hover: #CACBCD; // semantic-ui default + --hover: #cacbcd; // semantic-ui default } // dark theme vars @@ -16,14 +16,14 @@ // roughly following: https://m2.material.io/design/color/dark-theme.html [data-theme='dark'] { --background: #121212; - --overlay1: #1E1E1E; + --overlay1: #1e1e1e; --overlay2: #292929; --overlay3: #363636; --overlay4: #404040; --text: #fff; --text-dark: #fff; --text-light: #fff; - --hover: #CACBCD; + --hover: #cacbcd; color-scheme: dark; } @@ -37,12 +37,13 @@ color: var(--text-dark); } - [data-theme='dark'] { .list-group-item, .modal-content, - .dropdown-menu, .dropdown-item, - .form-control, .form-control:focus { + .dropdown-menu, + .dropdown-item, + .form-control, + .form-control:focus { color: var(--text); background-color: var(--overlay2); } @@ -61,23 +62,24 @@ background-color: var(--overlay1); color: var(--text); } -.bs-popover-top>.arrow::after { +.bs-popover-top > .arrow::after { border-top-color: var(--overlay1); } -.bs-popover-bottom>.arrow::after { +.bs-popover-bottom > .arrow::after { border-bottom-color: var(--overlay1); } -.bs-popover-left>.arrow::after { +.bs-popover-left > .arrow::after { border-left-color: var(--overlay1); } -.bs-popover-right>.arrow::after { +.bs-popover-right > .arrow::after { border-right-color: var(--overlay1); } // end bootstrap overwrites // general semantic-ui overwrites. bg/border color may need to be customized per component [data-theme='dark'] { - .ui, .ui.popup:before { + .ui, + .ui.popup:before { color: var(--text); background-color: var(--overlay2); border-color: var(--overlay1); @@ -87,14 +89,15 @@ box-shadow: -1px -1px 0 0 var(--overlay1); } - .ui.dropdown, .ui.dropdown .menu { + .ui.dropdown, + .ui.dropdown .menu { color: var(--text); background-color: var(--overlay2); border-color: var(--overlay1); } - .ui.selection.visible.dropdown>.text:not(.default), - .ui.dropdown .menu>.item { + .ui.selection.visible.dropdown > .text:not(.default), + .ui.dropdown .menu > .item { color: var(--text); } @@ -102,8 +105,8 @@ border-color: var(--overlay3); } .ui.dropdown { - .menu>.item:hover, - .menu>.item.active{ + .menu > .item:hover, + .menu > .item.active { background-color: var(--overlay3); } } diff --git a/sst.config.ts b/sst.config.ts index ecf5c492..9c0aeaba 100644 --- a/sst.config.ts +++ b/sst.config.ts @@ -1,24 +1,25 @@ -import { FrontendStack } from "./stacks/frontend"; -import { BackendStack } from "./stacks/backend"; +import { FrontendStack } from './stacks/frontend'; +import { BackendStack } from './stacks/backend'; import dotenv from 'dotenv-flow'; -import { App } from "sst/constructs"; +import { App } from 'sst/constructs'; dotenv.config(); export default { - config(_input) { - return { - name: "peterportal-client", - region: "us-west-1", - }; - }, - stacks(app: App) { - if (app.stage !== "prod") { - app.setDefaultRemovalPolicy("destroy"); - } - - app.stack(FrontendStack, {stackName: `${app.name}-${app.stage}-frontend`} ) - .stack(BackendStack, {stackName: `${app.name}-${app.stage}-backend`}); + config(_input) { + return { + name: 'peterportal-client', + region: 'us-west-1', + }; + }, + stacks(app: App) { + if (app.stage !== 'prod') { + app.setDefaultRemovalPolicy('destroy'); } -}; \ No newline at end of file + + app + .stack(FrontendStack, { stackName: `${app.name}-${app.stage}-frontend` }) + .stack(BackendStack, { stackName: `${app.name}-${app.stage}-backend` }); + }, +}; From ee18c00b8fba1f04030a4bc2339300c8b0485fb8 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Sun, 21 Jan 2024 02:12:38 -0800 Subject: [PATCH 33/41] Remove unneeded width.config.scss --- site/src/pages/SearchPage/SearchPage.scss | 8 -------- site/src/pages/SearchPage/width.config.scss | 3 --- 2 files changed, 11 deletions(-) delete mode 100644 site/src/pages/SearchPage/width.config.scss diff --git a/site/src/pages/SearchPage/SearchPage.scss b/site/src/pages/SearchPage/SearchPage.scss index 0cf7bc9f..714dcff2 100644 --- a/site/src/pages/SearchPage/SearchPage.scss +++ b/site/src/pages/SearchPage/SearchPage.scss @@ -1,11 +1,3 @@ -@import './width.config.scss'; - -// index -// .sidebar-container { -// position: sticky; -// top: 4rem; -// } - #content-container { display: flex; flex-grow: 1; diff --git a/site/src/pages/SearchPage/width.config.scss b/site/src/pages/SearchPage/width.config.scss deleted file mode 100644 index bcae1fd9..00000000 --- a/site/src/pages/SearchPage/width.config.scss +++ /dev/null @@ -1,3 +0,0 @@ -$content-max-width: 800px; -$content-min-width: 800px; -$content-width: 90%; From 4bc5ea78c4e3d9048a61bb126c4cef8ce36f95b4 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Tue, 23 Jan 2024 17:24:19 -0800 Subject: [PATCH 34/41] Address comments for /users/preferences endpoint --- api/src/controllers/users.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/api/src/controllers/users.ts b/api/src/controllers/users.ts index 1dc6a35e..81392e39 100644 --- a/api/src/controllers/users.ts +++ b/api/src/controllers/users.ts @@ -4,7 +4,7 @@ import express, { Request, Response } from 'express'; import passport from 'passport'; -import { COLLECTION_NAMES, addDocument, getCollection, getDocuments, updateDocument } from '../helpers/mongo'; +import { COLLECTION_NAMES, addDocument, containsID, getDocuments, updateDocument } from '../helpers/mongo'; import { SESSION_LENGTH } from '../config/constants'; let router = express.Router(); @@ -16,21 +16,20 @@ router.get('/', function (req, res, next) { res.json(req.session); }); -router.get('/preferences', (req, res) => { +router.get('/preferences', async (req, res) => { if (!req.session.passport) { res.json({ error: 'Must be logged in to get preferences.' }); return; } const userID = req.session.passport.user.id; + const preferences = await getDocuments(COLLECTION_NAMES.PREFERENCES, { _id: userID }); - getDocuments(COLLECTION_NAMES.PREFERENCES, { _id: userID }).then((preferences) => { - if (preferences.length > 0) { - res.json(preferences[0]); - } else { - res.json({ error: 'No preferences found' }); - } - }); + if (preferences.length > 0) { + res.json(preferences[0]); + } else { + res.json({ error: 'No preferences found' }); + } }); interface UserPreferences { @@ -46,8 +45,7 @@ router.post('/preferences', async (req, res) => { const userID = req.session.passport.user.id; // make user's preference doc if it doesn't exist - const preferencesCollection = await getCollection(COLLECTION_NAMES.PREFERENCES); - if ((await preferencesCollection.find({ _id: userID }).count()) == 0) { + if (!(await containsID(COLLECTION_NAMES.PREFERENCES, userID))) { await addDocument(COLLECTION_NAMES.PREFERENCES, { _id: userID }); } From 4f987811ca286343c8a5869ccafd3dfb75cefa36 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Wed, 24 Jan 2024 00:44:52 -0800 Subject: [PATCH 35/41] refactor: function for default dark mode value. remove test stuff --- site/src/App.tsx | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/site/src/App.tsx b/site/src/App.tsx index 8187bf84..5ca55e21 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -21,15 +21,20 @@ import ThemeContext from './style/theme-context'; import axios from 'axios'; import { useCookies } from 'react-cookie'; +function getDefaultDarkModeValue() { + switch (localStorage.getItem('theme')) { + case 'dark': + return true; + case 'light': + return false; + default: + return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; + } +} + export default function App() { // default darkMode to local or system preferences - const [darkMode, setDarkMode] = useState( - localStorage.getItem('theme') === 'dark' - ? true - : localStorage.getItem('theme') === 'light' - ? false - : window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches, - ); + const [darkMode, setDarkMode] = useState(getDefaultDarkModeValue()); const [cookies] = useCookies(['user']); useEffect(() => { @@ -41,16 +46,6 @@ export default function App() { setDarkMode(true); } else if (theme === 'light') { setDarkMode(false); - } else { - // not defined or set to use local/system prefs - setDarkMode( - localStorage.getItem('theme') === 'dark' - ? true - : localStorage.getItem('theme') === 'light' - ? false - : window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches, - ); - setDarkMode(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches); } }); } @@ -59,7 +54,7 @@ export default function App() { useEffect(() => { document.querySelector('body')!.setAttribute('data-theme', darkMode ? 'dark' : 'light'); if (cookies.user) { - axios.post('/api/users/preferences', { theme: darkMode ? 'dark' : 'light', bs: '123', hello: 'world' }); + axios.post('/api/users/preferences', { theme: darkMode ? 'dark' : 'light' }); } else { localStorage.setItem('theme', darkMode ? 'dark' : 'light'); } From 0c63c43fa649517e708921473aee74edd13220d2 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Wed, 24 Jan 2024 12:34:00 -0800 Subject: [PATCH 36/41] add future support for setting to system theme --- api/src/controllers/users.ts | 2 +- site/src/App.tsx | 74 ++++++++++++++++---------- site/src/component/SideBar/SideBar.tsx | 4 +- site/src/style/theme-context.ts | 11 +++- 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/api/src/controllers/users.ts b/api/src/controllers/users.ts index 81392e39..0de7b1c0 100644 --- a/api/src/controllers/users.ts +++ b/api/src/controllers/users.ts @@ -33,7 +33,7 @@ router.get('/preferences', async (req, res) => { }); interface UserPreferences { - theme?: string; + theme?: 'light' | 'dark' | 'system'; } router.post('/preferences', async (req, res) => { diff --git a/site/src/App.tsx b/site/src/App.tsx index 5ca55e21..f39d962d 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import 'semantic-ui-css/semantic.min.css'; import 'bootstrap/dist/css/bootstrap.min.css'; @@ -17,56 +17,72 @@ import AdminPage from './pages/AdminPage'; import ReviewsPage from './pages/ReviewsPage'; import SideBar from './component/SideBar/SideBar'; -import ThemeContext from './style/theme-context'; +import ThemeContext, { Theme } from './style/theme-context'; import axios from 'axios'; import { useCookies } from 'react-cookie'; -function getDefaultDarkModeValue() { - switch (localStorage.getItem('theme')) { - case 'dark': - return true; - case 'light': - return false; - default: - return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; - } +function isSystemDark() { + return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; } export default function App() { // default darkMode to local or system preferences - const [darkMode, setDarkMode] = useState(getDefaultDarkModeValue()); + const [usingSystemTheme, setUsingSystemTheme] = useState( + localStorage.getItem('theme') === 'system' || !localStorage.getItem('theme'), + ); + const [darkMode, setDarkMode] = useState( + usingSystemTheme ? isSystemDark() : localStorage.getItem('theme') === 'dark', + ); const [cookies] = useCookies(['user']); + /** + * Sets the theme state + * @param theme + */ + const setThemeState = useCallback((theme: Theme) => { + if (theme === 'system') { + setDarkMode(isSystemDark()); + setUsingSystemTheme(true); + } else { + setDarkMode(theme === 'dark'); + setUsingSystemTheme(false); + } + }, []); + + /** + * Sets the theme state and saves the users theme preference. + * Saves to account if logged in, local storage if not + * @param theme + */ + const setTheme = (theme: Theme) => { + setThemeState(theme); + if (cookies.user) { + axios.post('/api/users/preferences', { theme }); + } else { + localStorage.setItem('theme', theme); + } + }; + useEffect(() => { // if logged in, load user prefs (theme) from mongo if (cookies.user) { axios.get('/api/users/preferences').then((res) => { - const { theme } = res.data; - if (theme === 'dark') { - setDarkMode(true); - } else if (theme === 'light') { - setDarkMode(false); + const { theme }: { theme?: Theme } = res.data; + if (theme) { + setThemeState(theme); } }); } - }, [cookies.user]); + }, [cookies.user, setThemeState]); useEffect(() => { + // Theme styling is controlled by data-theme attribute on body being set to light or dark document.querySelector('body')!.setAttribute('data-theme', darkMode ? 'dark' : 'light'); - if (cookies.user) { - axios.post('/api/users/preferences', { theme: darkMode ? 'dark' : 'light' }); - } else { - localStorage.setItem('theme', darkMode ? 'dark' : 'light'); - } - }, [cookies.user, darkMode]); - - const toggleTheme = () => { - setDarkMode(!darkMode); - }; + }, [darkMode]); return ( - +
    diff --git a/site/src/component/SideBar/SideBar.tsx b/site/src/component/SideBar/SideBar.tsx index 166346d1..3897d487 100644 --- a/site/src/component/SideBar/SideBar.tsx +++ b/site/src/component/SideBar/SideBar.tsx @@ -19,7 +19,7 @@ const SideBar = () => { const [name, setName] = useState(''); const [picture, setPicture] = useState(''); const [isAdmin, setIsAdmin] = useState(false); - const { darkMode, toggleTheme } = useContext(ThemeContext); + const { darkMode, setTheme } = useContext(ThemeContext); const isLoggedIn = cookies.user !== undefined; @@ -89,7 +89,7 @@ const SideBar = () => { )} {showSidebar && (
  • - + setTheme(darkMode ? 'light' : 'dark')}>
    diff --git a/site/src/style/theme-context.ts b/site/src/style/theme-context.ts index 448ff8a6..73347ce1 100644 --- a/site/src/style/theme-context.ts +++ b/site/src/style/theme-context.ts @@ -1,8 +1,15 @@ import React from 'react'; -const ThemeContext = React.createContext<{ darkMode: boolean; toggleTheme: () => void }>({ +export type Theme = 'dark' | 'light' | 'system'; + +const ThemeContext = React.createContext<{ + darkMode: boolean; + usingSystemTheme: boolean; + setTheme: (theme: Theme) => void; +}>({ darkMode: false, - toggleTheme: () => {}, + usingSystemTheme: false, + setTheme: () => {}, }); export default ThemeContext; From a850e3fe74ea799b9e8a689cec3de66450a34dcf Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Wed, 24 Jan 2024 13:21:09 -0800 Subject: [PATCH 37/41] Fix border colors and year name bg --- site/src/component/ReviewForm/ReviewForm.scss | 3 +++ site/src/pages/RoadmapPage/AddYearPopup.tsx | 4 ++-- site/src/pages/RoadmapPage/Transfer.scss | 8 ++++++++ site/src/pages/RoadmapPage/Transfer.tsx | 4 ++-- site/src/pages/RoadmapPage/Year.scss | 7 +++++++ site/src/pages/RoadmapPage/Year.tsx | 2 +- site/src/style/theme.scss | 7 ++++++- 7 files changed, 29 insertions(+), 6 deletions(-) diff --git a/site/src/component/ReviewForm/ReviewForm.scss b/site/src/component/ReviewForm/ReviewForm.scss index df9a24bb..6905566f 100644 --- a/site/src/component/ReviewForm/ReviewForm.scss +++ b/site/src/component/ReviewForm/ReviewForm.scss @@ -4,6 +4,9 @@ .form-control:focus { background-color: var(--overlay3); } + .form-control { + border-color: var(--overlay4); + } } } diff --git a/site/src/pages/RoadmapPage/AddYearPopup.tsx b/site/src/pages/RoadmapPage/AddYearPopup.tsx index 2a90f960..13a5b2aa 100644 --- a/site/src/pages/RoadmapPage/AddYearPopup.tsx +++ b/site/src/pages/RoadmapPage/AddYearPopup.tsx @@ -36,8 +36,8 @@ const AddYearPopup: FC = ({ placeholderName, placeholderYear - - + + Name = ({ missingPrereqNames }) => { return ( - + Transfer Credits @@ -107,7 +107,7 @@ const Transfer: FC = ({ missingPrereqNames }) => { - + diff --git a/site/src/pages/RoadmapPage/Year.scss b/site/src/pages/RoadmapPage/Year.scss index 58fb969f..effb8e88 100644 --- a/site/src/pages/RoadmapPage/Year.scss +++ b/site/src/pages/RoadmapPage/Year.scss @@ -11,6 +11,13 @@ .popover-body .year-settings-btn:active { background-color: var(--overlay2); } + + .edit-year-form { + .form-control, + .form-control:focus { + background-color: var(--overlay1); + } + } } .year { diff --git a/site/src/pages/RoadmapPage/Year.tsx b/site/src/pages/RoadmapPage/Year.tsx index 2ea07212..9e86f21f 100644 --- a/site/src/pages/RoadmapPage/Year.tsx +++ b/site/src/pages/RoadmapPage/Year.tsx @@ -220,7 +220,7 @@ const Year: FC = ({ yearIndex, data }) => { -
    + Name Date: Wed, 24 Jan 2024 13:32:03 -0800 Subject: [PATCH 38/41] Dark theme for toggles --- site/src/component/Review/Review.scss | 1 - site/src/style/theme.scss | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/site/src/component/Review/Review.scss b/site/src/component/Review/Review.scss index 9cec4d73..4e57264a 100644 --- a/site/src/component/Review/Review.scss +++ b/site/src/component/Review/Review.scss @@ -1,4 +1,3 @@ -$avatarWidth: 65px; .subreview { background-color: var(--overlay2); border-radius: var(--border-radius); diff --git a/site/src/style/theme.scss b/site/src/style/theme.scss index 51c4ebb3..79597f08 100644 --- a/site/src/style/theme.scss +++ b/site/src/style/theme.scss @@ -53,6 +53,10 @@ border-color: var(--overlay3); } + .custom-control-label::before { + background-color: var(--overlay3); + } + .dropdown-item:hover { background-color: var(--overlay3); } From 62dc70c84eaddca016e5257889365aa196c841b8 Mon Sep 17 00:00:00 2001 From: Jacob Sommer Date: Wed, 24 Jan 2024 13:40:58 -0800 Subject: [PATCH 39/41] Recaptcha dark theme patch --- site/src/component/ReviewForm/ReviewForm.scss | 8 ++++++++ site/src/component/ReviewForm/ReviewForm.tsx | 14 ++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/site/src/component/ReviewForm/ReviewForm.scss b/site/src/component/ReviewForm/ReviewForm.scss index 6905566f..eb7136b7 100644 --- a/site/src/component/ReviewForm/ReviewForm.scss +++ b/site/src/component/ReviewForm/ReviewForm.scss @@ -8,6 +8,14 @@ border-color: var(--overlay4); } } + + // monkey patch recaptcha dark theme bug (crop out white borders) + .g-recaptcha { + overflow: hidden; + width: 302px; + height: 76px; + border-radius: 4px; + } } .review-form { diff --git a/site/src/component/ReviewForm/ReviewForm.tsx b/site/src/component/ReviewForm/ReviewForm.tsx index f58bdbe1..2a9f6966 100644 --- a/site/src/component/ReviewForm/ReviewForm.tsx +++ b/site/src/component/ReviewForm/ReviewForm.tsx @@ -451,12 +451,14 @@ const ReviewForm: FC = (props) => { - setCaptchaToken(token ?? '')} - /> +
    + setCaptchaToken(token ?? '')} + /> +