workarea 3.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +326 -0
- data/CHANGELOG.md +20501 -0
- data/README.md +163 -0
- data/docker-compose.yml +27 -0
- data/docs/Gemfile +8 -0
- data/docs/bin/middleman +29 -0
- data/docs/config.rb +87 -0
- data/docs/config.ru +7 -0
- data/docs/data/articles.yml +157 -0
- data/docs/package.json +15 -0
- data/docs/source/404.html.erb +13 -0
- data/docs/source/articles/access-routes-in-javascript.html.md +33 -0
- data/docs/source/articles/add-a-content-area.html.md +169 -0
- data/docs/source/articles/add-a-content-block-type.html.md +334 -0
- data/docs/source/articles/add-a-report.html.md +202 -0
- data/docs/source/articles/add-css-through-the-admin-ui.html.md +30 -0
- data/docs/source/articles/add-javascript-through-a-manifest.html.md +367 -0
- data/docs/source/articles/add-javascript-through-a-view.html.md +80 -0
- data/docs/source/articles/add-javascript-through-the-admin-ui.html.md +30 -0
- data/docs/source/articles/add-metrics.html.md +58 -0
- data/docs/source/articles/add-or-replace-a-pricing-calculator.html.md +150 -0
- data/docs/source/articles/add-remove-or-change-a-mongoid-validation.html.md +147 -0
- data/docs/source/articles/add-remove-or-change-a-product-template.html.md +142 -0
- data/docs/source/articles/add-remove-sort-and-group-storefront-search-filters.html.md +483 -0
- data/docs/source/articles/add-stylesheets-through-a-manifest.html.md +276 -0
- data/docs/source/articles/add-system-content.html.md +138 -0
- data/docs/source/articles/analytics-overview.html.md +51 -0
- data/docs/source/articles/analyze-storefront-search-results.html.md +261 -0
- data/docs/source/articles/api-overview.html.md +35 -0
- data/docs/source/articles/appending.html.md +506 -0
- data/docs/source/articles/application-document.html.md +88 -0
- data/docs/source/articles/automated-javascript-testing.html.md +162 -0
- data/docs/source/articles/b2b-overview.html.md +64 -0
- data/docs/source/articles/browser-and-device-support.html.md +47 -0
- data/docs/source/articles/change-product-placeholder-image.html.md +39 -0
- data/docs/source/articles/change-storefront-search-results.html.md +283 -0
- data/docs/source/articles/change-the-storefront-product-pricing-ui.html.md +348 -0
- data/docs/source/articles/change-the-storefront-search-filters-ui.html.md +103 -0
- data/docs/source/articles/checkout.html.md +479 -0
- data/docs/source/articles/commerce-model.html.md +164 -0
- data/docs/source/articles/configuration-for-hosting.html.md +106 -0
- data/docs/source/articles/configuration.html.md +406 -0
- data/docs/source/articles/configure-a-payment-gateway.html.md +58 -0
- data/docs/source/articles/configure-asset-storage.html.md +29 -0
- data/docs/source/articles/configure-asset-types.html.md +18 -0
- data/docs/source/articles/configure-contact-form-subjects-list.html.md +24 -0
- data/docs/source/articles/configure-imageoptim.html.md +23 -0
- data/docs/source/articles/configure-locales.html.md +45 -0
- data/docs/source/articles/configure-logins-and-authentication.html.md +42 -0
- data/docs/source/articles/configure-low-inventory-threshold.html.md +26 -0
- data/docs/source/articles/configure-product-image-sizes-and-processing.html.md +28 -0
- data/docs/source/articles/content.html.md +554 -0
- data/docs/source/articles/contentable.html.md +41 -0
- data/docs/source/articles/contribute-code.html.md +69 -0
- data/docs/source/articles/contribute-documentation.html.md +60 -0
- data/docs/source/articles/create-a-custom-discount.html.md +234 -0
- data/docs/source/articles/create-a-new-app.html.md +131 -0
- data/docs/source/articles/create-a-plugin.html.md +19 -0
- data/docs/source/articles/create-a-style-guide.html.md +71 -0
- data/docs/source/articles/create-a-theme.html.md +134 -0
- data/docs/source/articles/css-architectural-overview.html.md +89 -0
- data/docs/source/articles/customize-a-helper.html.md +91 -0
- data/docs/source/articles/decoration.html.md +415 -0
- data/docs/source/articles/define-and-configure-inventory-policies.html.md +107 -0
- data/docs/source/articles/documentation-style-guide.html.md +48 -0
- data/docs/source/articles/documentation.html.md +54 -0
- data/docs/source/articles/domain-modeling.html.md +82 -0
- data/docs/source/articles/error-pages.html.md.erb +95 -0
- data/docs/source/articles/extension-overview.html.md +152 -0
- data/docs/source/articles/favicon-support.html.md +112 -0
- data/docs/source/articles/feature-spec-helper-stylesheet.html.md +25 -0
- data/docs/source/articles/featurejs-and-feature-spec-helper.html.md +20 -0
- data/docs/source/articles/help-and-support.html.md +34 -0
- data/docs/source/articles/html-fragment-caching.html.md +46 -0
- data/docs/source/articles/http-caching.html.md +43 -0
- data/docs/source/articles/i18n.html.md +35 -0
- data/docs/source/articles/images-flow.html.md +10 -0
- data/docs/source/articles/index-storefront-search-documents.html.md +104 -0
- data/docs/source/articles/infrastructure.html.md +46 -0
- data/docs/source/articles/installing.html.md +61 -0
- data/docs/source/articles/integrate-a-payment-gateway.html.md +124 -0
- data/docs/source/articles/integrate-a-web-analytics-provider.html.md +35 -0
- data/docs/source/articles/integrate-an-inventory-management-system.html.md +88 -0
- data/docs/source/articles/integrating-with-other-software.html.md +59 -0
- data/docs/source/articles/inventory.html.md +352 -0
- data/docs/source/articles/javascript-coding-standards.html.md +30 -0
- data/docs/source/articles/javascript-modules.html.md +174 -0
- data/docs/source/articles/javascript-overview.html.md +62 -0
- data/docs/source/articles/javascript-reference-documentation.html.md +51 -0
- data/docs/source/articles/javascript-templates.html.md +52 -0
- data/docs/source/articles/low-level-caching.html.md +25 -0
- data/docs/source/articles/maintain-a-plugin.html.md +12 -0
- data/docs/source/articles/maintenance-policy.html.md +79 -0
- data/docs/source/articles/navigable.html.md +51 -0
- data/docs/source/articles/navigating-the-code.html.md +149 -0
- data/docs/source/articles/navigation.html.md +386 -0
- data/docs/source/articles/order-life-cycle.html.md +546 -0
- data/docs/source/articles/order-pricing.html.md +389 -0
- data/docs/source/articles/orders-and-items.html.md +210 -0
- data/docs/source/articles/orders.html.md +66 -0
- data/docs/source/articles/overriding.html.md +155 -0
- data/docs/source/articles/overview.html.md +43 -0
- data/docs/source/articles/plugins-overview.html.md +12 -0
- data/docs/source/articles/prerequisites-and-dependencies.html.md +202 -0
- data/docs/source/articles/products.html.md.erb +1270 -0
- data/docs/source/articles/progressive-web-application-support.html.md +148 -0
- data/docs/source/articles/rails-asset-manifests.html.md +33 -0
- data/docs/source/articles/rails-asset-view-helpers.html.md +25 -0
- data/docs/source/articles/reading-data.html.md +10 -0
- data/docs/source/articles/releasable.html.md +37 -0
- data/docs/source/articles/report-a-bug.html.md +75 -0
- data/docs/source/articles/ruby-coding-standards.html.md +10 -0
- data/docs/source/articles/run-sidekiq-in-a-local-environment.html.md +40 -0
- data/docs/source/articles/searching.html.md +1005 -0
- data/docs/source/articles/security-policy.html.md +42 -0
- data/docs/source/articles/seeds.html.md +345 -0
- data/docs/source/articles/shipping.html.md +756 -0
- data/docs/source/articles/sort-and-exclude-product-options.html.md +47 -0
- data/docs/source/articles/storefront-search-features.html.md +568 -0
- data/docs/source/articles/storefront-searches.html.md +126 -0
- data/docs/source/articles/style-guides.html.md +21 -0
- data/docs/source/articles/stylesheet-coding-standards.html.md +24 -0
- data/docs/source/articles/stylesheets-overview.html.md +67 -0
- data/docs/source/articles/swappable-list-data-structure.html.md +81 -0
- data/docs/source/articles/system-emails.html.md +102 -0
- data/docs/source/articles/taggable.html.md +8 -0
- data/docs/source/articles/test-a-credit-card-transaction.html.md +16 -0
- data/docs/source/articles/test-if-a-plugin-is-installed.html.md +34 -0
- data/docs/source/articles/testing.html.md +914 -0
- data/docs/source/articles/themes-overview.html.md +155 -0
- data/docs/source/articles/translate-administrable-content.html.md +14 -0
- data/docs/source/articles/translate-javascript-content.html.md +16 -0
- data/docs/source/articles/translate-or-customize-message-content.html.md +29 -0
- data/docs/source/articles/translate-or-customize-static-content.html.md +30 -0
- data/docs/source/articles/use-an-existing-workarea-app.html.md +108 -0
- data/docs/source/articles/view-models.html.md +509 -0
- data/docs/source/articles/views.html.md +14 -0
- data/docs/source/articles/workers.html.md +613 -0
- data/docs/source/articles/writing-data.html.md +10 -0
- data/docs/source/cli.html.md +163 -0
- data/docs/source/favicon.ico +0 -0
- data/docs/source/images/3-variants-1-option.png +0 -0
- data/docs/source/images/3-variants-3-options.png +0 -0
- data/docs/source/images/3-years-primary-image.png +0 -0
- data/docs/source/images/404-storefront-error-page.png +0 -0
- data/docs/source/images/404-system-content-admin.png +0 -0
- data/docs/source/images/404.jpg +0 -0
- data/docs/source/images/5-years-primary-image.png +0 -0
- data/docs/source/images/activity-dashboard.png +0 -0
- data/docs/source/images/activity-for-object.png +0 -0
- data/docs/source/images/activity-ui.png +0 -0
- data/docs/source/images/adding-captioned-image-block-custom-icon.png +0 -0
- data/docs/source/images/adding-captioned-image-block-default-icon.png +0 -0
- data/docs/source/images/admin-alerts-ui.png +0 -0
- data/docs/source/images/admin-category-range-filters.png +0 -0
- data/docs/source/images/admin-for-3-column-hero.png +0 -0
- data/docs/source/images/admin-help-index.png +0 -0
- data/docs/source/images/admin-help-ui.png +0 -0
- data/docs/source/images/admin-javascript.png +0 -0
- data/docs/source/images/admin-notification-for-deactivated-discount.png +0 -0
- data/docs/source/images/admin-notifications-ui.png +0 -0
- data/docs/source/images/admin-product-show-page.png +0 -0
- data/docs/source/images/admin-products-index-page.png +0 -0
- data/docs/source/images/admin-range-filters.png +0 -0
- data/docs/source/images/admin-style-guides-navigation.png +0 -0
- data/docs/source/images/after-re-seeding.png +0 -0
- data/docs/source/images/after-seeding-localhost-3000.png +0 -0
- data/docs/source/images/after-seeding.png +0 -0
- data/docs/source/images/arrow.svg +1 -0
- data/docs/source/images/arrow_white.svg +1 -0
- data/docs/source/images/aws-resource-map.png +0 -0
- data/docs/source/images/backordered-until-output-on-inventory-sku-card.png +0 -0
- data/docs/source/images/before-seeding-localhost-3000.png +0 -0
- data/docs/source/images/before-seeding.png +0 -0
- data/docs/source/images/browsing-workarea-versions-on-the-web.png +0 -0
- data/docs/source/images/bulk-asset-upload-on-assets-index-page.png +0 -0
- data/docs/source/images/bulk-asset-upload-while-editing-content.png +0 -0
- data/docs/source/images/bundle-show-workarea-core.png +0 -0
- data/docs/source/images/bundle-show-workarea.png +0 -0
- data/docs/source/images/calendar-for-backordered-until-field.png +0 -0
- data/docs/source/images/captioned-image-block-in-storefront.png +0 -0
- data/docs/source/images/captioned-image-content-block-storefront-component-style-guide.png +0 -0
- data/docs/source/images/cart-system-content-in-admin.png +0 -0
- data/docs/source/images/cart-system-content-in-storefront.png +0 -0
- data/docs/source/images/checkout-addresses-guest.png +0 -0
- data/docs/source/images/checkout-addresses-user.png +0 -0
- data/docs/source/images/checkout-confirmation.png +0 -0
- data/docs/source/images/checkout-flow-0.png +0 -0
- data/docs/source/images/checkout-flow-1.png +0 -0
- data/docs/source/images/checkout-flow-2.png +0 -0
- data/docs/source/images/checkout-flow-3.png +0 -0
- data/docs/source/images/checkout-flow-4.png +0 -0
- data/docs/source/images/checkout-payment-guest.png +0 -0
- data/docs/source/images/checkout-payment-user.png +0 -0
- data/docs/source/images/checkout-shipping.png +0 -0
- data/docs/source/images/color-picker-component-admin-style-guide.png +0 -0
- data/docs/source/images/color-picker-component-on-content-editing-screen.png +0 -0
- data/docs/source/images/commerce-model-carts-orders.png +0 -0
- data/docs/source/images/commerce-model-order-pricing.png +0 -0
- data/docs/source/images/commerce-model.png +0 -0
- data/docs/source/images/configuring-an-index-pattern-in-kibana.png +0 -0
- data/docs/source/images/content-block-presets.png +0 -0
- data/docs/source/images/content-search-customization.png +0 -0
- data/docs/source/images/country-with-region-data-in-address-form.png +0 -0
- data/docs/source/images/country-without-region-data-in-address-form.png +0 -0
- data/docs/source/images/create-content-block-preset-ui.png +0 -0
- data/docs/source/images/credit-card-icons.png +0 -0
- data/docs/source/images/css-added-through-admin.png +0 -0
- data/docs/source/images/css-admin-ui.png +0 -0
- data/docs/source/images/current-configuration-shown-in-admin-settings.png +0 -0
- data/docs/source/images/customer-impersonation-in-admin.png +0 -0
- data/docs/source/images/customer-impersonation-in-store-front.png +0 -0
- data/docs/source/images/date-filter-same-day.png +0 -0
- data/docs/source/images/developer-toolbar-in-store-front.png +0 -0
- data/docs/source/images/discounts-sorted-by-most-redeemed.png +0 -0
- data/docs/source/images/edit-help-article.png +0 -0
- data/docs/source/images/editing-content-for-search-customization.png +0 -0
- data/docs/source/images/editing-dynamic-captioned-image-block.png +0 -0
- data/docs/source/images/editing-product-fields-in-the-admin.png +0 -0
- data/docs/source/images/editing-search-system-content.png +0 -0
- data/docs/source/images/editing-static-captioned-image-block-custom-icon.png +0 -0
- data/docs/source/images/editing-static-captioned-image-block-default-icon.png +0 -0
- data/docs/source/images/external.svg +1 -0
- data/docs/source/images/favicon_16.png +0 -0
- data/docs/source/images/favicon_180.png +0 -0
- data/docs/source/images/favicon_32.png +0 -0
- data/docs/source/images/filters-all.png +0 -0
- data/docs/source/images/filters-control.png +0 -0
- data/docs/source/images/filters-custom.png +0 -0
- data/docs/source/images/filters-groups.png +0 -0
- data/docs/source/images/filters-material.png +0 -0
- data/docs/source/images/filters-omitted.png +0 -0
- data/docs/source/images/filters-pinned.png +0 -0
- data/docs/source/images/filters-range.png +0 -0
- data/docs/source/images/filters-sorted.png +0 -0
- data/docs/source/images/filters-wrapping-to-second-line-in-admin.png +0 -0
- data/docs/source/images/generic-product-template-images-no-options-selected.png +0 -0
- data/docs/source/images/generic-product-template-images-options-selected.png +0 -0
- data/docs/source/images/generic-template.png +0 -0
- data/docs/source/images/hosting.svg +1 -0
- data/docs/source/images/image-group-content-block-in-storefront.png +0 -0
- data/docs/source/images/images.svg +1 -0
- data/docs/source/images/import-export-screenshot.png +0 -0
- data/docs/source/images/invalid-display.png +0 -0
- data/docs/source/images/itcss.png +0 -0
- data/docs/source/images/kibana-dev-tools-console.png +0 -0
- data/docs/source/images/layout-content-admin-with-2-areas.png +0 -0
- data/docs/source/images/layout-content-admin-with-3-areas.png +0 -0
- data/docs/source/images/link-to-search-system-content.png +0 -0
- data/docs/source/images/logo.svg +1 -0
- data/docs/source/images/menu.svg +2 -0
- data/docs/source/images/mongo-replica-set.svg +1 -0
- data/docs/source/images/multi-column-hero-blocks.png +0 -0
- data/docs/source/images/option-selects-product-template-images-options-selected.png +0 -0
- data/docs/source/images/option-selects-template.png +0 -0
- data/docs/source/images/option-thumbnails-template.png +0 -0
- data/docs/source/images/order-item-total-price-diagram.png +0 -0
- data/docs/source/images/order-pricing-cart-example.png +0 -0
- data/docs/source/images/order-pricing-example-adjustments.png +0 -0
- data/docs/source/images/order-pricing-example-totals.png +0 -0
- data/docs/source/images/order-pricing-placed-order-example.png +0 -0
- data/docs/source/images/order-shipping-total-diagram.png +0 -0
- data/docs/source/images/order-show-with-multiple-tenders.png +0 -0
- data/docs/source/images/order-subtotal-price-diagram.png +0 -0
- data/docs/source/images/order-tax-total-diagram.png +0 -0
- data/docs/source/images/order-total-price-diagram.png +0 -0
- data/docs/source/images/order-total-value-diagram.png +0 -0
- data/docs/source/images/orders-dashboard-links.png +0 -0
- data/docs/source/images/oval.svg +1 -0
- data/docs/source/images/payment-icon-storefront-style-guide.png +0 -0
- data/docs/source/images/people-dashboard-links.png +0 -0
- data/docs/source/images/price-adjustments-diagram.png +0 -0
- data/docs/source/images/price-display-no-options.png +0 -0
- data/docs/source/images/price-display-options-selected.png +0 -0
- data/docs/source/images/pricing-calculators-diagram.png +0 -0
- data/docs/source/images/product-list-content-block-admin.png +0 -0
- data/docs/source/images/product-list-content-block-in-store-front.png +0 -0
- data/docs/source/images/promo-products-excluded-autocomplete-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-featured-category-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-recommendations-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-search-category-results-after.png +0 -0
- data/docs/source/images/promo-products-excluded-search-results-after.png +0 -0
- data/docs/source/images/promo-products-included-autocomplete-results-before.png +0 -0
- data/docs/source/images/promo-products-included-featured-category-results-before.png +0 -0
- data/docs/source/images/promo-products-included-recommendations-results-before.png +0 -0
- data/docs/source/images/promo-products-included-search-category-results-before.png +0 -0
- data/docs/source/images/promo-products-included-search-results-before.png +0 -0
- data/docs/source/images/rails-version-constraint.png +0 -0
- data/docs/source/images/re-enable-discount.png +0 -0
- data/docs/source/images/reading-data.svg +1 -0
- data/docs/source/images/readme-hero.png +0 -0
- data/docs/source/images/redesigned-customized-sort-for-search-results.png +0 -0
- data/docs/source/images/reviews-summary-above-share-buttons.png +0 -0
- data/docs/source/images/reviews-summary-below-product-name.png +0 -0
- data/docs/source/images/reviews-summary-below-share-buttons.png +0 -0
- data/docs/source/images/reviews-summary-removed.png +0 -0
- data/docs/source/images/rsa-fingerprint-for-stash.png +0 -0
- data/docs/source/images/ruby-version-constraint.png +0 -0
- data/docs/source/images/script-tag-added-through-admin.png +0 -0
- data/docs/source/images/search-analysis-admin-alternate-rendering.png +0 -0
- data/docs/source/images/search-analysis-admin.png +0 -0
- data/docs/source/images/search-quality-report.png +0 -0
- data/docs/source/images/search.svg +1 -0
- data/docs/source/images/searching-for-cart-system-content-in-admin.png +0 -0
- data/docs/source/images/searching-for-layout-system-content-in-admin.png +0 -0
- data/docs/source/images/seeded-admin.png +0 -0
- data/docs/source/images/seeds-from-plugins.png +0 -0
- data/docs/source/images/seo-metadata-automation-ui.png +0 -0
- data/docs/source/images/show-password-button.png +0 -0
- data/docs/source/images/storefront-autocomplete.png +0 -0
- data/docs/source/images/storefront-category-summary-content-block.png +0 -0
- data/docs/source/images/storefront-category.png +0 -0
- data/docs/source/images/storefront-product-after-overriding.png +0 -0
- data/docs/source/images/storefront-product-before-overriding.png +0 -0
- data/docs/source/images/storefront-product-browse-page.png +0 -0
- data/docs/source/images/storefront-product-recommendations.png +0 -0
- data/docs/source/images/storefront-product-show-page.png +0 -0
- data/docs/source/images/storefront-requests-and-search-requests.png +0 -0
- data/docs/source/images/storefront-search-request-handling.png +0 -0
- data/docs/source/images/storefront-search-response-creation.png +0 -0
- data/docs/source/images/storefront-search.png +0 -0
- data/docs/source/images/storefront-style-guides-navigation.png +0 -0
- data/docs/source/images/styles.css +3 -0
- data/docs/source/images/tax-categories-ui.png +0 -0
- data/docs/source/images/tax-rates-ui.png +0 -0
- data/docs/source/images/unpurchasable-product.png +0 -0
- data/docs/source/images/url-redirects-filtering.png +0 -0
- data/docs/source/images/utility-nav-area-in-admin.png +0 -0
- data/docs/source/images/utility-nav-area-in-storefront.png +0 -0
- data/docs/source/images/validation-message-in-storefront.png +0 -0
- data/docs/source/images/view-model-interface.png +0 -0
- data/docs/source/images/viewing-workarea-version-in-source.png +0 -0
- data/docs/source/images/workarea.svg +1 -0
- data/docs/source/images/worst-performing-searches-on-results-customization-page.png +0 -0
- data/docs/source/images/writing-data.svg +1 -0
- data/docs/source/index.html.erb +167 -0
- data/docs/source/javascripts/jquery.js +2 -0
- data/docs/source/javascripts/lunr.js +7 -0
- data/docs/source/javascripts/site.js +299 -0
- data/docs/source/javascripts/vendor/highlight.pack.js +2 -0
- data/docs/source/layouts/article.erb +106 -0
- data/docs/source/layouts/bare.erb +46 -0
- data/docs/source/layouts/layout.erb +43 -0
- data/docs/source/release-notes.html.md +258 -0
- data/docs/source/release-notes/workarea-3-0-0.html.md +146 -0
- data/docs/source/release-notes/workarea-3-0-1.html.md +161 -0
- data/docs/source/release-notes/workarea-3-0-10.html.md +39 -0
- data/docs/source/release-notes/workarea-3-0-11.html.md +277 -0
- data/docs/source/release-notes/workarea-3-0-12.html.md +14 -0
- data/docs/source/release-notes/workarea-3-0-13.html.md +153 -0
- data/docs/source/release-notes/workarea-3-0-14.html.md +93 -0
- data/docs/source/release-notes/workarea-3-0-15.html.md +107 -0
- data/docs/source/release-notes/workarea-3-0-16.html.md +36 -0
- data/docs/source/release-notes/workarea-3-0-17.html.md +141 -0
- data/docs/source/release-notes/workarea-3-0-18.html.md +123 -0
- data/docs/source/release-notes/workarea-3-0-19.html.md +160 -0
- data/docs/source/release-notes/workarea-3-0-2.html.md +222 -0
- data/docs/source/release-notes/workarea-3-0-20.html.md +95 -0
- data/docs/source/release-notes/workarea-3-0-21.html.md +168 -0
- data/docs/source/release-notes/workarea-3-0-22.html.md +268 -0
- data/docs/source/release-notes/workarea-3-0-23.html.md +173 -0
- data/docs/source/release-notes/workarea-3-0-24.html.md +19 -0
- data/docs/source/release-notes/workarea-3-0-25.html.md +26 -0
- data/docs/source/release-notes/workarea-3-0-26.html.md +199 -0
- data/docs/source/release-notes/workarea-3-0-27.html.md +113 -0
- data/docs/source/release-notes/workarea-3-0-28.html.md +39 -0
- data/docs/source/release-notes/workarea-3-0-29.html.md +73 -0
- data/docs/source/release-notes/workarea-3-0-3.html.md +35 -0
- data/docs/source/release-notes/workarea-3-0-30.html.md +186 -0
- data/docs/source/release-notes/workarea-3-0-31.html.md +125 -0
- data/docs/source/release-notes/workarea-3-0-32.html.md +73 -0
- data/docs/source/release-notes/workarea-3-0-33.html.md +137 -0
- data/docs/source/release-notes/workarea-3-0-34.html.md +203 -0
- data/docs/source/release-notes/workarea-3-0-35.html.md +205 -0
- data/docs/source/release-notes/workarea-3-0-36.html.md +105 -0
- data/docs/source/release-notes/workarea-3-0-37.html.md +144 -0
- data/docs/source/release-notes/workarea-3-0-38.html.md +73 -0
- data/docs/source/release-notes/workarea-3-0-39.html.md +77 -0
- data/docs/source/release-notes/workarea-3-0-4.html.md +14 -0
- data/docs/source/release-notes/workarea-3-0-40.html.md +130 -0
- data/docs/source/release-notes/workarea-3-0-41.html.md +70 -0
- data/docs/source/release-notes/workarea-3-0-42.html.md +52 -0
- data/docs/source/release-notes/workarea-3-0-43.html.md +72 -0
- data/docs/source/release-notes/workarea-3-0-44.html.md +93 -0
- data/docs/source/release-notes/workarea-3-0-45.html.md +61 -0
- data/docs/source/release-notes/workarea-3-0-46.html.md +171 -0
- data/docs/source/release-notes/workarea-3-0-47.html.md +130 -0
- data/docs/source/release-notes/workarea-3-0-48.html.md +160 -0
- data/docs/source/release-notes/workarea-3-0-49.html.md +28 -0
- data/docs/source/release-notes/workarea-3-0-5.html.md +225 -0
- data/docs/source/release-notes/workarea-3-0-50.html.md +74 -0
- data/docs/source/release-notes/workarea-3-0-51.html.md +61 -0
- data/docs/source/release-notes/workarea-3-0-52.html.md +76 -0
- data/docs/source/release-notes/workarea-3-0-53.html.md +126 -0
- data/docs/source/release-notes/workarea-3-0-54.html.md +112 -0
- data/docs/source/release-notes/workarea-3-0-55.html.md +105 -0
- data/docs/source/release-notes/workarea-3-0-56.html.md +56 -0
- data/docs/source/release-notes/workarea-3-0-57.html.md +82 -0
- data/docs/source/release-notes/workarea-3-0-58.html.md +153 -0
- data/docs/source/release-notes/workarea-3-0-59.html.md +78 -0
- data/docs/source/release-notes/workarea-3-0-6.html.md +165 -0
- data/docs/source/release-notes/workarea-3-0-60.html.md +43 -0
- data/docs/source/release-notes/workarea-3-0-61.html.md +46 -0
- data/docs/source/release-notes/workarea-3-0-62.html.md +23 -0
- data/docs/source/release-notes/workarea-3-0-63.html.md +25 -0
- data/docs/source/release-notes/workarea-3-0-64.html.md +25 -0
- data/docs/source/release-notes/workarea-3-0-65.html.md +37 -0
- data/docs/source/release-notes/workarea-3-0-7.html.md +207 -0
- data/docs/source/release-notes/workarea-3-0-8.html.md +337 -0
- data/docs/source/release-notes/workarea-3-0-9.html.md +196 -0
- data/docs/source/release-notes/workarea-3-1-0.html.md +414 -0
- data/docs/source/release-notes/workarea-3-1-1.html.md +139 -0
- data/docs/source/release-notes/workarea-3-1-10.html.md +19 -0
- data/docs/source/release-notes/workarea-3-1-11.html.md +27 -0
- data/docs/source/release-notes/workarea-3-1-12.html.md +216 -0
- data/docs/source/release-notes/workarea-3-1-13.html.md +113 -0
- data/docs/source/release-notes/workarea-3-1-14.html.md +39 -0
- data/docs/source/release-notes/workarea-3-1-15.html.md +107 -0
- data/docs/source/release-notes/workarea-3-1-16.html.md +188 -0
- data/docs/source/release-notes/workarea-3-1-17.html.md +141 -0
- data/docs/source/release-notes/workarea-3-1-18.html.md +73 -0
- data/docs/source/release-notes/workarea-3-1-19.html.md +137 -0
- data/docs/source/release-notes/workarea-3-1-2.html.md +55 -0
- data/docs/source/release-notes/workarea-3-1-20.html.md +203 -0
- data/docs/source/release-notes/workarea-3-1-21.html.md +205 -0
- data/docs/source/release-notes/workarea-3-1-22.html.md +121 -0
- data/docs/source/release-notes/workarea-3-1-23.html.md +144 -0
- data/docs/source/release-notes/workarea-3-1-24.html.md +94 -0
- data/docs/source/release-notes/workarea-3-1-25.html.md +77 -0
- data/docs/source/release-notes/workarea-3-1-26.html.md +130 -0
- data/docs/source/release-notes/workarea-3-1-27.html.md +70 -0
- data/docs/source/release-notes/workarea-3-1-28.html.md +52 -0
- data/docs/source/release-notes/workarea-3-1-29.html.md +44 -0
- data/docs/source/release-notes/workarea-3-1-3.html.md +185 -0
- data/docs/source/release-notes/workarea-3-1-30.html.md +72 -0
- data/docs/source/release-notes/workarea-3-1-31.html.md +93 -0
- data/docs/source/release-notes/workarea-3-1-32.html.md +61 -0
- data/docs/source/release-notes/workarea-3-1-33.html.md +171 -0
- data/docs/source/release-notes/workarea-3-1-34.html.md +130 -0
- data/docs/source/release-notes/workarea-3-1-35.html.md +179 -0
- data/docs/source/release-notes/workarea-3-1-36.html.md +28 -0
- data/docs/source/release-notes/workarea-3-1-37.html.md +74 -0
- data/docs/source/release-notes/workarea-3-1-38.html.md +61 -0
- data/docs/source/release-notes/workarea-3-1-39.html.md +96 -0
- data/docs/source/release-notes/workarea-3-1-4.html.md +148 -0
- data/docs/source/release-notes/workarea-3-1-40.html.md +126 -0
- data/docs/source/release-notes/workarea-3-1-41.html.md +128 -0
- data/docs/source/release-notes/workarea-3-1-42.html.md +105 -0
- data/docs/source/release-notes/workarea-3-1-43.html.md +37 -0
- data/docs/source/release-notes/workarea-3-1-44.html.md +82 -0
- data/docs/source/release-notes/workarea-3-1-45.html.md +153 -0
- data/docs/source/release-notes/workarea-3-1-46.html.md +91 -0
- data/docs/source/release-notes/workarea-3-1-47.html.md +65 -0
- data/docs/source/release-notes/workarea-3-1-48.html.md +46 -0
- data/docs/source/release-notes/workarea-3-1-49.html.md +23 -0
- data/docs/source/release-notes/workarea-3-1-5.html.md +169 -0
- data/docs/source/release-notes/workarea-3-1-50.html.md +42 -0
- data/docs/source/release-notes/workarea-3-1-51.html.md +25 -0
- data/docs/source/release-notes/workarea-3-1-52.html.md +57 -0
- data/docs/source/release-notes/workarea-3-1-6.html.md +117 -0
- data/docs/source/release-notes/workarea-3-1-7.html.md +176 -0
- data/docs/source/release-notes/workarea-3-1-8.html.md +283 -0
- data/docs/source/release-notes/workarea-3-1-9.html.md +212 -0
- data/docs/source/release-notes/workarea-3-2-0.html.md +1705 -0
- data/docs/source/release-notes/workarea-3-2-1.html.md +216 -0
- data/docs/source/release-notes/workarea-3-2-10.html.md +237 -0
- data/docs/source/release-notes/workarea-3-2-11.html.md +121 -0
- data/docs/source/release-notes/workarea-3-2-12.html.md +145 -0
- data/docs/source/release-notes/workarea-3-2-13.html.md +138 -0
- data/docs/source/release-notes/workarea-3-2-14.html.md +77 -0
- data/docs/source/release-notes/workarea-3-2-15.html.md +130 -0
- data/docs/source/release-notes/workarea-3-2-16.html.md +111 -0
- data/docs/source/release-notes/workarea-3-2-17.html.md +52 -0
- data/docs/source/release-notes/workarea-3-2-18.html.md +44 -0
- data/docs/source/release-notes/workarea-3-2-19.html.md +72 -0
- data/docs/source/release-notes/workarea-3-2-2.html.md +145 -0
- data/docs/source/release-notes/workarea-3-2-20.html.md +93 -0
- data/docs/source/release-notes/workarea-3-2-21.html.md +61 -0
- data/docs/source/release-notes/workarea-3-2-22.html.md +154 -0
- data/docs/source/release-notes/workarea-3-2-23.html.md +130 -0
- data/docs/source/release-notes/workarea-3-2-24.html.md +200 -0
- data/docs/source/release-notes/workarea-3-2-25.html.md +28 -0
- data/docs/source/release-notes/workarea-3-2-26.html.md +94 -0
- data/docs/source/release-notes/workarea-3-2-27.html.md +61 -0
- data/docs/source/release-notes/workarea-3-2-28.html.md +96 -0
- data/docs/source/release-notes/workarea-3-2-29.html.md +126 -0
- data/docs/source/release-notes/workarea-3-2-30.html.md +112 -0
- data/docs/source/release-notes/workarea-3-2-31.html.md +105 -0
- data/docs/source/release-notes/workarea-3-2-32.html.md +56 -0
- data/docs/source/release-notes/workarea-3-2-33.html.md +82 -0
- data/docs/source/release-notes/workarea-3-2-34.html.md +153 -0
- data/docs/source/release-notes/workarea-3-2-35.html.md +91 -0
- data/docs/source/release-notes/workarea-3-2-36.html.md +118 -0
- data/docs/source/release-notes/workarea-3-2-37.html.md +46 -0
- data/docs/source/release-notes/workarea-3-2-38.html.md +23 -0
- data/docs/source/release-notes/workarea-3-2-39.html.md +42 -0
- data/docs/source/release-notes/workarea-3-2-4.html.md +109 -0
- data/docs/source/release-notes/workarea-3-2-40.html.md +25 -0
- data/docs/source/release-notes/workarea-3-2-41.html.md +90 -0
- data/docs/source/release-notes/workarea-3-2-5.html.md +186 -0
- data/docs/source/release-notes/workarea-3-2-6.html.md +173 -0
- data/docs/source/release-notes/workarea-3-2-7.html.md +89 -0
- data/docs/source/release-notes/workarea-3-2-8.html.md +137 -0
- data/docs/source/release-notes/workarea-3-2-9.html.md +219 -0
- data/docs/source/release-notes/workarea-3-3-0.html.md +1272 -0
- data/docs/source/release-notes/workarea-3-3-1.html.md +324 -0
- data/docs/source/release-notes/workarea-3-3-10.html.md +69 -0
- data/docs/source/release-notes/workarea-3-3-11.html.md +72 -0
- data/docs/source/release-notes/workarea-3-3-12.html.md +136 -0
- data/docs/source/release-notes/workarea-3-3-13.html.md +61 -0
- data/docs/source/release-notes/workarea-3-3-14.html.md +196 -0
- data/docs/source/release-notes/workarea-3-3-15.html.md +167 -0
- data/docs/source/release-notes/workarea-3-3-16.html.md +234 -0
- data/docs/source/release-notes/workarea-3-3-17.html.md +82 -0
- data/docs/source/release-notes/workarea-3-3-18.html.md +165 -0
- data/docs/source/release-notes/workarea-3-3-19.html.md +106 -0
- data/docs/source/release-notes/workarea-3-3-2.html.md +72 -0
- data/docs/source/release-notes/workarea-3-3-20.html.md +116 -0
- data/docs/source/release-notes/workarea-3-3-21.html.md +228 -0
- data/docs/source/release-notes/workarea-3-3-22.html.md +125 -0
- data/docs/source/release-notes/workarea-3-3-23.html.md +154 -0
- data/docs/source/release-notes/workarea-3-3-24.html.md +70 -0
- data/docs/source/release-notes/workarea-3-3-25.html.md +114 -0
- data/docs/source/release-notes/workarea-3-3-26.html.md +260 -0
- data/docs/source/release-notes/workarea-3-3-27.html.md +138 -0
- data/docs/source/release-notes/workarea-3-3-28.html.md +147 -0
- data/docs/source/release-notes/workarea-3-3-29.html.md +63 -0
- data/docs/source/release-notes/workarea-3-3-3.html.md +153 -0
- data/docs/source/release-notes/workarea-3-3-30.html.md +102 -0
- data/docs/source/release-notes/workarea-3-3-31.html.md +57 -0
- data/docs/source/release-notes/workarea-3-3-32.html.md +44 -0
- data/docs/source/release-notes/workarea-3-3-33.html.md +114 -0
- data/docs/source/release-notes/workarea-3-3-4.html.md +332 -0
- data/docs/source/release-notes/workarea-3-3-5.html.md +242 -0
- data/docs/source/release-notes/workarea-3-3-6.html.md +100 -0
- data/docs/source/release-notes/workarea-3-3-7.html.md +148 -0
- data/docs/source/release-notes/workarea-3-3-8.html.md +163 -0
- data/docs/source/release-notes/workarea-3-3-9.html.md +93 -0
- data/docs/source/release-notes/workarea-3-4-0.html.md +580 -0
- data/docs/source/release-notes/workarea-3-4-1.html.md +150 -0
- data/docs/source/release-notes/workarea-3-4-10.html.md +72 -0
- data/docs/source/release-notes/workarea-3-4-11.html.md +60 -0
- data/docs/source/release-notes/workarea-3-4-12.html.md +155 -0
- data/docs/source/release-notes/workarea-3-4-2.html.md +188 -0
- data/docs/source/release-notes/workarea-3-4-3.html.md +136 -0
- data/docs/source/release-notes/workarea-3-4-4.html.md +114 -0
- data/docs/source/release-notes/workarea-3-4-5.html.md +275 -0
- data/docs/source/release-notes/workarea-3-4-6.html.md +169 -0
- data/docs/source/release-notes/workarea-3-4-7.html.md +162 -0
- data/docs/source/release-notes/workarea-3-4-8.html.md +95 -0
- data/docs/source/release-notes/workarea-3-4-9.html.md +135 -0
- data/docs/source/search.html.erb +34 -0
- data/docs/source/shared/_header.erb +61 -0
- data/docs/source/shared/_svgs.erb +17 -0
- data/docs/source/style_guide/index.html.erb +382 -0
- data/docs/source/stylesheets/_base.scss +125 -0
- data/docs/source/stylesheets/_components.scss +669 -0
- data/docs/source/stylesheets/_helpers.scss +10 -0
- data/docs/source/stylesheets/_opinions.scss +42 -0
- data/docs/source/stylesheets/_settings.scss +56 -0
- data/docs/source/stylesheets/_typography.scss +119 -0
- data/docs/source/stylesheets/site.css.scss +14 -0
- data/docs/source/stylesheets/vendor/_avalanche.scss +328 -0
- data/docs/source/stylesheets/vendor/_normalize.scss +341 -0
- data/docs/source/stylesheets/vendor/highlight/_tomorrow_night_blue.scss +75 -0
- data/docs/source/upgrade-guides.html.md +18 -0
- data/docs/source/upgrade-guides/workarea-3-4-0.html.md +152 -0
- data/docs/workarea_renderer.rb +8 -0
- data/docs/yarn.lock +2522 -0
- metadata +669 -0
@@ -0,0 +1,348 @@
|
|
1
|
+
---
|
2
|
+
title: Change the Storefront Product Pricing UI
|
3
|
+
excerpt: An overview of how Workarea displays pricing for products and how to customize its UI.
|
4
|
+
---
|
5
|
+
|
6
|
+
# Change the Storefront Product Pricing UI
|
7
|
+
|
8
|
+
A common customization for projects is making updates to the way pricing is displayed for a given product. In this guide we will outline the basics of how a product's price is displayed within the browser and how to make adjustments to said presentation.
|
9
|
+
|
10
|
+
## Overview
|
11
|
+
|
12
|
+
In the Workarea platform you can imagine a product as a group of items for sale. Each item's price is determined via a `Pricing::Price` object embedded within the item's `Pricing:Sku`. Each `Pricing::Price` contains fields that set the "regular" and, optionally, "sale" price for that item. It are these objects that allow the displayed "sell" price for the product to be derived.
|
13
|
+
|
14
|
+
When browsing the catalog (categories, products, content blocks, etc), only generic prices are shown out-of-the-box. A generic price refers to the price being usable without additional information, such as quantity or segment influence. As soon as items are priced in an order, the most specific prices available will be applied.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
# core/app/models/workarea/pricing/price.rb
|
18
|
+
module Workarea
|
19
|
+
module Pricing
|
20
|
+
class Price
|
21
|
+
...
|
22
|
+
field :min_quantity, type: Integer, default: 1
|
23
|
+
field :regular, type: Money, default: 0
|
24
|
+
field :sale, type: Money
|
25
|
+
...
|
26
|
+
def generic?
|
27
|
+
min_quantity == 1
|
28
|
+
end
|
29
|
+
...
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# core/app/models/workarea/pricing/sku.rb
|
37
|
+
module Workarea
|
38
|
+
module Pricing
|
39
|
+
class Sku
|
40
|
+
...
|
41
|
+
embeds_many :prices, class_name: 'Workarea::Pricing::Price'
|
42
|
+
...
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
It should be noted that, in addition to "regular" and "sale" prices, `Pricing::Sku`s may also set an MSRP for the item, though it is not used in the actual pricing calculation.
|
49
|
+
|
50
|
+
## Presentation
|
51
|
+
|
52
|
+
A product's presentation is determined by the help of its view model. In this case we're concerned with the `ProudctViewModel#pricing` method:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
module Workarea
|
56
|
+
module Storefront
|
57
|
+
class ProductViewModel < ApplicationViewModel
|
58
|
+
...
|
59
|
+
delegate :sell_min_price, :sell_max_price, :on_sale?, :has_prices?, to: :pricing
|
60
|
+
|
61
|
+
def pricing
|
62
|
+
@pricing ||= options[:pricing] || Pricing::Collection.new(
|
63
|
+
options[:sku].presence || variants.map(&:sku)
|
64
|
+
)
|
65
|
+
end
|
66
|
+
...
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
This method returns a `Pricing::Collection` which represents every instance of `Pricing::Price` for the product. It should be noted, however, that if the user has selected a SKU as "current" only that current SKU's price will be returned by this method.
|
73
|
+
|
74
|
+
The `Pricing::Collection` returned by `ProductViewModel#pricing` derives the minimum and maximum regular, sale, sell, and MSRP from all "generic" prices found.
|
75
|
+
|
76
|
+
The product view model also adds a concept of an "original" price, which will either be:
|
77
|
+
|
78
|
+
* the MSRP or
|
79
|
+
* the "regular" price, if the MSRP is assumed to be greater
|
80
|
+
|
81
|
+
Lastly the product view model also has logic to determine if the same and original prices should be displayed, and whether the sell and original prices should be displayed as a specific price or as a price range.
|
82
|
+
|
83
|
+
## Styling
|
84
|
+
|
85
|
+
The styling for the Product Prices UI is provided by the `product-prices` SCSS component. Each element containing a price carries a class which may be styled as needed. Here is an overview of this Stylesheet:
|
86
|
+
|
87
|
+
```css
|
88
|
+
/* app/assets/stylesheets/workarea/storefront/components/_product_prices.scss */
|
89
|
+
.product-prices {}
|
90
|
+
|
91
|
+
.product-prices--summary {}
|
92
|
+
.product-prices--details {}
|
93
|
+
|
94
|
+
.product-prices__price {}
|
95
|
+
|
96
|
+
.product-prices__price--single {}
|
97
|
+
.product-prices__price--multiple {}
|
98
|
+
.product-prices__price--on-sale {}
|
99
|
+
.product-prices__price--original {}
|
100
|
+
|
101
|
+
.product-prices__sell-price {}
|
102
|
+
.product-prices__sell-price--min {}
|
103
|
+
.product-prices__sell-price--max {}
|
104
|
+
|
105
|
+
.product-prices__original-price {}
|
106
|
+
```
|
107
|
+
|
108
|
+
The `.product-prices` component is used in multiple sections of the application, each of which are accounted for within the associated component's style guide. When customizing the styles you are encouraged to develop against and maintain the style guide examples.
|
109
|
+
|
110
|
+
## Markup
|
111
|
+
|
112
|
+
The aforementioned class names are applied to the product pricing partial, which makes further use of the product price partial. The latter is supplied merely as an effort to DRY up the former, as the product pricing partial handles the many display conditions of the price. The logical permutations are as follows:
|
113
|
+
|
114
|
+
* if the product has only one price
|
115
|
+
* and if the product should show a range of prices
|
116
|
+
* or if the product should show a single price
|
117
|
+
* if the product has multiple prices
|
118
|
+
* and if the product is on sale
|
119
|
+
* and if the product should show a range of prices
|
120
|
+
* or if the product should show a single price
|
121
|
+
* or if the product is not on sale
|
122
|
+
* and if the product should show a range of prices
|
123
|
+
* or if the product should show a single price
|
124
|
+
|
125
|
+
The product pricing partial will always show the determined original price by default.
|
126
|
+
|
127
|
+
```haml
|
128
|
+
-# app/views/workarea/storefront/products/_pricing.html.haml
|
129
|
+
- cache "#{product.cache_key}/prices", expires_in: Workarea.config.cache_expirations.product_pricing_fragment_cache do
|
130
|
+
- if product.one_price?
|
131
|
+
%p.product-prices__price
|
132
|
+
- if product.show_sell_range?
|
133
|
+
%span.product-prices__sell-price.product-prices__sell-price--min= render 'workarea/storefront/products/price', price: product.sell_min_price
|
134
|
+
%span.product-prices__sell-price.product-prices__sell-price--max – #{number_to_currency product.sell_max_price}
|
135
|
+
- else
|
136
|
+
%span.product-prices__sell-price= render 'workarea/storefront/products/price', price: product.sell_min_price
|
137
|
+
|
138
|
+
- else
|
139
|
+
- if product.on_sale?
|
140
|
+
%p.product-prices__price.product-prices__price--on-sale
|
141
|
+
- if product.show_sell_range?
|
142
|
+
%strong.product-prices__sell-price.product-prices__sell-price--min= render 'workarea/storefront/products/price', price: product.sell_min_price
|
143
|
+
%strong.product-prices__sell-price.product-prices__sell-price--max – #{number_to_currency product.sell_max_price}
|
144
|
+
- else
|
145
|
+
%strong.product-prices__sell-price= render 'workarea/storefront/products/price', price: product.sell_min_price
|
146
|
+
|
147
|
+
- else
|
148
|
+
%p.product-prices__price
|
149
|
+
- if product.show_sell_range?
|
150
|
+
%span.product-prices__sell-price.product-prices__sell-price--min= render 'workarea/storefront/products/price', price: product.sell_min_price
|
151
|
+
%span.product-prices__sell-price.product-prices__sell-price--max – #{number_to_currency product.sell_max_price}
|
152
|
+
- else
|
153
|
+
%span.product-prices__sell-price= render 'workarea/storefront/products/price', price: product.sell_min_price
|
154
|
+
|
155
|
+
%p.product-prices__price.product-prices__price--original
|
156
|
+
- if product.show_original_range?
|
157
|
+
%s.product-prices__original-price #{number_to_currency product.original_min_price} – #{number_to_currency product.original_max_price}
|
158
|
+
- else
|
159
|
+
%s.product-prices__original-price= number_to_currency product.original_min_price
|
160
|
+
```
|
161
|
+
|
162
|
+
```haml
|
163
|
+
-# app/views/workarea/storefront/products/_price.html.haml
|
164
|
+
- if price.present?
|
165
|
+
%meta{ itemprop: 'priceCurrency', content: price.currency }
|
166
|
+
%meta{ itemprop: 'price', content: price.to_f }
|
167
|
+
= number_to_currency price
|
168
|
+
```
|
169
|
+
|
170
|
+
As you can see we use `strong` and `s` HTML tags within these which carry semantic value.
|
171
|
+
|
172
|
+
These partials are rendered within the product details and summary views, each applying their own modifier to the component, which allows these components to be conditionally styled based on which page they appear.
|
173
|
+
|
174
|
+
## Caching
|
175
|
+
|
176
|
+
The product pricing code is partialized to make use of fragment caching, which you can see at the top of this file, above. Because of the cache the markup for every place the markup is output must be the same. This is another reason why the parent `.product-prices` component lives outside of the partial and provides the unique styling hooks for both the product detail and product summary views. These classes are:
|
177
|
+
|
178
|
+
* `product-prices--details`
|
179
|
+
* `product-prices--summary`
|
180
|
+
|
181
|
+
Each usage of the product pricing partial is further cached by either the product detail or product summary view, using the following fragment cache keys:
|
182
|
+
|
183
|
+
* `config.cache_expirations.product_show_fragment_cache`
|
184
|
+
* `config.cache_expirations.product_summary_fragment_cache`
|
185
|
+
|
186
|
+
Additional fragment caches may be added as well, such as if the summary is an recommended product inside the product detail page.
|
187
|
+
|
188
|
+
## Recommendations in Storefront emails
|
189
|
+
|
190
|
+
The product pricing partial is also referenced by the recommendations mailer partial, for use in generating recommendations to users of the site.
|
191
|
+
|
192
|
+
Styling for this markup is provided by the `.product-grid` component that lives inside the `email` Stylesheet directory, specifically in:
|
193
|
+
|
194
|
+
```scss
|
195
|
+
/* app/assets/stylesheets/workarea/storefront/email/_components.scss */
|
196
|
+
.product-grid {
|
197
|
+
& > tr > td {
|
198
|
+
vertical-align: top;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
.product-grid__product {
|
203
|
+
text-align: center;
|
204
|
+
}
|
205
|
+
|
206
|
+
.product-grid__image {
|
207
|
+
padding: 0 0 $spacing-unit;
|
208
|
+
}
|
209
|
+
|
210
|
+
.product-grid__info {
|
211
|
+
padding: 0 0 ($spacing-unit * 2);
|
212
|
+
font-size: $font-size - 2px;
|
213
|
+
font-family: $font-family;
|
214
|
+
}
|
215
|
+
|
216
|
+
.product-grid__link {
|
217
|
+
text-decoration: none;
|
218
|
+
}
|
219
|
+
|
220
|
+
.product-grid__name {
|
221
|
+
display: block;
|
222
|
+
}
|
223
|
+
|
224
|
+
.product-grid__price {
|
225
|
+
font-weight: bold;
|
226
|
+
}
|
227
|
+
```
|
228
|
+
|
229
|
+
The styling for the pricing partial is provided specifically by the `.product-grid__price` class, above.
|
230
|
+
|
231
|
+
## Example Customization
|
232
|
+
|
233
|
+
The `product-prices` component is often customized to satisfy design and further clarify each price that is output. In this example we'll start by styling the Sell and Original prices green and gray, respectively, to make the actual price of the product stand out more.
|
234
|
+
|
235
|
+
If the `product-prices` component has not yet been overridden in your project, override it using:
|
236
|
+
|
237
|
+
```sh
|
238
|
+
bin/rails g workarea:override stylesheets storefront/components/_product_prices.scss
|
239
|
+
```
|
240
|
+
|
241
|
+
Inside of this component you will find many classes, but the two that are of interest to us are
|
242
|
+
|
243
|
+
```scss
|
244
|
+
.product-prices__sell-price {}
|
245
|
+
.product-prices__original-price {}
|
246
|
+
```
|
247
|
+
|
248
|
+
First we should add a few functional color variables to the top of the component to help us quickly reskin or theme this UI for use in another multi-site instance. Then we should add these colors to each class. We'll assume that the colors variables `$green` and `$gray` are already defined within the `workarea/storefront/settings/_colors.scss` file:
|
249
|
+
|
250
|
+
```scss
|
251
|
+
// app/assets/stylesheets/workarea/storefront/components/_product_prices.scss
|
252
|
+
|
253
|
+
/*------------------------------------*\
|
254
|
+
#PRODUCT-PRICES
|
255
|
+
\*------------------------------------*/
|
256
|
+
|
257
|
+
$product-prices-sell-price-color: $green !default;
|
258
|
+
$product-prices-original-price-color: $gray !default;
|
259
|
+
|
260
|
+
.product-prices {}
|
261
|
+
|
262
|
+
...
|
263
|
+
|
264
|
+
.product-prices__sell-price {
|
265
|
+
color: $product-prices-sell-price-color;
|
266
|
+
}
|
267
|
+
|
268
|
+
.product-prices__original-price {
|
269
|
+
color: $product-prices-original-price-color;
|
270
|
+
}
|
271
|
+
```
|
272
|
+
|
273
|
+
Now the UI should be a bit clearer to the user, but sometimes designers or clients find price ranges to be confusing as well. Another common customization is to show a minimum price only, using a "From" label to show the product's lowest price.
|
274
|
+
|
275
|
+
To do this we'll first need to add an entry to our locale file, for use in the partial. If it does not yet exist, you can create one in the `config/locales/` directory.
|
276
|
+
|
277
|
+
```yaml
|
278
|
+
# config/locales/en.yml
|
279
|
+
en:
|
280
|
+
workarea:
|
281
|
+
storefront:
|
282
|
+
...
|
283
|
+
products:
|
284
|
+
...
|
285
|
+
min_price_label: "From:"
|
286
|
+
...
|
287
|
+
```
|
288
|
+
|
289
|
+
Next we'll add the new locale to the product pricing partial, removing the elements containing the max price from all sell price ranges as well:
|
290
|
+
|
291
|
+
```haml
|
292
|
+
- cache "#{product.cache_key}/prices", expires_in: Workarea.config.cache_expirations.product_pricing_fragment_cache do
|
293
|
+
- if product.one_price?
|
294
|
+
%p.product-prices__price
|
295
|
+
- if product.show_sell_range?
|
296
|
+
%span.product-prices__sell-price.product-prices__sell-price--min
|
297
|
+
= t('workarea.storefront.products.min_price_label')
|
298
|
+
= render 'workarea/storefront/products/price', price: product.sell_min_price
|
299
|
+
- else
|
300
|
+
%span.product-prices__sell-price= render 'workarea/storefront/products/price', price: product.sell_min_price
|
301
|
+
|
302
|
+
- else
|
303
|
+
- if product.on_sale?
|
304
|
+
%p.product-prices__price.product-prices__price--on-sale
|
305
|
+
- if product.show_sell_range?
|
306
|
+
%strong.product-prices__sell-price.product-prices__sell-price--min
|
307
|
+
= t('workarea.storefront.products.min_price_label')
|
308
|
+
= render 'workarea/storefront/products/price', price: product.sell_min_price
|
309
|
+
- else
|
310
|
+
%strong.product-prices__sell-price= render 'workarea/storefront/products/price', price: product.sell_min_price
|
311
|
+
|
312
|
+
- else
|
313
|
+
%p.product-prices__price
|
314
|
+
- if product.show_sell_range?
|
315
|
+
%span.product-prices__sell-price.product-prices__sell-price--min
|
316
|
+
= t('workarea.storefront.products.min_price_label')
|
317
|
+
= render 'workarea/storefront/products/price', price: product.sell_min_price
|
318
|
+
- else
|
319
|
+
%span.product-prices__sell-price= render 'workarea/storefront/products/price', price: product.sell_min_price
|
320
|
+
|
321
|
+
%p.product-prices__price.product-prices__price--original
|
322
|
+
- if product.show_original_range?
|
323
|
+
%s.product-prices__original-price #{number_to_currency product.original_min_price} – #{number_to_currency product.original_max_price}
|
324
|
+
- else
|
325
|
+
%s.product-prices__original-price= number_to_currency product.original_min_price
|
326
|
+
```
|
327
|
+
|
328
|
+
This change will undoubtedly break some tests. The tests pertaining to pricing live in the Storefront's product's system test. As an example we'll modify the `test_showing_a_product` test method in a decorator:
|
329
|
+
|
330
|
+
```ruby
|
331
|
+
# test/workarea/storefront/products_system_test.decorator
|
332
|
+
|
333
|
+
require 'test_helper'
|
334
|
+
|
335
|
+
module Workarea
|
336
|
+
decorate Storefront::ProductsSystemTest do
|
337
|
+
def test_showing_a_product
|
338
|
+
visit storefront.product_path(@product)
|
339
|
+
assert(page.has_content?('Integration Product'))
|
340
|
+
assert(page.has_content?('From: $10.00'))
|
341
|
+
refute(page.has_content?('$15.00'))
|
342
|
+
assert(page.has_select?('sku', options: ['Select options', 'SKU1', 'SKU2', 'SKU3']))
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
```
|
347
|
+
|
348
|
+
Similar customizations may need to be made to test methods in this file as well.
|
@@ -0,0 +1,103 @@
|
|
1
|
+
---
|
2
|
+
title: Change the Storefront Search Filters UI
|
3
|
+
excerpt: Learn the steps to style and adjust a frequently customized area of the Storefront
|
4
|
+
---
|
5
|
+
|
6
|
+
# Change the Storefront Search Filters UI
|
7
|
+
|
8
|
+
Invariably, through the course of developing the Storefront, your designer will design aspects of the site differently than what the platform supplies out of the box. To handle these changes a developer will need to <a href='overriding.html'>override views, Stylesheet and JavaScript files</a> from the platform into their application in order to make the necessary customizations. Additional changes may be made to helpers or view models used for the simplification of the views themselves.
|
9
|
+
|
10
|
+
## Types of Customizations
|
11
|
+
|
12
|
+
Based on the design and user-experience processes a developer may need to customize this UI to best suit the needs of the user and the aesthetic of the brand.
|
13
|
+
|
14
|
+
Some common customizations include
|
15
|
+
|
16
|
+
* using the jQuery UI Accordion widget to compress the list of filters
|
17
|
+
* move filters into a custom overlay or drop-down
|
18
|
+
* change the look and feel of the filter's selected state
|
19
|
+
* apply a faux checkbox UI to filter links
|
20
|
+
* break out the list of selected filters from the list unselected filters
|
21
|
+
|
22
|
+
As with all other aspects of Storefront development, this UI is built mobile-first. The presentation of the Search Filters UI, on mobile, is hidden behind a button click. When clicked, the button triggers the display of a drawer-like UI which contains the Search Filters UI.
|
23
|
+
|
24
|
+
## File Overview
|
25
|
+
|
26
|
+
### Views & View Partials
|
27
|
+
|
28
|
+
The markup for the Search Filters UI is provided by the following views:
|
29
|
+
|
30
|
+
```
|
31
|
+
app/views/workarea/storefront:
|
32
|
+
categories:
|
33
|
+
show.html.haml
|
34
|
+
searches:
|
35
|
+
show.html.haml
|
36
|
+
```
|
37
|
+
|
38
|
+
These views reference a variety of partials, named after the type of facet by which a user would filter their results. Consider this an incomplete list, as plugins may also register their own facet partials. The facet partials that the platform provides out of the box are:
|
39
|
+
|
40
|
+
```
|
41
|
+
app/views/workarea/storefront/facets:
|
42
|
+
_range.html.haml
|
43
|
+
_terms.html.haml
|
44
|
+
```
|
45
|
+
|
46
|
+
The category and search views define the key and expiry duration for the fragment cache that wraps the UI.
|
47
|
+
|
48
|
+
These views also define the `mobile-filters` and `result-filters` component blocks, with the elements of the latter being housed within each facet partial.
|
49
|
+
|
50
|
+
### Helpers
|
51
|
+
|
52
|
+
The facet's path, price range link text, and associated hidden inputs that are output on the page are generated by the `Workarea::FacetsHelper` located in:
|
53
|
+
|
54
|
+
```
|
55
|
+
app/helpers/workarea/facets_helper.rb
|
56
|
+
```
|
57
|
+
|
58
|
+
This helper is shared between the Storefront and Admin engines, which is why it is located in the Core engine. Be aware that changes made to this file will impact both Storefront and Admin engines in tandem.
|
59
|
+
|
60
|
+
If you need to add an additional method to this helper that was used for output on the Storefront only, you would simply create a new helper `Workarea::Storefront::FacetsHelper` and place it in:
|
61
|
+
|
62
|
+
```
|
63
|
+
app/helpers/workarea/storefront/facets_helper.rb
|
64
|
+
```
|
65
|
+
|
66
|
+
Please note that helpers cannot be decorated, but <a href='customize-a-helper.html'>they can be customized</a>.
|
67
|
+
|
68
|
+
### Stylesheets
|
69
|
+
|
70
|
+
The styling for the `mobile-filters` and `result-filters` components are supplied by the following Stylesheets:
|
71
|
+
|
72
|
+
```
|
73
|
+
app/assets/stylesheets/workarea/storefront/components:
|
74
|
+
_mobile_filters.scss
|
75
|
+
_mobile_filters_nav.scss
|
76
|
+
_result_filters.scss
|
77
|
+
```
|
78
|
+
|
79
|
+
The `mobile-filters` are comprised of element classes used for styling a hidden checkbox used for handling the button's change state, a clickable trigger, and a block of content that will toggle based on the state of the aforementioned checkbox.
|
80
|
+
|
81
|
+
As for the `result-filters`, by default each section of the UI provides element classes for styling a list of facets, a selected state modifier, and the number of results that match the current facet. The latter toggles into a prompt to remove the facet once it has been selected by the user.
|
82
|
+
|
83
|
+
### JavaScript
|
84
|
+
|
85
|
+
Naturally JavaScript is used to handle the `mobile-filter` button user experience. There is one module which handles its functionality:
|
86
|
+
|
87
|
+
```
|
88
|
+
app/javascripts/workarea/storefront/modules/mobile_filter_buttons.js
|
89
|
+
```
|
90
|
+
|
91
|
+
On initialization, this module binds two events, one to an element with a `data-mobile-filter-click` attribute and one to the document's `body`. The first triggers the building, injection, activation and ultimate display of the mobile filters with the second responsible for the removal of the UI from view.
|
92
|
+
|
93
|
+
Due to the simplicity of the markup wrapping the `mobile-filters-nav` component there is no associated JST template to accompany this UI; it is simply built within the module itself.
|
94
|
+
|
95
|
+
### System Tests
|
96
|
+
|
97
|
+
As with almost all other interactive aspects of the Storefront, modifying the Search Filters UI may cause its associated system tests to fail. After considerable modification to this UI you should review and run the following tests to make sure that they are still relevant and that the changes you have made have not caused them to fail:
|
98
|
+
|
99
|
+
```
|
100
|
+
test/system/workarea/storefront:
|
101
|
+
categories_system_test.rb
|
102
|
+
search_system_test.rb
|
103
|
+
```
|