From da309f9684bfcb63bc9db7948510ccade6a59d2a Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Mon, 1 Jul 2019 16:00:19 +0200 Subject: [PATCH 01/14] Added quantity of products to input --- core/modules/catalog/store/stock/actions.ts | 172 +++++++++++++------- src/themes/default/pages/Product.vue | 66 ++++---- 2 files changed, 152 insertions(+), 86 deletions(-) diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index 8fbceccae8..89856e44c2 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -1,92 +1,150 @@ -import Vue from 'vue' -import { ActionTree } from 'vuex' -import i18n from '@vue-storefront/i18n' +import Vue from 'vue'; +import { ActionTree } from 'vuex'; +import i18n from '@vue-storefront/i18n'; // requires cart module -import * as types from '@vue-storefront/core/modules/cart/store/mutation-types' -import RootState from '@vue-storefront/core/types/RootState' -import StockState from '../../types/StockState' -import rootStore from '@vue-storefront/core/store' -import { TaskQueue } from '@vue-storefront/core/lib/sync' -import { Logger } from '@vue-storefront/core/lib/logger' -import config from 'config' +import * as types from '@vue-storefront/core/modules/cart/store/mutation-types'; +import RootState from '@vue-storefront/core/types/RootState'; +import StockState from '../../types/StockState'; +import rootStore from '@vue-storefront/core/store'; +import { TaskQueue } from '@vue-storefront/core/lib/sync'; +import { Logger } from '@vue-storefront/core/lib/logger'; +import config from 'config'; const actions: ActionTree = { /** * Reset current configuration and selected variatnts */ - check (context, { product, qty = 1 }) { - return new Promise((resolve, reject) => { - if (config.stock.synchronize) { - TaskQueue.queue({ url: config.stock.endpoint + '/check?sku=' + encodeURIComponent(product.sku), - payload: { - method: 'GET', - headers: { 'Content-Type': 'application/json' }, - mode: 'cors' - }, - product_sku: product.sku, - callback_event: 'store:stock/stockAfterCheck' - }).then((task: any) => { - resolve({ qty: product.stock ? product.stock.qty : 0, status: product.stock ? (product.stock.is_in_stock ? 'ok' : 'out_of_stock') : 'ok', onlineCheckTaskId: task.task_id }) // if online we can return ok because it will be verified anyway - }) - } else { - resolve({ qty: product.stock ? product.stock.qty : 0, status: product.stock ? (product.stock.is_in_stock ? 'ok' : 'out_of_stock') : 'volatile' }) // if not online, cannot check the source of true here - } - }) + async check(context, { product, qty = 1 }) { + if (rootStore.state.config.stock.synchronize) { + const task: any = await TaskQueue.execute({ + url: + rootStore.state.config.stock.endpoint + + '/check?sku=' + + encodeURIComponent(product.sku), + payload: { + method: 'GET', + headers: { 'Content-Type': 'application/json' }, + mode: 'cors' + }, + product_sku: product.sku, + callback_event: 'store:stock/stockAfterCheck' + }); + let result = task.result; + const cartProduct = await rootStore.dispatch('cart/getItem', product.sku); + let totalQty = cartProduct ? cartProduct.qty + product.qty : product.qty; + const status = result.is_in_stock + ? totalQty > result.qty + ? 'not_enough_stock' + : 'ok' + : 'out_of_stock'; + return Object.assign({}, task, { + qty: task.result.qty, + status, + onlineCheckTaskId: task.task_id + }); + } else { + return { + qty: product.stock ? product.stock.qty : 0, + status: product.stock + ? product.stock.is_in_stock + ? 'ok' + : 'out_of_stock' + : 'volatile' + }; // if not online, cannot check the source of true here + } }, /** * Reset current configuration and selected variatnts */ - list (context, { skus }) { + list(context, { skus }) { return new Promise((resolve, reject) => { if (config.stock.synchronize) { - TaskQueue.execute({ url: config.stock.endpoint + '/list?skus=' + encodeURIComponent(skus.join(',')), + TaskQueue.execute({ + url: + config.stock.endpoint + + '/list?skus=' + + encodeURIComponent(skus.join(',')), payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, mode: 'cors' }, skus: skus - }).then((task: any) => { - if (task.resultCode === 200) { - for (const si of task.result) { - context.state.cache[si.product_id] = { is_in_stock: si.is_in_stock, qty: si.qty, product_id: si.product_id } // TODO: should be moved to mutation - } - } - resolve(task) // if online we can return ok because it will be verified anyway - }).catch((err) => { - Logger.error(err, 'stock')() - resolve(null) }) + .then((task: any) => { + if (task.resultCode === 200) { + for (const si of task.result) { + context.state.cache[si.product_id] = { + is_in_stock: si.is_in_stock, + qty: si.qty, + product_id: si.product_id + }; // TODO: should be moved to mutation + } + } + resolve(task); // if online we can return ok because it will be verified anyway + }) + .catch(err => { + Logger.error(err, 'stock')(); + resolve(null); + }); } else { - resolve(null) // if not online, cannot check the source of true here + resolve(null); // if not online, cannot check the source of true here } - }) + }); }, - clearCache (context) { - context.state.cache = {} + clearCache(context) { + context.state.cache = {}; }, - stockAfterCheck (context, event) { + stockAfterCheck(context, event) { setTimeout(() => { // TODO: Move to cart module - rootStore.dispatch('cart/getItem', event.product_sku).then((cartItem) => { + rootStore.dispatch('cart/getItem', event.product_sku).then(cartItem => { if (cartItem && event.result.code !== 'ENOTFOUND') { if (!event.result.is_in_stock) { if (!config.stock.allowOutOfStockInCart) { - Logger.log('Removing product from cart' + event.product_sku, 'stock')() - rootStore.commit('cart/' + types.CART_DEL_ITEM, { product: { sku: event.product_sku } }, {root: true}) + Logger.log( + 'Removing product from cart' + event.product_sku, + 'stock' + )(); + rootStore.commit( + 'cart/' + types.CART_DEL_ITEM, + { product: { sku: event.product_sku } }, + { root: true } + ); } else { - rootStore.dispatch('cart/updateItem', { product: { errors: { stock: i18n.t('Out of the stock!') }, sku: event.product_sku, is_in_stock: false } }) + rootStore.dispatch('cart/updateItem', { + product: { + errors: { stock: i18n.t('Out of the stock!') }, + sku: event.product_sku, + is_in_stock: false + } + }); } } else { - rootStore.dispatch('cart/updateItem', { product: { info: { stock: i18n.t('In stock!') }, sku: event.product_sku, is_in_stock: true } }) + rootStore.dispatch('cart/updateItem', { + product: { + info: { stock: i18n.t('In stock!') }, + sku: event.product_sku, + is_in_stock: true + } + }); } - Vue.prototype.$bus.$emit('cart-after-itemchanged', { item: cartItem }) + Vue.prototype.$bus.$emit('cart-after-itemchanged', { + item: cartItem + }); } - }) - Logger.debug('Stock quantity checked for ' + event.result.product_id + ', response time: ' + (event.transmited_at - event.created_at) + ' ms', 'stock')() - Logger.debug(event, 'stock')() - }, 500) + }); + Logger.debug( + 'Stock quantity checked for ' + + event.result.product_id + + ', response time: ' + + (event.transmited_at - event.created_at) + + ' ms', + 'stock' + )(); + Logger.debug(event, 'stock')(); + }, 500); } -} +}; -export default actions +export default actions; diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 1f1263e681..247fc93b6b 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -33,9 +33,7 @@ class="mb20 uppercase cl-secondary" itemprop="sku" :content="product.sku" - > - {{ $t('SKU') }}: {{ product.sku }} - + >{{ $t('SKU') }}: {{ product.sku }}
@@ -56,17 +54,13 @@
- {{ product.qty > 0 ? product.priceInclTax * product.qty : product.priceInclTax | price }} -
+ >{{ product.qty > 0 ? product.priceInclTax * product.qty : product.priceInclTax | price }}
- {{ product.errors | formatProductMessages }} -
+ >{{ product.errors | formatProductMessages }}
- +
- +
@@ -181,13 +175,11 @@
-

- {{ $t('Product details') }} -

+

{{ $t('Product details') }}

-
+
    @@ -200,15 +192,15 @@ />
-
+
- - - - - + + + + + @@ -258,25 +250,32 @@ export default { SizeGuide }, mixins: [Product, VueOfflineMixin], - data () { + data() { return { - detailsOpen: false + detailsOpen: false, + quantity: 0 } }, directives: { focusClean }, computed: { - structuredData () { + structuredData() { return { availability: this.product.stock.is_in_stock ? 'InStock' : 'OutOfStock' } } }, + created() { + this.getQuantity() + }, + updated() { + this.getQuantity() + }, methods: { - showDetails (event) { + showDetails(event) { this.detailsOpen = true event.target.classList.add('hidden') }, - notifyOutStock () { + notifyOutStock() { this.$store.dispatch('notification/spawnNotification', { type: 'error', message: this.$t( @@ -285,7 +284,7 @@ export default { action1: { label: this.$t('OK') } }) }, - notifyWrongAttributes () { + notifyWrongAttributes() { this.$store.dispatch('notification/spawnNotification', { type: 'warning', message: this.$t( @@ -294,8 +293,17 @@ export default { action1: { label: this.$t('OK') } }) }, - openSizeGuide () { + openSizeGuide() { this.$bus.$emit('modal-show', 'modal-sizeguide') + }, + getQuantity() { + this.$store + .dispatch('stock/check', { + product: this.product, + qty: this.product.qte + // qty: record ? record.qty + 1 : product.qty ? product.qty : 1 + }) + .then(res => (this.quantity = res.qty)) } }, validations: { From ce9f9550c09bd67c8e7ecd38a020c68981a76040 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Mon, 1 Jul 2019 16:04:40 +0200 Subject: [PATCH 02/14] Added max range of product which depends on quantity of product --- core/modules/catalog/store/stock/actions.ts | 8 +-- .../default/components/core/ProductTile.vue | 16 +++--- .../core/blocks/Form/BaseInputNumber.vue | 51 +++++++++--------- src/themes/default/pages/Product.vue | 53 +++++++++++-------- 4 files changed, 71 insertions(+), 57 deletions(-) diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index 89856e44c2..f5f43c97f5 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -14,7 +14,7 @@ const actions: ActionTree = { /** * Reset current configuration and selected variatnts */ - async check(context, { product, qty = 1 }) { + async check (context, { product, qty = 1 }) { if (rootStore.state.config.stock.synchronize) { const task: any = await TaskQueue.execute({ url: @@ -56,7 +56,7 @@ const actions: ActionTree = { /** * Reset current configuration and selected variatnts */ - list(context, { skus }) { + list (context, { skus }) { return new Promise((resolve, reject) => { if (config.stock.synchronize) { TaskQueue.execute({ @@ -92,10 +92,10 @@ const actions: ActionTree = { } }); }, - clearCache(context) { + clearCache (context) { context.state.cache = {}; }, - stockAfterCheck(context, event) { + stockAfterCheck (context, event) { setTimeout(() => { // TODO: Move to cart module rootStore.dispatch('cart/getItem', event.product_sku).then(cartItem => { diff --git a/src/themes/default/components/core/ProductTile.vue b/src/themes/default/components/core/ProductTile.vue index e8b3a630ff..197f7f8596 100644 --- a/src/themes/default/components/core/ProductTile.vue +++ b/src/themes/default/components/core/ProductTile.vue @@ -37,7 +37,9 @@ /> -

{{ product.name | htmlDecode }}

+

+ {{ product.name | htmlDecode }} +

diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 247fc93b6b..280bb8b696 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -33,7 +33,9 @@ class="mb20 uppercase cl-secondary" itemprop="sku" :content="product.sku" - >{{ $t('SKU') }}: {{ product.sku }} + > + {{ $t('SKU') }}: {{ product.sku }} +
@@ -54,13 +56,17 @@
{{ product.qty > 0 ? product.priceInclTax * product.qty : product.priceInclTax | price }}
+ > + {{ product.qty > 0 ? product.priceInclTax * product.qty : product.priceInclTax | price }} +
{{ product.errors | formatProductMessages }}
+ > + {{ product.errors | formatProductMessages }} +
- +
- +
@@ -175,11 +182,13 @@
-

{{ $t('Product details') }}

+

+ {{ $t('Product details') }} +

-
+
    @@ -192,15 +201,15 @@ />
-
+
- - - - - + + + + + @@ -250,7 +259,7 @@ export default { SizeGuide }, mixins: [Product, VueOfflineMixin], - data() { + data () { return { detailsOpen: false, quantity: 0 @@ -258,24 +267,24 @@ export default { }, directives: { focusClean }, computed: { - structuredData() { + structuredData () { return { availability: this.product.stock.is_in_stock ? 'InStock' : 'OutOfStock' } } }, - created() { + created () { this.getQuantity() }, - updated() { + updated () { this.getQuantity() }, methods: { - showDetails(event) { + showDetails (event) { this.detailsOpen = true event.target.classList.add('hidden') }, - notifyOutStock() { + notifyOutStock () { this.$store.dispatch('notification/spawnNotification', { type: 'error', message: this.$t( @@ -284,7 +293,7 @@ export default { action1: { label: this.$t('OK') } }) }, - notifyWrongAttributes() { + notifyWrongAttributes () { this.$store.dispatch('notification/spawnNotification', { type: 'warning', message: this.$t( @@ -293,10 +302,10 @@ export default { action1: { label: this.$t('OK') } }) }, - openSizeGuide() { + openSizeGuide () { this.$bus.$emit('modal-show', 'modal-sizeguide') }, - getQuantity() { + getQuantity () { this.$store .dispatch('stock/check', { product: this.product, From 4bfa06486b1f48bfe042276a9a098340dd03a8c5 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Mon, 1 Jul 2019 17:00:05 +0200 Subject: [PATCH 03/14] Added disable atribute to input component --- .../default/components/core/blocks/Form/BaseInputNumber.vue | 5 +++++ src/themes/default/pages/Product.vue | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue b/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue index aaf6d7bf49..0bc85e7e99 100644 --- a/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue +++ b/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue @@ -6,6 +6,7 @@ type="number" :min="min" :max="max" + :disabled="disabled" class="m0 no-outline base-input-number__input brdr-cl-primary bg-cl-transparent h4" :focus="autofocus" :value="value" @@ -44,6 +45,10 @@ export default { type: Number, default: 0 }, + disabled: { + type: Boolean, + default: false + }, autofocus: { type: Boolean, required: false, diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 280bb8b696..dd88f9d591 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -151,8 +151,10 @@ @@ -261,13 +261,13 @@ export default { SizeGuide }, mixins: [Product, VueOfflineMixin], + directives: { focusClean }, data () { return { detailsOpen: false, quantity: 0 } }, - directives: { focusClean }, computed: { structuredData () { return { From d6f1a456f3797be754437900716732edc97a2c59 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Fri, 5 Jul 2019 10:16:00 +0200 Subject: [PATCH 05/14] Added changes to actions filem proposed at CR --- core/modules/catalog/store/stock/actions.ts | 35 +++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index f5f43c97f5..696ad44f5e 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -14,13 +14,12 @@ const actions: ActionTree = { /** * Reset current configuration and selected variatnts */ - async check (context, { product, qty = 1 }) { - if (rootStore.state.config.stock.synchronize) { + async check ({ dispatch }, { product, qty = 1 }) { + if (config.stock.synchronize) { const task: any = await TaskQueue.execute({ - url: - rootStore.state.config.stock.endpoint + - '/check?sku=' + - encodeURIComponent(product.sku), + url: `${config.stock.endpoint}/check?sku=${encodeURIComponent( + product.sku + )}`, payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, @@ -30,8 +29,10 @@ const actions: ActionTree = { callback_event: 'store:stock/stockAfterCheck' }); let result = task.result; - const cartProduct = await rootStore.dispatch('cart/getItem', product.sku); - let totalQty = cartProduct ? cartProduct.qty + product.qty : product.qty; + const cartProduct = await dispatch('cart/getItem', product.sku); + const totalQty = cartProduct + ? cartProduct.qty + product.qty + : product.qty; const status = result.is_in_stock ? totalQty > result.qty ? 'not_enough_stock' @@ -43,13 +44,14 @@ const actions: ActionTree = { onlineCheckTaskId: task.task_id }); } else { + const status = product.stock + ? product.stock.is_in_stock + ? 'ok' + : 'out_of_stock' + : 'volatile'; return { qty: product.stock ? product.stock.qty : 0, - status: product.stock - ? product.stock.is_in_stock - ? 'ok' - : 'out_of_stock' - : 'volatile' + status }; // if not online, cannot check the source of true here } }, @@ -60,10 +62,9 @@ const actions: ActionTree = { return new Promise((resolve, reject) => { if (config.stock.synchronize) { TaskQueue.execute({ - url: - config.stock.endpoint + - '/list?skus=' + - encodeURIComponent(skus.join(',')), + url: `${config.stock.endpoint}/list?skus=${encodeURIComponent( + skus.join(',') + )}`, payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, From 98c86bb47be2410a06bcdb83618307f939c85783 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Mon, 15 Jul 2019 14:12:09 +0200 Subject: [PATCH 06/14] Added await to check action --- core/modules/catalog/store/stock/actions.ts | 2 +- src/themes/default/pages/Product.vue | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index 72303aee95..76aaf6ac70 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -56,7 +56,7 @@ const actions: ActionTree = { */ async check (context, { product, qty = 1 }) { if (config.stock.synchronize) { - const task: any = TaskQueue.execute({ + const task: any = await TaskQueue.execute({ url: processURLAddress( `${config.stock.endpoint}/check?sku=${encodeURIComponent( product.sku diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index a619d10a78..844ddb7453 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -351,7 +351,6 @@ export default { .dispatch('stock/check', { product: this.product, qty: this.product.qte - // qty: record ? record.qty + 1 : product.qty ? product.qty : 1 }) .then(res => (this.quantity = res.qty)) } From 928e000900aee3a517375586fd61ba30cf9cf098 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Tue, 16 Jul 2019 15:33:07 +0200 Subject: [PATCH 07/14] Add pleceholder when getting quantity, change place of calling getQuantity method --- core/modules/catalog/store/stock/actions.ts | 88 ++++++++++----------- core/modules/compare/store/getters.ts | 10 +-- src/themes/default/pages/Product.vue | 17 ++-- 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index 76aaf6ac70..d8a243d304 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -1,14 +1,14 @@ -import { ActionTree } from 'vuex'; -import i18n from '@vue-storefront/i18n'; +import { ActionTree } from 'vuex' +import i18n from '@vue-storefront/i18n' // requires cart module -import * as types from '@vue-storefront/core/modules/cart/store/mutation-types'; -import RootState from '@vue-storefront/core/types/RootState'; -import StockState from '../../types/StockState'; -import { TaskQueue } from '@vue-storefront/core/lib/sync'; -import { Logger } from '@vue-storefront/core/lib/logger'; -import config from 'config'; -import EventBus from '@vue-storefront/core/compatibility/plugins/event-bus'; -import { processURLAddress } from '@vue-storefront/core/helpers'; +import * as types from '@vue-storefront/core/modules/cart/store/mutation-types' +import RootState from '@vue-storefront/core/types/RootState' +import StockState from '../../types/StockState' +import { TaskQueue } from '@vue-storefront/core/lib/sync' +import { Logger } from '@vue-storefront/core/lib/logger' +import config from 'config' +import EventBus from '@vue-storefront/core/compatibility/plugins/event-bus' +import { processURLAddress } from '@vue-storefront/core/helpers' const actions: ActionTree = { /** @@ -30,7 +30,7 @@ const actions: ActionTree = { is_result_cacheable: true, // store result for the Checkout.js double check product_sku: product.sku, callback_event: 'store:stock/stockAfterCheck' - }); + }) return { qty: product.stock ? product.stock.qty : 0, status: product.stock @@ -39,7 +39,7 @@ const actions: ActionTree = { : 'out_of_stock' : 'ok', onlineCheckTaskId: task.task_id - }; // if online we can return ok because it will be verified anyway + } // if online we can return ok because it will be verified anyway } else { return { qty: product.stock ? product.stock.qty : 0, @@ -48,7 +48,7 @@ const actions: ActionTree = { ? 'ok' : 'out_of_stock' : 'volatile' - }; // if not online, cannot check the source of true here + } // if not online, cannot check the source of true here } }, /** @@ -68,7 +68,7 @@ const actions: ActionTree = { mode: 'cors' }, product_sku: product.sku - }); + }) return { qty: task.result ? task.result.qty : 0, status: task.result @@ -77,7 +77,7 @@ const actions: ActionTree = { : 'out_of_stock' : 'ok', onlineCheckTaskId: task.task_id - }; // if online we can return ok because it will be verified anyway + } // if online we can return ok because it will be verified anyway } else { return { qty: product.stock ? product.stock.qty : 0, @@ -86,13 +86,13 @@ const actions: ActionTree = { ? 'ok' : 'out_of_stock' : 'volatile' - }; // if not online, cannot check the source of true here + } // if not online, cannot check the source of true here } }, /** * Reset current configuration and selected variatnts */ - list (context, { skus }) { + list ({ state }, { skus }) { if (config.stock.synchronize) { try { const task: any = TaskQueue.execute({ @@ -107,36 +107,34 @@ const actions: ActionTree = { mode: 'cors' }, skus: skus - }); + }) if (task.resultCode === 200) { for (const si of task.result) { - context.state.cache[si.product_id] = { + state.cache[si.product_id] = { is_in_stock: si.is_in_stock, qty: si.qty, product_id: si.product_id - }; // TODO: should be moved to mutation + } // TODO: should be moved to mutation } } - return task; // if online we can return ok because it will be verified anyway + return task // if online we can return ok because it will be verified anyway } catch (err) { - Logger.error(err, 'stock')(); - return null; + Logger.error(err, 'stock')() + return null } } else { - return null; // if not online, cannot check the source of true here + return null // if not online, cannot check the source of true here } }, - clearCache (context) { - context.state.cache = {}; + clearCache ({ state }) { + state.cache = {} }, - async stockAfterCheck (context, event) { + async stockAfterCheck ({ dispatch, commit }, event) { setTimeout(async () => { // TODO: Move to cart module - const cartItem: any = await context.dispatch( - 'cart/getItem', - event.product_sku, - { root: true } - ); + const cartItem: any = await dispatch('cart/getItem', event.product_sku, { + root: true + }) if (cartItem && event.result.code !== 'ENOTFOUND') { if (!event.result.is_in_stock) { if (!config.stock.allowOutOfStockInCart && !config.cart.synchronize) { @@ -144,14 +142,14 @@ const actions: ActionTree = { Logger.log( 'Removing product from cart' + event.product_sku, 'stock' - )(); - context.commit( + )() + commit( 'cart/' + types.CART_DEL_ITEM, { product: { sku: event.product_sku } }, { root: true } - ); + ) } else { - context.dispatch( + dispatch( 'cart/updateItem', { product: { @@ -161,10 +159,10 @@ const actions: ActionTree = { } }, { root: true } - ); + ) } } else { - context.dispatch( + dispatch( 'cart/updateItem', { product: { @@ -174,9 +172,9 @@ const actions: ActionTree = { } }, { root: true } - ); + ) } - EventBus.$emit('cart-after-itemchanged', { item: cartItem }); + EventBus.$emit('cart-after-itemchanged', { item: cartItem }) } Logger.debug( 'Stock quantity checked for ' + @@ -185,10 +183,10 @@ const actions: ActionTree = { (event.transmited_at - event.created_at) + ' ms', 'stock' - )(); - Logger.debug(event, 'stock')(); - }, 500); + )() + Logger.debug(event, 'stock')() + }, 500) } -}; +} -export default actions; +export default actions diff --git a/core/modules/compare/store/getters.ts b/core/modules/compare/store/getters.ts index ca2c0d15a0..4f09a9ce40 100644 --- a/core/modules/compare/store/getters.ts +++ b/core/modules/compare/store/getters.ts @@ -1,12 +1,12 @@ -import { GetterTree } from 'vuex'; -import RootState from '@vue-storefront/core/types/RootState'; -import CompareState from '../types/CompareState'; +import { GetterTree } from 'vuex' +import RootState from '@vue-storefront/core/types/RootState' +import CompareState from '../types/CompareState' const getters: GetterTree = { isEmpty: state => state.items.length === 0, isOnCompare: state => product => state.items.find(p => p.sku === product.sku), isCompareLoaded: state => state.loaded, getCompareProductsCount: state => state.items.length -}; +} -export default getters; +export default getters diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 844ddb7453..2e9b8d4cac 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -136,7 +136,7 @@ v-if="product.type_id !== 'grouped' && product.type_id !== 'bundle'" > @@ -252,7 +252,8 @@ export default { data () { return { detailsOpen: false, - quantity: 0 + quantity: 0, + isProductLoading: true } }, computed: { @@ -311,9 +312,6 @@ export default { created () { this.getQuantity() }, - updated () { - this.getQuantity() - }, methods: { showDetails (event) { this.detailsOpen = true @@ -342,17 +340,22 @@ export default { 'filter-changed-product', Object.assign({ attribute_code: variant.type }, variant) ) + this.getQuantity() }, openSizeGuide () { this.$bus.$emit('modal-show', 'modal-sizeguide') }, getQuantity () { + this.isProductLoading = true this.$store .dispatch('stock/check', { product: this.product, qty: this.product.qte }) - .then(res => (this.quantity = res.qty)) + .then(res => { + this.isProductLoading = false + this.quantity = res.qty + }) } }, validations: { From c05c851846667bcc92760bb39334c077f495e175 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Wed, 17 Jul 2019 15:34:33 +0200 Subject: [PATCH 08/14] Fix disabled button --- src/themes/default/pages/Product.vue | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 2e9b8d4cac..f425b18b32 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -136,7 +136,7 @@ v-if="product.type_id !== 'grouped' && product.type_id !== 'bundle'" > @@ -307,10 +307,19 @@ export default { }) } return selectedFilters + }, + isSimpleOrConfigurable () { + if ( + this.product.type_id === 'simple' || + this.product.type_id === 'configurable' + ) { return true } + + return false } }, created () { this.getQuantity() + console.log(this.product.type_id) }, methods: { showDetails (event) { From a523ccab4691633628a791ea9bc88eebdff0bfd8 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Thu, 18 Jul 2019 11:24:04 +0200 Subject: [PATCH 09/14] Remove console.log() --- src/themes/default/pages/Product.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 59eb0e79f6..8ac3a30cd6 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -321,7 +321,6 @@ export default { }, created () { this.getQuantity() - console.log(this.product.type_id) }, methods: { showDetails (event) { From f9727f39259b2bbe0fadc4191624790bbedde1bd Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Thu, 18 Jul 2019 12:26:29 +0200 Subject: [PATCH 10/14] Add mutations to stock --- core/modules/catalog/store/stock/actions.ts | 15 ++++++++++----- .../modules/catalog/store/stock/mutation-types.ts | 3 +++ core/modules/catalog/store/stock/mutations.ts | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 core/modules/catalog/store/stock/mutation-types.ts create mode 100644 core/modules/catalog/store/stock/mutations.ts diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index d8a243d304..796223e0d9 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -2,6 +2,7 @@ import { ActionTree } from 'vuex' import i18n from '@vue-storefront/i18n' // requires cart module import * as types from '@vue-storefront/core/modules/cart/store/mutation-types' +import * as mutationTypes from '@vue-storefront/core/modules/catalog/store/stock/mutation-types' import RootState from '@vue-storefront/core/types/RootState' import StockState from '../../types/StockState' import { TaskQueue } from '@vue-storefront/core/lib/sync' @@ -92,7 +93,7 @@ const actions: ActionTree = { /** * Reset current configuration and selected variatnts */ - list ({ state }, { skus }) { + list ({ commit }, { skus }) { if (config.stock.synchronize) { try { const task: any = TaskQueue.execute({ @@ -110,11 +111,15 @@ const actions: ActionTree = { }) if (task.resultCode === 200) { for (const si of task.result) { - state.cache[si.product_id] = { + const productInfo = { is_in_stock: si.is_in_stock, qty: si.qty, product_id: si.product_id - } // TODO: should be moved to mutation + } + commit(mutationTypes.SET_CACHE_PRODUCT, { + productId: si.product_id, + productInfo + }) } } return task // if online we can return ok because it will be verified anyway @@ -126,8 +131,8 @@ const actions: ActionTree = { return null // if not online, cannot check the source of true here } }, - clearCache ({ state }) { - state.cache = {} + clearCache ({ commit }) { + commit(mutationTypes.SET_CACHE, {}) }, async stockAfterCheck ({ dispatch, commit }, event) { setTimeout(async () => { diff --git a/core/modules/catalog/store/stock/mutation-types.ts b/core/modules/catalog/store/stock/mutation-types.ts new file mode 100644 index 0000000000..0c95007168 --- /dev/null +++ b/core/modules/catalog/store/stock/mutation-types.ts @@ -0,0 +1,3 @@ +export const SN_CATALOG = 'catalog' +export const SET_CACHE = `${SN_CATALOG}/SET_CACHE` +export const SET_CACHE_PRODUCT = `${SN_CATALOG}/SET_CACHE_PRODUCT` diff --git a/core/modules/catalog/store/stock/mutations.ts b/core/modules/catalog/store/stock/mutations.ts new file mode 100644 index 0000000000..8e62897b61 --- /dev/null +++ b/core/modules/catalog/store/stock/mutations.ts @@ -0,0 +1,14 @@ +import { MutationTree } from 'vuex' +import StockState from '../../types/StockState' +import * as types from './mutation-types' + +const mutations: MutationTree = { + [types.SET_CACHE] (state, payload) { + state.cache = payload + }, + [types.SET_CACHE_PRODUCT] (state, { productId, productInfo }) { + state.cache[productId] = productInfo + } +} + +export default mutations From 841d333d05f5eaa1c8395bd8e7a60bfeeed984b1 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Thu, 18 Jul 2019 13:08:37 +0200 Subject: [PATCH 11/14] Fix some names, import mutations to indes.ts, fix SET_STOCK_CACHE_PRODUCT mutation --- core/modules/catalog/store/stock/actions.ts | 6 +++--- core/modules/catalog/store/stock/index.ts | 2 ++ core/modules/catalog/store/stock/mutation-types.ts | 4 ++-- core/modules/catalog/store/stock/mutations.ts | 10 ++++++---- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/core/modules/catalog/store/stock/actions.ts b/core/modules/catalog/store/stock/actions.ts index 796223e0d9..09b258a844 100644 --- a/core/modules/catalog/store/stock/actions.ts +++ b/core/modules/catalog/store/stock/actions.ts @@ -2,7 +2,7 @@ import { ActionTree } from 'vuex' import i18n from '@vue-storefront/i18n' // requires cart module import * as types from '@vue-storefront/core/modules/cart/store/mutation-types' -import * as mutationTypes from '@vue-storefront/core/modules/catalog/store/stock/mutation-types' +import * as stockMutationTypes from '@vue-storefront/core/modules/catalog/store/stock/mutation-types' import RootState from '@vue-storefront/core/types/RootState' import StockState from '../../types/StockState' import { TaskQueue } from '@vue-storefront/core/lib/sync' @@ -116,7 +116,7 @@ const actions: ActionTree = { qty: si.qty, product_id: si.product_id } - commit(mutationTypes.SET_CACHE_PRODUCT, { + commit(stockMutationTypes.SET_STOCK_CACHE_PRODUCT, { productId: si.product_id, productInfo }) @@ -132,7 +132,7 @@ const actions: ActionTree = { } }, clearCache ({ commit }) { - commit(mutationTypes.SET_CACHE, {}) + commit(stockMutationTypes.SET_STOCK_CACHE, {}) }, async stockAfterCheck ({ dispatch, commit }, event) { setTimeout(async () => { diff --git a/core/modules/catalog/store/stock/index.ts b/core/modules/catalog/store/stock/index.ts index 4e4f00aa40..264dd31fc2 100644 --- a/core/modules/catalog/store/stock/index.ts +++ b/core/modules/catalog/store/stock/index.ts @@ -1,11 +1,13 @@ import { Module } from 'vuex' import actions from './actions' +import mutations from './mutations' import RootState from '@vue-storefront/core/types/RootState' import StockState from '../../types/StockState' export const stockModule: Module = { namespaced: true, actions, + mutations, state: { cache: {} } diff --git a/core/modules/catalog/store/stock/mutation-types.ts b/core/modules/catalog/store/stock/mutation-types.ts index 0c95007168..688b201064 100644 --- a/core/modules/catalog/store/stock/mutation-types.ts +++ b/core/modules/catalog/store/stock/mutation-types.ts @@ -1,3 +1,3 @@ export const SN_CATALOG = 'catalog' -export const SET_CACHE = `${SN_CATALOG}/SET_CACHE` -export const SET_CACHE_PRODUCT = `${SN_CATALOG}/SET_CACHE_PRODUCT` +export const SET_STOCK_CACHE = `${SN_CATALOG}/SET_STOCK_CACHE` +export const SET_STOCK_CACHE_PRODUCT = `${SN_CATALOG}/SET_STOCK_CACHE_PRODUCT` diff --git a/core/modules/catalog/store/stock/mutations.ts b/core/modules/catalog/store/stock/mutations.ts index 8e62897b61..7eeca39bd3 100644 --- a/core/modules/catalog/store/stock/mutations.ts +++ b/core/modules/catalog/store/stock/mutations.ts @@ -3,11 +3,13 @@ import StockState from '../../types/StockState' import * as types from './mutation-types' const mutations: MutationTree = { - [types.SET_CACHE] (state, payload) { - state.cache = payload + [types.SET_STOCK_CACHE] (state, cache) { + state.cache = cache }, - [types.SET_CACHE_PRODUCT] (state, { productId, productInfo }) { - state.cache[productId] = productInfo + [types.SET_STOCK_CACHE_PRODUCT] (state, { productId, productInfo }) { + state.cache[productId] = Object.assign({}, state.cache, { + productId: productInfo + }) } } From 5f0637abd9b31d8146af951eed41e17094854a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dziedzi=C5=84ski?= <32803679+Michal-Dziedzinski@users.noreply.github.com> Date: Tue, 23 Jul 2019 09:18:18 +0200 Subject: [PATCH 12/14] Update core/modules/catalog/store/stock/mutations.ts Co-Authored-By: Patryk Tomczyk <13100280+patzick@users.noreply.github.com> --- core/modules/catalog/store/stock/mutations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/catalog/store/stock/mutations.ts b/core/modules/catalog/store/stock/mutations.ts index 7eeca39bd3..815c06d96b 100644 --- a/core/modules/catalog/store/stock/mutations.ts +++ b/core/modules/catalog/store/stock/mutations.ts @@ -7,7 +7,7 @@ const mutations: MutationTree = { state.cache = cache }, [types.SET_STOCK_CACHE_PRODUCT] (state, { productId, productInfo }) { - state.cache[productId] = Object.assign({}, state.cache, { + state.cache = Object.assign({}, state.cache, { productId: productInfo }) } From 2fd3f7c8b183e70963d66b6b6ddfd04af648f94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dziedzi=C5=84ski?= <32803679+Michal-Dziedzinski@users.noreply.github.com> Date: Tue, 23 Jul 2019 09:35:11 +0200 Subject: [PATCH 13/14] Update core/modules/catalog/store/stock/mutations.ts Co-Authored-By: Patryk Tomczyk <13100280+patzick@users.noreply.github.com> --- core/modules/catalog/store/stock/mutations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/catalog/store/stock/mutations.ts b/core/modules/catalog/store/stock/mutations.ts index 815c06d96b..b684e25992 100644 --- a/core/modules/catalog/store/stock/mutations.ts +++ b/core/modules/catalog/store/stock/mutations.ts @@ -8,7 +8,7 @@ const mutations: MutationTree = { }, [types.SET_STOCK_CACHE_PRODUCT] (state, { productId, productInfo }) { state.cache = Object.assign({}, state.cache, { - productId: productInfo + [productId]: productInfo }) } } From a081cea0e13b24a0e37cd09e2c70f1e9d5bd45f3 Mon Sep 17 00:00:00 2001 From: Michal-Dziedzinski Date: Tue, 23 Jul 2019 12:17:08 +0200 Subject: [PATCH 14/14] Add loader and add computed property as input name --- src/themes/default/components/core/Spinner.vue | 18 ++++++++++++++++++ .../core/blocks/Form/BaseInputNumber.vue | 2 -- src/themes/default/pages/Product.vue | 16 ++++++++++------ 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 src/themes/default/components/core/Spinner.vue diff --git a/src/themes/default/components/core/Spinner.vue b/src/themes/default/components/core/Spinner.vue new file mode 100644 index 0000000000..9fdbf719bf --- /dev/null +++ b/src/themes/default/components/core/Spinner.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue b/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue index a287633eb9..3e1de0e737 100644 --- a/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue +++ b/src/themes/default/components/core/blocks/Form/BaseInputNumber.vue @@ -72,8 +72,6 @@ export default { @import '~theme/css/helpers/functions/color'; .base-input-number { - width: 100%; - &__input { border-style: solid; border-width: 0 0 1px 0; diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 8ac3a30cd6..a5816f0e21 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -133,7 +133,7 @@ v-if="product.type_id !== 'grouped' && product.type_id !== 'bundle'" > +