From a53f2c4087f354c8293fab64fcee5d1b00997755 Mon Sep 17 00:00:00 2001
From: Wilson Chua <wwc4618@ic.ac.uk>
Date: Sat, 22 Aug 2020 00:27:10 +0800
Subject: [PATCH] ModuleResources List view: Convert section download button to
 select section checkbox

---
 src/assets/scss/global.scss                   | 48 +++++++++++++++++
 .../molecules/CategoryHeader/index.tsx        | 34 ++++++------
 .../CategoryHeader/style.module.scss          | 48 +----------------
 .../molecules/CategoryList/index.tsx          |  6 +--
 .../SectionHeader/style.module.scss           | 52 +------------------
 .../molecules/SelectionView/index.tsx         |  2 +
 .../ModuleResources/components/ListView.tsx   | 28 ++++++++--
 7 files changed, 98 insertions(+), 120 deletions(-)

diff --git a/src/assets/scss/global.scss b/src/assets/scss/global.scss
index 2f9b6ca2b..575583219 100644
--- a/src/assets/scss/global.scss
+++ b/src/assets/scss/global.scss
@@ -20,4 +20,52 @@ $teal-tag-background: transparentize($teal-100, 0.5);
 .tagTeal {
   color: $teal-700;
   background: $teal-tag-background;
+}
+
+// Section header with checkbox settings
+.sectionHeaderContainer {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 1.875rem;
+  align-items: center;
+}
+
+.sectionHeader {
+  font-weight: 500;
+  font-size: 20px;
+  text-transform: uppercase;
+}
+
+.sectionHeaderButton {
+  background-color: $white;
+  color: $gray-500;
+  border-width: 0px;
+  border-radius: 8px;
+  margin-left: 20px;
+  justify-content: space-between;
+  height: 2.25rem;
+  transition: 0.2s background-color;
+  -webkit-transition: 0.2s background-color;
+  -moz-transition: 0.2s background-color;
+  font-size: 1.05rem;
+}
+
+.buttonIcon {
+  margin-top: 0.22rem;
+}
+
+.sectionHeaderButton:global(.active),
+.sectionHeaderButton:active {
+  background: $gray-400 !important;
+  font-weight: 500;
+  text-align: left;
+  border-width: 0rem;
+  height: 2.25rem;
+  line-height: 1.375rem;
+}
+
+.sectionHeaderButton:hover, .sectionHeaderButton:focus {
+  background-color: $gray-200;
+	color: $gray-700 !important;
+	box-shadow: none !important;
 }
\ No newline at end of file
diff --git a/src/components/molecules/CategoryHeader/index.tsx b/src/components/molecules/CategoryHeader/index.tsx
index 25082f656..8aa7ac14d 100644
--- a/src/components/molecules/CategoryHeader/index.tsx
+++ b/src/components/molecules/CategoryHeader/index.tsx
@@ -3,16 +3,20 @@ 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 { IconDefinition } from "@fortawesome/free-solid-svg-icons";
 
 export interface CategoryHeaderProps {
   heading: string;
-	onDownloadClick: (event: React.MouseEvent) => void;
+  onSelectAllClick: (event: React.MouseEvent) => void;
+  selectAllIcon: IconDefinition;
+  checkBoxColor: string;
 }
 
 const CategoryHeader: React.FC<CategoryHeaderProps> = ({
   heading,
-  onDownloadClick,
+  onSelectAllClick,
+  selectAllIcon,
+  checkBoxColor
 }: CategoryHeaderProps) => {
   return (
     <>
@@ -21,19 +25,17 @@ const CategoryHeader: React.FC<CategoryHeaderProps> = ({
           {heading}
         </span>
         <div className={styles.sectionHeaderButtonGroup}>
-            <span id="download-button">
-              <Button
-								variant="secondary" 
-                className={styles.sectionHeaderButton}
-                onClick={onDownloadClick}
-              >
-                <FontAwesomeIcon
-                  className={styles.buttonIcon}
-                  icon={faDownload}
-                />
-                Download Section
-              </Button>
-            </span>
+          <Button
+            style={{ color: checkBoxColor }}
+            className={styles.sectionHeaderButton}
+						onClick={onSelectAllClick}
+						variant="secondary"
+          >
+            <FontAwesomeIcon
+              className={styles.buttonIcon}
+              icon={selectAllIcon}
+            />
+          </Button>
         </div>
       </div>
     </>
diff --git a/src/components/molecules/CategoryHeader/style.module.scss b/src/components/molecules/CategoryHeader/style.module.scss
index 359988885..e2a1338b5 100644
--- a/src/components/molecules/CategoryHeader/style.module.scss
+++ b/src/components/molecules/CategoryHeader/style.module.scss
@@ -1,48 +1,2 @@
 @import "assets/scss/custom";
-
-.sectionHeaderContainer {
-  display: flex;
-  justify-content: space-between;
-  margin-top: 1.875rem;  
-  align-items: center;
-}
-
-.sectionHeader {
-  font-size: 20px;
-  text-transform: uppercase;
-}
-
-.sectionHeaderButton {
-  background-color: $white;
-  color: $gray-500;
-  border-width: 0px;
-  border-radius: 8px;
-  margin-left: 20px;
-  justify-content: space-between;
-  height: 2.25rem;
-  transition: 0.2s background-color;
-  -webkit-transition: 0.2s background-color;
-  -moz-transition: 0.2s background-color;
-  font-size: 1.05rem;
-}
-
-.buttonIcon {
-  margin-top: 0.22rem;
-  margin-right: 0.22rem;
-}
-
-.sectionHeaderButton:global(.active),
-.sectionHeaderButton:active {
-  background: $gray-400 !important;
-  font-weight: 500;
-  text-align: left;
-  border-width: 0rem;
-  height: 2.25rem;
-  line-height: 1.375rem;
-}
-
-.sectionHeaderButton:hover, .sectionHeaderButton:focus {
-  background-color: $gray-200;
-	color: $gray-700 !important;
-	box-shadow: none !important;
-}
+@import "assets/scss/global";
diff --git a/src/components/molecules/CategoryList/index.tsx b/src/components/molecules/CategoryList/index.tsx
index f74bd0675..7d431b8ff 100644
--- a/src/components/molecules/CategoryList/index.tsx
+++ b/src/components/molecules/CategoryList/index.tsx
@@ -43,7 +43,7 @@ const CategoryList: React.FC<{ select: SelectionProps }> = ({
 
         return (
           <Row
-          style={{ marginTop: "10px", marginLeft: "-10px", marginRight: "-10px", cursor: "pointer" }}
+          style={{ marginTop: "10px", marginLeft: "0px", marginRight: "0px", cursor: "pointer" }}
           onClick={() => select.handleCardClick(id)}
           onMouseOver={() => select.handleMouseOver(id)}
           onMouseOut={() => select.handleMouseOut(id)}
@@ -62,9 +62,9 @@ const CategoryList: React.FC<{ select: SelectionProps }> = ({
                 </Badge>
               ))}
             </Col>
-            <Col md="auto">
+            <Col md="auto" className="px-0">
               <FontAwesomeIcon
-                style={{ fontSize: "1.125rem" }}
+                style={{ fontSize: "1.125rem", marginRight: "0.5rem" }}
                 icon={icon}
                 onClick={(e) => {
                   e.stopPropagation();
diff --git a/src/components/molecules/SelectionView/components/SectionHeader/style.module.scss b/src/components/molecules/SelectionView/components/SectionHeader/style.module.scss
index c74607afb..9fee92a78 100644
--- a/src/components/molecules/SelectionView/components/SectionHeader/style.module.scss
+++ b/src/components/molecules/SelectionView/components/SectionHeader/style.module.scss
@@ -1,55 +1,5 @@
 @import "assets/scss/custom";
-
-.sectionHeaderContainer {
-  display: flex;
-  justify-content: space-between;
-  margin-top: 1.875rem;  
-  align-items: center;
-}
-
-.sectionHeader {
-  font-weight: 500;
-	font-size: 20px;
-	cursor: pointer;
-}
-
-.sectionHeaderButton {
-  background-color: $white;
-  color: $gray-500;
-  border-width: 0px;
-  border-radius: 8px;
-  margin-left: 20px;
-  justify-content: space-between;
-  height: 2.25rem;
-  transition: 0.2s background-color;
-  -webkit-transition: 0.2s background-color;
-  -moz-transition: 0.2s background-color;
-  font-size: 1.05rem;
-}
-
-.buttonIcon {
-  margin-top: 0.22rem;
-}
-
-.buttonCheckbox :global(.form-check-input) {
-  margin: 0px; 
-}
-
-.sectionHeaderButton:global(.active),
-.sectionHeaderButton:active {
-  background: $gray-400 !important;
-  font-weight: 500;
-  text-align: left;
-  border-width: 0rem;
-  height: 2.25rem;
-  line-height: 1.375rem;
-}
-
-.sectionHeaderButton:hover, .sectionHeaderButton:focus {
-  background-color: $gray-200;
-	color: $gray-700 !important;
-	box-shadow: none !important;
-}
+@import "assets/scss/global";
 
 .alert-enter {
   opacity: 0;
diff --git a/src/components/molecules/SelectionView/index.tsx b/src/components/molecules/SelectionView/index.tsx
index ffdda456e..b920facb1 100644
--- a/src/components/molecules/SelectionView/index.tsx
+++ b/src/components/molecules/SelectionView/index.tsx
@@ -15,6 +15,7 @@ type idBooleanMap = { [key: number]: boolean };
 export interface SelectionProps {
   selectionItems: SelectionItem[];
   state: MyState;
+  setIsSelected: (selection: idBooleanMap) => void;
   isAnySelected: () => boolean;
   handleCardClick: (id: number) => void;
   handleIconClick: (id: number) => void;
@@ -126,6 +127,7 @@ class SelectionView extends React.Component<MyProps, MyState> {
     let selection: SelectionProps = {
       selectionItems: this.props.selectionItems,
       state: this.state,
+      setIsSelected: (selection) => this.setState({ isSelected: selection }),
       isAnySelected: () => this.isAnySelected(),
       handleCardClick: (id: number) => this.handleCardClick(id),
       handleIconClick: (id: number) => this.handleIconClick(id),
diff --git a/src/components/pages/ModuleResources/components/ListView.tsx b/src/components/pages/ModuleResources/components/ListView.tsx
index 34e2db1b5..8ac1e2167 100644
--- a/src/components/pages/ModuleResources/components/ListView.tsx
+++ b/src/components/pages/ModuleResources/components/ListView.tsx
@@ -5,6 +5,7 @@ import SelectionView, {
 } from "components/molecules/SelectionView";
 import CategoryList from "components/molecules/CategoryList";
 import CategoryHeader from "components/molecules/CategoryHeader";
+import { faSquare, faCheckSquare } from "@fortawesome/free-regular-svg-icons";
 
 export interface ListViewProps {
   folders: Folder[];
@@ -20,8 +21,7 @@ const ListView: React.FC<ListViewProps> = ({
   folders,
   resources,
   searchText,
-	onDownloadClick,
-	onSectionDownloadClick,
+  onDownloadClick,
   onItemClick,
   includeInSearchResult
 }) => {
@@ -44,14 +44,36 @@ const ListView: React.FC<ListViewProps> = ({
 					let categorySelect : SelectionProps = {
 						selectionItems: select.selectionItems.filter(res => res.folder === title),
 						state: select.state,
+						setIsSelected: select.setIsSelected,
 						isAnySelected: select.isAnySelected,
 						handleCardClick: select.handleCardClick,
 						handleIconClick: select.handleIconClick,
 						handleMouseOver: select.handleMouseOver,
 						handleMouseOut: select.handleMouseOut
 					}
+
+				  function isAllSelected() : boolean {
+						let isSelected = categorySelect.state.isSelected;
+						return categorySelect.selectionItems.every(item => isSelected[item.id]);
+					}
+
+					function onSelectAllClick() {
+						let setValue = !isAllSelected();
+						let isSelected = JSON.parse(JSON.stringify(select.state.isSelected));
+						let items = categorySelect.selectionItems;
+						for (let item in items) {
+							isSelected[items[item].id] = setValue;
+						}
+						select.setIsSelected(isSelected);
+					}
+
 					return (<>
-						<CategoryHeader heading={title} onDownloadClick={() => onSectionDownloadClick(title)}/>
+						<CategoryHeader
+							heading={title}
+						  onSelectAllClick={onSelectAllClick}
+							selectAllIcon={isAllSelected() ? faCheckSquare : faSquare}
+							checkBoxColor={select.isAnySelected() ? "#495057" : "#e9ecef"}
+						/>
 						<CategoryList select={categorySelect} />
 					</>)
 				})}
-- 
GitLab