WooCommerce Gutenberg Products Block - Version 1.1.0

Version Description

  • 2018-06-06 =
  • Feature - Add "Best Selling" and "Top Rated" product scopes.
  • Fix - Only enqueue scripts and styles in the site backend.
  • Fix - Remove focus checks deprecated in latest Gutenberg version.
  • Fix - Added keys to some elements to prevent React warnings.
  • Enhancement - Added custom API endpoint for more accurate block previews with orderby.
  • Performance - Refactored the way the attribute select works to prevent many concurrent API requests on sites with many attributes.
Download this release

Release Info

Developer claudiulodro
Plugin Icon 128x128 WooCommerce Gutenberg Products Block
Version 1.1.0
Comparing to
See all releases

Code changes from version 1.0.0 to 1.1.0

assets/css/gutenberg-products-block-rtl.css CHANGED
@@ -1 +1 @@
1
- .wc-products-block-preview{overflow:hidden}.wc-products-block-preview .product-preview{float:right;text-align:center;margin-left:3.8%}.wc-products-block-preview.cols-1 .product-preview{float:none;margin-left:0}.wc-products-block-preview.cols-2 .product-preview{width:48%}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n){margin-left:0}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n+1){clear:both}.wc-products-block-preview.cols-3 .product-preview{width:30.75%}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n){margin-left:0}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n+1){clear:both}.wc-products-block-preview.cols-4 .product-preview{width:22.05%}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n){margin-left:0}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview{width:16.9%}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n){margin-left:0}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview.cols-6 .product-preview{width:13.5%}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n){margin-left:0}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n+1){clear:both}.wc-products-block-preview.cols-6 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview .product-add-to-cart{display:inline-block;background:#ababab;border-radius:1.5em;color:#fff;cursor:pointer;padding:.75em 1.25em;line-height:1.2em;margin-top:.5em;margin-bottom:1em}.wc-products-settings{background-color:#f8f9f9;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px;position:relative}.wc-products-settings__title{margin:0;padding:1.5rem 0;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-settings__title .dashicon{vertical-align:top;margin-left:.25em}.wc-products-settings__footer{margin:2em 0 0;padding:1.5em 0;border-top:1px solid #e6eaee;text-align:center}.wc-products-settings__footer .button{padding-right:1.5em;padding-left:1.5em}.wc-products-display-options--popover+.wc-products-settings__footer,.wc-products-settings-heading+.wc-products-settings__footer{margin-top:-2em;border-top:none}p.wc-products-block-description{margin:2em 0 1.5em 0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;text-align:center}.wc-products-display-options{margin:0 0 2.5em}.wc-products-display-options__option{display:flex;align-items:flex-start;flex-wrap:wrap;margin:0 auto;padding:1.25em 1.5em;max-width:80%;background:#fff;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee;cursor:pointer}.wc-products-display-options__option:last-of-type{border-bottom-width:1px}.wc-products-display-options__option--attribute,.wc-products-display-options__option--best_rated,.wc-products-display-options__option--best_sellers,.wc-products-display-options__option--featured,.wc-products-display-options__option--on_sale{display:none;background-color:#fdfdfd;padding-top:1em;padding-bottom:1em}.wc-products-display-options__option--attribute .wc-products-display-options__option-title,.wc-products-display-options__option--best_rated .wc-products-display-options__option-title,.wc-products-display-options__option--best_sellers .wc-products-display-options__option-title,.wc-products-display-options__option--featured .wc-products-display-options__option-title,.wc-products-display-options__option--on_sale .wc-products-display-options__option-title{font-size:1.15em}.wc-products-display-options__option--attribute .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--best_rated .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--best_sellers .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--featured .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--on_sale .wc-products-display-options__icon .dashicon{height:20px;width:20px}.wc-products-display-options__option--current{cursor:default}.wc-products-display-options__option--current .wc-products-display-options__option-title{color:#86909b}.wc-products-display-options__option-content{width:85%;align-self:center}.wc-products-display-options__option-title{display:block;font-size:1.25em}p.wc-products-display-options__option-description{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;color:#86909b}.wc-products-display-options__icon{align-self:center;margin-right:auto;color:#b9bcc2}.wc-products-display-options__icon .dashicon{height:25px;width:25px}.wc-products-display-options--popover{position:absolute;left:-2em;max-width:60%;margin:0;z-index:999;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);margin-top:-2.15em}.wc-products-display-options--popover .wc-products-display-options__option{margin:0;max-width:none}.wc-products-display-options--popover__arrow{width:2em;height:1.25em;position:absolute;top:-1.15em;left:30%;overflow:hidden}.wc-products-display-options--popover__arrow:after{content:'';position:absolute;width:1.25em;height:1.25em;background:#fff;transform:rotate(-45deg);top:.625em;right:.3125em;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);border:1px solid #e6eaee}.wc-products-display-options--extended .wc-products-display-options__option--attribute,.wc-products-display-options--extended .wc-products-display-options__option--best_rated,.wc-products-display-options--extended .wc-products-display-options__option--best_sellers,.wc-products-display-options--extended .wc-products-display-options__option--featured,.wc-products-display-options--extended .wc-products-display-options__option--on_sale{display:flex}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--category{border-bottom-width:1px}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--filter{margin-top:.5em}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--attribute{margin-bottom:.5em;border-bottom-width:1px}.wc-products-settings-heading{margin:0 0 2em 0;padding:1em 2em;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-list-card{position:relative;margin-right:auto;margin-left:auto;padding:0 1em;overflow:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__input-wrapper{position:relative;background:#fff;margin:0 0 1em}.wc-products-list-card .wc-products-list-card__input-wrapper .dashicon{position:absolute;top:calc(1em - 1px);right:1em;z-index:1}.wc-products-list-card input[type=search]{position:relative;width:100%;margin:0;padding:1em 3em 1em 1.25em;border-radius:0;background:0 0;border-color:#e6eaee;box-shadow:none;z-index:2}.wc-products-list-card .wc-products-list-card__results{max-height:200px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__results ul{list-style:none}.wc-products-list-card .wc-products-list-card__results ul li{margin:0;border:1px solid #e6eaee;border-bottom-width:0}.wc-products-list-card .wc-products-list-card__results ul li:last-child{border-bottom-width:1px}.wc-products-list-card .wc-products-list-card__content{display:flex;align-items:center;flex-direction:row;padding:.75em 1.25em;background:#fff;border-bottom:1px solid #e6eaee}.wc-products-list-card:after{content:'';position:absolute;right:0;bottom:0;width:100%;height:1.5em;background:linear-gradient(rgba(255,255,255,.1) 0,#f8f9f9 100%)}.wc-products-list-card--taxonomy .wc-products-list-card__taxonomy-count{text-align:center;width:30px;font-size:.8em;border:1px solid #e9e9e9;border-radius:1em;color:#aaa}.wc-products-list-card--taxonomy input[type=checkbox]{position:relative;margin-top:0;margin-left:.75em;border-radius:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li{margin-top:-1px}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:last-child{border-bottom-width:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul{display:none;padding:1em 3.25em 1em 1.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open{margin:.5em 0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul{display:block}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li label{display:flex;align-items:center;flex-direction:row}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li .wc-products-list-card__taxonomy-count{margin-right:auto}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button{cursor:pointer;color:#666;margin:0 auto 0 1em;padding:0 .75em 0 0;border:none;border-radius:0;background:0 0;outline:0;text-decoration:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button .dashicon{align-self:center;display:flex}.wc-products-list-card--taxonomy-category input[type=checkbox]:indeterminate:before{position:absolute;top:0;bottom:0;left:0;right:0;content:'';margin:42% 20%;width:60%;background:#0073aa}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul{padding:1em 3.25em 1em 1.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li .wc-products-list-card__content{padding:0;background:0 0;border:none}.wc-products-list-card--taxonomy-atributes__atribute{margin:-1px 0 0;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee}.wc-products-list-card--taxonomy-atributes__atribute:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open{margin-top:.5em;margin-bottom:.5em}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__taxonomy-count{margin-right:auto}.wc-products-list-card--taxonomy-atributes input[type=radio]{position:relative;margin-top:0;margin-left:.75em;border-radius:100%}.wc-products-list-card--specific{overflow:visible}.wc-products-list-card--specific:after{content:none}.wc-products-list-card--specific .wc-products-list-card__item{position:relative;border:none}.wc-products-list-card--specific .wc-products-list-card__item img{margin:0;outline:4px solid #00a0d2;outline-offset:-4px}.wc-products-list-card--specific .wc-products-list-card__item button{position:absolute;top:0;left:0;background:#00a0d2;padding:0;margin:0;border:none;margin-right:auto;line-height:10px;cursor:pointer}.wc-products-list-card--specific .wc-products-list-card__item .dashicon{color:#fff}.wc-products-list-card--specific .wc-products-list-card__input-wrapper{margin:0}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-1 .wc-products-list-card__item{width:100%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-2 .wc-products-list-card__item{width:50%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-3 .wc-products-list-card__item{width:33.3333333333%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-4 .wc-products-list-card__item{width:25%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-5 .wc-products-list-card__item{width:20%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-6 .wc-products-list-card__item{width:16.6666666667%}.wc-products-list-card--specific .wc-products-list-card__results{max-height:none;overflow:visible}.wc-products-list-card--specific .wc-products-list-card__results h3{margin:0 0 1em;font-size:1em}.wc-products-list-card--specific .wc-products-list-card__results ul{display:flex;flex-wrap:wrap;margin:0 -.5em -1em}.wc-products-list-card--specific .wc-products-list-card__results ul li{border:none;padding:0 .5em;margin:0 0 1em}.wc-products-list-card--specific .wc-products-list-card__results .wc-products-list-card__content{position:relative;display:block;padding:0;background:0 0;border:none}.wc-products-list-card__search-wrapper{position:relative;margin:0 0 1.5em}.wc-products-list-card__search-results{width:100%;list-style:none;background:#fff;margin:-1px 0 0;border:1px solid #e6eaee;box-shadow:0 1px 3px #e6eaee}.wc-products-list-card__search-results>div{max-height:175px;overflow-y:auto}.wc-products-list-card__search-results .wc-products-list-card__content{position:relative;border-width:1px 0 0;border-style:solid;border-color:#e6eaee;transition:opacity .7s;cursor:pointer;color:#00a0d2}.wc-products-list-card__search-results .wc-products-list-card__content--added{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content:hover{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content--transition-exit-active{opacity:0}.wc-products-list-card__search-results .wc-products-list-card__content:first-child{border-top-width:0}.wc-products-list-card__search-results .wc-products-list-card__content img{object-fit:cover;object-position:center;width:2.5em;height:2.5em;margin:0 0 0 1em}.wc-products-list-card__search-results .wc-products-list-card__content .dashicon{color:#0073aa;margin-right:auto}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item img{outline:0}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item button{display:none}.wc-products-list-card__search-no-results{display:block;margin:1em 0 0}.wc-products-list-card__search-no-selected{display:block;margin:-.75em 0 0}.wc-products-list-card__results-wrapper{position:relative;overflow:hidden}@media only screen and (min-width:700px){.wc-products-settings-heading{display:flex;justify-content:space-between}.wc-products-list-card{max-width:480px}}.edit-post-sidebar .wc-products-scope-descriptions{margin-bottom:1.5em;position:relative;padding-right:46px;padding-top:1em;padding-bottom:1.5em;border-bottom:1px solid #e6eaee;display:flex;justify-content:space-between}.edit-post-sidebar h3{font-weight:500;margin-bottom:5px;color:#555d66}.edit-post-sidebar .scope-description{font-size:12px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink{margin-right:1em;min-width:24px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink a{cursor:pointer}
1
+ .wc-products-block-preview{overflow:hidden}.wc-products-block-preview .product-preview{float:right;text-align:center;margin-left:3.8%}.wc-products-block-preview.cols-1 .product-preview{float:none;margin-left:0}.wc-products-block-preview.cols-2 .product-preview{width:48%}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n){margin-left:0}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n+1){clear:both}.wc-products-block-preview.cols-3 .product-preview{width:30.75%}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n){margin-left:0}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n+1){clear:both}.wc-products-block-preview.cols-4 .product-preview{width:22.05%}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n){margin-left:0}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview{width:16.9%}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n){margin-left:0}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview.cols-6 .product-preview{width:13.5%}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n){margin-left:0}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n+1){clear:both}.wc-products-block-preview.cols-6 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview .product-add-to-cart{display:inline-block;background:#ababab;border-radius:1.5em;color:#fff;cursor:pointer;padding:.75em 1.25em;line-height:1.2em;margin-top:.5em;margin-bottom:1em}.wc-products-settings{background-color:#f8f9f9;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px;position:relative}.wc-products-settings__title{margin:0;padding:1.5rem 0;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-settings__title .dashicon{vertical-align:top;margin-left:.25em}.wc-products-settings__footer{margin:2em 0 0;padding:1.5em 0;border-top:1px solid #e6eaee;text-align:center}.wc-products-settings__footer .button{padding-right:1.5em;padding-left:1.5em}.wc-products-display-options--popover+.wc-products-settings__footer,.wc-products-settings-heading+.wc-products-settings__footer{margin-top:-2em;border-top:none}p.wc-products-block-description{margin:2em 0 1.5em 0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;text-align:center}.wc-products-display-options{margin:0 0 2.5em}.wc-products-display-options__option{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0 auto;padding:1.25em 1.5em;max-width:80%;background:#fff;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee;cursor:pointer}.wc-products-display-options__option:last-of-type{border-bottom-width:1px}.wc-products-display-options__option--attribute,.wc-products-display-options__option--best_selling,.wc-products-display-options__option--featured,.wc-products-display-options__option--on_sale,.wc-products-display-options__option--top_rated{display:none;background-color:#fdfdfd;padding-top:1em;padding-bottom:1em}.wc-products-display-options__option--attribute .wc-products-display-options__option-title,.wc-products-display-options__option--best_selling .wc-products-display-options__option-title,.wc-products-display-options__option--featured .wc-products-display-options__option-title,.wc-products-display-options__option--on_sale .wc-products-display-options__option-title,.wc-products-display-options__option--top_rated .wc-products-display-options__option-title{font-size:1.15em}.wc-products-display-options__option--attribute .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--best_selling .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--featured .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--on_sale .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--top_rated .wc-products-display-options__icon .dashicon{height:20px;width:20px}.wc-products-display-options__option--current{cursor:default}.wc-products-display-options__option--current .wc-products-display-options__option-title{color:#86909b}.wc-products-display-options__option-content{width:85%;-ms-flex-item-align:center;align-self:center}.wc-products-display-options__option-title{display:block;font-size:1.25em}p.wc-products-display-options__option-description{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;color:#86909b}.wc-products-display-options__icon{-ms-flex-item-align:center;align-self:center;margin-right:auto;color:#b9bcc2}.wc-products-display-options__icon .dashicon{height:25px;width:25px}.wc-products-display-options--popover{position:absolute;left:-2em;max-width:60%;margin:0;z-index:999;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);margin-top:-2.15em}.wc-products-display-options--popover .wc-products-display-options__option{margin:0;max-width:none}.wc-products-display-options--popover__arrow{width:2em;height:1.25em;position:absolute;top:-1.15em;left:30%;overflow:hidden}.wc-products-display-options--popover__arrow:after{content:'';position:absolute;width:1.25em;height:1.25em;background:#fff;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);top:.625em;right:.3125em;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);border:1px solid #e6eaee}.wc-products-display-options--extended .wc-products-display-options__option--attribute,.wc-products-display-options--extended .wc-products-display-options__option--best_selling,.wc-products-display-options--extended .wc-products-display-options__option--featured,.wc-products-display-options--extended .wc-products-display-options__option--on_sale,.wc-products-display-options--extended .wc-products-display-options__option--top_rated{display:-webkit-box;display:-ms-flexbox;display:flex}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--category{border-bottom-width:1px}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--filter{margin-top:.5em}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--attribute{margin-bottom:.5em;border-bottom-width:1px}.wc-products-settings-heading{margin:0 0 2em 0;padding:1em 2em;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-list-card{position:relative;margin-right:auto;margin-left:auto;padding:0 1em;overflow:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__input-wrapper{position:relative;background:#fff;margin:0 0 1em}.wc-products-list-card .wc-products-list-card__input-wrapper .dashicon{position:absolute;top:calc(1em - 1px);right:1em;z-index:1}.wc-products-list-card input[type=search]{position:relative;width:100%;margin:0;padding:1em 3em 1em 1.25em;border-radius:0;background:0 0;border-color:#e6eaee;box-shadow:none;z-index:2}.wc-products-list-card .wc-products-list-card__results{max-height:200px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__results ul{list-style:none}.wc-products-list-card .wc-products-list-card__results ul li{margin:0;border:1px solid #e6eaee;border-bottom-width:0}.wc-products-list-card .wc-products-list-card__results ul li:last-child{border-bottom-width:1px}.wc-products-list-card .wc-products-list-card__content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:.75em 1.25em;background:#fff;border-bottom:1px solid #e6eaee}.wc-products-list-card:after{content:'';position:absolute;right:0;bottom:0;width:100%;height:1.5em;background:-webkit-linear-gradient(rgba(255,255,255,.1) 0,#f8f9f9 100%);background:linear-gradient(rgba(255,255,255,.1) 0,#f8f9f9 100%)}.wc-products-list-card--taxonomy .wc-products-list-card__taxonomy-count{text-align:center;width:30px;font-size:.8em;border:1px solid #e9e9e9;border-radius:1em;color:#aaa}.wc-products-list-card--taxonomy input[type=checkbox]{position:relative;margin-top:0;margin-left:.75em;border-radius:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li{margin-top:-1px}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:last-child{border-bottom-width:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul{display:none;padding:1em 3.25em 1em 1.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open{margin:.5em 0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul{display:block}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li .wc-products-list-card__taxonomy-count{margin-right:auto}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button{cursor:pointer;color:#666;margin:0 auto 0 1em;padding:0 .75em 0 0;border:none;border-radius:0;background:0 0;outline:0;text-decoration:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button .dashicon{-ms-flex-item-align:center;align-self:center;display:-webkit-box;display:-ms-flexbox;display:flex}.wc-products-list-card--taxonomy-category input[type=checkbox]:indeterminate:before{position:absolute;top:0;bottom:0;left:0;right:0;content:'';margin:42% 20%;width:60%;background:#0073aa}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul{padding:1em 3.25em 1em 1.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li .wc-products-list-card__content{padding:0;background:0 0;border:none}.wc-products-list-card--taxonomy-atributes__atribute{margin:-1px 0 0;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee}.wc-products-list-card--taxonomy-atributes__atribute:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open{margin-top:.5em;margin-bottom:.5em}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__taxonomy-count{margin-right:auto}.wc-products-list-card--taxonomy-atributes input[type=radio]{position:relative;margin-top:0;margin-left:.75em;border-radius:100%}.wc-products-list-card--specific{overflow:visible}.wc-products-list-card--specific:after{content:none}.wc-products-list-card--specific .wc-products-list-card__item{position:relative;border:none}.wc-products-list-card--specific .wc-products-list-card__item img{margin:0;outline:4px solid #00a0d2;outline-offset:-4px}.wc-products-list-card--specific .wc-products-list-card__item button{position:absolute;top:0;left:0;background:#00a0d2;padding:0;margin:0;border:none;margin-right:auto;line-height:10px;cursor:pointer}.wc-products-list-card--specific .wc-products-list-card__item .dashicon{color:#fff}.wc-products-list-card--specific .wc-products-list-card__input-wrapper{margin:0}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-1 .wc-products-list-card__item{width:100%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-2 .wc-products-list-card__item{width:50%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-3 .wc-products-list-card__item{width:33.3333333333%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-4 .wc-products-list-card__item{width:25%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-5 .wc-products-list-card__item{width:20%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-6 .wc-products-list-card__item{width:16.6666666667%}.wc-products-list-card--specific .wc-products-list-card__results{max-height:none;overflow:visible}.wc-products-list-card--specific .wc-products-list-card__results h3{margin:0 0 1em;font-size:1em}.wc-products-list-card--specific .wc-products-list-card__results ul{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0 -.5em -1em}.wc-products-list-card--specific .wc-products-list-card__results ul li{border:none;padding:0 .5em;margin:0 0 1em}.wc-products-list-card--specific .wc-products-list-card__results .wc-products-list-card__content{position:relative;display:block;padding:0;background:0 0;border:none}.wc-products-list-card__search-wrapper{position:relative;margin:0 0 1.5em}.wc-products-list-card__search-results{width:100%;list-style:none;background:#fff;margin:-1px 0 0;border:1px solid #e6eaee;box-shadow:0 1px 3px #e6eaee}.wc-products-list-card__search-results>div{max-height:175px;overflow-y:auto}.wc-products-list-card__search-results .wc-products-list-card__content{position:relative;border-width:1px 0 0;border-style:solid;border-color:#e6eaee;-webkit-transition:opacity .7s;transition:opacity .7s;cursor:pointer;color:#00a0d2}.wc-products-list-card__search-results .wc-products-list-card__content--added{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content:hover{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content--transition-exit-active{opacity:0}.wc-products-list-card__search-results .wc-products-list-card__content:first-child{border-top-width:0}.wc-products-list-card__search-results .wc-products-list-card__content img{-o-object-fit:cover;object-fit:cover;-o-object-position:center;object-position:center;width:2.5em;height:2.5em;margin:0 0 0 1em}.wc-products-list-card__search-results .wc-products-list-card__content .dashicon{color:#0073aa;margin-right:auto}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item img{outline:0}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item button{display:none}.wc-products-list-card__search-no-results{display:block;margin:1em 0 0}.wc-products-list-card__search-no-selected{display:block;margin:-.75em 0 0}.wc-products-list-card__results-wrapper{position:relative;overflow:hidden}@media only screen and (min-width:700px){.wc-products-settings-heading{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.wc-products-list-card{max-width:480px}}.edit-post-sidebar .wc-products-scope-descriptions{margin-bottom:1.5em;position:relative;padding-right:46px;padding-top:1em;padding-bottom:1.5em;border-bottom:1px solid #e6eaee;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.edit-post-sidebar h3{font-weight:500;margin-bottom:5px;color:#555d66}.edit-post-sidebar .scope-description{font-size:12px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink{margin-right:1em;min-width:24px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink a{cursor:pointer}
assets/css/gutenberg-products-block.css CHANGED
@@ -1 +1 @@
1
- .wc-products-block-preview{overflow:hidden}.wc-products-block-preview .product-preview{float:left;text-align:center;margin-right:3.8%}.wc-products-block-preview.cols-1 .product-preview{float:none;margin-right:0}.wc-products-block-preview.cols-2 .product-preview{width:48%}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n){margin-right:0}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n+1){clear:both}.wc-products-block-preview.cols-3 .product-preview{width:30.75%}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n){margin-right:0}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n+1){clear:both}.wc-products-block-preview.cols-4 .product-preview{width:22.05%}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n){margin-right:0}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview{width:16.9%}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n){margin-right:0}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview.cols-6 .product-preview{width:13.5%}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n){margin-right:0}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n+1){clear:both}.wc-products-block-preview.cols-6 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview .product-add-to-cart{display:inline-block;background:#ababab;border-radius:1.5em;color:#fff;cursor:pointer;padding:.75em 1.25em;line-height:1.2em;margin-top:.5em;margin-bottom:1em}.wc-products-settings{background-color:#f8f9f9;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px;position:relative}.wc-products-settings__title{margin:0;padding:1.5rem 0;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-settings__title .dashicon{vertical-align:top;margin-right:.25em}.wc-products-settings__footer{margin:2em 0 0;padding:1.5em 0;border-top:1px solid #e6eaee;text-align:center}.wc-products-settings__footer .button{padding-left:1.5em;padding-right:1.5em}.wc-products-display-options--popover+.wc-products-settings__footer,.wc-products-settings-heading+.wc-products-settings__footer{margin-top:-2em;border-top:none}p.wc-products-block-description{margin:2em 0 1.5em 0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;text-align:center}.wc-products-display-options{margin:0 0 2.5em}.wc-products-display-options__option{display:flex;align-items:flex-start;flex-wrap:wrap;margin:0 auto;padding:1.25em 1.5em;max-width:80%;background:#fff;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee;cursor:pointer}.wc-products-display-options__option:last-of-type{border-bottom-width:1px}.wc-products-display-options__option--attribute,.wc-products-display-options__option--best_rated,.wc-products-display-options__option--best_sellers,.wc-products-display-options__option--featured,.wc-products-display-options__option--on_sale{display:none;background-color:#fdfdfd;padding-top:1em;padding-bottom:1em}.wc-products-display-options__option--attribute .wc-products-display-options__option-title,.wc-products-display-options__option--best_rated .wc-products-display-options__option-title,.wc-products-display-options__option--best_sellers .wc-products-display-options__option-title,.wc-products-display-options__option--featured .wc-products-display-options__option-title,.wc-products-display-options__option--on_sale .wc-products-display-options__option-title{font-size:1.15em}.wc-products-display-options__option--attribute .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--best_rated .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--best_sellers .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--featured .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--on_sale .wc-products-display-options__icon .dashicon{height:20px;width:20px}.wc-products-display-options__option--current{cursor:default}.wc-products-display-options__option--current .wc-products-display-options__option-title{color:#86909b}.wc-products-display-options__option-content{width:85%;align-self:center}.wc-products-display-options__option-title{display:block;font-size:1.25em}p.wc-products-display-options__option-description{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;color:#86909b}.wc-products-display-options__icon{align-self:center;margin-left:auto;color:#b9bcc2}.wc-products-display-options__icon .dashicon{height:25px;width:25px}.wc-products-display-options--popover{position:absolute;right:-2em;max-width:60%;margin:0;z-index:999;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);margin-top:-2.15em}.wc-products-display-options--popover .wc-products-display-options__option{margin:0;max-width:none}.wc-products-display-options--popover__arrow{width:2em;height:1.25em;position:absolute;top:-1.15em;right:30%;overflow:hidden}.wc-products-display-options--popover__arrow:after{content:'';position:absolute;width:1.25em;height:1.25em;background:#fff;transform:rotate(45deg);top:.625em;left:.3125em;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);border:1px solid #e6eaee}.wc-products-display-options--extended .wc-products-display-options__option--attribute,.wc-products-display-options--extended .wc-products-display-options__option--best_rated,.wc-products-display-options--extended .wc-products-display-options__option--best_sellers,.wc-products-display-options--extended .wc-products-display-options__option--featured,.wc-products-display-options--extended .wc-products-display-options__option--on_sale{display:flex}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--category{border-bottom-width:1px}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--filter{margin-top:.5em}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--attribute{margin-bottom:.5em;border-bottom-width:1px}.wc-products-settings-heading{margin:0 0 2em 0;padding:1em 2em;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-list-card{position:relative;margin-left:auto;margin-right:auto;padding:0 1em;overflow:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__input-wrapper{position:relative;background:#fff;margin:0 0 1em}.wc-products-list-card .wc-products-list-card__input-wrapper .dashicon{position:absolute;top:calc(1em - 1px);left:1em;z-index:1}.wc-products-list-card input[type=search]{position:relative;width:100%;margin:0;padding:1em 1.25em 1em 3em;border-radius:0;background:0 0;border-color:#e6eaee;box-shadow:none;z-index:2}.wc-products-list-card .wc-products-list-card__results{max-height:200px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__results ul{list-style:none}.wc-products-list-card .wc-products-list-card__results ul li{margin:0;border:1px solid #e6eaee;border-bottom-width:0}.wc-products-list-card .wc-products-list-card__results ul li:last-child{border-bottom-width:1px}.wc-products-list-card .wc-products-list-card__content{display:flex;align-items:center;flex-direction:row;padding:.75em 1.25em;background:#fff;border-bottom:1px solid #e6eaee}.wc-products-list-card:after{content:'';position:absolute;left:0;bottom:0;width:100%;height:1.5em;background:linear-gradient(rgba(255,255,255,.1) 0,#f8f9f9 100%)}.wc-products-list-card--taxonomy .wc-products-list-card__taxonomy-count{text-align:center;width:30px;font-size:.8em;border:1px solid #e9e9e9;border-radius:1em;color:#aaa}.wc-products-list-card--taxonomy input[type=checkbox]{position:relative;margin-top:0;margin-right:.75em;border-radius:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li{margin-top:-1px}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:last-child{border-bottom-width:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul{display:none;padding:1em 1.25em 1em 3.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open{margin:.5em 0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul{display:block}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li label{display:flex;align-items:center;flex-direction:row}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li .wc-products-list-card__taxonomy-count{margin-left:auto}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button{cursor:pointer;color:#666;margin:0 1em 0 auto;padding:0 0 0 .75em;border:none;border-radius:0;background:0 0;outline:0;text-decoration:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button .dashicon{align-self:center;display:flex}.wc-products-list-card--taxonomy-category input[type=checkbox]:indeterminate:before{position:absolute;top:0;bottom:0;right:0;left:0;content:'';margin:42% 20%;width:60%;background:#0073aa}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul{padding:1em 1.25em 1em 3.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li .wc-products-list-card__content{padding:0;background:0 0;border:none}.wc-products-list-card--taxonomy-atributes__atribute{margin:-1px 0 0;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee}.wc-products-list-card--taxonomy-atributes__atribute:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open{margin-top:.5em;margin-bottom:.5em}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__taxonomy-count{margin-left:auto}.wc-products-list-card--taxonomy-atributes input[type=radio]{position:relative;margin-top:0;margin-right:.75em;border-radius:100%}.wc-products-list-card--specific{overflow:visible}.wc-products-list-card--specific:after{content:none}.wc-products-list-card--specific .wc-products-list-card__item{position:relative;border:none}.wc-products-list-card--specific .wc-products-list-card__item img{margin:0;outline:4px solid #00a0d2;outline-offset:-4px}.wc-products-list-card--specific .wc-products-list-card__item button{position:absolute;top:0;right:0;background:#00a0d2;padding:0;margin:0;border:none;margin-left:auto;line-height:10px;cursor:pointer}.wc-products-list-card--specific .wc-products-list-card__item .dashicon{color:#fff}.wc-products-list-card--specific .wc-products-list-card__input-wrapper{margin:0}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-1 .wc-products-list-card__item{width:100%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-2 .wc-products-list-card__item{width:50%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-3 .wc-products-list-card__item{width:33.3333333333%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-4 .wc-products-list-card__item{width:25%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-5 .wc-products-list-card__item{width:20%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-6 .wc-products-list-card__item{width:16.6666666667%}.wc-products-list-card--specific .wc-products-list-card__results{max-height:none;overflow:visible}.wc-products-list-card--specific .wc-products-list-card__results h3{margin:0 0 1em;font-size:1em}.wc-products-list-card--specific .wc-products-list-card__results ul{display:flex;flex-wrap:wrap;margin:0 -.5em -1em}.wc-products-list-card--specific .wc-products-list-card__results ul li{border:none;padding:0 .5em;margin:0 0 1em}.wc-products-list-card--specific .wc-products-list-card__results .wc-products-list-card__content{position:relative;display:block;padding:0;background:0 0;border:none}.wc-products-list-card__search-wrapper{position:relative;margin:0 0 1.5em}.wc-products-list-card__search-results{width:100%;list-style:none;background:#fff;margin:-1px 0 0;border:1px solid #e6eaee;box-shadow:0 1px 3px #e6eaee}.wc-products-list-card__search-results>div{max-height:175px;overflow-y:auto}.wc-products-list-card__search-results .wc-products-list-card__content{position:relative;border-width:1px 0 0;border-style:solid;border-color:#e6eaee;transition:opacity .7s;cursor:pointer;color:#00a0d2}.wc-products-list-card__search-results .wc-products-list-card__content--added{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content:hover{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content--transition-exit-active{opacity:0}.wc-products-list-card__search-results .wc-products-list-card__content:first-child{border-top-width:0}.wc-products-list-card__search-results .wc-products-list-card__content img{object-fit:cover;object-position:center;width:2.5em;height:2.5em;margin:0 1em 0 0}.wc-products-list-card__search-results .wc-products-list-card__content .dashicon{color:#0073aa;margin-left:auto}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item img{outline:0}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item button{display:none}.wc-products-list-card__search-no-results{display:block;margin:1em 0 0}.wc-products-list-card__search-no-selected{display:block;margin:-.75em 0 0}.wc-products-list-card__results-wrapper{position:relative;overflow:hidden}@media only screen and (min-width:700px){.wc-products-settings-heading{display:flex;justify-content:space-between}.wc-products-list-card{max-width:480px}}.edit-post-sidebar .wc-products-scope-descriptions{margin-bottom:1.5em;position:relative;padding-left:46px;padding-top:1em;padding-bottom:1.5em;border-bottom:1px solid #e6eaee;display:flex;justify-content:space-between}.edit-post-sidebar h3{font-weight:500;margin-bottom:5px;color:#555d66}.edit-post-sidebar .scope-description{font-size:12px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink{margin-left:1em;min-width:24px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink a{cursor:pointer}
1
+ .wc-products-block-preview{overflow:hidden}.wc-products-block-preview .product-preview{float:left;text-align:center;margin-right:3.8%}.wc-products-block-preview.cols-1 .product-preview{float:none;margin-right:0}.wc-products-block-preview.cols-2 .product-preview{width:48%}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n){margin-right:0}.wc-products-block-preview.cols-2 .product-preview:nth-of-type(2n+1){clear:both}.wc-products-block-preview.cols-3 .product-preview{width:30.75%}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n){margin-right:0}.wc-products-block-preview.cols-3 .product-preview:nth-of-type(3n+1){clear:both}.wc-products-block-preview.cols-4 .product-preview{width:22.05%}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n){margin-right:0}.wc-products-block-preview.cols-4 .product-preview:nth-of-type(4n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview{width:16.9%}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n){margin-right:0}.wc-products-block-preview.cols-5 .product-preview:nth-of-type(5n+1){clear:both}.wc-products-block-preview.cols-5 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview.cols-6 .product-preview{width:13.5%}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n){margin-right:0}.wc-products-block-preview.cols-6 .product-preview:nth-of-type(6n+1){clear:both}.wc-products-block-preview.cols-6 .product-preview .product-add-to-cart{font-size:.75em}.wc-products-block-preview .product-add-to-cart{display:inline-block;background:#ababab;border-radius:1.5em;color:#fff;cursor:pointer;padding:.75em 1.25em;line-height:1.2em;margin-top:.5em;margin-bottom:1em}.wc-products-settings{background-color:#f8f9f9;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px;position:relative}.wc-products-settings__title{margin:0;padding:1.5rem 0;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-settings__title .dashicon{vertical-align:top;margin-right:.25em}.wc-products-settings__footer{margin:2em 0 0;padding:1.5em 0;border-top:1px solid #e6eaee;text-align:center}.wc-products-settings__footer .button{padding-left:1.5em;padding-right:1.5em}.wc-products-display-options--popover+.wc-products-settings__footer,.wc-products-settings-heading+.wc-products-settings__footer{margin-top:-2em;border-top:none}p.wc-products-block-description{margin:2em 0 1.5em 0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;text-align:center}.wc-products-display-options{margin:0 0 2.5em}.wc-products-display-options__option{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0 auto;padding:1.25em 1.5em;max-width:80%;background:#fff;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee;cursor:pointer}.wc-products-display-options__option:last-of-type{border-bottom-width:1px}.wc-products-display-options__option--attribute,.wc-products-display-options__option--best_selling,.wc-products-display-options__option--featured,.wc-products-display-options__option--on_sale,.wc-products-display-options__option--top_rated{display:none;background-color:#fdfdfd;padding-top:1em;padding-bottom:1em}.wc-products-display-options__option--attribute .wc-products-display-options__option-title,.wc-products-display-options__option--best_selling .wc-products-display-options__option-title,.wc-products-display-options__option--featured .wc-products-display-options__option-title,.wc-products-display-options__option--on_sale .wc-products-display-options__option-title,.wc-products-display-options__option--top_rated .wc-products-display-options__option-title{font-size:1.15em}.wc-products-display-options__option--attribute .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--best_selling .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--featured .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--on_sale .wc-products-display-options__icon .dashicon,.wc-products-display-options__option--top_rated .wc-products-display-options__icon .dashicon{height:20px;width:20px}.wc-products-display-options__option--current{cursor:default}.wc-products-display-options__option--current .wc-products-display-options__option-title{color:#86909b}.wc-products-display-options__option-content{width:85%;-ms-flex-item-align:center;align-self:center}.wc-products-display-options__option-title{display:block;font-size:1.25em}p.wc-products-display-options__option-description{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:1em;color:#86909b}.wc-products-display-options__icon{-ms-flex-item-align:center;align-self:center;margin-left:auto;color:#b9bcc2}.wc-products-display-options__icon .dashicon{height:25px;width:25px}.wc-products-display-options--popover{position:absolute;right:-2em;max-width:60%;margin:0;z-index:999;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);margin-top:-2.15em}.wc-products-display-options--popover .wc-products-display-options__option{margin:0;max-width:none}.wc-products-display-options--popover__arrow{width:2em;height:1.25em;position:absolute;top:-1.15em;right:30%;overflow:hidden}.wc-products-display-options--popover__arrow:after{content:'';position:absolute;width:1.25em;height:1.25em;background:#fff;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);top:.625em;left:.3125em;box-shadow:0 2px 10px 0 rgba(0,0,0,.1);border:1px solid #e6eaee}.wc-products-display-options--extended .wc-products-display-options__option--attribute,.wc-products-display-options--extended .wc-products-display-options__option--best_selling,.wc-products-display-options--extended .wc-products-display-options__option--featured,.wc-products-display-options--extended .wc-products-display-options__option--on_sale,.wc-products-display-options--extended .wc-products-display-options__option--top_rated{display:-webkit-box;display:-ms-flexbox;display:flex}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--category{border-bottom-width:1px}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--filter{margin-top:.5em}.wc-products-display-options--extended:not(.wc-products-display-options--popover) .wc-products-display-options__option--attribute{margin-bottom:.5em;border-bottom-width:1px}.wc-products-settings-heading{margin:0 0 2em 0;padding:1em 2em;text-align:center;border-bottom:1px solid #e6eaee}.wc-products-list-card{position:relative;margin-left:auto;margin-right:auto;padding:0 1em;overflow:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__input-wrapper{position:relative;background:#fff;margin:0 0 1em}.wc-products-list-card .wc-products-list-card__input-wrapper .dashicon{position:absolute;top:calc(1em - 1px);left:1em;z-index:1}.wc-products-list-card input[type=search]{position:relative;width:100%;margin:0;padding:1em 1.25em 1em 3em;border-radius:0;background:0 0;border-color:#e6eaee;box-shadow:none;z-index:2}.wc-products-list-card .wc-products-list-card__results{max-height:200px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box}.wc-products-list-card .wc-products-list-card__results ul{list-style:none}.wc-products-list-card .wc-products-list-card__results ul li{margin:0;border:1px solid #e6eaee;border-bottom-width:0}.wc-products-list-card .wc-products-list-card__results ul li:last-child{border-bottom-width:1px}.wc-products-list-card .wc-products-list-card__content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:.75em 1.25em;background:#fff;border-bottom:1px solid #e6eaee}.wc-products-list-card:after{content:'';position:absolute;left:0;bottom:0;width:100%;height:1.5em;background:-webkit-linear-gradient(rgba(255,255,255,.1) 0,#f8f9f9 100%);background:linear-gradient(rgba(255,255,255,.1) 0,#f8f9f9 100%)}.wc-products-list-card--taxonomy .wc-products-list-card__taxonomy-count{text-align:center;width:30px;font-size:.8em;border:1px solid #e9e9e9;border-radius:1em;color:#aaa}.wc-products-list-card--taxonomy input[type=checkbox]{position:relative;margin-top:0;margin-right:.75em;border-radius:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li{margin-top:-1px}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li:last-child{border-bottom-width:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul{display:none;padding:1em 1.25em 1em 3.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li ul li:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open{margin:.5em 0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul{display:block}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.wc-products-list-card--taxonomy-category .wc-products-list-card__results ul li.wc-products-list-card__accordion-open ul li .wc-products-list-card__taxonomy-count{margin-left:auto}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button{cursor:pointer;color:#666;margin:0 1em 0 auto;padding:0 0 0 .75em;border:none;border-radius:0;background:0 0;outline:0;text-decoration:none}.wc-products-list-card--taxonomy-category .wc-products-list-card__accordion-button .dashicon{-ms-flex-item-align:center;align-self:center;display:-webkit-box;display:-ms-flexbox;display:flex}.wc-products-list-card--taxonomy-category input[type=checkbox]:indeterminate:before{position:absolute;top:0;bottom:0;right:0;left:0;content:'';margin:42% 20%;width:60%;background:#0073aa}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul{padding:1em 1.25em 1em 3.25em;background:#fdfdfd;border-bottom:1px solid #e6eaee}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li{margin-bottom:.25em;border:none}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__results ul li .wc-products-list-card__content{padding:0;background:0 0;border:none}.wc-products-list-card--taxonomy-atributes__atribute{margin:-1px 0 0;border-width:1px 1px 0;border-style:solid;border-color:#e6eaee}.wc-products-list-card--taxonomy-atributes__atribute:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open{margin-top:.5em;margin-bottom:.5em}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:first-child{margin-top:0}.wc-products-list-card--taxonomy-atributes__atribute.wc-products-list-card__accordion-open:last-child{margin-bottom:0}.wc-products-list-card--taxonomy-atributes .wc-products-list-card__taxonomy-count{margin-left:auto}.wc-products-list-card--taxonomy-atributes input[type=radio]{position:relative;margin-top:0;margin-right:.75em;border-radius:100%}.wc-products-list-card--specific{overflow:visible}.wc-products-list-card--specific:after{content:none}.wc-products-list-card--specific .wc-products-list-card__item{position:relative;border:none}.wc-products-list-card--specific .wc-products-list-card__item img{margin:0;outline:4px solid #00a0d2;outline-offset:-4px}.wc-products-list-card--specific .wc-products-list-card__item button{position:absolute;top:0;right:0;background:#00a0d2;padding:0;margin:0;border:none;margin-left:auto;line-height:10px;cursor:pointer}.wc-products-list-card--specific .wc-products-list-card__item .dashicon{color:#fff}.wc-products-list-card--specific .wc-products-list-card__input-wrapper{margin:0}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-1 .wc-products-list-card__item{width:100%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-2 .wc-products-list-card__item{width:50%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-3 .wc-products-list-card__item{width:33.3333333333%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-4 .wc-products-list-card__item{width:25%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-5 .wc-products-list-card__item{width:20%}.wc-products-list-card--specific .wc-products-list-card__results-wrapper--cols-6 .wc-products-list-card__item{width:16.6666666667%}.wc-products-list-card--specific .wc-products-list-card__results{max-height:none;overflow:visible}.wc-products-list-card--specific .wc-products-list-card__results h3{margin:0 0 1em;font-size:1em}.wc-products-list-card--specific .wc-products-list-card__results ul{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0 -.5em -1em}.wc-products-list-card--specific .wc-products-list-card__results ul li{border:none;padding:0 .5em;margin:0 0 1em}.wc-products-list-card--specific .wc-products-list-card__results .wc-products-list-card__content{position:relative;display:block;padding:0;background:0 0;border:none}.wc-products-list-card__search-wrapper{position:relative;margin:0 0 1.5em}.wc-products-list-card__search-results{width:100%;list-style:none;background:#fff;margin:-1px 0 0;border:1px solid #e6eaee;box-shadow:0 1px 3px #e6eaee}.wc-products-list-card__search-results>div{max-height:175px;overflow-y:auto}.wc-products-list-card__search-results .wc-products-list-card__content{position:relative;border-width:1px 0 0;border-style:solid;border-color:#e6eaee;-webkit-transition:opacity .7s;transition:opacity .7s;cursor:pointer;color:#00a0d2}.wc-products-list-card__search-results .wc-products-list-card__content--added{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content:hover{background-color:#f7fcff}.wc-products-list-card__search-results .wc-products-list-card__content--transition-exit-active{opacity:0}.wc-products-list-card__search-results .wc-products-list-card__content:first-child{border-top-width:0}.wc-products-list-card__search-results .wc-products-list-card__content img{-o-object-fit:cover;object-fit:cover;-o-object-position:center;object-position:center;width:2.5em;height:2.5em;margin:0 1em 0 0}.wc-products-list-card__search-results .wc-products-list-card__content .dashicon{color:#0073aa;margin-left:auto}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item img{outline:0}.wc-products-list-card__search-wrapper--with-results+.wc-products-list-card__results-wrapper .wc-products-list-card__item button{display:none}.wc-products-list-card__search-no-results{display:block;margin:1em 0 0}.wc-products-list-card__search-no-selected{display:block;margin:-.75em 0 0}.wc-products-list-card__results-wrapper{position:relative;overflow:hidden}@media only screen and (min-width:700px){.wc-products-settings-heading{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.wc-products-list-card{max-width:480px}}.edit-post-sidebar .wc-products-scope-descriptions{margin-bottom:1.5em;position:relative;padding-left:46px;padding-top:1em;padding-bottom:1.5em;border-bottom:1px solid #e6eaee;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.edit-post-sidebar h3{font-weight:500;margin-bottom:5px;color:#555d66}.edit-post-sidebar .scope-description{font-size:12px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink{margin-left:1em;min-width:24px}.edit-post-sidebar .wc-products-scope-description--edit-quicklink a{cursor:pointer}
assets/css/gutenberg-products-block.scss CHANGED
@@ -185,8 +185,8 @@ p.wc-products-block-description {
185
  }
186
 
187
  &--featured,
188
- &--best_sellers,
189
- &--best_rated,
190
  &--on_sale,
191
  &--attribute {
192
  display: none;
@@ -285,8 +285,8 @@ p.wc-products-display-options__option-description {
285
  .wc-products-display-options--extended {
286
  .wc-products-display-options__option {
287
  &--featured,
288
- &--best_sellers,
289
- &--best_rated,
290
  &--on_sale,
291
  &--attribute {
292
  display: flex;
185
  }
186
 
187
  &--featured,
188
+ &--best_selling,
189
+ &--top_rated,
190
  &--on_sale,
191
  &--attribute {
192
  display: none;
285
  .wc-products-display-options--extended {
286
  .wc-products-display-options__option {
287
  &--featured,
288
+ &--best_selling,
289
+ &--top_rated,
290
  &--on_sale,
291
  &--attribute {
292
  display: flex;
assets/js/products-block.js CHANGED
@@ -90,10 +90,10 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function"
90
 
91
  var __ = wp.i18n.__;
92
  var RawHTML = wp.element.RawHTML;
93
- var _wp$blocks = wp.blocks,
94
- registerBlockType = _wp$blocks.registerBlockType,
95
- InspectorControls = _wp$blocks.InspectorControls,
96
- BlockControls = _wp$blocks.BlockControls;
97
  var _wp$components = wp.components,
98
  Toolbar = _wp$components.Toolbar,
99
  withAPIData = _wp$components.withAPIData,
@@ -110,6 +110,7 @@ var _wp$components = wp.components,
110
  * description - Display description of the setting.
111
  * value - Display setting slug to set when selected.
112
  * group_container - (optional) If set the setting is a parent container.
 
113
  */
114
  var PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
115
  'specific': {
@@ -138,6 +139,18 @@ var PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
138
  description: '',
139
  value: 'on_sale'
140
  },
 
 
 
 
 
 
 
 
 
 
 
 
141
  'attribute': {
142
  title: __('Attribute'),
143
  description: '',
@@ -150,6 +163,16 @@ var PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
150
  }
151
  };
152
 
 
 
 
 
 
 
 
 
 
 
153
  /**
154
  * One option from the list of all available ways to display products.
155
  */
@@ -420,7 +443,7 @@ var ProductsBlockSettingsEditor = function (_React$Component3) {
420
 
421
  var heading = null;
422
  if (this.state.display) {
423
- var group_options = ['featured', 'on_sale', 'attribute'];
424
  var should_group_expand = group_options.includes(this.state.display) ? this.state.display : '';
425
  var menu_link = wp.element.createElement(
426
  'button',
@@ -529,7 +552,7 @@ var ProductPreview = function (_React$Component4) {
529
 
530
  return wp.element.createElement(
531
  'div',
532
- { className: 'product-preview' },
533
  image,
534
  wp.element.createElement(
535
  'div',
@@ -584,12 +607,18 @@ var ProductsBlockPreview = withAPIData(function (_ref) {
584
  query.on_sale = 1;
585
  }
586
 
587
- // @todo Add support for orderby by sales, rating, and price to the API.
588
- if ('title' === orderby || 'date' === orderby) {
589
- query.orderby = orderby;
590
-
591
- if ('title' === orderby) {
 
 
 
 
592
  query.order = 'asc';
 
 
593
  }
594
  }
595
 
@@ -620,7 +649,8 @@ var ProductsBlockPreview = withAPIData(function (_ref) {
620
  }
621
 
622
  return {
623
- products: '/wc/v2/products' + query_string
 
624
  };
625
  })(function (_ref2) {
626
  var products = _ref2.products,
@@ -822,33 +852,36 @@ var ProductsBlock = function (_React$Component5) {
822
  max: wc_product_block_data.max_columns
823
  });
824
 
825
- var orderControl = wp.element.createElement(SelectControl, {
826
- key: 'query-panel-select',
827
- label: __('Order Products By'),
828
- value: orderby,
829
- options: [{
830
- label: __('Newness - newest first'),
831
- value: 'date'
832
- }, {
833
- label: __('Price - low to high'),
834
- value: 'price_asc'
835
- }, {
836
- label: __('Price - high to low'),
837
- value: 'price_desc'
838
- }, {
839
- label: __('Rating - highest first'),
840
- value: 'rating'
841
- }, {
842
- label: __('Sales - most first'),
843
- value: 'popularity'
844
- }, {
845
- label: __('Title - alphabetical'),
846
- value: 'title'
847
- }],
848
- onChange: function onChange(value) {
849
- return setAttributes({ orderby: value });
850
- }
851
- });
 
 
 
852
 
853
  // Row settings don't make sense for specific-selected products display.
854
  var rowControl = null;
@@ -1032,13 +1065,11 @@ var ProductsBlock = function (_React$Component5) {
1032
  }, {
1033
  key: 'render',
1034
  value: function render() {
1035
- var _props5 = this.props,
1036
- attributes = _props5.attributes,
1037
- focus = _props5.focus;
1038
  var edit_mode = attributes.edit_mode;
1039
 
1040
 
1041
- return [!!focus ? this.getInspectorControls() : null, !!focus ? this.getToolbarControls() : null, edit_mode ? this.getSettingsEditor() : this.getPreview()];
1042
  }
1043
  }]);
1044
 
@@ -1143,6 +1174,10 @@ registerBlockType('woocommerce/products', {
1143
  shortcode_atts.set('visibility', 'featured');
1144
  } else if ('on_sale' === display) {
1145
  shortcode_atts.set('on_sale', '1');
 
 
 
 
1146
  } else if ('attribute' === display) {
1147
  var attribute = display_setting.length ? (0, _attributeSelect.getAttributeSlug)(display_setting[0]) : '';
1148
  var terms = display_setting.length > 1 ? display_setting.slice(1).join(',') : '';
@@ -1153,7 +1188,7 @@ registerBlockType('woocommerce/products', {
1153
  }
1154
  }
1155
 
1156
- if ('specific' !== display) {
1157
  if ('price_desc' === orderby) {
1158
  shortcode_atts.set('orderby', 'price');
1159
  shortcode_atts.set('order', 'DESC');
@@ -1767,7 +1802,7 @@ var ProductSpecificSelectedProducts = withAPIData(function (props) {
1767
 
1768
  productElements.push(wp.element.createElement(
1769
  'li',
1770
- { className: 'wc-products-list-card__item' },
1771
  wp.element.createElement(
1772
  'div',
1773
  { className: 'wc-products-list-card__content' },
@@ -2268,13 +2303,6 @@ var _wp$components = wp.components,
2268
  Dropdown = _wp$components.Dropdown,
2269
  Dashicon = _wp$components.Dashicon;
2270
 
2271
- /**
2272
- * Attribute data cache.
2273
- * Needed because it takes a lot of API calls to generate attribute info.
2274
- */
2275
-
2276
- var PRODUCT_ATTRIBUTE_DATA = {};
2277
-
2278
  /**
2279
  * Get the identifier for an attribute. The identifier can be used to determine
2280
  * the slug or the ID of the attribute.
@@ -2282,6 +2310,7 @@ var PRODUCT_ATTRIBUTE_DATA = {};
2282
  * @param string slug The attribute slug.
2283
  * @param int|numeric string id The attribute ID.
2284
  */
 
2285
  function getAttributeIdentifier(slug, id) {
2286
  return slug + ',' + id;
2287
  }
@@ -2510,31 +2539,19 @@ var ProductAttributeList = withAPIData(function (props) {
2510
  for (var _iterator2 = attributes.data[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
2511
  var attribute = _step2.value;
2512
 
2513
-
2514
  // Filter out attributes that don't match the search query.
2515
  if (filter.length && -1 === attribute.name.toLowerCase().indexOf(filter)) {
2516
  continue;
2517
  }
2518
 
2519
- if (PRODUCT_ATTRIBUTE_DATA.hasOwnProperty(attribute.slug)) {
2520
- attributeElements.push(wp.element.createElement(ProductAttributeElement, {
2521
- selectedAttribute: selectedAttribute,
2522
- selectedTerms: selectedTerms,
2523
- attribute: attribute,
2524
- setSelectedAttribute: setSelectedAttribute,
2525
- addTerm: addTerm,
2526
- removeTerm: removeTerm
2527
- }));
2528
- } else {
2529
- attributeElements.push(wp.element.createElement(UncachedProductAttributeElement, {
2530
- selectedAttribute: selectedAttribute,
2531
- selectedTerms: selectedTerms,
2532
- attribute: attribute,
2533
- setSelectedAttribute: setSelectedAttribute,
2534
- addTerm: addTerm,
2535
- removeTerm: removeTerm
2536
- }));
2537
- }
2538
  }
2539
  } catch (err) {
2540
  _didIteratorError2 = true;
@@ -2559,77 +2576,12 @@ var ProductAttributeList = withAPIData(function (props) {
2559
  });
2560
 
2561
  /**
2562
- * Caches then renders a product attribute term element.
2563
- */
2564
- var UncachedProductAttributeElement = withAPIData(function (props) {
2565
- return {
2566
- terms: '/wc/v2/products/attributes/' + props.attribute.id + '/terms'
2567
- };
2568
- })(function (_ref2) {
2569
- var terms = _ref2.terms,
2570
- selectedAttribute = _ref2.selectedAttribute,
2571
- selectedTerms = _ref2.selectedTerms,
2572
- attribute = _ref2.attribute,
2573
- setSelectedAttribute = _ref2.setSelectedAttribute,
2574
- addTerm = _ref2.addTerm,
2575
- removeTerm = _ref2.removeTerm;
2576
-
2577
- if (!terms.data || 0 === terms.data.length) {
2578
- return null;
2579
- }
2580
-
2581
- // Populate cache.
2582
- PRODUCT_ATTRIBUTE_DATA[attribute.slug] = { terms: [] };
2583
-
2584
- var totalCount = 0;
2585
- var _iteratorNormalCompletion3 = true;
2586
- var _didIteratorError3 = false;
2587
- var _iteratorError3 = undefined;
2588
-
2589
- try {
2590
- for (var _iterator3 = terms.data[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
2591
- var term = _step3.value;
2592
-
2593
- totalCount += term.count;
2594
- PRODUCT_ATTRIBUTE_DATA[attribute.slug].terms.push(term);
2595
- }
2596
- } catch (err) {
2597
- _didIteratorError3 = true;
2598
- _iteratorError3 = err;
2599
- } finally {
2600
- try {
2601
- if (!_iteratorNormalCompletion3 && _iterator3.return) {
2602
- _iterator3.return();
2603
- }
2604
- } finally {
2605
- if (_didIteratorError3) {
2606
- throw _iteratorError3;
2607
- }
2608
- }
2609
- }
2610
-
2611
- PRODUCT_ATTRIBUTE_DATA[attribute.slug].count = totalCount;
2612
-
2613
- return wp.element.createElement(ProductAttributeElement, {
2614
- selectedAttribute: selectedAttribute,
2615
- selectedTerms: selectedTerms,
2616
- attribute: attribute,
2617
- setSelectedAttribute: setSelectedAttribute,
2618
- addTerm: addTerm,
2619
- removeTerm: removeTerm
2620
- });
2621
- });
2622
-
2623
- /**
2624
- * A product attribute term element.
2625
  */
2626
 
2627
  var ProductAttributeElement = function (_React$Component2) {
2628
  _inherits(ProductAttributeElement, _React$Component2);
2629
 
2630
- /**
2631
- * Constructor.
2632
- */
2633
  function ProductAttributeElement(props) {
2634
  _classCallCheck(this, ProductAttributeElement);
2635
 
@@ -2672,50 +2624,22 @@ var ProductAttributeElement = function (_React$Component2) {
2672
  this.props.removeTerm(evt.target.value);
2673
  }
2674
  }
2675
-
2676
- /**
2677
- * Render the details for one attribute.
2678
- */
2679
-
2680
  }, {
2681
  key: 'render',
2682
  value: function render() {
2683
- var _this3 = this;
2684
-
2685
- var attribute = PRODUCT_ATTRIBUTE_DATA[this.props.attribute.slug];
2686
  var isSelected = this.props.selectedAttribute === getAttributeIdentifier(this.props.attribute.slug, this.props.attribute.id);
2687
 
2688
  var attributeTerms = null;
2689
  if (isSelected) {
2690
- attributeTerms = wp.element.createElement(
2691
- 'ul',
2692
- null,
2693
- attribute.terms.map(function (term) {
2694
- return wp.element.createElement(
2695
- 'li',
2696
- { className: 'wc-products-list-card__item' },
2697
- wp.element.createElement(
2698
- 'label',
2699
- { className: 'wc-products-list-card__content' },
2700
- wp.element.createElement('input', { type: 'checkbox',
2701
- value: term.id,
2702
- onChange: _this3.handleTermChange,
2703
- checked: _this3.props.selectedTerms.includes(String(term.id))
2704
- }),
2705
- term.name,
2706
- wp.element.createElement(
2707
- 'span',
2708
- { className: 'wc-products-list-card__taxonomy-count' },
2709
- term.count
2710
- )
2711
- )
2712
- );
2713
- })
2714
- );
2715
  }
2716
 
2717
  var cssClasses = ['wc-products-list-card--taxonomy-atributes__atribute'];
2718
-
2719
  if (isSelected) {
2720
  cssClasses.push('wc-products-list-card__accordion-open');
2721
  }
@@ -2734,12 +2658,7 @@ var ProductAttributeElement = function (_React$Component2) {
2734
  onChange: this.handleAttributeChange,
2735
  checked: isSelected
2736
  }),
2737
- this.props.attribute.name,
2738
- wp.element.createElement(
2739
- 'span',
2740
- { className: 'wc-products-list-card__taxonomy-count' },
2741
- attribute.count
2742
- )
2743
  )
2744
  ),
2745
  attributeTerms
@@ -2750,5 +2669,85 @@ var ProductAttributeElement = function (_React$Component2) {
2750
  return ProductAttributeElement;
2751
  }(React.Component);
2752
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2753
  /***/ })
2754
  /******/ ]);
90
 
91
  var __ = wp.i18n.__;
92
  var RawHTML = wp.element.RawHTML;
93
+ var registerBlockType = wp.blocks.registerBlockType;
94
+ var _wp$editor = wp.editor,
95
+ InspectorControls = _wp$editor.InspectorControls,
96
+ BlockControls = _wp$editor.BlockControls;
97
  var _wp$components = wp.components,
98
  Toolbar = _wp$components.Toolbar,
99
  withAPIData = _wp$components.withAPIData,
110
  * description - Display description of the setting.
111
  * value - Display setting slug to set when selected.
112
  * group_container - (optional) If set the setting is a parent container.
113
+ * no_orderby - (optional) If set the setting does not allow orderby settings.
114
  */
115
  var PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
116
  'specific': {
139
  description: '',
140
  value: 'on_sale'
141
  },
142
+ 'best_selling': {
143
+ title: __('Best sellers'),
144
+ description: '',
145
+ value: 'best_selling',
146
+ no_orderby: true
147
+ },
148
+ 'top_rated': {
149
+ title: __('Top rated'),
150
+ description: '',
151
+ value: 'top_rated',
152
+ no_orderby: true
153
+ },
154
  'attribute': {
155
  title: __('Attribute'),
156
  description: '',
163
  }
164
  };
165
 
166
+ /**
167
+ * Returns whether or not a display scope supports orderby options.
168
+ *
169
+ * @param string display The display scope slug.
170
+ * @return bool
171
+ */
172
+ function supportsOrderby(display) {
173
+ return !(PRODUCTS_BLOCK_DISPLAY_SETTINGS.hasOwnProperty(display) && PRODUCTS_BLOCK_DISPLAY_SETTINGS[display].hasOwnProperty('no_orderby') && PRODUCTS_BLOCK_DISPLAY_SETTINGS[display].no_orderby);
174
+ }
175
+
176
  /**
177
  * One option from the list of all available ways to display products.
178
  */
443
 
444
  var heading = null;
445
  if (this.state.display) {
446
+ var group_options = ['featured', 'on_sale', 'attribute', 'best_selling', 'top_rated'];
447
  var should_group_expand = group_options.includes(this.state.display) ? this.state.display : '';
448
  var menu_link = wp.element.createElement(
449
  'button',
552
 
553
  return wp.element.createElement(
554
  'div',
555
+ { className: 'product-preview', key: product.id + '-preview' },
556
  image,
557
  wp.element.createElement(
558
  'div',
607
  query.on_sale = 1;
608
  }
609
 
610
+ if (supportsOrderby(display)) {
611
+ if ('price_desc' === orderby) {
612
+ query.orderby = 'price';
613
+ query.order = 'desc';
614
+ } else if ('price_asc' === orderby) {
615
+ query.orderby = 'price';
616
+ query.order = 'asc';
617
+ } else if ('title' === orderby) {
618
+ query.orderby = 'title';
619
  query.order = 'asc';
620
+ } else {
621
+ query.orderby = orderby;
622
  }
623
  }
624
 
649
  }
650
 
651
  return {
652
+ // @todo Switch this to use WC core API when possible.
653
+ products: '/wgbp/v3/products' + query_string
654
  };
655
  })(function (_ref2) {
656
  var products = _ref2.products,
852
  max: wc_product_block_data.max_columns
853
  });
854
 
855
+ var orderControl = null;
856
+ if (supportsOrderby(display)) {
857
+ orderControl = wp.element.createElement(SelectControl, {
858
+ key: 'query-panel-select',
859
+ label: __('Order Products By'),
860
+ value: orderby,
861
+ options: [{
862
+ label: __('Newness - newest first'),
863
+ value: 'date'
864
+ }, {
865
+ label: __('Price - low to high'),
866
+ value: 'price_asc'
867
+ }, {
868
+ label: __('Price - high to low'),
869
+ value: 'price_desc'
870
+ }, {
871
+ label: __('Rating - highest first'),
872
+ value: 'rating'
873
+ }, {
874
+ label: __('Sales - most first'),
875
+ value: 'popularity'
876
+ }, {
877
+ label: __('Title - alphabetical'),
878
+ value: 'title'
879
+ }],
880
+ onChange: function onChange(value) {
881
+ return setAttributes({ orderby: value });
882
+ }
883
+ });
884
+ }
885
 
886
  // Row settings don't make sense for specific-selected products display.
887
  var rowControl = null;
1065
  }, {
1066
  key: 'render',
1067
  value: function render() {
1068
+ var attributes = this.props.attributes;
 
 
1069
  var edit_mode = attributes.edit_mode;
1070
 
1071
 
1072
+ return [this.getInspectorControls(), this.getToolbarControls(), edit_mode ? this.getSettingsEditor() : this.getPreview()];
1073
  }
1074
  }]);
1075
 
1174
  shortcode_atts.set('visibility', 'featured');
1175
  } else if ('on_sale' === display) {
1176
  shortcode_atts.set('on_sale', '1');
1177
+ } else if ('best_selling' === display) {
1178
+ shortcode_atts.set('best_selling', '1');
1179
+ } else if ('top_rated' === display) {
1180
+ shortcode_atts.set('top_rated', '1');
1181
  } else if ('attribute' === display) {
1182
  var attribute = display_setting.length ? (0, _attributeSelect.getAttributeSlug)(display_setting[0]) : '';
1183
  var terms = display_setting.length > 1 ? display_setting.slice(1).join(',') : '';
1188
  }
1189
  }
1190
 
1191
+ if (supportsOrderby(display)) {
1192
  if ('price_desc' === orderby) {
1193
  shortcode_atts.set('orderby', 'price');
1194
  shortcode_atts.set('order', 'DESC');
1802
 
1803
  productElements.push(wp.element.createElement(
1804
  'li',
1805
+ { className: 'wc-products-list-card__item', key: productData.id + '-specific-select-edit' },
1806
  wp.element.createElement(
1807
  'div',
1808
  { className: 'wc-products-list-card__content' },
2303
  Dropdown = _wp$components.Dropdown,
2304
  Dashicon = _wp$components.Dashicon;
2305
 
 
 
 
 
 
 
 
2306
  /**
2307
  * Get the identifier for an attribute. The identifier can be used to determine
2308
  * the slug or the ID of the attribute.
2310
  * @param string slug The attribute slug.
2311
  * @param int|numeric string id The attribute ID.
2312
  */
2313
+
2314
  function getAttributeIdentifier(slug, id) {
2315
  return slug + ',' + id;
2316
  }
2539
  for (var _iterator2 = attributes.data[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
2540
  var attribute = _step2.value;
2541
 
 
2542
  // Filter out attributes that don't match the search query.
2543
  if (filter.length && -1 === attribute.name.toLowerCase().indexOf(filter)) {
2544
  continue;
2545
  }
2546
 
2547
+ attributeElements.push(wp.element.createElement(ProductAttributeElement, {
2548
+ attribute: attribute,
2549
+ selectedAttribute: selectedAttribute,
2550
+ selectedTerms: selectedTerms,
2551
+ setSelectedAttribute: setSelectedAttribute,
2552
+ addTerm: addTerm,
2553
+ removeTerm: removeTerm
2554
+ }));
 
 
 
 
 
 
 
 
 
 
 
2555
  }
2556
  } catch (err) {
2557
  _didIteratorError2 = true;
2576
  });
2577
 
2578
  /**
2579
+ * One product attribute.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2580
  */
2581
 
2582
  var ProductAttributeElement = function (_React$Component2) {
2583
  _inherits(ProductAttributeElement, _React$Component2);
2584
 
 
 
 
2585
  function ProductAttributeElement(props) {
2586
  _classCallCheck(this, ProductAttributeElement);
2587
 
2624
  this.props.removeTerm(evt.target.value);
2625
  }
2626
  }
 
 
 
 
 
2627
  }, {
2628
  key: 'render',
2629
  value: function render() {
 
 
 
2630
  var isSelected = this.props.selectedAttribute === getAttributeIdentifier(this.props.attribute.slug, this.props.attribute.id);
2631
 
2632
  var attributeTerms = null;
2633
  if (isSelected) {
2634
+ attributeTerms = wp.element.createElement(AttributeTerms, {
2635
+ attribute: this.props.attribute,
2636
+ selectedTerms: this.props.selectedTerms,
2637
+ addTerm: this.props.addTerm,
2638
+ removeTerm: this.props.removeTerm
2639
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2640
  }
2641
 
2642
  var cssClasses = ['wc-products-list-card--taxonomy-atributes__atribute'];
 
2643
  if (isSelected) {
2644
  cssClasses.push('wc-products-list-card__accordion-open');
2645
  }
2658
  onChange: this.handleAttributeChange,
2659
  checked: isSelected
2660
  }),
2661
+ this.props.attribute.name
 
 
 
 
 
2662
  )
2663
  ),
2664
  attributeTerms
2669
  return ProductAttributeElement;
2670
  }(React.Component);
2671
 
2672
+ /**
2673
+ * The list of terms in an attribute.
2674
+ */
2675
+
2676
+
2677
+ var AttributeTerms = withAPIData(function (props) {
2678
+ return {
2679
+ terms: '/wc/v2/products/attributes/' + props.attribute.id + '/terms'
2680
+ };
2681
+ })(function (_ref2) {
2682
+ var terms = _ref2.terms,
2683
+ selectedTerms = _ref2.selectedTerms,
2684
+ attribute = _ref2.attribute,
2685
+ addTerm = _ref2.addTerm,
2686
+ removeTerm = _ref2.removeTerm;
2687
+
2688
+ if (!terms.data) {
2689
+ return wp.element.createElement(
2690
+ 'ul',
2691
+ null,
2692
+ wp.element.createElement(
2693
+ 'li',
2694
+ null,
2695
+ __('Loading')
2696
+ )
2697
+ );
2698
+ }
2699
+
2700
+ if (0 === terms.data.length) {
2701
+ return wp.element.createElement(
2702
+ 'ul',
2703
+ null,
2704
+ wp.element.createElement(
2705
+ 'li',
2706
+ null,
2707
+ __('No terms found')
2708
+ )
2709
+ );
2710
+ }
2711
+
2712
+ /**
2713
+ * Add or remove selected terms.
2714
+ *
2715
+ * @param evt Event object
2716
+ */
2717
+ function handleTermChange(evt) {
2718
+ if (evt.target.checked) {
2719
+ addTerm(evt.target.value);
2720
+ } else {
2721
+ removeTerm(evt.target.value);
2722
+ }
2723
+ }
2724
+
2725
+ return wp.element.createElement(
2726
+ 'ul',
2727
+ null,
2728
+ terms.data.map(function (term) {
2729
+ return wp.element.createElement(
2730
+ 'li',
2731
+ { className: 'wc-products-list-card__item' },
2732
+ wp.element.createElement(
2733
+ 'label',
2734
+ { className: 'wc-products-list-card__content' },
2735
+ wp.element.createElement('input', { type: 'checkbox',
2736
+ value: term.id,
2737
+ onChange: handleTermChange,
2738
+ checked: selectedTerms.includes(String(term.id))
2739
+ }),
2740
+ term.name,
2741
+ wp.element.createElement(
2742
+ 'span',
2743
+ { className: 'wc-products-list-card__taxonomy-count' },
2744
+ term.count
2745
+ )
2746
+ )
2747
+ );
2748
+ })
2749
+ );
2750
+ });
2751
+
2752
  /***/ })
2753
  /******/ ]);
assets/js/products-block.jsx CHANGED
@@ -1,6 +1,7 @@
1
  const { __ } = wp.i18n;
2
  const { RawHTML } = wp.element;
3
- const { registerBlockType, InspectorControls, BlockControls } = wp.blocks;
 
4
  const { Toolbar, withAPIData, Dropdown, Dashicon, RangeControl, Tooltip, SelectControl } = wp.components;
5
 
6
  import { ProductsSpecificSelect } from './views/specific-select.jsx';
@@ -13,6 +14,7 @@ import { ProductsAttributeSelect, getAttributeSlug, getAttributeID } from './vie
13
  * description - Display description of the setting.
14
  * value - Display setting slug to set when selected.
15
  * group_container - (optional) If set the setting is a parent container.
 
16
  */
17
  const PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
18
  'specific' : {
@@ -41,6 +43,18 @@ const PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
41
  description: '',
42
  value: 'on_sale',
43
  },
 
 
 
 
 
 
 
 
 
 
 
 
44
  'attribute' : {
45
  title: __( 'Attribute' ),
46
  description: '',
@@ -53,6 +67,18 @@ const PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
53
  }
54
  };
55
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  /**
57
  * One option from the list of all available ways to display products.
58
  */
@@ -248,7 +274,7 @@ class ProductsBlockSettingsEditor extends React.Component {
248
 
249
  let heading = null;
250
  if ( this.state.display ) {
251
- const group_options = [ 'featured', 'on_sale', 'attribute' ];
252
  let should_group_expand = group_options.includes( this.state.display ) ? this.state.display : '';
253
  let menu_link = <button type="button" className="wc-products-settings-heading__change-button button-link" onClick={ () => { this.setState( { menu_visible: ! this.state.menu_visible, expanded_group: should_group_expand } ) } }>{ __( 'Display different products' ) }</button>;
254
 
@@ -314,7 +340,7 @@ class ProductPreview extends React.Component {
314
  }
315
 
316
  return (
317
- <div className="product-preview">
318
  { image }
319
  <div className="product-title">{ product.name }</div>
320
  <div className="product-price" dangerouslySetInnerHTML={ { __html: product.price_html } } />
@@ -352,12 +378,18 @@ const ProductsBlockPreview = withAPIData( ( { attributes } ) => {
352
  query.on_sale = 1;
353
  }
354
 
355
- // @todo Add support for orderby by sales, rating, and price to the API.
356
- if ( 'title' === orderby || 'date' === orderby ) {
357
- query.orderby = orderby;
358
-
359
- if ( 'title' === orderby ) {
 
 
 
 
360
  query.order = 'asc';
 
 
361
  }
362
  }
363
 
@@ -367,7 +399,8 @@ const ProductsBlockPreview = withAPIData( ( { attributes } ) => {
367
  }
368
 
369
  return {
370
- products: '/wc/v2/products' + query_string
 
371
  };
372
 
373
  } )( ( { products, attributes } ) => {
@@ -502,40 +535,43 @@ class ProductsBlock extends React.Component {
502
  />
503
  );
504
 
505
- let orderControl = (
506
- <SelectControl
507
- key="query-panel-select"
508
- label={ __( 'Order Products By' ) }
509
- value={ orderby }
510
- options={ [
511
- {
512
- label: __( 'Newness - newest first' ),
513
- value: 'date',
514
- },
515
- {
516
- label: __( 'Price - low to high' ),
517
- value: 'price_asc',
518
- },
519
- {
520
- label: __( 'Price - high to low' ),
521
- value: 'price_desc',
522
- },
523
- {
524
- label: __( 'Rating - highest first' ),
525
- value: 'rating',
526
- },
527
- {
528
- label: __( 'Sales - most first' ),
529
- value: 'popularity',
530
- },
531
- {
532
- label: __( 'Title - alphabetical' ),
533
- value: 'title',
534
- },
535
- ] }
536
- onChange={ ( value ) => setAttributes( { orderby: value } ) }
537
- />
538
- );
 
 
 
539
 
540
  // Row settings don't make sense for specific-selected products display.
541
  let rowControl = null;
@@ -677,12 +713,12 @@ class ProductsBlock extends React.Component {
677
  }
678
 
679
  render() {
680
- const { attributes, focus } = this.props;
681
  const { edit_mode } = attributes;
682
 
683
  return [
684
- ( !! focus ) ? this.getInspectorControls() : null,
685
- ( !! focus ) ? this.getToolbarControls() : null,
686
  edit_mode ? this.getSettingsEditor() : this.getPreview(),
687
  ];
688
  }
@@ -777,6 +813,10 @@ registerBlockType( 'woocommerce/products', {
777
  shortcode_atts.set( 'visibility', 'featured' );
778
  } else if ( 'on_sale' === display ) {
779
  shortcode_atts.set( 'on_sale', '1' );
 
 
 
 
780
  } else if ( 'attribute' === display ) {
781
  const attribute = display_setting.length ? getAttributeSlug( display_setting[0] ) : '';
782
  const terms = display_setting.length > 1 ? display_setting.slice( 1 ).join( ',' ) : '';
@@ -787,7 +827,7 @@ registerBlockType( 'woocommerce/products', {
787
  }
788
  }
789
 
790
- if ( 'specific' !== display ) {
791
  if ( 'price_desc' === orderby ) {
792
  shortcode_atts.set( 'orderby', 'price' );
793
  shortcode_atts.set( 'order', 'DESC' )
1
  const { __ } = wp.i18n;
2
  const { RawHTML } = wp.element;
3
+ const { registerBlockType } = wp.blocks;
4
+ const { InspectorControls, BlockControls } = wp.editor;
5
  const { Toolbar, withAPIData, Dropdown, Dashicon, RangeControl, Tooltip, SelectControl } = wp.components;
6
 
7
  import { ProductsSpecificSelect } from './views/specific-select.jsx';
14
  * description - Display description of the setting.
15
  * value - Display setting slug to set when selected.
16
  * group_container - (optional) If set the setting is a parent container.
17
+ * no_orderby - (optional) If set the setting does not allow orderby settings.
18
  */
19
  const PRODUCTS_BLOCK_DISPLAY_SETTINGS = {
20
  'specific' : {
43
  description: '',
44
  value: 'on_sale',
45
  },
46
+ 'best_selling' : {
47
+ title: __( 'Best sellers' ),
48
+ description: '',
49
+ value: 'best_selling',
50
+ no_orderby: true,
51
+ },
52
+ 'top_rated' : {
53
+ title: __( 'Top rated' ),
54
+ description: '',
55
+ value: 'top_rated',
56
+ no_orderby: true,
57
+ },
58
  'attribute' : {
59
  title: __( 'Attribute' ),
60
  description: '',
67
  }
68
  };
69
 
70
+ /**
71
+ * Returns whether or not a display scope supports orderby options.
72
+ *
73
+ * @param string display The display scope slug.
74
+ * @return bool
75
+ */
76
+ function supportsOrderby( display ) {
77
+ return ! ( PRODUCTS_BLOCK_DISPLAY_SETTINGS.hasOwnProperty( display )
78
+ && PRODUCTS_BLOCK_DISPLAY_SETTINGS[ display ].hasOwnProperty( 'no_orderby' )
79
+ && PRODUCTS_BLOCK_DISPLAY_SETTINGS[ display ].no_orderby );
80
+ }
81
+
82
  /**
83
  * One option from the list of all available ways to display products.
84
  */
274
 
275
  let heading = null;
276
  if ( this.state.display ) {
277
+ const group_options = [ 'featured', 'on_sale', 'attribute', 'best_selling', 'top_rated' ];
278
  let should_group_expand = group_options.includes( this.state.display ) ? this.state.display : '';
279
  let menu_link = <button type="button" className="wc-products-settings-heading__change-button button-link" onClick={ () => { this.setState( { menu_visible: ! this.state.menu_visible, expanded_group: should_group_expand } ) } }>{ __( 'Display different products' ) }</button>;
280
 
340
  }
341
 
342
  return (
343
+ <div className="product-preview" key={ product.id + '-preview' } >
344
  { image }
345
  <div className="product-title">{ product.name }</div>
346
  <div className="product-price" dangerouslySetInnerHTML={ { __html: product.price_html } } />
378
  query.on_sale = 1;
379
  }
380
 
381
+ if ( supportsOrderby( display ) ) {
382
+ if ( 'price_desc' === orderby ) {
383
+ query.orderby = 'price';
384
+ query.order = 'desc';
385
+ } else if ( 'price_asc' === orderby ) {
386
+ query.orderby = 'price';
387
+ query.order = 'asc';
388
+ } else if ( 'title' === orderby ) {
389
+ query.orderby = 'title';
390
  query.order = 'asc';
391
+ } else {
392
+ query.orderby = orderby;
393
  }
394
  }
395
 
399
  }
400
 
401
  return {
402
+ // @todo Switch this to use WC core API when possible.
403
+ products: '/wgbp/v3/products' + query_string
404
  };
405
 
406
  } )( ( { products, attributes } ) => {
535
  />
536
  );
537
 
538
+ let orderControl = null;
539
+ if ( supportsOrderby( display ) ) {
540
+ orderControl = (
541
+ <SelectControl
542
+ key="query-panel-select"
543
+ label={ __( 'Order Products By' ) }
544
+ value={ orderby }
545
+ options={ [
546
+ {
547
+ label: __( 'Newness - newest first' ),
548
+ value: 'date',
549
+ },
550
+ {
551
+ label: __( 'Price - low to high' ),
552
+ value: 'price_asc',
553
+ },
554
+ {
555
+ label: __( 'Price - high to low' ),
556
+ value: 'price_desc',
557
+ },
558
+ {
559
+ label: __( 'Rating - highest first' ),
560
+ value: 'rating',
561
+ },
562
+ {
563
+ label: __( 'Sales - most first' ),
564
+ value: 'popularity',
565
+ },
566
+ {
567
+ label: __( 'Title - alphabetical' ),
568
+ value: 'title',
569
+ },
570
+ ] }
571
+ onChange={ ( value ) => setAttributes( { orderby: value } ) }
572
+ />
573
+ );
574
+ }
575
 
576
  // Row settings don't make sense for specific-selected products display.
577
  let rowControl = null;
713
  }
714
 
715
  render() {
716
+ const { attributes } = this.props;
717
  const { edit_mode } = attributes;
718
 
719
  return [
720
+ this.getInspectorControls(),
721
+ this.getToolbarControls(),
722
  edit_mode ? this.getSettingsEditor() : this.getPreview(),
723
  ];
724
  }
813
  shortcode_atts.set( 'visibility', 'featured' );
814
  } else if ( 'on_sale' === display ) {
815
  shortcode_atts.set( 'on_sale', '1' );
816
+ } else if ( 'best_selling' === display ) {
817
+ shortcode_atts.set( 'best_selling', '1' );
818
+ } else if ( 'top_rated' === display ) {
819
+ shortcode_atts.set( 'top_rated', '1' );
820
  } else if ( 'attribute' === display ) {
821
  const attribute = display_setting.length ? getAttributeSlug( display_setting[0] ) : '';
822
  const terms = display_setting.length > 1 ? display_setting.slice( 1 ).join( ',' ) : '';
827
  }
828
  }
829
 
830
+ if ( supportsOrderby( display ) ) {
831
  if ( 'price_desc' === orderby ) {
832
  shortcode_atts.set( 'orderby', 'price' );
833
  shortcode_atts.set( 'order', 'DESC' )
assets/js/views/attribute-select.jsx CHANGED
@@ -1,12 +1,6 @@
1
  const { __ } = wp.i18n;
2
  const { Toolbar, withAPIData, Dropdown, Dashicon } = wp.components;
3
 
4
- /**
5
- * Attribute data cache.
6
- * Needed because it takes a lot of API calls to generate attribute info.
7
- */
8
- const PRODUCT_ATTRIBUTE_DATA = {};
9
-
10
  /**
11
  * Get the identifier for an attribute. The identifier can be used to determine
12
  * the slug or the ID of the attribute.
@@ -181,31 +175,21 @@ const ProductAttributeList = withAPIData( ( props ) => {
181
  const filter = filterQuery.toLowerCase();
182
  let attributeElements = [];
183
  for ( let attribute of attributes.data ) {
184
-
185
  // Filter out attributes that don't match the search query.
186
  if ( filter.length && -1 === attribute.name.toLowerCase().indexOf( filter ) ) {
187
  continue;
188
  }
189
 
190
- if ( PRODUCT_ATTRIBUTE_DATA.hasOwnProperty( attribute.slug ) ) {
191
- attributeElements.push( <ProductAttributeElement
192
- selectedAttribute={ selectedAttribute }
193
- selectedTerms={ selectedTerms }
194
- attribute={attribute}
195
- setSelectedAttribute={ setSelectedAttribute }
196
  addTerm={ addTerm }
197
- removeTerm={ removeTerm }
198
- /> );
199
- } else {
200
- attributeElements.push( <UncachedProductAttributeElement
201
- selectedAttribute={ selectedAttribute }
202
- selectedTerms={ selectedTerms }
203
- attribute={ attribute }
204
- setSelectedAttribute={ setSelectedAttribute }
205
- addTerm={ addTerm }
206
- removeTerm={ removeTerm }
207
- /> );
208
- }
209
  }
210
 
211
  return (
@@ -217,47 +201,10 @@ const ProductAttributeList = withAPIData( ( props ) => {
217
  );
218
 
219
  /**
220
- * Caches then renders a product attribute term element.
221
- */
222
- const UncachedProductAttributeElement = withAPIData( ( props ) => {
223
- return {
224
- terms: '/wc/v2/products/attributes/' + props.attribute.id + '/terms'
225
- };
226
- } )( ( { terms, selectedAttribute, selectedTerms, attribute, setSelectedAttribute, addTerm, removeTerm } ) => {
227
- if ( ! terms.data || 0 === terms.data.length ) {
228
- return null;
229
- }
230
-
231
- // Populate cache.
232
- PRODUCT_ATTRIBUTE_DATA[ attribute.slug ] = { terms: [] };
233
-
234
- let totalCount = 0;
235
- for ( let term of terms.data ) {
236
- totalCount += term.count;
237
- PRODUCT_ATTRIBUTE_DATA[ attribute.slug ].terms.push( term );
238
- }
239
-
240
- PRODUCT_ATTRIBUTE_DATA[ attribute.slug ].count = totalCount;
241
-
242
- return <ProductAttributeElement
243
- selectedAttribute={ selectedAttribute }
244
- selectedTerms={ selectedTerms }
245
- attribute={ attribute }
246
- setSelectedAttribute={ setSelectedAttribute }
247
- addTerm={ addTerm }
248
- removeTerm={ removeTerm }
249
- />
250
- }
251
- );
252
-
253
- /**
254
- * A product attribute term element.
255
  */
256
  class ProductAttributeElement extends React.Component {
257
 
258
- /**
259
- * Constructor.
260
- */
261
  constructor( props ) {
262
  super( props );
263
 
@@ -291,36 +238,20 @@ class ProductAttributeElement extends React.Component {
291
  }
292
  }
293
 
294
- /**
295
- * Render the details for one attribute.
296
- */
297
  render() {
298
- const attribute = PRODUCT_ATTRIBUTE_DATA[ this.props.attribute.slug ];
299
  const isSelected = this.props.selectedAttribute === getAttributeIdentifier( this.props.attribute.slug, this.props.attribute.id );
300
 
301
  let attributeTerms = null;
302
  if ( isSelected ) {
303
- attributeTerms = (
304
- <ul>
305
- { attribute.terms.map( ( term ) => (
306
- <li className="wc-products-list-card__item">
307
- <label className="wc-products-list-card__content">
308
- <input type="checkbox"
309
- value={ term.id }
310
- onChange={ this.handleTermChange }
311
- checked={ this.props.selectedTerms.includes( String( term.id ) ) }
312
- />
313
- { term.name }
314
- <span className="wc-products-list-card__taxonomy-count">{ term.count }</span>
315
- </label>
316
- </li>
317
- ) ) }
318
- </ul>
319
- );
320
  }
321
 
322
  let cssClasses = [ 'wc-products-list-card--taxonomy-atributes__atribute' ];
323
-
324
  if ( isSelected ) {
325
  cssClasses.push( 'wc-products-list-card__accordion-open' );
326
  }
@@ -335,7 +266,6 @@ class ProductAttributeElement extends React.Component {
335
  checked={ isSelected }
336
  />
337
  { this.props.attribute.name }
338
- <span className="wc-products-list-card__taxonomy-count">{ attribute.count }</span>
339
  </label>
340
  </div>
341
  { attributeTerms }
@@ -343,3 +273,52 @@ class ProductAttributeElement extends React.Component {
343
  );
344
  }
345
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const { __ } = wp.i18n;
2
  const { Toolbar, withAPIData, Dropdown, Dashicon } = wp.components;
3
 
 
 
 
 
 
 
4
  /**
5
  * Get the identifier for an attribute. The identifier can be used to determine
6
  * the slug or the ID of the attribute.
175
  const filter = filterQuery.toLowerCase();
176
  let attributeElements = [];
177
  for ( let attribute of attributes.data ) {
 
178
  // Filter out attributes that don't match the search query.
179
  if ( filter.length && -1 === attribute.name.toLowerCase().indexOf( filter ) ) {
180
  continue;
181
  }
182
 
183
+ attributeElements.push(
184
+ <ProductAttributeElement
185
+ attribute={ attribute }
186
+ selectedAttribute={ selectedAttribute }
187
+ selectedTerms={ selectedTerms }
188
+ setSelectedAttribute={ setSelectedAttribute}
189
  addTerm={ addTerm }
190
+ removeTerm={ removeTerm }
191
+ />
192
+ );
 
 
 
 
 
 
 
 
 
193
  }
194
 
195
  return (
201
  );
202
 
203
  /**
204
+ * One product attribute.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  */
206
  class ProductAttributeElement extends React.Component {
207
 
 
 
 
208
  constructor( props ) {
209
  super( props );
210
 
238
  }
239
  }
240
 
 
 
 
241
  render() {
 
242
  const isSelected = this.props.selectedAttribute === getAttributeIdentifier( this.props.attribute.slug, this.props.attribute.id );
243
 
244
  let attributeTerms = null;
245
  if ( isSelected ) {
246
+ attributeTerms = <AttributeTerms
247
+ attribute={ this.props.attribute }
248
+ selectedTerms={ this.props.selectedTerms }
249
+ addTerm={ this.props.addTerm }
250
+ removeTerm={ this.props.removeTerm }
251
+ />
 
 
 
 
 
 
 
 
 
 
 
252
  }
253
 
254
  let cssClasses = [ 'wc-products-list-card--taxonomy-atributes__atribute' ];
 
255
  if ( isSelected ) {
256
  cssClasses.push( 'wc-products-list-card__accordion-open' );
257
  }
266
  checked={ isSelected }
267
  />
268
  { this.props.attribute.name }
 
269
  </label>
270
  </div>
271
  { attributeTerms }
273
  );
274
  }
275
  }
276
+
277
+ /**
278
+ * The list of terms in an attribute.
279
+ */
280
+ const AttributeTerms = withAPIData( ( props ) => {
281
+ return {
282
+ terms: '/wc/v2/products/attributes/' + props.attribute.id + '/terms'
283
+ };
284
+ } )( ( { terms, selectedTerms, attribute, addTerm, removeTerm } ) => {
285
+ if ( ! terms.data ) {
286
+ return ( <ul><li>{ __( 'Loading' ) }</li></ul> );
287
+ }
288
+
289
+ if ( 0 === terms.data.length ) {
290
+ return ( <ul><li>{ __( 'No terms found' ) }</li></ul> );
291
+ }
292
+
293
+ /**
294
+ * Add or remove selected terms.
295
+ *
296
+ * @param evt Event object
297
+ */
298
+ function handleTermChange( evt ) {
299
+ if ( evt.target.checked ) {
300
+ addTerm( evt.target.value );
301
+ } else {
302
+ removeTerm( evt.target.value );
303
+ }
304
+ }
305
+
306
+ return (
307
+ <ul>
308
+ { terms.data.map( ( term ) => (
309
+ <li className="wc-products-list-card__item">
310
+ <label className="wc-products-list-card__content">
311
+ <input type="checkbox"
312
+ value={ term.id }
313
+ onChange={ handleTermChange }
314
+ checked={ selectedTerms.includes( String( term.id ) ) }
315
+ />
316
+ { term.name }
317
+ <span className="wc-products-list-card__taxonomy-count">{ term.count }</span>
318
+ </label>
319
+ </li>
320
+ ) ) }
321
+ </ul>
322
+ );
323
+ }
324
+ );
assets/js/views/specific-select.jsx CHANGED
@@ -337,7 +337,7 @@ const ProductSpecificSelectedProducts = withAPIData( ( props ) => {
337
  const productData = PRODUCT_DATA[ productId ];
338
 
339
  productElements.push(
340
- <li className="wc-products-list-card__item">
341
  <div className="wc-products-list-card__content">
342
  <img src={ productData.images[0].src } />
343
  <span className="wc-products-list-card__content-item-name">{ productData.name }</span>
337
  const productData = PRODUCT_DATA[ productId ];
338
 
339
  productElements.push(
340
+ <li className="wc-products-list-card__item" key={ productData.id + '-specific-select-edit' } >
341
  <div className="wc-products-list-card__content">
342
  <img src={ productData.images[0].src } />
343
  <span className="wc-products-list-card__content-item-name">{ productData.name }</span>
includes/class-wgpb-products-controller.php ADDED
@@ -0,0 +1,784 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * REST API Products controller with extra functionality not yet available in WC core.
4
+ *
5
+ * Handles requests to the /products endpoint.
6
+ * @todo Remove this once the orderby features are available in WC core.
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * REST API Products controller class.
15
+ *
16
+ * @package WooCommerce/API
17
+ */
18
+ class WGPB_Products_Controller extends WC_REST_Products_Controller {
19
+
20
+ /**
21
+ * Endpoint namespace.
22
+ *
23
+ * @var string
24
+ */
25
+ protected $namespace = 'wgbp/v3';
26
+
27
+ /**
28
+ * Get the images for a product or product variation.
29
+ *
30
+ * @param WC_Product|WC_Product_Variation $product Product instance.
31
+ * @return array
32
+ */
33
+ protected function get_images( $product ) {
34
+ $images = array();
35
+ $attachment_ids = array();
36
+
37
+ // Add featured image.
38
+ if ( has_post_thumbnail( $product->get_id() ) ) {
39
+ $attachment_ids[] = $product->get_image_id();
40
+ }
41
+
42
+ // Add gallery images.
43
+ $attachment_ids = array_merge( $attachment_ids, $product->get_gallery_image_ids() );
44
+
45
+ // Build image data.
46
+ foreach ( $attachment_ids as $attachment_id ) {
47
+ $attachment_post = get_post( $attachment_id );
48
+ if ( is_null( $attachment_post ) ) {
49
+ continue;
50
+ }
51
+
52
+ $attachment = wp_get_attachment_image_src( $attachment_id, 'full' );
53
+ if ( ! is_array( $attachment ) ) {
54
+ continue;
55
+ }
56
+
57
+ $images[] = array(
58
+ 'id' => (int) $attachment_id,
59
+ 'date_created' => wc_rest_prepare_date_response( $attachment_post->post_date, false ),
60
+ 'date_created_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_date_gmt ) ),
61
+ 'date_modified' => wc_rest_prepare_date_response( $attachment_post->post_modified, false ),
62
+ 'date_modified_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_modified_gmt ) ),
63
+ 'src' => current( $attachment ),
64
+ 'name' => get_the_title( $attachment_id ),
65
+ 'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
66
+ );
67
+ }
68
+
69
+ return $images;
70
+ }
71
+
72
+ /**
73
+ * Make extra product orderby features supported by WooCommerce available to the WC API.
74
+ * This includes 'price', 'popularity', and 'rating'.
75
+ *
76
+ * @param WP_REST_Request $request Request data.
77
+ * @return array
78
+ */
79
+ protected function prepare_objects_query( $request ) {
80
+ $args = parent::prepare_objects_query( $request );
81
+
82
+ $orderby = $request->get_param( 'orderby' );
83
+ $order = $request->get_param( 'order' );
84
+
85
+ $ordering_args = WC()->query->get_catalog_ordering_args( $orderby, $order );
86
+ $args['orderby'] = $ordering_args['orderby'];
87
+ $args['order'] = $ordering_args['order'];
88
+ if ( $ordering_args['meta_key'] ) {
89
+ $args['meta_key'] = $ordering_args['meta_key'];
90
+ }
91
+
92
+ return $args;
93
+ }
94
+
95
+ /**
96
+ * Set product images.
97
+ *
98
+ * @throws WC_REST_Exception REST API exceptions.
99
+ * @param WC_Product $product Product instance.
100
+ * @param array $images Images data.
101
+ * @return WC_Product
102
+ */
103
+ protected function set_product_images( $product, $images ) {
104
+ if ( is_array( $images ) ) {
105
+ $gallery = array();
106
+
107
+ foreach ( $images as $index => $image ) {
108
+ $attachment_id = isset( $image['id'] ) ? absint( $image['id'] ) : 0;
109
+
110
+ if ( 0 === $attachment_id && isset( $image['src'] ) ) {
111
+ $upload = wc_rest_upload_image_from_url( esc_url_raw( $image['src'] ) );
112
+
113
+ if ( is_wp_error( $upload ) ) {
114
+ if ( ! apply_filters( 'woocommerce_rest_suppress_image_upload_error', false, $upload, $product->get_id(), $images ) ) {
115
+ throw new WC_REST_Exception( 'woocommerce_product_image_upload_error', $upload->get_error_message(), 400 );
116
+ } else {
117
+ continue;
118
+ }
119
+ }
120
+
121
+ $attachment_id = wc_rest_set_uploaded_image_as_attachment( $upload, $product->get_id() );
122
+ }
123
+
124
+ if ( ! wp_attachment_is_image( $attachment_id ) ) {
125
+ throw new WC_REST_Exception( 'woocommerce_product_invalid_image_id', sprintf( __( '#%s is an invalid image ID.', 'woocommerce' ), $attachment_id ), 400 );
126
+ }
127
+
128
+ $featured_image = $product->get_image_id();
129
+
130
+ if ( 0 === $index ) {
131
+ $product->set_image_id( $attachment_id );
132
+ } else {
133
+ $gallery[] = $attachment_id;
134
+ }
135
+
136
+ // Set the image alt if present.
137
+ if ( ! empty( $image['alt'] ) ) {
138
+ update_post_meta( $attachment_id, '_wp_attachment_image_alt', wc_clean( $image['alt'] ) );
139
+ }
140
+
141
+ // Set the image name if present.
142
+ if ( ! empty( $image['name'] ) ) {
143
+ wp_update_post( array( 'ID' => $attachment_id, 'post_title' => $image['name'] ) );
144
+ }
145
+ }
146
+
147
+ $product->set_gallery_image_ids( $gallery );
148
+ } else {
149
+ $product->set_image_id( '' );
150
+ $product->set_gallery_image_ids( array() );
151
+ }
152
+
153
+ return $product;
154
+ }
155
+
156
+ /**
157
+ * Add new options for 'orderby' to the collection params.
158
+ *
159
+ * @return array
160
+ */
161
+ public function get_collection_params() {
162
+ $params = parent::get_collection_params();
163
+ $params['orderby']['enum'] = array_merge( $params['orderby']['enum'], array( 'price', 'popularity', 'rating' ) );
164
+ return $params;
165
+ }
166
+
167
+ /**
168
+ * Get the Product's schema, conforming to JSON Schema.
169
+ *
170
+ * @return array
171
+ */
172
+ public function get_item_schema() {
173
+ $weight_unit = get_option( 'woocommerce_weight_unit' );
174
+ $dimension_unit = get_option( 'woocommerce_dimension_unit' );
175
+ $schema = array(
176
+ '$schema' => 'http://json-schema.org/draft-04/schema#',
177
+ 'title' => $this->post_type,
178
+ 'type' => 'object',
179
+ 'properties' => array(
180
+ 'id' => array(
181
+ 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
182
+ 'type' => 'integer',
183
+ 'context' => array( 'view', 'edit' ),
184
+ 'readonly' => true,
185
+ ),
186
+ 'name' => array(
187
+ 'description' => __( 'Product name.', 'woocommerce' ),
188
+ 'type' => 'string',
189
+ 'context' => array( 'view', 'edit' ),
190
+ ),
191
+ 'slug' => array(
192
+ 'description' => __( 'Product slug.', 'woocommerce' ),
193
+ 'type' => 'string',
194
+ 'context' => array( 'view', 'edit' ),
195
+ ),
196
+ 'permalink' => array(
197
+ 'description' => __( 'Product URL.', 'woocommerce' ),
198
+ 'type' => 'string',
199
+ 'format' => 'uri',
200
+ 'context' => array( 'view', 'edit' ),
201
+ 'readonly' => true,
202
+ ),
203
+ 'date_created' => array(
204
+ 'description' => __( "The date the product was created, in the site's timezone.", 'woocommerce' ),
205
+ 'type' => 'date-time',
206
+ 'context' => array( 'view', 'edit' ),
207
+ 'readonly' => true,
208
+ ),
209
+ 'date_created_gmt' => array(
210
+ 'description' => __( "The date the product was created, as GMT.", 'woocommerce' ),
211
+ 'type' => 'date-time',
212
+ 'context' => array( 'view', 'edit' ),
213
+ 'readonly' => true,
214
+ ),
215
+ 'date_modified' => array(
216
+ 'description' => __( "The date the product was last modified, in the site's timezone.", 'woocommerce' ),
217
+ 'type' => 'date-time',
218
+ 'context' => array( 'view', 'edit' ),
219
+ 'readonly' => true,
220
+ ),
221
+ 'date_modified_gmt' => array(
222
+ 'description' => __( "The date the product was last modified, as GMT.", 'woocommerce' ),
223
+ 'type' => 'date-time',
224
+ 'context' => array( 'view', 'edit' ),
225
+ 'readonly' => true,
226
+ ),
227
+ 'type' => array(
228
+ 'description' => __( 'Product type.', 'woocommerce' ),
229
+ 'type' => 'string',
230
+ 'default' => 'simple',
231
+ 'enum' => array_keys( wc_get_product_types() ),
232
+ 'context' => array( 'view', 'edit' ),
233
+ ),
234
+ 'status' => array(
235
+ 'description' => __( 'Product status (post status).', 'woocommerce' ),
236
+ 'type' => 'string',
237
+ 'default' => 'publish',
238
+ 'enum' => array_keys( get_post_statuses() ),
239
+ 'context' => array( 'view', 'edit' ),
240
+ ),
241
+ 'featured' => array(
242
+ 'description' => __( 'Featured product.', 'woocommerce' ),
243
+ 'type' => 'boolean',
244
+ 'default' => false,
245
+ 'context' => array( 'view', 'edit' ),
246
+ ),
247
+ 'catalog_visibility' => array(
248
+ 'description' => __( 'Catalog visibility.', 'woocommerce' ),
249
+ 'type' => 'string',
250
+ 'default' => 'visible',
251
+ 'enum' => array( 'visible', 'catalog', 'search', 'hidden' ),
252
+ 'context' => array( 'view', 'edit' ),
253
+ ),
254
+ 'description' => array(
255
+ 'description' => __( 'Product description.', 'woocommerce' ),
256
+ 'type' => 'string',
257
+ 'context' => array( 'view', 'edit' ),
258
+ ),
259
+ 'short_description' => array(
260
+ 'description' => __( 'Product short description.', 'woocommerce' ),
261
+ 'type' => 'string',
262
+ 'context' => array( 'view', 'edit' ),
263
+ ),
264
+ 'sku' => array(
265
+ 'description' => __( 'Unique identifier.', 'woocommerce' ),
266
+ 'type' => 'string',
267
+ 'context' => array( 'view', 'edit' ),
268
+ ),
269
+ 'price' => array(
270
+ 'description' => __( 'Current product price.', 'woocommerce' ),
271
+ 'type' => 'string',
272
+ 'context' => array( 'view', 'edit' ),
273
+ 'readonly' => true,
274
+ ),
275
+ 'regular_price' => array(
276
+ 'description' => __( 'Product regular price.', 'woocommerce' ),
277
+ 'type' => 'string',
278
+ 'context' => array( 'view', 'edit' ),
279
+ ),
280
+ 'sale_price' => array(
281
+ 'description' => __( 'Product sale price.', 'woocommerce' ),
282
+ 'type' => 'string',
283
+ 'context' => array( 'view', 'edit' ),
284
+ ),
285
+ 'date_on_sale_from' => array(
286
+ 'description' => __( "Start date of sale price, in the site's timezone.", 'woocommerce' ),
287
+ 'type' => 'date-time',
288
+ 'context' => array( 'view', 'edit' ),
289
+ ),
290
+ 'date_on_sale_from_gmt' => array(
291
+ 'description' => __( 'Start date of sale price, as GMT.', 'woocommerce' ),
292
+ 'type' => 'date-time',
293
+ 'context' => array( 'view', 'edit' ),
294
+ ),
295
+ 'date_on_sale_to' => array(
296
+ 'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ),
297
+ 'type' => 'date-time',
298
+ 'context' => array( 'view', 'edit' ),
299
+ ),
300
+ 'date_on_sale_to_gmt' => array(
301
+ 'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ),
302
+ 'type' => 'date-time',
303
+ 'context' => array( 'view', 'edit' ),
304
+ ),
305
+ 'price_html' => array(
306
+ 'description' => __( 'Price formatted in HTML.', 'woocommerce' ),
307
+ 'type' => 'string',
308
+ 'context' => array( 'view', 'edit' ),
309
+ 'readonly' => true,
310
+ ),
311
+ 'on_sale' => array(
312
+ 'description' => __( 'Shows if the product is on sale.', 'woocommerce' ),
313
+ 'type' => 'boolean',
314
+ 'context' => array( 'view', 'edit' ),
315
+ 'readonly' => true,
316
+ ),
317
+ 'purchasable' => array(
318
+ 'description' => __( 'Shows if the product can be bought.', 'woocommerce' ),
319
+ 'type' => 'boolean',
320
+ 'context' => array( 'view', 'edit' ),
321
+ 'readonly' => true,
322
+ ),
323
+ 'total_sales' => array(
324
+ 'description' => __( 'Amount of sales.', 'woocommerce' ),
325
+ 'type' => 'integer',
326
+ 'context' => array( 'view', 'edit' ),
327
+ 'readonly' => true,
328
+ ),
329
+ 'virtual' => array(
330
+ 'description' => __( 'If the product is virtual.', 'woocommerce' ),
331
+ 'type' => 'boolean',
332
+ 'default' => false,
333
+ 'context' => array( 'view', 'edit' ),
334
+ ),
335
+ 'downloadable' => array(
336
+ 'description' => __( 'If the product is downloadable.', 'woocommerce' ),
337
+ 'type' => 'boolean',
338
+ 'default' => false,
339
+ 'context' => array( 'view', 'edit' ),
340
+ ),
341
+ 'downloads' => array(
342
+ 'description' => __( 'List of downloadable files.', 'woocommerce' ),
343
+ 'type' => 'array',
344
+ 'context' => array( 'view', 'edit' ),
345
+ 'items' => array(
346
+ 'type' => 'object',
347
+ 'properties' => array(
348
+ 'id' => array(
349
+ 'description' => __( 'File MD5 hash.', 'woocommerce' ),
350
+ 'type' => 'string',
351
+ 'context' => array( 'view', 'edit' ),
352
+ 'readonly' => true,
353
+ ),
354
+ 'name' => array(
355
+ 'description' => __( 'File name.', 'woocommerce' ),
356
+ 'type' => 'string',
357
+ 'context' => array( 'view', 'edit' ),
358
+ ),
359
+ 'file' => array(
360
+ 'description' => __( 'File URL.', 'woocommerce' ),
361
+ 'type' => 'string',
362
+ 'context' => array( 'view', 'edit' ),
363
+ ),
364
+ ),
365
+ ),
366
+ ),
367
+ 'download_limit' => array(
368
+ 'description' => __( 'Number of times downloadable files can be downloaded after purchase.', 'woocommerce' ),
369
+ 'type' => 'integer',
370
+ 'default' => -1,
371
+ 'context' => array( 'view', 'edit' ),
372
+ ),
373
+ 'download_expiry' => array(
374
+ 'description' => __( 'Number of days until access to downloadable files expires.', 'woocommerce' ),
375
+ 'type' => 'integer',
376
+ 'default' => -1,
377
+ 'context' => array( 'view', 'edit' ),
378
+ ),
379
+ 'external_url' => array(
380
+ 'description' => __( 'Product external URL. Only for external products.', 'woocommerce' ),
381
+ 'type' => 'string',
382
+ 'format' => 'uri',
383
+ 'context' => array( 'view', 'edit' ),
384
+ ),
385
+ 'button_text' => array(
386
+ 'description' => __( 'Product external button text. Only for external products.', 'woocommerce' ),
387
+ 'type' => 'string',
388
+ 'context' => array( 'view', 'edit' ),
389
+ ),
390
+ 'tax_status' => array(
391
+ 'description' => __( 'Tax status.', 'woocommerce' ),
392
+ 'type' => 'string',
393
+ 'default' => 'taxable',
394
+ 'enum' => array( 'taxable', 'shipping', 'none' ),
395
+ 'context' => array( 'view', 'edit' ),
396
+ ),
397
+ 'tax_class' => array(
398
+ 'description' => __( 'Tax class.', 'woocommerce' ),
399
+ 'type' => 'string',
400
+ 'context' => array( 'view', 'edit' ),
401
+ ),
402
+ 'manage_stock' => array(
403
+ 'description' => __( 'Stock management at product level.', 'woocommerce' ),
404
+ 'type' => 'boolean',
405
+ 'default' => false,
406
+ 'context' => array( 'view', 'edit' ),
407
+ ),
408
+ 'stock_quantity' => array(
409
+ 'description' => __( 'Stock quantity.', 'woocommerce' ),
410
+ 'type' => 'integer',
411
+ 'context' => array( 'view', 'edit' ),
412
+ ),
413
+ 'in_stock' => array(
414
+ 'description' => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
415
+ 'type' => 'boolean',
416
+ 'default' => true,
417
+ 'context' => array( 'view', 'edit' ),
418
+ ),
419
+ 'backorders' => array(
420
+ 'description' => __( 'If managing stock, this controls if backorders are allowed.', 'woocommerce' ),
421
+ 'type' => 'string',
422
+ 'default' => 'no',
423
+ 'enum' => array( 'no', 'notify', 'yes' ),
424
+ 'context' => array( 'view', 'edit' ),
425
+ ),
426
+ 'backorders_allowed' => array(
427
+ 'description' => __( 'Shows if backorders are allowed.', 'woocommerce' ),
428
+ 'type' => 'boolean',
429
+ 'context' => array( 'view', 'edit' ),
430
+ 'readonly' => true,
431
+ ),
432
+ 'backordered' => array(
433
+ 'description' => __( 'Shows if the product is on backordered.', 'woocommerce' ),
434
+ 'type' => 'boolean',
435
+ 'context' => array( 'view', 'edit' ),
436
+ 'readonly' => true,
437
+ ),
438
+ 'sold_individually' => array(
439
+ 'description' => __( 'Allow one item to be bought in a single order.', 'woocommerce' ),
440
+ 'type' => 'boolean',
441
+ 'default' => false,
442
+ 'context' => array( 'view', 'edit' ),
443
+ ),
444
+ 'weight' => array(
445
+ /* translators: %s: weight unit */
446
+ 'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), $weight_unit ),
447
+ 'type' => 'string',
448
+ 'context' => array( 'view', 'edit' ),
449
+ ),
450
+ 'dimensions' => array(
451
+ 'description' => __( 'Product dimensions.', 'woocommerce' ),
452
+ 'type' => 'object',
453
+ 'context' => array( 'view', 'edit' ),
454
+ 'properties' => array(
455
+ 'length' => array(
456
+ /* translators: %s: dimension unit */
457
+ 'description' => sprintf( __( 'Product length (%s).', 'woocommerce' ), $dimension_unit ),
458
+ 'type' => 'string',
459
+ 'context' => array( 'view', 'edit' ),
460
+ ),
461
+ 'width' => array(
462
+ /* translators: %s: dimension unit */
463
+ 'description' => sprintf( __( 'Product width (%s).', 'woocommerce' ), $dimension_unit ),
464
+ 'type' => 'string',
465
+ 'context' => array( 'view', 'edit' ),
466
+ ),
467
+ 'height' => array(
468
+ /* translators: %s: dimension unit */
469
+ 'description' => sprintf( __( 'Product height (%s).', 'woocommerce' ), $dimension_unit ),
470
+ 'type' => 'string',
471
+ 'context' => array( 'view', 'edit' ),
472
+ ),
473
+ ),
474
+ ),
475
+ 'shipping_required' => array(
476
+ 'description' => __( 'Shows if the product need to be shipped.', 'woocommerce' ),
477
+ 'type' => 'boolean',
478
+ 'context' => array( 'view', 'edit' ),
479
+ 'readonly' => true,
480
+ ),
481
+ 'shipping_taxable' => array(
482
+ 'description' => __( 'Shows whether or not the product shipping is taxable.', 'woocommerce' ),
483
+ 'type' => 'boolean',
484
+ 'context' => array( 'view', 'edit' ),
485
+ 'readonly' => true,
486
+ ),
487
+ 'shipping_class' => array(
488
+ 'description' => __( 'Shipping class slug.', 'woocommerce' ),
489
+ 'type' => 'string',
490
+ 'context' => array( 'view', 'edit' ),
491
+ ),
492
+ 'shipping_class_id' => array(
493
+ 'description' => __( 'Shipping class ID.', 'woocommerce' ),
494
+ 'type' => 'string',
495
+ 'context' => array( 'view', 'edit' ),
496
+ 'readonly' => true,
497
+ ),
498
+ 'reviews_allowed' => array(
499
+ 'description' => __( 'Allow reviews.', 'woocommerce' ),
500
+ 'type' => 'boolean',
501
+ 'default' => true,
502
+ 'context' => array( 'view', 'edit' ),
503
+ ),
504
+ 'average_rating' => array(
505
+ 'description' => __( 'Reviews average rating.', 'woocommerce' ),
506
+ 'type' => 'string',
507
+ 'context' => array( 'view', 'edit' ),
508
+ 'readonly' => true,
509
+ ),
510
+ 'rating_count' => array(
511
+ 'description' => __( 'Amount of reviews that the product have.', 'woocommerce' ),
512
+ 'type' => 'integer',
513
+ 'context' => array( 'view', 'edit' ),
514
+ 'readonly' => true,
515
+ ),
516
+ 'related_ids' => array(
517
+ 'description' => __( 'List of related products IDs.', 'woocommerce' ),
518
+ 'type' => 'array',
519
+ 'items' => array(
520
+ 'type' => 'integer',
521
+ ),
522
+ 'context' => array( 'view', 'edit' ),
523
+ 'readonly' => true,
524
+ ),
525
+ 'upsell_ids' => array(
526
+ 'description' => __( 'List of up-sell products IDs.', 'woocommerce' ),
527
+ 'type' => 'array',
528
+ 'items' => array(
529
+ 'type' => 'integer',
530
+ ),
531
+ 'context' => array( 'view', 'edit' ),
532
+ ),
533
+ 'cross_sell_ids' => array(
534
+ 'description' => __( 'List of cross-sell products IDs.', 'woocommerce' ),
535
+ 'type' => 'array',
536
+ 'items' => array(
537
+ 'type' => 'integer',
538
+ ),
539
+ 'context' => array( 'view', 'edit' ),
540
+ ),
541
+ 'parent_id' => array(
542
+ 'description' => __( 'Product parent ID.', 'woocommerce' ),
543
+ 'type' => 'integer',
544
+ 'context' => array( 'view', 'edit' ),
545
+ ),
546
+ 'purchase_note' => array(
547
+ 'description' => __( 'Optional note to send the customer after purchase.', 'woocommerce' ),
548
+ 'type' => 'string',
549
+ 'context' => array( 'view', 'edit' ),
550
+ ),
551
+ 'categories' => array(
552
+ 'description' => __( 'List of categories.', 'woocommerce' ),
553
+ 'type' => 'array',
554
+ 'context' => array( 'view', 'edit' ),
555
+ 'items' => array(
556
+ 'type' => 'object',
557
+ 'properties' => array(
558
+ 'id' => array(
559
+ 'description' => __( 'Category ID.', 'woocommerce' ),
560
+ 'type' => 'integer',
561
+ 'context' => array( 'view', 'edit' ),
562
+ ),
563
+ 'name' => array(
564
+ 'description' => __( 'Category name.', 'woocommerce' ),
565
+ 'type' => 'string',
566
+ 'context' => array( 'view', 'edit' ),
567
+ 'readonly' => true,
568
+ ),
569
+ 'slug' => array(
570
+ 'description' => __( 'Category slug.', 'woocommerce' ),
571
+ 'type' => 'string',
572
+ 'context' => array( 'view', 'edit' ),
573
+ 'readonly' => true,
574
+ ),
575
+ ),
576
+ ),
577
+ ),
578
+ 'tags' => array(
579
+ 'description' => __( 'List of tags.', 'woocommerce' ),
580
+ 'type' => 'array',
581
+ 'context' => array( 'view', 'edit' ),
582
+ 'items' => array(
583
+ 'type' => 'object',
584
+ 'properties' => array(
585
+ 'id' => array(
586
+ 'description' => __( 'Tag ID.', 'woocommerce' ),
587
+ 'type' => 'integer',
588
+ 'context' => array( 'view', 'edit' ),
589
+ ),
590
+ 'name' => array(
591
+ 'description' => __( 'Tag name.', 'woocommerce' ),
592
+ 'type' => 'string',
593
+ 'context' => array( 'view', 'edit' ),
594
+ 'readonly' => true,
595
+ ),
596
+ 'slug' => array(
597
+ 'description' => __( 'Tag slug.', 'woocommerce' ),
598
+ 'type' => 'string',
599
+ 'context' => array( 'view', 'edit' ),
600
+ 'readonly' => true,
601
+ ),
602
+ ),
603
+ ),
604
+ ),
605
+ 'images' => array(
606
+ 'description' => __( 'List of images.', 'woocommerce' ),
607
+ 'type' => 'object',
608
+ 'context' => array( 'view', 'edit' ),
609
+ 'items' => array(
610
+ 'type' => 'object',
611
+ 'properties' => array(
612
+ 'id' => array(
613
+ 'description' => __( 'Image ID.', 'woocommerce' ),
614
+ 'type' => 'integer',
615
+ 'context' => array( 'view', 'edit' ),
616
+ ),
617
+ 'date_created' => array(
618
+ 'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ),
619
+ 'type' => 'date-time',
620
+ 'context' => array( 'view', 'edit' ),
621
+ 'readonly' => true,
622
+ ),
623
+ 'date_created_gmt' => array(
624
+ 'description' => __( "The date the image was created, as GMT.", 'woocommerce' ),
625
+ 'type' => 'date-time',
626
+ 'context' => array( 'view', 'edit' ),
627
+ 'readonly' => true,
628
+ ),
629
+ 'date_modified' => array(
630
+ 'description' => __( "The date the image was last modified, in the site's timezone.", 'woocommerce' ),
631
+ 'type' => 'date-time',
632
+ 'context' => array( 'view', 'edit' ),
633
+ 'readonly' => true,
634
+ ),
635
+ 'date_modified_gmt' => array(
636
+ 'description' => __( "The date the image was last modified, as GMT.", 'woocommerce' ),
637
+ 'type' => 'date-time',
638
+ 'context' => array( 'view', 'edit' ),
639
+ 'readonly' => true,
640
+ ),
641
+ 'src' => array(
642
+ 'description' => __( 'Image URL.', 'woocommerce' ),
643
+ 'type' => 'string',
644
+ 'format' => 'uri',
645
+ 'context' => array( 'view', 'edit' ),
646
+ ),
647
+ 'name' => array(
648
+ 'description' => __( 'Image name.', 'woocommerce' ),
649
+ 'type' => 'string',
650
+ 'context' => array( 'view', 'edit' ),
651
+ ),
652
+ 'alt' => array(
653
+ 'description' => __( 'Image alternative text.', 'woocommerce' ),
654
+ 'type' => 'string',
655
+ 'context' => array( 'view', 'edit' ),
656
+ ),
657
+ ),
658
+ ),
659
+ ),
660
+ 'attributes' => array(
661
+ 'description' => __( 'List of attributes.', 'woocommerce' ),
662
+ 'type' => 'array',
663
+ 'context' => array( 'view', 'edit' ),
664
+ 'items' => array(
665
+ 'type' => 'object',
666
+ 'properties' => array(
667
+ 'id' => array(
668
+ 'description' => __( 'Attribute ID.', 'woocommerce' ),
669
+ 'type' => 'integer',
670
+ 'context' => array( 'view', 'edit' ),
671
+ ),
672
+ 'name' => array(
673
+ 'description' => __( 'Attribute name.', 'woocommerce' ),
674
+ 'type' => 'string',
675
+ 'context' => array( 'view', 'edit' ),
676
+ ),
677
+ 'position' => array(
678
+ 'description' => __( 'Attribute position.', 'woocommerce' ),
679
+ 'type' => 'integer',
680
+ 'context' => array( 'view', 'edit' ),
681
+ ),
682
+ 'visible' => array(
683
+ 'description' => __( "Define if the attribute is visible on the \"Additional information\" tab in the product's page.", 'woocommerce' ),
684
+ 'type' => 'boolean',
685
+ 'default' => false,
686
+ 'context' => array( 'view', 'edit' ),
687
+ ),
688
+ 'variation' => array(
689
+ 'description' => __( 'Define if the attribute can be used as variation.', 'woocommerce' ),
690
+ 'type' => 'boolean',
691
+ 'default' => false,
692
+ 'context' => array( 'view', 'edit' ),
693
+ ),
694
+ 'options' => array(
695
+ 'description' => __( 'List of available term names of the attribute.', 'woocommerce' ),
696
+ 'type' => 'array',
697
+ 'items' => array(
698
+ 'type' => 'string',
699
+ ),
700
+ 'context' => array( 'view', 'edit' ),
701
+ ),
702
+ ),
703
+ ),
704
+ ),
705
+ 'default_attributes' => array(
706
+ 'description' => __( 'Defaults variation attributes.', 'woocommerce' ),
707
+ 'type' => 'array',
708
+ 'context' => array( 'view', 'edit' ),
709
+ 'items' => array(
710
+ 'type' => 'object',
711
+ 'properties' => array(
712
+ 'id' => array(
713
+ 'description' => __( 'Attribute ID.', 'woocommerce' ),
714
+ 'type' => 'integer',
715
+ 'context' => array( 'view', 'edit' ),
716
+ ),
717
+ 'name' => array(
718
+ 'description' => __( 'Attribute name.', 'woocommerce' ),
719
+ 'type' => 'string',
720
+ 'context' => array( 'view', 'edit' ),
721
+ ),
722
+ 'option' => array(
723
+ 'description' => __( 'Selected attribute term name.', 'woocommerce' ),
724
+ 'type' => 'string',
725
+ 'context' => array( 'view', 'edit' ),
726
+ ),
727
+ ),
728
+ ),
729
+ ),
730
+ 'variations' => array(
731
+ 'description' => __( 'List of variations IDs.', 'woocommerce' ),
732
+ 'type' => 'array',
733
+ 'context' => array( 'view', 'edit' ),
734
+ 'items' => array(
735
+ 'type' => 'integer',
736
+ ),
737
+ 'readonly' => true,
738
+ ),
739
+ 'grouped_products' => array(
740
+ 'description' => __( 'List of grouped products ID.', 'woocommerce' ),
741
+ 'type' => 'array',
742
+ 'items' => array(
743
+ 'type' => 'integer',
744
+ ),
745
+ 'context' => array( 'view', 'edit' ),
746
+ 'readonly' => true,
747
+ ),
748
+ 'menu_order' => array(
749
+ 'description' => __( 'Menu order, used to custom sort products.', 'woocommerce' ),
750
+ 'type' => 'integer',
751
+ 'context' => array( 'view', 'edit' ),
752
+ ),
753
+ 'meta_data' => array(
754
+ 'description' => __( 'Meta data.', 'woocommerce' ),
755
+ 'type' => 'array',
756
+ 'context' => array( 'view', 'edit' ),
757
+ 'items' => array(
758
+ 'type' => 'object',
759
+ 'properties' => array(
760
+ 'id' => array(
761
+ 'description' => __( 'Meta ID.', 'woocommerce' ),
762
+ 'type' => 'integer',
763
+ 'context' => array( 'view', 'edit' ),
764
+ 'readonly' => true,
765
+ ),
766
+ 'key' => array(
767
+ 'description' => __( 'Meta key.', 'woocommerce' ),
768
+ 'type' => 'string',
769
+ 'context' => array( 'view', 'edit' ),
770
+ ),
771
+ 'value' => array(
772
+ 'description' => __( 'Meta value.', 'woocommerce' ),
773
+ 'type' => 'mixed',
774
+ 'context' => array( 'view', 'edit' ),
775
+ ),
776
+ ),
777
+ ),
778
+ ),
779
+ ),
780
+ );
781
+ return $this->add_additional_fields_schema( $schema );
782
+ }
783
+
784
+ }
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: gutenberg, woocommerce, woo commerce, products
4
  Requires at least: 4.7
5
  Tested up to: 4.9
6
  Requires PHP: 5.2
7
- Stable tag: 1.0.0
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -53,6 +53,14 @@ Yes you can! Join in on our [GitHub repository](https://github.com/woocommerce/w
53
 
54
  == Changelog ==
55
 
 
 
 
 
 
 
 
 
56
  = 1.0.0 - 2018-04-24 =
57
  * Initial implementation of the Gutenberg Products block.
58
 
4
  Requires at least: 4.7
5
  Tested up to: 4.9
6
  Requires PHP: 5.2
7
+ Stable tag: 1.1.0
8
  License: GPLv3
9
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
10
 
53
 
54
  == Changelog ==
55
 
56
+ = 1.1.0 - 2018-06-06 =
57
+ * Feature - Add "Best Selling" and "Top Rated" product scopes.
58
+ * Fix - Only enqueue scripts and styles in the site backend.
59
+ * Fix - Remove focus checks deprecated in latest Gutenberg version.
60
+ * Fix - Added keys to some elements to prevent React warnings.
61
+ * Enhancement - Added custom API endpoint for more accurate block previews with orderby.
62
+ * Performance - Refactored the way the attribute select works to prevent many concurrent API requests on sites with many attributes.
63
+
64
  = 1.0.0 - 2018-04-24 =
65
  * Initial implementation of the Gutenberg Products block.
66
 
woocommerce-gutenberg-products-block.php CHANGED
@@ -3,16 +3,18 @@
3
  * Plugin Name: WooCommerce Gutenberg Products Block
4
  * Plugin URI: https://github.com/woocommerce/woocommerce-gutenberg-products-block
5
  * Description: WooCommerce Products block for the Gutenberg editor.
6
- * Version: 1.0.0
7
  * Author: Automattic
8
  * Author URI: https://woocommerce.com
9
  * Text Domain: woocommerce
10
  * Domain Path: /languages
 
 
11
  */
12
 
13
  defined( 'ABSPATH' ) || die();
14
 
15
- define( 'WGPB_VERSION', '1.0.0' );
16
 
17
  /**
18
  * Load up the assets if Gutenberg is active.
@@ -21,6 +23,7 @@ function wgpb_initialize() {
21
 
22
  if ( function_exists( 'register_block_type' ) ) {
23
  add_action( 'init', 'wgpb_register_products_block' );
 
24
  }
25
 
26
  }
@@ -30,6 +33,23 @@ add_action( 'woocommerce_loaded', 'wgpb_initialize' );
30
  * Register the Products block and its scripts.
31
  */
32
  function wgpb_register_products_block() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  wp_register_script(
34
  'woocommerce-products-block-editor',
35
  plugins_url( 'assets/js/products-block.js', __FILE__ ),
@@ -47,31 +67,27 @@ function wgpb_register_products_block() {
47
  );
48
  wp_localize_script( 'woocommerce-products-block-editor', 'wc_product_block_data', $product_block_data );
49
 
50
- wp_register_style(
 
 
51
  'woocommerce-products-block-editor',
52
  plugins_url( 'assets/css/gutenberg-products-block.css', __FILE__ ),
53
  array( 'wp-edit-blocks' ),
54
  WGPB_VERSION
55
  );
56
-
57
- register_block_type( 'woocommerce/products', array(
58
- 'editor_script' => 'woocommerce-products-block-editor',
59
- 'editor_style' => 'woocommerce-products-block-editor',
60
- ) );
61
  }
 
62
 
63
  /**
64
- * Register extra scripts needed.
 
 
65
  */
66
- function wgpb_extra_gutenberg_scripts() {
67
- wp_enqueue_script(
68
- 'react-transition-group',
69
- plugins_url( 'assets/js/vendor/react-transition-group.js', __FILE__ ),
70
- array( 'wp-blocks', 'wp-element' ),
71
- '2.2.1'
72
- );
73
  }
74
- add_action( 'enqueue_block_assets', 'wgpb_extra_gutenberg_scripts' );
75
 
76
  /**
77
  * Brings some extra required shortcode features from WC core 3.4+ to this feature plugin.
3
  * Plugin Name: WooCommerce Gutenberg Products Block
4
  * Plugin URI: https://github.com/woocommerce/woocommerce-gutenberg-products-block
5
  * Description: WooCommerce Products block for the Gutenberg editor.
6
+ * Version: 1.1.0
7
  * Author: Automattic
8
  * Author URI: https://woocommerce.com
9
  * Text Domain: woocommerce
10
  * Domain Path: /languages
11
+ * WC requires at least: 3.3
12
+ * WC tested up to: 3.4
13
  */
14
 
15
  defined( 'ABSPATH' ) || die();
16
 
17
+ define( 'WGPB_VERSION', '1.1.0' );
18
 
19
  /**
20
  * Load up the assets if Gutenberg is active.
23
 
24
  if ( function_exists( 'register_block_type' ) ) {
25
  add_action( 'init', 'wgpb_register_products_block' );
26
+ add_action( 'rest_api_init', 'wgpb_register_api_routes' );
27
  }
28
 
29
  }
33
  * Register the Products block and its scripts.
34
  */
35
  function wgpb_register_products_block() {
36
+ register_block_type( 'woocommerce/products', array(
37
+ 'editor_script' => 'woocommerce-products-block-editor',
38
+ 'editor_style' => 'woocommerce-products-block-editor',
39
+ ) );
40
+ }
41
+
42
+ /**
43
+ * Register extra scripts needed.
44
+ */
45
+ function wgpb_extra_gutenberg_scripts() {
46
+ wp_enqueue_script(
47
+ 'react-transition-group',
48
+ plugins_url( 'assets/js/vendor/react-transition-group.js', __FILE__ ),
49
+ array( 'wp-blocks', 'wp-element' ),
50
+ '2.2.1'
51
+ );
52
+
53
  wp_register_script(
54
  'woocommerce-products-block-editor',
55
  plugins_url( 'assets/js/products-block.js', __FILE__ ),
67
  );
68
  wp_localize_script( 'woocommerce-products-block-editor', 'wc_product_block_data', $product_block_data );
69
 
70
+ wp_enqueue_script( 'woocommerce-products-block-editor' );
71
+
72
+ wp_enqueue_style(
73
  'woocommerce-products-block-editor',
74
  plugins_url( 'assets/css/gutenberg-products-block.css', __FILE__ ),
75
  array( 'wp-edit-blocks' ),
76
  WGPB_VERSION
77
  );
 
 
 
 
 
78
  }
79
+ add_action( 'enqueue_block_editor_assets', 'wgpb_extra_gutenberg_scripts' );
80
 
81
  /**
82
+ * Register extra API routes with functionality not available in WC core yet.
83
+ *
84
+ * @todo Remove this function when merging into core because it won't be necessary.
85
  */
86
+ function wgpb_register_api_routes() {
87
+ include_once( dirname( __FILE__ ) . '/includes/class-wgpb-products-controller.php' );
88
+ $controller = new WGPB_Products_Controller();
89
+ $controller->register_routes();
 
 
 
90
  }
 
91
 
92
  /**
93
  * Brings some extra required shortcode features from WC core 3.4+ to this feature plugin.