@lancom/shared 0.0.467 → 0.0.469

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.
@@ -152,8 +152,8 @@ export default {
152
152
  returnShipments(body) {
153
153
  return _post('admin/shipments/return', body);
154
154
  },
155
- markShipmentAsDispatched(order, shipment) {
156
- return _post(`admin/shop/${order.shop?._id || order.shop}/order/${order._id}/shipment/${shipment._id || shipment.guid}/dispatched`, shipment);
155
+ markShipmentAsDispatched(order, shipment, options) {
156
+ return _post(`admin/shop/${order.shop?._id || order.shop}/order/${order._id}/shipment/${shipment._id || shipment.guid}/dispatched`, { ...shipment, ...(options || {}) });
157
157
  },
158
158
  markLabelsPrinted(order) {
159
159
  return _post(`admin/order/${order._id}/mark-labels-printed`);
@@ -72,16 +72,19 @@ export class ArtLayer extends Layer {
72
72
  width = null;
73
73
  height = null;
74
74
 
75
- constructor(type, colorId, top, left, url, originalSize, fileName) {
75
+ constructor(type, colorId, top, left, url, originalSize, fileName, file) {
76
76
  super(colorId, top, left);
77
77
  this.type = type;
78
78
  this.url = url;
79
79
  this.originalSize = originalSize;
80
80
  this.fileName = fileName;
81
+ this.file = file;
81
82
  }
82
83
  };
83
84
 
84
- export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url, originalSize, sideId, fileName, properties = {} }) => {
85
+ export const getLayerModel = async options => {
86
+ const { type, colorId, top, left, isEditMode, url, originalSize, sideId, fileName, file, properties = {} } = options;
87
+
85
88
  if (!type) {
86
89
  throw new Error('When creating a new layer, you must specify its type');
87
90
  }
@@ -97,7 +100,7 @@ export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url,
97
100
  }
98
101
  break;
99
102
  case 'art':
100
- layer = new ArtLayer(type, colorId, top, left, url, originalSize, fileName);
103
+ layer = new ArtLayer(type, colorId, top, left, url, originalSize, fileName, file);
101
104
  break;
102
105
  default:
103
106
  throw new Error(`Layer type '${type}' not found or not supported.`);
@@ -20,7 +20,7 @@ export function createText(layer) {
20
20
  .then(() => {
21
21
  const params = { ...layer, layer };
22
22
  delete params.copy;
23
- const copy = layer.copy.length ? layer.copy : '';
23
+ const copy = layer.copy?.length ? layer.copy : '';
24
24
  if (!layer.enableOutline) {
25
25
  params.strokeWidth = 0;
26
26
  }
@@ -201,7 +201,7 @@ export default class FabricHelper {
201
201
  });
202
202
  }
203
203
 
204
- createObject({ layer, active }) {
204
+ createObject({ layer, active, selectable = true }) {
205
205
  const initial = !layer.modifiedAt;
206
206
  return new Promise(resolve => {
207
207
  const methods = {
@@ -211,6 +211,16 @@ export default class FabricHelper {
211
211
  this[methods[layer.type]]({ layer, initial }).then(obj => {
212
212
  // obj.clipPath = this.boundingBox;
213
213
  // console.log('obj: ', obj.top, obj.left);
214
+ if (!selectable) {
215
+ obj.set({
216
+ selectable: false,
217
+ evented: false,
218
+ hasControls: false,
219
+ hasBorders: false,
220
+ lockMovementX: true,
221
+ lockMovementY: true
222
+ });
223
+ }
214
224
  this.handleListeners(obj, layer.type);
215
225
  this.editor.add(obj);
216
226
  if (active) {
@@ -120,8 +120,9 @@ export default {
120
120
  const layer = await this.createLayer({ type: 'text' });
121
121
  this.$emit('layer-added', { layer, toEditMode: true });
122
122
  },
123
- async handleUploaded({ url, size, fileName }) {
124
- const layer = await this.createLayer({ type: 'art', url, size, fileName });
123
+ async handleUploaded(file) {
124
+ const { url, size, fileName } = file;
125
+ const layer = await this.createLayer({ type: 'art', url, size, fileName, file });
125
126
  this.$emit('layer-added', { layer, toEditMode: false });
126
127
  }
127
128
  }
@@ -30,6 +30,7 @@
30
30
  ref="editor"
31
31
  :key="side"
32
32
  :is-edit-mode="isEditMode"
33
+ :is-selectable="isSelectable"
33
34
  :side="side"
34
35
  :print-area="editablePrintArea"
35
36
  :zoom-size="sideZoomSize"
@@ -160,6 +161,10 @@ export default {
160
161
  isEditMode: {
161
162
  type: Boolean,
162
163
  default: true
164
+ },
165
+ isSelectable: {
166
+ type: Boolean,
167
+ default: true
163
168
  }
164
169
  },
165
170
  data() {
@@ -171,6 +171,10 @@ export default {
171
171
  isEditMode: {
172
172
  type: Boolean,
173
173
  default: true
174
+ },
175
+ isSelectable: {
176
+ type: Boolean,
177
+ default: true
174
178
  }
175
179
  },
176
180
  data() {
@@ -435,7 +439,8 @@ export default {
435
439
  for (const layer of this.sideEditableLayers) {
436
440
  const params = {
437
441
  layer,
438
- active: this.isLayerSelected(layer)
442
+ active: this.isLayerSelected(layer),
443
+ selectable: this.isSelectable
439
444
  };
440
445
  await this.fabricHelper.createObject(params);
441
446
  }
@@ -493,9 +498,10 @@ export default {
493
498
  });
494
499
  }
495
500
  },
496
- async handleUploaded({ url, size, fileName }) {
501
+ async handleUploaded(file) {
497
502
  window.scrollTo(0, 0);
498
- await this.createLayer({ type: 'art', url, size, fileName });
503
+ const { url, size, fileName } = file;
504
+ await this.createLayer({ type: 'art', url, size, fileName, file });
499
505
  this.visibleWireframe = true;
500
506
  },
501
507
  setOffsetWarningVisibility(visible) {
@@ -7,6 +7,7 @@
7
7
  </div>
8
8
  <product-list
9
9
  :products="products"
10
+ :visible-quick-view="false"
10
11
  :lazy="false" />
11
12
  </div>
12
13
  </template>
@@ -4,8 +4,8 @@
4
4
  font-weight: 800;
5
5
  font-size: 28px;
6
6
  line-height: 38px;
7
- color: $black;
8
- margin-bottom: 26px;
7
+ color: $black;
8
+ margin-bottom: 26px;
9
9
  }
10
10
  &__types {
11
11
  display: flex;
@@ -135,4 +135,4 @@
135
135
  outline: none;
136
136
  }
137
137
  }
138
- }
138
+ }
@@ -6,12 +6,19 @@
6
6
  :class="{
7
7
  'WizardTextOrLogoForm__type--selected': layerType === 'text'
8
8
  }"
9
+ style="width: 45%"
9
10
  @click="selectLayerType('text')">
10
11
  <div class="WizardTextOrLogoForm__type-name">
11
12
  Add text
12
13
  </div>
13
14
  <div class="WizardTextOrLogoForm__type-input">
15
+ <wizard-print-template-select
16
+ v-if="hasPrintTemplateOptions"
17
+ v-model="layer.printTemplate"
18
+ :options="layer.printTemplates"
19
+ @input="onPrintTemplateChange" />
14
20
  <input
21
+ v-else
15
22
  v-model="layer.copy"
16
23
  placeholder="Enter your text"
17
24
  type="text"
@@ -83,6 +90,7 @@
83
90
  </a>
84
91
  </div>
85
92
  </div>
93
+
86
94
  </div>
87
95
  <div class="WizardTextOrLogoForm__description">
88
96
  <textarea
@@ -95,13 +103,18 @@
95
103
  </template>
96
104
 
97
105
  <script>
98
- import { mapGetters } from 'vuex';
106
+ import { mapGetters, mapMutations } from 'vuex';
107
+ import { getLayerModel } from '@lancom/shared/assets/js/models/product-layers';
108
+ import { fitLayerToEditorSize } from '@lancom/shared/assets/js/utils/layers';
109
+ import { getPrintAreaByName } from '@lancom/shared/assets/js/models/print-area';
99
110
  import FileUploader from '@lancom/shared/components/common/file_uploader';
111
+ import WizardPrintTemplateSelect from './wizard_print_template_select/wizard-print-template-select';
100
112
 
101
113
  export default {
102
114
  name: 'WizardTextOrLogoForm',
103
115
  components: {
104
- FileUploader
116
+ FileUploader,
117
+ WizardPrintTemplateSelect
105
118
  },
106
119
  props: {
107
120
  layer: {
@@ -117,9 +130,52 @@ export default {
117
130
  },
118
131
  computed: {
119
132
  ...mapGetters(['shop']),
120
- ...mapGetters('product', ['product'])
133
+ ...mapGetters('product', ['product', 'editorSize', 'editableColor']),
134
+ hasPrintTemplateOptions() {
135
+ return (this.layer.printTemplates || []).length > 1;
136
+ }
121
137
  },
122
138
  methods: {
139
+ ...mapMutations('product', ['addTemplateLayer', 'removeTemplateLayer']),
140
+ async onPrintTemplateChange(template) {
141
+ if (!template) return;
142
+
143
+ this.removeTemplateLayer(this.layer);
144
+
145
+ const layers = template.layers || [{ type: 'text' }];
146
+ for (const templateLayer of layers) {
147
+ const properties = {
148
+ ...templateLayer,
149
+ printArea: this.layer.printArea,
150
+ printSize: this.layer.printSize,
151
+ printType: this.layer.printType,
152
+ printTemplates: this.layer.printTemplates,
153
+ printTemplate: template,
154
+ copy: templateLayer.copy || templateLayer.text || '',
155
+ required: true
156
+ };
157
+ delete properties.guid;
158
+
159
+ const printArea = getPrintAreaByName({
160
+ printArea: this.layer.printArea,
161
+ printSize: this.layer.printSize,
162
+ editorWidth: this.editorSize.width,
163
+ editorHeight: this.editorSize.height
164
+ }, this.product, true);
165
+ fitLayerToEditorSize(properties, template, printArea);
166
+ properties.sideId = printArea?.sideId;
167
+
168
+ const data = {
169
+ colorId: this.editableColor._id,
170
+ type: templateLayer.type || 'text',
171
+ sideId: properties.sideId || 'front',
172
+ properties
173
+ };
174
+ const model = await getLayerModel(data);
175
+ model.createdAt = Date.now();
176
+ this.addTemplateLayer(model);
177
+ }
178
+ },
123
179
  selectLayerType(type) {
124
180
  if (this.layerType !== type) {
125
181
  this.layerType = type;
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <multiselect
3
+ class="WizardPrintTemplateSelect"
4
+ :value="value"
5
+ :options="options"
6
+ label="name"
7
+ track-by="_id"
8
+ :searchable="false"
9
+ :show-labels="false"
10
+ placeholder="Select template"
11
+ @input="$emit('input', $event)" />
12
+ </template>
13
+
14
+ <script>
15
+ import Multiselect from 'vue-multiselect';
16
+
17
+ export default {
18
+ name: 'WizardPrintTemplateSelect',
19
+ components: {
20
+ Multiselect
21
+ },
22
+ props: {
23
+ value: {
24
+ type: Object,
25
+ default: null
26
+ },
27
+ options: {
28
+ type: Array,
29
+ default: () => []
30
+ }
31
+ }
32
+ };
33
+ </script>
@@ -153,12 +153,16 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
153
153
  if (this.preSetPrints?.length) {
154
154
  for (const preSetPrint of this.preSetPrints) {
155
155
  const layers = preSetPrint.printTemplate?.layers || [{ type: 'text' }];
156
+ const printTemplates = [preSetPrint.printTemplate, ...(preSetPrint.additionalPrintTemplates || [])]
156
157
  for (const layer of layers) {
157
158
  const properties = {
158
159
  ...layer,
159
160
  printArea: preSetPrint.printArea,
160
161
  printSize: preSetPrint.printSize,
161
162
  printType: preSetPrint.printType,
163
+ printTemplates,
164
+ printTemplate: preSetPrint.printTemplate,
165
+ minimumOrderQuantity: preSetPrint.minimumOrderQuantity,
162
166
  required: true
163
167
  };
164
168
  delete properties.guid;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lancom/shared",
3
- "version": "0.0.467",
3
+ "version": "0.0.469",
4
4
  "description": "lancom common scripts",
5
5
  "author": "e.tokovenko <e.tokovenko@gmail.com>",
6
6
  "repository": {
package/store/cart.js CHANGED
@@ -65,12 +65,13 @@ const getInvalidStockQuantities = entities => {
65
65
  };
66
66
 
67
67
  const getPrintsQuantities = entities => {
68
- const printTypes = entities.reduce((types, e) => [...types, ...e.prints.map(({ printType }) => ({ ...printType, guid: `${e.guid}-${printType?._id}` }))], []);
68
+ const printTypes = entities.reduce((types, e) => [...types, ...e.prints.map(({ printType, layers }) => ({ ...printType, layers, guid: `${e.guid}-${printType?._id}` }))], []);
69
69
  const grouped = groupBy(printTypes, 'guid');
70
70
  const quantities = Object.keys(grouped).map(guid => {
71
- const [{ name, minQuantity }] = grouped[guid];
71
+ const [{ name, minQuantity, layers }] = grouped[guid];
72
72
  const printTypeEntities = entities.filter(e => (e.prints || []).some(({ printType }) => `${e.guid}-${printType?._id}` === guid));
73
- return { name, minQuantity, quantity: getEntitiesQuantity(printTypeEntities) };
73
+ const layersMinOrderQty = Math.max(0, ...(layers?.map(l => l?.params?.minimumOrderQuantity || 0) || []));
74
+ return { name, minQuantity: layersMinOrderQty || minQuantity, quantity: getEntitiesQuantity(printTypeEntities), layers };
74
75
  });
75
76
  return quantities;
76
77
  };
@@ -147,7 +148,10 @@ export const getters = {
147
148
  return (quantities?.stock || []).filter(({ maxQuantity, quantity }) => quantity > maxQuantity);
148
149
  },
149
150
  notValidPrintsQuantities(state, { quantities }) {
150
- return (quantities?.prints || []).filter(({ minQuantity, quantity }) => quantity < minQuantity);
151
+ return (quantities?.prints || []).filter(({ minQuantity, quantity, layers }) => {
152
+ const printMinQty = quantity || 0;
153
+ return printMinQty < minQuantity;
154
+ });
151
155
  },
152
156
  cartPricingError: ({ cartPricingError }) => cartPricingError
153
157
  };
package/store/product.js CHANGED
@@ -17,7 +17,7 @@ export const state = () => ({
17
17
  loadingProductDetails: false,
18
18
  productDetailsKey: Date.now(),
19
19
  images: [],
20
- priceIncludeGST: true,
20
+ priceIncludeGST: false,
21
21
  product: null,
22
22
  preSetPrints: null,
23
23
  loadError: null,
@@ -117,7 +117,7 @@ export const getters = {
117
117
  editModeSelectedLayer: ({ editModeSelectedLayer }) => editModeSelectedLayer,
118
118
  selectedPrintAreas: ({ selectedPrintAreas }) => selectedPrintAreas,
119
119
  selectedPrintArea: ({ selectedPrintAreas, editablePrintArea }) =>
120
- (!!editablePrintArea && selectedPrintAreas[editablePrintArea._id]),
120
+ (editablePrintArea ? selectedPrintAreas[editablePrintArea._id] : null),
121
121
  productPricing: ({ productPricing }) => productPricing,
122
122
  mainProductPricing: ({ productPricing, product }) => (productPricing?.products || {})[product._id],
123
123
  selectedColors: ({ template: { colors = [] }, availableColors }) => {
@@ -148,13 +148,16 @@ export const getters = {
148
148
  availablePrintTypes: ({ availablePrintTypes }) => availablePrintTypes,
149
149
  isPrintPricing: ({ isPrintPricing }) => isPrintPricing,
150
150
  minimumOrderQuantity: ({ product, template }) => {
151
- const layersPrintTypes = (template.layers || []).map(({ printType }) => printType);
151
+ const layersPrintTypes = (template.layers || []).map(({ printType, minimumOrderQuantity }) => minimumOrderQuantity > 0 ? null : printType);
152
152
  const printTypesMinQuantity = (product.printTypes || [])
153
153
  .filter(printType => layersPrintTypes.includes(printType._id || printType))
154
154
  .map(printType => printType.minQuantity);
155
+ const layersWithTemplate = (template.layers || []).map(({ minimumOrderQuantity }) => minimumOrderQuantity).filter(mo => mo > 0);
156
+
155
157
  return Math.max(
156
- layersPrintTypes?.length > 0 ? product.minimumPrintOrderQuantity : product.minimumOrderQuantity,
157
- ...printTypesMinQuantity
158
+ template.layers?.length > 0 ? product.minimumPrintOrderQuantity : product.minimumOrderQuantity,
159
+ ...printTypesMinQuantity,
160
+ ...layersWithTemplate
158
161
  );
159
162
  },
160
163
  images: ({ images, product }) => {
@@ -332,6 +335,7 @@ export const actions = {
332
335
  preselect = true,
333
336
  isEditMode,
334
337
  size,
338
+ file,
335
339
  properties,
336
340
  fileName
337
341
  }
@@ -344,6 +348,7 @@ export const actions = {
344
348
  left,
345
349
  isEditMode,
346
350
  fileName,
351
+ file,
347
352
  url,
348
353
  originalSize: size,
349
354
  sideId: getters.editableSide?.id,
@@ -410,8 +415,8 @@ export const mutations = {
410
415
  },
411
416
  setProductDetails(state, simpleProducts) {
412
417
  const { preSetPrints } = state;
413
- const [preSetPrint] = preSetPrints || [];
414
- simpleProducts = simpleProducts.filter(sp => !preSetPrint || (preSetPrint.colors || []).includes(sp.color._id));
418
+ const allPreSetColors = (preSetPrints || []).reduce((colors, print) => [...colors, ...(print.colors || [])], []);
419
+ simpleProducts = simpleProducts.filter(sp => !allPreSetColors.length || allPreSetColors.includes(sp.color._id));
415
420
  state.productDetails = { simpleProducts };
416
421
  const availableSizes = [];
417
422
  const sizesPerColor = simpleProducts.reduce((map, { color, size }) => {