@lancom/shared 0.0.294 → 0.0.296

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.
@@ -71,15 +71,16 @@ export class ArtLayer extends Layer {
71
71
  width = null;
72
72
  height = null;
73
73
 
74
- constructor(type, colorId, top, left, url, originalSize) {
74
+ constructor(type, colorId, top, left, url, originalSize, fileName) {
75
75
  super(colorId, top, left);
76
76
  this.type = type;
77
77
  this.url = url;
78
78
  this.originalSize = originalSize;
79
+ this.fileName = fileName;
79
80
  }
80
81
  };
81
82
 
82
- export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url, originalSize, sideId, properties = {} }) => {
83
+ export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url, originalSize, sideId, fileName, properties = {} }) => {
83
84
  if (!type) {
84
85
  throw new Error('When creating a new layer, you must specify its type');
85
86
  }
@@ -95,7 +96,7 @@ export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url,
95
96
  }
96
97
  break;
97
98
  case 'art':
98
- layer = new ArtLayer(type, colorId, top, left, url, originalSize);
99
+ layer = new ArtLayer(type, colorId, top, left, url, originalSize, fileName);
99
100
  break;
100
101
  default:
101
102
  throw new Error(`Layer type '${type}' not found or not supported.`);
@@ -7,7 +7,7 @@ export const isValidImageType = (i, type) => i.type === type || (i.types || []).
7
7
  export const isValidImageTypes = (i, types) => types.some(type => isValidImageType(i, type));
8
8
 
9
9
  export const getColorImage = (product = {}, size = 'small', type, color, allowAnyColor = false) => {
10
- const colorImage = color && (product.images || []).find(i => isValidImageType(i, type || COLORS_IMAGES_TYPES.FRONT) && (color._id === i.color || color._id === i.color._id));
10
+ const colorImage = color && (product.images || []).find(i => isValidImageType(i, type || COLORS_IMAGES_TYPES.FRONT) && (color?._id === i.color || color?._id === i.color?._id));
11
11
  const image = colorImage || (product.images || []).find(i => isValidImageType(i, type || COLORS_IMAGES_TYPES.FRONT) && (allowAnyColor || !i.color));
12
12
  return image && staticLink(image[size]);
13
13
  };
@@ -7,14 +7,13 @@ import { createObject } from './fabric/object-factory';
7
7
 
8
8
  const sizes = [];
9
9
 
10
- export function convertPrintToSVG(entity, sideId) {
10
+ export function convertPrintToSVG(layers, printSize) {
11
11
  return new Promise(resolve => {
12
- const svgSize = getSVGSize(entity, sideId);
12
+ const svgSize = getSVGSize(printSize);
13
+ console.log('svgSize: ', svgSize);
13
14
  const canvas = new fabric.Canvas(document.createElement('canvas'), { ...svgSize, uniScaleTransform: false });
14
-
15
- const sideLayers = getSideLayers(entity, sideId);
16
15
  Promise.all(
17
- sideLayers
16
+ layers
18
17
  .map(layer => {
19
18
  if (layer.type === 'art') {
20
19
  layer.url = layer.url.replace('thumb', 'origin');
@@ -27,7 +26,7 @@ export function convertPrintToSVG(entity, sideId) {
27
26
  .map(l => createObject(l, true))
28
27
  ).then(objects => {
29
28
  objects.forEach(object => {
30
- const zoom = svgSize.width / object.layer.printAreaSize.width;
29
+ const zoom = 1;
31
30
  let artOriginZoom = 1;
32
31
  if (object.layer.type === 'art') {
33
32
  artOriginZoom *= object.layer._width / object.width;
@@ -40,33 +39,26 @@ export function convertPrintToSVG(entity, sideId) {
40
39
  });
41
40
 
42
41
  let svg = canvas.toSVG();
43
- svg = insertFontsStyleToSvg(sideLayers, svg);
42
+ svg = insertFontsStyleToSvg(layers, svg);
44
43
  resolve(svg);
45
44
  });
46
45
  });
47
46
  }
48
47
 
49
- export function exportPrintToSVG(entity, sideId) {
50
- convertPrintToSVG(entity, sideId).then(svg => {
48
+ export function exportPrintToSVG(layers, printSize) {
49
+ convertPrintToSVG(layers, printSize).then(svg => {
51
50
  const blob = new Blob([svg], { type: 'image/svg+xml' });
52
- FileSaver.saveAs(blob, `${sideId}-${entity.guid}.svg`);
51
+ FileSaver.saveAs(blob, `Pint-${Date.now()}.svg`);
53
52
  });
54
53
  };
55
54
 
56
- function getSVGSize(entity, sideId) {
57
- const printArea = getPrintArea(entity, sideId);
58
- const printSize = sizes[printArea];
55
+ function getSVGSize(printSize) {
59
56
  return {
60
- width: printSize[0] * PIXELS_PER_CM,
61
- height: printSize[1] * PIXELS_PER_CM
57
+ width: printSize.width * PIXELS_PER_CM,
58
+ height: printSize.height * PIXELS_PER_CM
62
59
  };
63
60
  }
64
61
 
65
- function getPrintArea(entity, sideId) {
66
- const printAreas = entity.printAreas || {};
67
- return printAreas[sideId];
68
- }
69
-
70
62
  function getSideLayers(entity, sideId) {
71
63
  return (entity.layers || []).filter(layer => layer.sideId === sideId);
72
64
  }
@@ -3,9 +3,9 @@ import { fabric } from 'fabric';
3
3
 
4
4
  const sizes = [];
5
5
 
6
- export const buildWireframe = ({ width, height, editor, print }) => {
6
+ export const buildWireframe = ({ width, height, editor, print, printSize }) => {
7
7
  const layers = editor.getObjects();
8
- const printAreaSize = print.printSize;
8
+ const printAreaSize = printSize || print?.printSize || { width: 1, height: 1};
9
9
  const group = new fabric.Group(layers);
10
10
  const groupBounding = group.getBoundingRect();
11
11
  const ratioX = (width / groupBounding.width) * 0.8;
@@ -108,8 +108,8 @@ export const buildWireframe = ({ width, height, editor, print }) => {
108
108
  ], 'h');
109
109
  verticalArrow.set({ selectable: false });
110
110
  horizontalArrow.set({ selectable: false });
111
- const W = Math.round(groupBounding.width / printAreaSize.width);
112
- const H = Math.round(groupBounding.height / printAreaSize.height);
111
+ const W = Math.round(groupBounding.width / printAreaSize.width * 10);
112
+ const H = Math.round(groupBounding.height / printAreaSize.height * 10);
113
113
  const verticalSize = new fabric.Text(`H: ${H * 10}mm`, {
114
114
  top: bounding.top + (bounding.height / 2),
115
115
  left: 0,
@@ -220,8 +220,8 @@ export default class FabricHelper {
220
220
  });
221
221
  }
222
222
 
223
- buildWireframe({ width, height, print }) {
224
- buildWireframe({ width, height, editor: this.editor, print });
223
+ buildWireframe({ width, height, print, printSize }) {
224
+ buildWireframe({ width, height, editor: this.editor, print, printSize });
225
225
  }
226
226
 
227
227
  checkBoundingIntersection(object) {
@@ -1,4 +1,4 @@
1
- import { getProductSides } from './product';
1
+ import { getProductSides, getProductLayers } from './product';
2
2
  import { getPrintTypeSizePricing } from '@lancom/shared/assets/js/utils/prints';
3
3
 
4
4
  export function populateProductsFields(products, pricing) {
@@ -9,7 +9,8 @@ export function populateProductsFields(products, pricing) {
9
9
  const sides = getProductSides(product);
10
10
  const sidesKeys = [];
11
11
  sides.forEach(side => {
12
- const sideLayers = product.layers.filter(l => l.sideId === side);
12
+ const layers = getProductLayers(product);
13
+ const sideLayers = layers.filter(l => l.sideId === side);
13
14
  const lastModifiedLayer = sideLayers.sort((l1, l2) => l2.modifiedAt - l1.modifiedAt)[0];
14
15
  const key = `${side}-${lastModifiedLayer.modifiedAt}`;
15
16
 
@@ -23,7 +24,9 @@ export function populateProductsFields(products, pricing) {
23
24
  sideLayers.forEach(l => {
24
25
  l.printId = printId;
25
26
  });
26
-
27
+ if (!product.printIds) {
28
+ product.printIds = {};
29
+ }
27
30
  product.printIds[side] = printId;
28
31
  });
29
32
 
@@ -21,11 +21,18 @@ export function getPrintAreaSizes({ printSize, sizes = [] }) {
21
21
  };
22
22
 
23
23
  export const generatePrintLayer = layer => {
24
- return {
24
+ const model = {
25
25
  ...layer,
26
26
  text: layer.copy,
27
27
  params: layer
28
28
  };
29
+ if (layer.url) {
30
+ model.file = {
31
+ fileName: layer.fileName,
32
+ origin: layer.url
33
+ }
34
+ }
35
+ return model
29
36
  };
30
37
 
31
38
  export function getPrintsFromLayers(layers, product) {
@@ -58,12 +58,21 @@ export function generateCartProducts(mainProduct, simpleProducts, layers, hasPri
58
58
  // });
59
59
  }
60
60
 
61
- export function getProductSides({ layers = [] }) {
61
+ export function getProductLayers(product, layersSideId) {
62
+ const layers = (product?.prints || [])
63
+ .reduce((layers, print) => [
64
+ ...layers,
65
+ ...(print.layers || []).map(l => ({ ...(l.params || {}) }))
66
+ ], []);
67
+ return layers.filter(({ sideId }) => !layersSideId || sideId === layersSideId);
68
+ }
69
+
70
+ export function getProductSides(product) {
71
+ const layers = getProductLayers(product);
62
72
  const sidesSet = layers.reduce((sides, layer) => {
63
73
  sides.add(layer.sideId);
64
74
  return sides;
65
75
  }, new Set());
66
-
67
76
  return [...sidesSet];
68
77
  }
69
78
 
@@ -10,6 +10,16 @@
10
10
  side="front"
11
11
  size="medium" />
12
12
  </div>
13
+ <div
14
+ v-if="entity && entity.printsThumbnails && entity.printsThumbnails.back"
15
+ class="CartEntityColorSimpleProducts__image"
16
+ @click="showImage(images, 1)">
17
+ <product-side-with-print
18
+ :product="group"
19
+ :default-preview="defaultPreview"
20
+ side="back"
21
+ size="medium" />
22
+ </div>
13
23
  </div>
14
24
  <div class="CartEntityColorSimpleProducts__info">
15
25
  <div class="CartEntityColorSimpleProducts__features">
@@ -82,7 +82,8 @@ export default {
82
82
  },
83
83
  image() {
84
84
  const color = this.defaultPreview ? null : this.product.color;
85
- return getColorImage(this.product, this.size, this.side, color) || getProductCover(this.product, this.size, this.side, color);
85
+ const product = this.product?.product || this.product;
86
+ return getColorImage(product, this.size, this.side, color) || getProductCover(product, this.size, this.side, color);
86
87
  },
87
88
  print() {
88
89
  const { printsThumbnails = {} } = this.product || {};
@@ -75,7 +75,6 @@
75
75
 
76
76
  <script>
77
77
  import { mapGetters, mapActions, mapMutations } from 'vuex';
78
- import { generateCartProducts } from '@lancom/shared/assets/js/utils/product';
79
78
  import modals from '@lancom/shared/mixins/modals';
80
79
  import confirmModal from '@lancom/shared/mixins/confirm';
81
80
  import OfferScreenPrinting from '@lancom/shared/components/asides/offer_screen_printing/offer-screen-printing';
@@ -103,8 +103,8 @@ export default {
103
103
  const layer = await this.createLayer({ type: 'text' });
104
104
  this.$emit('layer-added', { layer, toEditMode: true });
105
105
  },
106
- async handleUploaded({ url, size }) {
107
- const layer = await this.createLayer({ type: 'art', url, size });
106
+ async handleUploaded({ url, size, fileName }) {
107
+ const layer = await this.createLayer({ type: 'art', url, size, fileName });
108
108
  this.$emit('layer-added', { layer, toEditMode: false });
109
109
  }
110
110
  }
@@ -6,14 +6,15 @@
6
6
  align-items: center;
7
7
  justify-content: center;
8
8
  padding: 8px 0;
9
+ flex-wrap: wrap;
9
10
  &.singleRow {
10
11
  grid-template-columns: repeat(4, 1fr);
11
12
  }
12
13
  }
13
14
 
14
15
  &__option {
15
- margin: 0 5px;
16
- min-width: 150px;
16
+ margin: 0 5px 10px 5px;
17
+ min-width: 144px;
17
18
  display: flex;
18
19
  align-items: center;
19
20
  justify-content: center;
@@ -35,7 +35,7 @@
35
35
  top: -90px;
36
36
  left: calc((-720px + 100vw) / 2);
37
37
  max-width: none;
38
- z-index: 104;
38
+ z-index: 9999;
39
39
  }
40
40
  }
41
41
  &-toggle {
@@ -86,7 +86,7 @@
86
86
  position: sticky;
87
87
  bottom: 20px;
88
88
  background: white;
89
- width: 296px;
89
+ width: 310px;
90
90
  @media (min-width: $bp-small-min) {
91
91
  width: 580px;
92
92
  }
@@ -8,7 +8,7 @@
8
8
  bottom: 0;
9
9
  left: 0;
10
10
  height: 78px;
11
- z-index: 105;
11
+ z-index: 10000;
12
12
  display: grid;
13
13
  grid-template-columns: repeat(3, 1fr);
14
14
  background-color: $white_high_emphasis;
@@ -115,7 +115,7 @@
115
115
  Account name: {{ depositInfo.accountName }}
116
116
  </div>
117
117
  <div class="lc_regular16">
118
- BSB: {{ depositInfo.BSB }}
118
+ {{ bsbLabel }}: {{ depositInfo.BSB }}
119
119
  </div>
120
120
  <div class="lc_regular16">
121
121
  Account: {{ depositInfo.account }}
@@ -205,6 +205,7 @@
205
205
  </template>
206
206
 
207
207
  <script>
208
+ import { mapGetters } from 'vuex';
208
209
  import OrderViewMixin from './order-view.mixin';
209
210
  import OrderViewProduct from './order_view_product/order-view-product';
210
211
 
@@ -219,6 +220,12 @@ export default {
219
220
  type: Boolean,
220
221
  default: true
221
222
  }
223
+ },
224
+ computed: {
225
+ ...mapGetters(['MESSAGES']),
226
+ bsbLabel() {
227
+ return this.MESSAGES.DIRECT_DEPOSIT_BSB || 'BSB';
228
+ },
222
229
  }
223
230
  };
224
231
  </script>
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <div class="ProductPrintPreview__wrapper">
3
+ <canvas ref="print"></canvas>
4
+ <div
5
+ class="ProductPrintPreview__export"
6
+ @click="exportPrintToSVG">
7
+ Export To SVG
8
+ </div>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ import { exportPrintToSVG } from '@lancom/shared/assets/js/utils/export-print-to-svg';
14
+ import FabricHelper from '@lancom/shared/assets/js/utils/fabric-helper';
15
+
16
+ export default {
17
+ name: 'ProductPrintPreview',
18
+ data() {
19
+ return {
20
+ fabricHelper: null,
21
+ size: {
22
+ width: 540,
23
+ height: 540
24
+ }
25
+ };
26
+ },
27
+ props: {
28
+ product: {
29
+ type: Object,
30
+ required: true
31
+ },
32
+ print: {
33
+ type: Object,
34
+ required: true
35
+ },
36
+ printSize: {
37
+ type: Object,
38
+ required: true
39
+ }
40
+ },
41
+ computed: {
42
+ layers() {
43
+ const layers = (this.print.layers || [])
44
+ .filter(l => !!l.params)
45
+ .map(l => ({ ...l.params }));
46
+ return layers;
47
+ }
48
+ },
49
+ async mounted() {
50
+ console.log('print: ', this.print);
51
+ this.fabricHelper = new FabricHelper({
52
+ editor: this.$refs.print,
53
+ size: this.size
54
+ });
55
+ await this.drawLayers();
56
+ this.fabricHelper.buildWireframe({
57
+ ...this.size,
58
+ // area: product.printAreas[this.sideId],
59
+ printSize: this.printSize,
60
+ product: this.product
61
+ });
62
+ },
63
+ methods: {
64
+ drawLayers() {
65
+ return this.layers.reduce(async (promise, layer) => {
66
+ await promise;
67
+ return new Promise(resolve => {
68
+ this.fabricHelper.createObject({ layer }).then(obj => {
69
+ resolve();
70
+ });
71
+ });
72
+ }, Promise.resolve());
73
+ },
74
+ exportPrintToSVG() {
75
+ exportPrintToSVG(this.layers, this.printSize);
76
+ }
77
+ }
78
+ };
79
+ </script>
80
+
81
+ <style lang="scss" scoped>
82
+ .ProductPrintPreview {
83
+ &__wrapper {
84
+ width: 540px;
85
+ height: 540px;
86
+ position: relative;
87
+ // background-image: url(~static/images/trasnparent-pattern.png);
88
+ canvas {
89
+ // border: 2px solid blue;
90
+ }
91
+ }
92
+ &__export {
93
+ position: absolute;
94
+ top: 50px;
95
+ right: 50px;
96
+ display: inline-block;
97
+ padding: 10px;
98
+ cursor: pointer;
99
+ background: rgb(110, 217, 246);
100
+ z-index: 99;
101
+ }
102
+ }
103
+ </style>
@@ -39,7 +39,7 @@
39
39
  <div
40
40
  v-if="product.quantityStock"
41
41
  class="ProductSizeSelectorColor__in-stock">
42
- {{ currentQuantityStock }} in stock
42
+ {{ currentQuantityStockLabel }} in stock
43
43
  </div>
44
44
  <div
45
45
  v-else
@@ -52,7 +52,7 @@
52
52
  <div
53
53
  v-if="product.quantityStock"
54
54
  class="ProductSizeSelectorColor__in-stock">
55
- {{ currentQuantityStock }} in stock
55
+ {{ currentQuantityStockLabel }} in stock
56
56
  </div>
57
57
  <div
58
58
  v-else
@@ -104,6 +104,9 @@ export default {
104
104
  computed: {
105
105
  ...mapGetters('product', ['isPrintPricing', 'usedSimpleProductsQuantity']),
106
106
  ...mapGetters(['gstTax', 'currency']),
107
+ currentQuantityStockLabel() {
108
+ return this.currentQuantityStock > 100 ? '100+' : this.currentQuantityStock;
109
+ },
107
110
  pricing() {
108
111
  return (this.isPrintPricing ? this.product.pricing : this.product.unprintedPricing) || [];
109
112
  },
@@ -41,7 +41,7 @@
41
41
  <div><b>{{ MESSAGES.DIRECT_DEPOSIT_DETAILS || 'DIRECT DEPOSIT DETAILS'}}</b></div>
42
42
  <div>Bank: {{ depositInfo.bank }}</div>
43
43
  <div>Account name: {{ depositInfo.accountName }}</div>
44
- <div>BSB: {{ depositInfo.BSB }}</div>
44
+ <div>{{ bsbLabel }}: {{ depositInfo.BSB }}</div>
45
45
  <div>Account: {{ depositInfo.account }}</div>
46
46
  </td>
47
47
  </tr>
@@ -62,6 +62,7 @@
62
62
  </template>
63
63
 
64
64
  <script>
65
+ import { mapGetters } from 'vuex';
65
66
  import QuoteViewMixin from './quote-view.mixin';
66
67
  import QuoteOptionView from './quote_option_view/quote-option-view';
67
68
 
@@ -70,7 +71,13 @@ export default {
70
71
  components: {
71
72
  QuoteOptionView
72
73
  },
73
- mixins: [QuoteViewMixin]
74
+ mixins: [QuoteViewMixin],
75
+ computed: {
76
+ ...mapGetters(['MESSAGES']),
77
+ bsbLabel() {
78
+ return this.MESSAGES.DIRECT_DEPOSIT_BSB || 'BSB';
79
+ },
80
+ }
74
81
  };
75
82
  </script>
76
83
 
@@ -14,6 +14,11 @@ async function googleLocalShoppingFeed(axios, config, availableStores, country)
14
14
  .map(i => fields.reduce((item, field) => ({ ...item, [field]: i[field] }), {}));
15
15
  return result;
16
16
  }
17
+
18
+ const COUNTRIES_SIZE_SYSTEMS = {
19
+ GB: 'UK'
20
+ };
21
+
17
22
  async function googleShoppingFeed(axios, config, availableStores, country) {
18
23
  const { data } = await axios.get(`${config.LOCAL_API_URL}/feed/products?host=${config.HOST_NAME}&country=${country || ''}`);
19
24
  const spliceFirstImage = images => (images || []).splice(0, 1)[0];
@@ -58,7 +63,7 @@ async function googleShoppingFeed(axios, config, availableStores, country) {
58
63
  'g:id': { _text: sp.SKU },
59
64
  'g:item_group_id': { _text: product.SKU },
60
65
  'g:size': { _text: sp.size.name },
61
- 'g:size_system': country || 'AU',
66
+ 'g:size_system': COUNTRIES_SIZE_SYSTEMS[country] || country || 'AU',
62
67
  'g:size_type': 'regular',
63
68
  'g:gender': { _text: product.gender },
64
69
  'g:material': { _text: product.fabricInfoShort },
@@ -22,6 +22,9 @@ export default {
22
22
  'calculatingPrice',
23
23
  'multipack'
24
24
  ]),
25
+ ...mapGetters('layers', [
26
+ 'layerThumbnails'
27
+ ]),
25
28
  isValidOrderQuantity() {
26
29
  return this.isValidBigSizeOrderQuantity && this.isValidMiltipackOrderQuantity && (!this.minimumOrderQuantity || this.usedSimpleProductsQuantity >= this.minimumOrderQuantity);
27
30
  },
@@ -40,7 +43,7 @@ export default {
40
43
  ...mapMutations('product', ['clearTemplate', 'setIsPrintPricing']),
41
44
  ...mapMutations('layers', ['resetLayers']),
42
45
  async proceedToCard() {
43
- const entities = generateCartProducts(this.product, this.template.simpleProducts, this.template.layers, this.isPrintPricing);
46
+ const entities = generateCartProducts(this.product, this.template.simpleProducts, this.template.layers, this.isPrintPricing, this.layerThumbnails);
44
47
  await this.addToCart({
45
48
  entities,
46
49
  shop: this.shop,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lancom/shared",
3
- "version": "0.0.294",
3
+ "version": "0.0.296",
4
4
  "description": "lancom common scripts",
5
5
  "author": "e.tokovenko <e.tokovenko@gmail.com>",
6
6
  "repository": {
package/store/layers.js CHANGED
@@ -19,6 +19,7 @@ export const actions = {
19
19
 
20
20
  export const mutations = {
21
21
  setLayersThumbnail(state, { side, value }) {
22
+ console.log('setLayersThumbnail: ', side, value);
22
23
  Vue.set(state.layerThumbnails, side, value);
23
24
  },
24
25
  setEditableLayer(state, layer) {
package/store/product.js CHANGED
@@ -220,7 +220,8 @@ export const actions = {
220
220
  preselect = true,
221
221
  isEditMode,
222
222
  size,
223
- properties
223
+ properties,
224
+ fileName
224
225
  }
225
226
  ) {
226
227
  const { center: { top, left } } = getters.printArea;
@@ -230,6 +231,7 @@ export const actions = {
230
231
  top,
231
232
  left,
232
233
  isEditMode,
234
+ fileName,
233
235
  url,
234
236
  originalSize: size,
235
237
  sideId: getters.editableSide?.id,