From 8b7393023323b6c52aae0264af98ff3a9db1380d Mon Sep 17 00:00:00 2001 From: danieldeng2 <danieldeng223@gmail.com> Date: Wed, 12 Aug 2020 00:35:13 +0100 Subject: [PATCH] Add select all logic to both quick access and folders --- .../src/components/atoms/FileCard/index.tsx | 14 +- .../atoms/FileCard/style.module.scss | 6 +- .../atoms/FolderCard/style.module.scss | 6 +- .../molecules/QuickAccess/index.tsx | 143 ++++++++++++++---- .../molecules/ResourceFolders/index.tsx | 26 +++- .../molecules/ResourceSectionHeader/index.tsx | 40 +++-- 6 files changed, 172 insertions(+), 63 deletions(-) diff --git a/frontend/src/components/atoms/FileCard/index.tsx b/frontend/src/components/atoms/FileCard/index.tsx index 8eb6924f3..1835a9930 100644 --- a/frontend/src/components/atoms/FileCard/index.tsx +++ b/frontend/src/components/atoms/FileCard/index.tsx @@ -7,27 +7,29 @@ import graphIllustration from "assets/images/graph-illustration.svg"; import Badge from "react-bootstrap/Badge"; import Card from "react-bootstrap/Card"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faFile } from "@fortawesome/free-solid-svg-icons"; +import { IconDefinition } from "@fortawesome/free-solid-svg-icons"; export interface FileCardProps { title: string; type: string; - tags: string[]; - id: number; + tags: string[]; + icon: IconDefinition; + onIconClick: (event: React.MouseEvent) => void; } const FileCard: React.FC<FileCardProps> = ({ title, type, - tags, - id, + tags, + icon, + onIconClick, }: FileCardProps) => { return ( <Card className={styles.quickViewCard}> <Card.Img variant="top" src={graphIllustration} /> <Card.Body> <Card.Title>{title}</Card.Title> - <FontAwesomeIcon style={{ fontSize: "1.125rem" }} icon={faFile} /> + <FontAwesomeIcon style={{ fontSize: "1.125rem" }} icon={icon} onClick={onIconClick}/> </Card.Body> <Card.Footer> { diff --git a/frontend/src/components/atoms/FileCard/style.module.scss b/frontend/src/components/atoms/FileCard/style.module.scss index 4c3395e6c..dc20d13cf 100644 --- a/frontend/src/components/atoms/FileCard/style.module.scss +++ b/frontend/src/components/atoms/FileCard/style.module.scss @@ -8,9 +8,9 @@ margin-bottom: 10px; } -.quickViewCard:hover { - transform: scale(1.03); -} +// .quickViewCard:hover { +// transform: scale(1.03); +// } .quickViewCard :global(.card-body) { padding: 0.5rem; diff --git a/frontend/src/components/atoms/FolderCard/style.module.scss b/frontend/src/components/atoms/FolderCard/style.module.scss index 7b3d07224..eb6316295 100644 --- a/frontend/src/components/atoms/FolderCard/style.module.scss +++ b/frontend/src/components/atoms/FolderCard/style.module.scss @@ -6,9 +6,9 @@ margin-top: 0.67rem; } -.folderCard:hover { - transform: scale(1.03); -} +// .folderCard:hover { +// transform: scale(1.03); +// } .folderCard :global(.card-body) { display: flex; diff --git a/frontend/src/components/molecules/QuickAccess/index.tsx b/frontend/src/components/molecules/QuickAccess/index.tsx index f0739ff84..23900dba5 100644 --- a/frontend/src/components/molecules/QuickAccess/index.tsx +++ b/frontend/src/components/molecules/QuickAccess/index.tsx @@ -6,6 +6,9 @@ import Row from "react-bootstrap/esm/Row"; import Col from "react-bootstrap/esm/Col"; import ResourceSectionHeader from "../ResourceSectionHeader"; import FileCard from "components/atoms/FileCard"; +import { faSquare, faCheckSquare } from "@fortawesome/free-regular-svg-icons"; +import { faFile } from "@fortawesome/free-solid-svg-icons"; + export interface QuickAccessProps { quickAccessItems: { title: string; @@ -15,37 +18,113 @@ export interface QuickAccessProps { }[]; } -const QuickAccess: React.FC<QuickAccessProps> = ({ - quickAccessItems, -}: QuickAccessProps) => { - return ( - <> - <ResourceSectionHeader heading="Quick Access" /> - - <Row - className={classNames( - "d-flex", - "flex-row", - "flex-nowrap", - styles.quickAccessRow - )} - > - {quickAccessItems.map(({ title, type, tags, id }) => ( - <Col - xs={7} - sm={5} - md={5} - lg={4} - xl={3} - key={id} - style={{ marginBottom: ".5rem" }} - > - <FileCard title={title} type={type} tags={tags} id={id} /> - </Col> - ))} - </Row> - </> - ); -}; +type idBooleanMap = { [key: number]: boolean }; +interface MyState { + isSelected: idBooleanMap; +} + +class QuickAccess extends React.Component<QuickAccessProps, MyState> { + constructor(props: QuickAccessProps) { + super(props); + let isSelected: idBooleanMap = []; + this.state = { isSelected }; + } + + componentDidMount() { + let isSelected: idBooleanMap = []; + this.props.quickAccessItems.forEach(({ id }: { id: number }) => { + isSelected[id] = false; + }); + this.setState({ isSelected }); + } + + isAnySelected(): boolean { + let items = this.props.quickAccessItems; + let isSelected = this.state.isSelected; + for (let item in items) { + if (isSelected[items[item].id]) { + return true; + } + } + return false; + } + + isAllSelected(): boolean { + let items = this.props.quickAccessItems; + let isSelected = this.state.isSelected; + for (let item in items) { + if (!isSelected[items[item].id]) { + return false; + } + } + return true; + } + + handleIconClick(id: number) { + let isSelected = JSON.parse(JSON.stringify(this.state.isSelected)); + isSelected[id] = !isSelected[id]; + this.setState({ isSelected }); + } + + handleSelectAllClick() { + let items = this.props.quickAccessItems; + let isSelected = JSON.parse(JSON.stringify(this.state.isSelected)); + let setValue = !this.isAllSelected(); + for (let item in items) { + isSelected[items[item].id] = setValue; + } + this.setState({ isSelected }); + } + + render() { + return ( + <> + <ResourceSectionHeader + heading="Quick Access" + showDownload={this.isAnySelected()} + onSelectAllClick={() => this.handleSelectAllClick()} + selectAllIcon={this.isAllSelected() ? faCheckSquare : faSquare} + /> + + <Row + className={classNames( + "d-flex", + "flex-row", + "flex-nowrap", + styles.quickAccessRow + )} + > + {this.props.quickAccessItems.map(({ title, type, tags, id }) => ( + <Col + xs={7} + sm={5} + md={5} + lg={4} + xl={3} + key={id} + style={{ marginBottom: ".5rem" }} + > + <FileCard + title={title} + type={type} + tags={tags} + icon={ + this.isAnySelected() + ? this.state.isSelected[id] + ? faCheckSquare + : faSquare + : faFile + } + onIconClick={() => { + this.handleIconClick(id); + }} + /> + </Col> + ))} + </Row> + </> + ); + } +} export default QuickAccess; diff --git a/frontend/src/components/molecules/ResourceFolders/index.tsx b/frontend/src/components/molecules/ResourceFolders/index.tsx index 5ca493d02..28de847f1 100644 --- a/frontend/src/components/molecules/ResourceFolders/index.tsx +++ b/frontend/src/components/molecules/ResourceFolders/index.tsx @@ -3,13 +3,8 @@ import Row from "react-bootstrap/esm/Row"; import Col from "react-bootstrap/esm/Col"; import ResourceSectionHeader from "../ResourceSectionHeader"; import FolderCard from "components/atoms/FolderCard"; -import { - faSquare, - faCheckSquare, -} from "@fortawesome/free-regular-svg-icons"; -import { - faFolder -} from "@fortawesome/free-solid-svg-icons"; +import { faSquare, faCheckSquare } from "@fortawesome/free-regular-svg-icons"; +import { faFolder } from "@fortawesome/free-solid-svg-icons"; export interface ResourceFoldersProps { folderItems: { title: string; @@ -65,10 +60,25 @@ class ResourceFolders extends React.Component<ResourceFoldersProps, MyState> { this.setState({ isSelected }); } + handleSelectAllClick() { + let items = this.props.folderItems; + let isSelected = JSON.parse(JSON.stringify(this.state.isSelected)); + let setValue = !this.isAllSelected(); + for (let item in items) { + isSelected[items[item].id] = setValue; + } + this.setState({ isSelected }); + } + render() { return ( <> - <ResourceSectionHeader heading="Folders" /> + <ResourceSectionHeader + heading="Folders" + showDownload={this.isAnySelected()} + onSelectAllClick={() => this.handleSelectAllClick()} + selectAllIcon={this.isAllSelected() ? faCheckSquare : faSquare} + /> <Row style={{ marginTop: "10px" }}> {this.props.folderItems.map(({ title, id }) => ( diff --git a/frontend/src/components/molecules/ResourceSectionHeader/index.tsx b/frontend/src/components/molecules/ResourceSectionHeader/index.tsx index 1f772ff7c..e0a0774f2 100644 --- a/frontend/src/components/molecules/ResourceSectionHeader/index.tsx +++ b/frontend/src/components/molecules/ResourceSectionHeader/index.tsx @@ -3,26 +3,44 @@ import styles from "./style.module.scss"; import Button from "react-bootstrap/Button"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faDownload, -} from "@fortawesome/free-solid-svg-icons"; -import { faSquare , faCheckSquare} from "@fortawesome/free-regular-svg-icons"; +import { faDownload, IconDefinition } from "@fortawesome/free-solid-svg-icons"; export interface SectionHeaderProps { heading: string; + selectAllIcon: IconDefinition; + showDownload: boolean; + onSelectAllClick: (event: React.MouseEvent) => void; } -const ResourceSectionHeader: React.FC<SectionHeaderProps> = ({heading}: SectionHeaderProps) => { +const ResourceSectionHeader: React.FC<SectionHeaderProps> = ({ + heading, + onSelectAllClick, + showDownload, + selectAllIcon, +}: SectionHeaderProps) => { return ( <> <div className={styles.sectionHeaderContainer}> - <span className={styles.sectionHeader}>{heading}</span> + <span className={styles.sectionHeader} onClick={onSelectAllClick}> + {heading} + </span> <div className={styles.sectionHeaderButtonGroup}> - <Button className={styles.sectionHeaderButton}> - <FontAwesomeIcon className={styles.buttonIcon} icon={faDownload} /> - </Button> - <Button className={styles.sectionHeaderButton}> - <FontAwesomeIcon className={styles.buttonIcon} icon={faSquare} /> + {showDownload ? ( + <Button className={styles.sectionHeaderButton}> + <FontAwesomeIcon + className={styles.buttonIcon} + icon={faDownload} + /> + </Button> + ) : null} + <Button + className={styles.sectionHeaderButton} + onClick={onSelectAllClick} + > + <FontAwesomeIcon + className={styles.buttonIcon} + icon={selectAllIcon} + /> </Button> </div> </div> -- GitLab