From b38a3a22009ed951db6e9566724c7b0b1fe8b0da Mon Sep 17 00:00:00 2001 From: danieldeng2 <danieldeng223@gmail.com> Date: Wed, 19 Aug 2020 22:53:06 +0100 Subject: [PATCH] Add download and open functionality back to resource files --- .../molecules/CurrentDirectoryView/index.tsx | 222 ---------------- .../CurrentDirectoryView/style.module.scss | 5 - .../molecules/QuickAccessView/index.tsx | 238 ------------------ .../QuickAccessView/style.module.scss | 34 --- .../molecules/ResourcesFolderView/index.tsx | 153 ----------- .../ResourcesFolderView/style.module.scss | 1 - .../molecules/SelectionView/index.tsx | 21 +- .../pages/ModuleResources/index.tsx | 88 ++++++- 8 files changed, 96 insertions(+), 666 deletions(-) delete mode 100644 src/components/molecules/CurrentDirectoryView/index.tsx delete mode 100644 src/components/molecules/CurrentDirectoryView/style.module.scss delete mode 100644 src/components/molecules/QuickAccessView/index.tsx delete mode 100644 src/components/molecules/QuickAccessView/style.module.scss delete mode 100644 src/components/molecules/ResourcesFolderView/index.tsx delete mode 100644 src/components/molecules/ResourcesFolderView/style.module.scss diff --git a/src/components/molecules/CurrentDirectoryView/index.tsx b/src/components/molecules/CurrentDirectoryView/index.tsx deleted file mode 100644 index bd5696bb7..000000000 --- a/src/components/molecules/CurrentDirectoryView/index.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import React from "react"; -import Row from "react-bootstrap/esm/Row"; -import Col from "react-bootstrap/esm/Col"; -import ResourceSectionHeader from "../ResourceSectionHeader"; -import { api, methods } from "../../../constants/routes"; -import { request } from "../../../utils/api"; -import { faSquare, faCheckSquare } from "@fortawesome/free-regular-svg-icons"; -import { faFileAlt, faFileVideo, faFilePdf, IconDefinition } from "@fortawesome/free-solid-svg-icons"; -import FileCard from "components/atoms/FileCard"; - -// TODO: Refactor out duplication with QuickAccessView -export interface CurrentDirectoryViewProps { - documentItems: { - title: string; - type: string; - tags: string[]; - id: number; - }[]; - moduleCode?: string; -} - -type idBooleanMap = { [key: number]: boolean }; -interface MyState { - isSelected: idBooleanMap; - isHoveringOver: idBooleanMap; -} - -class CurrentDirectoryView extends React.Component<CurrentDirectoryViewProps, MyState> { - constructor(props: CurrentDirectoryViewProps) { - super(props); - this.state = { isSelected: [], isHoveringOver: []}; - } - - componentDidMount() { - let isSelected: idBooleanMap = []; - this.props.documentItems.forEach(({ id }: { id: number }) => { - isSelected[id] = false; - }); - this.setState({ isSelected }); - } - - isAnySelected(): boolean { - let items = this.props.documentItems; - 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.documentItems; - 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)); - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isSelected[id] = !isSelected[id]; - isHoveringOver[id] = false; - this.setState({ isSelected, isHoveringOver }); - } - - handleDownloadClick() { - const onSuccess = (filename: string, data: any) => { - data.blob().then((blob: any) => { - let url = URL.createObjectURL(blob); - let a = document.createElement("a"); - a.href = url; - a.download = filename; - a.click(); - a.remove(); - }); - }; - // Partial application utility - const downloadFilename = (filename: string) => { - return (data: any) => { - return onSuccess(filename, data); - }; - }; - const onFailure = (error: { text: () => Promise<any> }) => { - error.text().then((errorText) => { - console.log(errorText); - }); - }; - - let indices : number[] = []; - for (let key in this.state.isSelected) { - if (this.state.isSelected[key]) { - indices.push(parseInt(key)); - } - } - - if (indices.length === 1) { - // Only one file to download, call single file endpoint - let filename = this.props.documentItems.filter(document => document.id === indices[0])[0].title; - request(api.MATERIALS_RESOURCES_FILE(indices[0]), methods.GET, downloadFilename(filename), onFailure); - } else { - // Multiple files to download, call zipped selection endpoint - request(api.MATERIALS_ZIPPED_SELECTION, methods.GET, downloadFilename("materials.zip"), onFailure, { - ids: indices, - course: this.props.moduleCode, - }); - } - } - - handleSelectAllClick() { - let items = this.props.documentItems; - 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}); - } - - handleCardClick(id: number) { - const onSuccess = (data: any) => { - data.blob().then((blob: any) => { - let url = URL.createObjectURL(blob); - let a = document.createElement("a"); - a.target = "_blank"; - a.href = url; - a.click(); - a.remove(); - }); - }; - const onFailure = (error: { text: () => Promise<any> }) => { - error.text().then((errorText) => { - console.log(errorText); - }); - }; - request(api.MATERIALS_RESOURCES_FILE(id), methods.GET, onSuccess, onFailure); - - if (this.isAnySelected()) { - this.handleIconClick(id); - } - } - - handleMouseOver(id: number) { - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isHoveringOver[id] = true; - this.setState({ isHoveringOver }); - } - - handleMouseOut(id: number) { - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isHoveringOver[id] = false; - this.setState({ isHoveringOver }); - } - - render() { - return ( - <> - <ResourceSectionHeader - heading="Files" - showDownload={this.isAnySelected()} - onDownloadClick={() => this.handleDownloadClick()} - onSelectAllClick={() => this.handleSelectAllClick()} - selectAllIcon={this.isAllSelected() ? faCheckSquare : faSquare} - checkBoxColur={this.isAnySelected() ? "#495057" : "#dee2e6"} - /> - - <Row style={{ marginTop: "10px", marginLeft: "-10px", marginRight: "-10px" }}> - {this.props.documentItems.map(({ title, type, tags, id }) => { - let normalIcon : IconDefinition; - switch (type) { - case "pdf": - normalIcon = faFilePdf; - break; - case "video": - normalIcon = faFileVideo; - break; - default: - normalIcon = faFileAlt; - break; - } - return (<Col - xs={6} - sm={6} - md={6} - lg={4} - xl={3} - key={id} - style={{ marginBottom: ".5rem", marginTop: ".5rem", paddingLeft: "10px", paddingRight: "10px" }} - > - <FileCard - title={title} - type={type} - tags={tags} - icon={ - this.isAnySelected() || this.state.isHoveringOver[id] - ? this.state.isSelected[id] - ? faCheckSquare - : faSquare - : normalIcon - } - onClick={() => this.handleCardClick(id)} - onIconClick={(e) => { - e.stopPropagation(); - this.handleIconClick(id); - }} - onMouseOver={() => this.handleMouseOver(id)} - onMouseOut={() => this.handleMouseOut(id)} - /> - </Col>) -})} - </Row> - </> - ); - } -} - -export default CurrentDirectoryView; diff --git a/src/components/molecules/CurrentDirectoryView/style.module.scss b/src/components/molecules/CurrentDirectoryView/style.module.scss deleted file mode 100644 index 471dfec95..000000000 --- a/src/components/molecules/CurrentDirectoryView/style.module.scss +++ /dev/null @@ -1,5 +0,0 @@ -@import "assets/scss/custom"; - -.quickAccessRow { - height: fit-content; -} diff --git a/src/components/molecules/QuickAccessView/index.tsx b/src/components/molecules/QuickAccessView/index.tsx deleted file mode 100644 index 76bab3782..000000000 --- a/src/components/molecules/QuickAccessView/index.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import React from "react"; -import styles from "./style.module.scss"; - -import classNames from "classnames"; -import Row from "react-bootstrap/esm/Row"; -import Col from "react-bootstrap/esm/Col"; -import { api, methods } from "../../../constants/routes"; -import { request } from "../../../utils/api"; -import ResourceSectionHeader from "../ResourceSectionHeader"; -import FileCard from "components/atoms/FileCard"; -import { faSquare, faCheckSquare } from "@fortawesome/free-regular-svg-icons"; -import { faFileAlt, IconDefinition, faFilePdf, faFileVideo } from "@fortawesome/free-solid-svg-icons"; - -export interface QuickAccessProps { - quickAccessItems: { - title: string; - type: string; - tags: string[]; - id: number; - }[]; - moduleCode?: string; -} - -type idBooleanMap = { [key: number]: boolean }; -interface MyState { - isSelected: idBooleanMap; - isHoveringOver: idBooleanMap; -} - -class QuickAccessView extends React.Component<QuickAccessProps, MyState> { - constructor(props: QuickAccessProps) { - super(props); - this.state = { isSelected: [], isHoveringOver: [] }; - } - - componentDidMount() { - let isSelected: idBooleanMap = []; - let isHoveringOver: idBooleanMap = []; - this.props.quickAccessItems.forEach(({ id }: { id: number }) => { - isSelected[id] = false; - isHoveringOver[id] = false; - }); - this.setState({ isSelected, isHoveringOver }); - } - - 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)); - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isSelected[id] = !isSelected[id]; - isHoveringOver[id] = false; - this.setState({ isSelected, isHoveringOver }); - } - - handleDownloadClick() { - const onSuccess = (filename: string, data: any) => { - // TODO: Try to navigate straight to the endpoint url instead of creating an object url - data.blob().then((blob: any) => { - let url = URL.createObjectURL(blob); - let a = document.createElement("a"); - a.href = url; - a.download = filename; - a.click(); - a.remove(); - }); - }; - // Partial application utility - const downloadFilename = (filename: string) => { - return (data: any) => { - return onSuccess(filename, data); - }; - }; - const onFailure = (error: { text: () => Promise<any> }) => { - error.text().then((errorText) => { - console.log(errorText); - }); - }; - - let indices : number[] = []; - for (let key in this.state.isSelected) { - if (this.state.isSelected[key]) { - indices.push(parseInt(key)); - } - } - - if (indices.length === 1) { - // Only one file to download, call single file endpoint - let filename = this.props.quickAccessItems.filter(document => document.id === indices[0])[0].title; - request(api.MATERIALS_RESOURCES_FILE(indices[0]), methods.GET, downloadFilename(filename), onFailure); - } else { - // Multiple files to download, call zipped selection endpoint - request(api.MATERIALS_ZIPPED_SELECTION, methods.GET, downloadFilename("materials.zip"), onFailure, { - ids: indices, - course: this.props.moduleCode, - }); - } - } - - 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 }); - } - - handleCardClick(id: number) { - if (this.isAnySelected()) { - this.handleIconClick(id); - return; - } - - const onSuccess = (data: any) => { - // TODO: Try to navigate straight to the endpoint url instead of creating an object url - data.blob().then((blob: any) => { - let url = URL.createObjectURL(blob); - let a = document.createElement("a"); - a.target = "_blank"; - a.href = url; - a.click(); - a.remove(); - }); - }; - const onFailure = (error: { text: () => Promise<any> }) => { - error.text().then((errorText) => { - console.log(errorText); - }); - }; - request(api.MATERIALS_RESOURCES_FILE(id), methods.GET, onSuccess, onFailure); - } - - handleMouseOver(id: number) { - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isHoveringOver[id] = true; - this.setState({ isHoveringOver }); - } - - handleMouseOut(id: number) { - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isHoveringOver[id] = false; - this.setState({ isHoveringOver }); - } - - render() { - return ( - <> - <ResourceSectionHeader - heading="Quick Access" - onDownloadClick={() => this.handleDownloadClick()} - showDownload={this.isAnySelected()} - onSelectAllClick={() => this.handleSelectAllClick()} - selectAllIcon={this.isAllSelected() ? faCheckSquare : faSquare} - checkBoxColur={this.isAnySelected() ? "#495057" : "#dee2e6"} - /> - - <Row - className={classNames( - "d-flex", - "flex-row", - "flex-nowrap", - styles.quickAccessRow - )} - > - {this.props.quickAccessItems.map(({ title, type, tags, id }) => { - let normalIcon: IconDefinition; - switch (type) { - case "pdf": - normalIcon = faFilePdf; - break; - case "video": - normalIcon = faFileVideo; - break; - default: - normalIcon = faFileAlt; - break; - } - return ( - <Col - xs={7} - sm={5} - md={5} - lg={4} - xl={3} - key={id} - style={{ marginBottom: ".5rem", marginTop: ".5rem", paddingLeft: "10px", paddingRight: "10px" }} - > - <FileCard - title={title} - type={type} - tags={tags} - icon={ - this.isAnySelected() || this.state.isHoveringOver[id] - ? this.state.isSelected[id] - ? faCheckSquare - : faSquare - : normalIcon - } - onClick={() => this.handleCardClick(id)} - onIconClick={(e) => { - e.stopPropagation(); - this.handleIconClick(id); - }} - onMouseOver={() => this.handleMouseOver(id)} - onMouseOut={() => this.handleMouseOut(id)} - /> - </Col> - ); - })} - </Row> - </> - ); - } -} - -export default QuickAccessView; diff --git a/src/components/molecules/QuickAccessView/style.module.scss b/src/components/molecules/QuickAccessView/style.module.scss deleted file mode 100644 index be0bbee19..000000000 --- a/src/components/molecules/QuickAccessView/style.module.scss +++ /dev/null @@ -1,34 +0,0 @@ -@import "assets/scss/custom"; - -.quickAccessRow { - scrollbar-width: thin; - scrollbar-color: $white $white; - margin-top: 10px; - overflow-y: visible; - overflow-x: auto; - margin-right: -10px; - margin-left: -10px; - // margin-left: 0; // leave space before card -} - -.quickAccessRow::-webkit-scrollbar { - width: 1rem; - height: 0.5rem; -} -.quickAccessRow::-webkit-scrollbar-track { - background: $white; - margin-left: 10px; - margin-right: 10px; -} -.quickAccessRow::-webkit-scrollbar-thumb { - background-color: $white; - border-radius: .5rem; -} - -.quickAccessRow:hover { - scrollbar-color: $gray-400 $white; -} - -.quickAccessRow:hover::-webkit-scrollbar-thumb { - background-color: $gray-400; -} diff --git a/src/components/molecules/ResourcesFolderView/index.tsx b/src/components/molecules/ResourcesFolderView/index.tsx deleted file mode 100644 index 4184388fb..000000000 --- a/src/components/molecules/ResourcesFolderView/index.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import React from "react"; -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 { withRouter, RouteComponentProps } from "react-router-dom"; - -type PathParamsType = { - location: any; - history: string; -}; - -type PropsType = RouteComponentProps<PathParamsType> & ResourceFoldersProps; - -export interface ResourceFoldersProps { - folderItems: { - title: string; - id: number; - }[]; -} - -type idBooleanMap = { [key: number]: boolean }; -interface MyState { - isSelected: idBooleanMap; - isHoveringOver: idBooleanMap; -} - -class ResourcesFolderView extends React.Component<PropsType, MyState> { - constructor(props: PropsType) { - super(props); - this.state = { isSelected: [], isHoveringOver: []}; - } - - componentDidMount() { - let isSelected: idBooleanMap = []; - this.props.folderItems.forEach(({ id }: { id: number }) => { - isSelected[id] = false; - }); - this.setState({ isSelected }); - } - - isAnySelected(): boolean { - let items = this.props.folderItems; - 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.folderItems; - 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)); - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isSelected[id] = !isSelected[id]; - isHoveringOver[id] = false; - this.setState({ isSelected, isHoveringOver }); - } - - 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 }); - } - - handleCardClick(id: number) { - if (this.isAnySelected()) { - this.handleIconClick(id); - return; - } - - let items = this.props.folderItems; - for (let item in items) { - if (items[item].id === id) { - this.props.history.push( - `${this.props.location.pathname}/${items[item].title}` - ); - return; - } - } - } - - handleMouseOver(id: number) { - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isHoveringOver[id] = true; - this.setState({ isHoveringOver }); - } - - handleMouseOut(id: number) { - let isHoveringOver = JSON.parse(JSON.stringify(this.state.isHoveringOver)); - isHoveringOver[id] = false; - this.setState({ isHoveringOver }); - } - - render() { - return ( - <> - <ResourceSectionHeader - heading="Folders" - showDownload={this.isAnySelected()} - onDownloadClick={() => {}} - onSelectAllClick={() => this.handleSelectAllClick()} - selectAllIcon={this.isAllSelected() ? faCheckSquare : faSquare} - checkBoxColur={this.isAnySelected() ? "#495057" : "#dee2e6"} - /> - - <Row style={{ marginTop: "10px", marginRight: "-10px", marginLeft: "-10px" }}> - {this.props.folderItems.map(({ title, id }) => ( - <Col xs={6} sm={6} md={3} key={id} style={{ paddingLeft: "10px", paddingRight: "10px" }}> - <FolderCard - title={title} - icon={ - this.isAnySelected() || this.state.isHoveringOver[id] - ? this.state.isSelected[id] - ? faCheckSquare - : faSquare - : faFolder - } - onIconClick={(e) => { - e.stopPropagation(); - this.handleIconClick(id); - }} - onClick={() => this.handleCardClick(id)} - onMouseOver={() => this.handleMouseOver(id)} - onMouseOut={() => this.handleMouseOut(id)} - /> - </Col> - ))} - </Row> - </> - ); - } -} - -export default withRouter(ResourcesFolderView); diff --git a/src/components/molecules/ResourcesFolderView/style.module.scss b/src/components/molecules/ResourcesFolderView/style.module.scss deleted file mode 100644 index 90ea856af..000000000 --- a/src/components/molecules/ResourcesFolderView/style.module.scss +++ /dev/null @@ -1 +0,0 @@ -@import "assets/scss/custom"; \ No newline at end of file diff --git a/src/components/molecules/SelectionView/index.tsx b/src/components/molecules/SelectionView/index.tsx index b41bc74f8..1e74ac2ad 100644 --- a/src/components/molecules/SelectionView/index.tsx +++ b/src/components/molecules/SelectionView/index.tsx @@ -26,9 +26,10 @@ export interface SelectionProps { export interface MyProps { selectionItems: SelectionItem[]; - moduleCode?: string; render: (selection: SelectionProps) => any; heading: string; + onDownloadClick: (identifiers: number[]) => void; + onItemClick: (identifier: number) => void; } interface MyState { @@ -80,10 +81,19 @@ class SelectionView extends React.Component<MyProps, MyState> { isSelected[id] = !isSelected[id]; isHoveringOver[id] = false; this.setState({ isSelected, isHoveringOver }); + } + + handleDownloadClick(e: React.MouseEvent) { + e.preventDefault(); + let indices : number[] = []; + for (let key in this.state.isSelected) { + if (this.state.isSelected[key]) { + indices.push(parseInt(key)); + } + } + this.props.onDownloadClick(indices); } - handleDownloadClick() {} - handleSelectAllClick() { let items = this.props.selectionItems; let isSelected = JSON.parse(JSON.stringify(this.state.isSelected)); @@ -98,7 +108,8 @@ class SelectionView extends React.Component<MyProps, MyState> { if (this.isAnySelected()) { this.handleIconClick(id); return; - } + } + this.props.onItemClick(id); } handleMouseOver(id: number) { @@ -128,7 +139,7 @@ class SelectionView extends React.Component<MyProps, MyState> { <> <ResourceSectionHeader heading={this.props.heading} - onDownloadClick={() => this.handleDownloadClick()} + onDownloadClick={(e) => this.handleDownloadClick(e)} showDownload={this.isAnySelected()} onSelectAllClick={() => this.handleSelectAllClick()} selectAllIcon={this.isAllSelected() ? faCheckSquare : faSquare} diff --git a/src/components/pages/ModuleResources/index.tsx b/src/components/pages/ModuleResources/index.tsx index 3d07f8d01..89242227b 100644 --- a/src/components/pages/ModuleResources/index.tsx +++ b/src/components/pages/ModuleResources/index.tsx @@ -5,8 +5,6 @@ import { api, methods } from "../../../constants/routes"; import MyBreadcrumbs from "components/atoms/MyBreadcrumbs"; import QuickAccessRow from "components/molecules/QuickAccessRow"; -import ResourcesFolderView from "components/molecules/ResourcesFolderView"; -import CurrentDirectoryView from "components/molecules/CurrentDirectoryView"; import SearchBox from "components/molecules/SearchBox"; import SelectionView, { SelectionProps, @@ -113,6 +111,76 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { return title.indexOf(rest) !== -1; } + handleFileDownload(indices: number[]) { + const onSuccess = (filename: string, data: any) => { + // TODO: Try to navigate straight to the endpoint url instead of creating an object url + data.blob().then((blob: any) => { + let url = URL.createObjectURL(blob); + let a = document.createElement("a"); + a.href = url; + a.download = filename; + a.click(); + a.remove(); + }); + }; + // Partial application utility + const downloadFilename = (filename: string) => { + return (data: any) => { + return onSuccess(filename, data); + }; + }; + const onFailure = (error: { text: () => Promise<any> }) => { + error.text().then((errorText) => { + console.log(errorText); + }); + }; + + if (indices.length === 1) { + // Only one file to download, call single file endpoint + let filename = this.state.resources.filter( + (document) => document.id === indices[0] + )[0].title; + request( + api.MATERIALS_RESOURCES_FILE(indices[0]), + methods.GET, + downloadFilename(filename), + onFailure + ); + } else { + // Multiple files to download, call zipped selection endpoint + request( + api.MATERIALS_ZIPPED_SELECTION, + methods.GET, + downloadFilename("materials.zip"), + onFailure, + { + ids: indices, + course: this.moduleCode, + } + ); + } + } + + handleFileClick(id: number){ + const onSuccess = (data: any) => { + // TODO: Try to navigate straight to the endpoint url instead of creating an object url + data.blob().then((blob: any) => { + let url = URL.createObjectURL(blob); + let a = document.createElement("a"); + a.target = "_blank"; + a.href = url; + a.click(); + a.remove(); + }); + }; + const onFailure = (error: { text: () => Promise<any> }) => { + error.text().then((errorText) => { + console.log(errorText); + }); + }; + request(api.MATERIALS_RESOURCES_FILE(id), methods.GET, onSuccess, onFailure); + } + getResourcesFolderView(scope: any) { let folders: { title: string; id: number }[] = Array.from( new Set<string>(this.state.resources.map((res: Resource) => res.folder)) @@ -121,16 +189,16 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { id: id, })); - if (this.state.searchText === "" && scope === "" && folders.length > 0) { - return ( + if (this.state.searchText === "" && scope === "" && folders.length > 0) { + return ( <SelectionView heading="Folders" + onDownloadClick={() => {}} + onItemClick={() => {}} selectionItems={folders} - render={(select: SelectionProps) => ( - <FoldersRow select={select} /> - )} + render={(select: SelectionProps) => <FoldersRow select={select} />} /> - ); + ); } } @@ -149,6 +217,8 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { return ( <SelectionView heading="Files" + onItemClick={(id) => this.handleFileClick(id)} + onDownloadClick={(ids) => this.handleFileDownload(ids)} selectionItems={filesContent} render={(select: SelectionProps) => ( <CurrentDirectoryRow select={select} /> @@ -172,6 +242,8 @@ class ModuleResources extends React.Component<ResourcesProps, ResourceState> { return ( <SelectionView heading="Quick Access" + onItemClick={(id) => this.handleFileClick(id)} + onDownloadClick={(ids) => this.handleFileDownload(ids)} selectionItems={quickAccessItems} render={(select: SelectionProps) => ( <QuickAccessRow select={select} /> -- GitLab