@lancom/shared 0.0.310 → 0.0.312

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.
@@ -3,7 +3,7 @@ import { fabric } from 'fabric';
3
3
 
4
4
  const sizes = [];
5
5
 
6
- export const buildWireframe = ({ width, height, editor, print, printSize }) => {
6
+ export const buildWireframe = ({ width, height, editor, print, printSize, hiddenFrame }) => {
7
7
  const layers = editor.getObjects();
8
8
  const printAreaSize = printSize || print?.printSize || { width: 1, height: 1};
9
9
  const group = new fabric.Group(layers);
@@ -133,11 +133,14 @@ export const buildWireframe = ({ width, height, editor, print, printSize }) => {
133
133
  horizontalSize.set({
134
134
  left: horizontalSize.left - horizontalSize.width / 2
135
135
  });
136
- editor.add(verticalLine);
137
- editor.add(horizontallLine);
138
- editor.add(verticalArrow);
139
- editor.add(horizontalArrow);
140
- editor.add(verticalSize);
141
- editor.add(horizontalSize);
142
- editor.add(bounding);
136
+ console.log('hiddenFrame: ', hiddenFrame);
137
+ if (!hiddenFrame) {
138
+ editor.add(verticalLine);
139
+ editor.add(horizontallLine);
140
+ editor.add(verticalArrow);
141
+ editor.add(horizontalArrow);
142
+ editor.add(verticalSize);
143
+ editor.add(horizontalSize);
144
+ editor.add(bounding);
145
+ }
143
146
  };
@@ -192,7 +192,6 @@ export default class FabricHelper {
192
192
 
193
193
  createObject({ layer, active }) {
194
194
  const initial = !layer.modifiedAt;
195
- console.log('createObject...', layer.type, layer.top, layer.left);
196
195
  return new Promise(resolve => {
197
196
  const methods = {
198
197
  text: 'createTextObject',
@@ -220,8 +219,8 @@ export default class FabricHelper {
220
219
  });
221
220
  }
222
221
 
223
- buildWireframe({ width, height, print, printSize }) {
224
- buildWireframe({ width, height, editor: this.editor, print, printSize });
222
+ buildWireframe({ width, height, print, printSize, hiddenFrame }) {
223
+ buildWireframe({ width, height, editor: this.editor, print, printSize, hiddenFrame });
225
224
  }
226
225
 
227
226
  checkBoundingIntersection(object) {
@@ -363,7 +362,10 @@ export default class FabricHelper {
363
362
  }
364
363
 
365
364
  getLayersAsImage() {
366
- const data = this.editor.toDataURL('png');
365
+ const data = this.editor.toDataURL({
366
+ format: 'png',
367
+ multiplier: this.editor.width < 500 ? 2 : 1
368
+ });
367
369
  this.editor.renderAll();
368
370
  return data;
369
371
  }
@@ -7,10 +7,11 @@ export function generateLayersTemplate(template, printArea) {
7
7
  }));
8
8
  }
9
9
 
10
- export function fitLayerToEditorSize(layer, { size }, { width, height, top, left }) {
11
- const scaleKoef = (width < height ? width / size.width : height / size.height) - 0.02;
12
- layer.top = top + layer.top * scaleKoef + (Math.abs(size.height * scaleKoef - height) / 2) - 4;
13
- layer.left = left + layer.left * scaleKoef + Math.abs((size.width * scaleKoef - width) / 2) - 3;
10
+ export function fitLayerToEditorSize(layer, { size }, printArea) {
11
+ const { width, height, top, left } = printArea;
12
+ const scaleKoef = width / size.width;
13
+ layer.top = top + layer.top * scaleKoef - 5 + (height - size.height * scaleKoef) / 2;
14
+ layer.left = left + layer.left * scaleKoef - 5 + (width - size.width * scaleKoef) / 2;
14
15
  ['fontSize', 'scaleX', 'scaleY'].forEach(property => {
15
16
  if (property in layer) {
16
17
  const originalSize = layer[property];
@@ -24,13 +24,13 @@
24
24
  </template>
25
25
 
26
26
  <script>
27
- import messages from '@/messages';
27
+ import { MESSAGES } from '@/messages';
28
28
 
29
29
  export default {
30
30
  name: 'PaymentSuccess',
31
31
  data() {
32
32
  return {
33
- messages
33
+ messages: MESSAGES
34
34
  };
35
35
  },
36
36
  props: {
@@ -1,6 +1,17 @@
1
1
  @import "@/assets/scss/variables";
2
2
 
3
3
  .EditorWorkspace {
4
+ &__preloading {
5
+ position: absolute;
6
+ top: 0;
7
+ right: 0;
8
+ bottom: 0;
9
+ left: 0;
10
+ background-color: white;
11
+ display: flex;
12
+ justify-content: center;
13
+ z-index: 1;
14
+ }
4
15
  &__sides {
5
16
  position: relative;
6
17
  width: 100%;
@@ -1,5 +1,10 @@
1
1
  <template>
2
2
  <div class="EditorWorkspace__wrapper">
3
+ <div
4
+ v-if="preloading"
5
+ class="EditorWorkspace__preloading">
6
+ <placeholder />
7
+ </div>
3
8
  <breakpoint
4
9
  name="md"
5
10
  mode="up">
@@ -17,7 +22,7 @@
17
22
  class="EditorWorkspace__sides rotate-y-container"
18
23
  :class="{rotating: isRotating}">
19
24
  <transition
20
- name="rotate"
25
+ :name="preloading ? 'empty' : 'rotate'"
21
26
  mode="in-out"
22
27
  @before-enter="isRotating = true"
23
28
  @after-leave="isRotating = false">
@@ -50,7 +55,7 @@
50
55
  class="EditorWorkspace__sides rotate-y-container"
51
56
  :class="{rotating: isRotating}">
52
57
  <transition
53
- name="rotate"
58
+ :name="preloading ? 'empty' : 'rotate'"
54
59
  mode="in-out"
55
60
  @before-enter="isRotating = true"
56
61
  @after-leave="isRotating = false">
@@ -72,7 +77,7 @@
72
77
  :class="{
73
78
  'EditorWorkspace__sides-toggle--fixed': isZoomIn
74
79
  }"
75
- @click="toggleSide">
80
+ @click="toggleSide()">
76
81
  <i class="icon-rotate-tee"></i>
77
82
  </div>
78
83
  <div
@@ -108,6 +113,7 @@ import { createNamespacedHelpers } from 'vuex';
108
113
  import EditorPrintAreaOptions from '@lancom/shared/components/editor/editor_print_area_options/editor-print-area-options';
109
114
  import EditorPricing from '@lancom/shared/components/product/editor_pricing/editor-pricing';
110
115
  import Tabs from '@lancom/shared/components/common/tabs';
116
+ import Placeholder from '@lancom/shared/components/placeholder/placeholder';
111
117
  import EditorWorkspaceSide from './editor_workspace_side/editor-workspace-side';
112
118
 
113
119
  const { mapGetters, mapMutations } = createNamespacedHelpers('product');
@@ -115,6 +121,7 @@ const { mapGetters, mapMutations } = createNamespacedHelpers('product');
115
121
  export default {
116
122
  name: 'EditorWorkspace',
117
123
  components: {
124
+ Placeholder,
118
125
  EditorWorkspaceSide,
119
126
  EditorPrintAreaOptions,
120
127
  EditorPricing,
@@ -122,6 +129,7 @@ export default {
122
129
  },
123
130
  data() {
124
131
  return {
132
+ preloading: true,
125
133
  isRotating: false,
126
134
  zoomSize: null,
127
135
  productSides: [
@@ -146,22 +154,38 @@ export default {
146
154
  return !!this.zoomSize;
147
155
  }
148
156
  },
157
+ mounted() {
158
+ this.preloadingEditor();
159
+ },
149
160
  methods: {
150
161
  ...mapMutations([
151
162
  'setEditableSide',
152
163
  'setSelectedPrintArea',
153
164
  'setEditablePrintArea'
154
165
  ]),
166
+ async preloadingEditor() {
167
+ this.preloading = true;
168
+ const sides = ['back', 'front'];
169
+ for (const side of sides) {
170
+ await (new Promise((resolve) => {
171
+ setTimeout(() => {
172
+ this.toggleSide(side);
173
+ resolve();
174
+ }, 500);
175
+ }));
176
+ }
177
+ this.preloading = false;
178
+ },
155
179
  selectTab(value) {
156
180
  if (this.editableSide.id !== value) {
157
181
  this.setEditablePrintArea(null);
158
182
  this.setEditableSide({ id: value });
159
183
  }
160
184
  },
161
- toggleSide() {
185
+ toggleSide(side) {
162
186
  this.setEditablePrintArea(null);
163
187
  this.setEditableSide({
164
- id: this.editableSide.id === 'front' ? 'back' : 'front'
188
+ id: side || (this.editableSide.id === 'front' ? 'back' : 'front')
165
189
  });
166
190
  },
167
191
  selectPrintArea({ printArea, size }) {
@@ -48,7 +48,7 @@
48
48
  @click="hide">
49
49
  </div>
50
50
  <div
51
- v-if="isOpen"
51
+ v-show="isOpen"
52
52
  key="container"
53
53
  class="MobileEditorProductDetails__container"
54
54
  @close="hide">
@@ -46,32 +46,35 @@ export default {
46
46
  depositInfo() {
47
47
  return this.settings?.depositInfo || {};
48
48
  },
49
+ displayAddress() {
50
+ return this.invoice?.address || this.order.billingAddress || this.order.shippingAddress;
51
+ },
49
52
  fullName() {
50
- return this.invoice?.address?.fullName || this.order.shippingAddress.fullName;
53
+ return this.displayAddress.fullName;
51
54
  },
52
55
  company() {
53
- return this.invoice?.address?.company || this.order.shippingAddress.company;
56
+ return this.displayAddress.company;
54
57
  },
55
58
  phone() {
56
- return this.invoice?.address?.phone || this.order.shippingAddress.phone;
59
+ return this.displayAddress.phone;
57
60
  },
58
61
  email() {
59
- return this.invoice?.address?.email || this.order.shippingAddress.email;
62
+ return this.displayAddress.email;
60
63
  },
61
64
  additionalInfo() {
62
- return this.invoice?.address?.additionalInfo || this.order.shippingAddress.additionalInfo;
65
+ return this.displayAddress.additionalInfo;
63
66
  },
64
67
  purchaseOrderNumber() {
65
68
  return this.invoice?.purchaseOrderNumber || this.order.purchaseOrderNumber;
66
69
  },
67
70
  orderAddress() {
68
71
  return [
69
- this.invoice?.address?.addressLine1 || this.order.shippingAddress.addressLine1,
70
- this.invoice?.address?.addressLine2 || this.order.shippingAddress.addressLine2,
71
- this.invoice?.address?.city || this.order.shippingAddress.city,
72
- this.invoice?.address?.postcode || this.order.shippingAddress.postcode,
73
- this.invoice?.address?.state || this.order.shippingAddress.state,
74
- this.invoice?.address?.country || this.order.shippingAddress.country
72
+ this.displayAddress.addressLine1,
73
+ this.displayAddress.addressLine2,
74
+ this.displayAddress.city,
75
+ this.displayAddress.postcode,
76
+ this.displayAddress.state,
77
+ this.displayAddress.country
75
78
  ].filter(i => !!i).join(', ');
76
79
  },
77
80
  gstTax() {
@@ -3,21 +3,33 @@
3
3
  <canvas ref="print"></canvas>
4
4
  <div
5
5
  class="ProductPrintPreview__export"
6
- @click="exportPrintToSVG">
7
- Export To SVG
6
+ @click="exportPrintToPNG">
7
+ Export To PNG
8
+ </div>
9
+ <div
10
+ class="ProductPrintPreview__frame"
11
+ @click="hiddenFrame = !hiddenFrame">
12
+ {{ hiddenFrame ? 'Show' : 'Hide'}} Frame
8
13
  </div>
9
14
  </div>
10
15
  </template>
11
16
 
12
17
  <script>
13
- import { exportPrintToSVG } from '@lancom/shared/assets/js/utils/export-print-to-svg';
18
+ import FileSaver from 'file-saver';
14
19
  import FabricHelper from '@lancom/shared/assets/js/utils/fabric-helper';
15
20
 
16
21
  export default {
17
22
  name: 'ProductPrintPreview',
23
+ watch: {
24
+ hiddenFrame() {
25
+ this.fabricHelper.clear();
26
+ this.draw();
27
+ }
28
+ },
18
29
  data() {
19
30
  return {
20
31
  fabricHelper: null,
32
+ hiddenFrame: true,
21
33
  size: {
22
34
  width: 540,
23
35
  height: 540
@@ -46,23 +58,27 @@ export default {
46
58
  return layers;
47
59
  }
48
60
  },
49
- async mounted() {
50
- console.log('print: ', this.print);
61
+ mounted() {
51
62
  this.fabricHelper = new FabricHelper({
52
63
  editor: this.$refs.print,
53
64
  size: this.size
54
65
  });
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
- });
66
+ this.draw();
62
67
  },
63
68
  methods: {
69
+ async draw() {
70
+ await this.drawLayers();
71
+ this.fabricHelper.buildWireframe({
72
+ ...this.size,
73
+ // area: product.printAreas[this.sideId],
74
+ printSize: this.printSize,
75
+ product: this.product,
76
+ hiddenFrame: this.hiddenFrame
77
+ });
78
+ },
64
79
  drawLayers() {
65
- return this.layers.reduce(async (promise, layer) => {
80
+ const layers = JSON.parse(JSON.stringify(this.layers));
81
+ return layers.reduce(async (promise, layer) => {
66
82
  await promise;
67
83
  return new Promise(resolve => {
68
84
  this.fabricHelper.createObject({ layer }).then(obj => {
@@ -71,8 +87,15 @@ export default {
71
87
  });
72
88
  }, Promise.resolve());
73
89
  },
74
- exportPrintToSVG() {
75
- exportPrintToSVG(this.layers, this.printSize);
90
+ async exportPrintToPNG() {
91
+ const data = this.fabricHelper.editor.toDataURL({
92
+ format: 'png',
93
+ multiplier: 3
94
+ });
95
+ const response = await fetch(data);
96
+ const blob = await response.blob();
97
+ const file = new Blob([blob], {type: 'image/png'});
98
+ FileSaver.saveAs(file, `Print-${Date.now()}.png`);
76
99
  }
77
100
  }
78
101
  };
@@ -89,15 +112,20 @@ export default {
89
112
  // border: 2px solid blue;
90
113
  }
91
114
  }
92
- &__export {
115
+ &__export,
116
+ &__frame {
93
117
  position: absolute;
94
118
  top: 50px;
95
119
  right: 50px;
96
120
  display: inline-block;
97
- padding: 10px;
121
+ padding: 6px;
122
+ font-size: 13px;
98
123
  cursor: pointer;
99
124
  background: rgb(110, 217, 246);
100
125
  z-index: 99;
101
126
  }
127
+ &__frame {
128
+ top: 90px;
129
+ }
102
130
  }
103
131
  </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="Wizard__wrapper">
3
3
  <div
4
- v-if="preSetPrints"
4
+ v-if="hasPresetPrints"
5
5
  class="Wizard__header Wizard__header--active">
6
6
  <div class="Wizard__header-name">
7
7
  PRINT OPTIONS
@@ -43,7 +43,7 @@
43
43
  @edit="editLayer($event)"
44
44
  @delete="removeTemplateLayer($event)" />
45
45
  <div
46
- v-if="!preSetPrints"
46
+ v-if="!hasPresetPrints"
47
47
  class="Wizard__layers-info">
48
48
  <p>1. Note final print price will be calculated once garment quantity is finalised</p>
49
49
  <p>2. PDF mockup will be provided for approval prior to printing</p>
@@ -190,10 +190,13 @@ export default {
190
190
  },
191
191
  productPrintAreas() {
192
192
  return this.product.printAreas || [];
193
+ },
194
+ hasPresetPrints() {
195
+ return this.preSetPrints?.length > 0
193
196
  }
194
197
  },
195
198
  mounted() {
196
- if (this.product.printOnly || this.preSetPrints || this.layers.length > 0) {
199
+ if (this.product.printOnly || this.hasPresetPrints || this.layers.length > 0) {
197
200
  this.isVisible = true;
198
201
  this.setIsPrintPricing(this.isVisible);
199
202
  }
@@ -57,7 +57,7 @@
57
57
  <div
58
58
  v-if="noMinimum"
59
59
  class="ProductListProduct__tag-item ProductListProduct__tag-item--qty">
60
- <span>No Mimimums</span>
60
+ <span>No Minimums</span>
61
61
  </div>
62
62
  <div
63
63
  v-if="!noMinimum && product.minimumPrintOrderQuantity > 0"
@@ -110,7 +110,7 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING) => ({
110
110
  }
111
111
 
112
112
  try {
113
- if (this.preSetPrints) {
113
+ if (this.preSetPrints?.length) {
114
114
  for (const preSetPrint of this.preSetPrints) {
115
115
  const layers = preSetPrint.printTemplate?.layers || [{ type: 'text' }];
116
116
  for (const layer of layers) {
@@ -140,6 +140,7 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING) => ({
140
140
  properties
141
141
  };
142
142
  const model = await getLayerModel(data);
143
+ model.createdAt = Date.now();
143
144
  this.addTemplateLayer(model);
144
145
  }
145
146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lancom/shared",
3
- "version": "0.0.310",
3
+ "version": "0.0.312",
4
4
  "description": "lancom common scripts",
5
5
  "author": "e.tokovenko <e.tokovenko@gmail.com>",
6
6
  "repository": {