@lancom/shared 0.0.87 → 0.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,8 +34,11 @@ export default {
34
34
  saveOrder(order) {
35
35
  return order._id ? _put(`admin/order/${order._id}`, order) : _post('admin/order', order);
36
36
  },
37
- exportOrderToStarshipit(order) {
38
- return _post(`shop/${order.shop}/order/${order._id}/export-to-starshipit`, order);
37
+ exportOrderToStarshipit(order, shipment) {
38
+ return _post(`admin/shop/${order.shop}/order/${order._id}/shipment/${shipment._id || shipment.guid}/export-to-starshipit`, shipment);
39
+ },
40
+ calculateShipmentRates(order, shipment) {
41
+ return _get(`admin/shop/${order.shop}/order/${order._id}/shipment/${shipment._id || shipment.guid}/calculate-shipping`);
39
42
  },
40
43
  createOrderRefund(order, refund, shop) {
41
44
  return _post(`shop/${shop}/order/${order}/refund`, refund);
@@ -1,4 +1,4 @@
1
- import moment from 'moment';
1
+ import dayjs from 'dayjs';
2
2
  import DateOnly from 'dateonly';
3
3
 
4
4
  import currencies from '../constants/currencies';
@@ -16,6 +16,8 @@ export const number = (value, digits = 0) => {
16
16
  return fixed.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
17
17
  };
18
18
 
19
+ export const decimal = value => number(value || 0, 2);
20
+
19
21
  export const price = (value = 0, currency = 'USD') => {
20
22
  const amount = number(value, 2);
21
23
  const cur = currencies.find(c => c.value.toUpperCase() === currency.toUpperCase());
@@ -66,11 +68,11 @@ export const highlight = (string = '', query) => {
66
68
  return string.toString().replace(q, matchedTxt => (`<span class="highlight">${matchedTxt}</span>`));
67
69
  };
68
70
 
69
- export const date = d => moment(d).format('lll');
71
+ export const date = d => dayjs(d).format('ddd, MMM D, YYYY h:mm A');
70
72
 
71
- export const shortDate = d => moment(d).format('DD/MM/YYYY');
73
+ export const shortDate = d => dayjs(d).format('DD/MM/YYYY');
72
74
 
73
- export const sydneyTime = d => moment(d).utc().utcOffset(10).format('lll');
75
+ export const sydneyTime = d => dayjs(d).utc().utcOffset(10).format('MMM D, YYYY h:mm A');
74
76
 
75
77
  export const priceInRange = (prices, amount) => (prices.find(({ min, max }) => min <= amount && (!max || max >= amount)) || { price: 0 }).price;
76
78
 
@@ -121,7 +121,6 @@ export function generateProductsLink($route, data) {
121
121
  }
122
122
 
123
123
  export function generateProductLink(product, color, toEditor = false) {
124
- console.log(product);
125
124
  const baseLink = `/${product.brand.alias}/${product.productType.alias}/${product.alias}`;
126
125
  return `${toEditor ? `${baseLink}/editor` : baseLink}${color ? `?color=${color.alias}` : ''}`;
127
126
  }
@@ -36,7 +36,6 @@ export default {
36
36
  if (!this.suburb && this.user?.suburb) {
37
37
  this.handleSuburbChange(this.user.suburb);
38
38
  }
39
- console.log('user: ', this.user);
40
39
  },
41
40
  methods: {
42
41
  ...mapMutations('cart', [
@@ -79,12 +79,16 @@
79
79
 
80
80
  <script>
81
81
  import { createNamespacedHelpers, mapGetters } from 'vuex';
82
+ import FileUploader from '@lancom/shared/components/common/file_uploader';
82
83
  import modals from '@lancom/shared/mixins/modals';
83
84
 
84
85
  const { mapActions, mapMutations } = createNamespacedHelpers('product');
85
86
 
86
87
  export default {
87
88
  name: 'EditorLayersToolbar',
89
+ components: {
90
+ FileUploader
91
+ },
88
92
  mixins: [
89
93
  modals
90
94
  ],
@@ -14,7 +14,22 @@
14
14
  }"
15
15
  @mouseenter="setActiveProduct(index)"
16
16
  @mouseleave="setActiveProduct(null)">
17
- <slot name="product" v-bind="{ product, full: activeProduct === index, toEditor }">
17
+ <slot
18
+ v-if="placeholder"
19
+ name="placeholder"
20
+ v-bind="{ product, full: activeProduct === index, toEditor }">
21
+ <product-list-product-placeholder
22
+ :product="product"
23
+ :to-editor="toEditor"
24
+ class="ProductList__item"
25
+ :class="{
26
+ 'ProductList__item--active': activeProduct === index
27
+ }" />
28
+ </slot>
29
+ <slot
30
+ v-else
31
+ name="product"
32
+ v-bind="{ product, full: activeProduct === index, toEditor }">
18
33
  <product-list-product
19
34
  :product="product"
20
35
  :to-editor="toEditor"
@@ -36,11 +51,13 @@
36
51
 
37
52
  <script>
38
53
  import ProductListProduct from '../product_list_product/product-list-product';
54
+ import ProductListProductPlaceholder from '../product_list_product_placeholder/product-list-product-placeholder';
39
55
 
40
56
  export default {
41
57
  name: 'LancomProductList',
42
58
  components: {
43
- ProductListProduct
59
+ ProductListProduct,
60
+ ProductListProductPlaceholder
44
61
  },
45
62
  props: {
46
63
  products: {
@@ -50,6 +67,10 @@ export default {
50
67
  toEditor: {
51
68
  type: Boolean,
52
69
  default: true
70
+ },
71
+ placeholder: {
72
+ type: Boolean,
73
+ default: true
53
74
  }
54
75
  },
55
76
  data() {
@@ -0,0 +1,52 @@
1
+ @import "@/assets/scss/variables";
2
+
3
+ .ProductListProductPlaceholder {
4
+ &__wrapper {
5
+ padding: 30px;
6
+ }
7
+ &__link {
8
+ position: absolute;
9
+ top: 0;
10
+ left: 0;
11
+ right: 0;
12
+ bottom: 0;
13
+ padding: 30px;
14
+ text-indent: -99999px;
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ flex-direction: column;
19
+ }
20
+ &__image {
21
+ width: 100%;
22
+ height: 250px;
23
+ animation-name: backgroundColorPalette;
24
+ animation-duration: 1s;
25
+ animation-iteration-count: infinite;
26
+ animation-direction: alternate;
27
+ }
28
+ &__info {
29
+ margin-top: 20px;
30
+ width: 100%;
31
+ height: 30px;
32
+ animation-name: backgroundColorPalette;
33
+ animation-duration: 1.5s;
34
+ animation-iteration-count: infinite;
35
+ animation-direction: alternate;
36
+ &--medium {
37
+ width: 80%;
38
+ }
39
+ &--small {
40
+ width: 60%;
41
+ }
42
+ }
43
+ }
44
+
45
+ @keyframes backgroundColorPalette {
46
+ 0% {
47
+ background: #efefef;
48
+ }
49
+ 100% {
50
+ background: #d9d9d9;
51
+ }
52
+ }
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <div class="ProductListProductPlaceholder__wrapper">
3
+ <nuxt-link
4
+ :to="productLink"
5
+ class="ProductListProductPlaceholder__link">
6
+ <span class="ProductListProductPlaceholder__image"></span>
7
+ <span class="ProductListProductPlaceholder__info ProductListProductPlaceholder__info--large"></span>
8
+ <span class="ProductListProductPlaceholder__info ProductListProductPlaceholder__info--medium"></span>
9
+ <span class="ProductListProductPlaceholder__info ProductListProductPlaceholder__info--small"></span>
10
+ {{ product.name }}
11
+ </nuxt-link>
12
+ </div>
13
+ </template>
14
+
15
+ <script>
16
+ import productPreview from '@lancom/shared/mixins/product-preview';
17
+
18
+ export default {
19
+ name: 'ProductListProductPlaceholder',
20
+ mixins: [productPreview]
21
+ };
22
+ </script>
23
+
24
+ <style lang="scss" scoped>
25
+ @import 'product-list-product-placeholder';
26
+ </style>
@@ -11,4 +11,36 @@
11
11
  display: none;
12
12
  }
13
13
  }
14
+ &__placeholder {
15
+ display: flex;
16
+ flex-direction: column;
17
+ margin-right: 20px;
18
+ }
19
+ &__info {
20
+ margin-top: 20px;
21
+ width: 100%;
22
+ height: 20px;
23
+ animation-name: backgroundColorPalette;
24
+ animation-duration: 1.5s;
25
+ animation-iteration-count: infinite;
26
+ animation-direction: alternate;
27
+ &--medium {
28
+ width: 85%;
29
+ }
30
+ &--small {
31
+ width: 70%;
32
+ }
33
+ &--small2 {
34
+ width: 55%;
35
+ }
36
+ }
37
+ }
38
+
39
+ @keyframes backgroundColorPalette {
40
+ 0% {
41
+ background: #efefef;
42
+ }
43
+ 100% {
44
+ background: #d9d9d9;
45
+ }
14
46
  }
@@ -2,38 +2,35 @@
2
2
  <div
3
3
  :data-aos="aosFadeRight"
4
4
  class="ProductsAside__wrapper">
5
- <!-- <div class="ProductsAside__item hidden-md-and-up">
6
- <input
7
- v-model="search"
8
- name="search"
9
- placeholder="Search"
10
- type="text"
11
- class="form-field no-label tiny-placeholder labelless"
12
- @change="goToTextSearch" />
13
- </div> -->
14
- <!-- <div class="ProductsAside__item">
15
- <products-types
16
- :has-selected-icon="hasSelectedIcon"
17
- :has-thumbs="hasThumbs" />
18
- </div> -->
19
- <div class="ProductsAside__item">
20
- <products-brands
21
- :has-selected-icon="hasSelectedIcon" />
5
+ <div
6
+ v-if="placeholder"
7
+ class="ProductsAside__placeholder">
8
+ <span class="ProductsAside__info ProductsAside__info--large"></span>
9
+ <span class="ProductsAside__info ProductsAside__info--medium"></span>
10
+ <span class="ProductsAside__info ProductsAside__info--small"></span>
11
+ <span class="ProductsAside__info ProductsAside__info--small2"></span>
22
12
  </div>
23
- <div class="ProductsAside__item">
24
- <products-colors />
25
- </div>
26
- <div class="ProductsAside__item">
27
- <products-attributes
28
- :has-selected-icon="hasSelectedIcon" />
29
- <products-tags
30
- :has-selected-icon="hasSelectedIcon" />
13
+ <div v-else>
14
+ <div class="ProductsAside__item">
15
+ <products-brands
16
+ :has-selected-icon="hasSelectedIcon" />
17
+ </div>
18
+ <div class="ProductsAside__item">
19
+ <products-colors />
20
+ </div>
21
+ <div class="ProductsAside__item">
22
+ <products-attributes
23
+ :has-selected-icon="hasSelectedIcon" />
24
+ <products-tags
25
+ :has-selected-icon="hasSelectedIcon" />
26
+ </div>
31
27
  </div>
32
28
  </div>
33
29
  </template>
34
30
 
35
31
  <script>
36
- import ProductsTypes from '@lancom/shared/components/products/products_types/products-types';
32
+ // import ProductsTypes from '@lancom/shared/components/products/products_types/products-types';
33
+ import { mapGetters } from 'vuex';
37
34
  import ProductsBrands from '@lancom/shared/components/products/products_brands/products-brands';
38
35
  import ProductsTags from '@lancom/shared/components/products/products_tags/products-tags';
39
36
  import ProductsAttributes from '@lancom/shared/components/products/products_attributes/products-attributes';
@@ -43,7 +40,7 @@ import { generateProductsLink } from '@lancom/shared/assets/js/utils/product';
43
40
  export default {
44
41
  name: 'ProductsAside',
45
42
  components: {
46
- ProductsTypes,
43
+ // ProductsTypes,
47
44
  ProductsBrands,
48
45
  ProductsTags,
49
46
  ProductsAttributes,
@@ -64,6 +61,9 @@ export default {
64
61
  search: this.$route.query.text || ''
65
62
  };
66
63
  },
64
+ computed: {
65
+ ...mapGetters('products', ['placeholder'])
66
+ },
67
67
  methods: {
68
68
  goToTextSearch() {
69
69
  this.goToPageWithFilters({ text: this.search });
@@ -3,8 +3,11 @@
3
3
  <div v-if="products">
4
4
  <slot
5
5
  name="list"
6
- v-bind="{ products, toEditor }">
7
- <product-list :products="products" :to-editor="toEditor" />
6
+ v-bind="{ products, toEditor, placeholder }">
7
+ <product-list
8
+ :products="products"
9
+ :to-editor="toEditor"
10
+ :placeholder="placeholder" />
8
11
  </slot>
9
12
  <pagination
10
13
  v-model="currentPage"
@@ -38,7 +41,8 @@ export default {
38
41
  'products',
39
42
  'page',
40
43
  'count',
41
- 'perPage'
44
+ 'perPage',
45
+ 'placeholder'
42
46
  ]),
43
47
  currentPage: {
44
48
  get() {
@@ -47,6 +51,7 @@ export default {
47
51
  set(page) {
48
52
  const link = generateProductsLink(this.$route, { page });
49
53
  this.$router.push(link);
54
+ window.scrollTo(0, 0);
50
55
  }
51
56
  }
52
57
  }
@@ -31,6 +31,7 @@
31
31
  'ProductsColors__color--selected': isSelectedColor(color)
32
32
  }">
33
33
  <product-color-image
34
+ v-if="canLoadImages"
34
35
  :color="color"
35
36
  class="ProductsColors__color-image" />
36
37
  </div>
@@ -53,6 +54,11 @@ export default {
53
54
  ProductsLink,
54
55
  ToggleContent
55
56
  },
57
+ data() {
58
+ return {
59
+ canLoadImages: false
60
+ };
61
+ },
56
62
  computed: {
57
63
  ...mapGetters('products', ['colors']),
58
64
  selectedColors() {
@@ -60,6 +66,11 @@ export default {
60
66
  return this.colors.filter(color => colors.includes(color.alias));
61
67
  }
62
68
  },
69
+ mounted() {
70
+ setTimeout(() => {
71
+ this.canLoadImages = true;
72
+ }, 1000);
73
+ },
63
74
  methods: {
64
75
  isSelectedColor(color) {
65
76
  return this.selectedColors.some(c => c._id === color._id);
@@ -297,11 +297,13 @@
297
297
  import api from '@lancom/shared/assets/js/api';
298
298
  import { mapGetters } from 'vuex';
299
299
  import CheckedIcon from '@lancom/shared/components/common/checked-icon';
300
+ import FileUploader from '@lancom/shared/components/common/file_uploader';
300
301
 
301
302
  export default {
302
303
  name: 'QuoteRequest',
303
304
  components: {
304
- CheckedIcon
305
+ CheckedIcon,
306
+ FileUploader
305
307
  },
306
308
  data() {
307
309
  return {
package/mixins/payment.js CHANGED
@@ -22,7 +22,6 @@ export default {
22
22
  },
23
23
  isSuccessOrderCharge() {
24
24
  const { charge, test, paymentMethod } = this.orderData || {};
25
- console.log('charge...', charge, test, paymentMethod);
26
25
  return charge?.success || test || paymentMethod === ORDER_PAYMENT_METHOD.DEPOSIT;
27
26
  },
28
27
  isFailedOrderCharge() {
@@ -4,6 +4,12 @@ import { generateProductLink } from '@lancom/shared/assets/js/utils/product';
4
4
 
5
5
  const getBgStyle = img => img && ({ 'background-image': `url("${img}")` });
6
6
 
7
+ const loadHolder = {
8
+ canLoadImages: false,
9
+ canLoadColorImages: false,
10
+ canLoadBackImages: false
11
+ };
12
+
7
13
  const productPreview = {
8
14
  props: {
9
15
  product: {
@@ -21,10 +27,20 @@ const productPreview = {
21
27
  data() {
22
28
  return {
23
29
  currentColor: null,
24
- productСoverLoaded: false
30
+ productСoverLoaded: false,
31
+ loadHolder
25
32
  };
26
33
  },
27
34
  computed: {
35
+ canLoadImages() {
36
+ return this.loadHolder.canLoadImages;
37
+ },
38
+ canLoadColorImages() {
39
+ return this.loadHolder.canLoadColorImages;
40
+ },
41
+ canLoadBackImages() {
42
+ return this.loadHolder.canLoadBackImages;
43
+ },
28
44
  previewTags() {
29
45
  return this.product.previewTags || [];
30
46
  },
@@ -38,9 +54,6 @@ const productPreview = {
38
54
  productLink() {
39
55
  return generateProductLink(this.product, this.currentColor, this.toEditor);
40
56
  },
41
- productСoverBig() {
42
- return getProductLargeCover(this.product, 'front', this.currentColor);
43
- },
44
57
  productСover() {
45
58
  return getProductMediumCover(this.product, 'front', this.currentColor);
46
59
  },
@@ -63,6 +76,17 @@ const productPreview = {
63
76
  hasTags() {
64
77
  return this.product?.tags.length > 0;
65
78
  }
79
+ },
80
+ mounted() {
81
+ if (process.client) {
82
+ setTimeout(() => {
83
+ this.loadHolder.canLoadImages = true;
84
+ }, 0);
85
+ setTimeout(() => {
86
+ this.loadHolder.canLoadBackImages = true;
87
+ this.loadHolder.canLoadColorImages = true;
88
+ }, 3000);
89
+ }
66
90
  }
67
91
  };
68
92
 
package/nuxt.config.js CHANGED
@@ -47,7 +47,6 @@ module.exports = (config, axios) => ({
47
47
  { src: '@/node_modules/@lancom/shared/plugins/vue-hummer', ssr: false },
48
48
  '@/node_modules/@lancom/shared/plugins/vue-multiselect',
49
49
  '@/node_modules/@lancom/shared/plugins/vue-tooltip',
50
- '@/node_modules/@lancom/shared/plugins/vue-color',
51
50
  '@/node_modules/@lancom/shared/plugins/vue-click-outside',
52
51
  { src: '@/node_modules/@lancom/shared/plugins/error-handler', ssr: false },
53
52
  { src: '@/node_modules/@lancom/shared/plugins/aos', ssr: false },
@@ -74,7 +73,11 @@ module.exports = (config, axios) => ({
74
73
  '@lancom',
75
74
  '@lancom/shared/plugins/aos-animation'
76
75
  ],
77
- extend(config, ctx) {}
76
+ extend(config, { isClient }) {
77
+ if (isClient) {
78
+ config.devtool = 'source-map';
79
+ }
80
+ }
78
81
  },
79
82
  feed: [{
80
83
  path: '/google-shopping.xml',
@@ -118,7 +121,7 @@ module.exports = (config, axios) => ({
118
121
  'g:google_product_category': { _text: 2047 },
119
122
  'g:product_type': { _text: `Home > Products > ${product.productType.name}`, },
120
123
  'g:is_bundle': { _text: product.prePrint ? 'yes' : 'no' },
121
- 'g:identifier_exists': 'yes',
124
+ 'g:identifier_exists': sp.gtin ? 'yes' : 'no',
122
125
  'g:product_weight': { _text: `${product.weight} kg` }
123
126
  };
124
127
  if (sp.gtin) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lancom/shared",
3
- "version": "0.0.87",
3
+ "version": "0.0.91",
4
4
  "description": "lancom common scripts",
5
5
  "author": "e.tokovenko <e.tokovenko@gmail.com>",
6
6
  "repository": {
@@ -1,14 +1,10 @@
1
1
  import Vue from 'vue';
2
2
  import Btn from '@lancom/shared/components/common/btn';
3
3
  import Spinner from '@lancom/shared/components/common/spinner';
4
- import FileUploader from '@lancom/shared/components/common/file_uploader';
5
4
  import Checkbox from '@lancom/shared/components/common/checkbox';
6
- import ColorPicker from '@lancom/shared/components/common/color-picker';
7
5
  import Breakpoint from '@lancom/shared/components/common/breakpoint';
8
6
 
9
7
  Vue.component('btn', Btn);
10
8
  Vue.component('spinner', Spinner);
11
- Vue.component('file-uploader', FileUploader);
12
9
  Vue.component('Checkbox', Checkbox);
13
- Vue.component('ColorPicker', ColorPicker);
14
10
  Vue.component('breakpoint', Breakpoint);
@@ -1,17 +1,22 @@
1
1
  import Vue from 'vue';
2
- import { VueReCaptcha } from 'vue-recaptcha-v3';
3
2
 
4
3
  export default () => {
5
- Vue.use(VueReCaptcha, {
6
- siteKey: process.env.RECAPTCHA_KEY,
7
- loaderOptions: {
8
- useRecaptchaNet: true
9
- }
10
- });
11
4
  Vue.mixin({
12
5
  methods: {
13
6
  async getRecaptcha(name) {
7
+ if (!this.$recaptcha) {
8
+ await this.loadReCaptcha();
9
+ }
14
10
  return process.env.IS_LOCAL === 'true' || await this.$recaptcha(name);
11
+ },
12
+ async loadReCaptcha() {
13
+ const { VueReCaptcha } = await import('vue-recaptcha-v3');
14
+ Vue.use(VueReCaptcha, {
15
+ siteKey: process.env.RECAPTCHA_KEY,
16
+ loaderOptions: {
17
+ useRecaptchaNet: true
18
+ }
19
+ });
15
20
  }
16
21
  }
17
22
  });
package/store/product.js CHANGED
@@ -133,7 +133,6 @@ export const actions = {
133
133
  commit('setProduct', response);
134
134
  commit('setPreSetPrint', (response.prints || []).find(({ _id }) => _id === print));
135
135
  } catch (e) {
136
- console.log(e);
137
136
  const { status, data } = e?.response || {};
138
137
  const statusCode = status || 500;
139
138
  commit('setLoadError', {
@@ -305,7 +304,6 @@ export const mutations = {
305
304
  ...(state.template.layers || []).filter(l => l.guid !== layer.guid),
306
305
  layer
307
306
  ];
308
- console.log('addTemplateLayer: ', layer);
309
307
  Vue.set(state.template, 'layers', layers);
310
308
  },
311
309
  removeTemplateLayer(state, layer) {
package/store/products.js CHANGED
@@ -10,7 +10,8 @@ export const state = () => ({
10
10
  brands: [],
11
11
  tags: [],
12
12
  attributes: [],
13
- loadError: null
13
+ loadError: null,
14
+ placeholder: false
14
15
  });
15
16
 
16
17
  export const getters = {
@@ -23,7 +24,8 @@ export const getters = {
23
24
  page: ({ page }) => page,
24
25
  count: ({ count }) => count,
25
26
  perPage: ({ perPage }) => perPage,
26
- loadError: ({ loadError }) => loadError
27
+ loadError: ({ loadError }) => loadError,
28
+ placeholder: ({ placeholder }) => placeholder
27
29
  };
28
30
 
29
31
  export const actions = {
@@ -55,6 +57,9 @@ export const actions = {
55
57
  };
56
58
 
57
59
  export const mutations = {
60
+ setPlaceholder(state, placeholder) {
61
+ state.placeholder = placeholder;
62
+ },
58
63
  setProducts(state, products) {
59
64
  state.products = products;
60
65
  },