Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature to download Bahmni form builder forms as a PDF #76

Merged
merged 13 commits into from Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading