Skip to content

Commit

Permalink
Feature to download Bahmni form builder forms as a PDF (#76)
Browse files Browse the repository at this point in the history
* [PrintForm] | Chiran, Natheesh | Add UI for form printer

Co-authored-by: Chiranjeewee <[email protected]>

* [PrintForm] | Chiranjeewee, Natheeshkumar, Rushikesh, Rachana, Pranav | Fix download url for pdf

Co-authored-by: Rachana <[email protected]> | Chiranjeewee Koirala <[email protected]> | Natheeshkumar <[email protected]> | Pranav Sricharan <[email protected]>

* [PrintForm] | Chiran, Natheesh | Fix download button status

Co-authored-by: Chiranjeewee <[email protected]>

* [PrintForm] | Sameera, Priya | Added a new button to download a pdf of a form

* Removing extra files

* added yarn.lock

* Updated. yarn.lock

* Fix. test failures

* Fix. ESlint Indentation and spacing error

---------

Co-authored-by: Natheeshkumar <[email protected]>
Co-authored-by: Chiranjeewee <[email protected]>
Co-authored-by: RishiHalle <[email protected]>
Co-authored-by: Rachana <[email protected]> | Chiranjeewee Koirala <[email protected]> | Natheeshkumar <[email protected]> | Pranav Sricharan <[email protected]>
Co-authored-by: praveenadayanand <[email protected]>
Co-authored-by: SanoferSameera <[email protected]>
  • Loading branch information
7 people authored Dec 1, 2023
1 parent e4b8159 commit 04352c7
Show file tree
Hide file tree
Showing 10 changed files with 421 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"stylelint-webpack-plugin": "^0.5.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.1",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^1.14.1"
},
"dependencies": {
Expand Down
4 changes: 4 additions & 0 deletions src/common/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const Dashboard = () =>
<i className="fa fa-user-secret"></i>
Form Builder
</Link>
<Link to="form-printer">
<i className="fa fa-user-secret"></i>
Print Form
</Link>
</div>
</div>;

Expand Down
35 changes: 34 additions & 1 deletion src/form-builder/components/FormList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,19 @@ export default class FormList extends Component {
<td>
<b className="edit-icon">{this._editOrReuseIcon(rowItem)}</b>
<a hidden={!rowItem.published}
onClick={() => this.downloadFile(index)}
onClick={() => this.downloadFile(index)} title="Export Form"
>
<i className="fa fa-download" title="Export Form" />
</a>
<b className="translate-icon" hidden={!rowItem.isLatestPublished}>
{this._translateIcon(rowItem)}</b>
<b className="privilege-icon" hidden={!rowItem.published}>
{this._privilegesIcon(rowItem)}</b>
<a hidden={!rowItem.published}
onClick={() => this.pdfPreview(index)}
>
<i className="fa fa-file-pdf-o" title="Download PDF Form" />
</a>
</td>
</tr>
));
Expand All @@ -56,6 +61,34 @@ export default class FormList extends Component {
}, commonConstants.toastTimeout);
}

downloadPDFFile(index) {
const form = this.props.data[index];
const params =
'v=custom:(id,uuid,name,version,published,auditInfo,' +
'resources:(value,dataType,uuid))';
const fileName = `${form.name}_${form.version}`;
httpInterceptor
.get(`${formBuilderConstants.formUrl}/${form.uuid}?${params}`)
.then((formJson) => {
const translationParams =
`formName=${form.name}&formVersion=${form.version}&formUuid=${form.uuid}`;
httpInterceptor.get(`${formBuilderConstants.translationsUrl}?${translationParams}`)
.then((translations) => {
const formData = { formJson, translations };
console.log(formData);
try {
httpInterceptor.post(formBuilderConstants.jsonToPdfConvertionUrl, formData).then((response) => {
let fileName = response.pdfName;
const link = formBuilderConstants.pdfDownloadUrl + fileName;
window.open(`/pdf/${fileName}`, '_self');
});
} catch (error) {
console.log('error state');
}
});
});
}

downloadFile(index) {
const form = this.props.data[index];
const params =
Expand Down
84 changes: 84 additions & 0 deletions src/form-builder/components/FormPrinterContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { Component } from 'react';
import FormBuilderHeader from 'form-builder/components/FormBuilderHeader.jsx';
import PdfList from 'form-builder/components/PdfList.jsx';
import { httpInterceptor } from 'common/utils/httpInterceptor';
import { formBuilderConstants } from 'form-builder/constants';

class FormPrinterContainer extends Component {

constructor(props) {
super(props);
this.state = {
selectedFile: '',
downloadLink: '',
importBtnStatus: '',
status: 'Processing',
};
this.onFileChange = this.onFileChange.bind(this);
this.onFileUpload = this.onFileUpload.bind(this);
}
onFileChange(event) {
event.preventDefault();
this.setState({ selectedFile: event.target.files[0] });
}

onFileUpload(event) {
let file = this.state.selectedFile;
this.setState({ importBtnStatus: 'clicked' });
const self = this;
const reader = new FileReader();
// eslint-disable-next-line
reader.onload = function () {
try {
const formData = JSON.parse(reader.result);
httpInterceptor.post(formBuilderConstants.jsonToPdfConvertionUrl, formData).then((response) => {
let fileName = response.pdfName;
let link = formBuilderConstants.pdfDownloadUrl + fileName;
self.setState({ downloadLink: link });
self.setState({ status: 'Completed' });
});
} catch (error) {
self.setState({ status: 'Error' });
}
};
reader.readAsText(file);
}


render() {
return (
<div>
<div>
<FormBuilderHeader />
</div>
<div className="breadcrumb-wrap">
<div className="breadcrumb-inner">
<div style={{ display: 'flex', flexWrap: 'nowrap' }}>
<label htmlFor="jsonName" style={{ paddingTop: '5px', marginRight: '10px' }}>Import JSON file:</label>
<input type="text" id="jsonName" name="jsonName" value={this.state.selectedFile.name} readOnly />
<label htmlFor="files" className="button">Add</label>
<input id="files" style={{ visibility: 'collapse' }} type="file" accept=".json" onChange={this.onFileChange} />
{this.state.selectedFile != '' && <button className="btn--highlight" onClick={this.onFileUpload}>
Import
</button>}

</div>
</div>

{this.state.importBtnStatus != '' && <div>
<div className="container-content-wrap">
<div className="container-content">
<div className="container-main form-list">
<h2 className="header-title">Generated PDF's</h2>
<PdfList downloadLink={this.state.downloadLink} status={this.state.status} />
</div>
</div>
</div>
</div>}

</div>
</div >
);
}
}
export default FormPrinterContainer;
36 changes: 36 additions & 0 deletions src/form-builder/components/PdfList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { Component } from 'react';

export default class FormList extends Component {
constructor(props) {
super(props);

this.downloadFile = this.downloadFile.bind(this);
}
downloadFile() {
window.open(this.props.downloadLink);
}
render() {
return (
<div>
<table>
<thead>
<tr>
<th>Form Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>

<tr >
<td>{this.props.status}</td>
<td>
<button onClick={this.downloadFile} disabled={this.props.status != 'Completed'} >Download</button>
</td>
</tr>

</tbody>
</table>
</div>
);
}
}
3 changes: 3 additions & 0 deletions src/form-builder/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ export const formBuilderConstants = {
saveFormPrivilegesUrl: '/openmrs/ws/rest/v1/bahmniie/form/saveFormPrivileges',
getFormPrivilegesUrl: '/openmrs/ws/rest/v1/bahmniie/form/getFormPrivileges',
getFormPrivilegesFromUuidUrl: '/openmrs/ws/rest/v1/bahmniie/form/getFormPrivilegesFromUuid',
jsonToPdfConvertionUrl: '/openmrs/ws/rest/v1/bahmniie/form/jsonToPdf',
pdfDownloadUrl: '/openmrs/ws/rest/v1/bahmniie/form/download/',

};
7 changes: 7 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FormBuilderContainer from 'form-builder/components/FormBuilderContainer.j
import FormDetailContainer from 'form-builder/components/FormDetailContainer.jsx';
import FormTranslationsContainer from 'form-builder/components/FormTranslationsContainer.jsx';
import FormPrivilegesPreviewContainer from 'form-builder/components/FormPrivilegesPreviewContainer.jsx';
import FormPrinterContainer from 'form-builder/components/FormPrinterContainer.jsx';
import 'bahmni-form-controls';
const store = createStore(implementerInterface);
const routes = [
Expand All @@ -24,6 +25,12 @@ const routes = [
path: '/form-builder',
title: 'Form Builder',
},
{
component: FormPrinterContainer,
exact: true,
path: '/form-printer',
title: 'Form Printer',
},
{
component: FormDetailContainer,
exact: true,
Expand Down
2 changes: 1 addition & 1 deletion styles/common/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ $bahmniTableHeaderBg: #f1f1f1;
$bahmniPageBg: #fafafa;

//fonts
$fontPath: "/implementer-interface/fonts";
$fontPath: "/implementer-interface/dist/fonts";

//colors
$alertBackground: #FFFDF0;
Expand Down
11 changes: 6 additions & 5 deletions test/form-builder/components/FormList.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ describe('FormList', () => {
it('should render Export when form published', () => {
wrapper = shallow(<FormList data={data} handleSelectedForm={undefined} />);

expect(getItem(0, 5).find('a').prop('hidden')).to.eql(true);
expect(getItem(1, 5).find('a').prop('hidden')).to.eql(false);
expect(getItem(1, 5).find('a').find('i').prop('className')).to.eql('fa fa-download');
expect(getItem(0, 5).find('a[title="Export Form"]').prop('hidden')).to.eql(true);
expect(getItem(1, 5).find('a[title="Export Form"]').prop('hidden')).to.eql(false);
expect(getItem(1, 5).find('a[title="Export Form"]')
.find('i').prop('className')).to.eql('fa fa-download');
});

it('should call downloadFile when export be clicked', (done) => {
Expand All @@ -113,7 +114,7 @@ describe('FormList', () => {
.onSecondCall(1).returns(Promise.resolve([]));

wrapper = shallow(<FormList data={data} />);
const exportElement = getItem(0, 5).find('a');
const exportElement = getItem(0, 5).find('a[title="Export Form"]');
exportElement.simulate('click');
const params =
'v=custom:(id,uuid,name,version,published,auditInfo,' +
Expand Down Expand Up @@ -142,7 +143,7 @@ describe('FormList', () => {
wrapper = shallow(<FormList data={data} handleSelectedForm={undefined} />);
const spy = sinon.spy(wrapper.instance(), 'setMessage');

const exportElement = getItem(1, 5).find('a');
const exportElement = getItem(1, 5).find('a[title="Export Form"]');
exportElement.simulate('click');

setTimeout(() => {
Expand Down
Loading

0 comments on commit 04352c7

Please sign in to comment.