@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.
- package/assets/js/utils/fabric/wireframe.js +11 -8
- package/assets/js/utils/fabric-helper.js +6 -4
- package/assets/js/utils/layers.js +5 -4
- package/components/common/payment/payment_success/payment-success.vue +2 -2
- package/components/editor/editor_workspace/editor-workspace.scss +11 -0
- package/components/editor/editor_workspace/editor-workspace.vue +29 -5
- package/components/editor/mobile_editor_product_details/mobile-editor-product-details.vue +1 -1
- package/components/order/order_view/order-view.mixin.js +14 -11
- package/components/product/product_print_preview/product-print-preview.vue +45 -17
- package/components/product/wizard/wizard.vue +6 -3
- package/components/products/product_list_product/product-list-product.vue +1 -1
- package/mixins/product-view.js +2 -1
- package/package.json +1 -1
|
@@ -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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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(
|
|
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 },
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
layer.
|
|
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
|
|
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 }) {
|
|
@@ -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.
|
|
53
|
+
return this.displayAddress.fullName;
|
|
51
54
|
},
|
|
52
55
|
company() {
|
|
53
|
-
return this.
|
|
56
|
+
return this.displayAddress.company;
|
|
54
57
|
},
|
|
55
58
|
phone() {
|
|
56
|
-
return this.
|
|
59
|
+
return this.displayAddress.phone;
|
|
57
60
|
},
|
|
58
61
|
email() {
|
|
59
|
-
return this.
|
|
62
|
+
return this.displayAddress.email;
|
|
60
63
|
},
|
|
61
64
|
additionalInfo() {
|
|
62
|
-
return this.
|
|
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.
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
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="
|
|
7
|
-
Export To
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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:
|
|
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="
|
|
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="!
|
|
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.
|
|
199
|
+
if (this.product.printOnly || this.hasPresetPrints || this.layers.length > 0) {
|
|
197
200
|
this.isVisible = true;
|
|
198
201
|
this.setIsPrintPricing(this.isVisible);
|
|
199
202
|
}
|
package/mixins/product-view.js
CHANGED
|
@@ -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
|
}
|