pim-import 5.0.1 → 5.0.2
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/algolia/clean.js +0 -1
- package/dist/algolia/config.js +0 -1
- package/dist/algolia/downloads.js +0 -1
- package/dist/algolia/families.js +0 -1
- package/dist/algolia/inspirations.js +0 -1
- package/dist/algolia/models.js +0 -1
- package/dist/algolia/news.js +0 -1
- package/dist/algolia/pressRelease.js +0 -1
- package/dist/algolia/pressReview.js +0 -1
- package/dist/algolia/products.js +0 -1
- package/dist/algolia/projects.js +0 -1
- package/dist/algolia/stories.js +0 -1
- package/dist/algolia/subFamilies.js +0 -1
- package/dist/algolia/subModels.js +0 -1
- package/dist/browser.js +0 -1
- package/dist/downloads/classes/manageEntry.js +0 -1
- package/dist/downloads/import.js +0 -1
- package/dist/index.js +0 -1
- package/dist/libs/contentful-cda.js +0 -1
- package/dist/libs/contentful.js +0 -1
- package/dist/libs/imgix.js +0 -1
- package/dist/libs/logs.js +0 -1
- package/dist/libs/netlify.js +0 -1
- package/dist/libs/notifications.js +0 -1
- package/dist/libs/pdf.js +0 -1
- package/dist/libs/s3.js +0 -1
- package/dist/libs/sentry.js +0 -1
- package/dist/pim/config.js +0 -1
- package/dist/pim/endpoints.js +0 -1
- package/dist/pim/methods/bulkPublish.js +0 -1
- package/dist/pim/methods/catalogs.js +0 -1
- package/dist/pim/methods/checkTopicDraftAndPagePublished.js +0 -1
- package/dist/pim/methods/designers.js +0 -1
- package/dist/pim/methods/dictionary.js +0 -1
- package/dist/pim/methods/families.js +0 -1
- package/dist/pim/methods/latestProducts.js +0 -1
- package/dist/pim/methods/migrateEntryFields.js +0 -1
- package/dist/pim/methods/models.js +0 -1
- package/dist/pim/methods/pages/catalogs.js +0 -1
- package/dist/pim/methods/pages/families.js +0 -1
- package/dist/pim/methods/pages/subfamilies.js +0 -1
- package/dist/pim/methods/products.js +0 -1
- package/dist/pim/methods/subfamilies.js +0 -1
- package/dist/pim/methods/submodels.js +0 -1
- package/dist/pim/request.js +0 -1
- package/dist/resources/AllProducts.js +0 -1
- package/dist/resources/Audit.js +0 -1
- package/dist/resources/CatalogDetails.js +0 -1
- package/dist/resources/CollectionModels.js +0 -1
- package/dist/resources/CollectionSubFamilies.js +0 -1
- package/dist/resources/CollectionSubModels.js +0 -1
- package/dist/resources/DProductSubLine.js +0 -1
- package/dist/resources/FamilyDetails.js +0 -1
- package/dist/resources/ProductDetails.js +0 -1
- package/dist/resources/ProductRelation.js +0 -1
- package/dist/resources/cfFields.js +0 -1
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -1
- package/package.json +7 -2
- package/.env.example +0 -45
- package/.nvmrc +0 -1
- package/.vscode/settings.json +0 -21
- package/dist/algolia/clean.js.map +0 -1
- package/dist/algolia/config.js.map +0 -1
- package/dist/algolia/downloads.js.map +0 -1
- package/dist/algolia/families.js.map +0 -1
- package/dist/algolia/inspirations.js.map +0 -1
- package/dist/algolia/models.js.map +0 -1
- package/dist/algolia/news.js.map +0 -1
- package/dist/algolia/pressRelease.js.map +0 -1
- package/dist/algolia/pressReview.js.map +0 -1
- package/dist/algolia/products.js.map +0 -1
- package/dist/algolia/projects.js.map +0 -1
- package/dist/algolia/stories.js.map +0 -1
- package/dist/algolia/subFamilies.js.map +0 -1
- package/dist/algolia/subModels.js.map +0 -1
- package/dist/browser.js.map +0 -1
- package/dist/downloads/classes/manageEntry.js.map +0 -1
- package/dist/downloads/import.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/libs/contentful-cda.js.map +0 -1
- package/dist/libs/contentful.js.map +0 -1
- package/dist/libs/imgix.js.map +0 -1
- package/dist/libs/logs.js.map +0 -1
- package/dist/libs/netlify.js.map +0 -1
- package/dist/libs/notifications.js.map +0 -1
- package/dist/libs/pdf.js.map +0 -1
- package/dist/libs/s3.js.map +0 -1
- package/dist/libs/sentry.js.map +0 -1
- package/dist/pim/config.js.map +0 -1
- package/dist/pim/endpoints.js.map +0 -1
- package/dist/pim/methods/bulkPublish.js.map +0 -1
- package/dist/pim/methods/catalogs.js.map +0 -1
- package/dist/pim/methods/checkTopicDraftAndPagePublished.js.map +0 -1
- package/dist/pim/methods/designers.js.map +0 -1
- package/dist/pim/methods/dictionary.js.map +0 -1
- package/dist/pim/methods/families.js.map +0 -1
- package/dist/pim/methods/latestProducts.js.map +0 -1
- package/dist/pim/methods/migrateEntryFields.js.map +0 -1
- package/dist/pim/methods/models.js.map +0 -1
- package/dist/pim/methods/pages/catalogs.js.map +0 -1
- package/dist/pim/methods/pages/families.js.map +0 -1
- package/dist/pim/methods/pages/subfamilies.js.map +0 -1
- package/dist/pim/methods/products.js.map +0 -1
- package/dist/pim/methods/subfamilies.js.map +0 -1
- package/dist/pim/methods/submodels.js.map +0 -1
- package/dist/pim/request.js.map +0 -1
- package/dist/resources/AllProducts.js.map +0 -1
- package/dist/resources/Audit.js.map +0 -1
- package/dist/resources/CatalogDetails.js.map +0 -1
- package/dist/resources/CollectionModels.js.map +0 -1
- package/dist/resources/CollectionSubFamilies.js.map +0 -1
- package/dist/resources/CollectionSubModels.js.map +0 -1
- package/dist/resources/DProductSubLine.js.map +0 -1
- package/dist/resources/FamilyDetails.js.map +0 -1
- package/dist/resources/ProductDetails.js.map +0 -1
- package/dist/resources/ProductRelation.js.map +0 -1
- package/dist/resources/cfFields.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/docs/import-data-from-the-dictionary.md +0 -83
- package/docs/import-products.md +0 -61
- package/docs/import-taxonomies-from-the-catalog.md +0 -60
- package/docs/settings.md +0 -47
- package/jest.config.js +0 -16
- package/local-fn/reindex.js +0 -182
- package/src/algolia/clean.ts +0 -164
- package/src/algolia/config.ts +0 -390
- package/src/algolia/downloads.ts +0 -346
- package/src/algolia/families.ts +0 -652
- package/src/algolia/inspirations.ts +0 -315
- package/src/algolia/models.ts +0 -589
- package/src/algolia/news.ts +0 -258
- package/src/algolia/pressRelease.ts +0 -255
- package/src/algolia/pressReview.ts +0 -247
- package/src/algolia/products.ts +0 -731
- package/src/algolia/projects.ts +0 -339
- package/src/algolia/stories.ts +0 -347
- package/src/algolia/subFamilies.ts +0 -709
- package/src/algolia/subModels.ts +0 -359
- package/src/browser.ts +0 -122
- package/src/downloads/classes/manageEntry.ts +0 -99
- package/src/downloads/csv/legal.csv +0 -5
- package/src/downloads/csv/products.csv +0 -373
- package/src/downloads/import.ts +0 -381
- package/src/index.ts +0 -140
- package/src/libs/contentful-cda.ts +0 -543
- package/src/libs/contentful.ts +0 -1453
- package/src/libs/imgix.ts +0 -297
- package/src/libs/logs.ts +0 -121
- package/src/libs/netlify.ts +0 -37
- package/src/libs/notifications.ts +0 -104
- package/src/libs/pdf.ts +0 -107
- package/src/libs/s3.ts +0 -305
- package/src/libs/sentry.ts +0 -33
- package/src/pim/config.ts +0 -84
- package/src/pim/data/productFields.json +0 -1178
- package/src/pim/endpoints.ts +0 -364
- package/src/pim/methods/bulkPublish.ts +0 -266
- package/src/pim/methods/catalogs.ts +0 -586
- package/src/pim/methods/checkTopicDraftAndPagePublished.ts +0 -70
- package/src/pim/methods/designers.ts +0 -128
- package/src/pim/methods/dictionary.ts +0 -611
- package/src/pim/methods/families.ts +0 -345
- package/src/pim/methods/latestProducts.ts +0 -70
- package/src/pim/methods/migrateEntryFields.ts +0 -99
- package/src/pim/methods/models.ts +0 -349
- package/src/pim/methods/pages/catalogs.ts +0 -28
- package/src/pim/methods/pages/families.ts +0 -50
- package/src/pim/methods/pages/subfamilies.ts +0 -98
- package/src/pim/methods/products.ts +0 -3297
- package/src/pim/methods/subfamilies.ts +0 -706
- package/src/pim/methods/submodels.ts +0 -262
- package/src/pim/request.ts +0 -61
- package/src/resources/AllProducts.ts +0 -41
- package/src/resources/Audit.ts +0 -24
- package/src/resources/CatalogDetails.ts +0 -51
- package/src/resources/CollectionModels.ts +0 -42
- package/src/resources/CollectionSubFamilies.ts +0 -45
- package/src/resources/CollectionSubModels.ts +0 -36
- package/src/resources/DProductSubLine.ts +0 -34
- package/src/resources/FamilyDetails.ts +0 -31
- package/src/resources/ProductDetails.ts +0 -352
- package/src/resources/ProductRelation.ts +0 -24
- package/src/resources/cfFields.ts +0 -8
- package/src/types.ts +0 -268
- package/src/utils.ts +0 -553
- package/tsconfig.json +0 -93
- package/tslint.json +0 -22
- package/types/libs/puppeteer.d.ts +0 -17
- package/types/pim/methods/checkIp.d.ts +0 -1
- /package/{types → dist}/algolia/clean.d.ts +0 -0
- /package/{types → dist}/algolia/config.d.ts +0 -0
- /package/{types → dist}/algolia/downloads.d.ts +0 -0
- /package/{types → dist}/algolia/families.d.ts +0 -0
- /package/{types → dist}/algolia/inspirations.d.ts +0 -0
- /package/{types → dist}/algolia/models.d.ts +0 -0
- /package/{types → dist}/algolia/news.d.ts +0 -0
- /package/{types → dist}/algolia/pressRelease.d.ts +0 -0
- /package/{types → dist}/algolia/pressReview.d.ts +0 -0
- /package/{types → dist}/algolia/products.d.ts +0 -0
- /package/{types → dist}/algolia/projects.d.ts +0 -0
- /package/{types → dist}/algolia/stories.d.ts +0 -0
- /package/{types → dist}/algolia/subFamilies.d.ts +0 -0
- /package/{types → dist}/algolia/subModels.d.ts +0 -0
- /package/{types → dist}/browser.d.ts +0 -0
- /package/{types → dist}/downloads/classes/manageEntry.d.ts +0 -0
- /package/{types → dist}/downloads/import.d.ts +0 -0
- /package/{types → dist}/index.d.ts +0 -0
- /package/{types → dist}/libs/contentful-cda.d.ts +0 -0
- /package/{types → dist}/libs/contentful.d.ts +0 -0
- /package/{types → dist}/libs/imgix.d.ts +0 -0
- /package/{types → dist}/libs/logs.d.ts +0 -0
- /package/{types → dist}/libs/netlify.d.ts +0 -0
- /package/{types → dist}/libs/notifications.d.ts +0 -0
- /package/{types → dist}/libs/pdf.d.ts +0 -0
- /package/{types → dist}/libs/s3.d.ts +0 -0
- /package/{types → dist}/libs/sentry.d.ts +0 -0
- /package/{types → dist}/pim/config.d.ts +0 -0
- /package/{types → dist}/pim/endpoints.d.ts +0 -0
- /package/{types → dist}/pim/methods/bulkPublish.d.ts +0 -0
- /package/{types → dist}/pim/methods/catalogs.d.ts +0 -0
- /package/{types → dist}/pim/methods/checkTopicDraftAndPagePublished.d.ts +0 -0
- /package/{types → dist}/pim/methods/designers.d.ts +0 -0
- /package/{types → dist}/pim/methods/dictionary.d.ts +0 -0
- /package/{types → dist}/pim/methods/families.d.ts +0 -0
- /package/{types → dist}/pim/methods/latestProducts.d.ts +0 -0
- /package/{types → dist}/pim/methods/migrateEntryFields.d.ts +0 -0
- /package/{types → dist}/pim/methods/models.d.ts +0 -0
- /package/{types → dist}/pim/methods/pages/catalogs.d.ts +0 -0
- /package/{types → dist}/pim/methods/pages/families.d.ts +0 -0
- /package/{types → dist}/pim/methods/pages/subfamilies.d.ts +0 -0
- /package/{types → dist}/pim/methods/products.d.ts +0 -0
- /package/{types → dist}/pim/methods/subfamilies.d.ts +0 -0
- /package/{types → dist}/pim/methods/submodels.d.ts +0 -0
- /package/{types → dist}/pim/request.d.ts +0 -0
- /package/{types → dist}/resources/AllProducts.d.ts +0 -0
- /package/{types → dist}/resources/Audit.d.ts +0 -0
- /package/{types → dist}/resources/CatalogDetails.d.ts +0 -0
- /package/{types → dist}/resources/CollectionModels.d.ts +0 -0
- /package/{types → dist}/resources/CollectionSubFamilies.d.ts +0 -0
- /package/{types → dist}/resources/CollectionSubModels.d.ts +0 -0
- /package/{types → dist}/resources/DProductSubLine.d.ts +0 -0
- /package/{types → dist}/resources/FamilyDetails.d.ts +0 -0
- /package/{types → dist}/resources/ProductDetails.d.ts +0 -0
- /package/{types → dist}/resources/ProductRelation.d.ts +0 -0
- /package/{types → dist}/resources/cfFields.d.ts +0 -0
- /package/{types → dist}/types.d.ts +0 -0
- /package/{types → dist}/utils.d.ts +0 -0
package/src/algolia/subModels.ts
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SubModel index
|
|
3
|
-
*/
|
|
4
|
-
import {
|
|
5
|
-
getClient,
|
|
6
|
-
getEnvironmentDefaultLocaleCode,
|
|
7
|
-
getEntryByID,
|
|
8
|
-
getAllEntries,
|
|
9
|
-
getTopicDetails,
|
|
10
|
-
} from "../libs/contentful-cda";
|
|
11
|
-
import {
|
|
12
|
-
CfLocalizedEntryField,
|
|
13
|
-
TopicDetailsResponse,
|
|
14
|
-
AlgoliaPaginateRecords,
|
|
15
|
-
AvailableCatalogs,
|
|
16
|
-
TopicProductFieldsResponse,
|
|
17
|
-
WrapperImageFields,
|
|
18
|
-
} from "../types";
|
|
19
|
-
import { log, serverUtils } from "../libs/logs";
|
|
20
|
-
import { getIndex, AvailableIndicesKey, removeIndexObject } from "./config";
|
|
21
|
-
import type { Entry } from "contentful-management/dist/typings/entities/entry";
|
|
22
|
-
import {
|
|
23
|
-
getLocalISOTime,
|
|
24
|
-
secondBetweenTwoDate,
|
|
25
|
-
capitalizeFirstLetter,
|
|
26
|
-
addProductFieldValueCodesByPimDetails,
|
|
27
|
-
getAllTranslations,
|
|
28
|
-
} from "../utils";
|
|
29
|
-
import productFieldsRequiredData from "../pim/data/productFields.json";
|
|
30
|
-
import { getWrapperImgixFields } from "../libs/imgix";
|
|
31
|
-
|
|
32
|
-
const indexKey: AvailableIndicesKey = "subModels";
|
|
33
|
-
const topicSubModelSelect =
|
|
34
|
-
"fields.name,fields.code,fields.description,fields.thumbnailImgix,fields.productLine,fields.catalog,fields.subFamily,fields.parentModel,fields.priority";
|
|
35
|
-
|
|
36
|
-
type AlgoliaSubModelRecord = {
|
|
37
|
-
objectID: string;
|
|
38
|
-
names?: CfLocalizedEntryField;
|
|
39
|
-
code?: string;
|
|
40
|
-
description?: string | null;
|
|
41
|
-
thumbnailImgix?: WrapperImageFields | {};
|
|
42
|
-
productLine?: TopicDetailsResponse;
|
|
43
|
-
productFields?: TopicProductFieldsResponse[];
|
|
44
|
-
catalog?: TopicDetailsResponse;
|
|
45
|
-
subFamily?: TopicDetailsResponse;
|
|
46
|
-
parentModel?: TopicDetailsResponse;
|
|
47
|
-
isNew?: boolean;
|
|
48
|
-
priority?: number;
|
|
49
|
-
productCounter?: number;
|
|
50
|
-
destinations?: string[];
|
|
51
|
-
lastSyncDate?: string;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get the count of products associated with a subModel
|
|
56
|
-
*
|
|
57
|
-
* @param topicSubModelWithFields
|
|
58
|
-
*/
|
|
59
|
-
const getProductCounter = async (
|
|
60
|
-
topicSubModelWithFields: Entry
|
|
61
|
-
): Promise<number> => {
|
|
62
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
63
|
-
const catalogId =
|
|
64
|
-
topicSubModelWithFields?.fields?.catalog?.[defaultEnvironmentLocaleCode]
|
|
65
|
-
?.sys?.id;
|
|
66
|
-
if (!catalogId) {
|
|
67
|
-
log(
|
|
68
|
-
`catalog not found for the topicSubModel ${topicSubModelWithFields.sys.id}`
|
|
69
|
-
);
|
|
70
|
-
return 0;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const allProductOfModel = await getAllEntries(
|
|
74
|
-
"topicProduct",
|
|
75
|
-
"sys",
|
|
76
|
-
`fields.subModels${capitalizeFirstLetter(catalogId)}.sys.id[in]`,
|
|
77
|
-
topicSubModelWithFields.sys.id
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
return allProductOfModel.length;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const getProductFields = async (
|
|
84
|
-
topicSubModel: Entry,
|
|
85
|
-
catalog: AvailableCatalogs
|
|
86
|
-
): Promise<any> => {
|
|
87
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
88
|
-
const topicProductEntries = await getAllEntries(
|
|
89
|
-
"topicProduct",
|
|
90
|
-
"sys,fields.productFields",
|
|
91
|
-
`fields.subModels${capitalizeFirstLetter(catalog)}.sys.id[in]`,
|
|
92
|
-
`${topicSubModel.sys.id}`,
|
|
93
|
-
50
|
|
94
|
-
);
|
|
95
|
-
if (!topicProductEntries?.length) {
|
|
96
|
-
log(`No products founded`);
|
|
97
|
-
return false;
|
|
98
|
-
} else {
|
|
99
|
-
log(`${topicProductEntries?.length} products founded`);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
let productFields: any = {};
|
|
103
|
-
productFields.totalProducts = topicProductEntries.length;
|
|
104
|
-
|
|
105
|
-
for (const topicProduct of topicProductEntries) {
|
|
106
|
-
if (topicProduct?.fields?.productFields?.[defaultEnvironmentLocaleCode]) {
|
|
107
|
-
const pimDetails =
|
|
108
|
-
topicProduct?.fields?.productFields?.[defaultEnvironmentLocaleCode];
|
|
109
|
-
|
|
110
|
-
productFieldsRequiredData.forEach((fieldData) => {
|
|
111
|
-
productFields = addProductFieldValueCodesByPimDetails(
|
|
112
|
-
pimDetails,
|
|
113
|
-
productFields,
|
|
114
|
-
fieldData.key,
|
|
115
|
-
fieldData.parent
|
|
116
|
-
);
|
|
117
|
-
});
|
|
118
|
-
productFields = addProductFieldValueCodesByPimDetails(
|
|
119
|
-
pimDetails,
|
|
120
|
-
productFields,
|
|
121
|
-
"certifications"
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return productFields;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const isObjectToDelete = (object: any) => {
|
|
130
|
-
return Object.entries(object).length === 1;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const getObject = async (
|
|
134
|
-
topicSubModel: string | Entry
|
|
135
|
-
): Promise<AlgoliaSubModelRecord> => {
|
|
136
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
137
|
-
const topicSubModelId =
|
|
138
|
-
typeof topicSubModel === "string" ? topicSubModel : topicSubModel?.sys.id;
|
|
139
|
-
|
|
140
|
-
if (!topicSubModelId) {
|
|
141
|
-
log(`The topicSubModelId not found`, "ERROR");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
log(`Get details of the ${topicSubModelId} topicSubModel`);
|
|
145
|
-
const topicSubModelWithFields = await getEntryByID(
|
|
146
|
-
topicSubModelId,
|
|
147
|
-
"topicSubModel"
|
|
148
|
-
);
|
|
149
|
-
if (!topicSubModelWithFields) {
|
|
150
|
-
log(`The topicSubModel with id ${topicSubModelId} not found`, "WARN");
|
|
151
|
-
return { objectID: topicSubModelId };
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
log(`Get catalog details...`);
|
|
155
|
-
const catalogs = await getTopicDetails(
|
|
156
|
-
topicSubModelWithFields,
|
|
157
|
-
"catalog",
|
|
158
|
-
"topicCatalog"
|
|
159
|
-
);
|
|
160
|
-
const catalog = catalogs?.[0];
|
|
161
|
-
let productFields = [];
|
|
162
|
-
if (!catalog) {
|
|
163
|
-
log(
|
|
164
|
-
`catalog not found for the topicSubModel ${topicSubModelWithFields.sys.id}`,
|
|
165
|
-
"WARN"
|
|
166
|
-
);
|
|
167
|
-
} else {
|
|
168
|
-
log(`Get productFields details...`);
|
|
169
|
-
if (catalog) {
|
|
170
|
-
const catalogCode = catalog.code as AvailableCatalogs;
|
|
171
|
-
productFields = await getProductFields(
|
|
172
|
-
topicSubModelWithFields,
|
|
173
|
-
catalogCode
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
log(`Get productLine details...`);
|
|
179
|
-
const productLines = await getTopicDetails(
|
|
180
|
-
topicSubModelWithFields,
|
|
181
|
-
"productLine",
|
|
182
|
-
"topicProductLine"
|
|
183
|
-
);
|
|
184
|
-
const productLine = productLines?.[0];
|
|
185
|
-
|
|
186
|
-
log(`Get parentModel details...`);
|
|
187
|
-
const parentModels = await getTopicDetails(
|
|
188
|
-
topicSubModelWithFields,
|
|
189
|
-
"parentModel",
|
|
190
|
-
"topicModel"
|
|
191
|
-
);
|
|
192
|
-
const parentModel = parentModels?.[0];
|
|
193
|
-
|
|
194
|
-
log(`Get subFamily details...`);
|
|
195
|
-
const subFamilies = await getTopicDetails(
|
|
196
|
-
topicSubModelWithFields,
|
|
197
|
-
"subFamily",
|
|
198
|
-
"topicSubFamily",
|
|
199
|
-
false,
|
|
200
|
-
true,
|
|
201
|
-
true
|
|
202
|
-
);
|
|
203
|
-
const subFamily = subFamilies?.[0];
|
|
204
|
-
|
|
205
|
-
log(`Get thumbnail imgix details...`);
|
|
206
|
-
let thumbnailImgix = {};
|
|
207
|
-
const thumbnailImgixWrapperImgixID =
|
|
208
|
-
topicSubModelWithFields?.fields?.thumbnailImgix?.[
|
|
209
|
-
defaultEnvironmentLocaleCode
|
|
210
|
-
]?.sys.id;
|
|
211
|
-
if (thumbnailImgixWrapperImgixID) {
|
|
212
|
-
thumbnailImgix = await getWrapperImgixFields(thumbnailImgixWrapperImgixID);
|
|
213
|
-
} else {
|
|
214
|
-
log(`No thumbnail imgix found`, "WARN");
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const record: AlgoliaSubModelRecord = {
|
|
218
|
-
objectID: topicSubModelWithFields.sys.id,
|
|
219
|
-
names: await getAllTranslations(
|
|
220
|
-
topicSubModelWithFields?.fields?.name || {}
|
|
221
|
-
),
|
|
222
|
-
code:
|
|
223
|
-
topicSubModelWithFields?.fields?.code?.[defaultEnvironmentLocaleCode] ||
|
|
224
|
-
"",
|
|
225
|
-
description: await getAllTranslations(
|
|
226
|
-
topicSubModelWithFields?.fields?.description || {}
|
|
227
|
-
),
|
|
228
|
-
thumbnailImgix,
|
|
229
|
-
catalog,
|
|
230
|
-
productLine,
|
|
231
|
-
productFields,
|
|
232
|
-
subFamily,
|
|
233
|
-
parentModel,
|
|
234
|
-
priority:
|
|
235
|
-
topicSubModelWithFields?.fields?.priority?.[
|
|
236
|
-
defaultEnvironmentLocaleCode
|
|
237
|
-
] || 0,
|
|
238
|
-
isNew: topicSubModelWithFields?.fields?.isNew || false,
|
|
239
|
-
productCounter: await getProductCounter(topicSubModelWithFields),
|
|
240
|
-
destinations:
|
|
241
|
-
topicSubModelWithFields?.fields?.destinations?.[
|
|
242
|
-
defaultEnvironmentLocaleCode
|
|
243
|
-
] || [],
|
|
244
|
-
lastSyncDate: getLocalISOTime(),
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
return record;
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
export const reindexSubModel = async (topicSubModelId: string) => {
|
|
251
|
-
const timeStart = new Date();
|
|
252
|
-
|
|
253
|
-
log(`reindexSubModel - entryId: ${topicSubModelId} `);
|
|
254
|
-
|
|
255
|
-
const object = await getObject(topicSubModelId);
|
|
256
|
-
|
|
257
|
-
// Save record to Algolia
|
|
258
|
-
const index = getIndex(indexKey);
|
|
259
|
-
let record = null;
|
|
260
|
-
if (!isObjectToDelete(object)) {
|
|
261
|
-
log(`Save object`);
|
|
262
|
-
record = await index.saveObject(object);
|
|
263
|
-
} else {
|
|
264
|
-
log(`Delete object`);
|
|
265
|
-
record = await index.deleteObject(object.objectID);
|
|
266
|
-
}
|
|
267
|
-
const timeEnd = new Date();
|
|
268
|
-
const seconds = secondBetweenTwoDate(timeStart, timeEnd);
|
|
269
|
-
log(`Execution time: ${seconds} seconds`);
|
|
270
|
-
|
|
271
|
-
return { ...record, ...object };
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const getObjects = async (
|
|
275
|
-
offset: number,
|
|
276
|
-
limit: number,
|
|
277
|
-
catalogCode?: AvailableCatalogs
|
|
278
|
-
): Promise<AlgoliaPaginateRecords> => {
|
|
279
|
-
const client = await getClient();
|
|
280
|
-
|
|
281
|
-
const opts: any = {
|
|
282
|
-
content_type: "topicSubModel",
|
|
283
|
-
limit,
|
|
284
|
-
skip: offset,
|
|
285
|
-
select: topicSubModelSelect,
|
|
286
|
-
};
|
|
287
|
-
if (catalogCode) {
|
|
288
|
-
opts["fields.catalog.sys.id"] = catalogCode;
|
|
289
|
-
}
|
|
290
|
-
const { items, total } = await client.withAllLocales.getEntries(opts);
|
|
291
|
-
|
|
292
|
-
const objects: AlgoliaSubModelRecord[] = [];
|
|
293
|
-
let count: number = Number(offset);
|
|
294
|
-
let current: number = 0;
|
|
295
|
-
for (const topicSubModel of items) {
|
|
296
|
-
log(`${++count} of ${total}`, "INFO");
|
|
297
|
-
const timeStart = new Date();
|
|
298
|
-
const record = await getObject(topicSubModel);
|
|
299
|
-
const timeEnd = new Date();
|
|
300
|
-
const seconds = secondBetweenTwoDate(timeStart, timeEnd);
|
|
301
|
-
log(`Execution time: ${seconds} seconds`);
|
|
302
|
-
objects.push(record);
|
|
303
|
-
if (serverUtils) {
|
|
304
|
-
serverUtils.log(topicSubModel.sys.id);
|
|
305
|
-
const progress = Math.floor((++current / items.length) * 100);
|
|
306
|
-
serverUtils.updateProgress(progress);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return {
|
|
311
|
-
objects,
|
|
312
|
-
offset: Number(offset) + Number(limit),
|
|
313
|
-
limit: Number(limit),
|
|
314
|
-
completed: count >= total, // if is true the import is completed
|
|
315
|
-
total,
|
|
316
|
-
};
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
export const reindexSubModels = async (
|
|
320
|
-
offset: number = 0,
|
|
321
|
-
limit: number = 50,
|
|
322
|
-
catalogCode?: AvailableCatalogs
|
|
323
|
-
) => {
|
|
324
|
-
const timeStart = new Date();
|
|
325
|
-
log(
|
|
326
|
-
`reindexSubModels - offset: ${offset} limit: ${limit} catalogCode: ${catalogCode}`
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
const records = await getObjects(offset, limit, catalogCode);
|
|
330
|
-
const objectsToSave = records.objects.filter(
|
|
331
|
-
(object) => !isObjectToDelete(object)
|
|
332
|
-
);
|
|
333
|
-
const objectIdsToDelete = records.objects
|
|
334
|
-
.filter((object) => isObjectToDelete(object))
|
|
335
|
-
.map((object) => object.objectID);
|
|
336
|
-
|
|
337
|
-
// Save records to Algolia
|
|
338
|
-
const index = getIndex(indexKey);
|
|
339
|
-
log(`Save ${objectsToSave.length} objects to ${index.indexName} index`);
|
|
340
|
-
const savedObjectIDs = await index.saveObjects(objectsToSave);
|
|
341
|
-
log(
|
|
342
|
-
`Delete ${objectIdsToDelete.length} objects from ${index.indexName} index`
|
|
343
|
-
);
|
|
344
|
-
const deletedObjectIDs = await index.deleteObjects(objectIdsToDelete);
|
|
345
|
-
|
|
346
|
-
const timeEnd = new Date();
|
|
347
|
-
const seconds = secondBetweenTwoDate(timeStart, timeEnd);
|
|
348
|
-
log(`Execution time: ${seconds} seconds`);
|
|
349
|
-
|
|
350
|
-
return {
|
|
351
|
-
...records,
|
|
352
|
-
savedObjectIDs: savedObjectIDs.objectIDs,
|
|
353
|
-
deletedObjectIDs: deletedObjectIDs.objectIDs,
|
|
354
|
-
};
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
export const removeSubModelObject = async (topicSubModelId: string) => {
|
|
358
|
-
return removeIndexObject(topicSubModelId, indexKey);
|
|
359
|
-
};
|
package/src/browser.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
// import { initSentry } from "./libs/sentry";
|
|
2
|
-
// initSentry();
|
|
3
|
-
// export { reportError } from "./libs/sentry";
|
|
4
|
-
export { init as initPim } from "./pim/config";
|
|
5
|
-
export {
|
|
6
|
-
init as initContentful,
|
|
7
|
-
initBaseEntries,
|
|
8
|
-
deletePages,
|
|
9
|
-
deleteEntries,
|
|
10
|
-
getEntryByID,
|
|
11
|
-
getTopicPage,
|
|
12
|
-
} from "./libs/contentful";
|
|
13
|
-
export {
|
|
14
|
-
init as initS3,
|
|
15
|
-
upload as uploadS3,
|
|
16
|
-
saveJsonToS3,
|
|
17
|
-
getFileFromS3,
|
|
18
|
-
savePDFToS3,
|
|
19
|
-
} from "./libs/s3";
|
|
20
|
-
export {
|
|
21
|
-
importDictionaryFields,
|
|
22
|
-
importDictionaryIcons,
|
|
23
|
-
importDictionaryData,
|
|
24
|
-
importDictionaryProductLine,
|
|
25
|
-
importDictionaryProductSubLine,
|
|
26
|
-
} from "./pim/methods/dictionary";
|
|
27
|
-
export { importCategories } from "./pim/methods/catalogs";
|
|
28
|
-
export { importLatestProducts } from "./pim/methods/latestProducts";
|
|
29
|
-
export { importModels } from "./pim/methods/models";
|
|
30
|
-
export { importSubModels } from "./pim/methods/submodels";
|
|
31
|
-
export { importSubFamilies } from "./pim/methods/subfamilies";
|
|
32
|
-
export { importFamilies } from "./pim/methods/families";
|
|
33
|
-
export {
|
|
34
|
-
importProductByCode,
|
|
35
|
-
setProductsRelationships,
|
|
36
|
-
setProductRelationships,
|
|
37
|
-
getAllProductEntriesByCatalog,
|
|
38
|
-
audit,
|
|
39
|
-
generateTechSpecPdf,
|
|
40
|
-
setProductsAutodescription,
|
|
41
|
-
getProductAutodescription,
|
|
42
|
-
setProductAutodescriptionByTopicId,
|
|
43
|
-
removeProductFromColorVariantsByProductLine,
|
|
44
|
-
removeAllProductModelProductRelations,
|
|
45
|
-
} from "./pim/methods/products";
|
|
46
|
-
// export {
|
|
47
|
-
// createOrUpdateCatalogPages,
|
|
48
|
-
// createOrUpdateCatalogPageByCode,
|
|
49
|
-
// } from "./pim/methods/pages/catalogs";
|
|
50
|
-
export { resetIndexSettings } from "./algolia/config";
|
|
51
|
-
export {
|
|
52
|
-
reindexFamilies,
|
|
53
|
-
reindexFamily,
|
|
54
|
-
removeFamilyObject,
|
|
55
|
-
} from "./algolia/families";
|
|
56
|
-
// export {
|
|
57
|
-
// createOrUpdateFamilyPages,
|
|
58
|
-
// createOrUpdateFamilyPageByCode,
|
|
59
|
-
// } from "./pim/methods/pages/families";
|
|
60
|
-
export {
|
|
61
|
-
reindexSubFamilies,
|
|
62
|
-
reindexSubFamily,
|
|
63
|
-
removeSubFamilyObject,
|
|
64
|
-
} from "./algolia/subFamilies";
|
|
65
|
-
// export {
|
|
66
|
-
// createOrUpdateSubFamilyPages,
|
|
67
|
-
// createOrUpdateSubFamilyPageByCode,
|
|
68
|
-
// createOrUpdateSubFamilyPagesByCatalog,
|
|
69
|
-
// } from "./pim/methods/pages/subfamilies";
|
|
70
|
-
export {
|
|
71
|
-
reindexProduct,
|
|
72
|
-
reindexProducts,
|
|
73
|
-
removeProductObject,
|
|
74
|
-
} from "./algolia/products";
|
|
75
|
-
export {
|
|
76
|
-
reindexSubModel,
|
|
77
|
-
reindexSubModels,
|
|
78
|
-
removeSubModelObject,
|
|
79
|
-
} from "./algolia/subModels";
|
|
80
|
-
export {
|
|
81
|
-
reindexModel,
|
|
82
|
-
reindexModels,
|
|
83
|
-
removeModelObject,
|
|
84
|
-
} from "./algolia/models";
|
|
85
|
-
export {
|
|
86
|
-
reindexDownload,
|
|
87
|
-
reindexDownloads,
|
|
88
|
-
removeDownloadObject,
|
|
89
|
-
} from "./algolia/downloads";
|
|
90
|
-
export {
|
|
91
|
-
reindexInspiration,
|
|
92
|
-
reindexInspirations,
|
|
93
|
-
removeInspirationObject,
|
|
94
|
-
} from "./algolia/inspirations";
|
|
95
|
-
export {
|
|
96
|
-
reindexProject,
|
|
97
|
-
reindexProjects,
|
|
98
|
-
removeProjectObject,
|
|
99
|
-
} from "./algolia/projects";
|
|
100
|
-
export {
|
|
101
|
-
reindexStory,
|
|
102
|
-
reindexStories,
|
|
103
|
-
removeStoryObject,
|
|
104
|
-
} from "./algolia/stories";
|
|
105
|
-
export {
|
|
106
|
-
reindexPressReview,
|
|
107
|
-
reindexPressReviews,
|
|
108
|
-
removePressReviewObject,
|
|
109
|
-
} from "./algolia/pressReview";
|
|
110
|
-
export {
|
|
111
|
-
reindexPressRelease,
|
|
112
|
-
reindexPressReleases,
|
|
113
|
-
removePressReleaseObject,
|
|
114
|
-
} from "./algolia/pressRelease";
|
|
115
|
-
export { reindexPost, reindexPosts, removePostObject } from "./algolia/news";
|
|
116
|
-
export { importDownloads } from "./downloads/import";
|
|
117
|
-
export { getLocalISOTime } from "./utils";
|
|
118
|
-
export { getStaticDailyProducts } from "./pim/endpoints";
|
|
119
|
-
export { log, setLogId } from "./libs/logs";
|
|
120
|
-
export { removeRecordsByStatus } from "./algolia/clean";
|
|
121
|
-
export { generatePDFByUrl } from "./libs/pdf";
|
|
122
|
-
export { netlifyBuild } from "./libs/netlify";
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getEnvironmentDefaultLocaleCode,
|
|
3
|
-
getEnvironment,
|
|
4
|
-
} from "../../libs/contentful";
|
|
5
|
-
import type { EntryProps } from "contentful-management/dist/typings/entities/entry";
|
|
6
|
-
|
|
7
|
-
interface Filter {
|
|
8
|
-
key: string;
|
|
9
|
-
value: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default class ManageEntry {
|
|
13
|
-
/**
|
|
14
|
-
* Get Entry
|
|
15
|
-
*
|
|
16
|
-
* @param contentType
|
|
17
|
-
* @param filter Default:
|
|
18
|
-
* {
|
|
19
|
-
* key: "fields.name",
|
|
20
|
-
* value: categoryTitle
|
|
21
|
-
* }
|
|
22
|
-
* @param select
|
|
23
|
-
*
|
|
24
|
-
* @example ```javascript
|
|
25
|
-
* const contentType = "topicDownloadCategory";
|
|
26
|
-
* const filter = {
|
|
27
|
-
* key: "fields.name",
|
|
28
|
-
* value: categoryTitle
|
|
29
|
-
* }
|
|
30
|
-
*
|
|
31
|
-
* ManageEntry.get(contentType, filter)
|
|
32
|
-
* ```
|
|
33
|
-
* @returns
|
|
34
|
-
*/
|
|
35
|
-
async get(
|
|
36
|
-
contentType: string,
|
|
37
|
-
filter: Filter,
|
|
38
|
-
select?: string
|
|
39
|
-
): Promise<
|
|
40
|
-
| import("contentful-management/dist/typings/entities/entry").Entry
|
|
41
|
-
| undefined
|
|
42
|
-
> {
|
|
43
|
-
const env = await getEnvironment();
|
|
44
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
45
|
-
const opts: any = {
|
|
46
|
-
content_type: contentType,
|
|
47
|
-
limit: 1,
|
|
48
|
-
locale: defEnvLocaleCode,
|
|
49
|
-
select,
|
|
50
|
-
};
|
|
51
|
-
opts[filter.key] = filter.value;
|
|
52
|
-
const { items } = await env.getEntries(opts);
|
|
53
|
-
return items?.[0];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
*
|
|
58
|
-
* @param data
|
|
59
|
-
* @param contentType
|
|
60
|
-
* @param filter
|
|
61
|
-
*
|
|
62
|
-
* @example ```javascript
|
|
63
|
-
* const data: Omit<EntryProps, "sys"> = {
|
|
64
|
-
* fields: {
|
|
65
|
-
* name: {},
|
|
66
|
-
* showSearchBar: {},
|
|
67
|
-
* showFilterByType: {},
|
|
68
|
-
* filterBy: {},
|
|
69
|
-
* },
|
|
70
|
-
* };
|
|
71
|
-
* data.fields.name[defEnvLocaleCode] = "Foo";
|
|
72
|
-
*
|
|
73
|
-
* const contentType = "Bar";
|
|
74
|
-
* const filter = {
|
|
75
|
-
* key: "fields.name",
|
|
76
|
-
* value: "Foo"
|
|
77
|
-
* }
|
|
78
|
-
*
|
|
79
|
-
* ManageEntry.add(data, contentType, filter)
|
|
80
|
-
* ```
|
|
81
|
-
*
|
|
82
|
-
* @returns
|
|
83
|
-
*/
|
|
84
|
-
async add(
|
|
85
|
-
data: Omit<EntryProps, "sys">,
|
|
86
|
-
contentType: string,
|
|
87
|
-
filter: Filter
|
|
88
|
-
): Promise<
|
|
89
|
-
import("contentful-management/dist/typings/entities/entry").Entry
|
|
90
|
-
> {
|
|
91
|
-
let entry = await this.get(contentType, filter);
|
|
92
|
-
if (entry) return entry;
|
|
93
|
-
|
|
94
|
-
const env = await getEnvironment();
|
|
95
|
-
entry = await env.createEntry(contentType, data);
|
|
96
|
-
|
|
97
|
-
return entry;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
id,Title,"Download Legals Categories","Download Legals Catalogues",Files_type,Files_text_type,Files_file,Files_site_ids,"Image URL","Image Filename","Image ID","Image Title","Image Caption","Image Description","Image Alt Text","Image Featured"
|
|
2
|
-
376223,"Flos/Flos Architectural/Flos Outdoor/Flos Bespoke/Ares the outdoor by Flos/Ares branded products","General terms and conditions",,",,,,","EN,IT,ES,FR,DE","https://www.flos.com/wp-content/uploads/2020/10/Condizioni-generali-di-Vendita-FLOS-GROUP_EN.pdf,https://www.flos.com/wp-content/uploads/2020/10/Condizioni-generali-di-Vendita-FLOS-GROUP_IT.pdf,https://www.flos.com/wp-content/uploads/2020/10/Condizioni-generali-di-Vendita-FLOS-GROUP_ES.pdf,https://www.flos.com/wp-content/uploads/2020/10/Condizioni-generali-di-Vendita-FLOS-GROUP_FR.pdf,https://www.flos.com/wp-content/uploads/2020/10/Condizioni-generali-di-Vendita-FLOS-GROUP_DE.pdf","1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10",https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg,2_guarantee-thumb.jpg,119622,2_guarantee-thumb,,,,https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg
|
|
3
|
-
376224,"USA Canada Guarantee",Guarantees,,,EN,https://www.flos.com/wp-content/uploads/2017/10/USA_Canada_Warranty.pdf,1|2|3|4|5|6|7|8|9|10,https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg,2_guarantee-thumb.jpg,119622,2_guarantee-thumb,,,,https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg
|
|
4
|
-
376225,"No EU Guarantee",Guarantees,,",,,,,,,,,","EN,IT,FR,AR,DE,ES,CHN,JP,PT,RU","https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GUARANTEE_Flos_EN.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GARANZIA_Flos_IT.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GARANTIE_Flos_FR.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GUARANTEE_Flos_AR.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GARANTIE_derFirmaFlos_DE.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GARANTIA_Flos_ES.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GUARANTEE_Flos_CHN.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GUARANTEE_Flos_JP.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GARANTIA_Flos_PT.pdf,https://www.flos.com/wp-content/uploads/2017/10/NO_UE_GUARANTEE_Flos_RU.pdf","1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10",https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg,2_guarantee-thumb.jpg,119622,2_guarantee-thumb,,,,https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg
|
|
5
|
-
376226,"Flos Guarantee",Guarantees,,",,,,","EN,IT,FR,DE,ES","https://www.flos.com/wp-content/uploads/2020/10/WARRANTY_FLOS-GROUP_EN.pdf,https://www.flos.com/wp-content/uploads/2020/10/WARRANTY_FLOS-GROUP_IT.pdf,https://www.flos.com/wp-content/uploads/2020/10/WARRANTY_FLOS-GROUP_FR.pdf,https://www.flos.com/wp-content/uploads/2020/10/WARRANTY_FLOS-GROUP_DE-1.pdf,https://www.flos.com/wp-content/uploads/2020/10/WARRANTY_FLOS-GROUP_ES.pdf","1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10,1|2|3|4|5|6|7|8|9|10",https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg,2_guarantee-thumb.jpg,119622,2_guarantee-thumb,,,,https://www.flos.com/wp-content/uploads/2017/10/2_guarantee-thumb.jpg
|