initial docker setup

This commit is contained in:
GotPPay
2018-06-14 16:49:28 +02:00
parent bc80b7342e
commit b5f87f27f8
3023 changed files with 985078 additions and 1 deletions

View File

@@ -0,0 +1,79 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Button} from 'reactstrap';
import {Link} from 'react-router-dom';
import {WiaasTableRow, WiaasTableCol} from '../../../mainComponents/table/WiaasTable.jsx';
import {orderTexts} from '../../../constants/ordersConstants';
import '../style/Orders.css';
import OrderPackage from './OrderPackage.jsx';
class ActiveOrderItem extends Component {
constructor(props) {
super(props);
this.state = {
showPackages: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
showPackages: !this.state.showPackages
});
}
getIconClass(type) {
return 'fa fa-angle-' + type + ' toggle-view-packages';
}
render() {
const {order, isViewAllOrdersChecked} = this.props;
return (
<div>
<WiaasTableRow className={"order-central-row order-border-" + order.status}>
<WiaasTableCol header="#">
{!this.state.showPackages && <i className={this.getIconClass('down')} aria-hidden="true" onClick={this.toggle}></i>}
{this.state.showPackages && <i className={this.getIconClass('up')} aria-hidden="true" onClick={this.toggle}></i>}
<i className="fa fa-list-alt package-photo" aria-hidden="true" />
<div className="order-number">{order.orderNumber}</div>
</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.REFERENCE}>{order.reference ? order.reference : '-'}</WiaasTableCol>
{isViewAllOrdersChecked['active'] && <WiaasTableCol header={orderTexts.labels.PLACED_BY}>{order.customerName ? order.customerName : ''}</WiaasTableCol>}
<WiaasTableCol header={orderTexts.labels.ORDER_DATE}>{order.orderDate ? order.orderDate : '-'}</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.EST_DELIVERY}>{order.estimatedDeliveryDate ? order.estimatedDeliveryDate : '-'}</WiaasTableCol>
<WiaasTableCol header="Catalogue">
<div className="order-item-cl">
<img className="cl-photo" src="static/img/man-icon.png" alt="Catalogue" />
<div className="cl-details">
<div className="cl-contact-name">{order.clContactName}</div>
<div className="cl-name">{order.clName}</div>
</div>
</div>
</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.AMOUNT}>
{order.orderCurrency && order.orderCurrency.currency
? order.orderTotalPrice.toLocaleString() + ' ' + order.orderCurrency.currency
: parseFloat(order.orderTotalPrice).toLocaleString()}
</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.STATUS}>
<div className={'status-icon ' + order.status}></div>{order.status}
</WiaasTableCol>
<WiaasTableCol header="Buttons details">
<Link to={'/orders/' + order.id} className="actions-link">
<Button color="secondary" className="actions-button">{orderTexts.buttons.DELIVERY_DETAILS}</Button>
</Link>
</WiaasTableCol>
</WiaasTableRow>
{ this.state.showPackages && <OrderPackage order={order} type="active"/> }
</div>
);
}
}
const mapStateToProps = (state) => ({
isViewAllOrdersChecked: state.ordersReducer.isViewAllOrdersChecked
});
export default connect(mapStateToProps)(ActiveOrderItem);

View File

@@ -0,0 +1,26 @@
import React, {Component} from 'react';
import { Editor } from '@tinymce/tinymce-react';
class AddComment extends Component {
handleEditorChange = (e) => {
const comment = e.target.getContent();
this.props.onEditorChange(comment);
}
render() {
return (
<div>
<Editor
init={{
plugins: 'link textcolor lists colorpicker code',
toolbar: 'undo redo | styleselect | bold italic underline forecolor fontsizeselect | link | alignleft aligncenter alignright | numlist bullist | outdent indent | code'
}}
onChange={this.handleEditorChange}
/>
</div>
);
}
}
export default AddComment;

View File

@@ -0,0 +1,81 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Dropdown, DropdownToggle, DropdownMenu, DropdownItem} from 'reactstrap';
import {Link} from 'react-router-dom';
import SupportMail from './SupportMail.jsx';
import {setDialogContent, setDialogOpenFlag} from '../../../actions/dialog/dialogActions';
import {sendSupportMail} from '../../../actions/orders/processActions';
import {orderTexts} from '../../../constants/ordersConstants';
class HistoryOrdersButtons extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.sendSupportMail = this.sendSupportMail.bind(this);
this.openDialogContent = this.openDialogContent.bind(this);
this.state = {
dropdownOpen: false
};
}
toggle() {
this.setState({
dropdownOpen: !this.state.dropdownOpen
});
}
openDialogContent() {
const dialogContent = {
buttons: [
{
color: 'secondary',
name: orderTexts.buttons.SEND,
id: 'send-mail-to-support-btn',
action: this.sendSupportMail
},
{
color: 'secondary',
name: orderTexts.buttons.CANCEL,
id: 'cancel-send-mail-to-support-btn'
}
],
header: orderTexts.labels.SUPPORT_MESSAGE_HEADER,
TagName: SupportMail,
params: {orderInfo: this.props.order, orderPackages: this.props.order.packages}
};
this.props.dispatch(setDialogOpenFlag(true));
this.props.dispatch(setDialogContent(dialogContent));
}
sendSupportMail() {
this.props.dispatch(sendSupportMail(this.props.order, this.props.order.packages, this.props.supportText));
}
render() {
const {order} = this.props;
return (
<Dropdown size="sm" isOpen={this.state.dropdownOpen} toggle={this.toggle}>
<DropdownToggle className="actions-button" caret>
{orderTexts.buttons.ACTIONS}
</DropdownToggle>
<DropdownMenu right>
<DropdownItem className="actions-item" onClick={this.openDialogContent}> {orderTexts.buttons.SUPPORT}
</DropdownItem>
<Link to={'/orders/' + order.id} className="actions-link">
<DropdownItem className="actions-item">
{orderTexts.buttons.DETAILS}
</DropdownItem>
</Link>
</DropdownMenu>
</Dropdown>
)
}
}
const mapStateToProps = (state) => ({
supportText: state.processReducer.supportText
});
export default connect(mapStateToProps)(HistoryOrdersButtons);

View File

@@ -0,0 +1,77 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {WiaasTableRow, WiaasTableCol} from '../../../mainComponents/table/WiaasTable.jsx';
import {orderTexts} from '../../../constants/ordersConstants';
import '../style/Orders.css';
import OrderPackage from './OrderPackage.jsx';
import HistoryOrderButtons from './HistoryOrderButtons.jsx';
class HistoryOrdersItem extends Component {
constructor(props) {
super(props);
this.state = {
showPackages: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
showPackages: !this.state.showPackages
});
}
getIconClass(type) {
return 'fa fa-angle-' + type + ' toggle-view-packages';
}
render() {
const {order, isViewAllOrdersChecked} = this.props;
return (
<div>
<WiaasTableRow className={"order-central-row order-border-" + order.status}>
<WiaasTableCol header="#">
{!this.state.showPackages && <i className={this.getIconClass('down')} aria-hidden="true" onClick={this.toggle}></i>}
{this.state.showPackages && <i className={this.getIconClass('up')} aria-hidden="true" onClick={this.toggle}></i>}
<i className="fa fa-list-alt package-photo" aria-hidden="true" />
<div className="order-number">{order.orderNumber}</div>
</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.REFERENCE}>{order.reference ? order.reference : '-'}</WiaasTableCol>
{isViewAllOrdersChecked['history'] && <WiaasTableCol header={orderTexts.labels.PLACED_BY}>{order.customerName ? order.customerName : ''}</WiaasTableCol>}
<WiaasTableCol header={orderTexts.labels.ORDER_DATE}>{order.orderDate ? order.orderDate : '-'}</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.DELIVERY_DATE}>{order.deliveryDate}</WiaasTableCol>
<WiaasTableCol header="Catalogue">
<div className="order-item-cl">
<img className="cl-photo" src="static/img/man-icon.png" alt="Catalogue" />
<div className="cl-details">
<div className="cl-contact-name">{order.clContactName}</div>
<div className="cl-name">{order.clName}</div>
</div>
</div>
</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.AMOUNT}>
{order.orderCurrency && order.orderCurrency.currency
? order.orderTotalPrice.toLocaleString() + ' ' + order.orderCurrency.currency
: parseFloat(order.orderTotalPrice).toLocaleString()}
</WiaasTableCol>
<WiaasTableCol header={orderTexts.labels.STATUS}>
<div className={'status-icon ' + order.status}></div>{orderTexts.statuses[order.status]}
</WiaasTableCol>
<WiaasTableCol header="End of life">{order.endOfLife}</WiaasTableCol>
<WiaasTableCol header="Buttons details">
<HistoryOrderButtons order={order}/>
</WiaasTableCol>
</WiaasTableRow>
{ this.state.showPackages && <OrderPackage order={order} type="history"/> }
</div>
);
}
}
const mapStateToProps = (state) => ({
isViewAllOrdersChecked: state.ordersReducer.isViewAllOrdersChecked
});
export default connect(mapStateToProps)(HistoryOrdersItem);

View File

@@ -0,0 +1,72 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Button, Container, Row, Col} from 'reactstrap';
import WiaasBox from '../../../mainComponents/box/WiaasBox.jsx';
import AddComment from './AddComment.jsx';
import {addComment} from '../../../actions/orders/processActions';
import {orderTexts} from '../../../constants/ordersConstants';
class OrderComments extends Component {
constructor(props) {
super(props);
this.onEditorChange = this.onEditorChange.bind(this);
this.addNewComment = this.addNewComment.bind(this);
this.state = {
newComment: ''
};
}
addNewComment(){
this.props.dispatch(addComment(this.props.orderInfo.id, this.state.newComment));
}
onEditorChange(newComment){
this.setState({newComment});
}
getOffset(isOwner){
return isOwner ? 6 : 0;
}
getClassByOwner(isOwner){
return isOwner ? 'mine' : '';
}
render() {
const {orderComments} = this.props;
return (
<div id="order-comments" className="order-comments">
<WiaasBox mainTitle="Comments">
<Container fluid={true} className="order-coments-body">
<Row>
<Col xl="6">
{
orderComments &&
orderComments.map((orderComment, index) =>
<Row key={'order-comment-' + index}>
<Col xl={{size:6, offset:this.getOffset(orderComment.isOwner)}}>
<div className={'order-comment ' + this.getClassByOwner(orderComment.isOwner)} key={'order-comment-' + index}>
<div className="order-comment-header">{orderComment.username} - {orderComment.addDate}</div>
<div dangerouslySetInnerHTML={{__html: orderComment.comment}}></div>
</div>
</Col>
</Row>
)
}
</Col>
<Col xl="6">
<AddComment onEditorChange={this.onEditorChange}/>
<Button onClick={()=>{this.addNewComment()}} className="new-comment-button" color="secondary">{orderTexts.buttons.ADD_COMMENT}</Button>
</Col>
</Row>
</Container>
</WiaasBox>
</div>
);
}
}
export default connect()(OrderComments);

View File

@@ -0,0 +1,26 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import OrderDocumentsGroup from './OrderDocumentsGroup.jsx';
import {orderTexts} from '../../../constants/ordersConstants';
class OrderDocuments extends Component {
render() {
const {orderInfo} = this.props;
return (
<div id="order-documents" className="order-documents">
{
orderInfo.packages.map(orderPackage => <OrderDocumentsGroup key={'order-package-' + orderPackage.idPackage} documentsGroup={orderPackage} />)
}
{
orderInfo.orderDocuments && <OrderDocumentsGroup key={'order-package-0'} documentsGroup={{documents: orderInfo.orderDocuments, packageName: orderTexts.labels.OTHER_DOCS}} />
}
</div>
);
}
}
const mapStateToProps = (state) => ({
orderInfo: state.processReducer.orderInfo
});
export default connect(mapStateToProps)(OrderDocuments);

View File

@@ -0,0 +1,85 @@
import React, {Component} from 'react';
import {Tooltip} from 'reactstrap';
import WiaasBox from '../../../mainComponents/box/WiaasBox.jsx';
import {API_SERVER} from '../../../config';
import FileDownloader from '../../../helpers/FileDownloader';
const fileHandler = new FileDownloader();
const iconTypes = {
doc: 'file-word-o',
docx: 'file-word-o',
odt: 'file-word-o',
ods: 'file-excel-o',
pdf: 'file-pdf-o',
png: 'file-image-o',
jpg: 'file-image-o',
xls: 'file-excel-o',
xlsx: 'file-excel-o',
ppt: 'file-powerpoint-o',
pptx: 'file-powerpoint-o'
}
class OrderDocumentsGroup extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {};
}
toggle(idDocument) {
const obj = {}
obj[idDocument] = !this.state[idDocument];
this.setState(obj);
}
getDocumentIcon(documentType) {
return iconTypes[documentType] || 'file';
}
getDocumentText(document) {
const name = document.documentName + '.' + document.extension;
return name.length > 9 ? name.substring(0, 10) + '...' : name;
}
downloadDocument(document){
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}&fileType=${document.documentTypeName}`
const fileName = document.documentName + '.' + document.extension;
fileHandler.download(fileUrl, fileName);
}
render() {
const {documentsGroup} = this.props;
return (
<div>
{
documentsGroup.documents.length > 0 &&
<WiaasBox mainTitle={documentsGroup.packageName}>
{
documentsGroup.documents.map(document => <a id={'document-' + document.idDocument} key={'order-document-' + document.idDocument}>
<div onClick={() => {this.downloadDocument(document)}} className="document-link-big">
<i className={'fa fa-4x fa-' + this.getDocumentIcon(document.extension)} aria-hidden="true"></i>
<div>
{this.getDocumentText(document)}
<Tooltip placement="bottom"
delay={{ show: 0, hide: 0}}
container="order-documents"
isOpen={this.state[document.idDocument]}
target={'document-' + document.idDocument}
toggle={()=>this.toggle(document.idDocument)}>
{document.documentName} ({document.extension})
</Tooltip>
</div>
</div></a>)
}
</WiaasBox>
}
</div>)
}
}
export default OrderDocumentsGroup;

View File

@@ -0,0 +1,152 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import moment from 'moment';
import {Container, Row, Col} from 'reactstrap';
import TermsContainer from '../../terms/TermsContainer.jsx';
import {orderTexts} from '../../../constants/ordersConstants';
class OrderInfo extends Component {
constructor(props){
super(props);
this.state = {
acceptedDate: {},
proposedDate: {},
isPreliminaryInstallationDate: true
};
}
componentDidMount() {
this.setInstallationData(this.props);
}
componentWillReceiveProps(nextProps) {
this.setInstallationData(nextProps);
}
setInstallationData(props) {
const acceptedDate = {};
const proposedDate = {};
const idOrder = props.orderDetails.info.id;
const {isInstallationInPackage} = props.installationData;
const {confirmationDates, areAllShippingDatesConfirmed} = props;
const isPreliminaryInstallationDate = areAllShippingDatesConfirmed && idOrder in areAllShippingDatesConfirmed ? !areAllShippingDatesConfirmed[idOrder] : true;
const isInstallationInOrder = Object.keys(isInstallationInPackage).some(idOrderPackage => {return isInstallationInPackage[idOrderPackage] === true;});
props.orderDetails.packages.forEach(orderPackage => {
const idOrderPackagePair = idOrder + '-' + orderPackage.idPackage;
if(confirmationDates && confirmationDates[idOrderPackagePair]) {
const packageDates = confirmationDates[idOrderPackagePair];
const accepted = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'accepted'});
acceptedDate[idOrderPackagePair] = accepted ? moment(accepted).format('Do MMM, YYYY') : '';
const proposed = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'proposed'});
proposedDate[idOrderPackagePair] = proposed ? moment(proposed).format('Do MMM, YYYY') : '';
}
});
this.setState({acceptedDate, proposedDate, isPreliminaryInstallationDate, isInstallationInOrder});
}
render() {
const {totalPrice, installationData} = this.props;
const {acceptedDate, proposedDate, isPreliminaryInstallationDate, isInstallationInOrder} = this.state;
const orderPackages = installationData.packages;
const isInstallationInPackage = installationData.isInstallationInPackage;
const orderInfo = this.props.orderInfo.info;
return (
<Container fluid={true} id="order-info-description">
<Row>
<Col xl="2">
<div className="subtitle"><h6>{orderTexts.labels.ORDER_DATE}:</h6></div>
<span>{orderInfo.orderDate}</span>
<div className="subtitle"><h6>{orderTexts.labels.SOLD_BY}:</h6></div>
<span>{orderInfo.commercialLead}</span>
</Col>
<Col xl="2">
<div>
<div className="subtitle"><h6>{orderTexts.labels.REFERENCE}:</h6></div>
<span>{orderInfo.reference || '-'}</span>
</div>
<div>
<div className="subtitle"><h6>{orderTexts.labels.BID}:</h6></div>
<span>{orderInfo.tender || '-'}</span>
</div>
</Col>
{ isInstallationInOrder &&
<Col xl="3">
<div>
<div className="subtitle">
{ isPreliminaryInstallationDate
? <h6>{orderTexts.labels.PRELIMINARY_INSTALLATION_DATE_LABEL}:</h6>
: <h6>{orderTexts.labels.INSTALLATION_DATE}:</h6>
}
</div>
{ orderPackages &&
orderPackages.map(orderPackage =>
<div key={'package-install-date-' + orderPackage.idOrderPackagePair}>
{ isInstallationInPackage[orderPackage.idOrderPackagePair] &&
<div>
{ orderPackages.length > 1 &&
<span>{orderPackage.packageName}: </span>
}
<span className="installation-date-per-package">
{ acceptedDate && acceptedDate[orderPackage.idOrderPackagePair]
? acceptedDate[orderPackage.idOrderPackagePair]
: proposedDate && proposedDate[orderPackage.idOrderPackagePair]
? proposedDate[orderPackage.idOrderPackagePair]
: orderTexts.labels.NOT_SET
}
</span>
</div>
}
</div>
)
}
</div>
</Col>
}
<Col xl="2">
<div className="subtitle"><h6>{orderTexts.labels.TOTAL_DELVIERY_PRICE}:</h6></div>
<span>{totalPrice.fixedPrice.toLocaleString()} {totalPrice.currency}</span>
{
totalPrice.recurrentPrice > 0 &&
<div>
<div className="subtitle"><h6>{orderTexts.labels.TOTAL_RECURRENT_PRICE}:</h6></div>
<span>
{totalPrice.recurrentPrice.toLocaleString() + ' ' + totalPrice.currency}
</span>
</div>
}
</Col>
<Col xl="2">
<div>
<div className="subtitle"><h6>{orderTexts.labels.PROJECT}:</h6></div>
<span>{orderInfo.projectName || '-'}</span>
</div>
<div className="terms-link">
<i className="fa fa-link"></i>
<span className="terms-label">
<TermsContainer idTerms={orderInfo.idTerms}/>
</span>
</div>
</Col>
</Row>
</Container>
);
}
}
const mapStateToProps = (state) => ({
orderInfo: state.processReducer.orderInfo,
confirmationDates: state.processReducer.confirmationDates,
areAllShippingDatesConfirmed: state.processReducer.areAllShippingDatesConfirmed
});
export default connect(mapStateToProps)(OrderInfo);

View File

@@ -0,0 +1,75 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import ActiveOrderItem from './ActiveOrderItem.jsx';
import HistoryOrderItem from './HistoryOrderItem.jsx';
import {WiaasTable, WiaasTableHeader, WiaasTableBody} from '../../../mainComponents/table/WiaasTable.jsx';
import {orderTexts} from '../../../constants/ordersConstants';
class OrderList extends Component {
constructor(props) {
super(props);
this.getHeadersByType = this.getHeadersByType.bind(this);
}
getHeadersByType(type) {
const activeOrdersHeader = [
orderTexts.headers.ORDER,
orderTexts.headers.REFERENCE,
orderTexts.headers.ORDER_DATE,
orderTexts.headers.ESTIMATED_DATE,
orderTexts.headers.COMMERCIAL_LEAD,
orderTexts.headers.AMOUNT,
orderTexts.headers.STATUS,
''
];
const historyOrdersHeader = [
orderTexts.headers.ORDER,
orderTexts.headers.REFERENCE,
orderTexts.headers.ORDER_DATE,
orderTexts.headers.DELIVERY_DATE,
orderTexts.headers.COMMERCIAL_LEAD,
orderTexts.headers.AMOUNT,
orderTexts.headers.STATUS,
orderTexts.headers.END_OF_LIFE,
''
];
if(this.props.isCompanyAdmin && this.props.isViewAllOrdersChecked[type]) {
activeOrdersHeader.splice(2, 0, orderTexts.headers.PLACED_BY);
activeOrdersHeader.join();
historyOrdersHeader.splice(2, 0, orderTexts.headers.PLACED_BY);
historyOrdersHeader.join();
}
return type === 'active' ? activeOrdersHeader : historyOrdersHeader;
}
render() {
const {orders, type, isCompanyAdmin, isViewAllOrdersChecked} = this.props;
const TagName = type && type === 'active' ? ActiveOrderItem : HistoryOrderItem;
return (
<div>
<WiaasTable>
<WiaasTableHeader headers={this.getHeadersByType(type)}/>
<WiaasTableBody>
{
orders &&
orders.map((order, index) =>
(('isMyOrder' in order && order.isMyOrder) || (isCompanyAdmin && isViewAllOrdersChecked[type])) &&
<TagName key={order.orderNumber} order={order} />
)
}
</WiaasTableBody>
</WiaasTable>
</div>
);
}
}
const mapStateToProps = (state) => ({
isCompanyAdmin: state.auth.isCompanyAdmin,
isViewAllOrdersChecked: state.ordersReducer.isViewAllOrdersChecked
});
export default connect(mapStateToProps)(OrderList);

View File

@@ -0,0 +1,56 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Row, Col, Input} from 'reactstrap';
import '../style/OrdersList.css';
import {setViewAllOrdersFlag} from '../../../actions/orders/ordersActions';
import {orderTexts} from '../../../constants/ordersConstants';
class OrderListHeader extends Component {
constructor(props) {
super(props);
this.state = {
isViewAllOrdersChecked: false
};
this.handleInputChange = this.handleInputChange.bind(this);
}
componentDidMount() {
const isViewAllChecked = {};
isViewAllChecked[this.props.params] = this.state.isViewAllOrdersChecked;
this.props.dispatch(setViewAllOrdersFlag(isViewAllChecked));
}
handleInputChange(e) {
this.setState({
isViewAllOrdersChecked: !this.state.isViewAllOrdersChecked
});
const isViewAllChecked = {};
isViewAllChecked[this.props.params] = e.target.checked;
this.props.dispatch(setViewAllOrdersFlag(isViewAllChecked));
}
render() {
const {isCompanyAdmin} = this.props;
return (
<Row id="view-all-orders-checkbox">
{isCompanyAdmin &&
<Col xl="10">
<Input type="checkbox"
name="isViewAllOrdersChecked"
checked={this.state.isViewAllOrdersChecked}
onChange={this.handleInputChange}
className="view-all-orders-checkbox" />
<span className="view-all-orders-text">{orderTexts.labels.VIEW_ALL_ORDERS}</span>
</Col>
}
</Row>
);
}
}
const mapStateToProps = (state) => ({
isCompanyAdmin: state.auth.isCompanyAdmin
});
export default connect(mapStateToProps)(OrderListHeader);

View File

@@ -0,0 +1,92 @@
import React, {Component} from 'react';
import {Col} from 'reactstrap';
import WiaasBox from '../../../mainComponents/box/WiaasBox.jsx';
import {WiaasTable, WiaasTableHeader, WiaasTableBody, WiaasTableRow, WiaasTableCol} from '../../../mainComponents/table/WiaasTable.jsx';
import {orderTexts} from '../../../constants/ordersConstants';
import '../style/Orders.css';
class OrderPackage extends Component {
calculateRecuringPrice(packageDetails) {
return packageDetails.units * (parseFloat(packageDetails.packageRecuringPrice) + parseFloat(packageDetails.packageServicePrice));
}
calculateQuantityPrice(quantity, price, recurringPrice = 0) {
return quantity * parseFloat(price + recurringPrice);
}
getHeadersByType(type) {
if(type === 'active') {
return ['Package', 'Price', 'Services and support', 'Delivery active step'];
}
return ['Package', 'Price', 'Services and support', 'End of Life'];
}
render() {
const {order, type} = this.props;
return (
<WiaasTableRow className={"order-border-" + order.status}>
<Col lg="3" sm="12" xs="12">
<WiaasBox mainTitle="Order Details">
<div className="order-details-container">
<WiaasTableRow id={'delivery-address-' + order.id}>
<Col lg="4" sm="4" xs="4">{orderTexts.labels.DELIVERY_ADDRESS}:</Col>
<Col lg="8" sm="8" xs="8">{order.deliveryAddress}</Col>
</WiaasTableRow>
<WiaasTableRow id={'phone-' + order.id}>
<Col lg="4" sm="4" xs="4">{orderTexts.labels.PHONE_NUMBER}:</Col>
<Col lg="8" sm="8" xs="8">{order.phone}</Col>
</WiaasTableRow>
<WiaasTableRow id={'mail-' + order.id}>
<Col lg="4" sm="4" xs="4">{orderTexts.labels.MAIL}:</Col>
<Col lg="8" sm="8" xs="8">{order.mail}</Col>
</WiaasTableRow>
<WiaasTableRow id={'commercial-lead-phone-' + order.id}>
<Col lg="4" sm="4" xs="4">{order.clName} {orderTexts.labels.PHONE_NUMBER}:</Col>
<Col lg="8" sm="8" xs="8">{order.commercialLeadPhone}</Col>
</WiaasTableRow>
<WiaasTableRow id={'mail-' + order.id}>
<Col lg="4" sm="4" xs="4">{order.clName} {orderTexts.labels.MAIL}:</Col>
<Col lg="8" sm="8" xs="8">{order.commercialLeadMail}</Col>
</WiaasTableRow>
</div>
</WiaasBox>
</Col>
<Col lg="9" sm="12" xs="12">
<WiaasBox mainTitle="Items">
<WiaasTable>
<WiaasTableHeader headers={this.getHeadersByType(type)}/>
<WiaasTableBody>
{order.packages.map((orderPackage, index) =>
<WiaasTableRow className="order-central-row" key={orderPackage.idOrder + '-' + orderPackage.idPackage}>
<WiaasTableCol header="Package" className="package-info-col">
<div className="package-name">{orderPackage.units} x {orderPackage.packageName}</div>
</WiaasTableCol>
<WiaasTableCol header="Price">
{this.calculateQuantityPrice(orderPackage.units, orderPackage.packageFixedPrice).toLocaleString()} {orderPackage.packageCurrency && orderPackage.packageCurrency.currency} {' '}
({orderPackage.paymentType})
</WiaasTableCol>
<WiaasTableCol header="Services and support">
{this.calculateQuantityPrice(orderPackage.units, orderPackage.packageServicePrice, orderPackage.packageRecuringPrice).toLocaleString() + ' / ' + orderPackage.periodUnit + ' '}
{orderTexts.labels.EXTEND} {orderPackage.periodUnit} (Max {orderPackage.maxContractPeriod})
</WiaasTableCol>
<WiaasTableCol>
{
type === 'active'
? orderPackage.shortDesc ? orderPackage.shortDesc : '-'
: orderPackage.endOfLife ? orderPackage.endOfLife : '-'
}
</WiaasTableCol>
</WiaasTableRow>
)}
</WiaasTableBody>
</WiaasTable>
</WiaasBox>
</Col>
</WiaasTableRow>
);
}
}
export default OrderPackage;

View File

@@ -0,0 +1,35 @@
import React, {Component} from 'react';
import {Row, Col} from 'reactstrap';
import {orderTexts} from '../../../constants/ordersConstants';
class PackageNav extends Component {
getClass(packageName) {
return this.props.params.packageNameFilter === packageName ? 'process-nav-div selected-nav' : 'process-nav-div';
}
render() {
const {packages, onPackageFilter} = this.props.params;
return (
<Row id="process-nav" className="process-nav">
<Col xl="1" lg="2" md="3" sm="12" xs="12" className="process-nav-buttons">
<div className="wiaas-main-title">
{orderTexts.labels.PACKAGES}
</div>
</Col>
<Col xl="9" lg="9" md="4" xs="12" className="process-menu">
<div className={this.getClass('all')} onClick={()=>{onPackageFilter('all')}}>{orderTexts.buttons.ALL}</div>
{
packages.length > 0 &&
packages.map((orderPackage) => <div key={'menu-package-' + orderPackage.idPackage}
onClick={()=>{onPackageFilter(orderPackage.packageName)}}
className={this.getClass(orderPackage.packageName)}>{orderPackage.packageName}</div>)
}
</Col>
</Row>
);
}
}
export default PackageNav;

View File

@@ -0,0 +1,121 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Row, Col, FormGroup, Label, Input} from 'reactstrap';
import {setSupportMessage} from '../../../actions/orders/processActions';
import {orderTexts} from '../../../constants/ordersConstants';
class SupportMail extends Component {
constructor(props) {
super(props);
this.state = {
supportText: ''
};
this.setSupportMessage = this.setSupportMessage.bind(this);
}
calculateFixedPrice(quantity, price) {
return quantity*price;
}
calculateRecurrentPrice(orderPackage) {
return orderPackage.units*(orderPackage.packageRecuringPrice + orderPackage.packageServicePrice);
}
handleInputChange(event) {
this.setState({supportText: event.target.value});
event.preventDefault();
}
setSupportMessage() {
this.props.dispatch(setSupportMessage(this.state.supportText));
}
render() {
const {orderInfo, orderPackages} = this.props.params;
return (
<span id="send-support-mail-container">
{orderInfo && orderPackages &&
<div>
<div id="order-details">
<Row>
<Col>
<h5>{orderTexts.labels.ORDER_DETAILS}</h5>
</Col>
</Row>
<Row>
<Col xl="4">
<span className="subtitle">{orderTexts.labels.ORDER_NUMBER}:</span>
</Col>
<Col xl="8">
<span>{orderInfo.orderNumber}</span>
</Col>
</Row>
<Row>
<Col xl="4">
<span className="subtitle">{orderTexts.labels.LOCATION_DETAILS}:</span>
</Col>
<Col xl="8">
<span>{orderInfo.reference || '-'}</span>
</Col>
</Row>
</div>
<div id="order-items" className="support-details">
<Row>
<Col>
<h5>{orderTexts.labels.ORDER_ITEMS}</h5>
</Col>
</Row>
{ orderPackages.map((orderPackage, mapKey) =>
<div key={'order-package-'+mapKey} className="order-package-details">
<Row>
<Col>
<span className="fa fa-shopping-cart subtitle"></span>
<span className="package-name"> {orderPackage.units} x {orderPackage.packageName}</span>
</Col>
</Row>
{orderPackage.endOfLife &&
<Row>
<Col>
<span className="subtitle">{orderTexts.labels.END_OF_LIFE}:</span>
</Col>
<Col xl="8">
<span>{orderPackage.endOfLife}</span>
</Col>
</Row>
}
<Row>
<Col>
<span className="subtitle">{orderTexts.labels.STATUS}:</span>
</Col>
<Col xl="8">
<span>{orderPackage.status}</span>
</Col>
</Row>
</div>
)}
</div>
<div id="order-support-text" className="support-details">
<Row>
<Col>
<FormGroup>
<Label for="supportText">{orderTexts.labels.ENTER_TEXT}</Label>
<Input id="my-support-mail-text"
type="textarea"
name="supportText"
value={this.state.supportText}
onChange={(e) => this.handleInputChange(e)}
onBlur={this.setSupportMessage}/>
</FormGroup>
</Col>
</Row>
</div>
</div>
}
</span>
);
}
}
export default connect()(SupportMail);

View File

@@ -0,0 +1,165 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import 'react-datepicker/dist/react-datepicker.css';
import moment from 'moment';
import {Row, Col, Button, Popover, PopoverBody} from 'reactstrap';
import '../../style/InstallationScheduling.css';
import {updateInstallationDate, removeMyDate, setSchedulingFlag} from '../../../../actions/orders/processActions';
import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions';
import {orderTexts} from '../../../../constants/ordersConstants';
class InstallationSchedulingDatesPerPackage extends Component {
constructor(props) {
super(props);
this.state = {
startDate: undefined,
btnType: '',
nestedModal: false,
closeAll: false,
popoverOpen: false
};
this.toggle = this.toggle.bind(this);
this.openInstallationDialog = this.openInstallationDialog.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleBtnAction = this.handleBtnAction.bind(this);
}
componentDidMount() {
this.props.dispatch(setSchedulingFlag(this.props.installationParams.isSchedulingDisabled));
}
handleChange(date) {
this.setState({startDate: date});
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
canUserAcceptOrDecline(dateInfo, lastStatus) {
let additionalCondition = false;
if (lastStatus === 'declined') {
additionalCondition = dateInfo.lastStatus === 'canceled' && dateInfo.isProposedByMe;
}
return !this.props.isComponentDisabled &&
((dateInfo.lastStatus === 'proposed' && !dateInfo.isProposedByMe) ||
(dateInfo.lastStatus === lastStatus && dateInfo.isProposedByMe) ||
additionalCondition);
}
isDateProposedByMe() {
return this.props.dateInfo.lastStatus === 'proposed' && this.props.dateInfo.isProposedByMe === true;
}
isRemoveBtnVisible(confirmationDate) {
return !this.props.isComponentDisabled && this.isDateProposedByMe();
}
handleBtnClick(type) {
this.setState({type});
const upperCaseType = type.charAt(0).toUpperCase() + type.slice(1);
const dialogInstallationContent = {
buttons: [
{
color: 'success',
action: this.handleBtnAction,
name: orderTexts.buttons.YES,
id: type + '-installation-date-confirmation'
}, {
color: 'secondary',
name: orderTexts.buttons.NO,
action: this.openInstallationDialog,
id: 'cancel-' + type + '-installation-date'
}
],
header: upperCaseType + ' installation date confirmation',
body: 'Are you sure you want to ' + type + ' the installation date proposed?'
};
this.props.dispatch(setDialogOpenFlag(true));
this.props.dispatch(setDialogContent(dialogInstallationContent));
}
openInstallationDialog() {
this.props.openDialogInstallContent(this.props.installationParams);
}
handleBtnAction() {
let handleFunction = this.state.type === 'remove' ? removeMyDate : updateInstallationDate;
this.props.dispatch(handleFunction(this.props.orderPackage.idOrder, this.props.orderPackage.idPackage, this.props.confirmationDate, this.state.type));
this.openInstallationDialog();
}
getStatusIcon(status) {
const statusesIcons = {
proposed: 'clock-o',
accepted: 'check',
canceled: 'remove',
declined: 'ban',
invalid: 'remove'
};
return 'status-icon-installation-dates fa fa-' + statusesIcons[status];
}
render() {
const {confirmationDate, dateInfo, orderPackage} = this.props;
const idOrderPackageDatePair = orderPackage.idOrder + '-' + orderPackage.idPackage + '-' + confirmationDate;
return (
<div id={"installation-scheduling-dates-container-" + idOrderPackageDatePair} className="installation-scheduling-dates-container">
<span className="installation-date">
<span className={this.getStatusIcon(dateInfo.lastStatus) + ' confirmation-' + dateInfo.lastStatus}></span>
<span className="installation-date-proposed">{moment(confirmationDate).format('Do MMM, YYYY')}</span>
<i className="dates-info-btn fa fa-info-circle"
id={'dates-info-' + idOrderPackageDatePair}
onClick={this.toggle}></i>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'dates-info-' + idOrderPackageDatePair}
container={"installation-scheduling-dates-container-" + idOrderPackageDatePair}
className="dates-info-popover"
toggle={this.toggle}>
<PopoverBody>
{ dateInfo && dateInfo.details &&
dateInfo.details.map((details) =>
<Row key={'confirmation-date-details-' + details.currentDate}>
<Col>
{moment(details.currentDate).format('Do MMM, YYYY LT')}
</Col>
<Col className={"confirmation-" + details.status}>
<span className={this.getStatusIcon(details.status)}></span>
{details.status}
</Col>
<Col>
{details.username} ({details.userType})
</Col>
</Row>
)}
</PopoverBody>
</Popover>
</span>
<span className="confirmation-dates-buttons">
{ this.canUserAcceptOrDecline(dateInfo, 'declined') &&
<Button id={"accept-date-"+idOrderPackageDatePair} className="installation-button install-btn-accept" onClick={() => {this.handleBtnClick('accept')}} >{orderTexts.buttons.ACCEPT}</Button>
}
{ this.canUserAcceptOrDecline(dateInfo, 'accepted') &&
<Button id={"decline-date-"+idOrderPackageDatePair} className="installation-button install-btn-decline" onClick={() => {this.handleBtnClick('decline')}} >{orderTexts.buttons.DECLINE}</Button>
}
{ this.isRemoveBtnVisible(confirmationDate) &&
<Button id={"cancel-remove-installation-dates-"+idOrderPackageDatePair} className="installation-button install-btn-remove" onClick={() => {this.handleBtnClick('remove')}} >{orderTexts.buttons.REMOVE}</Button>
}
</span>
</div>
);
}
}
const mapStateToProps = (state) => ({
confirmationDates: state.processReducer.confirmationDates
});
export default connect(mapStateToProps)(InstallationSchedulingDatesPerPackage);

View File

@@ -0,0 +1,175 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import moment from 'moment';
import {Row, Col, Popover, PopoverBody} from 'reactstrap';
import '../../style/InstallationScheduling.css';
import InstallationSchedulingPerPackage from './InstallationSchedulingPerPackage.jsx';
import {orderTexts} from '../../../../constants/ordersConstants';
import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions';
class InstallationSchedulingForPackages extends Component {
constructor(props) {
super(props);
this.state = {
popoverOpen: false
}
this.toggle = this.toggle.bind(this);
this.setContentDialog = this.setContentDialog.bind(this);
this.openDialogInstallContent = this.openDialogInstallContent.bind(this);
}
setContentDialog(installationParams) {
return {
class: 'installation-scheduling',
hasCloseIcon: true,
header: orderTexts.labels.INSTALLATION_SCHEDULE_HEADER,
TagName: InstallationSchedulingPerPackage,
params: {installationParams, openDialogInstallContent: this.openDialogInstallContent}
};
}
openDialogInstallContent(installationParams) {
const dialogContent = this.setContentDialog(installationParams);
this.props.dispatch(setDialogOpenFlag(true));
this.props.dispatch(setDialogContent(dialogContent));
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
render() {
const {orderPackage, areComponentsDisabled, isInstallationSet, isInstallationInPackage, noOfPackages, installCompanies, isComponentDisabled, earliestInstallDate, confirmationDates, areAllShippingDatesConfirmed} = this.props;
const idOrder = orderPackage ? orderPackage.idOrder : 0;
const idOrderPackagePair = orderPackage ? idOrder + '-' + orderPackage.idPackage : '';
const acceptedDate = {};
const proposedDate = {};
const installationCompany = {};
const availableCompanies = {};
const selectedCompanies = {};
const isPreliminaryInstallationDate = {};
if(confirmationDates && confirmationDates[idOrderPackagePair]) {
const packageDates = confirmationDates[idOrderPackagePair];
const accepted = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'accepted'});
acceptedDate[idOrderPackagePair] = accepted ? moment(accepted).format('Do MMM, YYYY') : '';
const proposed = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'proposed'});
proposedDate[idOrderPackagePair] = proposed ? moment(proposed).format('Do MMM, YYYY') : '';
}
if(installCompanies) {
availableCompanies[idOrderPackagePair] = idOrderPackagePair in installCompanies.available ? installCompanies.available[idOrderPackagePair] : [];
selectedCompanies[idOrderPackagePair] = idOrderPackagePair in installCompanies.selected ? installCompanies.selected[idOrderPackagePair] : {};
if (idOrderPackagePair in selectedCompanies && Object.keys(selectedCompanies[idOrderPackagePair]).length > 0) {
installationCompany[idOrderPackagePair] = selectedCompanies[idOrderPackagePair];
}
}
isPreliminaryInstallationDate[idOrderPackagePair] = areAllShippingDatesConfirmed && orderPackage.idOrder in areAllShippingDatesConfirmed ? !areAllShippingDatesConfirmed[orderPackage.idOrder] : true;
const isSchedulingDisabled = (idOrder in areComponentsDisabled && areComponentsDisabled[idOrder]) || (isInstallationSet && !isInstallationSet[idOrderPackagePair]);
const installationParams = {
idOrder,
idOrderPackagePair,
orderPackage,
installCompanies,
isComponentDisabled,
earliestInstallDate,
confirmationDates,
isThisComponentDisabled: areComponentsDisabled[idOrder],
availableCompanies,
selectedCompanies,
installationCompany,
isSchedulingDisabled,
isInstallationSet,
isPreliminaryInstallationDate,
acceptedDate,
proposedDate
};
return (
<span id="installation-scheduler-container">
{ noOfPackages === 1
? this.openDialogInstallContent(installationParams)
: <Row className="package-installation-row">
<Col xl="7" id={"package-name-" + orderPackage.idOrder + '-' + orderPackage.idPackage}>
{orderPackage.packageName}
</Col>
<Col xl="5">
<div className="subtitle">
{
isInstallationInPackage && isInstallationInPackage[idOrderPackagePair] === false
? <span>{orderTexts.labels.INSTALLATION_NOT_REQUIRED}</span>
: isPreliminaryInstallationDate[idOrderPackagePair]
? <span>{orderTexts.labels.PRELIMINARY_INSTALLATION_DATE_LABEL}: </span>
: <span>{orderTexts.labels.INSTALLATION_DATE}: </span>
}
</div>
<div id={"installation-scheduler-container-" + idOrderPackagePair} className="install-date-text">
{
isSchedulingDisabled
? acceptedDate[idOrderPackagePair]
? acceptedDate[idOrderPackagePair]
: proposedDate[idOrderPackagePair]
? proposedDate[idOrderPackagePair]
: (isInstallationInPackage[idOrderPackagePair] && !proposedDate[idOrderPackagePair] && !acceptedDate[idOrderPackagePair]) && orderTexts.labels.NOT_SET
: <span className="check-installation-dates"
onClick={() => this.openDialogInstallContent(installationParams)}>
{
acceptedDate[idOrderPackagePair]
? acceptedDate[idOrderPackagePair]
: proposedDate[idOrderPackagePair]
? proposedDate[idOrderPackagePair]
: (isInstallationInPackage[idOrderPackagePair] && !proposedDate[idOrderPackagePair] && !acceptedDate[idOrderPackagePair]) && orderTexts.labels.NOT_SET
}
</span>
}
{
isInstallationInPackage[idOrderPackagePair] &&
<span>
<i className="scheduled-date-btn fa fa-info-circle"
id={'scheduled-date-' + idOrderPackagePair}
onClick={this.toggle}></i>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'scheduled-date-' + idOrderPackagePair}
container={"installation-scheduler-container-" + idOrderPackagePair}
className="scheduled-date-popover"
toggle={this.toggle}>
<PopoverBody>
{
isPreliminaryInstallationDate[idOrderPackagePair]
? acceptedDate[idOrderPackagePair]
? orderTexts.labels.PRELIMINARY_INSTALLATION_DATE
: orderTexts.labels.INSTALLATION_DATE_NOT_SET
: acceptedDate[idOrderPackagePair]
? orderTexts.labels.INSTALLATION_DATE_ACCEPTED
: orderTexts.labels.INSTALLATION_DATE_NOT_SET
}
</PopoverBody>
</Popover>
</span>
}
</div>
</Col>
</Row>
}
</span>
);
}
}
const mapStateToProps = (state) => ({
isNextStepWanted: state.processReducer.isNextStepWanted,
isComponentDisabled: state.processReducer.isComponentDisabled,
earliestInstallDate: state.processReducer.earliestInstallDate,
confirmationDates: state.processReducer.confirmationDates,
installCompanies: state.processReducer.installCompanies
});
export default connect(mapStateToProps)(InstallationSchedulingForPackages);

View File

@@ -0,0 +1,161 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import moment from 'moment';
import {Col, Button, Popover, PopoverBody} from 'reactstrap';
import '../../style/InstallationScheduling.css';
import {API_SERVER} from '../../../../config';
import FileDownloader from '../../../../helpers/FileDownloader';
import InstallationSchedulingDatesPerPackage from './InstallationSchedulingDatesPerPackage.jsx';
import {updateInstallationDate} from '../../../../actions/orders/processActions';
import {orderTexts} from '../../../../constants/ordersConstants';
const fileHandler = new FileDownloader();
const fileType = 'installationProtocol';
const status = 'proposed';
class InstallationSchedulingPerPackage extends Component {
constructor(props) {
super(props);
this.state = {
startDate: undefined
};
this.toggle = this.toggle.bind(this);
this.handleDateChange = this.handleDateChange.bind(this);
this.handleSelect = this.handleSelect.bind(this);
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
handleDateChange(startDate) {
this.setState({startDate});
}
handleSelect(date, idOrder, idPackage) {
const newDate = new Date(moment(date).toISOString());
this.handleDateChange(date);
this.toggle();
if(Date.parse(newDate)) {
const updateDate = moment(date).format('YYYY-MM-DD');
this.props.dispatch(updateInstallationDate(idOrder, idPackage, updateDate, status, this.handleDateChange));
}
}
downloadDocument(document){
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}&fileType=${fileType}`
const fileName = document.documentName + '.' + document.extension;
fileHandler.download(fileUrl, fileName);
}
render() {
const acceptedDate = {};
const proposedDate = {};
const {
idOrder,
idOrderPackagePair,
orderPackage,
earliestInstallDate,
isThisComponentDisabled,
isPreliminaryInstallationDate,
installationCompany,
isInstallationSet
} = this.props.params.installationParams;
const {confirmationDates} = this.props;
const earliestInstallationDate = earliestInstallDate && moment(earliestInstallDate[idOrder]);
if(confirmationDates && confirmationDates[idOrderPackagePair]) {
const packageDates = confirmationDates[idOrderPackagePair];
const accepted = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'accepted'});
acceptedDate[idOrderPackagePair] = accepted ? moment(accepted).format('Do MMM, YYYY') : '';
const proposed = Object.keys(packageDates).find(installDate => {return packageDates[installDate].lastStatus === 'proposed'});
proposedDate[idOrderPackagePair] = proposed ? moment(proposed).format('Do MMM, YYYY') : '';
}
return (
<fieldset disabled={isThisComponentDisabled} className="set-installation-dates">
<Col>
<div className="subtitle">
{
isPreliminaryInstallationDate[idOrderPackagePair]
? <h6>{orderTexts.labels.PRELIMINARY_INSTALLATION_DATE_LABEL}: </h6>
: <h6>{orderTexts.labels.INSTALLATION_DATE}: </h6>
}
</div>
<div id={"installation-scheduler-container-" + idOrderPackagePair} className="install-date-text">
{
acceptedDate[idOrderPackagePair]
? acceptedDate[idOrderPackagePair]
: proposedDate[idOrderPackagePair]
? proposedDate[idOrderPackagePair]
: (!proposedDate[idOrderPackagePair] && !acceptedDate[idOrderPackagePair]) && orderTexts.labels.NOT_SET
}
</div>
</Col>
<Col>
<div className="subtitle"><h6>{orderTexts.labels.INSTALL_COMPANY}:</h6></div>
<span id={"installation-company-name-" + idOrderPackagePair}>
{ isInstallationSet[idOrderPackagePair] ? installationCompany[idOrderPackagePair].name : <span>{orderTexts.labels.INSTALL_COMPANY_NOT_SET}</span>}
</span>
</Col>
<Col>
<div className="subtitle"><h6>{orderTexts.labels.EARLIEST_INSTALLATION}:</h6></div>
<span id={"earliest-installation-date-" + idOrderPackagePair}>
{(earliestInstallDate && earliestInstallDate[idOrder])
? moment(earliestInstallDate[idOrder]).format('Do MMM, YYYY')
: '-'}
</span>
</Col>
<Col>
<div className="subtitle"><h6>{orderTexts.labels.PROPOSED_DATES}</h6></div>
{
confirmationDates && confirmationDates[idOrderPackagePair]
&& Object.keys(confirmationDates[idOrderPackagePair]).map((confirmationDate) =>
<InstallationSchedulingDatesPerPackage
key={'order-package-installation-dates-' + confirmationDate}
minDate={earliestInstallationDate}
confirmationDate={confirmationDate}
dateInfo={confirmationDates[idOrderPackagePair][confirmationDate]}
orderPackage={orderPackage}
openDialogInstallContent={this.props.params.openDialogInstallContent}
installationParams={this.props.params.installationParams}
isComponentDisabled={isThisComponentDisabled}/>)
}
</Col>
<Col id={"installation-scheduling-propose-date-" + idOrderPackagePair}>
<Button id={"propose-new-installation-date-" + idOrderPackagePair} disabled={isThisComponentDisabled} className="propose-new-date-btn" onClick={this.toggle}>Add optional date</Button>
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={"propose-new-installation-date-" + idOrderPackagePair}
container={"installation-scheduling-propose-date-" + idOrderPackagePair}
className="dates-info-popover"
toggle={this.toggle}>
<PopoverBody>
<DatePicker
inline
id={"installation-date-propose-" + idOrderPackagePair}
selected={this.state.startDate}
onSelect={(date) => this.handleSelect(date, orderPackage.idOrder, orderPackage.idPackage)}
minDate={earliestInstallationDate}
dateFormat="Do MMM, YYYY"
placeholderText="Choose a date" />
</PopoverBody>
</Popover>
</Col>
</fieldset>
);
}
}
const mapStateToProps = (state) => ({
confirmationDates: state.processReducer.confirmationDates
});
export default connect(mapStateToProps)(InstallationSchedulingPerPackage);

View File

@@ -0,0 +1,142 @@
import React, {Component} from 'react';
import {Row, Col, Container, Popover, PopoverBody, PopoverHeader} from 'reactstrap';
import {API_SERVER} from '../../../../config';
import FileDownloader from '../../../../helpers/FileDownloader';
import {orderTexts} from '../../../../constants/ordersConstants';
const fileHandler = new FileDownloader();
class PackageInfo extends Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
popoverOpen: false
};
}
toggle() {
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
downloadDocument(document){
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}&fileType=${document.documentTypeName}`
const fileName = document.documentName + '.' + document.extension;
fileHandler.download(fileUrl, fileName);
}
render() {
const {orderPackage, onViewChange} = this.props;
const shouldShowPriceInfo = orderPackage.packageRecuringPrice > 0 || orderPackage.packageServicePrice > 0;
return (
<Container fluid={true} id="package-info" className="order-package-info">
<Row>
<Col xl="3">
<div className="subtitle">
<h6>
{orderTexts.labels.PACKAGE_PRICE}: {' '}
{ shouldShowPriceInfo &&
<i className="price-info-btn fa fa-info-circle"
id={'price-info-' + orderPackage.idPackage}
onClick={this.toggle}></i>
}
</h6>
</div>
<div>
{orderTexts.labels.TOTAL_DELVIERY_PRICE}: {' '}
{(orderPackage.units * orderPackage.packageFixedPrice).toLocaleString() + ' ' + orderPackage.packageCurrency.currency}
</div>
{
shouldShowPriceInfo &&
<div>
{orderTexts.labels.TOTAL_RECURRENT_PRICE}:{' '}
{(orderPackage.units * (orderPackage.packageRecuringPrice + orderPackage.packageServicePrice)).toLocaleString()} {orderPackage.packageCurrency.currency}
</div>
}
{ shouldShowPriceInfo &&
<Popover placement="bottom"
isOpen={this.state.popoverOpen}
target={'price-info-' + orderPackage.idPackage}
container={'price-info-' + orderPackage.idPackage}
className="price-info-popover"
toggle={this.toggle}>
<PopoverHeader>{orderPackage.paymentType}</PopoverHeader>
<PopoverBody>
<div>
{ orderPackage.packageRecuringPrice > 0 &&
<div className="package-price-recurrent">
<span className="price-info-title">{orderTexts.labels.RECURRENT_PRICE}: </span>
{(orderPackage.units * orderPackage.packageRecuringPrice).toLocaleString()} {orderPackage.packageCurrency.currency} / {orderPackage.periodUnit}
{
orderPackage.packagePayPeriod > 0 &&
<span>
for {orderPackage.packagePayPeriod} {orderPackage.periodUnit}
</span>
}
</div>
}
{ orderPackage.packageServicePrice > 0 &&
<div className="services-price-recurrent">
<span className="price-info-title">{orderTexts.labels.SERVICES_PRICE}: </span>
{(orderPackage.units * orderPackage.packageServicePrice).toLocaleString()} {orderPackage.packageCurrency.currency} / {orderPackage.periodUnit}
{
orderPackage.servicesContractPeriod > 0 &&
<span>
for {orderPackage.servicesContractPeriod} {orderPackage.periodUnit}
</span>
}
<span> {orderTexts.labels.EXTEND} {orderPackage.periodUnit} (Max {orderPackage.maxContractPeriod} {orderPackage.periodUnit})</span>
</div>
}
</div>
</PopoverBody>
</Popover>
}
</Col>
{
orderPackage.options.length > 0 &&
<Col xl="3">
<div className="subtitle"><h6>{orderTexts.labels.OPTIONS}:</h6></div>
{
orderPackage.options.map((option, index) => <div key={'option-'+index}>
{option.groupName}: {option.packageName}
</div>)
}
</Col>
}
{
orderPackage.additionalPackages.length > 0 &&
<Col xl="3">
<div className="subtitle"><h6>{orderTexts.labels.ADDITIONAL_PACKAGES}:</h6></div>
{
orderPackage.additionalPackages.map((additional, index) => <div key={'additional-'+index}>
{additional.packageName}
</div>)
}
</Col>
}
{
orderPackage.documents &&
<Col xl="2">
<div className="subtitle"><h6>{orderTexts.labels.DOCUMENTS}:</h6></div>
{
orderPackage.documents.length > 0 ?
<div className="link-to-docs" onClick={()=>onViewChange('documents')}>{orderTexts.buttons.SEE_DOCUMENTS}</div>:
<span>{orderTexts.labels.NO_DOCUMENTS}</span>
}
</Col>
}
</Row>
</Container>
);
}
}
export default PackageInfo;

View File

@@ -0,0 +1,16 @@
import React, {Component} from 'react';
import {Link} from 'react-router-dom';
class PackageName extends Component {
render(){
const {orderPackage, idCommercialLead} = this.props.params;
return (
<div>
<Link to={'/co-market/' + idCommercialLead + '/' + orderPackage.idPackage } className="package-name-link">{orderPackage.units + ' x ' + orderPackage.packageName}</Link>
</div>
);
}
}
export default PackageName;

View File

@@ -0,0 +1,23 @@
import React, {Component} from 'react';
import {Row, Col} from 'reactstrap';
import WiaasBox from '../../../../mainComponents/box/WiaasBox.jsx';
import PackageInfo from './PackageInfo.jsx';
import PackageName from './PackageName.jsx';
class ProcessPackage extends Component {
render() {
const {orderPackage, idCommercialLead} = this.props;
return (
<WiaasBox customHeader={PackageName} customHeaderParams={{orderPackage, idCommercialLead}} className="order-package">
<Row>
<Col xl="12" lg="12" md="12" xs="12">
<PackageInfo onViewChange={this.props.onViewChange} orderPackage={orderPackage}/>
</Col>
</Row>
</WiaasBox>
);
}
}
export default ProcessPackage;

View File

@@ -0,0 +1,30 @@
import React, {Component} from 'react';
import {Input} from 'reactstrap';
import {orderTexts} from '../../../../constants/ordersConstants';
class AcceptanceDeclineReason extends Component {
handleEditorChange = (e) => {
const reason = e.target.value;
this.props.params.onEditorChange(reason);
}
render() {
const {actionType} = this.props.params;
return (
<div>
{
actionType === 'accept'
? <div>{orderTexts.labels.ACCEPT_INSTALLATION_TEXT}</div>
: <div>
<div>{orderTexts.labels.DECLINE_REASON_TEXT}</div>
<Input onChange={this.handleEditorChange} type="textarea" name="acceptance-decline-reason" id="installation-declined-reason" />
</div>
}
</div>
);
}
}
export default AcceptanceDeclineReason;

View File

@@ -0,0 +1,193 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Dropzone from 'react-dropzone';
import {Row, Col, Button} from 'reactstrap';
import {fetchCustomerAcceptance, uploadAcceptance, acceptDeclineInstallation, badFile} from '../../../../actions/orders/customerAcceptanceActions';
import {setDialogContent, setDialogOpenFlag} from '../../../../actions/dialog/dialogActions';
import AcceptanceDeclineReason from './AcceptanceDeclineReason.jsx';
import {API_SERVER} from '../../../../config';
import FileDownloader from '../../../../helpers/FileDownloader';
import {orderTexts} from '../../../../constants/ordersConstants';
import '../../style/CustomerAcceptance.css';
const fileHandler = new FileDownloader();
class CustomerAcceptance extends Component {
constructor(props){
super(props);
this.state = {
reason : '',
actionType : ''
}
this.acceptDeclineInstallation = this.acceptDeclineInstallation.bind(this);
this.onEditorChange = this.onEditorChange.bind(this);
}
downloadDocument(document){
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}`
const fileName = document.documentName + '.' + document.extension;
fileHandler.download(fileUrl, fileName);
}
uploadFile(idOrder, acceptedFiles, rejectedFiles) {
if(acceptedFiles && acceptedFiles.length){
const file = acceptedFiles[0];
this.props.dispatch(uploadAcceptance(idOrder, file));
}
if(rejectedFiles && rejectedFiles.length) {
this.props.dispatch(badFile());
}
}
getAcceptanceStatusClass(acceptance, daysDiff) {
const statuses = {
0 : 'waiting',
1 : 'accepted',
'-1' : 'declined'
};
if(acceptance === 0 && daysDiff <= 0){
return 'danger';
} else if(acceptance === 0 && daysDiff <= 3) {
return 'warning';
}else{
return statuses[acceptance];
}
}
acceptDeclineInstallation() {
const {idOrder} = this.props.step;
const {actionType, reason} = this.state;
this.props.dispatch(acceptDeclineInstallation(idOrder, actionType, reason));
this.setState({reason: ''});
}
getAcceptanceMessage(customerAcceptance){
const messages = {
0 : orderTexts.labels.NOT_ACCEPTED + (customerAcceptance.acceptanceDueDate || orderTexts.labels.NOT_SET),
1 : orderTexts.labels.ACCEPTED,
'-1' : orderTexts.labels.DECLINED
}
return messages[customerAcceptance.customerAccepted];
}
onEditorChange(reason) {
this.setState({reason});
}
openDialog(actionType) {
const dialogContent = this.getAcceptanceDialog(actionType);
this.setState({actionType});
this.props.dispatch(setDialogOpenFlag(true));
this.props.dispatch(setDialogContent(dialogContent));
}
getAcceptanceDialog(actionType) {
return {
buttons: [
{
color: 'success',
action: this.acceptDeclineInstallation,
name: orderTexts.buttons.SEND,
id: 'confirm-acceptance'
}, {
color: 'secondary',
name: orderTexts.buttons.CANCEL,
id: 'cancel-acceptance'
}
],
header: orderTexts.labels.ACCEPTANCE_HEADER,
TagName: AcceptanceDeclineReason,
params: {onEditorChange: this.onEditorChange, actionType}
};
}
componentDidMount(){
const {idOrder} = this.props.step;
this.props.dispatch(fetchCustomerAcceptance(idOrder));
}
render() {
const {step} = this.props;
const customerAcceptance = this.props.customerAcceptance || null;
return (
<div id="customer-acceptance" className="validate-questionnaire">
{
customerAcceptance &&
<Row>
<Col className="aceeptance-message">
{this.getAcceptanceMessage(customerAcceptance)} <div className={'status-icon ' + this.getAcceptanceStatusClass(customerAcceptance.customerAccepted, customerAcceptance.daysDiff)}></div>
</Col>
</Row>
}
{
(customerAcceptance && customerAcceptance.customerAccepted === -1) &&
<Row>
<Col>{orderTexts.labels.REASON}: {customerAcceptance.customerDeclineReason}</Col>
</Row>
}
<Row className="acceptance-docs">
<Col xl="4" lg="5" md="4">
<Dropzone className="upload-file-drop-zone"
multiple={false}
accept=".pdf,.docx,.doc,.xlsx,.xls,.odt,.ods,.jpg,.png,.jpeg"
activeClassName="upload-file-accept"
onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(step.idOrder, acceptedFiles, rejectedFiles)}}>
<h5 className="drop-zone-text">{orderTexts.labels.UPLOAD_ACCEPTANCE_LABEL}</h5>
</Dropzone>
</Col>
<Col xl="4" lg="7" md="8">
{
(customerAcceptance && customerAcceptance.acceptanceDocuments && customerAcceptance.acceptanceDocuments.length > 0) &&
<div>
{
customerAcceptance.acceptanceDocuments.map(document => <div key={'acceptance-documnet-' + document.idDocument}>
<span className="document-link"
onClick={() => {this.downloadDocument(document)}}>
<i className={'fa fa-file'}></i> {document.documentName} ({document.extension})
</span>
<span className="document-status">
{document.validation} <div className={'status-icon ' + document.validation}></div>
</span>
</div>)
}
</div>
}
{
(customerAcceptance && !customerAcceptance.acceptanceDocuments) &&
<div>
{orderTexts.labels.NO_DOCUMENTS_UPLOADED}
</div>
}
</Col>
</Row>
<Row>
<Col className="acceptance-label" xl="12" lg="12" md="12" xs="12">
{orderTexts.labels.ACCEPTANCE_LABEL}
</Col>
<Col lg="7">
<Button onClick={()=>{this.openDialog('accept')}}
id="acceptance-accept"
color="secondary"
className="acceptance-button acceptance-accept">{orderTexts.buttons.ACCEPT_INSTALLATION}</Button>
<Button onClick={()=>{this.openDialog('decline')}}
id="acceptance-decline"
color="secondary"
className="acceptance-button acceptance-decline">{orderTexts.buttons.DECLINE_INSTALLATION}</Button>
</Col>
</Row>
</div>
);
}
}
const mapStateToProps = (state) => ({
customerAcceptance: state.processReducer.customerAcceptance
});
export default connect(mapStateToProps)(CustomerAcceptance);

View File

@@ -0,0 +1,54 @@
import React, {Component} from 'react';
import {Row, Col} from 'reactstrap';
import ProcessStep from './ProcessStep.jsx';
import {orderTexts} from '../../../../constants/ordersConstants';
const completedOrdersStatuses = ['production', 'end-of-life'];
class OrderProcess extends Component {
isStepVisible(step) {
return (step.status === 'in-progress' || step.status === 'done') && step.isVisibleForCustomer === 1;
}
render() {
const {orderProcess, orderStatus} = this.props;
const visibleSteps = (orderProcess && orderProcess.steps) ? orderProcess.steps.filter(this.isStepVisible) : [];
if(orderProcess && completedOrdersStatuses.find((status) => {return status === orderStatus;})) {
const processCompleted = {
shortDesc: orderTexts.labels.COMPLETED,
status: 'done',
isVisibleForCustomer: 1,
actualDate: visibleSteps[0].actualDate
};
if(visibleSteps) {
visibleSteps.unshift(processCompleted);
}
}
return (
<div className="order-process">
{
(!orderProcess || !orderProcess.steps) &&
<Row>
<Col xl="12" lg="12" md="12" xs="12">
<div className="no-process-info">{orderTexts.labels.WILL_BE_PROCESS}</div>
</Col>
</Row>
}
{
(orderProcess && orderProcess.steps) &&
<Row>
<Col xl="12" lg="12" md="12" xs="12" className="order-package-process">
{
visibleSteps.map((step, index) => <ProcessStep isStepVisible={this.isStepVisible} stepNumber={visibleSteps.length - index} step={step} key={'step-' + step.idProcess + '-' + step.idProcessStep}/>)
}
</Col>
</Row>
}
</div>
);
}
}
export default OrderProcess;

View File

@@ -0,0 +1,76 @@
import React, {Component} from 'react';
import {Row, Col, Container} from 'reactstrap';
import WiaasBox from '../../../../mainComponents/box/WiaasBox.jsx';
import ValidateQuestionnaire from './ValidateQuestionnaire.jsx';
import CustomerAcceptance from './CustomerAcceptance.jsx';
const stepActions = {
'validate-questionnaire' : ValidateQuestionnaire,
'customer-acceptance' : CustomerAcceptance
}
class OrderStep extends Component {
isActiveStep(status) {
return status === 'in-progress' ;
}
getStepTitle(step, stepNumber) {
return stepNumber + '. ' + step.shortDesc;
}
getDayFromActual(step) {
const date = step.actualDate || step.now;
const dateParts = date.split(' ');
return dateParts[0];
}
getMonthFromActual(step) {
const date = step.actualDate || step.now;
const dateParts = date.split(' ');
const dateParts2 = dateParts[1].split(',');
return dateParts2[0];
}
render() {
const {step, stepNumber, isStepVisible} = this.props;
const TagName = step.actionCode !== 'manual' && stepActions[step.actionCode] ? stepActions[step.actionCode] : null;
return (
<Container fluid={true} className="order-step">
{
isStepVisible(step) &&
<Row className="step-layer">
<Col xl="1" lg="1" md="2" xs="2" className="step-circle-layer">
<div className="step-line"></div>
<div className={'step-circle ' + step.status}>
{!this.isActiveStep(step.status) &&
<span>
<div>{this.getDayFromActual(step)}</div>
<div>{this.getMonthFromActual(step)}</div>
</span>
}
</div>
</Col>
<Col xl="11" lg="11" md="10" xs="10" className="step-box-layer">
<WiaasBox isContentVisible={this.isActiveStep(step.status)} className={'step-box'} mainTitle={this.getStepTitle(step, stepNumber)}>
{
(this.isActiveStep(step.status) && TagName) &&
<Col>
{
(TagName && this.isActiveStep(step.status)) && <TagName step={step}/>
}
</Col>
}
</WiaasBox>
</Col>
</Row>
}
</Container>
);
}
}
export default OrderStep;

View File

@@ -0,0 +1,46 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {fetchCustomerDocuments, fetchValidationComments} from '../../../../actions/orders/processActions';
import ValidateQuestionnaireItem from './ValidateQuestionnaireItem.jsx';
import '../../style/ValidateQuestionnaire.css';
class ValidateQuestionnaire extends Component {
componentDidMount(){
const {idOrder, idProcessStep} = this.props.step;
this.props.dispatch(fetchCustomerDocuments(idOrder, 'orderQuestionaire'));
this.props.dispatch(fetchValidationComments(idOrder, idProcessStep, 'invalidQuestionnaireComment'));
}
findById(orderPackage, idOrderPackagePair){
const idPackage = idOrderPackagePair.split('-')[1];
return orderPackage.idPackage === parseInt(idPackage, 10);
}
render() {
const {customerDocuments, validationComments, orderPackages} = this.props;
return (
<div id="validate-questionnaire" className="validate-questionnaire">
{
customerDocuments &&
Object.keys(customerDocuments).map((idOrderPackagePair) =>
<ValidateQuestionnaireItem
customerDocuments={customerDocuments[idOrderPackagePair]}
validationComments={validationComments && validationComments[idOrderPackagePair] ? validationComments[idOrderPackagePair] : []}
orderPackage={orderPackages.find((orderPackage)=>{ return this.findById(orderPackage, idOrderPackagePair)})}
key={'validate-questionnaire-' + idOrderPackagePair}/>
)
}
</div>
);
}
}
const mapStateToProps = (state) => ({
customerDocuments: state.processReducer.customerDocuments,
validationComments: state.processReducer.validationComments,
orderPackages: state.processReducer.orderInfo.packages
});
export default connect(mapStateToProps)(ValidateQuestionnaire);

View File

@@ -0,0 +1,99 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Dropzone from 'react-dropzone';
import {Row, Col} from 'reactstrap';
import {reUploadOrderDocument, badFile} from '../../../../actions/orders/processActions';
import {API_SERVER} from '../../../../config';
import FileDownloader from '../../../../helpers/FileDownloader';
import {orderTexts} from '../../../../constants/ordersConstants';
const fileHandler = new FileDownloader();
class ValidateQuestionnaireItem extends Component {
downloadDocument(document){
const fileUrl = `${API_SERVER}/utils/api/downloadFile?idDocument=${document.idDocument}&fileName=${document.documentName}.${document.extension}`
const fileName = document.documentName + '.' + document.extension;
fileHandler.download(fileUrl, fileName);
}
uploadFile(idPackage, idOrder, idDocument,acceptedFiles, rejectedFiles) {
if(acceptedFiles && acceptedFiles.length){
const file = acceptedFiles[0];
this.props.dispatch(reUploadOrderDocument(idPackage, idOrder, idDocument, file));
}
if(rejectedFiles && rejectedFiles.length) {
this.props.dispatch(badFile());
}
}
render() {
const {customerDocuments, validationComments, orderPackage} = this.props;
return (
<div id="validate-questionnaire" className="validate-questionnaire">
{
customerDocuments &&
<div>
{orderPackage.packageName}
{
customerDocuments.map(document => <div key={'package-document-' + document.idDocument}>
{
document.validation === 'invalid'
? <div className="package-document">
<Row>
<Col xl="7" lg="8">
<div>
<span className="document-link"
onClick={() => {this.downloadDocument(document)}}>
<i className={'fa fa-file'}></i> {document.documentName} ({document.extension}) {' '}
</span>
<span className="document-status">
{document.validation.replace(/-/g,' ')} <div className={'status-icon ' + document.validation}></div>
</span>
</div>
{
(validationComments && validationComments.length > 0) &&
<div>
{validationComments.map((comment, key) => <div key={'step-comment-' + document.idDocument + '-' + key} className="step-comment">
<div>{comment.user} - {comment.addDate}</div>
<div>{comment.comment}</div>
</div>)}
</div>
}
</Col>
<Col xl="5">
<Dropzone className="upload-file-drop-zone"
multiple={false}
accept=".pdf,.docx,.doc,.xlsx,.xls,.odt,.ods"
activeClassName="upload-file-accept"
onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(document.idPackage, document.idOrder, document.idDocument, acceptedFiles, rejectedFiles)}}>
<h5 className="drop-zone-text">{orderTexts.labels.SELECT_OR_DROP}</h5>
</Dropzone>
</Col>
</Row>
</div>
: <div className="package-document">
<Row>
<Col>
<span className="document-link"
onClick={() => {this.downloadDocument(document)}}>
<i className={'fa fa-file'}></i> {document.documentName} ({document.extension}) {' '}
</span>
<span className="document-status">
{document.validation.replace(/-/g,' ')} <div className={'status-icon ' + document.validation}></div>
</span>
</Col>
</Row>
</div>
}
</div>)
}
</div>
}
</div>
);
}
}
export default connect()(ValidateQuestionnaireItem);