From f1c5624fc48788fb0f6eb52a0e739b84ef19ea9c Mon Sep 17 00:00:00 2001 From: Conrad S Date: Mon, 20 Feb 2017 12:09:25 -0500 Subject: [PATCH 1/6] Update getDocuments to take in a list of paths --- src/components/DocumentCardViewer/index.js | 2 +- src/containers/Documents/actions.js | 4 ++-- src/containers/Documents/sagas.js | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/DocumentCardViewer/index.js b/src/components/DocumentCardViewer/index.js index 73a605e5..be850c0a 100644 --- a/src/components/DocumentCardViewer/index.js +++ b/src/components/DocumentCardViewer/index.js @@ -16,7 +16,7 @@ export default class DocumentCardViewer extends Component { } componentDidMount() { - this.props.getDocuments(this.props.documentPath, this.props.fileKey); + this.props.getDocuments([this.props.documentPath], this.props.fileKey); } uploadHandler = (event) => { diff --git a/src/containers/Documents/actions.js b/src/containers/Documents/actions.js index 3c8c901d..0af0a2a8 100644 --- a/src/containers/Documents/actions.js +++ b/src/containers/Documents/actions.js @@ -7,10 +7,10 @@ import { UPLOAD_DOCUMENT_ERROR, } from './constants'; -export function loadDocuments(documentPath, fileKey) { +export function loadDocuments(documentPaths, fileKey) { return { type: LOAD_DOCUMENTS, - documentPath, + documentPaths, fileKey, }; } diff --git a/src/containers/Documents/sagas.js b/src/containers/Documents/sagas.js index d6f28455..d984e9f3 100644 --- a/src/containers/Documents/sagas.js +++ b/src/containers/Documents/sagas.js @@ -16,11 +16,14 @@ import { function* getDocuments(action) { - const { documentPath, fileKey } = action; + const { documentPaths, fileKey } = action; + const pathsString = documentPaths.reduce((acc, val) => ( + `${acc}paths[]=${val}&` + ), ''); const res = yield call( request, - `${documentURL}?paths[]=${documentPath}`, { + `${documentURL}?${pathsString}`, { method: 'GET', headers: getHeaders(), } -- GitLab From 11befc25284e67f305cb6347380f1a2a5c302776 Mon Sep 17 00:00:00 2001 From: Conrad S Date: Tue, 21 Feb 2017 11:03:02 -0500 Subject: [PATCH 2/6] Add vertical tree of states and slots --- src/components/Project/defaultSlots.js | 414 +++++++++++++++++++++++++ src/components/Project/index.js | 170 +++++++++- src/containers/Building/sagas.js | 27 +- 3 files changed, 597 insertions(+), 14 deletions(-) create mode 100644 src/components/Project/defaultSlots.js diff --git a/src/components/Project/defaultSlots.js b/src/components/Project/defaultSlots.js new file mode 100644 index 00000000..0aaf5408 --- /dev/null +++ b/src/components/Project/defaultSlots.js @@ -0,0 +1,414 @@ +const defaultSlots = { + 3: { + name: 'Collect Forms', + id: 3, + description: 'Collect 12 Months of Utility Bills and 3 years of Income. Fill out business section of PNS form.', + slots: [ + { name: 'income-statements', title: 'Income Statements', folder_name: 'Income Statements', state_id: 3 }, + { name: 'sceep-forms', title: 'SCEEP Forms', folder_name: 'SCEEP Forms', state_id: 3 }, + { name: 'pea-reports', title: 'PEA Reports', folder_name: 'PEA Reports', state_id: 3 }, + { name: 'taxes', title: 'Taxes', folder_name: 'Taxes', state_id: 3 }, + { name: 'credit-reports', title: 'Credit Reports', folder_name: 'Credit Reports', state_id: 3 }, + { name: 'certificate-of-incorporation', title: 'Certificate of Incorporation', folder_name: 'Certificate of Incorporation', state_id: 3 }, + { name: 'bank-statements', title: 'Bank Statements', folder_name: 'Bank Statements', state_id: 3 }, + { name: '501(c)3-confirmation', title: '501(c)3 Confirmation', folder_name: '501(c)3 Confirmation', state_id: 3 }, + { name: 'proof-of-insurance', title: 'Proof of Property and Liability Insurance', folder_name: 'Proof of Property and Liability Insurance', state_id: 3 }, + { name: 'property-appraisal', title: 'Property Appraisal', folder_name: 'Property Appraisal', state_id: 3 }, + { name: 'title-of-location', title: 'Title of Location', folder_name: 'Title of Location', state_id: 3 }, + { name: 'misc', title: 'Miscellaneous', folder_name: 'Miscellaneous', state_id: 3 }, + ], + }, + + 4: { + name: 'Create Opportunity', + id: 4, + description: 'Create object on project dashboard with pending state. Create opportunity on salesforce.', + slots: [], + }, + + 5: { + name: 'Confirm Bill Validity', + id: 5, + description: 'Quality Assurance checks bills on dashboard are correct.', + slots: [], + }, + + 6: { + name: 'Confirm Validity of 3 Years of Income Statements ', + id: 6, + description: 'Finance does quality check on 3 Years of Income Statements on dashboard.', + slots: [ + { name: 'financial-reports', title: 'Financial Reports', folder_name: 'Financial Reports', state_id: 6 }, + { name: 'balance-sheets', title: 'Balance Sheets', folder_name: 'Balance Sheets', state_id: 6 }, + ], + }, + + + 7: { + name: 'Schedule Site Visit', + id: 7, + description: 'Schedule site visit with client and project engineer.', + slots: [], + }, + + + 8: { + name: 'Complete Business Development PNS', + id: 8, + description: 'Complete Business Development section of PNS form', + slots: [], + }, + + + 9: { + name: 'Business Development PNS Approval', + id: 9, + description: 'Business Development section of PNS form will go through approval.', + slots: [], + }, + + 10: { + name: 'Perform Remote Assessment', + id: 10, + description: 'Project Engineers perform remote assessment (Energy Watch, Code Violations, Google Earth, Heat Load Calculations).', + slots: [ + { name: 'breakdown-of-bills', title: 'Breakdown of Bills', folder_name: 'Breakdown of Bills', state_id: 10 }, + { name: 'heat-load', title: 'Engineering Models', folder_name: 'Engineering Models', state_id: 10 }, + ], + }, + + + 11: { + name: 'Complete Engineer PNS', + id: 11, + description: 'Complete Engineer section of PNS Form.', + slots: [], + }, + + + 12: { + name: 'Engineer PNS Approval', + id: 12, + description: 'Engineer section of the PNS form will go through approval.', + slots: [], + }, + + 13: { + name: 'Conduct Site Visit', + id: 13, + description: 'Project Engineer conducts site visit audit. All data entry is complete. Sensors are installed.', + slots: [ + { name: 'canvas', title: 'Canvas', folder_name: 'Canvas', state_id: 13 }, + { name: 'pictures', title: 'Pictures', folder_name: 'Pictures', state_id: 13 }, + { name: 'sketches', title: 'Sketches', folder_name: 'Sketches', state_id: 13 }, + { name: 'marketplace-photos', title: 'Marketplace Photos', folder_name: 'Marketplace Photos', state_id: 13 }, + ], + }, + + 14: { + name: 'Perform Initial Engineering Analysis', + id: 14, + description: 'Project Engineer performs energy efficiency calculations for annual savings.', + slots: [ + { name: 'pns', title: 'PNS Form', folder_name: 'PNS Form', state_id: 14 }, + { name: 'cooling-load', title: 'Engineering Models', folder_name: 'Engineering Models', state_id: 14 }, + ], + }, + + 15: { + name: 'Send Diagnostic Report', + id: 15, + description: 'Project Engineer creates diagnostic report.', + slots: [ + { name: 'diagnostic-report', title: 'Diagnostic Report', folder_name: 'Diagnostic Report', state_id: 15 }, + ], + }, + + + 16: { + name: 'Complete Finance PNS', + id: 16, + description: 'Complete Finance section of the PNS Form. This step does not have any dependencies. Must only be complete one month post site visit.', + slots: [], + }, + + + 17: { + name: 'Finance PNS Approval', + id: 17, + description: 'Finance section of the PNS form will go through approval.', + slots: [], + }, + + + 18: { + name: 'Send PNS Form', + id: 18, + description: 'Project Engineer sends client PNS Form.', + slots: [], + }, + + + 19: { + name: 'Follow Up Post Project Update', + id: 19, + description: 'Project Engineer contacts client to discover if client is interested in moving forward.', + slots: [], + }, + + 20: { + name: 'Outsource Retrofit', + id: 20, + description: 'Project Manager assesses potential outsourced retrofits (e.g. lighting and windows).', + slots: [ + { name: 'signed-quotes', title: 'Quotes', folder_name: 'Quotes', state_id: 20 }, + ], + }, + + + 21: { + name: 'HPD Finance', + id: 21, + description: 'Finance discovers if HPD will finance the project.', + slots: [], + }, + + + 22: { + name: 'Confirm Client wants HPD', + id: 22, + description: 'Finance confirms client wants to proceed with HPD program.', + slots: [], + }, + + 23: { + name: 'Preliminary Financial Analysis', + id: 23, + description: 'Run preliminary financial model and suggest budget range for Project Engineer.', + slots: [ + { name: 'financial-model', title: 'Financial Model', folder_name: 'Financial Model', state_id: 23 }, + { name: 'budget', title: 'Budget', folder_name: 'Budget', state_id: 23 }, + ], + }, + + + 24: { + name: 'Confirm Project Financing', + id: 24, + description: 'Finance decides if project is feasible.', + slots: [], + }, + + 25: { + name: 'Perform Detailed Calculations and Analysis', + id: 25, + description: 'Project Engineer runs models (hydronic, steam, cooling, heating, controls).', + slots: [ + { name: 'engineering-models', title: 'Engineering Models', folder_name: 'Engineering Models', state_id: 25 }, + ], + }, + + 26: { + name: 'Write Scope of Work Report', + id: 26, + description: 'Project Engineer selects desired equipment for retrofits.', + slots: [ + { name: 'scope-of-work', title: 'Scope of Work', folder_name: 'Scope of Work', state_id: 26 }, + ], + }, + + 27: { + name: 'Obtain Quotes', + id: 27, + description: 'Project Manager bundles nearby projects together and sends equipment lists to contractor to collect quotes and look for violations.', + slots: [ + { name: 'quotes', title: 'Quotes', folder_name: 'Quotes', state_id: 27 }, + ], + }, + + 28: { + name: 'Create Engineering Energy Output Model', + id: 28, + description: 'Project Engineer generates Engineering Output Model for suggested scenario.', + slots: [ + { name: 'engineering-output-model', title: 'Engineering Output Model', folder_name: 'Engineering Output Model', state_id: 28 }, + ], + }, + + 29: { + name: 'Create Financial Model', + id: 29, + description: 'Finance uses quotes and Engineering Output Model to run financial model for suggested scenario.', + slots: [ + { name: 'financial-model', title: 'Financial Model', folder_name: 'Financial Model', state_id: 29 }, + ], + }, + + 30: { + name: 'Create Client Presentation', + id: 30, + description: 'Project Engineer creates final presentation for various retrofit scenarios with upfront cost estimates and annual savings.', + slots: [ + { name: 'final-presentation', title: 'Final Presentation', folder_name: 'Final Presentation', state_id: 30 }, + ], + }, + + + 31: { + name: 'Schedule Client Presentation', + id: 31, + description: 'Project Manager coordinates with client, engineer, and finance/business to set up presentation date.', + slots: [], + }, + + + 32: { + name: 'Present to Client', + id: 32, + description: 'Project Engineer presents retrofit scenarios and financing options to client.', + slots: [], + }, + + + 33: { + name: 'Client Chooses Retrofits', + id: 33, + description: 'Project Engineer contacts Client to determine actionable retrofits. ', + slots: [], + }, + + 34: { + name: 'Redesign Scope of Work', + id: 34, + description: 'Project Engineer redesigns and finalizes scope of work.', + slots: [ + { name: 'redesigned-scope-of-work', title: 'Redesigned Scope of Work', folder_name: 'Redesigned Scope of Work', state_id: 34 }, + ], + }, + + + 35: { + name: 'Send Client Scope of Work and List of Contractors', + id: 35, + description: 'Client will be sent the scope of work and a list of contractors.', + slots: [], + }, + + 36: { + name: 'Finalize Quotes', + id: 36, + description: 'Project Engineer sends contractor Final Scope of Work and finalizes quotes. Contractor signs contract.', + slots: [ + { name: 'contractor-quotes', title: 'Contractor Quotes', folder_name: 'Contractor Quotes', state_id: 36 }, + ], + }, + + 37: { + name: 'Final Financial Model', + id: 37, + description: 'Finance runs the financial model to obtain actual costs including payback years.', + slots: [ + { name: 'final-financial-model', title: 'Final Financial Model', folder_name: 'Final Financial Model', state_id: 37 }, + ], + }, + + + 38: { + name: 'Update Client with Project Financing', + id: 38, + description: 'Finance contacts client to discuss financing options such as loans and marketplace.', + slots: [], + + }, + + + 39: { + name: 'Client Decides on Marketplace', + id: 39, + description: 'Client decides if they want to use Marketplace.', + slots: [], + }, + + + 40: { + name: 'Marketplace Content', + id: 40, + description: 'The Project content gets collected to prepare it for a Marketplace Launch.', + slots: [], + }, + + + 41: { + name: 'Marketplace', + id: 41, + description: 'The Project is launched on the Marketplace and is being funded.', + slots: [], + }, + + + 42: { + name: 'Contractor Downpayment', + id: 42, + description: 'A downpayment is payed to contractor.', + slots: [], + }, + + 43: { + name: 'Apply for Loan', + id: 43, + description: 'Finance appplies for loan.', + slots: [ + { name: 'nyserda', title: 'NYSERDA Request for Financing Form', folder_name: 'NYSERDA Request for Financing Form', state_id: 43 }, + { name: 'loan-application', title: 'Loan Application', folder_name: 'Loan Application', state_id: 43 }, + ], + }, + + 44: { + name: 'Approval of Underwriter', + id: 44, + description: 'Finance is notified that the loan was approved by the Underwriter (banks).', + slots: [], + }, + + 45: { + name: 'Confirm Funding', + id: 45, + description: 'Finance confirms project is funded.', + slots: [], + }, + + + 46: { + name: 'Commence Construction', + id: 46, + description: 'Construction Manager coordinates with client contractor, and engineers to schedule retrofit construction.', + slots: [], + }, + + + 47: { + name: 'Measurement and Verification', + id: 47, + description: 'Project Engineer collects sensor data during site visit, recalibrates sensors, and reinstalls sensors for "post retrofit" measurement and verification.', + slots: [], + }, + + + 48: { + name: 'Loan Payback', + id: 48, + description: 'Loan is in the process of being paid back.', + slots: [], + }, + + + 49: { + name: 'Completed', + id: 49, + description: 'Project is complete!', + slots: [], + }, + +}; + +export { defaultSlots as default }; diff --git a/src/components/Project/index.js b/src/components/Project/index.js index 6cad3ff3..4fae8cd1 100644 --- a/src/components/Project/index.js +++ b/src/components/Project/index.js @@ -1,18 +1,162 @@ -import React, { PropTypes } from 'react'; - /* eslint-disable */ -const Project = ({ buildingId }) => { - return ( -
- Coming Soon! -
- {buildingId} -
- ); -}; +import React, { Component, PropTypes } from 'react'; +import defaultSlots from './defaultSlots'; +import documentsPropType from '../../containers/Documents/propTypes'; +import { +// completeProjectPropTypes, + completeOverviewPropTypes, +} from '../../containers/Building/propTypes'; +import DocumentCard from '../DocumentCard/'; +import { uploadSVG } from '../bpl'; + +export default class Project extends Component { + constructor(props) { + super(props); + + const { building, buildingId } = this.props; + this.state = { + documentPath: `/Buildings/${buildingId}_${building.address}/`, + projectId: this.props.params.projectId, + fileKey: 'project', + convertingFile: false, + }; + } + + componentDidMount() { + // Get all of the files for thsi project + const pathList = Object.keys(defaultSlots).reduce((acc, state) => { + const paths = defaultSlots[state]["slots"].map(val => ( + `${this.state.documentPath}Project-${this.state.projectId}/${val.folder_name}` + )); + return acc.concat(paths); + }, []); + this.props.getDocuments(pathList, this.state.fileKey); + } + + uploadHandler = (event) => { + const file = event.target.files[0]; + const { buildingId } = this.props; + const fileKey = this.state.fileKey; + const documentPath = event.target.name; + 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 = (uploadPath) => { + let disabled = false; + let img = ( +
+ + Choose a file +
+ ); + if (this.state.convertingFile || this.props.documents.uploading) { + disabled = true; + img = ( +
+
+
+
+
+
+ ); + } + + return ( +
+ + +
+ ); + } + + renderDocuments = (documentList) => { + let docs =
+ if (documentList != null && documentList.length > 0) { + docs = documentList.map(item => ( +
+ +
+ )); + } + return docs; + } + + // Generate the HTML to show all of the files for a state + generateStateHTML = (stateId, slotToDocuments) => ( + defaultSlots[stateId]["slots"].map(val => { + const slotPath = `${this.state.documentPath}Project-${this.state.projectId}/${val.folder_name}`; + return ( +
+

{val.title}

+ {/* Pass the download path into the render upload button function */} + {this.renderUploadButton(slotPath)} + {/* Render the documents for this slot */} + {this.renderDocuments(slotToDocuments[slotPath])} +
+
+ ); + }) + ) + + generateDocumentHTML = () => { + // An object that given a slot path name, returns a list of documents + const slotToDocuments = this.props.documents.files.project.reduce((acc, val) => { + if (acc[val.path]) { + acc[val.path].push(val); + } else { + acc[val.path] = [val]; + } + return acc; + }, {}); + return Object.keys(defaultSlots).map(val => ( +
+

{`${val}. ${defaultSlots[val]['name']}`}

+
{defaultSlots[val]['description']}
+
+ {this.generateStateHTML(val, slotToDocuments)} +
+
+ )); + } + + render() { + return ( +
+
+
+ {this.generateDocumentHTML()} +
+
+
+ ); + } +} Project.propTypes = { buildingId: PropTypes.string, + building: completeOverviewPropTypes, + params: PropTypes.shape({ + projectId: PropTypes.string, + }), + // projects: completeProjectPropTypes, + documents: documentsPropType, + getDocuments: PropTypes.func, + uploadDocument: PropTypes.func, }; - -export default Project; diff --git a/src/containers/Building/sagas.js b/src/containers/Building/sagas.js index 5e5852a9..bab5c4c5 100644 --- a/src/containers/Building/sagas.js +++ b/src/containers/Building/sagas.js @@ -39,7 +39,32 @@ function* getProjects(action) { const buildingId = action.buildingId; const res = { buildingId, - data: [], + data: [ + { + client_id: 5, + created: '2016-04-29T19:25:08.509790+00:00', + id: 6, + name: '2324 Pitkin Avenue', + sales_force_id: '00661000009yx9lAAA', + slug: '2324-pitkin-avenue-6', + state: 'pending', + updated: null, + program_type: 'CBRA', + building_id: buildingId, + }, + { + client_id: 10, + created: '2016-04-29T19:25:08.509790+00:00', + id: 7, + name: '2324 Pitkin Avenue', + sales_force_id: '00661000009yx9lAAA', + slug: '2324-pitkin-avenue-6', + state: 'pending', + updated: null, + program_type: 'BUILD HEALTH', + building_id: buildingId, + }, + ], }; yield put(projectsLoaded(res)); -- GitLab From 21bbfc120832f85ca7f8c7b729dc5d21d954a82e Mon Sep 17 00:00:00 2001 From: Conrad S Date: Tue, 21 Feb 2017 11:26:04 -0500 Subject: [PATCH 3/6] Add validation for project exists --- src/components/Project/index.js | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/components/Project/index.js b/src/components/Project/index.js index 038805bb..82dedbe1 100644 --- a/src/components/Project/index.js +++ b/src/components/Project/index.js @@ -3,7 +3,7 @@ import React, { Component, PropTypes } from 'react'; import defaultSlots from './defaultSlots'; import documentsPropType from '../../containers/Documents/propTypes'; import { -// completeProjectPropTypes, + completeProjectPropTypes, completeOverviewPropTypes, } from '../../containers/Building/propTypes'; import DocumentCard from '../DocumentCard/'; @@ -138,10 +138,34 @@ export default class Project extends Component { } render() { + const projectExists = this.props.projects["list"].reduce((acc, val) => ( + acc || val.id == this.props.params.projectId + ), false); + if (!projectExists) { + return ( +
+ +
+
+
+ This project does not exist +
+
+
+
+ ) + } return (
Date: Tue, 21 Feb 2017 11:26:34 -0500 Subject: [PATCH 4/6] Add semicolon --- src/components/Project/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Project/index.js b/src/components/Project/index.js index 82dedbe1..0280c4ab 100644 --- a/src/components/Project/index.js +++ b/src/components/Project/index.js @@ -160,7 +160,7 @@ export default class Project extends Component {
- ) + ); } return (
-- GitLab From b4b5fdeebb55bbf37a56d5d78ef42240d7e035f8 Mon Sep 17 00:00:00 2001 From: Conrad S Date: Tue, 21 Feb 2017 11:28:37 -0500 Subject: [PATCH 5/6] Add project id to breadcrumb title --- src/components/Project/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Project/index.js b/src/components/Project/index.js index 0280c4ab..fd57546a 100644 --- a/src/components/Project/index.js +++ b/src/components/Project/index.js @@ -148,7 +148,7 @@ export default class Project extends Component { building={this.props.building} breadcrumbs={[ { name: 'Overview', url: '' }, - { name: 'Project', url: 'null' }, + { name: `Project ${this.props.params.projectId}`, url: 'null' }, ]} links={[]} /> @@ -168,7 +168,7 @@ export default class Project extends Component { building={this.props.building} breadcrumbs={[ { name: 'Overview', url: '' }, - { name: 'Project', url: 'null' }, + { name: `Project ${this.props.params.projectId}`, url: 'null' }, ]} links={[]} /> -- GitLab From 4cf087778cdd23f3e85f05d3ccaa7c95b530704c Mon Sep 17 00:00:00 2001 From: Conrad S Date: Wed, 22 Feb 2017 10:21:01 -0500 Subject: [PATCH 6/6] Update to reflect es-lint and PR --- src/components/Project/defaultSlots.js | 2 +- src/components/Project/index.js | 113 ++++++++++--------------- 2 files changed, 48 insertions(+), 67 deletions(-) diff --git a/src/components/Project/defaultSlots.js b/src/components/Project/defaultSlots.js index 0aaf5408..d2af4ccc 100644 --- a/src/components/Project/defaultSlots.js +++ b/src/components/Project/defaultSlots.js @@ -411,4 +411,4 @@ const defaultSlots = { }; -export { defaultSlots as default }; +export default defaultSlots; diff --git a/src/components/Project/index.js b/src/components/Project/index.js index fd57546a..a7cceffe 100644 --- a/src/components/Project/index.js +++ b/src/components/Project/index.js @@ -1,4 +1,3 @@ -/* eslint-disable */ import React, { Component, PropTypes } from 'react'; import defaultSlots from './defaultSlots'; import documentsPropType from '../../containers/Documents/propTypes'; @@ -26,7 +25,7 @@ export default class Project extends Component { componentDidMount() { // Get all of the files for thsi project const pathList = Object.keys(defaultSlots).reduce((acc, state) => { - const paths = defaultSlots[state]["slots"].map(val => ( + const paths = defaultSlots[state].slots.map(val => ( `${this.state.documentPath}Project-${this.state.projectId}/${val.folder_name}` )); return acc.concat(paths); @@ -50,6 +49,46 @@ export default class Project extends Component { fileReader.readAsDataURL(file); } + + // Generate the HTML to show all of the files for a state + generateStateHTML = (stateId, slotToDocuments) => ( + defaultSlots[stateId].slots.map((val) => { + const slotPath = `${this.state.documentPath}Project-${this.state.projectId}/${val.folder_name}`; + return ( +
+

{val.title}

+ {/* Pass the download path into the render upload button function */} + {this.renderUploadButton(slotPath)} + {/* Render the documents for this slot */} + {this.renderDocuments(slotToDocuments[slotPath])} +
+
+ ); + }) + ) + + generateDocumentHTML = () => { + // An object that given a slot path name, returns a list of documents + const slotToDocuments = this.props.documents.files.project.reduce((acc, val) => { + const newAcc = acc; + if (acc[val.path]) { + newAcc[val.path].push(val); + } else { + newAcc[val.path] = [val]; + } + return acc; + }, {}); + return Object.keys(defaultSlots).map(val => ( +
+

{`${val}. ${defaultSlots[val].name}`}

+
{defaultSlots[val].description}
+
+ {this.generateStateHTML(val, slotToDocuments)} +
+
+ )); + } + renderUploadButton = (uploadPath) => { let disabled = false; let img = ( @@ -88,8 +127,8 @@ export default class Project extends Component { } renderDocuments = (documentList) => { - let docs =
- if (documentList != null && documentList.length > 0) { + let docs =
; + if (documentList != null && documentList.length > 0) { docs = documentList.map(item => (
@@ -99,69 +138,11 @@ export default class Project extends Component { return docs; } - // Generate the HTML to show all of the files for a state - generateStateHTML = (stateId, slotToDocuments) => ( - defaultSlots[stateId]["slots"].map(val => { - const slotPath = `${this.state.documentPath}Project-${this.state.projectId}/${val.folder_name}`; - return ( -
-

{val.title}

- {/* Pass the download path into the render upload button function */} - {this.renderUploadButton(slotPath)} - {/* Render the documents for this slot */} - {this.renderDocuments(slotToDocuments[slotPath])} -
-
- ); - }) - ) - - generateDocumentHTML = () => { - // An object that given a slot path name, returns a list of documents - const slotToDocuments = this.props.documents.files.project.reduce((acc, val) => { - if (acc[val.path]) { - acc[val.path].push(val); - } else { - acc[val.path] = [val]; - } - return acc; - }, {}); - return Object.keys(defaultSlots).map(val => ( -
-

{`${val}. ${defaultSlots[val]['name']}`}

-
{defaultSlots[val]['description']}
-
- {this.generateStateHTML(val, slotToDocuments)} -
-
- )); - } - render() { - const projectExists = this.props.projects["list"].reduce((acc, val) => ( - acc || val.id == this.props.params.projectId + /* eslint-disable eqeqeq */ + const projectExists = this.props.projects.list.reduce((acc, val) => ( + acc || (val.id == this.props.params.projectId) ), false); - if (!projectExists) { - return ( -
- -
-
-
- This project does not exist -
-
-
-
- ); - } return (
- {this.generateDocumentHTML()} + {projectExists ? this.generateDocumentHTML() : 'This project does not exist'}
-- GitLab