From 70a7942118bbf82a89c997043eb1d1560dbd1ffa Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Wed, 8 Feb 2017 14:03:09 -0500 Subject: [PATCH 01/14] Add document container --- src/containers/Documents/actions.js | 26 +++++++++++++++++++ src/containers/Documents/constants.js | 3 +++ src/containers/Documents/propTypes.js | 0 src/containers/Documents/reducer.js | 37 +++++++++++++++++++++++++++ src/containers/Documents/sagas.js | 35 +++++++++++++++++++++++++ src/reducers.js | 2 ++ src/sagas.js | 2 ++ src/utils/rest_services.js | 2 ++ 8 files changed, 107 insertions(+) create mode 100644 src/containers/Documents/actions.js create mode 100644 src/containers/Documents/constants.js create mode 100644 src/containers/Documents/propTypes.js create mode 100644 src/containers/Documents/reducer.js create mode 100644 src/containers/Documents/sagas.js diff --git a/src/containers/Documents/actions.js b/src/containers/Documents/actions.js new file mode 100644 index 00000000..95f64496 --- /dev/null +++ b/src/containers/Documents/actions.js @@ -0,0 +1,26 @@ +import { + LOAD_DOCUMENTS, + LOAD_DOCUMENTS_SUCCESS, + LOAD_DOCUMENTS_ERROR, +} from './constants'; + +export function loadDocuments(buildingId) { + return { + type: LOAD_DOCUMENTS, + buildingId, + }; +} + +export function documentsLoaded(documents) { + return { + type: LOAD_DOCUMENTS_SUCCESS, + payload: documents, + }; +} + +export function documentsLoadingError(error) { + return { + type: LOAD_DOCUMENTS_ERROR, + error, + }; +} diff --git a/src/containers/Documents/constants.js b/src/containers/Documents/constants.js new file mode 100644 index 00000000..410e2a32 --- /dev/null +++ b/src/containers/Documents/constants.js @@ -0,0 +1,3 @@ +export const LOAD_DOCUMENTS = 'LOAD_DOCUMENTS'; +export const LOAD_DOCUMENTS_SUCCESS = 'LOAD_DOCUMENTS_SUCCESS'; +export const LOAD_DOCUMENTS_ERROR = 'LOAD_DOCUMENTS_ERROR'; diff --git a/src/containers/Documents/propTypes.js b/src/containers/Documents/propTypes.js new file mode 100644 index 00000000..e69de29b diff --git a/src/containers/Documents/reducer.js b/src/containers/Documents/reducer.js new file mode 100644 index 00000000..b300579c --- /dev/null +++ b/src/containers/Documents/reducer.js @@ -0,0 +1,37 @@ +import { + LOAD_DOCUMENTS, + LOAD_DOCUMENTS_SUCCESS, + LOAD_DOCUMENTS_ERROR, +} from './constants'; + +const initState = { + loading: false, + error: false, + files: [], +}; + +export default function (state = initState, action) { + switch (action.type) { + case LOAD_DOCUMENTS: + return { + loading: true, + error: false, + }; + + case LOAD_DOCUMENTS_SUCCESS: + return { + loading: false, + error: false, + files: action.payload.data.data, + }; + + case LOAD_DOCUMENTS_ERROR: + return { + loading: false, + error: action.error, + }; + + default: + return state; + } +} diff --git a/src/containers/Documents/sagas.js b/src/containers/Documents/sagas.js new file mode 100644 index 00000000..1928c373 --- /dev/null +++ b/src/containers/Documents/sagas.js @@ -0,0 +1,35 @@ +import { call, put, takeLatest } from 'redux-saga/effects'; +import request from '../../utils/request'; +import { getHeaders, documentURL } from '../../utils/rest_services'; + +import { + LOAD_DOCUMENTS, +} from './constants'; + +import { + documentsLoaded, + documentsLoadingError, +} from './actions'; + + +function* getDocuments(action) { + const { buildingId } = action; + + const data = yield call( + request, + `${documentURL}?building_id=${buildingId}`, { + method: 'GET', + headers: getHeaders(), + } + ); + + if (!data.err) { + yield put(documentsLoaded(data)); + } else { + yield put(documentsLoadingError(data.err)); + } +} + +export default function* () { + yield takeLatest(LOAD_DOCUMENTS, getDocuments); +} diff --git a/src/reducers.js b/src/reducers.js index bf22b798..93772d98 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -5,6 +5,7 @@ import SearchBarReducer from './containers/SearchBar/reducer'; import BuildingReducer from './containers/Building/reducer'; import GoogleLoginReducer from './containers/GoogleLogin/reducer'; import DimensionsReducer from './containers/Dimensions/reducer'; +import documents from './containers/Documents/reducer'; export default combineReducers({ routing: routerReducer, @@ -12,4 +13,5 @@ export default combineReducers({ buildingDetail: BuildingReducer, googleLogin: GoogleLoginReducer, dimensions: DimensionsReducer, + documents, }); diff --git a/src/sagas.js b/src/sagas.js index bd7d214a..79cf9f73 100644 --- a/src/sagas.js +++ b/src/sagas.js @@ -1,11 +1,13 @@ import buildingsSearchSaga from './containers/SearchBar/sagas'; import buildingSaga from './containers/Building/sagas'; import dimensionsSaga from './containers/Dimensions/sagas'; +import documentsSaga from './containers/Documents/sagas'; export default function* rootSaga() { yield [ buildingSaga(), dimensionsSaga(), buildingsSearchSaga(), + documentsSaga(), ]; } diff --git a/src/utils/rest_services.js b/src/utils/rest_services.js index 4f2a2c16..81bdb6ce 100644 --- a/src/utils/rest_services.js +++ b/src/utils/rest_services.js @@ -7,7 +7,9 @@ export function getHeaders() { const buildingService = process.env.REACT_APP_BUILDING_SERVICE; const utilityService = process.env.REACT_APP_UTILITY_SERVICE; +const documentService = process.env.REACT_APP_DOCUMENT_SERVICE; export const buildingsURL = `${buildingService}/building/`; export const turkURL = `${buildingService}/turkhit/`; export const utilityURL = `${utilityService}/scraper/`; +export const documentURL = `${documentService}/document/`; -- GitLab From 9e95e4c0bbe8692e66cd61f5562b66c827d423f0 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Wed, 8 Feb 2017 17:22:59 -0500 Subject: [PATCH 02/14] Get document by type --- src/containers/Documents/actions.js | 8 ++++++-- src/containers/Documents/reducer.js | 11 +++++++++-- src/containers/Documents/sagas.js | 13 +++++++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/containers/Documents/actions.js b/src/containers/Documents/actions.js index 95f64496..d12b2b87 100644 --- a/src/containers/Documents/actions.js +++ b/src/containers/Documents/actions.js @@ -4,17 +4,21 @@ import { LOAD_DOCUMENTS_ERROR, } from './constants'; -export function loadDocuments(buildingId) { +export function loadDocuments(buildingId, address, boxFolder, fileKey) { return { type: LOAD_DOCUMENTS, buildingId, + address, + boxFolder, + fileKey, }; } -export function documentsLoaded(documents) { +export function documentsLoaded(documents, fileKey) { return { type: LOAD_DOCUMENTS_SUCCESS, payload: documents, + fileKey, }; } diff --git a/src/containers/Documents/reducer.js b/src/containers/Documents/reducer.js index b300579c..581c0d7c 100644 --- a/src/containers/Documents/reducer.js +++ b/src/containers/Documents/reducer.js @@ -7,7 +7,11 @@ import { const initState = { loading: false, error: false, - files: [], + files: { + building: [], + utilityBills: [], // Utility_Bills + buildingDimensions: [], // Building_Dimensions + }, }; export default function (state = initState, action) { @@ -22,7 +26,10 @@ export default function (state = initState, action) { return { loading: false, error: false, - files: action.payload.data.data, + files: { + ...state.files, + [action.fileKey]: action.payload.data.data, + }, }; case LOAD_DOCUMENTS_ERROR: diff --git a/src/containers/Documents/sagas.js b/src/containers/Documents/sagas.js index 1928c373..f06a7cf0 100644 --- a/src/containers/Documents/sagas.js +++ b/src/containers/Documents/sagas.js @@ -13,20 +13,21 @@ import { function* getDocuments(action) { - const { buildingId } = action; + const { buildingId, address, boxFolder, fileKey } = action; + const boxPath = `/Buildings/${buildingId}_${address}/${boxFolder}`; - const data = yield call( + const res = yield call( request, - `${documentURL}?building_id=${buildingId}`, { + `${documentURL}?paths[]=${boxPath}`, { method: 'GET', headers: getHeaders(), } ); - if (!data.err) { - yield put(documentsLoaded(data)); + if (!res.err) { + yield put(documentsLoaded(res, fileKey)); } else { - yield put(documentsLoadingError(data.err)); + yield put(documentsLoadingError(res.err)); } } -- GitLab From dfc3c3f7841c2063eded50f72fce8ff45212cf2f Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Thu, 9 Feb 2017 13:35:13 -0500 Subject: [PATCH 03/14] Add documents and document retrieval to building overview --- src/components/BuildingOverview/index.js | 49 ++++++++++++++++-------- src/containers/Building/index.js | 22 +++++++---- src/containers/Documents/actions.js | 6 +-- src/containers/Documents/propTypes.js | 31 +++++++++++++++ src/containers/Documents/reducer.js | 3 ++ src/containers/Documents/sagas.js | 5 +-- 6 files changed, 86 insertions(+), 30 deletions(-) diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverview/index.js index 12b083fa..2d44b576 100644 --- a/src/components/BuildingOverview/index.js +++ b/src/components/BuildingOverview/index.js @@ -1,24 +1,39 @@ -import React, { PropTypes } from 'react'; +import React, { Component, PropTypes } from 'react'; +import documentsPropType from '../../containers/Documents/propTypes'; import './styles.css'; -export default function BuildingOverview({ building }) { - return ( -
-

- {building.address} -

-
    -
  • Zipcode: {building.zipcode}
  • -
  • BBL: {building.bbl}
  • -
  • Building ID: {building.building_id}
  • -
  • Lot ID: {building.lot_id}
  • -
  • Borough: {building.borough}
  • -
-
- ); + +export default class BuildingOverview extends Component { + componentDidMount() { + const { building, buildingId } = this.props; + const documentPath = `/Buildings/${buildingId}_${building.address}/`; + this.props.getDocuments(documentPath, 'building'); + } + + render() { + const { building, documents } = this.props; + const { loading, error, files } = documents; + + return ( +
+

+ {building.address} +

+
    +
  • Zipcode: {building.zipcode}
  • +
  • BBL: {building.bbl}
  • +
  • Building ID: {building.building_id}
  • +
  • Lot ID: {building.lot_id}
  • +
  • Borough: {building.borough}
  • +
+ { !loading && !error && files.building.length > 0 && files.building[0].url_download} +
+ ); + } } BuildingOverview.propTypes = { + buildingId: PropTypes.string, building: PropTypes.shape({ address: PropTypes.string, bbl: PropTypes.number, @@ -27,4 +42,6 @@ BuildingOverview.propTypes = { borough: PropTypes.string, zipcode: PropTypes.number, }), + getDocuments: PropTypes.func, + documents: documentsPropType, }; diff --git a/src/containers/Building/index.js b/src/containers/Building/index.js index 43d300ae..99429393 100644 --- a/src/containers/Building/index.js +++ b/src/containers/Building/index.js @@ -1,15 +1,18 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import buildingDetailPropTypes from './propTypes'; +import buildingDetailPropTypes from './propTypes'; import { loadBuildingDetail } from './actions'; -import './styles.css'; +import documentsPropType from '../Documents/propTypes'; +import { loadDocuments } from '../Documents/actions'; + import SideBarDetail from '../../components/SideBarDetail'; +import './styles.css'; -class BuildingOverview extends Component { +class Building extends Component { componentDidMount() { this.props.loadBuildingDetail(this.props.buildingId); } @@ -21,6 +24,8 @@ class BuildingOverview extends Component { mainContent = React.cloneElement(this.props.children, { buildingId: this.props.buildingId, building: this.props.buildingDetail.overview, + getDocuments: this.props.loadDocuments, + documents: this.props.documents, }); } @@ -43,21 +48,24 @@ class BuildingOverview extends Component { } } -BuildingOverview.propTypes = { +Building.propTypes = { children: PropTypes.element, buildingDetail: buildingDetailPropTypes, buildingId: PropTypes.string, loadBuildingDetail: PropTypes.func, + loadDocuments: PropTypes.func, + documents: documentsPropType, }; function mapDispatchToProps(dispatch) { return bindActionCreators({ loadBuildingDetail, + loadDocuments, }, dispatch); } -function mapStateToProps({ buildingDetail }) { - return { buildingDetail }; +function mapStateToProps({ buildingDetail, documents }) { + return { buildingDetail, documents }; } -export default connect(mapStateToProps, mapDispatchToProps)(BuildingOverview); +export default connect(mapStateToProps, mapDispatchToProps)(Building); diff --git a/src/containers/Documents/actions.js b/src/containers/Documents/actions.js index d12b2b87..56413bf0 100644 --- a/src/containers/Documents/actions.js +++ b/src/containers/Documents/actions.js @@ -4,12 +4,10 @@ import { LOAD_DOCUMENTS_ERROR, } from './constants'; -export function loadDocuments(buildingId, address, boxFolder, fileKey) { +export function loadDocuments(documentPath, fileKey) { return { type: LOAD_DOCUMENTS, - buildingId, - address, - boxFolder, + documentPath, fileKey, }; } diff --git a/src/containers/Documents/propTypes.js b/src/containers/Documents/propTypes.js index e69de29b..b85ebcbf 100644 --- a/src/containers/Documents/propTypes.js +++ b/src/containers/Documents/propTypes.js @@ -0,0 +1,31 @@ +import { PropTypes } from 'react'; + +const { shape, arrayOf, oneOfType, string, number, bool } = PropTypes; + +const document = shape({ + box_id: number, + building_id: number, + content_type: string, + created: string, + id: number, + key: string, + name: string, + path: string, + tags: string, + updated: string, + url_box: string, + url_download: string, +}); + +export default shape({ + loading: bool, + error: oneOfType([ + bool, + string, + ]), + files: shape({ + building: arrayOf(document), + utilityBills: arrayOf(document), + buildingDimensions: arrayOf(document), + }), +}); diff --git a/src/containers/Documents/reducer.js b/src/containers/Documents/reducer.js index 581c0d7c..6f79f1b5 100644 --- a/src/containers/Documents/reducer.js +++ b/src/containers/Documents/reducer.js @@ -18,12 +18,14 @@ export default function (state = initState, action) { switch (action.type) { case LOAD_DOCUMENTS: return { + ...state, loading: true, error: false, }; case LOAD_DOCUMENTS_SUCCESS: return { + ...state, loading: false, error: false, files: { @@ -34,6 +36,7 @@ export default function (state = initState, action) { case LOAD_DOCUMENTS_ERROR: return { + ...state, loading: false, error: action.error, }; diff --git a/src/containers/Documents/sagas.js b/src/containers/Documents/sagas.js index f06a7cf0..1af1dbd9 100644 --- a/src/containers/Documents/sagas.js +++ b/src/containers/Documents/sagas.js @@ -13,12 +13,11 @@ import { function* getDocuments(action) { - const { buildingId, address, boxFolder, fileKey } = action; - const boxPath = `/Buildings/${buildingId}_${address}/${boxFolder}`; + const { documentPath, fileKey } = action; const res = yield call( request, - `${documentURL}?paths[]=${boxPath}`, { + `${documentURL}?paths[]=${documentPath}`, { method: 'GET', headers: getHeaders(), } -- GitLab From e47c2b1a24879ae0559b36a21a8a53f52e9f515b Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Thu, 9 Feb 2017 15:10:07 -0500 Subject: [PATCH 04/14] Add DocumentCardHolder and DocumentCard components to show files --- src/components/BuildingOverview/index.js | 32 +++++++----- src/components/DocumentCard/index.js | 32 ++++++++++++ src/components/DocumentCard/styles.css | 0 src/components/DocumentCardViewer/index.js | 53 ++++++++++++++++++++ src/components/DocumentCardViewer/styles.css | 0 src/components/bpl.js | 3 ++ src/containers/Documents/propTypes.js | 8 +-- 7 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 src/components/DocumentCard/index.js create mode 100644 src/components/DocumentCard/styles.css create mode 100644 src/components/DocumentCardViewer/index.js create mode 100644 src/components/DocumentCardViewer/styles.css diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverview/index.js index 2d44b576..72784ee0 100644 --- a/src/components/BuildingOverview/index.js +++ b/src/components/BuildingOverview/index.js @@ -1,5 +1,6 @@ import React, { Component, PropTypes } from 'react'; import documentsPropType from '../../containers/Documents/propTypes'; +import DocumentCardViewer from '../../components/DocumentCardViewer'; import './styles.css'; @@ -12,21 +13,26 @@ export default class BuildingOverview extends Component { render() { const { building, documents } = this.props; - const { loading, error, files } = documents; return ( -
-

- {building.address} -

-
    -
  • Zipcode: {building.zipcode}
  • -
  • BBL: {building.bbl}
  • -
  • Building ID: {building.building_id}
  • -
  • Lot ID: {building.lot_id}
  • -
  • Borough: {building.borough}
  • -
- { !loading && !error && files.building.length > 0 && files.building[0].url_download} +
+
+

+ {building.address} +

+
    +
  • Zipcode: {building.zipcode}
  • +
  • BBL: {building.bbl}
  • +
  • Building ID: {building.building_id}
  • +
  • Lot ID: {building.lot_id}
  • +
  • Borough: {building.borough}
  • +
+
+
); } diff --git a/src/components/DocumentCard/index.js b/src/components/DocumentCard/index.js new file mode 100644 index 00000000..22b69211 --- /dev/null +++ b/src/components/DocumentCard/index.js @@ -0,0 +1,32 @@ +import React, { Component } from 'react'; +import { documentProps } from '../../containers/Documents/propTypes'; + +class DocumentCard extends Component { + constructor(props) { + super(props); + + this.state = { + uploading: false, + }; + } + + render() { + const { document } = this.props; + + return ( + + {document.name} + {document.tags} + {document.updated !== null ? + `Last modified on ${document.updated}` : + `Created on ${document.created}`} + + ); + } +} + +DocumentCard.propTypes = { + document: documentProps, +}; + +export default DocumentCard; diff --git a/src/components/DocumentCard/styles.css b/src/components/DocumentCard/styles.css new file mode 100644 index 00000000..e69de29b diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js new file mode 100644 index 00000000..308aea68 --- /dev/null +++ b/src/components/DocumentCardViewer/index.js @@ -0,0 +1,53 @@ +import React, { Component, PropTypes } from 'react'; +import { documentProps } from '../../containers/Documents/propTypes'; +import DocumentCard from '../DocumentCard/'; +import { uploadSVG } from '../bpl'; + +export default class DocumentCardViewer extends Component { + constructor(props) { + super(props); + + this.state = { + files: [], + }; + } + + renderDocuments() { + if (this.props.error) { + return
; + } + const docs = this.props.documents.map(item => ( +
+ +
+ )); + return docs; + } + + render() { + return ( +
+
Documents + View all +
+
+ + +
+ { this.renderDocuments() } +
+ ); + } +} + +DocumentCardViewer.propTypes = { + // loading: PropTypes.bool, + error: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.string, + ]), + documents: PropTypes.arrayOf(documentProps), +}; diff --git a/src/components/DocumentCardViewer/styles.css b/src/components/DocumentCardViewer/styles.css new file mode 100644 index 00000000..e69de29b diff --git a/src/components/bpl.js b/src/components/bpl.js index a865f314..1349c49d 100644 --- a/src/components/bpl.js +++ b/src/components/bpl.js @@ -1,3 +1,5 @@ +import uploadSVG from 'bpl/dist/svg/upload.svg'; + const BPAnalyticsSVG = require('bpl/dist/svg/BlocPower_Analytics.svg'); const BPAuditSVG = require('bpl/dist/svg/BlocPower_Audit.svg'); const BPBuildingsSVG = require('bpl/dist/svg/BlocPower_Buildings.svg'); @@ -27,6 +29,7 @@ const LogoPNG = require('bpl/dist/img/logo.png'); export { + uploadSVG, BPAnalyticsSVG, BPAuditSVG, BPBuildingsSVG, diff --git a/src/containers/Documents/propTypes.js b/src/containers/Documents/propTypes.js index b85ebcbf..f6f413be 100644 --- a/src/containers/Documents/propTypes.js +++ b/src/containers/Documents/propTypes.js @@ -2,7 +2,7 @@ import { PropTypes } from 'react'; const { shape, arrayOf, oneOfType, string, number, bool } = PropTypes; -const document = shape({ +export const documentProps = shape({ box_id: number, building_id: number, content_type: string, @@ -24,8 +24,8 @@ export default shape({ string, ]), files: shape({ - building: arrayOf(document), - utilityBills: arrayOf(document), - buildingDimensions: arrayOf(document), + building: arrayOf(documentProps), + utilityBills: arrayOf(documentProps), + buildingDimensions: arrayOf(documentProps), }), }); -- GitLab From abc9881f9b2194d075fbb9812247f0624fc4b6bd Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Sun, 12 Feb 2017 15:53:26 -0500 Subject: [PATCH 05/14] Add upload actions to for box --- src/components/BuildingOverview/index.js | 25 ++++++++++++--- src/components/DocumentCard/index.js | 4 ++- src/components/DocumentCardViewer/index.js | 24 ++++++++++++-- src/components/DocumentCardViewer/styles.css | 11 +++++++ src/containers/Building/index.js | 9 ++++-- src/containers/Documents/actions.js | 31 ++++++++++++++++++ src/containers/Documents/constants.js | 3 ++ src/containers/Documents/reducer.js | 33 +++++++++++++++++++- src/containers/Documents/sagas.js | 29 +++++++++++++++++ 9 files changed, 157 insertions(+), 12 deletions(-) diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverview/index.js index 72784ee0..a3c1e06b 100644 --- a/src/components/BuildingOverview/index.js +++ b/src/components/BuildingOverview/index.js @@ -5,10 +5,25 @@ import './styles.css'; export default class BuildingOverview extends Component { - componentDidMount() { + constructor(props) { + super(props); + const { building, buildingId } = this.props; - const documentPath = `/Buildings/${buildingId}_${building.address}/`; - this.props.getDocuments(documentPath, 'building'); + this.state = { + documentPath: `/Buildings/${buildingId}_${building.address}/`, + fileKey: 'building', + }; + } + + componentDidMount() { + this.props.getDocuments(this.state.documentPath, this.state.fileKey); + } + + uploadDocumentHandler = (documentName, document) => { + const { buildingId } = this.props; + const { documentPath, fileKey } = this.state; + this.props.uploadDocument(buildingId, documentPath, document, '', + documentName, fileKey); } render() { @@ -32,6 +47,7 @@ export default class BuildingOverview extends Component { loading={documents.loading} error={documents.error} documents={documents.files.building} + uploadDocument={this.uploadDocumentHandler} />
); @@ -48,6 +64,7 @@ BuildingOverview.propTypes = { borough: PropTypes.string, zipcode: PropTypes.number, }), - getDocuments: PropTypes.func, documents: documentsPropType, + getDocuments: PropTypes.func, + uploadDocument: PropTypes.func, }; diff --git a/src/components/DocumentCard/index.js b/src/components/DocumentCard/index.js index 22b69211..6abeacfa 100644 --- a/src/components/DocumentCard/index.js +++ b/src/components/DocumentCard/index.js @@ -16,7 +16,9 @@ class DocumentCard extends Component { return ( {document.name} - {document.tags} + { document.tags !== '' + ? {document.tags} + : } {document.updated !== null ? `Last modified on ${document.updated}` : `Created on ${document.created}`} diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index 308aea68..1b87a26c 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -2,6 +2,7 @@ import React, { Component, PropTypes } from 'react'; import { documentProps } from '../../containers/Documents/propTypes'; import DocumentCard from '../DocumentCard/'; import { uploadSVG } from '../bpl'; +import './styles.css'; export default class DocumentCardViewer extends Component { constructor(props) { @@ -12,6 +13,16 @@ export default class DocumentCardViewer extends Component { }; } + uploadHandler = (event) => { + const file = event.target.files[0]; + const fileReader = new FileReader(); + fileReader.readAsDataURL(file); + + fileReader.onload = function fileResults() { + this.props.uploadDocument(file.name, fileReader.result); + }.bind(this); + } + renderDocuments() { if (this.props.error) { return
; @@ -26,18 +37,24 @@ export default class DocumentCardViewer extends Component { render() { return ( -
+
Documents View all
- +
- { this.renderDocuments() } +
{ this.renderDocuments() }
); } @@ -50,4 +67,5 @@ DocumentCardViewer.propTypes = { PropTypes.string, ]), documents: PropTypes.arrayOf(documentProps), + uploadDocument: PropTypes.func, }; diff --git a/src/components/DocumentCardViewer/styles.css b/src/components/DocumentCardViewer/styles.css index e69de29b..2e814cf6 100644 --- a/src/components/DocumentCardViewer/styles.css +++ b/src/components/DocumentCardViewer/styles.css @@ -0,0 +1,11 @@ +.documentCardViewer { + /* TODO: Fix max height, 68px is height of navbar, 27px is the padding */ + max-height: calc(100vh - 68px - 27px); + display: flex; + flex-direction: column; +} + +.scrollBox { + overflow: auto; + flex: 1; +} \ No newline at end of file diff --git a/src/containers/Building/index.js b/src/containers/Building/index.js index 99429393..63b5d823 100644 --- a/src/containers/Building/index.js +++ b/src/containers/Building/index.js @@ -6,7 +6,7 @@ import buildingDetailPropTypes from './propTypes'; import { loadBuildingDetail } from './actions'; import documentsPropType from '../Documents/propTypes'; -import { loadDocuments } from '../Documents/actions'; +import { loadDocuments, uploadDocument } from '../Documents/actions'; import SideBarDetail from '../../components/SideBarDetail'; import './styles.css'; @@ -24,8 +24,9 @@ class Building extends Component { mainContent = React.cloneElement(this.props.children, { buildingId: this.props.buildingId, building: this.props.buildingDetail.overview, - getDocuments: this.props.loadDocuments, documents: this.props.documents, + getDocuments: this.props.loadDocuments, + uploadDocument: this.props.uploadDocument, }); } @@ -53,14 +54,16 @@ Building.propTypes = { buildingDetail: buildingDetailPropTypes, buildingId: PropTypes.string, loadBuildingDetail: PropTypes.func, - loadDocuments: PropTypes.func, documents: documentsPropType, + loadDocuments: PropTypes.func, + uploadDocument: PropTypes.func, }; function mapDispatchToProps(dispatch) { return bindActionCreators({ loadBuildingDetail, loadDocuments, + uploadDocument, }, dispatch); } diff --git a/src/containers/Documents/actions.js b/src/containers/Documents/actions.js index 56413bf0..3c8c901d 100644 --- a/src/containers/Documents/actions.js +++ b/src/containers/Documents/actions.js @@ -2,6 +2,9 @@ import { LOAD_DOCUMENTS, LOAD_DOCUMENTS_SUCCESS, LOAD_DOCUMENTS_ERROR, + UPLOAD_DOCUMENT, + UPLOAD_DOCUMENT_SUCCESS, + UPLOAD_DOCUMENT_ERROR, } from './constants'; export function loadDocuments(documentPath, fileKey) { @@ -26,3 +29,31 @@ export function documentsLoadingError(error) { error, }; } + +export function uploadDocument(buildingId, documentPath, document, tags, + name, fileKey) { + return { + type: UPLOAD_DOCUMENT, + buildingId, + documentPath, + document, + tags, + name, + fileKey, + }; +} + +export function documentUploaded(document, fileKey) { + return { + type: UPLOAD_DOCUMENT_SUCCESS, + document, + fileKey, + }; +} + +export function documentUploadError(error) { + return { + type: UPLOAD_DOCUMENT_ERROR, + error, + }; +} diff --git a/src/containers/Documents/constants.js b/src/containers/Documents/constants.js index 410e2a32..ef186ca8 100644 --- a/src/containers/Documents/constants.js +++ b/src/containers/Documents/constants.js @@ -1,3 +1,6 @@ export const LOAD_DOCUMENTS = 'LOAD_DOCUMENTS'; export const LOAD_DOCUMENTS_SUCCESS = 'LOAD_DOCUMENTS_SUCCESS'; export const LOAD_DOCUMENTS_ERROR = 'LOAD_DOCUMENTS_ERROR'; +export const UPLOAD_DOCUMENT = 'UPLOAD_DOCUMENT'; +export const UPLOAD_DOCUMENT_SUCCESS = 'UPLOAD_DOCUMENT_SUCCESS'; +export const UPLOAD_DOCUMENT_ERROR = 'UPLOAD_DOCUMENT_ERROR'; diff --git a/src/containers/Documents/reducer.js b/src/containers/Documents/reducer.js index 6f79f1b5..5f345d17 100644 --- a/src/containers/Documents/reducer.js +++ b/src/containers/Documents/reducer.js @@ -2,13 +2,18 @@ import { LOAD_DOCUMENTS, LOAD_DOCUMENTS_SUCCESS, LOAD_DOCUMENTS_ERROR, + UPLOAD_DOCUMENT, + UPLOAD_DOCUMENT_SUCCESS, + UPLOAD_DOCUMENT_ERROR, } from './constants'; const initState = { loading: false, error: false, + uploading: false, + uploadError: false, files: { - building: [], + building: [], // Root Directory utilityBills: [], // Utility_Bills buildingDimensions: [], // Building_Dimensions }, @@ -41,6 +46,32 @@ export default function (state = initState, action) { error: action.error, }; + case UPLOAD_DOCUMENT: + return { + ...state, + uploading: true, + uploadError: false, + }; + + case UPLOAD_DOCUMENT_SUCCESS: + return { + ...state, + uploading: false, + uploadError: false, + files: { + ...state.files, + [action.fileKey]: [...state.files[action.fileKey], + action.document.data.data], + }, + }; + + case UPLOAD_DOCUMENT_ERROR: + return { + ...state, + uploading: false, + uploadError: action.error, + }; + default: return state; } diff --git a/src/containers/Documents/sagas.js b/src/containers/Documents/sagas.js index 1af1dbd9..ee27b102 100644 --- a/src/containers/Documents/sagas.js +++ b/src/containers/Documents/sagas.js @@ -4,11 +4,14 @@ import { getHeaders, documentURL } from '../../utils/rest_services'; import { LOAD_DOCUMENTS, + UPLOAD_DOCUMENT, } from './constants'; import { documentsLoaded, documentsLoadingError, + documentUploaded, + documentUploadError, } from './actions'; @@ -30,6 +33,32 @@ function* getDocuments(action) { } } +function* uploadDocument(action) { + const { buildingId, documentPath, document, tags, name, fileKey } = action; + + const res = yield call( + request, + `${documentURL}`, { + method: 'POST', + headers: getHeaders(), + body: JSON.stringify({ + building_id: buildingId, + path: documentPath, + data: document, + name, + tags, + }), + } + ); + + if (!res.err) { + yield put(documentUploaded(res, fileKey)); + } else { + yield put(documentUploadError(res.err)); + } +} + export default function* () { yield takeLatest(LOAD_DOCUMENTS, getDocuments); + yield takeLatest(UPLOAD_DOCUMENT, uploadDocument); } -- GitLab From 0fa53d407eba7faf07f7e2bac5bfeab3f68f60a4 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Sun, 12 Feb 2017 17:25:25 -0500 Subject: [PATCH 06/14] Loading icon when uploading file --- src/components/BuildingOverview/index.js | 20 +++++-- src/components/DocumentCardViewer/grid.svg | 56 ++++++++++++++++++ src/components/DocumentCardViewer/index.js | 68 +++++++++++++--------- src/containers/Documents/reducer.js | 4 +- 4 files changed, 111 insertions(+), 37 deletions(-) create mode 100755 src/components/DocumentCardViewer/grid.svg diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverview/index.js index a3c1e06b..95617d23 100644 --- a/src/components/BuildingOverview/index.js +++ b/src/components/BuildingOverview/index.js @@ -12,6 +12,7 @@ export default class BuildingOverview extends Component { this.state = { documentPath: `/Buildings/${buildingId}_${building.address}/`, fileKey: 'building', + convertingFile: false, }; } @@ -19,11 +20,19 @@ export default class BuildingOverview extends Component { this.props.getDocuments(this.state.documentPath, this.state.fileKey); } - uploadDocumentHandler = (documentName, document) => { + uploadDocumentHandler = (file) => { const { buildingId } = this.props; const { documentPath, fileKey } = this.state; - this.props.uploadDocument(buildingId, documentPath, document, '', - documentName, fileKey); + + this.setState({ convertingFile: true }); + const fileReader = new FileReader(); + + fileReader.onload = function fileResults() { + this.setState({ convertingFile: false }); + this.props.uploadDocument(buildingId, documentPath, fileReader.result, '', + file.name, fileKey); + }.bind(this); + fileReader.readAsDataURL(file); } render() { @@ -44,10 +53,9 @@ export default class BuildingOverview extends Component {
); diff --git a/src/components/DocumentCardViewer/grid.svg b/src/components/DocumentCardViewer/grid.svg new file mode 100755 index 00000000..1834087d --- /dev/null +++ b/src/components/DocumentCardViewer/grid.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index 1b87a26c..b0e8c34d 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -1,7 +1,8 @@ import React, { Component, PropTypes } from 'react'; -import { documentProps } from '../../containers/Documents/propTypes'; +import documentsPropType from '../../containers/Documents/propTypes'; import DocumentCard from '../DocumentCard/'; import { uploadSVG } from '../bpl'; +import gridSVG from './grid.svg'; import './styles.css'; export default class DocumentCardViewer extends Component { @@ -14,20 +15,45 @@ export default class DocumentCardViewer extends Component { } uploadHandler = (event) => { - const file = event.target.files[0]; - const fileReader = new FileReader(); - fileReader.readAsDataURL(file); + this.props.uploadDocument(event.target.files[0]); + } + + renderUploadButton = () => { + let disabled = false; + let img = ( +
+ + Choose a file +
+ ); + if (this.props.uploadingFile) { + disabled = true; + img = ; + } - fileReader.onload = function fileResults() { - this.props.uploadDocument(file.name, fileReader.result); - }.bind(this); + return ( +
+ + +
+ ); } - renderDocuments() { - if (this.props.error) { + renderDocuments = () => { + if (this.props.documents.error) { return
; } - const docs = this.props.documents.map(item => ( + const { building } = this.props.documents.files; + const docs = building.map(item => (
@@ -41,19 +67,7 @@ export default class DocumentCardViewer extends Component {
Documents View all
-
- - -
+ { this.renderUploadButton() }
{ this.renderDocuments() }
); @@ -61,11 +75,7 @@ export default class DocumentCardViewer extends Component { } DocumentCardViewer.propTypes = { - // loading: PropTypes.bool, - error: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.string, - ]), - documents: PropTypes.arrayOf(documentProps), + documents: documentsPropType, uploadDocument: PropTypes.func, + uploadingFile: PropTypes.bool, }; diff --git a/src/containers/Documents/reducer.js b/src/containers/Documents/reducer.js index 5f345d17..b33e2bdf 100644 --- a/src/containers/Documents/reducer.js +++ b/src/containers/Documents/reducer.js @@ -60,8 +60,8 @@ export default function (state = initState, action) { uploadError: false, files: { ...state.files, - [action.fileKey]: [...state.files[action.fileKey], - action.document.data.data], + [action.fileKey]: [action.document.data.data, + ...state.files[action.fileKey]], }, }; -- GitLab From 0dd9af422f00bc75ee52926028cbed79ee355db9 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Sun, 12 Feb 2017 22:13:30 -0500 Subject: [PATCH 07/14] Move upload functions into document card viewer --- src/components/BuildingOverview/index.js | 30 +++++----------------- src/components/DocumentCardViewer/index.js | 30 +++++++++++++++++----- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverview/index.js index 95617d23..0ab95de0 100644 --- a/src/components/BuildingOverview/index.js +++ b/src/components/BuildingOverview/index.js @@ -16,27 +16,8 @@ export default class BuildingOverview extends Component { }; } - componentDidMount() { - this.props.getDocuments(this.state.documentPath, this.state.fileKey); - } - - uploadDocumentHandler = (file) => { - const { buildingId } = this.props; - const { documentPath, fileKey } = this.state; - - this.setState({ convertingFile: true }); - const fileReader = new FileReader(); - - fileReader.onload = function fileResults() { - this.setState({ convertingFile: false }); - this.props.uploadDocument(buildingId, documentPath, fileReader.result, '', - file.name, fileKey); - }.bind(this); - fileReader.readAsDataURL(file); - } - render() { - const { building, documents } = this.props; + const { building } = this.props; return (
@@ -53,9 +34,12 @@ export default class BuildingOverview extends Component {
); diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index b0e8c34d..a911b441 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -10,12 +10,27 @@ export default class DocumentCardViewer extends Component { super(props); this.state = { - files: [], + convertingFile: false, }; } + componentDidMount() { + this.props.getDocuments(this.props.documentPath, this.props.fileKey); + } + uploadHandler = (event) => { - this.props.uploadDocument(event.target.files[0]); + const file = event.target.files[0]; + const { buildingId, documentPath, fileKey } = this.props; + + this.setState({ convertingFile: true }); + const fileReader = new FileReader(); + + fileReader.onload = function fileResults() { + this.setState({ convertingFile: false }); + this.props.uploadDocument(buildingId, documentPath, fileReader.result, '', + file.name, fileKey); + }.bind(this); + fileReader.readAsDataURL(file); } renderUploadButton = () => { @@ -26,7 +41,7 @@ export default class DocumentCardViewer extends Component { Choose a file ); - if (this.props.uploadingFile) { + if (this.state.convertingFile || this.props.documents.uploading) { disabled = true; img = ; } @@ -75,7 +90,10 @@ export default class DocumentCardViewer extends Component { } DocumentCardViewer.propTypes = { - documents: documentsPropType, - uploadDocument: PropTypes.func, - uploadingFile: PropTypes.bool, + buildingId: PropTypes.string.isRequired, + documentPath: PropTypes.string.isRequired, + fileKey: PropTypes.string.isRequired, + documents: documentsPropType.isRequired, + getDocuments: PropTypes.func.isRequired, + uploadDocument: PropTypes.func.isRequired, }; -- GitLab From 1af99def2ab4b4d1c5a6ff0fb800421875327b93 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Sun, 12 Feb 2017 23:11:24 -0500 Subject: [PATCH 08/14] Add ErrorAlert component --- src/components/DocumentCardViewer/index.js | 7 +++++ src/components/ErrorAlert/index.js | 31 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/components/ErrorAlert/index.js diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index a911b441..a64fc562 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -1,6 +1,8 @@ import React, { Component, PropTypes } from 'react'; + import documentsPropType from '../../containers/Documents/propTypes'; import DocumentCard from '../DocumentCard/'; +import ErrorAlert from '../ErrorAlert'; import { uploadSVG } from '../bpl'; import gridSVG from './grid.svg'; import './styles.css'; @@ -77,8 +79,13 @@ export default class DocumentCardViewer extends Component { } render() { + const { error, uploadError } = this.props.documents; return (
+
Documents View all
diff --git a/src/components/ErrorAlert/index.js b/src/components/ErrorAlert/index.js new file mode 100644 index 00000000..c0862b7e --- /dev/null +++ b/src/components/ErrorAlert/index.js @@ -0,0 +1,31 @@ +import React, { PropTypes } from 'react'; + +const ErrorAlert = (props) => { + const { error, genericMessage } = props; + let errMessage = ''; + + if (error && genericMessage !== undefined) { + errMessage = `${genericMessage} | ${error.message}`; + } else if (error) { + errMessage = error.message; + } + + return ( +
+ {errMessage} +
+ ); +}; + +ErrorAlert.propTypes = { + error: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.instanceOf(Error), + ]).isRequired, + genericMessage: PropTypes.string, +}; + +export default ErrorAlert; -- GitLab From 1a7a7d4b333586278e47b1982c9fb909a82b55e6 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Mon, 13 Feb 2017 09:10:10 -0500 Subject: [PATCH 09/14] Display date in a human readable format --- src/components/DocumentCard/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/DocumentCard/index.js b/src/components/DocumentCard/index.js index 6abeacfa..077ffb23 100644 --- a/src/components/DocumentCard/index.js +++ b/src/components/DocumentCard/index.js @@ -12,6 +12,12 @@ class DocumentCard extends Component { render() { const { document } = this.props; + let date = ''; + if (document.updated !== null) { + date = `Last modified on ${new Date(document.updated)}`; + } else { + date = `Created on ${new Date(document.created)}`; + } return ( @@ -19,9 +25,7 @@ class DocumentCard extends Component { { document.tags !== '' ? {document.tags} : } - {document.updated !== null ? - `Last modified on ${document.updated}` : - `Created on ${document.created}`} + {date} ); } -- GitLab From 904cb8628ade07a69f085b9175b13ea865e078f4 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Mon, 13 Feb 2017 09:25:23 -0500 Subject: [PATCH 10/14] Center document cards --- src/components/DocumentCardViewer/styles.css | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/DocumentCardViewer/styles.css b/src/components/DocumentCardViewer/styles.css index 2e814cf6..2552bcb9 100644 --- a/src/components/DocumentCardViewer/styles.css +++ b/src/components/DocumentCardViewer/styles.css @@ -1,6 +1,6 @@ .documentCardViewer { /* TODO: Fix max height, 68px is height of navbar, 27px is the padding */ - max-height: calc(100vh - 68px - 27px); + max-height: calc(95vh - 68px - 27px); display: flex; flex-direction: column; } @@ -8,4 +8,6 @@ .scrollBox { overflow: auto; flex: 1; -} \ No newline at end of file + width: 95%; + margin: 0 auto; +} -- GitLab From f60d55379e5d450ff31ebfa0f3848ad0622d6bb8 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Mon, 13 Feb 2017 09:41:02 -0500 Subject: [PATCH 11/14] Remove unused variable from building overview state --- src/components/BuildingOverview/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverview/index.js index 0ab95de0..df9a359b 100644 --- a/src/components/BuildingOverview/index.js +++ b/src/components/BuildingOverview/index.js @@ -12,7 +12,6 @@ export default class BuildingOverview extends Component { this.state = { documentPath: `/Buildings/${buildingId}_${building.address}/`, fileKey: 'building', - convertingFile: false, }; } -- GitLab From 8f3c8e93748e1a7c446b4f76acff9beecc191be3 Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Mon, 13 Feb 2017 09:45:29 -0500 Subject: [PATCH 12/14] Convert DocumentCard to a stateless component --- src/components/DocumentCard/index.js | 46 +++++++++++----------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/src/components/DocumentCard/index.js b/src/components/DocumentCard/index.js index 077ffb23..562a3539 100644 --- a/src/components/DocumentCard/index.js +++ b/src/components/DocumentCard/index.js @@ -1,35 +1,25 @@ -import React, { Component } from 'react'; +import React from 'react'; import { documentProps } from '../../containers/Documents/propTypes'; -class DocumentCard extends Component { - constructor(props) { - super(props); - - this.state = { - uploading: false, - }; +const DocumentCard = (props) => { + const { document } = props; + let date = ''; + if (document.updated !== null) { + date = `Last modified on ${new Date(document.updated)}`; + } else { + date = `Created on ${new Date(document.created)}`; } - render() { - const { document } = this.props; - let date = ''; - if (document.updated !== null) { - date = `Last modified on ${new Date(document.updated)}`; - } else { - date = `Created on ${new Date(document.created)}`; - } - - return ( - - {document.name} - { document.tags !== '' - ? {document.tags} - : } - {date} - - ); - } -} + return ( + + {document.name} + { document.tags !== '' + ? {document.tags} + : } + {date} + + ); +}; DocumentCard.propTypes = { document: documentProps, -- GitLab From d696ce1d158107a52e364596b94c43726c2e268c Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Mon, 13 Feb 2017 15:33:53 -0500 Subject: [PATCH 13/14] Use blocpower loader --- src/components/DocumentCardViewer/grid.svg | 56 ---------------------- src/components/DocumentCardViewer/index.js | 10 +++- 2 files changed, 8 insertions(+), 58 deletions(-) delete mode 100755 src/components/DocumentCardViewer/grid.svg diff --git a/src/components/DocumentCardViewer/grid.svg b/src/components/DocumentCardViewer/grid.svg deleted file mode 100755 index 1834087d..00000000 --- a/src/components/DocumentCardViewer/grid.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index a64fc562..4f5cd938 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -4,7 +4,6 @@ import documentsPropType from '../../containers/Documents/propTypes'; import DocumentCard from '../DocumentCard/'; import ErrorAlert from '../ErrorAlert'; import { uploadSVG } from '../bpl'; -import gridSVG from './grid.svg'; import './styles.css'; export default class DocumentCardViewer extends Component { @@ -45,7 +44,14 @@ export default class DocumentCardViewer extends Component { ); if (this.state.convertingFile || this.props.documents.uploading) { disabled = true; - img = ; + img = ( +
+
+
+
+
+
+ ); } return ( -- GitLab From 2bcfc69486d72b51e04081788339a55771823e4e Mon Sep 17 00:00:00 2001 From: Alessandro DiMarco Date: Mon, 13 Feb 2017 16:22:46 -0500 Subject: [PATCH 14/14] Set link to hash in document card viewr --- src/components/DocumentCardViewer/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index 4f5cd938..a17ec11a 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -93,7 +93,8 @@ export default class DocumentCardViewer extends Component { genericMessage="There has been an error" />
Documents - View all + {/* eslint-disable jsx-a11y/href-no-hash */} + View all
{ this.renderUploadButton() }
{ this.renderDocuments() }
-- GitLab