@evershop/evershop 1.0.0-beta.2 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +34 -51
  2. package/bin/lib/app.js +2 -1
  3. package/package.json +1 -1
  4. package/src/lib/components/Area.js +3 -3
  5. package/src/lib/components/form/Form.js +19 -5
  6. package/src/lib/components/form/fields/Hidden.js +13 -9
  7. package/src/lib/components/form/fields/Radio.js +1 -1
  8. package/src/modules/base/graphql/types/Country/Country.graphql +2 -0
  9. package/src/modules/base/graphql/types/Country/Country.resolvers.js +11 -1
  10. package/src/modules/catalog/components/product/list/List.js +18 -2
  11. package/src/modules/catalog/graphql/types/Category/Category.resolvers.js +37 -3
  12. package/src/modules/catalog/graphql/types/FeaturedProduct/FeaturedProduct.resolvers.js +1 -0
  13. package/src/modules/catalog/migration/Version-1.0.1.js +8 -0
  14. package/src/modules/catalog/pages/admin/attributeEdit/index.js +2 -2
  15. package/src/modules/catalog/pages/admin/attributeEdit+attributeNew/General.js +1 -1
  16. package/src/modules/catalog/pages/admin/attributeGrid/rows/GroupRow.js +2 -1
  17. package/src/modules/catalog/pages/admin/productEdit+productNew/VariantGroup.js +1 -0
  18. package/src/modules/catalog/pages/admin/productEdit+productNew/variants/Variant.js +1 -1
  19. package/src/modules/catalog/pages/frontStore/categoryView/CategoryView.js +22 -0
  20. package/src/modules/catalog/pages/frontStore/categoryView/Filter.js +68 -52
  21. package/src/modules/catalog/pages/frontStore/categoryView/Filter.scss +43 -8
  22. package/src/modules/catalog/pages/frontStore/categoryView/General.js +12 -40
  23. package/src/modules/catalog/pages/frontStore/categoryView/General.scss +5 -0
  24. package/src/modules/catalog/pages/frontStore/categoryView/Pagination.js +2 -2
  25. package/src/modules/catalog/pages/frontStore/categoryView/Products.js +5 -5
  26. package/src/modules/catalog/{components/product/list → pages/frontStore/categoryView}/Sorting.js +31 -17
  27. package/src/modules/catalog/pages/frontStore/categoryView/[index]filters.js +0 -1
  28. package/src/modules/catalog/pages/frontStore/homepage/FeaturedCategories.js +3 -3
  29. package/src/modules/catalog/pages/frontStore/homepage/FeaturedProducts.js +1 -1
  30. package/src/modules/checkout/api/frontStore/addToCart/{addToCart.js → [detectCurrentCart]addToCart.js} +1 -1
  31. package/src/modules/checkout/api/frontStore/addToCart/[tokenVerify]detectCurrentCart[auth].js +3 -0
  32. package/src/modules/checkout/api/frontStore/checkoutPlaceOrder/route +1 -1
  33. package/src/modules/checkout/api/frontStore/checkoutSetContactInfo/saveContactInfo.js +4 -4
  34. package/src/modules/checkout/api/frontStore/checkoutSetPaymentInfo/savePaymentInfo.js +26 -4
  35. package/src/modules/checkout/api/frontStore/checkoutSetShipmentInfo/saveShipmentInfo.js +4 -4
  36. package/src/modules/checkout/components/frontStore/checkout/payment/paymentStep/StepContent.js +43 -83
  37. package/src/modules/checkout/components/frontStore/checkout/shipment/StepContent.js +1 -2
  38. package/src/modules/checkout/pages/admin/all/CheckoutMenuGroup.js +1 -1
  39. package/src/modules/checkout/pages/admin/orderEdit/Payment.js +8 -1
  40. package/src/modules/checkout/pages/admin/orderEdit/payment/Total.js +1 -0
  41. package/src/modules/checkout/pages/frontStore/all/[tokenVerify]detectCurrentCart[auth].js +7 -1
  42. package/src/modules/checkout/pages/frontStore/cart/ShoppingCart.js +1 -0
  43. package/src/modules/checkout/pages/frontStore/checkout/Checkout.js +1 -1
  44. package/src/modules/checkout/pages/frontStore/checkout/PaymentStep.js +1 -2
  45. package/src/modules/checkout/pages/frontStore/checkoutSuccess/CustomerInfo.js +1 -1
  46. package/src/modules/checkout/services/cart/Cart.js +130 -106
  47. package/src/modules/checkout/services/cart/DataObject.js +37 -11
  48. package/src/modules/checkout/services/cart/Item.js +153 -115
  49. package/src/modules/checkout/services/orderCreator.js +2 -0
  50. package/src/modules/checkout/services/toPrice.js +1 -0
  51. package/src/modules/cms/api/admin/imageUpload/[context]multerFile[auth].js +1 -1
  52. package/src/modules/cms/pages/admin/all/CmsMenuGroup.js +1 -1
  53. package/src/modules/cms/pages/frontStore/all/Meta.js +1 -0
  54. package/src/modules/cms/pages/frontStore/all/MobileMenu.js +2 -2
  55. package/src/modules/cms/pages/frontStore/homepage/MainBanner.js +8 -4
  56. package/src/modules/cms/pages/frontStore/homepage/MainBanner.scss +6 -7
  57. package/src/modules/cod/api/frontStore/codCapturePayment/[bodyParser]capture.js +51 -0
  58. package/src/modules/cod/api/frontStore/codCapturePayment/bodyParser.js +5 -0
  59. package/src/modules/cod/api/frontStore/codCapturePayment/route +2 -0
  60. package/src/modules/cod/api/frontStore/paymentMethods/[validateCart]registerCod[sendMethods].js +14 -0
  61. package/src/modules/cod/bootstrap.js +20 -0
  62. package/src/modules/cod/components/CODLogo.js +5 -0
  63. package/src/modules/cod/graphql/types/CODSetting/CODSetting.graphql +5 -0
  64. package/src/modules/cod/graphql/types/CODSetting/CODSetting.resolvers.js +20 -0
  65. package/src/modules/cod/pages/admin/orderEdit/CaptureButton.js +54 -0
  66. package/src/modules/cod/pages/admin/paymentSetting/CODSetting.js +59 -0
  67. package/src/modules/cod/pages/frontStore/checkout/CashOnDelivery.js +70 -0
  68. package/src/modules/customer/components/Address/AddressForm/AddressForm.js +106 -0
  69. package/src/modules/customer/components/Address/AddressForm/AddressFormLoadingSkeleton.js +18 -0
  70. package/src/modules/customer/components/Address/AddressForm/AddressFormLoadingSkeleton.scss +27 -0
  71. package/src/modules/customer/components/Address/AddressForm/Country.js +36 -0
  72. package/src/modules/customer/components/Address/AddressForm/Index.js +35 -0
  73. package/src/modules/customer/components/Address/AddressForm/NameAndTelephone.js +43 -0
  74. package/src/modules/customer/components/Address/AddressForm/Province.js +42 -0
  75. package/src/modules/customer/components/Address/AddressForm/ProvinceAndPostcode.js +52 -0
  76. package/src/modules/customer/{pages/frontStore/address → components/Address}/AddressSummary.js +1 -1
  77. package/src/modules/customer/pages/admin/all/CustomerMenuGroup.js +1 -1
  78. package/src/modules/customer/pages/frontStore/all/UserIcon.js +1 -1
  79. package/src/modules/customer/pages/frontStore/checkout/CustomerInfoStep.js +7 -2
  80. package/src/modules/graphql/api/frontStore/graphql/[bodyParser]graphql.js +8 -0
  81. package/src/modules/paypal/api/frontStore/paymentMethods/[validateCart]registerPaypal[sendMethods].js +21 -0
  82. package/src/modules/paypal/api/frontStore/paypalAuthorizePayment/[bodyParser]authorize.js +76 -0
  83. package/src/modules/paypal/api/frontStore/paypalAuthorizePayment/bodyParser.js +5 -0
  84. package/src/modules/paypal/api/frontStore/paypalAuthorizePayment/route +2 -0
  85. package/src/modules/paypal/api/frontStore/paypalCapturePayment/[bodyParser]capture.js +74 -0
  86. package/src/modules/paypal/api/frontStore/paypalCapturePayment/bodyParser.js +5 -0
  87. package/src/modules/paypal/api/frontStore/paypalCapturePayment/route +2 -0
  88. package/src/modules/paypal/api/frontStore/paypalCreateOrder/[bodyParser]createOrder.js +168 -0
  89. package/src/modules/paypal/api/frontStore/paypalCreateOrder/bodyParser.js +5 -0
  90. package/src/modules/paypal/api/frontStore/paypalCreateOrder/route +2 -0
  91. package/src/modules/paypal/api/frontStore/paypalGetAccessToken/[bodyParser]getAccessToken.js +66 -0
  92. package/src/modules/paypal/api/frontStore/paypalGetAccessToken/bodyParser.js +5 -0
  93. package/src/modules/paypal/api/frontStore/paypalGetAccessToken/route +2 -0
  94. package/src/modules/paypal/bootstrap.js +20 -0
  95. package/src/modules/paypal/components/PaypalLogo.js +5 -0
  96. package/src/modules/paypal/graphql/types/PaypalSetting/PaypalSetting.graphql +9 -0
  97. package/src/modules/paypal/graphql/types/PaypalSetting/PaypalSetting.resolvers.js +90 -0
  98. package/src/modules/paypal/migration/Version-1.0.0.js +7 -0
  99. package/src/modules/paypal/pages/admin/paymentSetting/PaypalSetting.js +119 -0
  100. package/src/modules/paypal/pages/frontStore/checkout/Paypal.js +137 -0
  101. package/src/modules/paypal/pages/frontStore/paypalCancel/index.js +29 -0
  102. package/src/modules/paypal/pages/frontStore/paypalCancel/route +2 -0
  103. package/src/modules/paypal/pages/frontStore/paypalReturn/Error.js +13 -0
  104. package/src/modules/paypal/pages/frontStore/paypalReturn/index.js +51 -0
  105. package/src/modules/paypal/pages/frontStore/paypalReturn/route +2 -0
  106. package/src/modules/paypal/services/getApiBaseUrl.js +5 -0
  107. package/src/modules/promotion/bootstrap.js +67 -66
  108. package/src/modules/promotion/pages/admin/all/CouponMenuGroup.js +1 -1
  109. package/src/modules/promotion/services/{couponValidator.js → CouponValidator.js} +0 -0
  110. package/src/modules/promotion/services/{discountCalculator.js → DiscountCalculator.js} +21 -18
  111. package/src/modules/setting/graphql/types/ShippingSetting/ShippingSetting.graphql +1 -1
  112. package/src/modules/setting/graphql/types/ShippingSetting/ShippingSetting.resolvers.js +5 -5
  113. package/src/modules/setting/pages/admin/paymentSetting/PaymentSetting.js +1 -1
  114. package/src/modules/setting/pages/admin/shippingSetting/ShippingSetting.js +4 -4
  115. package/src/modules/setting/pages/admin/storeSetting/StoreSetting.js +6 -6
  116. package/src/modules/stripe/bootstrap.js +20 -0
  117. package/src/modules/stripe/components/StripeLogo.js +5 -0
  118. package/src/modules/stripe/pages/frontStore/checkout/CheckoutForm.js +20 -26
  119. package/src/modules/stripe/pages/frontStore/checkout/Stripe.js +87 -0
  120. package/src/modules/checkout/components/frontStore/checkout/address/AddressBook.js +0 -82
  121. package/src/modules/checkout/components/frontStore/checkout/address/NewBillingAddressForm.js +0 -36
  122. package/src/modules/checkout/components/frontStore/checkout/address/NewShippingAddressForm.js +0 -38
  123. package/src/modules/checkout/components/frontStore/checkout/address/UseShippingAddress.js +0 -64
  124. package/src/modules/customer/pages/admin/customerGrid/NewCustomertButton.js +0 -17
  125. package/src/modules/customer/pages/admin/customerNew/index.js +0 -8
  126. package/src/modules/customer/pages/admin/customerNew/route +0 -2
  127. package/src/modules/customer/pages/frontStore/address/AddressForm.js +0 -238
  128. package/src/modules/stripe/index.js +0 -1
  129. package/src/modules/stripe/pages/frontStore/checkout/PaymentFormContext.js +0 -40
  130. package/src/modules/stripe/pages/frontStore/checkout/PaymentFormCustom.js +0 -71
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
2
2
  <p align="center">
3
- <h1 align="center">Lightweight, modular, extendable React ecommerce platform.</h1>
3
+ <h1 align="center">Lightweight And Extendable React E-commerce Platform</h1>
4
4
  </p>
5
5
  <p align="center">
6
6
  <a href="https://evershop.io/docs/development/getting-started/introduction">Documentation</a>
@@ -15,49 +15,36 @@
15
15
  </a>
16
16
  </p>
17
17
 
18
- ## Component-Level Data Fetching (Server Side Props)
19
-
20
- ```javascript
21
- import React from 'react';
22
- import Products from './components/Products';
23
-
24
- export default function NewArrival({ products }) {
25
- return <div>
26
- <h2>New Arrival</h2>
27
- <Products products={products}/>
28
- </div>
29
- }
30
-
31
- // The GraphQL query result will be passed to the page component as props
32
- export const query = `
33
- query NewArrival {
34
- products {
35
- name
36
- price
37
- image {
38
- alt
39
- url
40
- }
41
- url
42
- }
43
- }
44
- `
45
- ```
18
+ ## Introduction
19
+
20
+ EverShop is a GraphQL Based and React ecommerce platform with essential commerce features. Built with React, modular and fully customizable.
21
+
22
+ ## Features
23
+ - Catalog management
24
+ - Product management
25
+ - Category management
26
+ - Attribute and attribute group
27
+ - Variant management
28
+ - Custom options
29
+ - Product layered navigation
30
+ - Order management
31
+ - Customer management
32
+ - Customer group
33
+ - Customer address
34
+ - Login, register and my account
35
+ - Advanced coupon management
36
+ - Online payment methods
37
+ - Stripe
38
+ - Paypal
46
39
 
47
40
  ## Demo
48
41
 
49
42
  Explore our demo store.
50
43
 
51
44
  <p align="center">
52
- <!--img alt="EverShop Admin Demo" width="950" src="https://raw.githubusercontent.com/evershopcommerce/evershop/dev/.github/images/evershop-backend-demo.png"/>
53
- </p-->
54
- <p align="left">
55
- <a href="https://demo.evershop.io/" target="_blank">
56
- <img alt="evershop-store-demo" height="35" alt="EverShop Store Demo" src="https://raw.githubusercontent.com/evershopcommerce/evershop/dev/.github/images/evershop-store-front-demo.png"/>
57
- </a>
45
+ <img alt="EverShop Admin Demo" width="950" src="https://raw.githubusercontent.com/evershopcommerce/evershop/dev/.github/images/evershop-backend-demo.png"/>
58
46
  </p>
59
-
60
- <p align="left">
47
+ <p align="center">
61
48
  <a href="https://demo.evershop.io/admin" target="_blank">
62
49
  <img alt="evershop-backend-demo" height="35" alt="EverShop Admin Demo" src="https://raw.githubusercontent.com/evershopcommerce/evershop/dev/.github/images/evershop-admin-demo.png"/>
63
50
  </a>
@@ -66,10 +53,14 @@ Explore our demo store.
66
53
 
67
54
  Email: demo@gmail.com<br/>
68
55
  Password: 123456
69
- <!--p align="center">
56
+ <p align="center">
70
57
  <img alt="EverShop Store Demo" width="950" src="https://raw.githubusercontent.com/evershopcommerce/evershop/dev/.github/images/evershop-product-detail.png"/>
71
- </p-->
72
-
58
+ </p>
59
+ <p align="center">
60
+ <a href="https://demo.evershop.io/" target="_blank">
61
+ <img alt="evershop-store-demo" height="35" alt="EverShop Store Demo" src="https://raw.githubusercontent.com/evershopcommerce/evershop/dev/.github/images/evershop-store-front-demo.png"/>
62
+ </a>
63
+ </p>
73
64
 
74
65
  ## Quick Start
75
66
 
@@ -85,22 +76,14 @@ npx create-evershop-app my-app --playAround
85
76
 
86
77
  - [Theme development](https://evershop.io/docs/development/theme/theme-overview).
87
78
 
88
- ## Features
89
- - Catalog management(with product attribute, custom option and variants)
90
- - Order management
91
- - Customer management
92
- - Coupon management
93
- - Tax
94
- - Online payment (For now using Stripe)
95
- - Basic CMS pages management
96
- - Easy to customize by developing extensions
79
+
97
80
 
98
81
  ## Support
99
82
 
100
83
  If you like my work, feel free to:
101
84
 
102
- - ⭐ this repository. It is a big motivation for me to continue working on this project.
103
- - [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)][tweet] about EverShop
85
+ - ⭐ this repository. It helps.
86
+ - [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)][tweet] about EverShop. Please accept my gratitude.
104
87
 
105
88
  [tweet]: https://twitter.com/intent/tweet?url=https%3A%2F%2Fgithub.com%2Fevershopcommerce%2Fevershop&text=Awesome%20React%20Ecommerce%20Project&hashtags=react,ecommerce,expressjs,graphql
106
89
  ### Ask a question about EverShop
package/bin/lib/app.js CHANGED
@@ -13,7 +13,8 @@ const { getEnabledExtensions } = require('../extension');
13
13
  module.exports.createApp = () => {
14
14
  /** Create express app */
15
15
  const app = express();
16
-
16
+ // Enable trust proxy
17
+ app.enable('trust proxy');
17
18
  /* Loading modules and initilize routes, components and services */
18
19
  const modules = getCoreModules();
19
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evershop/evershop",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.4",
4
4
  "description": "The React Ecommerce platform. Built with React and MySQL. Open-source and free. Fast and customizable.",
5
5
  "files": [
6
6
  "bin",
@@ -34,7 +34,7 @@ function Area(props) {
34
34
 
35
35
  return (
36
36
  <WrapperComponent {...areaWrapperProps}>
37
- {areaComponents.map((w) => {
37
+ {areaComponents.map((w, index) => {
38
38
  const C = w.component.default;
39
39
  const id = w.id;
40
40
  const propsMap = context.propsMap;
@@ -48,8 +48,8 @@ function Area(props) {
48
48
  if (w.props) {
49
49
  Object.assign(componentProps, w.props);
50
50
  }
51
- if (typeof C === 'string') return <C key={w.id} {...componentProps} />;
52
- return <C key={w.id} areaProps={props} {...componentProps} />;
51
+ if (typeof C === 'string') return <C key={index} {...componentProps} />;
52
+ return <C key={index} areaProps={props} {...componentProps} />;
53
53
  })}
54
54
  </WrapperComponent>
55
55
  );
@@ -50,10 +50,22 @@ export function Form(props) {
50
50
  const errors = {};
51
51
  fields.forEach((f) => {
52
52
  f.validationRules.forEach((r) => {
53
- const rule = validator.getRule(r);
54
- if (rule === undefined) return;
55
- if (!rule.handler.call(fields, f.value)) {
56
- errors[f.name] = rule.errorMessage;
53
+ let rule;
54
+ // Check if r is a string or an object
55
+ if (typeof r === 'string') {
56
+ rule = r;
57
+ } else {
58
+ rule = r.rule;
59
+ }
60
+
61
+ const ruleValidator = validator.getRule(rule);
62
+ if (ruleValidator === undefined) return;
63
+ if (!ruleValidator.handler.call(fields, f.value)) {
64
+ if (r.message) {
65
+ errors[f.name] = r.message;
66
+ } else {
67
+ errors[f.name] = ruleValidator.errorMessage;
68
+ }
57
69
  }
58
70
  });
59
71
  });
@@ -119,7 +131,9 @@ export function Form(props) {
119
131
  // Get the first element with the name of the field with error
120
132
  const firstElementWithError = document.getElementsByName(firstFieldWithError)[0];
121
133
  // Focus on the first element with error
122
- firstElementWithError.focus();
134
+ if (firstElementWithError) {
135
+ firstElementWithError.focus();
136
+ }
123
137
  }
124
138
  } catch (error) {
125
139
  if (onError) {
@@ -1,16 +1,20 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
+ import Error from './Error';
3
4
 
4
- export function Hidden({ name, value }) {
5
+ export function Hidden({ name, value, error }) {
5
6
  return (
6
- <input
7
- type="text"
8
- id={name}
9
- name={name}
10
- value={value}
11
- readOnly
12
- style={{ display: 'none' }}
13
- />
7
+ <>
8
+ {error && <Error error={error} />}
9
+ <input
10
+ type="text"
11
+ id={name}
12
+ name={name}
13
+ value={value}
14
+ readOnly
15
+ style={{ display: 'none' }}
16
+ />
17
+ </>
14
18
  );
15
19
  }
16
20
 
@@ -66,7 +66,7 @@ Radio.propTypes = {
66
66
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
67
67
  text: PropTypes.string
68
68
  })).isRequired,
69
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
69
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
70
70
  };
71
71
 
72
72
  Radio.defaultProps = {
@@ -1,8 +1,10 @@
1
1
  type Country {
2
2
  name: String!
3
3
  code: String!
4
+ provinces: [Province]
4
5
  }
5
6
 
6
7
  extend type Query {
7
8
  countries (countries: [String]) : [Country]
9
+ allowedCountries : [Country]
8
10
  }
@@ -1,4 +1,6 @@
1
- const { contries } = require("../../../../../lib/locale/countries")
1
+ const { contries } = require("../../../../../lib/locale/countries");
2
+ const { getSetting } = require("../../../../setting/services/setting");
3
+ const { provinces } = require("../../../../../lib/locale/provinces");
2
4
 
3
5
  module.exports = {
4
6
  Query: {
@@ -9,6 +11,11 @@ module.exports = {
9
11
  } else {
10
12
  return contries.filter((c) => list.includes(c.code));
11
13
  }
14
+ },
15
+ allowedCountries: async () => {
16
+ const allowedCountries = await getSetting("allowedCountries", '["US"]');
17
+ let list = JSON.parse(allowedCountries);
18
+ return contries.filter((c) => list.includes(c.code));
12
19
  }
13
20
  },
14
21
  Country: {
@@ -26,6 +33,9 @@ module.exports = {
26
33
  } else {
27
34
  return country;
28
35
  }
36
+ },
37
+ provinces: (country) => {
38
+ return provinces.filter((p) => p.countryCode === country.code);
29
39
  }
30
40
  }
31
41
  }
@@ -6,7 +6,7 @@ import { Price } from './item/Price';
6
6
  import Area from '../../../../../lib/components/Area';
7
7
  import { get } from '../../../../../lib/util/get';
8
8
 
9
- export default function ProductList({ products = [] }) {
9
+ export default function ProductList({ products = [], countPerRow = 3 }) {
10
10
  if (products.length === 0) {
11
11
  return (
12
12
  <div className="product-list">
@@ -14,8 +14,24 @@ export default function ProductList({ products = [] }) {
14
14
  </div>
15
15
  );
16
16
  }
17
+
18
+ let className;
19
+ switch (countPerRow) {
20
+ case 3:
21
+ className = 'grid grid-cols-2 md:grid-cols-3 gap-2';
22
+ break;
23
+ case 4:
24
+ className = 'grid grid-cols-2 md:grid-cols-4 gap-2';
25
+ break;
26
+ case 5:
27
+ className = 'grid grid-cols-2 md:grid-cols-5 gap-2';
28
+ break;
29
+ default:
30
+ className = 'grid grid-cols-2 md:grid-cols-3 gap-2';
31
+ }
32
+
17
33
  return (
18
- <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
34
+ <div className={className}>
19
35
  {
20
36
  products.map((p) => (
21
37
  <Area
@@ -1,8 +1,9 @@
1
- const { select } = require('@evershop/mysql-query-builder');
1
+ const { select, node } = require('@evershop/mysql-query-builder');
2
2
  const { buildUrl } = require('../../../../../lib/router/buildUrl');
3
3
  const { camelCase } = require('../../../../../lib/util/camelCase');
4
4
  const uniqid = require('uniqid');
5
- const { getProductsQuery } = require('../../../services/getProductsQuery');
5
+ const { getProductsBaseQuery } = require('../../../services/getProductsBaseQuery');
6
+ const { pool } = require('../../../../../lib/mysql/connection');
6
7
 
7
8
  module.exports = {
8
9
  Query: {
@@ -198,7 +199,7 @@ module.exports = {
198
199
  },
199
200
  Category: {
200
201
  products: async (category, { filters = [] }, { filterableAttributes, priceRange }) => {
201
- const query = await getProductsQuery(category.categoryId);
202
+ const query = await getProductsBaseQuery(category.categoryId);
202
203
  const currentFilters = [];
203
204
  // Price filter
204
205
  const priceFilter = filters.find((f) => f.key === 'price');
@@ -271,6 +272,39 @@ module.exports = {
271
272
  value: sortOrder.value
272
273
  });
273
274
  }
275
+
276
+ // Visibility. For variant group
277
+ const copy = query.clone();
278
+ // Get all group that have at lease 1 item visibile
279
+ const visibleGroups = (await select('variant_group_id')
280
+ .from('variant_group')
281
+ .where('visibility', '=', 1)
282
+ .execute(pool)).map((v) => v.variant_group_id);
283
+
284
+ if (visibleGroups) {
285
+ // Get all invisible variants from current query
286
+ copy.select('SUM(product.`visibility`)', 'sumv')
287
+ .select('product.`product_id`')
288
+ .andWhere('product.`variant_group_id`', 'IN', visibleGroups);
289
+ copy.groupBy('product.`variant_group_id`')
290
+ .having('sumv', '=', 0);
291
+
292
+ const invisibleIds = (await copy.execute(pool)).map((v) => v.product_id);
293
+ if (invisibleIds.length > 0) {
294
+ const n = node('AND');
295
+ n.addLeaf('AND', 'product.`product_id`', 'IN', invisibleIds)
296
+ .addNode(
297
+ node('OR')
298
+ .addLeaf('OR', 'product.`visibility`', '=', 1)
299
+ );
300
+ query.getWhere().addNode(n);
301
+ } else {
302
+ query.andWhere('product.`visibility`', '=', 1);
303
+ }
304
+ } else {
305
+ query.andWhere('product.`visibility`', '=', 1);
306
+ }
307
+
274
308
  // Clone the main query for getting total right before doing the paging
275
309
  const cloneQuery = query.clone();
276
310
  cloneQuery.select('COUNT(product.`product_id`)', 'total');
@@ -17,6 +17,7 @@ module.exports = {
17
17
  query.leftJoin('cart_item')
18
18
  .on('cart_item.`product_id`', '=', 'product.`product_id`');
19
19
  query.where('product.`status`', '=', 1);
20
+ query.andWhere('product.`visibility`', '=', 1);
20
21
  query.groupBy('product.`product_id`');
21
22
  query.orderBy('soldQty', 'desc');
22
23
  query.limit(0, 4);
@@ -0,0 +1,8 @@
1
+ const { execute } = require('@evershop/mysql-query-builder');
2
+ const { pool } = require('../../../lib/mysql/connection');
3
+
4
+ // eslint-disable-next-line no-multi-assign
5
+ module.exports = exports = async () => {
6
+ await execute(pool, `UPDATE product SET visibility = 1 WHERE visibility IS NULL`);
7
+ await execute(pool, `ALTER TABLE product MODIFY COLUMN visibility smallint(2) NOT NULL DEFAULT 1`);
8
+ };
@@ -15,8 +15,8 @@ module.exports = async (request, response, delegate, next) => {
15
15
  } else {
16
16
  setContextValue(request, 'attributeId', attribute.attribute_id);
17
17
  setContextValue(request, 'pageInfo', {
18
- title: attribute.name,
19
- description: attribute.name
18
+ title: attribute.attribute_name,
19
+ description: attribute.attribute_name
20
20
  });
21
21
  next();
22
22
  }
@@ -57,7 +57,7 @@ function Groups({ groups, addGroupUrl }) {
57
57
  <div className='grid gap-2 grid-cols-2'>
58
58
  <div>
59
59
  <Select
60
- name='groups'
60
+ name='groups[]'
61
61
  options={data.attributeGroups}
62
62
  hideSelectedOptions={true}
63
63
  isMulti={true}
@@ -21,11 +21,12 @@ export default function GroupRow({ groups, saveAttributeGroupUrl }) {
21
21
  onSuccess={() => {
22
22
  location.reload();
23
23
  }}
24
+ isJSON={true}
24
25
  >
25
26
  <Field
26
27
  formId="group-edit"
27
28
  type="text"
28
- name="groupName"
29
+ name="group_name"
29
30
  value={group.groupName}
30
31
  />
31
32
  <Field
@@ -53,6 +53,7 @@ query Query {
53
53
  name
54
54
  sku
55
55
  status
56
+ visibility
56
57
  price {
57
58
  regular {
58
59
  value
@@ -122,7 +122,7 @@ export function Variant({
122
122
  <Field
123
123
  name={`variant_group[variants][${variant.id}][visibility]`}
124
124
  formId="product-edit-form"
125
- value={variant.visibility}
125
+ value={variant.product?.visibility}
126
126
  type="toggle"
127
127
  />
128
128
  </div>
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import Area from '../../../../../lib/components/Area';
3
+
4
+ export default function CategoryView() {
5
+ return (
6
+ <div className="page-width grid grid-cols-1 md:grid-cols-4 gap-2">
7
+ <Area
8
+ id="leftColumn"
9
+ className="md:col-span-1"
10
+ />
11
+ <Area
12
+ id="rightColumn"
13
+ className="md:col-span-3"
14
+ />
15
+ </div>
16
+ );
17
+ }
18
+
19
+ export const layout = {
20
+ areaId: 'content',
21
+ sortOrder: 10
22
+ }