@localazy/strapi-plugin 0.1.9 → 0.1.11-rc.0

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.
Files changed (45) hide show
  1. package/.eslintrc +6 -2
  2. package/.nvmrc +1 -1
  3. package/admin/src/modules/@common/models/supported-content-type-fields.js +8 -0
  4. package/admin/src/modules/plugin-settings/components/Tree/index.js +2 -0
  5. package/admin/src/modules/plugin-settings/utils/get-filtered-models-schemas.js +4 -4
  6. package/admin/src/modules/plugin-settings/utils/get-models-tree.js +3 -1
  7. package/package.json +1 -1
  8. package/server/bootstrap.js +15 -1
  9. package/server/controllers/localazy-transfer-controller.js +45 -47
  10. package/server/functions/should-set-downloaded-property.js +16 -0
  11. package/server/models/supported-content-type-fields.js +8 -0
  12. package/server/services/index.js +2 -0
  13. package/server/services/strapi-i18n-service.js +4 -3
  14. package/server/services/strapi-localazy-i18n-service.js +104 -0
  15. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-cookbook.js +5761 -0
  16. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-restaurant-simple-menu.js +536 -0
  17. package/server/tests/fixtures/parsed-localazy-entry-to-update-entry.js +35157 -0
  18. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-cookbook-empty-recipes.js +202 -0
  19. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-cookbook.js +2700 -0
  20. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-flat-simple.js +47 -0
  21. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-flat-with-media.js +169 -0
  22. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-menu-empty.js +3003 -0
  23. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-menu-with-media.js +2057 -0
  24. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-sample-json.js +46 -0
  25. package/server/tests/fixtures/{all-models-with-multimedia.js → strapi-plugin-all-models.js} +717 -540
  26. package/server/utils/__tests__/get-models-tree.test.js +1 -1
  27. package/server/utils/__tests__/parsed-localazy-entry-to-create-entry.test.js +74 -107
  28. package/server/utils/__tests__/parsed-localazy-entry-to-update-entry.test.js +396 -133
  29. package/server/utils/__tests__/populate-create-update-entry-with-base-entry.test.js +852 -0
  30. package/server/utils/get-full-populate-object.js +56 -0
  31. package/server/utils/get-models-tree.js +3 -1
  32. package/server/utils/model-utils.js +38 -0
  33. package/server/utils/parsed-localazy-entry-to-create-entry.js +24 -24
  34. package/server/utils/parsed-localazy-entry-to-update-entry.js +43 -4
  35. package/server/utils/pick-entries.js +2 -1
  36. package/server/utils/populate-create-update-entry-with-base-entry.js +222 -0
  37. package/server/utils/reset-array-keys-deep.js +19 -0
  38. package/server/utils/transfer-setup-utils.js +14 -0
  39. package/server/tests/fixtures/restaurant-model.js +0 -230
  40. package/server/tests/fixtures/restaurants-entries.js +0 -152
  41. package/server/tests/fixtures/strapi-book-with-multimedia-components-cs.js +0 -31
  42. package/server/tests/fixtures/stringified-book-cs.js +0 -3
  43. package/server/tests/fixtures/stringified-book-with-multimedia-components-cs.js +0 -3
  44. package/server/tests/fixtures/stringified-restaurant-cs.js +0 -3
  45. package/server/tests/fixtures/stringified-restaurant-de.js +0 -5
package/.eslintrc CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  // "extends": "@strapi-community",
3
3
  "env": {
4
- "jest/globals": true
4
+ "jest/globals": true,
5
+ "es6": true
5
6
  },
6
- "plugins": ["jest"]
7
+ "plugins": ["jest"],
8
+ "parserOptions": {
9
+ "ecmaVersion": "latest"
10
+ }
7
11
  }
package/.nvmrc CHANGED
@@ -1 +1 @@
1
- 14
1
+ 16
@@ -0,0 +1,8 @@
1
+ const SUPPORTED_CONTENT_TYPE_FIELDS = [
2
+ "string",
3
+ "text",
4
+ "richtext",
5
+ "email",
6
+ ];
7
+
8
+ export default SUPPORTED_CONTENT_TYPE_FIELDS;
@@ -30,6 +30,7 @@ function Tree(props) {
30
30
 
31
31
  const hasTruthyValue = Object.values(flattened).some(v => v);
32
32
  const hasFalsyValue = Object.values(flattened).some(v => !v && v !== null);
33
+ const hasAllNullValue = Object.values(flattened).every(v => v === null);
33
34
 
34
35
  if (key === "__model__") {
35
36
  return false;
@@ -45,6 +46,7 @@ function Tree(props) {
45
46
  >
46
47
  {isSubbranchObject && (
47
48
  <Checkbox
49
+ disabled={hasAllNullValue}
48
50
  checked={hasTruthyValue && !hasFalsyValue}
49
51
  indeterminate={hasTruthyValue && hasFalsyValue}
50
52
  onChange={() => onTreeItemClick(flattenedKeys, hasTruthyValue && !hasFalsyValue)}
@@ -1,9 +1,9 @@
1
+ import baseSupportedContentTypeFields from "../../@common/models/supported-content-type-fields";
2
+
1
3
  const SUPPORTED_CONTENT_TYPE_FIELDS = [
2
- "string",
3
- "text",
4
- "richtext",
5
- // "relation", // relation cannot be supported field type
4
+ ...baseSupportedContentTypeFields,
6
5
  "component",
6
+ // "relation", // relation cannot be supported field type
7
7
  ];
8
8
 
9
9
  export default (models) => {
@@ -1,3 +1,5 @@
1
+ import SUPPORTED_CONTENT_TYPE_FIELDS from "../../@common/models/supported-content-type-fields";
2
+
1
3
  /**
2
4
  * Supported kinds of models are expected by the function, needs to be checked before calling the function
3
5
  */
@@ -27,7 +29,7 @@ const getModelsTree = (allModels, localizableModels = []) => {
27
29
  ),
28
30
  };
29
31
  } else if (
30
- ["string", "text", "richtext"].includes(attributes[attribute].type)
32
+ SUPPORTED_CONTENT_TYPE_FIELDS.includes(attributes[attribute].type)
31
33
  ) {
32
34
  // field might not be localizable
33
35
  if (isComponentAttributes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localazy/strapi-plugin",
3
- "version": "0.1.9",
3
+ "version": "0.1.11-rc.0",
4
4
  "description": "The official Strapi Plugin by Localazy.",
5
5
  "strapi": {
6
6
  "name": "localazy",
@@ -1,5 +1,19 @@
1
1
  "use strict";
2
2
 
3
- module.exports = () => {
3
+ const getFullPopulateObject = require('./utils/get-full-populate-object')
4
+
5
+ module.exports = ({ strapi }) => {
4
6
  // bootstrap phase
7
+ // Subscribe to the lifecycles that we are intrested in.
8
+ strapi.db.lifecycles.subscribe((event) => {
9
+ if (event.action === 'beforeFindMany' || event.action === 'beforeFindOne') {
10
+ const populate = event.params?.populate;
11
+
12
+ if (populate && populate[0] === 'deep') {
13
+ const depth = populate[1] ?? 5
14
+ const modelObject = getFullPopulateObject(event.model.uid, depth);
15
+ event.params.populate = modelObject.populate
16
+ }
17
+ }
18
+ });
5
19
  };
@@ -4,6 +4,7 @@ const flattenObject = require("../utils/flatten-object");
4
4
  const {
5
5
  getCollectionsNames,
6
6
  findSetupModelByCollectionName,
7
+ findSetupModelByCollectionUid,
7
8
  isCollectionTransferEnabled,
8
9
  getPickPaths,
9
10
  } = require("../utils/transfer-setup-utils");
@@ -13,10 +14,9 @@ const {
13
14
  isoLocalazyToStrapi,
14
15
  isoStrapiToLocalazy,
15
16
  } = require("../utils/iso-locales-utils");
16
- const parsedLocalazyEntryToCreateEntry = require("../utils/parsed-localazy-entry-to-create-entry");
17
- const parsedLocalazyEntryToUpdateEntry = require("../utils/parsed-localazy-entry-to-update-entry");
17
+ const shouldSetDownloadedProperty = require("../functions/should-set-downloaded-property");
18
18
  const set = require("lodash/set");
19
- const merge = require("lodash/merge");
19
+ const isEmpty = require("lodash/isEmpty");
20
20
 
21
21
  module.exports = {
22
22
  async upload(ctx) {
@@ -159,7 +159,9 @@ module.exports = {
159
159
  const messageReport = [];
160
160
 
161
161
  // Strapi service
162
- const StrapiService = strapi.plugin("localazy").service("strapiService");
162
+ const StrapiService = strapi
163
+ .plugin("localazy")
164
+ .service("strapiService");
163
165
 
164
166
  // Strapi i18n Service
165
167
  const StrapiI18nService = strapi
@@ -175,6 +177,14 @@ module.exports = {
175
177
  const LocalazyDownloadService = strapi
176
178
  .plugin("localazy")
177
179
  .service("localazyDownloadService");
180
+ const strapiLocalazyI18nService = strapi
181
+ .plugin("localazy")
182
+ .service("strapiLocalazyI18nService");
183
+
184
+ const contentTransferSetup = await strapi
185
+ .plugin("localazy")
186
+ .service("pluginSettingsService")
187
+ .getContentTransferSetup();
178
188
 
179
189
  const user = await LocalazyUserService.getUser();
180
190
 
@@ -307,6 +317,7 @@ module.exports = {
307
317
  * Parse Localazy content
308
318
  */
309
319
  const parsedLocalazyContent = {};
320
+ const strapiContentTypesModels = await StrapiService.getModels();
310
321
  for (const [isoLocalazy, keys] of Object.entries(localazyContent)) {
311
322
  const isoStrapi = isoLocalazyToStrapi(isoLocalazy);
312
323
  if (!isoStrapi) {
@@ -321,21 +332,29 @@ module.exports = {
321
332
  const value = localazyEntry.value;
322
333
 
323
334
  const parsedKey = StrapiI18nService.parseLocalazyKey(key);
324
- const setKey = [
325
- isoStrapi,
326
- parsedKey.uid,
327
- parsedKey.id,
328
- ...parsedKey.rest,
329
- ];
330
-
331
- set(parsedLocalazyContent, setKey, value);
335
+
336
+ const modelContentTransferSetup = findSetupModelByCollectionUid(
337
+ contentTransferSetup,
338
+ strapiContentTypesModels,
339
+ parsedKey.uid
340
+ );
341
+
342
+ if (shouldSetDownloadedProperty(modelContentTransferSetup, parsedKey.rest)) {
343
+ const setKey = [
344
+ isoStrapi,
345
+ parsedKey.uid,
346
+ parsedKey.id,
347
+ ...parsedKey.rest,
348
+ ];
349
+
350
+ set(parsedLocalazyContent, setKey, value);
351
+ }
332
352
  }
333
353
  }
334
354
 
335
355
  /**
336
356
  * Iterate over parsed Localazy content and insert/update content in Strapi
337
357
  */
338
- const strapiContentTypesModels = await StrapiService.getModels();
339
358
  for (const [isoStrapi, contentTypes] of Object.entries(
340
359
  parsedLocalazyContent
341
360
  )) {
@@ -358,16 +377,11 @@ module.exports = {
358
377
  /**
359
378
  * Get original source language entry
360
379
  */
361
- const populate = await StrapiService.getPopulateObject(uid);
362
- const baseEntryDeep = await strapi.entityService.findOne(uid, id, {
363
- populate,
364
- });
365
- let baseEntry = await strapi.entityService.findOne(uid, id, {
366
- populate: "*",
380
+ const baseEntry = await strapi.entityService.findOne(uid, id, {
381
+ populate: "deep",
367
382
  });
368
- baseEntry = merge(baseEntry, baseEntryDeep);
369
383
 
370
- if (!baseEntry) {
384
+ if (isEmpty(baseEntry)) {
371
385
  const message = `Source language entry ${uid}[${id}] does not exist anymore, skipping...`;
372
386
  throw new Error(message);
373
387
  }
@@ -391,19 +405,15 @@ module.exports = {
391
405
  if (!baseEntryCurrentLanguageLocalizationInfo) {
392
406
  // create new entry
393
407
  try {
394
- const createEntry = parsedLocalazyEntryToCreateEntry(
408
+ const createdEntry = await strapiLocalazyI18nService.createEntry(
409
+ ctx,
410
+ uid,
395
411
  strapiContentTypesModels,
396
412
  translatedModel,
397
- uid,
398
- isoStrapi
413
+ baseEntry,
414
+ isoStrapi,
399
415
  );
400
- const createdEntry =
401
- await StrapiI18nService.createLocalizationForAnExistingEntry(
402
- ctx,
403
- uid,
404
- baseEntry,
405
- createEntry
406
- );
416
+
407
417
  messageReport.push(
408
418
  `Created new entry ${uid}[${createdEntry.id}] in language ${isoStrapi}`
409
419
  );
@@ -419,28 +429,16 @@ module.exports = {
419
429
  try {
420
430
  const localizedEntryId =
421
431
  baseEntryCurrentLanguageLocalizationInfo.id;
422
- const populate = await StrapiService.getPopulateObject(uid); // not needed anymore here
423
- const localizedEntry = await strapi.entityService.findOne(
432
+
433
+ const updatedEntry = await strapiLocalazyI18nService.updateEntry(
424
434
  uid,
425
435
  localizedEntryId,
426
- {
427
- populate,
428
- }
429
- );
430
-
431
- const updateEntry = parsedLocalazyEntryToUpdateEntry(
432
436
  strapiContentTypesModels,
433
437
  translatedModel,
434
- localizedEntry,
435
- uid
438
+ baseEntry,
439
+ isoStrapi,
436
440
  );
437
441
 
438
- const updatedEntry =
439
- await StrapiI18nService.updateLocalizationForAnExistingEntry(
440
- uid,
441
- localizedEntryId,
442
- updateEntry
443
- );
444
442
  messageReport.push(
445
443
  `Updated ${uid}[${updatedEntry.id}] (${isoStrapi})`
446
444
  );
@@ -0,0 +1,16 @@
1
+ const get = require("lodash/get");
2
+
3
+ const shouldSetDownloadedProperty = (
4
+ modelContentTransferSetup,
5
+ parsedKeyRest,
6
+ ) => {
7
+ if (!modelContentTransferSetup.__model__) {
8
+ return false;
9
+ }
10
+
11
+ const filteredParsedKeyRest = parsedKeyRest
12
+ .filter((partialKey) => isNaN(parseInt(partialKey)));
13
+ return !!get(modelContentTransferSetup, filteredParsedKeyRest);
14
+ };
15
+
16
+ module.exports = shouldSetDownloadedProperty;
@@ -0,0 +1,8 @@
1
+ const SUPPORTED_CONTENT_TYPE_FIELDS = [
2
+ "string",
3
+ "text",
4
+ "richtext",
5
+ "email",
6
+ ];
7
+
8
+ module.exports = SUPPORTED_CONTENT_TYPE_FIELDS;
@@ -8,6 +8,7 @@ const localazyUploadService = require("./localazy-upload-service");
8
8
  const localazyDownloadService = require("./localazy-download-service");
9
9
  const localazyPubApiService = require("./localazy-pubapi-service");
10
10
  const strapiI18nService = require("./strapi-i18n-service");
11
+ const strapiLocalazyI18nService = require("./strapi-localazy-i18n-service");
11
12
 
12
13
  module.exports = {
13
14
  localazyUserService,
@@ -18,4 +19,5 @@ module.exports = {
18
19
  localazyDownloadService,
19
20
  localazyPubApiService,
20
21
  strapiI18nService,
22
+ strapiLocalazyI18nService,
21
23
  };
@@ -3,6 +3,7 @@
3
3
  const { isoLocalazyToStrapi } = require("../utils/iso-locales-utils.js");
4
4
  const intlDisplayName = require("../utils/intl-display-name.js");
5
5
  const merge = require("lodash/merge");
6
+ const cloneDeep = require("lodash/cloneDeep");
6
7
  const omitDeep = require("../utils/omit-deep.js");
7
8
 
8
9
  module.exports = ({ strapi }) => ({
@@ -79,7 +80,7 @@ module.exports = ({ strapi }) => ({
79
80
  // this might not be localizable (then method is missing, skip)
80
81
  const contentTypeController = strapi.controller(uid);
81
82
  const newLocalizationCtx = { ...ctx };
82
- newLocalizationCtx.is = () => false; // else throws an error in createLocalization
83
+ newLocalizationCtx.is = () => false; // ! else throws an error in createLocalization
83
84
  newLocalizationCtx.params.id = baseEntry.id;
84
85
 
85
86
  const newEntryLocale = newEntry.locale;
@@ -87,7 +88,7 @@ module.exports = ({ strapi }) => ({
87
88
  "locale",
88
89
  "id",
89
90
  "createdAt",
90
- "publishedAt", // sets as draft (no timestamp)
91
+ "publishedAt", // * sets as draft (no timestamp)
91
92
  "updatedAt",
92
93
  ]);
93
94
  filteredNewEntry.locale = newEntryLocale;
@@ -101,7 +102,7 @@ module.exports = ({ strapi }) => ({
101
102
  baseEntry.id,
102
103
  newEntryLocale
103
104
  );
104
- const mergedEntry = merge(baseEntry, insertedEntry);
105
+ const mergedEntry = merge(cloneDeep(baseEntry), insertedEntry);
105
106
 
106
107
  return mergedEntry;
107
108
  } catch (e) {
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+
3
+ const parsedLocalazyEntryToCreateEntry = require("../utils/parsed-localazy-entry-to-create-entry");
4
+ const parsedLocalazyEntryToUpdateEntry = require("../utils/parsed-localazy-entry-to-update-entry");
5
+
6
+ module.exports = ({ strapi }) => ({
7
+ async createEntry(
8
+ ctx,
9
+ uid,
10
+ strapiContentTypesModels,
11
+ translatedModel,
12
+ baseEntry,
13
+ isoStrapi,
14
+ ) {
15
+ // * The entry will be created and then updated as the structures differ
16
+ // * It's one extra database call, but the complexity of recursive code to maintain does worth it
17
+
18
+ // Strapi i18n Service
19
+ const StrapiI18nService = strapi
20
+ .plugin("localazy")
21
+ .service("strapiI18nService");
22
+
23
+ const createEntry = parsedLocalazyEntryToCreateEntry(
24
+ strapiContentTypesModels,
25
+ translatedModel,
26
+ baseEntry,
27
+ uid,
28
+ isoStrapi,
29
+ );
30
+
31
+ const createdEntry =
32
+ await StrapiI18nService.createLocalizationForAnExistingEntry(
33
+ ctx,
34
+ uid,
35
+ baseEntry,
36
+ createEntry,
37
+ );
38
+
39
+ await this.updateEntry(
40
+ uid,
41
+ createdEntry.id,
42
+ strapiContentTypesModels,
43
+ translatedModel,
44
+ baseEntry,
45
+ isoStrapi,
46
+ );
47
+
48
+ return createdEntry;
49
+ },
50
+
51
+ async updateEntry(
52
+ uid,
53
+ localizedEntryId,
54
+ strapiContentTypesModels,
55
+ translatedModel,
56
+ baseEntry,
57
+ isoStrapi,
58
+ ) {
59
+ // Strapi Service
60
+ const StrapiService = strapi
61
+ .plugin("localazy")
62
+ .service("strapiService");
63
+
64
+ // Strapi i18n Service
65
+ const StrapiI18nService = strapi
66
+ .plugin("localazy")
67
+ .service("strapiI18nService");
68
+
69
+ const populate = await StrapiService.getPopulateObject(uid);
70
+ const localizedEntry = await strapi.entityService.findOne(
71
+ uid,
72
+ localizedEntryId,
73
+ {
74
+ populate,
75
+ }
76
+ );
77
+
78
+ const fullyPopulatedLocalizedEntry = await strapi.entityService.findOne(
79
+ uid,
80
+ localizedEntryId,
81
+ {
82
+ populate: "deep",
83
+ }
84
+ );
85
+
86
+ const updateEntry = await parsedLocalazyEntryToUpdateEntry(
87
+ strapiContentTypesModels,
88
+ translatedModel,
89
+ fullyPopulatedLocalizedEntry,
90
+ localizedEntry,
91
+ baseEntry,
92
+ uid,
93
+ isoStrapi
94
+ );
95
+
96
+ const updatedEntry = await StrapiI18nService.updateLocalizationForAnExistingEntry(
97
+ uid,
98
+ localizedEntryId,
99
+ updateEntry
100
+ );
101
+
102
+ return updatedEntry;
103
+ }
104
+ });