pim-import 2.47.4 → 2.49.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.
@@ -1,21 +1,16 @@
1
1
  /**
2
2
  * Product index
3
3
  */
4
- import { cfLocales } from "../libs/contentful";
5
4
  import {
6
5
  getClient,
7
6
  getEnvironmentDefaultLocaleCode,
8
7
  getEntryByID,
9
8
  getTopicDetails,
10
- getDictionaryJson,
11
- getDictionaryLocaleValue,
12
9
  } from "../libs/contentful-cda";
13
10
  import {
14
11
  CfLocalizedEntryField,
15
12
  TopicDetailsResponse,
16
- AvailableCatalogs,
17
13
  AlgoliaPaginateRecords,
18
- CfSys,
19
14
  WrapperImageFields,
20
15
  } from "../types";
21
16
  import type { Entry } from "contentful-management/dist/typings/entities/entry";
@@ -62,218 +57,6 @@ const indexKey: AvailableIndicesKey = "products";
62
57
  const topicProductSelect =
63
58
  "sys,fields.name,fields.code,fields.catalogs,fields.categoriesArchitectural,fields.categoriesOutdoor,fields.categoriesDecorative,fields.families,fields.subFamiliesArchitectural,fields.subFamiliesOutdoor,fields.subFamiliesDecorative,fields.modelsArchitectural,fields.modelsOutdoor,fields.modelsDecorative,fields.subModelsArchitectural,fields.subModelsOutdoor,fields.subModelsDecorative,fields.productLine,fields.productSubLine,fields.productFields,fields.thumbnailImgix";
64
59
 
65
- const getLightModuleAutoDescriptionByProductFields = async (
66
- productFileds: any,
67
- catalogs: AvailableCatalogs[]
68
- ) => {
69
- const autoDescription: any = {};
70
- const dictionaryJson = await getDictionaryJson();
71
- for (const locale of cfLocales) {
72
- if (!autoDescription?.[locale]) {
73
- autoDescription[locale] = "";
74
- }
75
- let addSeparator = false;
76
- if (productFileds?.electrical?.lampCategories) {
77
- const lampCategoriesLocalizedValues = [];
78
- for (const lampCategory of productFileds.electrical.lampCategories) {
79
- const lampCategoryLocalizedValue = await getDictionaryLocaleValue(
80
- locale,
81
- "lampCategories",
82
- lampCategory.code,
83
- "electrical",
84
- dictionaryJson
85
- );
86
- if (lampCategoryLocalizedValue) {
87
- lampCategoriesLocalizedValues.push(lampCategoryLocalizedValue);
88
- }
89
- }
90
-
91
- if (lampCategoriesLocalizedValues.length) {
92
- if (addSeparator) {
93
- autoDescription[locale] += " - ";
94
- } else {
95
- addSeparator = true;
96
- }
97
- autoDescription[locale] += lampCategoriesLocalizedValues.join(", ");
98
- }
99
- }
100
-
101
- if (
102
- productFileds?.electrical?.wPower &&
103
- catalogs.indexOf("ARCHITECTURAL") !== -1
104
- ) {
105
- if (addSeparator) {
106
- autoDescription[locale] += " - ";
107
- } else {
108
- addSeparator = true;
109
- }
110
- autoDescription[locale] += productFileds.electrical.wPower;
111
- }
112
-
113
- if (
114
- productFileds?.optical?.numberOfHeads &&
115
- productFileds?.optical?.numberOfHeads > 1 &&
116
- productFileds?.photometric?.realNetFlow &&
117
- catalogs.indexOf("ARCHITECTURAL") !== -1
118
- ) {
119
- if (addSeparator) {
120
- autoDescription[locale] += " - ";
121
- } else {
122
- addSeparator = true;
123
- }
124
- autoDescription[locale] +=
125
- productFileds.optical.numberOfHeads +
126
- " x " +
127
- productFileds.photometric.realNetFlow;
128
- } else if (
129
- productFileds?.photometric?.realNetFlow &&
130
- catalogs.indexOf("ARCHITECTURAL") !== -1
131
- ) {
132
- if (addSeparator) {
133
- autoDescription[locale] += " - ";
134
- } else {
135
- addSeparator = true;
136
- }
137
- autoDescription[locale] += productFileds.photometric.realNetFlow;
138
- }
139
-
140
- if (productFileds?.photometric?.temperatureColor?.code) {
141
- const temperatireColorLocalizedValue = await getDictionaryLocaleValue(
142
- locale,
143
- "temperatureColor",
144
- productFileds.photometric.temperatureColor.code,
145
- "photometric",
146
- dictionaryJson
147
- );
148
- if (temperatireColorLocalizedValue) {
149
- if (addSeparator) {
150
- autoDescription[locale] += " - ";
151
- } else {
152
- addSeparator = true;
153
- }
154
- autoDescription[locale] += temperatireColorLocalizedValue;
155
- }
156
- }
157
-
158
- if (productFileds?.photometric?.cri?.code) {
159
- const CriLocalizedValue = await getDictionaryLocaleValue(
160
- locale,
161
- "cri",
162
- productFileds.photometric.cri.code,
163
- "photometric",
164
- dictionaryJson
165
- );
166
- if (CriLocalizedValue) {
167
- if (addSeparator) {
168
- autoDescription[locale] += " - ";
169
- } else {
170
- addSeparator = true;
171
- }
172
- autoDescription[locale] += "CRI " + CriLocalizedValue;
173
- }
174
- }
175
-
176
- if (
177
- productFileds?.photometric?.beam0_180 &&
178
- catalogs.indexOf("OUTDOOR") !== -1
179
- ) {
180
- if (addSeparator) {
181
- autoDescription[locale] += " - ";
182
- } else {
183
- addSeparator = true;
184
- }
185
- autoDescription[locale] += "BEAM " + productFileds.photometric.beam0_180;
186
- }
187
- }
188
-
189
- return autoDescription;
190
- };
191
-
192
- const getOtherAutoDescriptionByProductFields = async (productFileds: any) => {
193
- const autoDescription: any = {};
194
- const dictionaryJson = await getDictionaryJson();
195
- for (const locale of cfLocales) {
196
- if (!autoDescription?.[locale]) {
197
- autoDescription[locale] = "";
198
- }
199
- let addSeparator = false;
200
- // Profile and others
201
- if (productFileds?.physical?.length) {
202
- autoDescription[locale] += "Length: " + productFileds.physical.length;
203
- addSeparator = true;
204
- }
205
-
206
- if (productFileds?.mountings) {
207
- const mountingsLocalizedValues = [];
208
- for (const mounting of productFileds.mountings) {
209
- const mountingLocalizedValue = await getDictionaryLocaleValue(
210
- locale,
211
- "mountings",
212
- mounting.code,
213
- "",
214
- dictionaryJson
215
- );
216
- if (mountingLocalizedValue) {
217
- mountingsLocalizedValues.push(mountingLocalizedValue);
218
- }
219
- }
220
-
221
- if (addSeparator) {
222
- autoDescription[locale] += " - ";
223
- } else {
224
- addSeparator = true;
225
- }
226
- autoDescription[locale] += mountingsLocalizedValues.join(", ");
227
- }
228
- }
229
-
230
- return autoDescription;
231
- };
232
-
233
- /**
234
- * Get topicProduct autoDescription
235
- *
236
- * @param topicProduct
237
- * @returns
238
- */
239
- const getTopicProductAutodescription = async (topicProduct: Entry) => {
240
- const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
241
- let catalogs = topicProduct?.fields?.catalogs?.[defaultEnvironmentLocaleCode];
242
- if (catalogs) {
243
- catalogs = catalogs.map((catalog: CfSys) => catalog.sys.id);
244
- }
245
- const productLineCode =
246
- topicProduct?.fields?.productLine?.[defaultEnvironmentLocaleCode]?.sys?.id;
247
- const productFileds =
248
- topicProduct?.fields?.productFields?.[defaultEnvironmentLocaleCode];
249
-
250
- let autoDescription: any = {};
251
- switch (productLineCode) {
252
- case "PLINE6": // Soft Plate
253
- case "PLINE5": // Light Bulb
254
- case "PLINE3": // Driver
255
- case "PLINE2": // Accessory
256
- // post_content
257
- autoDescription = topicProduct?.fields?.description;
258
- break;
259
- case "PLINE1": // Light Module
260
- autoDescription = await getLightModuleAutoDescriptionByProductFields(
261
- productFileds,
262
- catalogs
263
- );
264
-
265
- break;
266
- default:
267
- autoDescription = await getOtherAutoDescriptionByProductFields(
268
- productFileds
269
- );
270
-
271
- break;
272
- }
273
-
274
- return autoDescription;
275
- };
276
-
277
60
  const pipedreamPDFGenerator = async (topicProductId: string) => {
278
61
  if (process.env.FPI_PIPEDREAM_TECH_SPEC_PDF) {
279
62
  const res = await axios.get(process.env.FPI_PIPEDREAM_TECH_SPEC_PDF, {
@@ -455,9 +238,7 @@ const getObject = async (
455
238
  );
456
239
 
457
240
  log(`Get autoDescription...`);
458
- const autoDescription = await getTopicProductAutodescription(
459
- topicProductWithFields
460
- );
241
+ const autoDescription = topicProductWithFields?.fields?.autoDescription ?? {};
461
242
 
462
243
  log(`Get thumbnail imgix details...`);
463
244
  let thumbnailImgix = {};
@@ -0,0 +1,187 @@
1
+ import { log } from "../libs/logs";
2
+ import {
3
+ getClient,
4
+ getEnvironmentDefaultLocaleCode,
5
+ getEntryByID,
6
+ getTopicPage,
7
+ } from "../libs/contentful-cda";
8
+ import { getIndex, AvailableIndicesKey, removeIndexObject } from "./config";
9
+ import { getLocalISOTime, secondBetweenTwoDate } from "../utils";
10
+ import type { Entry } from "contentful-management/dist/typings/entities/entry";
11
+ import { CfLocalizedEntryField, AlgoliaPaginateRecords } from "../types";
12
+
13
+ const indexKey: AvailableIndicesKey = "stories";
14
+
15
+ export type AlgoliaStoryRecord = {
16
+ objectID: string;
17
+ name?: CfLocalizedEntryField;
18
+ excerpt?: CfLocalizedEntryField;
19
+ description?: CfLocalizedEntryField;
20
+ slugs?: {};
21
+ lastSyncDate?: string;
22
+ };
23
+
24
+ const getObject = async (topicStory: Entry): Promise<AlgoliaStoryRecord> => {
25
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
26
+ log(`Sync the ${topicStory.sys.id} topicStory...`);
27
+ let topicStoryWithFields: Entry = topicStory;
28
+
29
+ const emptyLocalizedField: CfLocalizedEntryField = {
30
+ [defaultEnvironmentLocaleCode]: "",
31
+ };
32
+
33
+ if (!topicStoryWithFields?.fields) {
34
+ log(`Get the ${topicStory.sys.id} topicStory details...`);
35
+ topicStoryWithFields = await getEntryByID(topicStory.sys.id, "topicStory");
36
+ }
37
+
38
+ if (!topicStoryWithFields) {
39
+ log(`The topicStory ${topicStory.sys.id} not found`, "WARN");
40
+
41
+ const recordFail: AlgoliaStoryRecord = {
42
+ objectID: topicStory?.sys?.id,
43
+ };
44
+
45
+ return recordFail; // return objectID to delete the record if it exists
46
+ }
47
+
48
+ log(`Get page details...`);
49
+ const page = await getTopicPage(topicStory.sys.id, "fields.slug");
50
+ const slugs = page?.fields.slug || {};
51
+
52
+ // Single record
53
+ const record: AlgoliaStoryRecord = {
54
+ objectID: topicStoryWithFields.sys.id,
55
+ name: topicStoryWithFields?.fields?.title || emptyLocalizedField,
56
+ excerpt: topicStoryWithFields?.fields?.excerpt || emptyLocalizedField,
57
+ description:
58
+ topicStoryWithFields?.fields?.description || emptyLocalizedField,
59
+ slugs,
60
+ lastSyncDate: getLocalISOTime(),
61
+ };
62
+
63
+ return record;
64
+ };
65
+
66
+ export const reindexStory = async (topicStoryId: string) => {
67
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
68
+ const timeStart = new Date();
69
+
70
+ log(`reindexStory - entryId: ${topicStoryId} `);
71
+
72
+ const topicStory = await getEntryByID(topicStoryId, "topicStory");
73
+
74
+ if (!topicStory) {
75
+ log(`No topicStoryId found with id ${topicStoryId}`, "WARN");
76
+ return false;
77
+ }
78
+
79
+ const object = await getObject(topicStory);
80
+
81
+ // Save record to Algolia
82
+ const index = getIndex(indexKey);
83
+ let record = null;
84
+ const slugs: any = object?.slugs;
85
+ if (slugs?.[defaultEnvironmentLocaleCode]) {
86
+ log(`Save object`);
87
+ record = await index.saveObject(object);
88
+ } else {
89
+ log(`Delete object`);
90
+ record = await index.deleteObject(object.objectID);
91
+ }
92
+ const timeEnd = new Date();
93
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
94
+ log(`Execution time: ${seconds} seconds`);
95
+
96
+ return { ...record, ...object };
97
+ };
98
+
99
+ /**
100
+ * Get Objects
101
+ *
102
+ * @param offset
103
+ * @param limit
104
+ * @param filterKey
105
+ * @param filterValue
106
+ * @returns
107
+ */
108
+ const getObjects = async (
109
+ offset: number,
110
+ limit: number,
111
+ filterKey?: string,
112
+ filterValue?: string
113
+ ): Promise<AlgoliaPaginateRecords> => {
114
+ const client = await getClient();
115
+
116
+ const opts: any = {
117
+ content_type: "topicStory",
118
+ limit,
119
+ skip: offset,
120
+ locale: "*",
121
+ // select: "",
122
+ };
123
+ if (filterKey && filterValue) {
124
+ opts[filterKey] = filterValue;
125
+ }
126
+ const { items, total } = await client.getEntries(opts);
127
+
128
+ const objects: AlgoliaStoryRecord[] = [];
129
+ let count: number = Number(offset);
130
+ for (const topicStory of items) {
131
+ log(`${++count} of ${total}`, "INFO");
132
+ const timeStart = new Date();
133
+ const record = await getObject(topicStory);
134
+ const timeEnd = new Date();
135
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
136
+ log(`Execution time: ${seconds} seconds`);
137
+ objects.push(record);
138
+ }
139
+
140
+ return {
141
+ objects,
142
+ offset: Number(offset) + Number(limit),
143
+ limit: Number(limit),
144
+ completed: count >= total, // if is true the import is completed
145
+ total,
146
+ };
147
+ };
148
+
149
+ export const reindexStories = async (
150
+ offset: number = 0,
151
+ limit: number = 50,
152
+ filterKey: string = "",
153
+ filterValue: string = ""
154
+ ) => {
155
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
156
+ const timeStart = new Date();
157
+ log(
158
+ `reindexStories - filterKey: ${filterKey} filterValue: ${filterValue} offset: ${offset} limit: ${limit} `
159
+ );
160
+
161
+ const records = await getObjects(offset, limit, filterKey, filterValue);
162
+ const objectsToSave = records.objects.filter(
163
+ (object) => object?.slugs?.[defaultEnvironmentLocaleCode]
164
+ );
165
+ const objectIdsToDelete = records.objects
166
+ .filter((object) => !object?.slugs?.[defaultEnvironmentLocaleCode])
167
+ .map((object) => object.objectID);
168
+
169
+ // Save records to Algolia
170
+ const index = getIndex(indexKey);
171
+ log(`Save ${objectsToSave.length} objects to ${index.indexName} index`);
172
+ const savedObjectIDs = await index.saveObjects(objectsToSave);
173
+ log(
174
+ `Delete ${objectIdsToDelete.length} objects from ${index.indexName} index`
175
+ );
176
+ const deletedObjectIDs = await index.deleteObjects(objectIdsToDelete);
177
+
178
+ const timeEnd = new Date();
179
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
180
+ log(`Execution time: ${seconds} seconds`);
181
+
182
+ return { ...records, ...savedObjectIDs, ...deletedObjectIDs };
183
+ };
184
+
185
+ export const removeStoryObject = async (objectId: string) => {
186
+ return removeIndexObject(objectId, indexKey);
187
+ };
package/src/index.ts CHANGED
@@ -36,6 +36,9 @@ export {
36
36
  getAllProductEntriesByCatalog,
37
37
  audit,
38
38
  generateTechSpecPdf,
39
+ setProductsAutodescription,
40
+ getProductAutodescription,
41
+ setProductAutodescriptionByTopicId,
39
42
  } from "./pim/methods/products";
40
43
  // export {
41
44
  // createOrUpdateCatalogPages,
@@ -86,6 +89,11 @@ export {
86
89
  reindexProjects,
87
90
  removeProjectObject,
88
91
  } from "./algolia/projects";
92
+ export {
93
+ reindexStory,
94
+ reindexStories,
95
+ removeStoryObject,
96
+ } from "./algolia/stories";
89
97
  export { importDownloads } from "./downloads/import";
90
98
  export { getLocalISOTime } from "./utils";
91
99
  export { getStaticDailyProducts } from "./pim/endpoints";
@@ -244,7 +244,7 @@ export const getEntryImageDetails = async (entry: Entry, fieldKey: string) => {
244
244
  * 'en-US': 'Architectural Lighting',
245
245
  * ...
246
246
  * },
247
- * code: { 'en-GB': 'ARCHITECTURAL' },
247
+ * code: { 'en': 'ARCHITECTURAL' },
248
248
  * slugs: {
249
249
  * de: 'architectural lighting',
250
250
  * 'en-US': 'architectural lighting'
@@ -43,7 +43,7 @@ export let defaultEnvironmentLocale: Locale;
43
43
  export let defaultEnvironmentLocaleCode: string;
44
44
 
45
45
  export const cfLocales: ContentfulLocale[] = [
46
- "en-GB",
46
+ "en",
47
47
  "en-US",
48
48
  "it",
49
49
  "es",
@@ -537,10 +537,10 @@ export const initBaseEntries = async (): Promise<boolean> => {
537
537
  },
538
538
  };
539
539
  regionGlobalEntryData.fields.region[defaultEnvCode] = "global";
540
- regionGlobalEntryData.fields.defaultLocale[defaultEnvCode] = "en-GB";
540
+ regionGlobalEntryData.fields.defaultLocale[defaultEnvCode] = "en";
541
541
  regionGlobalEntryData.fields.locales[defaultEnvCode] = [
542
542
  "en-US",
543
- "en-GB",
543
+ "en",
544
544
  "it",
545
545
  "de",
546
546
  "fr",
@@ -1023,7 +1023,7 @@ export const addFieldValue = async (
1023
1023
  * 'en-US': 'Architectural Lighting',
1024
1024
  * ...
1025
1025
  * },
1026
- * code: { 'en-GB': 'ARCHITECTURAL' },
1026
+ * code: { 'en': 'ARCHITECTURAL' },
1027
1027
  * slugs: {
1028
1028
  * de: 'architectural lighting',
1029
1029
  * 'en-US': 'architectural lighting'