Handle wiaas documents
This commit is contained in:
@@ -225,15 +225,15 @@ export const previousStep = (params) => ({type: GO_TO_PREVIOUS_STEP, params});
|
||||
|
||||
export const uploadDocumnet = () => ({type: UPLOAD_DOCUMENT});
|
||||
|
||||
export const uploadOrderDocument = (idPackage, idDocumentType, file, packages) => {
|
||||
export const uploadOrderDocument = (packageCartKey, idDocumentType, file, packages) => {
|
||||
return dispatch => {
|
||||
dispatch(uploadDocumnet());
|
||||
|
||||
return client.uploadFile(file, {
|
||||
url: `${API_SERVER}/cart/api/uploadOrderDocument`,
|
||||
url: `${API_SERVER}/wp-json/wiaas/cart/documents`,
|
||||
data: {
|
||||
idDocumentType,
|
||||
idPackage
|
||||
'doc_type': idDocumentType,
|
||||
'package_key': packageCartKey
|
||||
}
|
||||
}).then(response => {
|
||||
if (typeof response.data !== 'undefined' && 'messages' in response.data) {
|
||||
@@ -266,30 +266,21 @@ export const fetchCartDocuments = (packages, isForSteps = false) => {
|
||||
return dispatch => {
|
||||
dispatch(requestCartDocuments());
|
||||
|
||||
dispatch(receiveCartDocuments({
|
||||
areFilesUploaded: true,
|
||||
templates: [],
|
||||
uploaded: []
|
||||
}));
|
||||
if(isForSteps) {
|
||||
dispatch(loadSteps(true));
|
||||
}
|
||||
|
||||
// return client.fetch({
|
||||
// url: `${API_SERVER}/wp-json/wiaas/cart/documents`,
|
||||
// method: 'get',
|
||||
// data: {packages}
|
||||
// }).then(response => {
|
||||
// if (response.data) {
|
||||
// dispatch(receiveCartDocuments(response.data));
|
||||
// if(isForSteps) {
|
||||
// const whitoutUploadDoc = response.data.templates.length === 0;
|
||||
// dispatch(loadSteps(whitoutUploadDoc));
|
||||
// }
|
||||
// }
|
||||
// }).catch(error => {
|
||||
// client.onError(error, dispatch);
|
||||
// });
|
||||
return client.fetch({
|
||||
url: `${API_SERVER}/wp-json/wiaas/cart/documents`,
|
||||
method: 'get',
|
||||
data: {packages}
|
||||
}).then(response => {
|
||||
if (response.data) {
|
||||
dispatch(receiveCartDocuments(response.data));
|
||||
if(isForSteps) {
|
||||
const whitoutUploadDoc = response.data.templates.length === 0;
|
||||
dispatch(loadSteps(whitoutUploadDoc));
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
client.onError(error, dispatch);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,9 +147,9 @@ export const cartTexts = {
|
||||
DOC_NOT_REQUIRED: 'Document not required',
|
||||
FILE_UPLOADED_TEXT: 'File uploaded! Select or drop to replace ',
|
||||
FILE: 'file',
|
||||
NO_FILE_UPLOAD_TEXT_1: 'Click here to select',
|
||||
NO_FILE_UPLOAD_TEXT_2: 'or drag and drop file here',
|
||||
TEMPLATES: 'Templates',
|
||||
NO_FILE_UPLOAD_TEXT_1: 'Drag and drop',
|
||||
NO_FILE_UPLOAD_TEXT_2: 'click to upload',
|
||||
TEMPLATE: 'Template',
|
||||
UPLOADED: 'Uploaded dcuments',
|
||||
PACKAGE_UNAVAILABLE: 'This package is no longer available. Remove it from the cart to place the order successfully',
|
||||
BID_AVAILABLE: 'Bids available!',
|
||||
@@ -167,7 +167,7 @@ export const cartTexts = {
|
||||
buttons: {
|
||||
YES: 'Yes',
|
||||
CANCEL: 'Cancel',
|
||||
PREVIOUS: 'Previous',
|
||||
BACK: 'Back',
|
||||
NEXT: 'Next',
|
||||
ADD_ADDRESS: 'Add address',
|
||||
USE: 'Use',
|
||||
|
||||
@@ -38,7 +38,7 @@ class CartStepsContainer extends Component {
|
||||
{(cartSteps && cartSteps[currentStep] && cartSteps[currentStep].previous && !isLoading) &&
|
||||
<span onClick={()=>{this.handleStepChange('previous')}} className="prev-btn">
|
||||
<Col sm="12" xs="12">
|
||||
{cartTexts.buttons.PREVIOUS}
|
||||
{cartTexts.buttons.BACK}
|
||||
</Col>
|
||||
</span>
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import {updateMessages} from '../../actions/notification/notificationActions';
|
||||
import {nextStep, setNextActionFct} from '../../actions/cart/cartActions';
|
||||
|
||||
const DOCUMENT_TYPES = {
|
||||
TEMPLATE_QUESTINNAIRE: 1,
|
||||
QUESTIONNAIRE: 2,
|
||||
TEMPLATE_AGREEMENT: 6,
|
||||
AGREEMENT: 7
|
||||
TEMPLATE_QUESTINNAIRE: 'template_questionaire',
|
||||
QUESTIONNAIRE: 'order_questionaire',
|
||||
TEMPLATE_AGREEMENT: 'template_agreement',
|
||||
AGREEMENT: 'order_agreement'
|
||||
};
|
||||
|
||||
class CartCustomerQuestionnaireContainer extends Component {
|
||||
@@ -34,7 +34,7 @@ class CartCustomerQuestionnaireContainer extends Component {
|
||||
}
|
||||
|
||||
handleStepChange() {
|
||||
if(this.props.cartDocuments && this.props.cartDocuments.areFilesUploaded) {
|
||||
if(this.props.cartDocuments && !this.props.cartDocuments.pending) {
|
||||
this.props.dispatch(nextStep());
|
||||
} else {
|
||||
this.props.dispatch(updateMessages([{code:'warning', message: 'DOCS_MISSING'}], cartMessages));
|
||||
|
||||
@@ -6,11 +6,13 @@ import Dropzone from 'react-dropzone';
|
||||
import {API_SERVER} from '../../../config';
|
||||
import FileDownloader from '../../../helpers/FileDownloader';
|
||||
import {cartTexts} from '../../../constants/cartConstants';
|
||||
import {getDocumentIcon} from '../../../helpers/DocumentHelper';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const fileHandler = new FileDownloader();
|
||||
const documentTypes = {
|
||||
2 : 'Customer Questionnaire',
|
||||
7 : 'Customer Agreement'
|
||||
'order_questionaire' : 'Customer Questionnaire',
|
||||
'order_agreement' : 'Customer Agreement'
|
||||
};
|
||||
|
||||
class CartUploadDocument extends Component {
|
||||
@@ -20,11 +22,11 @@ class CartUploadDocument extends Component {
|
||||
this.uploadFile = this.uploadFile.bind(this);
|
||||
}
|
||||
|
||||
uploadFile(idPackage, idDocumentType,acceptedFiles, rejectedFiles, packages){
|
||||
uploadFile(packageCartKey, idDocumentType,acceptedFiles, rejectedFiles, packages){
|
||||
const self = this;
|
||||
|
||||
acceptedFiles.forEach(file => {
|
||||
self.props.dispatch(uploadOrderDocument(idPackage, idDocumentType, file, packages));
|
||||
self.props.dispatch(uploadOrderDocument(packageCartKey, idDocumentType, file, packages));
|
||||
});
|
||||
|
||||
if(rejectedFiles && rejectedFiles.length) {
|
||||
@@ -33,9 +35,15 @@ class CartUploadDocument 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);
|
||||
fileHandler.download(
|
||||
`${API_SERVER}/wp-json/wiaas/cart/items/${this.props.cartItem.key}/documents/${this.props.idDocumentType}?document_key=${document.key}`,
|
||||
document.name);
|
||||
}
|
||||
|
||||
downloadTemplate(document) {
|
||||
fileHandler.download(
|
||||
`${API_SERVER}/wp-json/wiaas/documents?document_id=${document.id}`,
|
||||
document.name);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -45,30 +53,51 @@ class CartUploadDocument extends Component {
|
||||
{
|
||||
templateDocument &&
|
||||
<div>
|
||||
<Dropzone className="upload-file-drop-zone"
|
||||
<div className="cart-template">
|
||||
<p className="cart-subtitle">{documentTypes[idDocumentType]} {cartTexts.labels.TEMPLATE}:</p>
|
||||
<p className="document-link" onClick={() => {this.downloadTemplate(templateDocument)}}>
|
||||
<i className={`fa fa-${getDocumentIcon(templateDocument.extension)}`} aria-hidden="true"></i> {templateDocument.name}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Dropzone className={classnames('upload-file-drop-zone', { 'pending-upload': !uploadedDocument })}
|
||||
accept=".pdf,.docx,.doc,.xlsx,.xls,.odt,.ods"
|
||||
onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(cartItem.idPackage, idDocumentType, acceptedFiles, rejectedFiles, packages)}}>
|
||||
onDrop={(acceptedFiles, rejectedFiles)=>{this.uploadFile(cartItem.key, idDocumentType, acceptedFiles, rejectedFiles, packages)}}>
|
||||
{
|
||||
uploadedDocument
|
||||
? <h6 className="drop-zone-text uploaded">{cartTexts.labels.FILE_UPLOADED_TEXT} {documentTypes[idDocumentType]} {cartTexts.labels.FILE}</h6>
|
||||
: <h6 className="drop-zone-text">{cartTexts.labels.NO_FILE_UPLOAD_TEXT_1} {documentTypes[idDocumentType]} {cartTexts.labels.NO_FILE_UPLOAD_TEXT_2}</h6>
|
||||
? (
|
||||
<div>
|
||||
<h1 className="drop-zone-icon">
|
||||
<i className="fa fa-upload"></i>
|
||||
</h1>
|
||||
<h6 className="drop-zone-text">{uploadedDocument.name}</h6>
|
||||
<span className="drop-zone-text">
|
||||
Drag and drop or click to replace file
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div>
|
||||
<h1 className="drop-zone-icon pending-upload">
|
||||
<i className="fa fa-upload"></i>
|
||||
</h1>
|
||||
<span className="drop-zone-text">
|
||||
Drag and drop or click to upload file
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Dropzone>
|
||||
{
|
||||
uploadedDocument &&
|
||||
<div>
|
||||
<div className="cart-subtitle">{cartTexts.labels.UPLOADED}:</div>
|
||||
<div className="document-link" onClick={() => {this.downloadDocument(uploadedDocument)}}>
|
||||
<i className="fa fa-file" aria-hidden="true"></i>
|
||||
{' ' + uploadedDocument.documentName + ' (' + uploadedDocument.extension + ')'}
|
||||
</div>
|
||||
<span className="document-link" onClick={() => {this.downloadDocument(uploadedDocument)}}>
|
||||
<strong>
|
||||
<i className={`fa fa-${getDocumentIcon(uploadedDocument.extension)}`} aria-hidden="true"></i> {uploadedDocument.name}
|
||||
</strong>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
<div className="cart-subtitle">{cartTexts.labels.TEMPLATES}:</div>
|
||||
<div className="document-link" onClick={() => {this.downloadDocument(templateDocument)}}>
|
||||
<i className="fa fa-file" aria-hidden="true"></i>
|
||||
{' ' + templateDocument.documentName + ' (' + templateDocument.extension + ')'}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -6,19 +6,37 @@
|
||||
|
||||
.upload-file-drop-zone {
|
||||
width: 100%;
|
||||
border: 3px dashed $borderColor;
|
||||
margin-top: 1rem;
|
||||
height: 5rem;
|
||||
border: 1px dashed $borderColor;
|
||||
margin: 1rem 0;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
&:hover {
|
||||
background-color: $lightHoverColor;
|
||||
}
|
||||
color: $font-light-color;
|
||||
&.pending-upload {
|
||||
border: 1px dashed $accentColor;
|
||||
|
||||
.drop-zone-icon, .drop-zone-text {
|
||||
color: $accentColor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.drop-zone-text {
|
||||
text-align: center;
|
||||
padding: 1.3rem 0.5rem;
|
||||
color: $font-light-color;
|
||||
padding: 0;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.uploaded {
|
||||
color: #155724;
|
||||
.drop-zone-icon {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
|
||||
.next-btn {
|
||||
@@ -28,18 +46,33 @@
|
||||
color: $darkGreyColor;
|
||||
}
|
||||
|
||||
.cart-template {
|
||||
margin: 1rem 0;
|
||||
.cart-subtitle {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-subtitle {
|
||||
font-weight: $font-weight;
|
||||
color: $font-light-color;
|
||||
font-size: $font-size-small;
|
||||
padding-top: 0.3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-layer{
|
||||
background: $whiteColor;
|
||||
padding-bottom: 1rem;
|
||||
padding: 1rem;
|
||||
color: $title-color;
|
||||
|
||||
.upload-layer {
|
||||
color: $title-color;
|
||||
}
|
||||
|
||||
.document-link{
|
||||
cursor: pointer;
|
||||
color: #2b6279;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ const fileHandler = new FileDownloader();
|
||||
|
||||
class PackageInfo extends Component {
|
||||
downloadDocument(document){
|
||||
const fileUrl = `${API_SERVER}/wp-json/wiaas/download-package-file?document_id=${document.idDocument}&package_id=${document.idPackage}`
|
||||
const fileName = document.documentName + '.' + document.extension;
|
||||
fileHandler.download(fileUrl, fileName);
|
||||
fileHandler.download(
|
||||
`${API_SERVER}/wp-json/wiaas/documents?document_id=${document.id}`,
|
||||
document.name);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -41,9 +41,9 @@ class PackageInfo extends Component {
|
||||
<div className="shop-package-label">{coMarketTexts.labels.DOCUMENTS}:</div>
|
||||
{
|
||||
documents.map((document) =>
|
||||
<span key={document.idDocument} className="document-link"
|
||||
<span key={document.id} className="document-link"
|
||||
onClick={() => {this.downloadDocument(document)}}>
|
||||
<i className="fa fa-file" aria-hidden="true"></i> {document.documentName} ({document.extension})
|
||||
<i className={`fa fa-${document.icon}`} aria-hidden="true"></i> {document.name}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,12 @@ class OrderDocuments extends Component {
|
||||
return (
|
||||
<div id="order-documents" className="order-documents">
|
||||
{
|
||||
orderInfo.packages.map(orderPackage => <OrderDocumentsGroup key={'order-package-' + orderPackage.id} documentsGroup={orderPackage} />)
|
||||
orderInfo.packages.map(orderPackage => (
|
||||
<OrderDocumentsGroup
|
||||
key={'order-package-' + orderPackage.id}
|
||||
orderId={orderInfo.id}
|
||||
documentsGroup={orderPackage}
|
||||
/>))
|
||||
}
|
||||
{
|
||||
orderInfo.orderDocuments && <OrderDocumentsGroup key={'order-package-0'} documentsGroup={{documents: orderInfo.documents, packageName: orderTexts.labels.OTHER_DOCS}} />
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
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';
|
||||
@@ -18,62 +17,39 @@ const iconTypes = {
|
||||
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);
|
||||
downloadDocument(orderId, itemId, document){
|
||||
const fileUrl = `${API_SERVER}/wp-json/wiaas/documents/order/${orderId}/${document.type}?item_id=${itemId}&document_key=${document.key}`;
|
||||
fileHandler.download(fileUrl, document.name);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {documentsGroup} = this.props;
|
||||
const {documentsGroup, orderId} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
documentsGroup.documents &&
|
||||
documentsGroup.documents.length > 0 &&
|
||||
<WiaasBox mainTitle={documentsGroup.packageName}>
|
||||
<WiaasBox mainTitle={documentsGroup.name}>
|
||||
{
|
||||
documentsGroup.documents.map(document => <a id={'document-' + document.idDocument} key={'order-document-' + document.idDocument}>
|
||||
<div onClick={() => {this.downloadDocument(document)}} className="document-link-big">
|
||||
documentsGroup.documents.map(document => <a id={'document-' + document.key} key={'order-document-' + document.key}>
|
||||
<div onClick={() => {this.downloadDocument(orderId, documentsGroup.orderItemId, 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>
|
||||
{document.name}
|
||||
</div>
|
||||
</div></a>)
|
||||
}
|
||||
|
||||
17
frontend/src/helpers/DocumentHelper.js
Normal file
17
frontend/src/helpers/DocumentHelper.js
Normal file
@@ -0,0 +1,17 @@
|
||||
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'
|
||||
};
|
||||
|
||||
export const getDocumentIcon = extension => {
|
||||
return iconTypes[extension] || 'file';
|
||||
};
|
||||
@@ -7,6 +7,7 @@ class FileDownloader {
|
||||
download(fileUrl, fileName){
|
||||
htmlClient.fetch({
|
||||
url: fileUrl,
|
||||
method: 'get',
|
||||
responseType: 'arraybuffer'
|
||||
})
|
||||
.then((response) => {
|
||||
|
||||
@@ -45,14 +45,14 @@ class HtmlClient {
|
||||
uploadFile(file, configParams = null) {
|
||||
let formData = new FormData();
|
||||
formData.append('file', file, file.name);
|
||||
/*
|
||||
|
||||
if(configParams) {
|
||||
|
||||
|
||||
Object.keys(configParams.data).forEach((paramKey) => {
|
||||
formData.append(paramKey, configParams.data[paramKey]);
|
||||
});
|
||||
|
||||
}*/
|
||||
|
||||
}
|
||||
configParams.data = formData;
|
||||
const params = Object.assign({}, uploadParams(), configParams);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import moment from 'moment';
|
||||
import {fromWiaasProcessStep} from './ProcessHelper';
|
||||
import { getDocumentIcon } from './DocumentHelper';
|
||||
|
||||
function formatDate(date) {
|
||||
return date ? moment(date).format("Do MMM, YYYY") : undefined;
|
||||
@@ -40,6 +41,7 @@ export const fromWCOrder = (WCOrder) => {
|
||||
packages: WCOrder['line_items'].map(packageLine => {
|
||||
return {
|
||||
id: packageLine['product_id'],
|
||||
orderItemId: packageLine['id'],
|
||||
name: packageLine.name,
|
||||
quantity: packageLine.quantity,
|
||||
price: packageLine.price,
|
||||
@@ -62,6 +64,10 @@ export const fromWCOrder = (WCOrder) => {
|
||||
packageName: packageOption.name,
|
||||
groupName: packageOption['group_name'] || '',
|
||||
})) : [],
|
||||
documents: packageLine.documents.map(document => {
|
||||
document['icon'] = getDocumentIcon(document.extension);
|
||||
return document;
|
||||
}) || []
|
||||
};
|
||||
}),
|
||||
process: processInfo,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { getDocumentIcon } from './DocumentHelper';
|
||||
|
||||
const DEFAULT_PACKAGE_IMG = 'static/img/no-photo-package.jpg';
|
||||
|
||||
@@ -49,12 +50,10 @@ export const fromWCPackage = wcPackage => {
|
||||
country: wcPackage.country,
|
||||
countryCode: wcPackage['country_code'],
|
||||
currency: wcPackage.currency,
|
||||
documents: wcPackage.documents ? wcPackage.documents.map(document => ({
|
||||
idDocument: document.id,
|
||||
documentName: document.name,
|
||||
extension: document.extension,
|
||||
idPackage: wcPackage.id,
|
||||
})) : [],
|
||||
documents: wcPackage.documents ? wcPackage.documents.map(document => {
|
||||
document.icon = getDocumentIcon(document.extension);
|
||||
return document;
|
||||
}) : [],
|
||||
shortDescription: wcPackage.description,
|
||||
prices: extractPrices(wcPackage.id, wcPackage.prices || []),
|
||||
groups: extractGroups(wcPackage.groups || {}),
|
||||
|
||||
Reference in New Issue
Block a user