diff --git a/package.json b/package.json index b9865e394911d59d2897172ee1c9fcb73499b67a..8ec8a46fd52790580ae8d735528a98fec5e3e9c4 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "react-router-dom": "^5.2.0", "react-scripts": "3.4.1", "react-transition-group": "^4.4.1", + "react-use-localstorage": "^3.5.3", "types": "^0.1.1", "typescript": "~3.7.2" }, diff --git a/public/index.html b/public/index.html index dd99758118c907b49512ad510a4c311233e60e2e..e85b7012e1b603c150e0a373b423528bbe2ff44b 100644 --- a/public/index.html +++ b/public/index.html @@ -41,12 +41,5 @@ To create a production bundle, use `npm run build` or `yarn build`. --> <script src="https://cdnjs.cloudflare.com/ajax/libs/holder/2.9.7/holder.js"></script> - <script> - /* functions to set user settings in console*/ - function setInterfaceSize(size) { - document.documentElement.style.fontSize = `${size}%`; - localStorage.setItem("interfaceSize", size); - } - </script> </body> </html> diff --git a/src/components/App.scss b/src/components/App.scss index 4ea60895db385dd84b75c0014b54de324b26932b..bdb3a88b8c63f5c5dcbe37ebadb1c44f0a15f29f 100644 --- a/src/components/App.scss +++ b/src/components/App.scss @@ -58,3 +58,7 @@ code { border-color: #fff; color: #000; } + +.modal-backdrop{ + z-index: 9000; +} diff --git a/src/components/App.tsx b/src/components/App.tsx index bc57898940b8482e2423086ca14e540d15368ad3..0e0acc9353356dfaac5e2529e69335fae6f96387 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -11,24 +11,30 @@ import { import StandardView from "./pages/StandardView"; import { Switch, Route } from "react-router-dom"; import SignIn from "./pages/SignIn"; +import SettingsModal from "./pages/SettingsModal"; type AppState = { toggledLeft: boolean; toggledRight: boolean; + showSettings: boolean; + fileView: string; }; class App extends React.Component<{}, AppState> { width = window.innerWidth; constructor(props: {}) { super(props); - this.state = { toggledLeft: false, toggledRight: false }; + this.state = { + toggledLeft: false, + toggledRight: false, + showSettings: false, + fileView: localStorage.getItem("fileView") || "card", + }; } componentDidMount() { - let interfaceSize = localStorage.getItem("interfaceSize"); - if (interfaceSize) { - document.documentElement.style.fontSize = `${interfaceSize}%`; - } + document.documentElement.style.fontSize = `${localStorage.getItem("interfaceSize") || "100"}%`; + window.addEventListener("resize", () => { if (window.innerWidth !== this.width) { @@ -73,7 +79,12 @@ class App extends React.Component<{}, AppState> { toggledRight: true, }); } - } + } + + setFileView(view: string){ + this.setState({fileView: view}); + localStorage.setItem("fileView", view); + } render() { const horizontalBarPages = [ @@ -85,6 +96,14 @@ class App extends React.Component<{}, AppState> { return ( <> + <SettingsModal + show={this.state.showSettings} + onHide={() => this.setState({ showSettings: false })} + fileView={this.state.fileView} + onCardViewClick={() => this.setFileView("card")} + onListViewClick={() => this.setFileView("list")} + /> + <Switch> <Route path="/signin"> <SignIn /> @@ -104,13 +123,14 @@ class App extends React.Component<{}, AppState> { /> <StandardView - pages={horizontalBarPages} + onSettingsClick={() => this.setState({ showSettings: true })} toggledLeft={this.state.toggledLeft} toggledRight={this.state.toggledRight} onOverlayClick={(e) => { e.preventDefault(); this.setState({ toggledLeft: false, toggledRight: false }); - }} + }} + fileView={this.state.fileView} /> <BottomBar pages={horizontalBarPages} /> diff --git a/src/components/organisms/RightBar/index.tsx b/src/components/organisms/RightBar/index.tsx index 4f5b2c11d7e3e6bd87d6b20f99d89aacad7595ca..180b897595050075dd34d5dc8c21c082e332a6a7 100644 --- a/src/components/organisms/RightBar/index.tsx +++ b/src/components/organisms/RightBar/index.tsx @@ -3,14 +3,19 @@ import styles from "./style.module.scss"; import CalendarGroup from "components/molecules/CalendarGroup"; import SideBarTabGroup from "components/molecules/SideBarTabGroup"; import { faCog, faSignOutAlt } from "@fortawesome/free-solid-svg-icons"; + export interface RightBarState { date: Date; } -class RightBar extends React.Component<{}, RightBarState> { +export interface RightBarProps { + onSettingsClick: (event: React.MouseEvent) => void; +} + +class RightBar extends React.Component<RightBarProps, RightBarState> { private timerID: number = 0; - constructor(props: {}) { + constructor(props: RightBarProps) { super(props); this.state = { date: new Date() }; } @@ -33,7 +38,8 @@ class RightBar extends React.Component<{}, RightBarState> { let buttons = [ { title: "Settings", - icon: faCog, + icon: faCog, + onClick: this.props.onSettingsClick, }, { title: "Sign Out", diff --git a/src/components/pages/ModuleResources/components/TopSection/index.tsx b/src/components/pages/ModuleResources/components/TopSection/index.tsx deleted file mode 100644 index 0282349055f615112d21e8617bed8396a684d609..0000000000000000000000000000000000000000 --- a/src/components/pages/ModuleResources/components/TopSection/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from "react"; -import MyBreadcrumbs from "components/atoms/MyBreadcrumbs"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import Button from "react-bootstrap/Button"; -import styles from "./style.module.scss"; -import { faBorderAll, faList } from "@fortawesome/free-solid-svg-icons"; - -export interface TopSectionProps { - onViewButtonClick: (event: React.MouseEvent) => void; - currentView: string; - scope: string; -} - -const TopSection: React.FC<TopSectionProps> = ({ - onViewButtonClick, - currentView, - scope, -}) => { - return ( - <div - style={{ - display: "flex", - justifyContent: "space-between", - alignItems: "center", - marginTop: scope === "" ? "-0.375rem" : "0", - marginBottom: scope === "" ? "-0.375rem" : "0", - }} - > - <MyBreadcrumbs /> - - {scope === "" ? ( - <Button - className={styles.viewToggleButton} - onClick={onViewButtonClick} - variant="secondary" - > - <FontAwesomeIcon - icon={currentView === "folder" ? faBorderAll : faList} - /> - </Button> - ) : null} - </div> - ); -}; - -export default TopSection; diff --git a/src/components/pages/ModuleResources/components/TopSection/style.module.scss b/src/components/pages/ModuleResources/components/TopSection/style.module.scss deleted file mode 100644 index 0ced3aed00314801f8bd08ea3617f88a34eaf062..0000000000000000000000000000000000000000 --- a/src/components/pages/ModuleResources/components/TopSection/style.module.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import "assets/scss/custom"; - -.viewToggleButton { - background-color: $white !important; - // color: $gray-500 !important; - color: $gray-700 !important; - border-width: 0px !important; - justify-content: space-between !important; - height: 2.25rem !important; - box-shadow: none !important; - border-radius: .5rem; - margin-bottom: 1rem; - font-size: 1.05rem; - padding-top: 0; - padding-bottom: 0; -} - -.viewToggleButton:hover{ - background-color: $gray-100 !important; - color: $gray-700 !important; -} - -.buttonIcon { - margin-top: 0.22rem; -} \ No newline at end of file diff --git a/src/components/pages/ModuleResources/index.tsx b/src/components/pages/ModuleResources/index.tsx index ba28834997c24d5c1e4be84dfa71941e7da38592..f3ecef8bd41e485128e62e191a0c9657c0b8a8d3 100644 --- a/src/components/pages/ModuleResources/index.tsx +++ b/src/components/pages/ModuleResources/index.tsx @@ -7,7 +7,7 @@ import QuickAccessView from "./components/QuickAccessView"; import CurrentDirectoryView from "./components/CurrentDirectoryView"; import FoldersView from "./components/FoldersView"; import ListView from "./components/ListView"; -import TopSection from "./components/TopSection"; +import MyBreadcrumbs from "components/atoms/MyBreadcrumbs"; export interface Resource { title: string; @@ -20,13 +20,13 @@ export interface Resource { export interface ResourcesProps { year: string; moduleID: string; - scope?: string; + scope?: string; + view: string; } export interface ResourceState { error: any; isLoaded: Boolean; - view: string; resources: Resource[]; searchText: string; } @@ -41,7 +41,6 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { this.state = { error: null, isLoaded: false, - view: "folder", resources: [], searchText: "" }; @@ -178,13 +177,6 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { return null; } - toggleView() { - if (this.state.view === "folder") { - this.setState({ view: "list" }); - } else { - this.setState({ view: "folder" }); - } - } render() { let scope = this.props.scope || ""; @@ -197,8 +189,8 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { })); const view = () => { - switch (this.state.view) { - case "folder": + switch (this.props.view) { + case "card": return ( <> <FoldersView @@ -245,11 +237,7 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { }; return ( <> - <TopSection - onViewButtonClick={() => this.toggleView()} - currentView={this.state.view} - scope={scope} - /> + <MyBreadcrumbs /> <SearchBox searchText={this.state.searchText} onSearchTextChange={text => this.setState({ searchText: text })} diff --git a/src/components/pages/SettingsModal/index.tsx b/src/components/pages/SettingsModal/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..02201b95397f2750df39878fa189ded805c76f22 --- /dev/null +++ b/src/components/pages/SettingsModal/index.tsx @@ -0,0 +1,85 @@ +import React from "react"; +import Modal from "react-bootstrap/Modal"; +import Col from "react-bootstrap/Col"; +import Form from "react-bootstrap/Form"; +import Row from "react-bootstrap/Row"; +import ButtonGroup from "react-bootstrap/ButtonGroup"; +import Button from "react-bootstrap/Button"; +import useLocalStorage from "react-use-localstorage"; +import styles from "./style.module.scss"; +interface Props { + show: boolean; + onHide: any; + fileView: string; + onCardViewClick: (event: React.MouseEvent) => void; + onListViewClick: (event: React.MouseEvent) => void; +} + +const SettingsModal: React.FC<Props> = ({ + show, + onHide, + fileView, + onCardViewClick, + onListViewClick, +}) => { + const [interfaceSize, setInterfaceSize] = useLocalStorage( + "interfaceSize", + "100" + ); + + return ( + <Modal + style={{ zIndex: "10000" }} + dialogClassName={styles.modal} + show={show} + onHide={onHide} + centered + > + <Modal.Header closeButton> + <Modal.Title>Settings</Modal.Title> + </Modal.Header> + <Modal.Body style={{ minHeight: "60vh" }}> + <h5>Interface</h5> + + <Form> + <Form.Group as={Row}> + <Form.Label column xs="9" sm="10"> + Size + </Form.Label> + <Col xs="3" sm="2"> + <Form.Control + value={interfaceSize} + onChange={(e) => setInterfaceSize(e.target.value)} + onBlur={() => + (document.documentElement.style.fontSize = `${interfaceSize}%`) + } + /> + </Col> + </Form.Group> + + <Form.Group style={{ alignItems: "center" }}> + <Form.Label>File View</Form.Label> + <ButtonGroup style={{ float: "right" }}> + <Button + active={fileView === "card"} + variant="secondary" + onClick={onCardViewClick} + > + Card + </Button> + <Button + active={fileView === "list"} + variant="secondary" + onClick={onListViewClick} + > + List + </Button> + </ButtonGroup> + </Form.Group> + </Form> + </Modal.Body> + </Modal> + ); +}; + +export default SettingsModal; diff --git a/src/components/pages/SettingsModal/style.module.scss b/src/components/pages/SettingsModal/style.module.scss new file mode 100644 index 0000000000000000000000000000000000000000..89bd0266ca2a0231743e35a1aed0537fcbaec301 --- /dev/null +++ b/src/components/pages/SettingsModal/style.module.scss @@ -0,0 +1,11 @@ +@import "assets/scss/custom"; + +@media (min-width: 62rem) { + .modal { + width: 50%; + height: 70%; + max-width: none!important; + max-height: none!important; + + } +} \ No newline at end of file diff --git a/src/components/pages/StandardView/index.tsx b/src/components/pages/StandardView/index.tsx index 40c8cea46afafe295eb8202a92e5e54b560bed66..d69c8b49e3f6c922d51bad930fcb55ed17c0ab81 100644 --- a/src/components/pages/StandardView/index.tsx +++ b/src/components/pages/StandardView/index.tsx @@ -22,19 +22,19 @@ import ExamGrading from "../Exams/Grading"; import ExamPastPapers from "../Exams/PastPapers"; interface StandardViewProps { - pages: { - name: string; - path: string; - }[]; toggledLeft: boolean; - toggledRight: boolean; - onOverlayClick: (event: React.MouseEvent<HTMLElement>) => void; + toggledRight: boolean; + fileView: string; + onOverlayClick: (event: React.MouseEvent<HTMLElement>) => void; + onSettingsClick: (event: React.MouseEvent) => void; } const StandardView: React.FC<StandardViewProps> = ({ toggledLeft, toggledRight, - onOverlayClick, + onOverlayClick, + onSettingsClick, + fileView, }: StandardViewProps) => { const [modulesFilter, setModulesFilter] = useState("In Progress"); @@ -88,7 +88,8 @@ const StandardView: React.FC<StandardViewProps> = ({ <ModuleResources year="2021" moduleID={props.match.params.id} - scope={props.match.params.scope} + scope={props.match.params.scope} + view={fileView} /> )} /> @@ -132,7 +133,7 @@ const StandardView: React.FC<StandardViewProps> = ({ <Route path="/" render={() => <Redirect to="/dashboard" />} /> </Switch> </Container> - <RightBar /> + <RightBar onSettingsClick={onSettingsClick} /> </div> ); }; diff --git a/yarn.lock b/yarn.lock index b1bda88aa8b3837e8abc0165738e85a0d675527a..3b13ecfdf7eb857c2fb2fc7a898f26f2ecf6f4e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9252,6 +9252,11 @@ react-transition-group@^4.4.1: loose-envify "^1.4.0" prop-types "^15.6.2" +react-use-localstorage@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/react-use-localstorage/-/react-use-localstorage-3.5.3.tgz#c4bcc097859a2d2879e969f0a57b16345905df82" + integrity sha512-1oNvJmo72G4v5P9ytJZZTb6ywD3UzWBiainTtfbNlb+U08hc+SOD5HqgiLTKUF0MxGcIR9JSnZGmBttNLXaQYA== + react@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"