@softwear/latestcollectioncore 1.0.174 → 1.0.176
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/dist/imageBinder.js +18 -12
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -1
- package/dist/pdf.d.ts +67 -0
- package/dist/pdf.js +2 -0
- package/dist/reports.d.ts +35 -0
- package/dist/reports.js +705 -0
- package/package.json +3 -2
- package/src/imageBinder.ts +18 -16
- package/src/index.ts +3 -0
- package/src/pdf.ts +76 -0
- package/src/reports.ts +831 -0
- package/test/imageBinder.spec.js +8 -8
- package/test/imageBinderTestData/brandDataMatched/dreamstar.json +6 -709
- package/test/imageBinderTestData/brandDataMatched/lowa.json +6 -1456
- package/test/imageBinderTestData/brandDataMatched/miraclesuit.json +838 -1721
- package/test/imageBinderTestData/brandDataMatched/vacanzeitaliane.json +1215 -2185
- package/test/imageBinderTestData/brandSkus/dreamstar.json +68 -34
- package/test/imageBinderTestData/brandSkus/lowa.json +168 -84
- package/test/imageBinderTestData/brandSkus/miraclesuit.json +78 -39
- package/test/imageBinderTestData/brandSkus/vacanzeitaliane.json +106 -53
- package/test/reports.spec.ts +74 -0
- package/test.pdf +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softwear/latestcollectioncore",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.176",
|
|
4
4
|
"description": "Core functions for LatestCollections applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"date-fns": "^2.29.3",
|
|
40
|
-
"filtrex": "^2.2.3"
|
|
40
|
+
"filtrex": "^2.2.3",
|
|
41
|
+
"jspdf": "^4.2.1"
|
|
41
42
|
}
|
|
42
43
|
}
|
package/src/imageBinder.ts
CHANGED
|
@@ -32,18 +32,19 @@ function prepFilterSkusImages(filteredSkus: SkuI[], merge = true, fileNames: Arr
|
|
|
32
32
|
const skusCopy = deepCopy(filteredSkus)
|
|
33
33
|
const preppedSkus: Array<Record<string, any>> = []
|
|
34
34
|
const fileNames2skip: Array<string> = []
|
|
35
|
-
|
|
36
|
-
skusCopy.forEach((sku) => {
|
|
37
|
-
const fieldsToBeMerged = {}
|
|
35
|
+
skusCopy.forEach((sku, idx) => {
|
|
38
36
|
if (sku.images && sku.images.length > 0) {
|
|
39
37
|
// If a fileName is already matched, we skip it
|
|
40
38
|
fileNames.forEach((fileName) => {
|
|
41
|
-
if (sku.images?.includes(fileName) &&
|
|
39
|
+
if (sku.images?.includes(fileName) && fileNames2skip.indexOf(fileName) == -1) fileNames2skip.push(fileName)
|
|
42
40
|
})
|
|
43
41
|
// If a sku has images, we skip it
|
|
42
|
+
sku['skip'] = true
|
|
43
|
+
preppedSkus.push(sku)
|
|
44
44
|
return
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
const fieldsToBeMerged = {}
|
|
47
48
|
for (const fieldName in sku) {
|
|
48
49
|
if (fieldName == '__created' || fieldName == '__modified' || fieldName == 'images' || fieldName == 'brandhash' || (merge == true && fieldName == 'colorFamily')) continue
|
|
49
50
|
let fieldVal = sku[fieldName]
|
|
@@ -70,7 +71,6 @@ function prepFilterSkusImages(filteredSkus: SkuI[], merge = true, fileNames: Arr
|
|
|
70
71
|
} else {
|
|
71
72
|
const newSku = {}
|
|
72
73
|
newSku['originalSku'] = filteredSkus[idx]
|
|
73
|
-
idx++
|
|
74
74
|
for (const fieldVal in fieldsToBeMerged) {
|
|
75
75
|
const fieldNameArray = fieldsToBeMerged[fieldVal].sort()
|
|
76
76
|
if (fieldNameArray.length > 1) {
|
|
@@ -83,7 +83,7 @@ function prepFilterSkusImages(filteredSkus: SkuI[], merge = true, fileNames: Arr
|
|
|
83
83
|
}
|
|
84
84
|
})
|
|
85
85
|
const fileNames2Match = fileNames.filter((fileName) => {
|
|
86
|
-
return fileNames2skip.
|
|
86
|
+
return fileNames2skip.indexOf(fileName) == -1
|
|
87
87
|
})
|
|
88
88
|
return { preppedSkus: preppedSkus, fileNames2Match: fileNames2Match }
|
|
89
89
|
}
|
|
@@ -116,7 +116,7 @@ function checkWithoutLast(fileName: string) {
|
|
|
116
116
|
.toLowerCase()
|
|
117
117
|
.split(/[_\-.\s()]+|%[0-9A-Fa-f]{2}/)
|
|
118
118
|
.slice(0, -1)
|
|
119
|
-
const lastToken = tokens.
|
|
119
|
+
const lastToken = tokens[tokens.length - 1]
|
|
120
120
|
let returnWithoutLast = false
|
|
121
121
|
if (lastToken) {
|
|
122
122
|
if (lastToken.includes('front') || lastToken.includes('back') || lastToken.includes('side') || lastToken.includes('sole')) returnWithoutLast = true
|
|
@@ -167,7 +167,7 @@ function testQuickSearch(
|
|
|
167
167
|
if (pair[0] == cleanedFileName) {
|
|
168
168
|
indicesToReturn.push(idx)
|
|
169
169
|
patternStringFound = quickSearchPattern
|
|
170
|
-
} else if (indicesToReturn.length == 0 && pair[0] == fileNameWithoutLast &&
|
|
170
|
+
} else if (indicesToReturn.length == 0 && pair[0] == fileNameWithoutLast && indicesWithoutLast.indexOf(idx) == -1) {
|
|
171
171
|
indicesWithoutLast.push(idx)
|
|
172
172
|
patternStringFound = quickSearchPattern
|
|
173
173
|
}
|
|
@@ -188,6 +188,7 @@ function prepQuickSearch(preppedSkus: any): Record<string, Array<any>> {
|
|
|
188
188
|
patternStrings.push(pattern.join('-'))
|
|
189
189
|
})
|
|
190
190
|
preppedSkus.forEach((sku, idx) => {
|
|
191
|
+
if (sku['skip']) return
|
|
191
192
|
GLOBAL_PATTERNS.forEach((pattern, patternIndex) => {
|
|
192
193
|
const proposedFilename = pattern.reduce((out, field) => out + (field in sku ? sku[field] : ''), '')
|
|
193
194
|
if (proposedFilename) {
|
|
@@ -204,11 +205,10 @@ function prepQuickSearch(preppedSkus: any): Record<string, Array<any>> {
|
|
|
204
205
|
|
|
205
206
|
function addNewPatternToQuickSearch(preppedSkus: any, pattern: Array<string>, quickSearch: Record<string, Array<Array<any>>>): Record<string, Array<any>> {
|
|
206
207
|
const newQuickSearchArray: Array<Array<any>> = []
|
|
207
|
-
|
|
208
|
-
|
|
208
|
+
preppedSkus.forEach((sku, idx) => {
|
|
209
|
+
if (sku['skip']) return
|
|
209
210
|
const proposedFilename = pattern.reduce((out, field) => out + (field in sku ? sku[field] : ''), '')
|
|
210
211
|
if (proposedFilename) newQuickSearchArray.push([proposedFilename, idx])
|
|
211
|
-
idx++
|
|
212
212
|
})
|
|
213
213
|
quickSearch[pattern.join('-')] = newQuickSearchArray
|
|
214
214
|
return quickSearch
|
|
@@ -223,6 +223,7 @@ function fallbackSearch(cleanedFileName: string, fileNameWithoutLast: string, pr
|
|
|
223
223
|
let currentBestSubstringPatterns: Record<string, Array<number>> = {}
|
|
224
224
|
let maxPatternlength = 0
|
|
225
225
|
preppedSkus.forEach((sku, idx) => {
|
|
226
|
+
if (sku['skip']) return
|
|
226
227
|
if (pattern_found.length > 0) {
|
|
227
228
|
// In case a new pattern has been found in one sku, test that on the remaining skus. If they don't match the pattern, skip them.
|
|
228
229
|
const proposedFilename = pattern_found.reduce((out, field) => out + (field in sku ? sku[field] : ''), '')
|
|
@@ -282,15 +283,15 @@ function fallbackSearch(cleanedFileName: string, fileNameWithoutLast: string, pr
|
|
|
282
283
|
substringPattern.splice(idx, 1)
|
|
283
284
|
}
|
|
284
285
|
})
|
|
285
|
-
const proposedFilename = Object.values(substringObject).join('')
|
|
286
|
+
const proposedFilename = (<any>Object).values(substringObject).join('')
|
|
286
287
|
if (proposedFilename == cleanedFileName || (fileNameWithoutLast && proposedFilename == fileNameWithoutLast)) {
|
|
287
288
|
// We've discovered a new pattern
|
|
288
|
-
pattern_found = Object.values(patternObject)
|
|
289
|
+
pattern_found = (<any>Object).values(patternObject)
|
|
289
290
|
exactMatches.push(idx)
|
|
290
291
|
return
|
|
291
292
|
}
|
|
292
|
-
patternString = Object.values(patternObject).join('-')
|
|
293
|
-
const revisedPatternLength = Object.values(patternObject).length
|
|
293
|
+
patternString = (<any>Object).values(patternObject).join('-')
|
|
294
|
+
const revisedPatternLength = (<any>Object).values(patternObject).length
|
|
294
295
|
if (revisedPatternLength == maxPatternlength) {
|
|
295
296
|
// We've found a new pattern of the same length, so we keep this one too
|
|
296
297
|
if (patternString in currentBestSubstringPatterns) {
|
|
@@ -317,7 +318,7 @@ function fallbackSearch(cleanedFileName: string, fileNameWithoutLast: string, pr
|
|
|
317
318
|
const sku = preppedSkus[idx]
|
|
318
319
|
pattern.forEach((fieldName) => {
|
|
319
320
|
const fieldVal = sku[fieldName]
|
|
320
|
-
if (fieldVal &&
|
|
321
|
+
if (fieldVal && uniqueFieldVals.indexOf(fieldVal) == -1) uniqueFieldVals.push(fieldVal)
|
|
321
322
|
})
|
|
322
323
|
})
|
|
323
324
|
uniqueFieldVals.sort((a, b) => {
|
|
@@ -364,6 +365,7 @@ function imageBinder(fileNames: Array<string>, filteredSkus: SkuI[], brand: stri
|
|
|
364
365
|
const fileNameWithoutLast = checkWithoutLast(fileName)
|
|
365
366
|
fileNameIndexMatch[fileName] = []
|
|
366
367
|
preppedSkus.forEach((sku, idx) => {
|
|
368
|
+
if (sku['skip']) return
|
|
367
369
|
let skuStillMatches = true
|
|
368
370
|
specifiedPattern.every((fieldName) => {
|
|
369
371
|
if (!(fieldName in sku)) skuStillMatches = false
|
package/src/index.ts
CHANGED
|
@@ -14,9 +14,12 @@ export { default as hasOnlyDigits } from './hasOnlyDigits'
|
|
|
14
14
|
export { default as imageBinder } from './imageBinder'
|
|
15
15
|
export { default as isean13 } from './isean13'
|
|
16
16
|
export { default as pivotTable } from './pivotTable'
|
|
17
|
+
export { default as reports, genPDF } from './reports'
|
|
17
18
|
export { default as round2 } from './round2'
|
|
18
19
|
export { default as sizeToMap } from './sizeToMap'
|
|
19
20
|
export { default as transaction } from './transaction'
|
|
21
|
+
export * from './pdf'
|
|
22
|
+
export type { GenPdfAlert, GenPdfOptions, PdfFontDefinition, PdfFontVariant, PdfImageAsset } from './reports'
|
|
20
23
|
export * from './types'
|
|
21
24
|
export * from './consts'
|
|
22
25
|
export {
|
package/src/pdf.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export interface PaperSize {
|
|
2
|
+
width: number
|
|
3
|
+
height: number
|
|
4
|
+
footerHeight: number
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type TextAlign = 1 | 2 | 3 // 1: left, 2: center, 3: right
|
|
8
|
+
export type ObjectType = 'text' | 'field' | 'rectangle' | 'image' | 'container'
|
|
9
|
+
export type RepeatContainer = 'horizontal' | 'vertical' | undefined
|
|
10
|
+
|
|
11
|
+
export interface BaseLayoutObject {
|
|
12
|
+
type: ObjectType
|
|
13
|
+
x: number
|
|
14
|
+
y: number
|
|
15
|
+
width: number
|
|
16
|
+
height: number
|
|
17
|
+
active?: boolean
|
|
18
|
+
snapToBottom?: boolean
|
|
19
|
+
name?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface TextLayoutObject extends BaseLayoutObject {
|
|
23
|
+
type: 'text'
|
|
24
|
+
text: string
|
|
25
|
+
textAlign?: TextAlign
|
|
26
|
+
fontFamily: string
|
|
27
|
+
fontSize: number
|
|
28
|
+
fontStyle: number
|
|
29
|
+
case?: 1 | 2 // 1: uppercase, 2: lowercase
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface FieldLayoutObject extends BaseLayoutObject {
|
|
33
|
+
type: 'field'
|
|
34
|
+
source?: string
|
|
35
|
+
format?: 'date' | 'currency'
|
|
36
|
+
textAlign?: TextAlign
|
|
37
|
+
fontFamily: string
|
|
38
|
+
fontSize: number
|
|
39
|
+
fontStyle: number
|
|
40
|
+
case?: 1 | 2
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface RectangleLayoutObject extends BaseLayoutObject {
|
|
44
|
+
type: 'rectangle'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ImageLayoutObject extends BaseLayoutObject {
|
|
48
|
+
type: 'image'
|
|
49
|
+
url?: string
|
|
50
|
+
image?: HTMLImageElement
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ContainerLayoutObject extends BaseLayoutObject {
|
|
54
|
+
type: 'container'
|
|
55
|
+
source: string
|
|
56
|
+
children: LayoutObject[]
|
|
57
|
+
repeatContainer?: RepeatContainer
|
|
58
|
+
repeatOnOverflow?: boolean
|
|
59
|
+
pageBreak?: boolean
|
|
60
|
+
/** Minimum mm of remaining space before drawing next item; if less, break to next page first */
|
|
61
|
+
minHeightBeforeBreak?: number
|
|
62
|
+
/** When true, container and children are drawn only once at the end of the report, not on every page */
|
|
63
|
+
printOnlyAtEnd?: boolean
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type LayoutObject = TextLayoutObject | FieldLayoutObject | RectangleLayoutObject | ImageLayoutObject | ContainerLayoutObject
|
|
67
|
+
|
|
68
|
+
export interface Layout {
|
|
69
|
+
name?: string
|
|
70
|
+
group?: string
|
|
71
|
+
paperSize: PaperSize
|
|
72
|
+
objects: LayoutObject[]
|
|
73
|
+
active?: boolean
|
|
74
|
+
/** Default font for text/field objects that have no fontFamily. E.g. 'Inter', 'Helvetica'. */
|
|
75
|
+
defaultFontFamily?: string
|
|
76
|
+
}
|