From bbfbf7c5239bdda837bee97843f94d09429f3562 Mon Sep 17 00:00:00 2001 From: Dmitry Pushnitsa <2745590@gmail.com> Date: Thu, 24 Dec 2020 15:51:07 +0200 Subject: [PATCH] v1.7.0 (#151) * Switch publish-theme to master version * Add ui-bootstrap 4 to bootstrap-migration layout * Make all buttons text uppercase and fix their box-shadow property * Migrate bulk-order-pad, categories dropdown and search-bar * Remove 'x' in inputs with type 'search' * Fix variables overriding * Fix popover font-size * Create separated scripts bundle for bootstrap v4 * Add ui-bootstrap4 to bower dependencies * Start migrate index page. Carusel * VDS-144: Migrate index page to bootstrap 4 * Remove blogs section * Fix row width in navbar * Fix navbar parts for logged user * Use npm package of ui-bootstrap instead of bower * Fix uppercase class for buttons * Replace custom css for popover border-radius * Remove unused font-size assigments * Fix template for searchBar and remove custom css for dropdown * Stretch searchBar in the header * Fix custom popover sizes * Add folders for custom styles, rename 'custom' to 'override' * Fix nav snippets * Fix categories popover font * Remove redundant code * VP-6270: Add status bages (#142) * VP-6270: Add status badges * VP-6270: Update status badges * v1.6.0 * VDS-252 Split product page to separate snippets (#141) * Split product page to separate snippets - Physical with variations - Physical without variations - Configured product * Formating. Extract acction-buttons snippet * Rename item-configure-btn snippet to item-configure-button * Move dialog controllers to separate files * Remove unused $timeout from controller * Create separate controllers for product-cards (common and configurable) * Change 'div' to 'ng-controller' * Use separate controllers for different product types * Fix code smells * Remove dublicated code * Reuse product-title-info code * Reuse product-delivery block code * Add formatting to if-else blocks Co-authored-by: Ilia * VDS-404: Remove unused workflows (#147) * VDS-408,VDS-348: Migrate 'Cover with image' block (#148) * Add space between buttons * Fix wrong property name * Add settings for padding (top/bottom) and margin (top/bottom) * Set default values for block paddings * Add full-width option * Add button style option * Fix titles position on mobile * Fix text position on mobile * Change max-height of block * Hide image block if there's no url * Revert changes for helpers * Include custom 'cover-text' html for block * VDS-348: Add new spacer size to bootstrap 4 * Fix paddings after adding new spacer to bootstrap 4 * Fix paddings after adding new spacer to bootstrap 4 * Set margins between parts of the block layout * Remove obsolete button colors from preset * Change font for titles * Add helper for block inner-paddings * Add helper for block margins * Change font for blocks subtitle * Fix button color for promotion block * Update doc for 'cover-with-image' block * Add criteria option for 'cover-with-image' block * Add liquid filter to customizable images * VDS-461: Rework navigation process on checkout (#149) * VDS-461: Rework navigation process on checkout * Fix cart content section position * Align top section and change pills size * Change 'u' to 'span' and remove 'text-decoration-none' class * Add variable for nav-outline border radius to bootstrap 3 * Add class nav-outline for cart navigation * VDS-392: Migrate bulk-order, product-compare, error and 404 pages to bootstrap 4 (#146) * Migrate 404 page template * Migrate product-compare page template * Migrate bulk-order page template * Migrate error page template * Remove inline style * Migrate lockedout page template * Migrate confirm_invitation page template * Return max-width style for product image * VDS-379: Migrate login page (with subpages) (#144) * Migrate forgot_password template * Migrate reset_password template * Migrate reset_password_confirmation template * Migrate login template * Fix advantages block on login page * Add mixin for disabled buttons * Migrate registration template * Fix loader appearence * Fix include paths for snippets * Remove mixin for buttons * Move loader to the separate component * Rename bg-variant to semitransparent * Add controller to loader component * Change prop name in template * Fix $ctrl Co-authored-by: Aleksandr Vishniakov * v1.7.0 Co-authored-by: Maksim Kopnov Co-authored-by: Ilia Co-authored-by: trueboroda Co-authored-by: Maksim Kopnov <44946644+mvktsk@users.noreply.github.com> Co-authored-by: Aleksandr Vishniakov --- .github/workflows/release-alpha.yml | 41 -- .../common-components/loader.js | 8 + .../common-components/loader.tpl.html.liquid | 5 + assets/js/controllers/dialogs/add-to-cart.js | 92 +++++ .../dialogs/change-configuration-group.js | 21 ++ .../product-card/common-product-card.js | 42 +++ .../product-card/configurable-product-card.js | 22 ++ .../product/configurable-product.js | 128 +++++++ .../product/product-with-variations.js | 69 ++++ .../product/product-without-variations.js | 22 ++ assets/js/product.js | 356 ------------------ assets/scss/_variables.scss | 1 + assets/scss/bootstrap-migration/_custom.scss | 3 + .../_default-variables.scss | 3 + assets/scss/bootstrap-migration/_helpers.scss | 15 + assets/scss/bootstrap-migration/_maps.scss | 9 + assets/scss/bootstrap-migration/_modules.scss | 1 + .../scss/bootstrap-migration/_variables.scss | 14 + .../custom/_backgrounds.scss | 6 + .../bootstrap-migration/custom/_buttons.scss | 15 + .../bootstrap-migration/custom/_sizing.scss | 7 + assets/scss/bootstrap-migration/main.scss | 2 + .../bootstrap-migration/modules/_loader.scss | 4 + .../override/_scaffolding.scss | 1 + assets/scss/custom/_navs.scss | 111 +++--- assets/scss/custom/_scaffolding.scss | 2 +- config/blocks_schema.json | 222 +++++++---- package-lock.json | 2 +- package.json | 2 +- .../customers/login-form.liquid | 3 +- .../dashboard/bulk-order-content.liquid | 2 +- .../shared/breadcrumb.liquid | 89 +++++ .../shared/bulk-order-fields.liquid | 8 +- snippets/dashboard/bulk-order-content.liquid | 2 +- snippets/product/grid-item.liquid | 21 +- snippets/product/main.liquid | 180 --------- snippets/product/price.liquid | 6 +- snippets/product/quantity-grid.liquid | 42 --- snippets/product/quantity.liquid | 26 +- .../type/common/product-action-buttons.liquid | 13 + .../type/common/product-delivery.liquid | 16 + .../type/common/product-description.liquid | 7 + .../type/common/product-properties.liquid | 25 ++ .../type/common/product-title-info.liquid | 16 + .../type/common/related-products.liquid | 10 + .../configured/item-configure-button.liquid | 14 + .../product/type/configured/item-price.liquid | 20 + .../product/type/configured/product.liquid | 84 +++++ .../product/type/configured/quantity.liquid | 25 ++ .../type/with-variations/product.liquid | 44 +++ .../type/without-variations/product.liquid | 44 +++ snippets/recommendations.liquid | 4 +- templates/404.liquid | 11 +- .../helpers/block-inner-paddings.liquid | 1 + templates/blocks/helpers/block-margins.liquid | 1 + .../blocks/helpers/block-paddings.liquid | 4 +- templates/blocks/helpers/block-title.liquid | 8 +- templates/blocks/helpers/cover-text.liquid | 12 +- templates/blocks/helpers/hide-criteria.liquid | 27 ++ templates/blocks/json-buy-now-search.liquid | 6 +- templates/blocks/json-buy-now.liquid | 8 +- templates/blocks/json-call-to-action.liquid | 4 +- templates/blocks/json-cover-with-form.liquid | 2 +- ...cover-with-image-and-flexible-title.liquid | 4 +- templates/blocks/json-cover-with-image.liquid | 56 ++- .../blocks/json-cover-with-simple-text.liquid | 2 +- ...json-features-with-icons-in-columns.liquid | 8 +- .../blocks/json-features-with-icons.liquid | 6 +- .../blocks/json-headline-with-form.liquid | 2 +- templates/blocks/json-headline.liquid | 2 +- templates/blocks/json-logotypes.liquid | 6 +- templates/blocks/json-product-tiles.liquid | 2 +- templates/blocks/json-text.liquid | 2 +- templates/blocks/json-two-columns-text.liquid | 6 +- templates/bulk-order.liquid | 107 +++--- templates/cart.liquid | 248 ++++++------ templates/customers/confirm_invitation.liquid | 83 ++-- templates/customers/forgot_password.liquid | 54 ++- templates/customers/login.liquid | 52 +-- templates/customers/register.liquid | 138 ++++--- templates/customers/reset_password.liquid | 62 +-- .../reset_password_confirmation.liquid | 3 +- templates/error.liquid | 13 +- templates/index.liquid | 2 +- templates/json-page.liquid | 2 +- templates/json-preview.liquid | 2 +- templates/lockedout.liquid | 7 +- templates/product-compare.liquid | 127 +++---- templates/product.liquid | 33 +- 89 files changed, 1734 insertions(+), 1306 deletions(-) delete mode 100644 .github/workflows/release-alpha.yml create mode 100644 assets/js/bootstrap-migration/common-components/loader.js create mode 100644 assets/js/bootstrap-migration/common-components/loader.tpl.html.liquid create mode 100644 assets/js/controllers/dialogs/add-to-cart.js create mode 100644 assets/js/controllers/dialogs/change-configuration-group.js create mode 100644 assets/js/controllers/product-card/common-product-card.js create mode 100644 assets/js/controllers/product-card/configurable-product-card.js create mode 100644 assets/js/controllers/product/configurable-product.js create mode 100644 assets/js/controllers/product/product-with-variations.js create mode 100644 assets/js/controllers/product/product-without-variations.js delete mode 100644 assets/js/product.js create mode 100644 assets/scss/bootstrap-migration/_helpers.scss create mode 100644 assets/scss/bootstrap-migration/_modules.scss create mode 100644 assets/scss/bootstrap-migration/custom/_backgrounds.scss create mode 100644 assets/scss/bootstrap-migration/custom/_buttons.scss create mode 100644 assets/scss/bootstrap-migration/custom/_sizing.scss create mode 100644 assets/scss/bootstrap-migration/modules/_loader.scss create mode 100644 snippets/bootstrap-migration/shared/breadcrumb.liquid delete mode 100644 snippets/product/main.liquid delete mode 100644 snippets/product/quantity-grid.liquid create mode 100644 snippets/product/type/common/product-action-buttons.liquid create mode 100644 snippets/product/type/common/product-delivery.liquid create mode 100644 snippets/product/type/common/product-description.liquid create mode 100644 snippets/product/type/common/product-properties.liquid create mode 100644 snippets/product/type/common/product-title-info.liquid create mode 100644 snippets/product/type/common/related-products.liquid create mode 100644 snippets/product/type/configured/item-configure-button.liquid create mode 100644 snippets/product/type/configured/item-price.liquid create mode 100644 snippets/product/type/configured/product.liquid create mode 100644 snippets/product/type/configured/quantity.liquid create mode 100644 snippets/product/type/with-variations/product.liquid create mode 100644 snippets/product/type/without-variations/product.liquid create mode 100644 templates/blocks/helpers/block-inner-paddings.liquid create mode 100644 templates/blocks/helpers/block-margins.liquid create mode 100644 templates/blocks/helpers/hide-criteria.liquid diff --git a/.github/workflows/release-alpha.yml b/.github/workflows/release-alpha.yml deleted file mode 100644 index b12d5ad6..00000000 --- a/.github/workflows/release-alpha.yml +++ /dev/null @@ -1,41 +0,0 @@ -# v1 -name: Release alpha -on: - workflow_dispatch: - - -jobs: - ci: - runs-on: ubuntu-latest - env: - SONAR_TOKEN: ${{secrets.SONAR_TOKEN}} - GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }} - BLOB_SAS: ${{ secrets.BLOB_TOKEN }} - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Setup sonarqube - uses: warchant/setup-sonar-scanner@v3 - - - name: Get Image Version - uses: VirtoCommerce/vc-github-actions/get-image-version@master - id: image - - - name: Get changelog - id: changelog - uses: VirtoCommerce/vc-github-actions/changelog-generator@master - - - name: SonarCloud Scan - uses: VirtoCommerce/vc-github-actions/sonar-theme@master - - - name: Build - uses: VirtoCommerce/vc-github-actions/build-theme@master - with: - versionSuffix: ${{ steps.image.outputs.fullSuffix }} - - - name: Publish - id: publish - uses: VirtoCommerce/vc-github-actions/publish-theme@master diff --git a/assets/js/bootstrap-migration/common-components/loader.js b/assets/js/bootstrap-migration/common-components/loader.js new file mode 100644 index 00000000..7f73a13f --- /dev/null +++ b/assets/js/bootstrap-migration/common-components/loader.js @@ -0,0 +1,8 @@ +var storefrontApp = angular.module('storefrontApp'); + +storefrontApp.component('vcLoader', { + templateUrl: "themes/assets/js/bootstrap-migration/common-components/loader.tpl.html", + bindings: { + isLoading: '<' + } +}); diff --git a/assets/js/bootstrap-migration/common-components/loader.tpl.html.liquid b/assets/js/bootstrap-migration/common-components/loader.tpl.html.liquid new file mode 100644 index 00000000..3f24c8a4 --- /dev/null +++ b/assets/js/bootstrap-migration/common-components/loader.tpl.html.liquid @@ -0,0 +1,5 @@ +
+
+ {{ 'general.loading' | t }} +
+
diff --git a/assets/js/controllers/dialogs/add-to-cart.js b/assets/js/controllers/dialogs/add-to-cart.js new file mode 100644 index 00000000..b3855f99 --- /dev/null +++ b/assets/js/controllers/dialogs/add-to-cart.js @@ -0,0 +1,92 @@ +angular.module('storefrontApp') + .controller('recentlyAddedCartItemDialogController', ['$rootScope', '$scope', '$window', '$uibModalInstance', 'mailingService', 'dialogData', 'baseUrl', 'cartService', 'roundHelper', '$filter', 'storeCurrency', function ($rootScope, $scope, $window, $uibModalInstance, mailingService, dialogData, baseUrl, cartService, roundHelper, $filter, storeCurrency) { + $scope.dialogData = dialogData || {}; + $scope.baseUrl = baseUrl; + $scope.regex = new RegExp(/^\/+/); + + $scope.close = function() { + $uibModalInstance.dismiss('cancel'); + } + + $scope.addToCart = function() { + $scope.dialogData.inventoryError = false; + if ($scope.dialogData && $scope.dialogData.items && $scope.dialogData.items.length === 1) { + cartService.addLineItem($scope.dialogData.items[0].id, $scope.dialogData.items[0].quantity).then(() => { + $rootScope.$broadcast('cartItemsChanged'); + }); + } else if ($scope.dialogData.configuredProductId) { + let items = $scope.dialogData.items.map(item => { + return { id: item.id, quantity: $scope.configurationQty, configuredProductId: item.configuredProductId }; + }); + cartService.addLineItems(items).then(response => { + let result = response.data; + if (result.isSuccess) { + $rootScope.$broadcast('cartItemsChanged'); + } + }); + } else { + let items = $scope.dialogData.items.map(item => { + return { id: item.id, quantity: item.quantity }; + }); + cartService.addLineItems(items).then(response => { + let result = response.data; + if (result.isSuccess) { + $rootScope.$broadcast('cartItemsChanged'); + } + }); + } + } + + $scope.calculateTotal = function(itemPrice, itemQuantity) { + var total = roundHelper.bankersRound(itemPrice * itemQuantity); + return $filter('currency')(total, storeCurrency.symbol); + } + + $scope.setInitQuantity = function(item) { + if (item.inventoryError) { + return item.availableQuantity; + } else { + return item.quantity; + } + } + + $scope.getConfirmationTitle = function() { + if ($scope.dialogData && $scope.dialogData.items && $scope.dialogData.items.length === 1) { + return '1 item was added to cart'; + } else { + return `${$scope.dialogData.items.length} items were added to cart`; + } + } + + $scope.quantityChanged = function(qty) { + $scope.configurationQty = qty; + } + + $scope.redirect = function (url) { + $window.location.href = url; + } + + $scope.send = function(email) { + mailingService.sendProduct(dialogData.productId, { email: email, storeId: dialogData.storeId, productUrl: dialogData.productUrl, language: dialogData.language }); + $uibModalInstance.close(); + } + + function getMaxInventory() { + var inventoryArray = $scope.dialogData.items.map(item => { + return item.availableQuantity; + }); + $scope.maxConfigurationQty = Math.min(...inventoryArray); + $scope.configurationQty = $scope.maxConfigurationQty; + } + + function initialize() { + if ($scope.dialogData.inventoryError && $scope.dialogData.configuredProductId) { + getMaxInventory(); + } else if (!$scope.dialogData.inventoryError && $scope.dialogData.configuredProductId) { + $scope.configurationQty = $scope.dialogData.configurationQty; + } + } + + initialize(); + + }]); diff --git a/assets/js/controllers/dialogs/change-configuration-group.js b/assets/js/controllers/dialogs/change-configuration-group.js new file mode 100644 index 00000000..a3b5b756 --- /dev/null +++ b/assets/js/controllers/dialogs/change-configuration-group.js @@ -0,0 +1,21 @@ +angular.module('storefrontApp') + .controller('changeConfigurationGroupItemDialogController', ['$scope', '$uibModalInstance', 'dialogData', function ($scope, $uibModalInstance, dialogData) { + $scope.dialogData = dialogData || {}; + $scope.selectedId = dialogData.selectedItemId; + + $scope.close = function() { + $uibModalInstance.dismiss('cancel'); + } + + $scope.getModalTitel = function() { + return `Choose ${$scope.dialogData.name}` + } + + $scope.handleRadioClick = function(id) { + $scope.selectedId = id; + } + + $scope.save = function(id) { + $uibModalInstance.close(id); + } + }]); diff --git a/assets/js/controllers/product-card/common-product-card.js b/assets/js/controllers/product-card/common-product-card.js new file mode 100644 index 00000000..2859199b --- /dev/null +++ b/assets/js/controllers/product-card/common-product-card.js @@ -0,0 +1,42 @@ +var storefrontApp = angular.module('storefrontApp'); + +storefrontApp.controller('commonProductCardController', ['$rootScope', '$scope', 'dialogService', 'catalogService', 'cartService', 'validationHelper', + function ($rootScope, $scope, dialogService, catalogService, cartService, validationHelper) { + $scope.validateQtyInput = validationHelper.positiveInt; + + $scope.addProductToCart = function (product, quantity) { + var inventoryError = product.availableQuantity < quantity; + var dialogData = toDialogDataModel([product], quantity, inventoryError, null); + dialogService.showDialog(dialogData, 'recentlyAddedCartItemDialogController', 'storefront.recently-added-cart-item-dialog.tpl', 'lg'); + if (!inventoryError) { + cartService.addLineItem(product.id, quantity).then(() => { + $rootScope.$broadcast('cartItemsChanged'); + }); + } + } + + $scope.addProductToCartById = function (productId, quantity, event) { + event.preventDefault(); + catalogService.getProduct([productId]).then(function (response) { + if (response.data && response.data.length) { + var product = response.data[0]; + $scope.addProductToCart(product, quantity); + } + }); + } + + $scope.sendToEmail = function (storeId, productId, productUrl, language) { + dialogService.showDialog({ storeId: storeId, productId: productId, productUrl: productUrl, language: language }, 'recentlyAddedCartItemDialogController', 'storefront.send-product-to-email.tpl'); + }; + + function toDialogDataModel(products, quantity, inventoryError, configuredProductId) { + let productIds = products.map(function(product) { + return product.id; + }); + let items = products.map(function(product) { + return angular.extend({ }, product, { quantity: +quantity, inventoryError: product.availableQuantity < quantity, configuredProductId: configuredProductId }) + }); + return { productIds, items, inventoryError, configuredProductId, configurationQty: quantity }; + } + + }]); diff --git a/assets/js/controllers/product-card/configurable-product-card.js b/assets/js/controllers/product-card/configurable-product-card.js new file mode 100644 index 00000000..e5250e3d --- /dev/null +++ b/assets/js/controllers/product-card/configurable-product-card.js @@ -0,0 +1,22 @@ +var storefrontApp = angular.module('storefrontApp'); + +storefrontApp.controller('configurableProductCardController', ['$scope', 'catalogService', '$filter', 'roundHelper', 'storeCurrency', + function ($scope, catalogService, $filter, roundHelper, storeCurrency) { + + $scope.getDefaultPrice = function() { + return $filter('currency')($scope.defaultPrice, storeCurrency.symbol); + } + + $scope.initProductConfiguration = function(productId) { + catalogService.getProductConfiguration(productId).then(function(response) { + $scope.productParts = response.data; + $scope.defaultProductParts = []; + _.each($scope.productParts, function (part) { + $scope.defaultProductParts.push(part.items.find(x => x.id === part.selectedItemId)); + }); + + $scope.defaultPrice = roundHelper.bankersRound($scope.defaultProductParts.reduce((prev, cur) => prev + cur.price.actualPrice.amount, 0)); + }); + } + + }]); diff --git a/assets/js/controllers/product/configurable-product.js b/assets/js/controllers/product/configurable-product.js new file mode 100644 index 00000000..781ea19d --- /dev/null +++ b/assets/js/controllers/product/configurable-product.js @@ -0,0 +1,128 @@ +var storefrontApp = angular.module('storefrontApp'); + +storefrontApp.controller('configurableProductController', ['$rootScope', '$scope', '$window', 'dialogService', 'catalogService', 'cartService', '$filter', 'roundHelper', 'availabilityService', 'validationHelper', 'storeCurrency', + function ($rootScope, $scope, $window, dialogService, catalogService, cartService, $filter, roundHelper, availabilityService, validationHelper, storeCurrency) { + $scope.configurationQty = 1; + $scope.validateQtyInput = validationHelper.positiveInt; + + $scope.addSelectedProductsToCart = function() { + var configuredProductId = $window.product.id; + var products = $scope.productParts.map(function(part) { + return part.items.find(function(item) { + return item.id === part.selectedItemId; + }); + }); + var inventoryError = products.some(product => { + return product.availableQuantity < $scope.configurationQty; + }); + var dialogData = toDialogDataModel(products, $scope.configurationQty, inventoryError, configuredProductId); + dialogService.showDialog(dialogData, 'recentlyAddedCartItemDialogController', 'storefront.recently-added-cart-item-dialog.tpl', 'lg'); + + if (!inventoryError) { + var items = $scope.productParts.map(function(value) { + return { id: value.selectedItemId, quantity: $scope.configurationQty, configuredProductId: configuredProductId }; + }); + + cartService.addLineItems(items).then(function (response) { + var result = response.data; + if (result.isSuccess) { + $rootScope.$broadcast('cartItemsChanged'); + } + }); + } + } + + $scope.changeGroupItem = function (productPart) { + var dialogInstance = dialogService.showDialog(productPart, 'changeConfigurationGroupItemDialogController', 'storefront.select-configuration-item-dialog.tpl'); + dialogInstance.result.then(function (id) { + const foundIndex = $scope.productParts.findIndex(x => x.name === productPart.name); + $scope.productParts[foundIndex].selectedItemId = id; + recalculateTotals(); + }); + }; + + $scope.getSelectedItem = function(configPart) { + const item = configPart.items.find(x => x.id === configPart.selectedItemId); + return item.name; + } + + $scope.getCurrentTotal = function() { + var total; + + if ($scope.updatedTotal) { + total = roundHelper.bankersRound($scope.updatedTotal * $scope.configurationQty); + } else { + total = roundHelper.bankersRound($scope.defaultPrice * $scope.configurationQty); + } + + return $filter('currency')(total, storeCurrency.symbol); + } + + $scope.getDefaultPrice = function() { + return $filter('currency')($scope.defaultPrice, storeCurrency.symbol); + } + + $scope.getCustomChangesTotal = function() { + return $scope.differenceSign + $filter('currency')($scope.totalDifference, storeCurrency.symbol) || $filter('currency')(0, storeCurrency.symbol); + } + + $scope.quantityChanged = function(qty) { + const intValue = parseInt(qty, 10); + + if (isNaN(intValue) || intValue === 0) { + $scope.configurationQty = 1 + } else { + $scope.configurationQty = intValue; + } + } + + function toDialogDataModel(products, quantity, inventoryError, configuredProductId) { + let productIds = products.map(function(product) { + return product.id; + }); + let items = products.map(function(product) { + return angular.extend({ }, product, { quantity: +quantity, inventoryError: product.availableQuantity < quantity, configuredProductId: configuredProductId }) + }); + return { productIds, items, inventoryError, configuredProductId, configurationQty: quantity }; + } + + function initialize() { + var product = $window.product; + if (!product) { + return; + } + catalogService.getProduct([product.id]).then(function (response) { + product = response.data[0]; + $scope.selectedVariation = product; + + return availabilityService.getProductsAvailability([product.id]).then(function(res) { + $scope.availability = _.object(_.pluck(res.data, 'productId'), res.data); + }); + }); + } + + function recalculateTotals() { + $scope.selectedProductParts = []; + _.each($scope.productParts, function (part) { + $scope.selectedProductParts.push(part.items.find(x => x.id === part.selectedItemId)); + }); + $scope.updatedTotal = roundHelper.bankersRound($scope.selectedProductParts.reduce((prev, cur) => prev + cur.price.actualPrice.amount, 0)); + $scope.totalDifference = roundHelper.bankersRound(Math.abs($scope.updatedTotal - $scope.defaultPrice)); + $scope.differenceSign = ($scope.updatedTotal === $scope.defaultPrice) ? '' : + ($scope.updatedTotal > $scope.defaultPrice) ? '+' : '-'; + } + + $scope.initProductConfiguration = function(productId) { + catalogService.getProductConfiguration(productId).then(function(response) { + $scope.productParts = response.data; + $scope.defaultProductParts = []; + _.each($scope.productParts, function (part) { + $scope.defaultProductParts.push(part.items.find(x => x.id === part.selectedItemId)); + }); + + $scope.defaultPrice = roundHelper.bankersRound($scope.defaultProductParts.reduce((prev, cur) => prev + cur.price.actualPrice.amount, 0)); + }); + } + + initialize(); + }]); diff --git a/assets/js/controllers/product/product-with-variations.js b/assets/js/controllers/product/product-with-variations.js new file mode 100644 index 00000000..5d9d8059 --- /dev/null +++ b/assets/js/controllers/product/product-with-variations.js @@ -0,0 +1,69 @@ +var storefrontApp = angular.module('storefrontApp'); + +storefrontApp.controller('productWithVariationsController', ['$scope', '$window', 'catalogService', 'availabilityService', + function ($scope, $window, catalogService, availabilityService) { + //TODO: prevent add to cart not selected variation + // display validator please select property + // display price range + $scope.allVariations = []; + $scope.allVariationsMap = {} + $scope.allVariationPropsMap = {}; + $scope.allVariationPropsMapCount = null; + $scope.filterableVariationPropsMap = { }; + $scope.selectedVariation = {}; + + function initialize(filters) { + var product = $window.product; + if (!product) { + return; + } + catalogService.getProduct([product.id]).then(function (response) { + product = response.data[0]; + //Current product is also a variation (titular) + var allVariations = [product].concat(product.variations || []); + var filteredVariations = allVariations; + $scope.allVariations.length = 0; + if (filters) { + var variationPropsKeys = Object.keys(filters.terms || {}); + filteredVariations = _.filter(allVariations, function(variation) { + return _.all(variation.variationProperties, function(property) { + return !variationPropsKeys.includes(property.displayName) || filters.terms[property.displayName].includes(property.value); + }); + }); + } + Array.prototype.push.apply($scope.allVariations, filteredVariations); + angular.copy(_.object(filteredVariations.map(function (variation) { return [variation.id, variation]; })), $scope.allVariationsMap); + angular.copy(getFlatternDistinctPropertiesMap(allVariations), $scope.allVariationPropsMap); + angular.copy(_.pick($scope.allVariationPropsMap, function (value, key, object) { return value.length > 1; }), $scope.filterableVariationPropsMap); + $scope.allVariationPropsMapCount = _.keys($scope.allVariationPropsMap).length; + //Auto select initial product as default variation (its possible because all our products is variations) + //var propertyMap = getVariationPropertyMap(product); + //_.each(_.keys(propertyMap), function (x) { + // $scope.checkProperty(propertyMap[x][0]) + //}); + $scope.selectedVariation = product; + + return availabilityService.getProductsAvailability([product.id]).then(function(res) { + $scope.availability = _.object(_.pluck(res.data, 'productId'), res.data); + }); + }); + } + + function getFlatternDistinctPropertiesMap(variations) { + var retVal = {}; + _.each(variations, function (variation) { + var propertyMap = getVariationPropertyMap(variation); + //merge + _.each(_.keys(propertyMap), function (x) { + retVal[x] = _.uniq(_.union(retVal[x], propertyMap[x]), "value"); + }); + }); + return retVal; + } + + function getVariationPropertyMap(variation) { + return _.groupBy(variation.variationProperties, function (x) { return x.displayName }); + } + + $scope.$watch('filters', initialize); + }]); diff --git a/assets/js/controllers/product/product-without-variations.js b/assets/js/controllers/product/product-without-variations.js new file mode 100644 index 00000000..b85032ef --- /dev/null +++ b/assets/js/controllers/product/product-without-variations.js @@ -0,0 +1,22 @@ +var storefrontApp = angular.module('storefrontApp'); + +storefrontApp.controller('productWithoutVariationsController', ['$scope', '$window', 'catalogService', 'availabilityService', + function ($scope, $window, catalogService, availabilityService) { + + function initialize() { + var product = $window.product; + if (!product) { + return; + } + catalogService.getProduct([product.id]).then(function (response) { + product = response.data[0]; + $scope.selectedVariation = product; + + return availabilityService.getProductsAvailability([product.id]).then(function(res) { + $scope.availability = _.object(_.pluck(res.data, 'productId'), res.data); + }); + }); + } + + initialize(); + }]); diff --git a/assets/js/product.js b/assets/js/product.js deleted file mode 100644 index b2dc30b8..00000000 --- a/assets/js/product.js +++ /dev/null @@ -1,356 +0,0 @@ -var storefrontApp = angular.module('storefrontApp'); - -storefrontApp.controller('productController', ['$rootScope', '$scope', '$window', '$timeout', 'dialogService', 'catalogService', 'cartService', 'quoteRequestService', 'availabilityService', '$filter', 'roundHelper', 'validationHelper', 'storeCurrency', - function ($rootScope, $scope, $window, $timeout, dialogService, catalogService, cartService, quoteRequestService, availabilityService, $filter, roundHelper, validationHelper, storeCurrency) { - //TODO: prevent add to cart not selected variation - // display validator please select property - // display price range - $scope.allVariations = []; - $scope.allVariationsMap = {} - $scope.allVariationPropsMap = {}; - $scope.allVariationPropsMapCount = null; - $scope.filterableVariationPropsMap = { }; - $scope.selectedVariation = {}; - $scope.productPrice = null; - $scope.productPriceLoaded = false; - $scope.configurationQty = 1; - $scope.validateQtyInput = validationHelper.positiveInt; - - $scope.addSelectedProductsToCart = function() { - if($window.product.productType != 'Configurable'){ - throw new Error("addSelectedProductsToCart method is allowed only in scope of configurable product"); - } - - var configuredProductId = $window.product.id; - var products = $scope.productParts.map(function(part) { - return part.items.find(function(item) { - return item.id === part.selectedItemId; - }); - }); - var inventoryError = products.some(product => { - return product.availableQuantity < $scope.configurationQty; - }); - var dialogData = toDialogDataModel(products, $scope.configurationQty, inventoryError, configuredProductId); - dialogService.showDialog(dialogData, 'recentlyAddedCartItemDialogController', 'storefront.recently-added-cart-item-dialog.tpl', 'lg'); - - if (!inventoryError) { - var items = $scope.productParts.map(function(value) { - return { id: value.selectedItemId, quantity: $scope.configurationQty, configuredProductId: configuredProductId }; - }); - - cartService.addLineItems(items).then(function (response) { - var result = response.data; - if (result.isSuccess) { - $rootScope.$broadcast('cartItemsChanged'); - } - }); - } - } - - $scope.addProductToCart = function (product, quantity) { - var inventoryError = product.availableQuantity < quantity; - var dialogData = toDialogDataModel([product], quantity, inventoryError, null); - dialogService.showDialog(dialogData, 'recentlyAddedCartItemDialogController', 'storefront.recently-added-cart-item-dialog.tpl', 'lg'); - if (!inventoryError) { - cartService.addLineItem(product.id, quantity).then(() => { - $rootScope.$broadcast('cartItemsChanged'); - }); - } - } - - $scope.addProductToCartById = function (productId, quantity, event) { - event.preventDefault(); - catalogService.getProduct([productId]).then(function (response) { - if (response.data && response.data.length) { - var product = response.data[0]; - $scope.addProductToCart(product, quantity); - } - }); - } - - $scope.addProductToActualQuoteRequest = function (product, quantity) { - var dialogData = toDialogDataModel([product], quantity); - dialogService.showDialog(dialogData, 'recentlyAddedActualQuoteRequestItemDialogController', 'storefront.recently-added-actual-quote-request-item-dialog.tpl', 'lg'); - quoteRequestService.addProductToQuoteRequest(product.id, quantity).then(function (response) { - $rootScope.$broadcast('actualQuoteRequestItemsChanged'); - }); - } - - $scope.changeGroupItem = function (productPart) { - var dialogInstance = dialogService.showDialog(productPart, 'changeConfigurationGroupItemDialogController', 'storefront.select-configuration-item-dialog.tpl'); - dialogInstance.result.then(function (id) { - const foundIndex = $scope.productParts.findIndex(x => x.name === productPart.name); - $scope.productParts[foundIndex].selectedItemId = id; - recalculateTotals(); - }); - }; - - $scope.getSelectedItem = function(configPart) { - const item = configPart.items.find(x => x.id === configPart.selectedItemId); - return item.name; - } - - $scope.getCurrentTotal = function() { - var total; - - if ($scope.updatedTotal) { - total = roundHelper.bankersRound($scope.updatedTotal * $scope.configurationQty); - } else { - total = roundHelper.bankersRound($scope.defaultPrice * $scope.configurationQty); - } - - return $filter('currency')(total, storeCurrency.symbol); - } - - $scope.getDefaultPrice = function() { - return $filter('currency')($scope.defaultPrice, storeCurrency.symbol); - } - - $scope.getCustomChangesTotal = function() { - return $scope.differenceSign + $filter('currency')($scope.totalDifference, storeCurrency.symbol) || $filter('currency')(0, storeCurrency.symbol); - } - - $scope.quantityChanged = function(qty) { - const intValue = parseInt(qty, 10); - - if (isNaN(intValue) || intValue === 0) { - $scope.configurationQty = 1 - } else { - $scope.configurationQty = intValue; - } - } - - function toDialogDataModel(products, quantity, inventoryError, configuredProductId) { - let productIds = products.map(function(product) { - return product.id; - }); - let items = products.map(function(product) { - return angular.extend({ }, product, { quantity: +quantity, inventoryError: product.availableQuantity < quantity, configuredProductId: configuredProductId }) - }); - return { productIds, items, inventoryError, configuredProductId, configurationQty: quantity }; - } - - function initialize(filters) { - var product = $window.product; - if ($window.products || !product) { - return; - } - catalogService.getProduct([product.id]).then(function (response) { - product = response.data[0]; - //Current product is also a variation (titular) - var allVariations = [product].concat(product.variations || []); - var filteredVariations = allVariations; - $scope.allVariations.length = 0; - if (filters) { - var variationPropsKeys = Object.keys(filters.terms || {}); - filteredVariations = _.filter(allVariations, function(variation) { - return _.all(variation.variationProperties, function(property) { - return !variationPropsKeys.includes(property.displayName) || filters.terms[property.displayName].includes(property.value); - }); - }); - } - Array.prototype.push.apply($scope.allVariations, filteredVariations); - angular.copy(_.object(filteredVariations.map(function (variation) { return [variation.id, variation]; })), $scope.allVariationsMap); - angular.copy(getFlatternDistinctPropertiesMap(allVariations), $scope.allVariationPropsMap); - angular.copy(_.pick($scope.allVariationPropsMap, function (value, key, object) { return value.length > 1; }), $scope.filterableVariationPropsMap); - $scope.allVariationPropsMapCount = _.keys($scope.allVariationPropsMap).length; - //Auto select initial product as default variation (its possible because all our products is variations) - //var propertyMap = getVariationPropertyMap(product); - //_.each(_.keys(propertyMap), function (x) { - // $scope.checkProperty(propertyMap[x][0]) - //}); - $scope.selectedVariation = product; - - return availabilityService.getProductsAvailability([product.id]).then(function(response) { - $scope.availability = _.object(_.pluck(response.data, 'productId'), response.data); - }); - }); - - if (product.productType != 'Configurable') { - return; - } - - $scope.initProductConfiguration(product.id); - }; - - function getFlatternDistinctPropertiesMap(variations) { - var retVal = {}; - _.each(variations, function (variation) { - var propertyMap = getVariationPropertyMap(variation); - //merge - _.each(_.keys(propertyMap), function (x) { - retVal[x] = _.uniq(_.union(retVal[x], propertyMap[x]), "value"); - }); - }); - return retVal; - }; - - function getVariationPropertyMap(variation) { - return _.groupBy(variation.variationProperties, function (x) { return x.displayName }); - } - - function getSelectedPropsMap(variationPropsMap) { - var retVal = {}; - _.each(_.keys(variationPropsMap), function (x) { - var property = _.find(variationPropsMap[x], function (y) { - return y.selected; - }); - if (property) { - retVal[x] = [property]; - } - }); - return retVal; - } - - function comparePropertyMaps(propMap1, propMap2) { - return _.every(_.keys(propMap1), function (x) { - var retVal = propMap2.hasOwnProperty(x); - if (retVal) { - retVal = propMap1[x][0].value == propMap2[x][0].value; - } - return retVal; - }); - }; - - function recalculateTotals() { - $scope.selectedProductParts = []; - _.each($scope.productParts, function (part) { - $scope.selectedProductParts.push(part.items.find(x => x.id === part.selectedItemId)); - }); - $scope.updatedTotal = roundHelper.bankersRound($scope.selectedProductParts.reduce((prev, cur) => prev + cur.price.actualPrice.amount, 0)); - $scope.totalDifference = roundHelper.bankersRound(Math.abs($scope.updatedTotal - $scope.defaultPrice)); - $scope.differenceSign = ($scope.updatedTotal === $scope.defaultPrice) ? '' : - ($scope.updatedTotal > $scope.defaultPrice) ? '+' : '-'; - } - - $scope.initProductConfiguration = function(productId) { - catalogService.getProductConfiguration(productId).then(function(response) { - $scope.productParts = response.data; - $scope.defaultProductParts = []; - _.each($scope.productParts, function (part) { - $scope.defaultProductParts.push(part.items.find(x => x.id === part.selectedItemId)); - }); - - $scope.defaultPrice = roundHelper.bankersRound($scope.defaultProductParts.reduce((prev, cur) => prev + cur.price.actualPrice.amount, 0)); - }); - } - - $scope.sendToEmail = function (storeId, productId, productUrl, language) { - dialogService.showDialog({ storeId: storeId, productId: productId, productUrl: productUrl, language: language }, 'recentlyAddedCartItemDialogController', 'storefront.send-product-to-email.tpl'); - }; - - $scope.$watch('filters', initialize); - }]); - -storefrontApp.controller('recentlyAddedCartItemDialogController', ['$rootScope', '$scope', '$window', '$uibModalInstance', 'mailingService', 'dialogData', 'baseUrl', 'cartService', 'roundHelper', '$filter', 'storeCurrency', function ($rootScope, $scope, $window, $uibModalInstance, mailingService, dialogData, baseUrl, cartService, roundHelper, $filter, storeCurrency) { - $scope.dialogData = dialogData || {}; - $scope.baseUrl = baseUrl; - $scope.regex = new RegExp(/^\/+/); - - $scope.close = function() { - $uibModalInstance.dismiss('cancel'); - } - - $scope.addToCart = function() { - $scope.dialogData.inventoryError = false; - if ($scope.dialogData && $scope.dialogData.items && $scope.dialogData.items.length === 1) { - cartService.addLineItem($scope.dialogData.items[0].id, $scope.dialogData.items[0].quantity).then(() => { - $rootScope.$broadcast('cartItemsChanged'); - }); - } else if ($scope.dialogData.configuredProductId) { - let items = $scope.dialogData.items.map(item => { - return { id: item.id, quantity: $scope.configurationQty, configuredProductId: item.configuredProductId }; - }); - cartService.addLineItems(items).then(response => { - let result = response.data; - if (result.isSuccess) { - $rootScope.$broadcast('cartItemsChanged'); - } - }); - } else { - let items = $scope.dialogData.items.map(item => { - return { id: item.id, quantity: item.quantity }; - }); - cartService.addLineItems(items).then(response => { - let result = response.data; - if (result.isSuccess) { - $rootScope.$broadcast('cartItemsChanged'); - } - }); - } - } - - $scope.calculateTotal = function(itemPrice, itemQuantity) { - var total = roundHelper.bankersRound(itemPrice * itemQuantity); - return $filter('currency')(total, storeCurrency.symbol); - } - - $scope.setInitQuantity = function(item) { - if (item.inventoryError) { - return item.availableQuantity; - } else { - return item.quantity; - } - } - - $scope.getConfirmationTitle = function() { - if ($scope.dialogData && $scope.dialogData.items && $scope.dialogData.items.length === 1) { - return '1 item was added to cart'; - } else { - return `${$scope.dialogData.items.length} items were added to cart`; - } - } - - $scope.quantityChanged = function(qty) { - $scope.configurationQty = qty; - } - - $scope.redirect = function (url) { - $window.location.href = url; - } - - $scope.send = function(email) { - mailingService.sendProduct(dialogData.productId, { email: email, storeId: dialogData.storeId, productUrl: dialogData.productUrl, language: dialogData.language }); - $uibModalInstance.close(); - } - - function getMaxInventory() { - var inventoryArray = $scope.dialogData.items.map(item => { - return item.availableQuantity; - }); - $scope.maxConfigurationQty = Math.min(...inventoryArray); - $scope.configurationQty = $scope.maxConfigurationQty; - } - - function initialize() { - if ($scope.dialogData.inventoryError && $scope.dialogData.configuredProductId) { - getMaxInventory(); - } else if (!$scope.dialogData.inventoryError && $scope.dialogData.configuredProductId) { - $scope.configurationQty = $scope.dialogData.configurationQty; - } - } - - initialize(); - -}]); - -storefrontApp.controller('changeConfigurationGroupItemDialogController', ['$scope', '$window', '$uibModalInstance', 'dialogData', function ($scope, $window, $uibModalInstance, dialogData) { - $scope.dialogData = dialogData || {}; - $scope.selectedId = dialogData.selectedItemId; - - $scope.close = function() { - $uibModalInstance.dismiss('cancel'); - } - - $scope.getModalTitel = function() { - return `Choose ${$scope.dialogData.name}` - } - - $scope.handleRadioClick = function(id) { - $scope.selectedId = id; - } - - $scope.save = function(id) { - $uibModalInstance.close(id); - } -}]); diff --git a/assets/scss/_variables.scss b/assets/scss/_variables.scss index 58d732e5..aa1022d9 100644 --- a/assets/scss/_variables.scss +++ b/assets/scss/_variables.scss @@ -523,6 +523,7 @@ $nav-link-padding: $padding-base-vertical $padding-base-horizontal; // 10px 15px // Migrating_To_Bootstrap4: DONE, not used in theme $nav-large-link-padding: $padding-large-vertical $padding-large-horizontal; // not predefined // Migrating_To_Bootstrap4: DONE, not used in theme $nav-small-link-padding: $padding-small-vertical $padding-small-horizontal; // not predefined // Migrating_To_Bootstrap4: ?? (not present in bs4) + $nav-outline-border-radius: $border-radius-base; //not predefined // $nav-link-hover-bg: $gray-lighter // $nav-disabled-link-color: $gray-light diff --git a/assets/scss/bootstrap-migration/_custom.scss b/assets/scss/bootstrap-migration/_custom.scss index 26bacf5b..25c47671 100644 --- a/assets/scss/bootstrap-migration/_custom.scss +++ b/assets/scss/bootstrap-migration/_custom.scss @@ -1,2 +1,5 @@ +@import "custom/backgrounds"; @import "custom/popover"; @import "custom/navbar"; +@import "custom/sizing"; +@import "custom/buttons"; diff --git a/assets/scss/bootstrap-migration/_default-variables.scss b/assets/scss/bootstrap-migration/_default-variables.scss index 9ce20336..35153bfe 100644 --- a/assets/scss/bootstrap-migration/_default-variables.scss +++ b/assets/scss/bootstrap-migration/_default-variables.scss @@ -15,6 +15,9 @@ $container-max-widths: ( xl: 1140px, ); +$spacer: 1rem; +$spacers: (); + $font-weight-bold: 700; $white: #fff; $body-bg: $white; diff --git a/assets/scss/bootstrap-migration/_helpers.scss b/assets/scss/bootstrap-migration/_helpers.scss new file mode 100644 index 00000000..2642d5dd --- /dev/null +++ b/assets/scss/bootstrap-migration/_helpers.scss @@ -0,0 +1,15 @@ +.t-0 { + top: 0; +} + +.l-0 { + left: 0; +} + +.r-0 { + right: 0; +} + +.b-0 { + bottom: 0; +} diff --git a/assets/scss/bootstrap-migration/_maps.scss b/assets/scss/bootstrap-migration/_maps.scss index 41e518ad..0f71b109 100644 --- a/assets/scss/bootstrap-migration/_maps.scss +++ b/assets/scss/bootstrap-migration/_maps.scss @@ -19,3 +19,12 @@ $container-max-widths: map-merge( xxl: 1336px, ) ); + +$spacers: map-merge( + $spacers, + ( + 5: ($spacer * 2), + 6: ($spacer * 3) + ) +); + diff --git a/assets/scss/bootstrap-migration/_modules.scss b/assets/scss/bootstrap-migration/_modules.scss new file mode 100644 index 00000000..89c9f228 --- /dev/null +++ b/assets/scss/bootstrap-migration/_modules.scss @@ -0,0 +1 @@ +@import "modules/loader"; diff --git a/assets/scss/bootstrap-migration/_variables.scss b/assets/scss/bootstrap-migration/_variables.scss index 81850e59..e4bfafe3 100644 --- a/assets/scss/bootstrap-migration/_variables.scss +++ b/assets/scss/bootstrap-migration/_variables.scss @@ -63,3 +63,17 @@ $card-border-color: $gray-300; $card-cap-color: $black; $card-spacer-x: 0.938rem; $popover-header-padding-x: 1rem; +$table-striped-order: even; +$table-dark-bg: $dark; +$breadcrumb-margin-bottom: 0; +$custom-control-indicator-checked-bg: $secondary; +$custom-control-indicator-checked-border-color: $secondary; +$custom-control-indicator-border-width: 2px; +$custom-control-indicator-border-color: $gray-400; +$custom-control-indicator-size: 1.2rem; +$custom-control-indicator-focus-box-shadow: $secondary; +$custom-control-cursor: pointer; +$custom-control-indicator-bg-size: 45% 35%; +$spinner-width: 3.75rem; +$spinner-height: 3.75rem; +$spinner-border-width: 0.375em; diff --git a/assets/scss/bootstrap-migration/custom/_backgrounds.scss b/assets/scss/bootstrap-migration/custom/_backgrounds.scss new file mode 100644 index 00000000..2c1bdf2c --- /dev/null +++ b/assets/scss/bootstrap-migration/custom/_backgrounds.scss @@ -0,0 +1,6 @@ +//Last argument in bg-variant is set to 'true' to prevent warning about bg-variant being deprecated +//The official @mixin for bg-variant and bg-gradient-variant in bootstrap 4.5.0 is now @mixin bg-variant($parent, $color, $ignore-warning: false) +//But in official docs this mixin is still presented and there's no alternatives right now. +@each $color, $value in $theme-colors { + @include bg-variant('.bg-#{$color}-semitransparent', rgba($value, 0.5), true); +} diff --git a/assets/scss/bootstrap-migration/custom/_buttons.scss b/assets/scss/bootstrap-migration/custom/_buttons.scss new file mode 100644 index 00000000..b465bf4f --- /dev/null +++ b/assets/scss/bootstrap-migration/custom/_buttons.scss @@ -0,0 +1,15 @@ +.btn { + &.disabled, + &[disabled], + fieldset[disabled] & { + &, + &:hover, + &:focus, + &.focus { + background-color: $gray-200; + border-color: $gray-500; + color: $text-muted; + cursor: default; + } + } +} diff --git a/assets/scss/bootstrap-migration/custom/_sizing.scss b/assets/scss/bootstrap-migration/custom/_sizing.scss new file mode 100644 index 00000000..ad9238f4 --- /dev/null +++ b/assets/scss/bootstrap-migration/custom/_sizing.scss @@ -0,0 +1,7 @@ +@each $breakpoint in map-keys($grid-breakpoints) { + @each $size, $length in $sizes { + @include media-breakpoint-up($breakpoint) { + .w-#{$breakpoint}-#{$size} {width: $length !important;} + } + } +} diff --git a/assets/scss/bootstrap-migration/main.scss b/assets/scss/bootstrap-migration/main.scss index f3f993fa..a24d8308 100644 --- a/assets/scss/bootstrap-migration/main.scss +++ b/assets/scss/bootstrap-migration/main.scss @@ -4,4 +4,6 @@ @import "maps"; @import "bootstrap/scss/bootstrap"; @import "override"; +@import "helpers"; @import "custom"; +@import "modules"; diff --git a/assets/scss/bootstrap-migration/modules/_loader.scss b/assets/scss/bootstrap-migration/modules/_loader.scss new file mode 100644 index 00000000..4d80face --- /dev/null +++ b/assets/scss/bootstrap-migration/modules/_loader.scss @@ -0,0 +1,4 @@ +.loader { + z-index: 5000; +} + diff --git a/assets/scss/bootstrap-migration/override/_scaffolding.scss b/assets/scss/bootstrap-migration/override/_scaffolding.scss index 25360b80..2ba9f856 100644 --- a/assets/scss/bootstrap-migration/override/_scaffolding.scss +++ b/assets/scss/bootstrap-migration/override/_scaffolding.scss @@ -3,5 +3,6 @@ a { &.btn.btn-link { font-family: $font-family-sans-serif; font-weight: $link-font-weight; + cursor: pointer; } } diff --git a/assets/scss/custom/_navs.scss b/assets/scss/custom/_navs.scss index 248de580..c1681bdb 100644 --- a/assets/scss/custom/_navs.scss +++ b/assets/scss/custom/_navs.scss @@ -1,91 +1,112 @@ .nav-sm { - > li > a { - padding: $nav-small-link-padding; - } + > li > a { + padding: $nav-small-link-padding; + } } .nav-lg { - > li > a { - padding: $nav-large-link-padding; - } + > li > a { + padding: $nav-large-link-padding; + } } .nav-pills { - > li > a { - color: $text-color; - font-weight: $btn-font-weight; - font-family: $font-family-condensed; - } + > li > a { + color: $text-color; + font-weight: $btn-font-weight; + font-family: $font-family-condensed; + } } .left-nav li a { - font-weight: $link-font-weight; + font-weight: $link-font-weight; } .nav-stacked > li > a:focus, .nav-stacked > li > a:hover { - background-color: $body-bg; - color: $brand-primary; - //border-left: 3px $brand-primary solid; + background-color: $body-bg; + color: $brand-primary; + //border-left: 3px $brand-primary solid; } - .left-nav > li > a:hover, .left-nav > li > a:focus { - background: $gray-lighter; - border: 0 !important; - color: $text-color; + background: $gray-lighter; + border: 0 !important; + color: $text-color; } -.left-nav > li.active > a, .left-nav > li.active:hover > a, .left-nav > li.active:focus > a { - background-color: $gray-lighter !important; - border-left: 3px $brand-primary solid !important; - color: $text-color !important; - font-weight: bold; - padding-left: 12px; +.left-nav > li.active > a, +.left-nav > li.active:hover > a, +.left-nav > li.active:focus > a { + background-color: $gray-lighter !important; + border-left: 3px $brand-primary solid !important; + color: $text-color !important; + font-weight: bold; + padding-left: 12px; } .nav-pills-transparent li:first-child { - margin-left: 18px; + margin-left: 18px; } .nav-pills-transparent > li + li { - margin-left: 20px; + margin-left: 20px; } .nav-pills-transparent > li > a { - color: $brand-alt; - border-left: none; - padding-left: 0; - padding-right: 0; - &:focus, - &:hover { - background-color: $body-bg; - color: $text-color; - } + color: $brand-alt; + border-left: none; + padding-left: 0; + padding-right: 0; + &:focus, + &:hover { + background-color: $body-bg; + color: $text-color; + } } .nav-pills-transparent > li.active > a, .nav-pills-transparent > li.active > a:focus, .nav-pills-transparent > li.active > a:hover { - border-bottom: 2px $brand-primary solid; - background-color: $body-bg; - color: $text-color; + border-bottom: 2px $brand-primary solid; + background-color: $body-bg; + color: $text-color; } .pagination { - margin: 0; + margin: 0; } -.pagination li a, .pagination li { +.pagination li a, +.pagination li { font-weight: $btn-font-weight; font-family: $font-family-condensed; } .coll-top-nav { - width: 102.6%; + width: 102.6%; +} + +.view-switcher { + margin-right: 15px; } -.view-switcher{ - margin-right: 15px; -} \ No newline at end of file +.nav-outline { + > li { + float: left; + > a { + border-radius: $nav-outline-border-radius; + } + &.active { + > a { + color: $brand-primary; + border: 1px solid $brand-primary !important; + &:hover, + &:focus { + background-color: $body-bg; + } + } + } + } +} diff --git a/assets/scss/custom/_scaffolding.scss b/assets/scss/custom/_scaffolding.scss index 3c310463..dc9d7998 100644 --- a/assets/scss/custom/_scaffolding.scss +++ b/assets/scss/custom/_scaffolding.scss @@ -41,4 +41,4 @@ a.primary-link { .panel-heading .col-md-3{ text-align: right; -} \ No newline at end of file +} diff --git a/config/blocks_schema.json b/config/blocks_schema.json index f09f0261..a24795aa 100644 --- a/config/blocks_schema.json +++ b/config/blocks_schema.json @@ -227,50 +227,22 @@ "type": "url", "urlLabel": "Url", "textLabel": "Button text", - "styleLabel": "Link style", + "styleLabel": "Color", "sort": 100, "styles": [ { - "value": "btn-primary", - "label": "Primary button" + "value": "primary", + "label": "Primary" }, { - "value": "btn-secondary", - "label": "Secondary button" - }, - { - "value": "btn-success", - "label": "Success button" - }, - { - "value": "btn-danger", - "label": "Danger button" - }, - { - "value": "btn-warning", - "label": "Warning button" - }, - { - "value": "btn-info", - "label": "Info button" - }, - { - "value": "btn-light", - "label": "Light button" - }, - { - "value": "btn-dark", - "label": "Dark button" - }, - { - "value": "btn-link", - "label": "Link button" + "value": "secondary", + "label": "Secondary" } ], "default": { "url": "", "urlText": "", - "style": "btn-primary" + "style": "primary" }, "group": "Buttons" }, @@ -280,51 +252,57 @@ "type": "url", "urlLabel": "Url", "textLabel": "Button text", - "styleLabel": "Link style", + "styleLabel": "Color", "sort": 101, "styles": [ { - "value": "btn-primary", - "label": "Primary button" - }, - { - "value": "btn-secondary", - "label": "Secondary button" - }, - { - "value": "btn-success", - "label": "Success button" + "value": "primary", + "label": "Primary" }, { - "value": "btn-danger", - "label": "Danger button" - }, - { - "value": "btn-warning", - "label": "Warning button" - }, + "value": "secondary", + "label": "Secondary" + } + ], + "default": { + "url": "", + "urlText": "", + "style": "secondary" + }, + "group": "Buttons" + }, + { + "id": "firstButtonStyle", + "label": "First button style", + "type":"select", + "default": "outline-", + "options": [ { - "value": "btn-info", - "label": "Info button" + "label": "Solid", + "value": null }, { - "value": "btn-light", - "label": "Light button" - }, + "label": "Outline", + "value": "outline-" + } + ], + "group": "Buttons" + }, + { + "id": "secondButtonStyle", + "label": "Second button style", + "type":"select", + "default": null, + "options": [ { - "value": "btn-dark", - "label": "Dark button" + "label": "Solid", + "value": null }, { - "value": "btn-link", - "label": "Link button" + "label": "Outline", + "value": "outline-" } ], - "default": { - "url": "", - "urlText": "", - "style": "btn-secondary" - }, "group": "Buttons" } ], @@ -656,10 +634,10 @@ "sort": 310 } ], - "margins": [ + "paddings": [ { "id": "noTop", - "label": "Remove top margin", + "label": "Remove top padding", "type": "checkbox", "tab": "Settings", "sort": 235, @@ -667,13 +645,59 @@ }, { "id": "noBottom", - "label": "Remove bottom margin", + "label": "Remove bottom padding", "type": "checkbox", "tab": "Settings", "sort": 236, "default": false } ], + "top/bottom-margins": [ + { + "id": "marginTop", + "label": "Margin top", + "type": "string", + "tab": "Settings", + "sort": 284, + "default": "0" + }, + { + "id": "marginBottom", + "label": "Margin bottom", + "type": "string", + "tab": "Settings", + "sort": 285, + "default": "0" + } + ], + "top/bottom-paddings": [ + { + "id": "paddingTop", + "label": "Padding top", + "type": "string", + "tab": "Settings", + "sort": 286, + "default": "48" + }, + { + "id": "paddingBottom", + "label": "Padding bottom", + "type": "string", + "tab": "Settings", + "sort": 287, + "default": "48" + } + ], + "full-width-option": [ + { + "id": "fullWidth", + "label": "Full width", + "type": "checkbox", + "tab": "Settings", + "sort": 39, + "default": false + } + ], "colors": [ { "id": "backgroundColor", @@ -710,7 +734,7 @@ "icon": "image-text", "displayField": "name", "category": "Covers and Hero", - "includeShared": [ "cover-items", "notes", "buttons" ], + "includeShared": [ "cover-items", "notes", "buttons", "top/bottom-margins", "top/bottom-paddings", "full-width-option" ], "excludeShared": [], "default": { "background": { @@ -719,7 +743,7 @@ "firstButton": { "url": "", "urlText": "Learn more", - "style": "btn-dark" + "style": "primary" }, "name": "Cover with image" }, @@ -751,6 +775,44 @@ "label": "Right" } ] + }, + { + "id": "criteria", + "label": "Criteria", + "tab": "Settings", + "sort": 281, + "type": "select", + "default": "none", + "options": [ + { + "value": "none", + "label": "None" + }, + { + "value": "url", + "label": "URL parameter" + }, + { + "value": "userGroup", + "label": "User group" + } + ] + }, + { + "id": "criteriaValue", + "label": "Criteria value", + "type": "string", + "sort": 282, + "tab": "Settings" + }, + { + "id": "hideOnMatch", + "label": "Hide on match", + "type": "checkbox", + "default": false, + "tab": "Settings", + "info": "When checked then block will be hidden when criteria matches, when unchecked block will be show only when criteria matches", + "sort": 283 } ] }, @@ -824,7 +886,7 @@ "firstButton": { "url": "", "urlText": "Learn why", - "style": "btn-warning" + "style": "primary" }, "titleColor": "#ffffff", "subtitleColor": "#c4c4c4", @@ -881,7 +943,7 @@ "icon": "text", "displayField": "name", "category": "Headlines and Forms", - "includeShared": [ "notes", "cover-items", "buttons", "margins", "text-width" ], + "includeShared": [ "notes", "cover-items", "buttons", "paddings", "text-width" ], "excludeShared": [ "textColumnWidth", "secondColumnWidth" ], "default": { "title": "How to write headlines that actually work?", @@ -899,7 +961,7 @@ "icon": "text", "displayField": "name", "category": "Headlines and Forms", - "includeShared": [ "notes", "cover-items", "margins", "form", "text-width" ], + "includeShared": [ "notes", "cover-items", "paddings", "form", "text-width" ], "excludeShared": [ "textColumnWidth", "secondColumnWidth" ], "default": { "title": "Subscribe to our promotions", @@ -966,7 +1028,7 @@ "icon": "text", "displayField": "name", "category": "Paragraphs and Links", - "includeShared": [ "text-width", "margins", "colors" ], + "includeShared": [ "text-width", "paddings", "colors" ], "excludeShared": [], "default": { "textAreaWidth": "col-md-12", @@ -993,7 +1055,7 @@ "icon": "image-text", "displayField": "name", "category": "Media and Logotypes", - "includeShared": [ "text-width", "margins", "colors" ], + "includeShared": [ "text-width", "paddings", "colors" ], "excludeShared": [], "default": { "titleColor": "#000000", @@ -1080,7 +1142,7 @@ "icon": "image-text", "displayField": "title", "category": "Features and Cards", - "includeShared": [ "text-width", "colors", "margins" ], + "includeShared": [ "text-width", "colors", "paddings" ], "default": { "backgroundColor": "#efefef", "name": "Features with icons" @@ -1277,7 +1339,7 @@ "default": { "url": "", "urlText": "Get my seat reserved", - "style": "btn-warning" + "style": "primary" } }, { @@ -1305,7 +1367,7 @@ "icon": "text", "displayField": "name", "category": "Queries and Others", - "includeShared": [ "utm-marks", "margins", "colors" ], + "includeShared": [ "utm-marks", "paddings", "colors" ], "excludeShared": [], "default": { "headerType": "like-h1", @@ -1469,7 +1531,7 @@ "icon": "text", "displayField": "name", "category": "Queries and Others", - "includeShared": [ "utm-marks", "margins", "colors" ], + "includeShared": [ "utm-marks", "paddings", "colors" ], "default": { "name": "Category promotion" }, diff --git a/package-lock.json b/package-lock.json index ad5cc565..e2139be3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vc-demo-theme-b2b", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 68c6f379..28137ec7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.6.0", + "version": "1.7.0", "name": "vc-demo-theme-b2b", "author": "VirtoCommerce", "description": "B2B theme for Storefront", diff --git a/snippets/bootstrap-migration/customers/login-form.liquid b/snippets/bootstrap-migration/customers/login-form.liquid index 93cc3323..789fa062 100644 --- a/snippets/bootstrap-migration/customers/login-form.liquid +++ b/snippets/bootstrap-migration/customers/login-form.liquid @@ -27,9 +27,10 @@
{% else %}
+ {% endif %} - {% if template != 'customers/login' %} +
{% endif %} {% if template != 'customers/login' %} diff --git a/snippets/bootstrap-migration/dashboard/bulk-order-content.liquid b/snippets/bootstrap-migration/dashboard/bulk-order-content.liquid index e4d74148..82af7d21 100644 --- a/snippets/bootstrap-migration/dashboard/bulk-order-content.liquid +++ b/snippets/bootstrap-migration/dashboard/bulk-order-content.liquid @@ -9,7 +9,7 @@
-
+
{% assign column_count = 1 %} {% assign rows_count = 6 %} diff --git a/snippets/bootstrap-migration/shared/breadcrumb.liquid b/snippets/bootstrap-migration/shared/breadcrumb.liquid new file mode 100644 index 00000000..bfc66a24 --- /dev/null +++ b/snippets/bootstrap-migration/shared/breadcrumb.liquid @@ -0,0 +1,89 @@ +{% unless template == 'index' or template == 'cart' %} + +{% endunless %} diff --git a/snippets/bootstrap-migration/shared/bulk-order-fields.liquid b/snippets/bootstrap-migration/shared/bulk-order-fields.liquid index b38bd5f0..c8a3d323 100644 --- a/snippets/bootstrap-migration/shared/bulk-order-fields.liquid +++ b/snippets/bootstrap-migration/shared/bulk-order-fields.liquid @@ -1,10 +1,10 @@ 
{% assign end_col_index = column_count | minus: 1 %} {% for col_index in (0..end_col_index) %} -
+
-
+
{% endfor %} @@ -15,10 +15,10 @@ {% assign end_col_index = column_count | minus: 1 %} {% for col_index in (0..end_col_index) %} {% assign item_index = i | plus: tens | minus: 1 %} -
+
-
+
{% endfor %} diff --git a/snippets/dashboard/bulk-order-content.liquid b/snippets/dashboard/bulk-order-content.liquid index d49c8a94..2605a6b6 100644 --- a/snippets/dashboard/bulk-order-content.liquid +++ b/snippets/dashboard/bulk-order-content.liquid @@ -14,7 +14,7 @@
-
+
{% assign column_count = 1 %} {% assign rows_count = 6 %} diff --git a/snippets/product/grid-item.liquid b/snippets/product/grid-item.liquid index 24504e56..817fe448 100644 --- a/snippets/product/grid-item.liquid +++ b/snippets/product/grid-item.liquid @@ -15,19 +15,22 @@ {% assign unavailable = true %} {% endif %} -
+
{% include 'shared/item-response-group' %} {% include 'product/item/image' %} {% include 'product/compare' %} {% include 'product/item/title-and-codes' %} - {% comment %} -
- {% include 'product/price' %} - {% include 'product/configurable' %} -
- {% endcomment %} - {% include 'product/price' %} - {% include 'product/quantity-grid' %} + + {% if product.product_type == "Configurable" %} + {% include 'product/type/configured/item-price' %} + {% include 'product/type/configured/item-configure-button' %} + {% else %} + + {% include 'product/price' %} + {% include 'product/quantity' %} + + {% endif %} +
{% include 'product/item/script' %} diff --git a/snippets/product/main.liquid b/snippets/product/main.liquid deleted file mode 100644 index 1df35f58..00000000 --- a/snippets/product/main.liquid +++ /dev/null @@ -1,180 +0,0 @@ -
- -
-
- - - -
-
- -

{{ product.title }}

-
    -
  • - {{ 'products.product.sku' | t }} {{ product.sku }} -
  • -
  • - {{ 'products.product.mmn' | t }} {{ product.properties['MMN'].value }} -
  • -
  • - UNSPSC #41112701 -
  • -
-
-
-
-
- {% include 'product/image' %} - {% include 'product/compare' %} - {% include 'product/product-compare-list-bar' %} -
- -
- {% if product.properties.size > 0 %} -
-
-
-
- Technical Specs -
-
-
-
- - {% for property in product.properties %} - {% assign column_count = 1 %} - {% include 'shared/grid/rows' %} - {% if should_start_row %} - - {% endif %} - - - {% if should_end_row %} - - {% endif %} - {% endfor %} -
{{ property.name }}{{ property.value }}
-
-
-
- {% for description in product.descriptions %} - {% if description.type == "FullReview" %} - {{ description.content }} - {% endif %} - {% endfor %} -
- {% endif %} - {% include 'product/variations-panel' %} - {% include 'product/product-configuration-list' %} -
- -
- -
-
-
-
- Price & delivery -
-
-
-
-
- {% if product.product_type == "Configurable" %} -
-
- - Default price - -
- -
- - - -
- -
- - Custom changes - -
- -
- - - -
- -
- -
- - Total - -
- -
- - - -
-
- {% else %} - {% assign product = product %} - {% include 'product/price' %} - {% endif %} -
- -
-
-

Expected to arrive:

-

Available for pickup:

- -
- {% include 'product/quantity' %} -
-
-
-
-
    -
  • - -
  • -
  • - Email -
  • -
  • - {% include 'shared/print' %} -
  • -
-
-
- -
-
- -
-
- -
-
-
-

{{ 'products.general.related_products' | t }}

-
-
- -
-
-
- -
- -
-
-
diff --git a/snippets/product/price.liquid b/snippets/product/price.liquid index 7a27efe2..37793786 100644 --- a/snippets/product/price.liquid +++ b/snippets/product/price.liquid @@ -12,9 +12,6 @@
- {% if product.product_type == "Configurable" %} - - {% else %} {% if settings.show_prices_with_taxes %} {% assign price = product.price_with_tax %} {% include 'product/price/static' %} @@ -26,9 +23,8 @@ {% assign price_name = 'actualPrice' %} {% include 'product/price/dynamic' %} {% endif %} - {% endif %} / each
- + diff --git a/snippets/product/quantity-grid.liquid b/snippets/product/quantity-grid.liquid deleted file mode 100644 index 2cf1428b..00000000 --- a/snippets/product/quantity-grid.liquid +++ /dev/null @@ -1,42 +0,0 @@ -{% if product.product_type == "Configurable" %} - - - -{% else %} - {% if show_label %} - - {% endif %} -
- - - - -
-{% endif %} diff --git a/snippets/product/quantity.liquid b/snippets/product/quantity.liquid index 49bd3f0b..40674d48 100644 --- a/snippets/product/quantity.liquid +++ b/snippets/product/quantity.liquid @@ -4,30 +4,22 @@
+ >
diff --git a/snippets/product/type/common/product-action-buttons.liquid b/snippets/product/type/common/product-action-buttons.liquid new file mode 100644 index 00000000..9a59160b --- /dev/null +++ b/snippets/product/type/common/product-action-buttons.liquid @@ -0,0 +1,13 @@ +
+
    +
  • + +
  • +
  • + Email +
  • +
  • + {% include 'shared/print' %} +
  • +
+
diff --git a/snippets/product/type/common/product-delivery.liquid b/snippets/product/type/common/product-delivery.liquid new file mode 100644 index 00000000..e3f6a83e --- /dev/null +++ b/snippets/product/type/common/product-delivery.liquid @@ -0,0 +1,16 @@ +
+
+

Expected to arrive:

+

Available for pickup:

+ +
+ {% if product.product_type == "Configurable" %} + {% include 'product/type/configured/quantity' %} + {% else %} + + {% include 'product/quantity' %} + + {% endif %} +
+
+
diff --git a/snippets/product/type/common/product-description.liquid b/snippets/product/type/common/product-description.liquid new file mode 100644 index 00000000..f87ace24 --- /dev/null +++ b/snippets/product/type/common/product-description.liquid @@ -0,0 +1,7 @@ +
+ {% for description in product.descriptions %} + {% if description.type == "FullReview" %} + {{ description.content }} + {% endif %} + {% endfor %} +
diff --git a/snippets/product/type/common/product-properties.liquid b/snippets/product/type/common/product-properties.liquid new file mode 100644 index 00000000..f2f32740 --- /dev/null +++ b/snippets/product/type/common/product-properties.liquid @@ -0,0 +1,25 @@ +
+
+
+
+ Technical Specs +
+
+
+
+ + {% for property in product.properties %} + {% assign column_count = 1 %} + {% include 'shared/grid/rows' %} + {% if should_start_row %} + + {% endif %} + + + {% if should_end_row %} + + {% endif %} + {% endfor %} +
{{ property.name }}{{ property.value }}
+
+
diff --git a/snippets/product/type/common/product-title-info.liquid b/snippets/product/type/common/product-title-info.liquid new file mode 100644 index 00000000..b13bba4e --- /dev/null +++ b/snippets/product/type/common/product-title-info.liquid @@ -0,0 +1,16 @@ +
+
+

{{ product.title }}

+
    +
  • + {{ 'products.product.sku' | t }} {{ product.sku }} +
  • +
  • + {{ 'products.product.mmn' | t }} {{ product.properties['MMN'].value }} +
  • +
  • + UNSPSC #41112701 +
  • +
+
+
diff --git a/snippets/product/type/common/related-products.liquid b/snippets/product/type/common/related-products.liquid new file mode 100644 index 00000000..2681b821 --- /dev/null +++ b/snippets/product/type/common/related-products.liquid @@ -0,0 +1,10 @@ +
+
+
+

{{ 'products.general.related_products' | t }}

+
+
+ +
+
+
diff --git a/snippets/product/type/configured/item-configure-button.liquid b/snippets/product/type/configured/item-configure-button.liquid new file mode 100644 index 00000000..be31997d --- /dev/null +++ b/snippets/product/type/configured/item-configure-button.liquid @@ -0,0 +1,14 @@ + + + diff --git a/snippets/product/type/configured/item-price.liquid b/snippets/product/type/configured/item-price.liquid new file mode 100644 index 00000000..d866b5b9 --- /dev/null +++ b/snippets/product/type/configured/item-price.liquid @@ -0,0 +1,20 @@ + +
+
+ + {% if customer %} + {{ 'products.price.private' | t }} + {% else %} + {{ 'products.price.public' | t }} + {% endif %} + +
+ +
+ + + + / each + +
+
diff --git a/snippets/product/type/configured/product.liquid b/snippets/product/type/configured/product.liquid new file mode 100644 index 00000000..2ce26358 --- /dev/null +++ b/snippets/product/type/configured/product.liquid @@ -0,0 +1,84 @@ +{% include 'product/type/common/product-title-info' %} +
+
+ {% include 'product/image' %} + {% include 'product/compare' %} + {% include 'product/product-compare-list-bar' %} +
+ +
+ {% if product.properties.size > 0 %} + {% include 'product/type/common/product-properties' %} + {% include 'product/type/common/product-description' %} + {% endif %} + {% include 'product/product-configuration-list' %} +
+ +
+ +
+
+
+
+ Price & delivery +
+
+
+
+
+ +
+
+ + Default price + +
+ +
+ + + +
+ +
+ + Custom changes + +
+ +
+ + + +
+ +
+ +
+ + Total + +
+ +
+ + + +
+
+ +
+ + {% include 'product/type/common/product-delivery' %} + {% include 'product/type/common/product-action-buttons' %} + +
+ +
+
+
+
+ + {% include 'product/type/common/related-products' %} + +
diff --git a/snippets/product/type/configured/quantity.liquid b/snippets/product/type/configured/quantity.liquid new file mode 100644 index 00000000..52193327 --- /dev/null +++ b/snippets/product/type/configured/quantity.liquid @@ -0,0 +1,25 @@ +{% if show_label %} + +{% endif %} +
+ + + + +
diff --git a/snippets/product/type/with-variations/product.liquid b/snippets/product/type/with-variations/product.liquid new file mode 100644 index 00000000..e9121993 --- /dev/null +++ b/snippets/product/type/with-variations/product.liquid @@ -0,0 +1,44 @@ +{% include 'product/type/common/product-title-info' %} +
+
+ {% include 'product/image' %} + {% include 'product/compare' %} + {% include 'product/product-compare-list-bar' %} +
+ +
+ {% if product.properties.size > 0 %} + {% include 'product/type/common/product-properties' %} + {% include 'product/type/common/product-description' %} + {% endif %} + {% include 'product/variations-panel' %} +
+ +
+
+
+
+
+ Price & delivery +
+
+
+
+
+ {% assign product = product %} + {% include 'product/price' %} +
+ + {% include 'product/type/common/product-delivery' %} + {% include 'product/type/common/product-action-buttons' %} + +
+ +
+
+
+
+ + {% include 'product/type/common/related-products' %} + +
diff --git a/snippets/product/type/without-variations/product.liquid b/snippets/product/type/without-variations/product.liquid new file mode 100644 index 00000000..73049e50 --- /dev/null +++ b/snippets/product/type/without-variations/product.liquid @@ -0,0 +1,44 @@ +{% include 'product/type/common/product-title-info' %} +
+
+ {% include 'product/image' %} + {% include 'product/compare' %} + {% include 'product/product-compare-list-bar' %} +
+ +
+ {% if product.properties.size > 0 %} + {% include 'product/type/common/product-properties' %} + {% include 'product/type/common/product-description' %} + {% endif %} +
+ +
+ +
+
+
+
+ Price & delivery +
+
+
+
+
+ {% assign product = product %} + {% include 'product/price' %} +
+ + {% include 'product/type/common/product-delivery' %} + {% include 'product/type/common/product-action-buttons' %} + +
+ +
+
+
+
+ + {% include 'product/type/common/related-products' %} + +
diff --git a/snippets/recommendations.liquid b/snippets/recommendations.liquid index e3b01b92..1b68c510 100644 --- a/snippets/recommendations.liquid +++ b/snippets/recommendations.liquid @@ -22,7 +22,7 @@
- @@ -60,4 +60,4 @@
- \ No newline at end of file + diff --git a/templates/404.liquid b/templates/404.liquid index 91f3dadc..164d5e13 100644 --- a/templates/404.liquid +++ b/templates/404.liquid @@ -1,12 +1,9 @@ -{% include 'shared/breadcrumb' %} - -
- -
+{% layout 'bootstrap_migration' %} +{% include 'bootstrap-migration/shared/breadcrumb' %} +
+

{{ 'general.error404.title' | t }}

{{ 'general.error404.subtext_html' | t }}

-
-
diff --git a/templates/blocks/helpers/block-inner-paddings.liquid b/templates/blocks/helpers/block-inner-paddings.liquid new file mode 100644 index 00000000..e0609adf --- /dev/null +++ b/templates/blocks/helpers/block-inner-paddings.liquid @@ -0,0 +1 @@ +padding-top: {{ block.paddingTop }}px;padding-bottom: {{ block.paddingBottom }}px; diff --git a/templates/blocks/helpers/block-margins.liquid b/templates/blocks/helpers/block-margins.liquid new file mode 100644 index 00000000..e928917b --- /dev/null +++ b/templates/blocks/helpers/block-margins.liquid @@ -0,0 +1 @@ +margin-top: {{ block.marginTop }}px;margin-bottom: {{ block.marginBottom }}px; diff --git a/templates/blocks/helpers/block-paddings.liquid b/templates/blocks/helpers/block-paddings.liquid index 26171ace..9c8772ae 100644 --- a/templates/blocks/helpers/block-paddings.liquid +++ b/templates/blocks/helpers/block-paddings.liquid @@ -1,2 +1,2 @@ -{% if block.noTop != 'True' %} pt-5 {% endif %} -{% if block.noBottom != 'True' %} pb-5 {% endif %} +{% if block.noTop != 'True' %} pt-6 {% endif %} +{% if block.noBottom != 'True' %} pb-6 {% endif %} diff --git a/templates/blocks/helpers/block-title.liquid b/templates/blocks/helpers/block-title.liquid index f0199500..58337ad9 100644 --- a/templates/blocks/helpers/block-title.liquid +++ b/templates/blocks/helpers/block-title.liquid @@ -6,7 +6,7 @@ {% assign classClause = '' %} {% if titleStyle %} - {% assign classClause = 'class="'|append titleStyle|append '"' %} + {% assign classClause = 'class="text-helvetica '|append titleStyle|append '"' %} {% endif %} {% if givenTitle != "" %} @@ -17,11 +17,11 @@ {% elsif block.headerType == 'h3' %}

{{ givenTitle }}

{% elsif block.headerType == 'like-h1' %} - + {% elsif block.headerType == 'like-h3' %} - + {% else %} - + {% endif %} {% endif %} {% assign givenTitle = null %} diff --git a/templates/blocks/helpers/cover-text.liquid b/templates/blocks/helpers/cover-text.liquid index 55d8222e..7f6d5adf 100644 --- a/templates/blocks/helpers/cover-text.liquid +++ b/templates/blocks/helpers/cover-text.liquid @@ -1,4 +1,4 @@ -
+
{% if block.note %}
{{ block.note }}
{% endif %} @@ -8,17 +8,17 @@ {% endif %} {% if block.subtitle %} -
{{ block.subtitle }}
- +
{{ block.subtitle }}
+ {% endif %} - + {% if (block.firstButton and block.firstButton.urlText) or (block.secondButton and block.secondButton.urlText) %}
{% if block.firstButton and block.firstButton.urlText and block.firstButton.urlText != '' %} - {{block.firstButton.urlText}} + {{block.firstButton.urlText}} {% endif %} {% if block.secondButton and block.secondButton.urlText and block.secondButton.urlText != '' %} - {{block.secondButton.urlText}} + {{block.secondButton.urlText}} {% endif %}
{% endif %} diff --git a/templates/blocks/helpers/hide-criteria.liquid b/templates/blocks/helpers/hide-criteria.liquid new file mode 100644 index 00000000..c1277c3e --- /dev/null +++ b/templates/blocks/helpers/hide-criteria.liquid @@ -0,0 +1,27 @@ +{% assign hideBlock = true %} +{% if block.criteria == 'url' %} + {% if request_url contains block.criteriaValue.value %} + {% assign hideBlock = false %} + {% endif %} +{% elsif block.criteria == 'userGroup' and current_user and current_user.contact %} + {% assign variantGroups = block.criteriaValue | string.split ',' %} + {% assign allEquals = true %} + {% for variantGroup in variantGroups %} + {% unless current_user.contact.user_groups contains variantGroup %} + {% assign allEquals = false %} + {% endunless %} + {% endfor %} + {% if allEquals %} + {% assign hideBlock = false %} + {% endif %} +{% elsif block.criteria == 'none' %} + {% assign hideBlock = false %} +{% endif %} + +{% if block.criteria != 'none' and block.hideOnMatch == 'True' %} + {% if hideBlock == false %} + {% assign hideBlock = true %} + {% elsif hideBlock == true %} + {% assign hideBlock = false %} + {% endif %} +{% endif %} diff --git a/templates/blocks/json-buy-now-search.liquid b/templates/blocks/json-buy-now-search.liquid index 862b8c4b..2c5b4c41 100644 --- a/templates/blocks/json-buy-now-search.liquid +++ b/templates/blocks/json-buy-now-search.liquid @@ -17,12 +17,12 @@
{% assign product = block.product %} -
+
{% include 'blocks/helpers/block-title' givenTitle: product.name %}
{% if product %} {% if block.hidePrice != 'True' %} -
+
@@ -32,7 +32,7 @@
{% endif %} -
+
diff --git a/templates/blocks/json-buy-now.liquid b/templates/blocks/json-buy-now.liquid index 6a50c9e2..09e4b4da 100644 --- a/templates/blocks/json-buy-now.liquid +++ b/templates/blocks/json-buy-now.liquid @@ -20,12 +20,12 @@
{% assign product = block.product %} -
+
{% include 'blocks/helpers/block-title' givenTitle: product.name %}
{% if product %} {% if block.hidePrice != 'True' %} -
+
@@ -35,11 +35,11 @@
{% endif %} -
+
-
+
{% if block.description != '' %} {{ block.description }} diff --git a/templates/blocks/json-call-to-action.liquid b/templates/blocks/json-call-to-action.liquid index 316981c3..1a9032bd 100644 --- a/templates/blocks/json-call-to-action.liquid +++ b/templates/blocks/json-call-to-action.liquid @@ -2,10 +2,10 @@
-
+
{% if block.title %} -
+
{% include 'blocks/helpers/block-title' %}
{% endif %} diff --git a/templates/blocks/json-cover-with-form.liquid b/templates/blocks/json-cover-with-form.liquid index 2eb56673..b8957cc5 100644 --- a/templates/blocks/json-cover-with-form.liquid +++ b/templates/blocks/json-cover-with-form.liquid @@ -2,7 +2,7 @@
+ {% if block.background != '' and block.background.url != '' %} style="background-image: url({{ block.background.url | strip_start '/' }})" {% endif %}>
diff --git a/templates/blocks/json-cover-with-image-and-flexible-title.liquid b/templates/blocks/json-cover-with-image-and-flexible-title.liquid index 695a0a3d..fb3b4da3 100644 --- a/templates/blocks/json-cover-with-image-and-flexible-title.liquid +++ b/templates/blocks/json-cover-with-image-and-flexible-title.liquid @@ -2,12 +2,12 @@
+ {% if block.background != '' and block.background.url != '' %} style="background-image: url({{ block.background.url | strip_start '/' }})" {% endif %}>
{% if block.containerImage and block.containerImage.url %}
- +
{% endif %} diff --git a/templates/blocks/json-cover-with-image.liquid b/templates/blocks/json-cover-with-image.liquid index 072da94e..25c97ef3 100644 --- a/templates/blocks/json-cover-with-image.liquid +++ b/templates/blocks/json-cover-with-image.liquid @@ -1,18 +1,48 @@ +{% include 'blocks/helpers/hide-criteria' %} {% include 'blocks/helpers/cover-style' %} -
-
-
-
+
+
+
-
+ style="min-height: 420px;"> +
{% if block.containerImage and block.containerImage.url != '' %} - + {% endif %}
- {% include 'blocks/helpers/cover-text' %} + +
+ {% if block.note %} +
{{ block.note }}
+ {% endif %} + + {% if block.title %} +
+ {% include 'blocks/helpers/block-title' %} +
+ {% endif %} + + {% if block.subtitle %} +
+ {{ block.subtitle }} +
+ {% endif %} + + {% if (block.firstButton and block.firstButton.urlText) or (block.secondButton and block.secondButton.urlText) %} +
+ {% if block.firstButton and block.firstButton.urlText and block.firstButton.urlText != '' %} + {{block.firstButton.urlText}} + {% endif %} + {% if block.secondButton and block.secondButton.urlText and block.secondButton.urlText != '' %} + {{block.secondButton.urlText}} + {% endif %} +
+ {% endif %} +
+
@@ -27,6 +57,14 @@ headerType: [ h1, h2, h3, like-h1, like-h2, like-h3 ] noTop: bool noBottom: bool +fullWidth: bool +marginTop: string (px) +marginBottom: string (px) +paddingTop: string (px) +paddingBottom: string (px) +criteria: string [none, url, userGroup] +criteriaValue: string +hideOnMatch: bool backgroundColor: string (hex color) overlayColor: string (hex color) imagePosition: string [ null, right ] diff --git a/templates/blocks/json-cover-with-simple-text.liquid b/templates/blocks/json-cover-with-simple-text.liquid index b1722f07..5e8522f6 100644 --- a/templates/blocks/json-cover-with-simple-text.liquid +++ b/templates/blocks/json-cover-with-simple-text.liquid @@ -1,7 +1,7 @@ {% include 'blocks/helpers/cover-style' %}
+ {% if block.background != '' and block.background.url != '' %} style="background-image: url({{ block.background.url | strip_start '/' }})" {% endif %}>
diff --git a/templates/blocks/json-features-with-icons-in-columns.liquid b/templates/blocks/json-features-with-icons-in-columns.liquid index a516461a..9b9b8531 100644 --- a/templates/blocks/json-features-with-icons-in-columns.liquid +++ b/templates/blocks/json-features-with-icons-in-columns.liquid @@ -1,9 +1,9 @@
-
+
{% include 'blocks/helpers/block-title' %}
-
+
{% if block.content %} {{ block.content }} @@ -21,10 +21,10 @@ {% endif %} {% if block.iconsType == 'customIcon' and column.image.url != '' %} -
+
{% endif %} {% if block.iconsType == 'images' and column.image.url != '' %} - + {% endif %} {% if column.title != '' %}
{{ column.title }}
diff --git a/templates/blocks/json-features-with-icons.liquid b/templates/blocks/json-features-with-icons.liquid index e44974ea..1ea250cc 100644 --- a/templates/blocks/json-features-with-icons.liquid +++ b/templates/blocks/json-features-with-icons.liquid @@ -3,7 +3,7 @@
-
+
{% include 'blocks/helpers/block-title' %} @@ -28,10 +28,10 @@ {% endif %} {% if block.iconsType == 'customIcon' and column.image.url != '' %} - + {% endif %} {% if block.iconsType == 'images' and column.image.url != '' %} -
+
{% endif %} {% if column.title != '' %}
{{ column.title }}
diff --git a/templates/blocks/json-headline-with-form.liquid b/templates/blocks/json-headline-with-form.liquid index 40b4854f..f00a1f61 100644 --- a/templates/blocks/json-headline-with-form.liquid +++ b/templates/blocks/json-headline-with-form.liquid @@ -1,7 +1,7 @@ {% include 'blocks/helpers/cover-style' %}
+ {% if block.background != '' and block.background.url != '' %} style="background-image: url({{ block.background.url | strip_start '/' }})" {% endif %}>
diff --git a/templates/blocks/json-headline.liquid b/templates/blocks/json-headline.liquid index 681fff46..4d9136d6 100644 --- a/templates/blocks/json-headline.liquid +++ b/templates/blocks/json-headline.liquid @@ -1,7 +1,7 @@ {% include 'blocks/helpers/cover-style' %}
+ {% if block.background != '' and block.background.url != '' %} style="background-image: url({{ block.background.url | strip_start '/' }})" {% endif %}>
diff --git a/templates/blocks/json-logotypes.liquid b/templates/blocks/json-logotypes.liquid index e181bee2..d429eca9 100644 --- a/templates/blocks/json-logotypes.liquid +++ b/templates/blocks/json-logotypes.liquid @@ -3,7 +3,7 @@
-
+
{% include 'blocks/helpers/block-title' %} @@ -24,10 +24,10 @@
{% if logotype.url != '' %} - + {% else %} - + {% endif %}
{% endfor %} diff --git a/templates/blocks/json-product-tiles.liquid b/templates/blocks/json-product-tiles.liquid index aab12fb4..6b7d7ef0 100644 --- a/templates/blocks/json-product-tiles.liquid +++ b/templates/blocks/json-product-tiles.liquid @@ -23,7 +23,7 @@ {% include 'blocks/helpers/color-style' %}
-
+
{% include 'blocks/helpers/block-title' givenTitle: block.categoryId.name %} {% if block.subtitle %} diff --git a/templates/blocks/json-text.liquid b/templates/blocks/json-text.liquid index 78b0c5a7..ddf30ed1 100644 --- a/templates/blocks/json-text.liquid +++ b/templates/blocks/json-text.liquid @@ -2,7 +2,7 @@
-
+
{% include 'blocks/helpers/block-title' %} diff --git a/templates/blocks/json-two-columns-text.liquid b/templates/blocks/json-two-columns-text.liquid index 88bce4bd..15d3e91f 100644 --- a/templates/blocks/json-two-columns-text.liquid +++ b/templates/blocks/json-two-columns-text.liquid @@ -5,18 +5,18 @@ bg-dark text-white {% endif %}">
-
+
{% include 'blocks/helpers/block-title' %}
{% if block.contentBefore != '' %} -
+
{{ block.contentBefore }}
{% endif %} {% for item in block.items %} -
{{ 'bulk_order.general.title' | t }} -
- {% unless form.errors.empty? %} - +{% layout 'bootstrap_migration' %} +
+

{{ 'bulk_order.general.title' | t }}

+
+ {% unless form.errors.empty? %} +
+ +
{% endunless %} -
-
-
{{ 'bulk_order.general.subtitle' | t }}
- {% assign url = 'cart' | absolute_url %} - {% assign text = 'layout.cart.cart' | t %} -
{{ 'bulk_order.general.description' | t: url, text }}
-
- - {% assign column_count = 2 %} - {% assign rows_count = 15 %} - {% assign sku_grid_column_count = 4 %} - {% assign quantity_grid_column_count = 2 %} -
- {% include 'shared/bulk-order-fields' %} -
- - +
+
+
{{ 'bulk_order.general.subtitle' | t }}
+ {% assign url = 'cart' | absolute_url %} + {% assign text = 'layout.cart.cart' | t %} +
{{ 'bulk_order.general.description' | t: url, text }}
+
+
+ {% assign column_count = 2 %} + {% assign rows_count = 15 %} + {% assign sku_grid_column_count = 4 %} + {% assign quantity_grid_column_count = 2 %} +
+ {% include 'bootstrap-migration/shared/bulk-order-fields' %} +
+ +
+
+
+
+
{{ 'bulk_order.general.csv_title' | t }}
+
+

+

+
{{ 'bulk_order.general.csv_subtitle' | t }}
+
{{ 'bulk_order.general.csv_subdescription' | t }}
+
+

+ {{ 'bulk_order.general.csv_description' | t }} +
+
+
+
+ +
+ +
+
-
-
-
{{ 'bulk_order.general.csv_title' | t }}
-
-

-

-
{{ 'bulk_order.general.csv_subtitle' | t }}
-
{{ 'bulk_order.general.csv_subdescription' | t }}
-
-

- {{ 'bulk_order.general.csv_description' | t }} -
-
-
-
- -
- -
-
-
+
diff --git a/templates/cart.liquid b/templates/cart.liquid index 0fc19070..97e206bc 100644 --- a/templates/cart.liquid +++ b/templates/cart.liquid @@ -16,16 +16,16 @@
diff --git a/templates/customers/forgot_password.liquid b/templates/customers/forgot_password.liquid index 2a9420db..20914207 100644 --- a/templates/customers/forgot_password.liquid +++ b/templates/customers/forgot_password.liquid @@ -1,38 +1,28 @@ -{% layout settings.customer_layout %} +{% layout 'bootstrap_migration' %} -
- -
- -
+
+
{% if form.posted_successfully %} -
- {{ 'customer.sign_in.reset_password_success' | t }} -
+
+ {{ 'customer.sign_in.reset_password_success' | t }} +
{% endif %} - -
-
-
- -

{{ 'customer.recover_password.title' | t }}

-

{{ 'customer.recover_password.subtext' | t }}

- -
- {% include 'form-errors-custom' %} - - - - -

- -

- - {{ antiforgery }} -
- -
-
+
+

{{ 'customer.recover_password.title' | t }}

+

{{ 'customer.recover_password.subtext' | t }}

+
+ {% include 'bootstrap-migration/form-errors-custom' %} +
+
+ +
+
+ +
+
+ + {{ antiforgery }} +
diff --git a/templates/customers/login.liquid b/templates/customers/login.liquid index 7f4cbb5e..598b2296 100644 --- a/templates/customers/login.liquid +++ b/templates/customers/login.liquid @@ -1,29 +1,29 @@ -
- +
diff --git a/templates/customers/register.liquid b/templates/customers/register.liquid index 621a413c..b46e2875 100644 --- a/templates/customers/register.liquid +++ b/templates/customers/register.liquid @@ -1,79 +1,71 @@ -{% layout settings.customer_layout %} +{% layout 'bootstrap_migration' %} {% anti_forgery %} -
- +
{% endif %} -
+
{% include 'bootstrap-migration/index/asides' %} diff --git a/templates/json-page.liquid b/templates/json-page.liquid index 5561ea57..e2f51a57 100644 --- a/templates/json-page.liquid +++ b/templates/json-page.liquid @@ -2,6 +2,6 @@ {% layout page.layout %} {% endif %} {% layout 'bootstrap_migration' %} -
+
{% include 'json-blocks' %}
diff --git a/templates/json-preview.liquid b/templates/json-preview.liquid index 28b2598e..560f4f1a 100644 --- a/templates/json-preview.liquid +++ b/templates/json-preview.liquid @@ -7,7 +7,7 @@ script.src = platformUrl + relativeUrl; document.body.appendChild(script); -
+