Skip to content

Commit 15da8c9

Browse files
authored
Merge pull request #191 from yasirunilan/master
fixed the issue #143 and #146
2 parents f9c6305 + 2a39d89 commit 15da8c9

File tree

9 files changed

+352
-32
lines changed

9 files changed

+352
-32
lines changed

client/src/components/CandidateFileUpload/CandidateFileUpload.jsx

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import DoneOutline from '@material-ui/icons/DoneOutline';
1212
import CloseIcon from '@material-ui/icons/Cancel';
1313
import { API_BASE_URL } from "../../config.js";
1414
import axios from "axios";
15+
import download from 'downloadjs';
1516

1617

1718

@@ -177,6 +178,15 @@ componentDidMount() {
177178
}
178179
};
179180

181+
handleFileDownload = (doc) => {
182+
axios.get(`${API_BASE_URL}/nominations/candidates/${this.props.index}/support-docs/${doc.id}/download`, {responseType: 'blob'}, {
183+
}).then((response) => {
184+
download(new Blob([response.data]), doc.originalname, response.headers['content-type']);
185+
}).catch(err => {
186+
console.log(err)
187+
});
188+
};
189+
180190
handleChangeButton = (e) => {
181191
const { onCloseModal } = this.props;
182192
if(e.currentTarget.value==="Submit&Clouse"){
@@ -234,20 +244,20 @@ componentDidMount() {
234244
<Grid item lg={6}>
235245
{docs.doc}
236246
</Grid>
237-
<Grid item lg={4}>
238-
<FileUpload value={docs.id} doneElement={doneElement} onSelectFiles={this.onSelectFiles} />
239-
{
240-
this.state.supportdoc.map(sdoc => (
241-
sdoc.id === docs.id ?
242-
<Typography variant="caption" gutterBottom>
243-
{sdoc.originalname}<div className={classes.done}>
244-
<CloseIcon ref={this.state.currentSdocId} onClick={this.handleRese} color="red"/>
245-
</div>
246-
</Typography>
247-
: ' '
248-
))
249-
}
250-
</Grid>
247+
<Grid item lg={4}>
248+
<FileUpload value={docs.id} doneElement={doneElement} onSelectFiles={this.onSelectFiles} />
249+
{
250+
this.state.supportdoc.map(sdoc => (
251+
sdoc.id === docs.id ?
252+
<Typography variant="caption" gutterBottom style={{cursor: 'pointer'}} onClick={() => { this.handleFileDownload(sdoc) }}>
253+
{sdoc.originalname}<div className={classes.done}>
254+
<CloseIcon ref={this.state.currentSdocId} onClick={this.handleRese} color="red"/>
255+
</div>
256+
</Typography>
257+
: ' '
258+
))
259+
}
260+
</Grid>
251261

252262
<Grid item lg={12}>
253263
<Divider className={classes.divider} variant="middle"/>

client/src/components/NominationStep3/NominationStep3.jsx

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import { createAndDownloadPdfPresidentialNominationForm, createAndDownloadPdfPar
1414
import ProgressButton from "../ProgressButton";
1515
import DoneOutline from '@material-ui/icons/DoneOutline';
1616
import CloseIcon from '@material-ui/icons/Cancel';
17+
import axios from "axios";
18+
import {API_BASE_URL} from "../../config";
19+
import download from "downloadjs";
1720

1821
const styles = theme => ({
1922
container: {
@@ -93,6 +96,15 @@ class TextFields extends React.Component {
9396
var filesArray = this.state.files;
9497
};
9598

99+
handleFileDownload = (doc) => {
100+
axios.get(`${API_BASE_URL}/nominations/${this.props.customProps}/support-docs/${doc.id}/download`, {responseType: 'blob'}, {
101+
}).then((response) => {
102+
download(new Blob([response.data]), doc.originalname, response.headers['content-type']);
103+
}).catch(err => {
104+
console.log(err)
105+
});
106+
};
107+
96108

97109

98110
handlePdfGenarationButton = (e) => {
@@ -158,21 +170,19 @@ class TextFields extends React.Component {
158170
</Grid>
159171
<Grid item lg={2}>
160172
<span ><FileUpload value={docs.id} doneElement={doneElement} onSelectFiles={onSelectFiles} /></span>
161-
162-
</Grid>
163-
<Grid style={{marginLeft:-44}} item lg={1}>
164-
{
165-
supportdoc.map(sdoc => (
166-
sdoc.id === docs.id ?
167-
<Typography variant="caption" gutterBottom>
168-
{sdoc.originalname}<div className={classes.done}>
169-
<CloseIcon color="red"/>
170-
</div>
171-
</Typography>
172-
: ' '
173-
))
174-
}
173+
175174
</Grid>
175+
{
176+
supportdoc.map(sdoc => (
177+
sdoc.id === docs.id ?
178+
<Typography variant="caption" gutterBottom style={{cursor: 'pointer'}} onClick={() => { this.handleFileDownload(sdoc) }}>
179+
{sdoc.originalname}<div className={classes.done}>
180+
<CloseIcon color="red"/>
181+
</div>
182+
</Typography>
183+
: ' '
184+
))
185+
}
176186
{/* {docs.id === 'b20dd58c-e5bb-469d-98c9-8711d6da1879' ?
177187
<Grid item lg={5}>
178188
<span><FileUpload style={{textAlign: 'right'}} value={docs.id} doneElement={doneElement} onSelectFiles={onSelectFiles} /></span>

client/src/modules/nomination/Nomination_review.jsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import CommentIcon from '@material-ui/icons/InsertComment';
4141
import IconButton from "@material-ui/core/IconButton";
4242
import Slide from '@material-ui/core/Slide';
4343
import TextField from '@material-ui/core/TextField';
44+
import axios from "axios";
45+
import {API_BASE_URL} from "../../config";
46+
import download from "downloadjs";
47+
import GetAppIcon from '@material-ui/icons/GetApp';
4448

4549
const drawerWidth = 240;
4650

@@ -230,6 +234,25 @@ class NominationReview extends React.Component {
230234
[name]: event.target.value,
231235
});
232236
};
237+
238+
downloadCandidateDocuments = (candidate) => {
239+
axios.get(`${API_BASE_URL}/nominations/candidates/${candidate.id}/support-docs/download`, {responseType: 'blob'}, {
240+
}).then((response) => {
241+
download(new Blob([response.data]), 'candidate_support_docs_'+candidate.id+'.zip', response.headers['content-type']);
242+
}).catch(err => {
243+
console.log(err)
244+
});
245+
};
246+
247+
downloadNominationDocuments = (nomination) => {
248+
axios.get(`${API_BASE_URL}/nominations/${nomination.id}/support-docs/download`, {responseType: 'blob'}, {
249+
}).then((response) => {
250+
download(new Blob([response.data]), 'nomination_support_docs_'+nomination.id+'.zip', response.headers['content-type']);
251+
}).catch(err => {
252+
console.log(err)
253+
});
254+
};
255+
233256
render() {
234257
const { classes, nominations, ApproveElections, partyList } = this.props;
235258
const { expandedPanelIndex } = this.state;
@@ -270,6 +293,9 @@ class NominationReview extends React.Component {
270293
<TableCell className={classes.candidate_table_cell} align="left">
271294
{candidate.address}
272295
</TableCell>
296+
<TableCell onClick={() => { this.downloadCandidateDocuments(candidate) }} className={classes.candidate_table_cell} align="left">
297+
<GetAppIcon style={{marginRight:10,marginBottom:-2}} className={classes.left_icon} />
298+
</TableCell>
273299
</TableRow>
274300
</React.Fragment>
275301
);
@@ -321,6 +347,7 @@ class NominationReview extends React.Component {
321347
<TableCell align="left">Full Name</TableCell>
322348
<TableCell align="left">Occupation</TableCell>
323349
<TableCell align="left">Address</TableCell>
350+
<TableCell align="left">Documents</TableCell>
324351
</TableHead>
325352
<TableBody>
326353
{
@@ -360,6 +387,11 @@ class NominationReview extends React.Component {
360387
</Grid>
361388
<br />
362389
</ExpansionPanelDetails>
390+
<Button
391+
onClick={() => { this.downloadNominationDocuments(nomination) }}
392+
className={classNames(classes.button, classes.green_button)}>Download Nomination Documents
393+
<GetAppIcon style={{marginRight:10,marginBottom:-2}} className={classes.left_icon} />
394+
</Button>
363395
</ExpansionPanel>
364396
));
365397

server/api-docs/swagger.yaml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,74 @@ paths:
550550
description: ''
551551
x-auth-type: Application & Application User
552552
x-throttling-tier: Unlimited
553+
'/payments/{paymentId}/download':
554+
get:
555+
parameters:
556+
- name: paymentId
557+
in: path
558+
required: true
559+
type: string
560+
responses:
561+
'200':
562+
description: ''
563+
x-auth-type: Application & Application User
564+
x-throttling-tier: Unlimited
565+
'/nominations/candidates/{candidateId}/support-docs/{documentId}/download':
566+
get:
567+
parameters:
568+
- name: candidateId
569+
in: path
570+
required: true
571+
type: string
572+
- name: documentId
573+
in: path
574+
required: true
575+
type: string
576+
responses:
577+
'200':
578+
description: ''
579+
x-auth-type: Application & Application User
580+
x-throttling-tier: Unlimited
581+
'/nominations/{nominationId}/support-docs/{documentId}/download':
582+
get:
583+
parameters:
584+
- name: nominationId
585+
in: path
586+
required: true
587+
type: string
588+
- name: documentId
589+
in: path
590+
required: true
591+
type: string
592+
responses:
593+
'200':
594+
description: ''
595+
x-auth-type: Application & Application User
596+
x-throttling-tier: Unlimited
597+
'/nominations/candidates/{candidateId}/support-docs/download':
598+
get:
599+
parameters:
600+
- name: candidateId
601+
in: path
602+
required: true
603+
type: string
604+
responses:
605+
'200':
606+
description: ''
607+
x-auth-type: Application & Application User
608+
x-throttling-tier: Unlimited
609+
'/nominations/{nominationId}/support-docs/download':
610+
get:
611+
parameters:
612+
- name: nominationId
613+
in: path
614+
required: true
615+
type: string
616+
responses:
617+
'200':
618+
description: ''
619+
x-auth-type: Application & Application User
620+
x-throttling-tier: Unlimited
553621
info:
554622
title: Nomination
555623
version: '0.9'

server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"dotenv": "^2.0.0",
4343
"express": "^4.14.0",
4444
"express-fileupload": "^1.1.1-alpha.1",
45+
"express-zip": "^3.0.0",
4546
"flow-runtime": "^0.2.1",
4647
"fraction.js": "^3.3.1",
4748
"globule": "^1.1.0",

server/src/repository/supportdoc.js

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,34 @@ const PAYMENT_SUPPORT_DOC_SELECT_QUERY = `SELECT
6868
ORIGINAL_NAME AS SUPPORT_DOC_originalname,
6969
FILE_PATH AS SUPPORT_DOC_filename
7070
FROM PAYMENT_SUPPORT_DOC WHERE PAYMENT_ID=:paymentId AND STATUS = 'NEW' LIMIT 1`;
71-
71+
72+
73+
const CANDIDATE_SUPPORT_DOC_BY_DOC_ID_AND_CANDIDATE_ID_SELECT_QUERY = `SELECT
74+
ID AS SUPPORT_DOC_id,
75+
ORIGINAL_NAME AS SUPPORT_DOC_originalname,
76+
FILE_PATH AS SUPPORT_DOC_filename
77+
FROM CANDIDATE_SUPPORT_DOC WHERE SUPPORT_DOC_CONFIG_ID=:documentId AND CANDIDATE_ID=:candidateId`;
78+
79+
const CANDIDATE_SUPPORT_DOC_BY_DOC_ID_AND_NOMINATION_ID_SELECT_QUERY = `SELECT
80+
ID AS SUPPORT_DOC_id,
81+
ORIGINAL_NAME AS SUPPORT_DOC_originalname,
82+
FILE_PATH AS SUPPORT_DOC_filename
83+
FROM NOMINATION_SUPPORT_DOC WHERE SUPPORT_DOC_CONFIG_ID=:documentId AND NOMINATION_ID=:nominationId`;
84+
85+
86+
const CANDIDATE_SUPPORT_DOCS_BY_CANDIDATE_ID_SELECT_QUERY = `SELECT
87+
ID AS SUPPORT_DOC_id,
88+
ORIGINAL_NAME AS SUPPORT_DOC_originalname,
89+
FILE_PATH AS SUPPORT_DOC_filename
90+
FROM CANDIDATE_SUPPORT_DOC WHERE CANDIDATE_ID=:candidateId`;
91+
92+
93+
const CANDIDATE_SUPPORT_DOCS_BY_NOMINATION_ID_SELECT_QUERY = `SELECT
94+
ID AS SUPPORT_DOC_id,
95+
ORIGINAL_NAME AS SUPPORT_DOC_originalname,
96+
FILE_PATH AS SUPPORT_DOC_filename
97+
FROM NOMINATION_SUPPORT_DOC WHERE NOMINATION_ID=:nominationId`;
98+
7299
const getSupportDocByNomination = (nominationId) => {
73100
const params = { nominationId: nominationId };
74101
return DbConnection()
@@ -191,6 +218,55 @@ const getSupportDocByPayment = (paymentId) => {
191218
});
192219
}
193220

221+
const getSupportDocByCandidateIdAndDocId = (documentId, candidateId) => {
222+
const params = { documentId: documentId, candidateId: candidateId };
223+
return DbConnection()
224+
.query(CANDIDATE_SUPPORT_DOC_BY_DOC_ID_AND_CANDIDATE_ID_SELECT_QUERY,
225+
{
226+
replacements: params,
227+
type: DbConnection().QueryTypes.SELECT,
228+
}).catch((error) => {
229+
throw new DBError(error);
230+
});
231+
}
232+
233+
const getSupportDocByNominationIdAndDocId = (documentId, nominationId) => {
234+
const params = { documentId: documentId, nominationId: nominationId };
235+
return DbConnection()
236+
.query(CANDIDATE_SUPPORT_DOC_BY_DOC_ID_AND_NOMINATION_ID_SELECT_QUERY,
237+
{
238+
replacements: params,
239+
type: DbConnection().QueryTypes.SELECT,
240+
}).catch((error) => {
241+
throw new DBError(error);
242+
});
243+
}
244+
245+
const getSupportDocsByCandidateId = (candidateId) => {
246+
const params = { candidateId: candidateId };
247+
return DbConnection()
248+
.query(CANDIDATE_SUPPORT_DOCS_BY_CANDIDATE_ID_SELECT_QUERY,
249+
{
250+
replacements: params,
251+
type: DbConnection().QueryTypes.SELECT,
252+
}).catch((error) => {
253+
throw new DBError(error);
254+
});
255+
}
256+
257+
258+
const getSupportDocsByNominationId = (nominationId) => {
259+
const params = { nominationId: nominationId };
260+
return DbConnection()
261+
.query(CANDIDATE_SUPPORT_DOCS_BY_NOMINATION_ID_SELECT_QUERY,
262+
{
263+
replacements: params,
264+
type: DbConnection().QueryTypes.SELECT,
265+
}).catch((error) => {
266+
throw new DBError(error);
267+
});
268+
}
269+
194270

195271

196272

@@ -269,5 +345,9 @@ export default {
269345
getSupportDocByCandidate,
270346
savePaymentSupportDocs,
271347
updatePaymentSupportDocs,
272-
getSupportDocByPayment
348+
getSupportDocByPayment,
349+
getSupportDocByCandidateIdAndDocId,
350+
getSupportDocByNominationIdAndDocId,
351+
getSupportDocsByCandidateId,
352+
getSupportDocsByNominationId
273353
}

server/src/routes/constants/URLSchema.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ export const URL_SCHEMA = Joi.object().keys({
1919
templateName: Joi.string(),
2020
keyName: Joi.string(),
2121
sid: Joi.string(),
22-
teamType: Joi.string()
22+
teamType: Joi.string(),
23+
documentId: Joi.string().max(36).regex(/^[A-Za-z0-9-]+$/)
2324
});

0 commit comments

Comments
 (0)