@localazy/strapi-plugin 0.1.10 → 0.1.11-rc.1

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 (59) hide show
  1. package/.eslintrc +6 -2
  2. package/admin/src/modules/@common/models/supported-content-type-fields.js +8 -0
  3. package/admin/src/modules/plugin-settings/components/ContentTransferSetup/index.js +5 -0
  4. package/admin/src/modules/plugin-settings/components/Tree/index.js +22 -5
  5. package/admin/src/modules/plugin-settings/functions/build-content-transfer-setup-schema.js +1 -1
  6. package/admin/src/modules/plugin-settings/functions/has-model-changed.js +1 -1
  7. package/admin/src/modules/plugin-settings/locale/en.js +1 -1
  8. package/admin/src/modules/plugin-settings/utils/get-filtered-models-schemas.js +1 -7
  9. package/admin/src/modules/plugin-settings/utils/get-models-tree.js +21 -3
  10. package/package.json +4 -4
  11. package/server/bootstrap.js +15 -1
  12. package/server/controllers/localazy-transfer-controller.js +67 -52
  13. package/server/functions/should-set-downloaded-property.js +61 -0
  14. package/server/models/supported-content-type-fields.js +8 -0
  15. package/server/services/index.js +2 -0
  16. package/server/services/strapi-i18n-service.js +5 -4
  17. package/server/services/strapi-localazy-i18n-service.js +104 -0
  18. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-cookbook.js +5761 -0
  19. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-lesson-dz.js +392 -0
  20. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-restaurant-simple-menu.js +536 -0
  21. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-sample-json-dz.js +4675 -0
  22. package/server/tests/fixtures/parsed-localazy-entry-to-update-entry.js +35157 -0
  23. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-cookbook-empty-recipes.js +202 -0
  24. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-cookbook.js +2700 -0
  25. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-lesson-dz.js +309 -0
  26. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-flat-simple.js +47 -0
  27. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-flat-with-media.js +169 -0
  28. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-menu-empty.js +3003 -0
  29. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-restaurant-simple-menu-with-media.js +2057 -0
  30. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-sample-json-dz.js +884 -0
  31. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-sample-json.js +46 -0
  32. package/server/tests/fixtures/strapi-plugin-all-models.js +2048 -0
  33. package/server/utils/__tests__/get-models-tree.test.js +1 -1
  34. package/server/utils/__tests__/parsed-localazy-entry-to-create-entry.test.js +237 -91
  35. package/server/utils/__tests__/parsed-localazy-entry-to-update-entry.test.js +417 -101
  36. package/server/utils/__tests__/pick-entries.test.js +936 -56
  37. package/server/utils/__tests__/populate-create-update-entry-with-base-entry.test.js +1139 -0
  38. package/server/utils/build-populate.js +5 -0
  39. package/server/utils/get-full-populate-object.js +56 -0
  40. package/server/utils/get-models-tree.js +3 -1
  41. package/server/utils/model-utils.js +43 -0
  42. package/server/utils/omit-deep.js +7 -0
  43. package/server/utils/parsed-localazy-entry-to-create-entry.js +58 -21
  44. package/server/utils/parsed-localazy-entry-to-update-entry.js +44 -4
  45. package/server/utils/pick-deep.js +22 -0
  46. package/server/utils/pick-entries.js +90 -5
  47. package/server/utils/populate-create-update-entry-with-base-entry.js +270 -0
  48. package/server/utils/transfer-setup-utils.js +14 -0
  49. package/server/tests/fixtures/all-models-with-multimedia.js +0 -1064
  50. package/server/tests/fixtures/collection-flattened.js +0 -76
  51. package/server/tests/fixtures/restaurant-flattened.js +0 -46
  52. package/server/tests/fixtures/restaurant-model.js +0 -230
  53. package/server/tests/fixtures/restaurants-entries.js +0 -152
  54. package/server/tests/fixtures/restaurants-pick-paths.js +0 -15
  55. package/server/tests/fixtures/strapi-book-with-multimedia-components-cs.js +0 -31
  56. package/server/tests/fixtures/stringified-book-cs.js +0 -3
  57. package/server/tests/fixtures/stringified-book-with-multimedia-components-cs.js +0 -3
  58. package/server/tests/fixtures/stringified-restaurant-cs.js +0 -3
  59. 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
  }
@@ -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;
@@ -111,6 +111,11 @@ function ContentTransferSetup() {
111
111
 
112
112
  const newState = cloneDeep(prevState);
113
113
  keys.forEach((key) => {
114
+ // * if there's a "__component__" in the key; skip
115
+ if (key.includes("__component__")) {
116
+ return;
117
+ }
118
+
114
119
  const isEditable = get(model, key) !== null;
115
120
 
116
121
  if (isEditable) {
@@ -1,8 +1,10 @@
1
1
  import React, { useState, useEffect } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import { Box } from "@strapi/design-system/Box";
4
+ import { Flex } from "@strapi/design-system/Flex";
4
5
  import { Switch } from '@strapi/design-system/Switch';
5
6
  import { Checkbox } from '@strapi/design-system/Checkbox';
7
+ import DynamicZone from '@strapi/icons/DynamicZone';
6
8
  import { Accordion, AccordionToggle, AccordionContent } from '@strapi/design-system/Accordion';
7
9
  import TreeItem from "../TreeItem";
8
10
  import flattenObject from "../../../@common/utils/functions/flatten-deep";
@@ -25,13 +27,24 @@ function Tree(props) {
25
27
  <>
26
28
  {Object.entries(branch).map(([key, value]) => {
27
29
  const isSubbranchObject = typeof value === "object" && value !== null;
28
- const flattened = flattenObject(value);
30
+ let flattened = flattenObject(value)
31
+ flattened = Object.fromEntries(Object.entries(flattened).filter(([key]) => !key.includes("__component__")));
29
32
  const flattenedKeys = Object.keys(flattened).map((k) => `${path}.${key}.${k}`);
30
33
 
31
- const hasTruthyValue = Object.values(flattened).some(v => v);
32
- const hasFalsyValue = Object.values(flattened).some(v => !v && v !== null);
34
+ // debugger;
35
+ const hasTruthyValue = Object
36
+ .values(flattened)
37
+ .some(v => v);
38
+ const hasFalsyValue = Object
39
+ .values(flattened)
40
+ .some(v => !v && v !== null);
41
+ const hasAllNullValue = Object
42
+ .values(flattened)
43
+ .every(v => v === null);
33
44
 
34
- if (key === "__model__") {
45
+ const RESERVED_KEYS_TO_SKIP = ["__model__", "__component__"];
46
+
47
+ if (RESERVED_KEYS_TO_SKIP.includes(key)) {
35
48
  return false;
36
49
  }
37
50
  const passedKey = `${path}.${key}`;
@@ -45,11 +58,15 @@ function Tree(props) {
45
58
  >
46
59
  {isSubbranchObject && (
47
60
  <Checkbox
61
+ disabled={hasAllNullValue}
48
62
  checked={hasTruthyValue && !hasFalsyValue}
49
63
  indeterminate={hasTruthyValue && hasFalsyValue}
50
64
  onChange={() => onTreeItemClick(flattenedKeys, hasTruthyValue && !hasFalsyValue)}
51
65
  >
52
- {key || "-"}
66
+ <Flex alignItems="center">
67
+ {!!value?.__component__ && (<Flex alignItems="center" marginRight={2}><DynamicZone width="1rem" height="1rem" /></Flex>)}
68
+ {value?.__component__ || key || "-"}
69
+ </Flex>
53
70
  </Checkbox>)
54
71
  }
55
72
  <TreeItem
@@ -1,6 +1,6 @@
1
1
  import set from "lodash-es/set";
2
2
  import get from "lodash-es/get";
3
- import deepKeys from "deep-keys";
3
+ import deepKeys from "@david-vaclavek/deep-keys";
4
4
  import sortByModelName from "../../@common/utils/sort-by-model-name";
5
5
  import arrayOfModelsToObject from "../utils/array-of-models-to-object";
6
6
  import findModelValueByKey from "../utils/find-model-value-by-key";
@@ -1,4 +1,4 @@
1
- import deepKeys from "deep-keys";
1
+ import deepKeys from "@david-vaclavek/deep-keys";
2
2
  import get from "lodash-es/get";
3
3
  import PluginSettingsService from "../services/plugin-settings-service";
4
4
  import StrapiModelService from "../services/strapi-model-service";
@@ -1,7 +1,7 @@
1
1
  export default {
2
2
  content_transfer_setup: "Content Transfer Setup",
3
3
  content_transfer_setup_description:
4
- "Setup what content type fields will be uploaded to Localazy",
4
+ "Select which content type fields will be uploaded to Localazy",
5
5
  save: "Save",
6
6
  cancel: "Cancel",
7
7
  close: "Close",
@@ -1,10 +1,4 @@
1
- const SUPPORTED_CONTENT_TYPE_FIELDS = [
2
- "string",
3
- "text",
4
- "richtext",
5
- // "relation", // relation cannot be supported field type
6
- "component",
7
- ];
1
+ import SUPPORTED_CONTENT_TYPE_FIELDS from "../../@common/models/supported-content-type-fields";
8
2
 
9
3
  export default (models) => {
10
4
  if (!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
  */
@@ -26,9 +28,25 @@ const getModelsTree = (allModels, localizableModels = []) => {
26
28
  : isComponentAttributesObjectTranslatable
27
29
  ),
28
30
  };
29
- } else if (
30
- ["string", "text", "richtext"].includes(attributes[attribute].type)
31
- ) {
31
+ } else if (attributes[attribute].type === "dynamiczone") {
32
+ const components = attributes[attribute].components;
33
+ currentModelTree[attribute] = [];
34
+ components.forEach((c) => {
35
+ const nestedModel = allModels.find((model) => model.uid === c);
36
+
37
+ const modelTree = getModelTree(
38
+ nestedModel.__schema__.attributes,
39
+ true,
40
+ isComponentAttributesObjectTranslatable === null
41
+ ? attributes[attribute].pluginOptions?.i18n?.localized || false
42
+ : isComponentAttributesObjectTranslatable
43
+ );
44
+ currentModelTree[attribute].push({
45
+ "__component__": c,
46
+ ...modelTree,
47
+ });
48
+ });
49
+ } else if (SUPPORTED_CONTENT_TYPE_FIELDS.includes(attributes[attribute].type)) {
32
50
  // field might not be localizable
33
51
  if (isComponentAttributes) {
34
52
  if (isComponentAttributesObjectTranslatable) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localazy/strapi-plugin",
3
- "version": "0.1.10",
3
+ "version": "0.1.11-rc.1",
4
4
  "description": "The official Strapi Plugin by Localazy.",
5
5
  "strapi": {
6
6
  "name": "localazy",
@@ -27,8 +27,8 @@
27
27
  "test:watch": "jest --watch --config ./jest.config.js"
28
28
  },
29
29
  "dependencies": {
30
+ "@david-vaclavek/deep-keys": "^0.5.0",
30
31
  "@localazy/ts-api": "^1.0.6",
31
- "deep-keys": "^0.5.0",
32
32
  "i18next": "^21.6.13",
33
33
  "isomorphic-fetch": "^3.0.0",
34
34
  "js-cookie": "^3.0.1",
@@ -39,9 +39,9 @@
39
39
  "styled-components": "^5.3.3"
40
40
  },
41
41
  "peerDependencies": {
42
- "@strapi/strapi": "^4.0.0",
43
42
  "@strapi/design-system": "^1.0.0",
44
- "@strapi/icons": "^1.0.0"
43
+ "@strapi/icons": "^1.0.0",
44
+ "@strapi/strapi": "^4.0.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@babel/plugin-transform-modules-commonjs": "^7.17.7",
@@ -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,11 +14,10 @@ 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");
20
19
  const isEmpty = require("lodash/isEmpty");
20
+ const omitDeep = require("../utils/omit-deep");
21
21
 
22
22
  module.exports = {
23
23
  async upload(ctx) {
@@ -87,7 +87,8 @@ module.exports = {
87
87
  }
88
88
 
89
89
  // get only enabled fields paths
90
- const pickPaths = getPickPaths(transferSetupModel[collectionName]);
90
+ const currentTransferSetupModel = transferSetupModel[collectionName];
91
+ const pickPaths = getPickPaths(currentTransferSetupModel);
91
92
  if (!pickPaths.length) {
92
93
  const message = `No fields for collection ${collectionName} transfer are enabled.`;
93
94
  messageReport.push(message);
@@ -98,11 +99,19 @@ module.exports = {
98
99
  (pickPath) => `${modelUid}.${pickPath}`
99
100
  );
100
101
 
101
- const populate = await StrapiService.getPopulateObject(modelUid);
102
-
103
102
  let entries = await strapi.entityService.findMany(modelUid, {
104
- populate,
103
+ populate: "deep",
105
104
  });
105
+ entries = omitDeep(entries, [
106
+ // "__component",
107
+ "locale",
108
+ "localizations",
109
+ "createdAt",
110
+ "createdBy",
111
+ "updatedAt",
112
+ "updatedBy",
113
+ "publishedAt",
114
+ ]);
106
115
 
107
116
  if (!entries) {
108
117
  strapi.log.info(`No entries found for model ${modelUid}`);
@@ -117,8 +126,8 @@ module.exports = {
117
126
  const flatten = flattenObject({
118
127
  [modelUid]: entry,
119
128
  });
120
- // get only enabled fields
121
- const pickedFlatten = pickEntries(flatten, pickPathsWithUid);
129
+ // get only enabled fields; "__component" will be filtered out inside of the function
130
+ const pickedFlatten = pickEntries(flatten, pickPathsWithUid, currentTransferSetupModel);
122
131
 
123
132
  flattenContent = {
124
133
  ...flattenContent,
@@ -160,7 +169,9 @@ module.exports = {
160
169
  const messageReport = [];
161
170
 
162
171
  // Strapi service
163
- const StrapiService = strapi.plugin("localazy").service("strapiService");
172
+ const StrapiService = strapi
173
+ .plugin("localazy")
174
+ .service("strapiService");
164
175
 
165
176
  // Strapi i18n Service
166
177
  const StrapiI18nService = strapi
@@ -176,6 +187,14 @@ module.exports = {
176
187
  const LocalazyDownloadService = strapi
177
188
  .plugin("localazy")
178
189
  .service("localazyDownloadService");
190
+ const strapiLocalazyI18nService = strapi
191
+ .plugin("localazy")
192
+ .service("strapiLocalazyI18nService");
193
+
194
+ const contentTransferSetup = await strapi
195
+ .plugin("localazy")
196
+ .service("pluginSettingsService")
197
+ .getContentTransferSetup();
179
198
 
180
199
  const user = await LocalazyUserService.getUser();
181
200
 
@@ -308,6 +327,7 @@ module.exports = {
308
327
  * Parse Localazy content
309
328
  */
310
329
  const parsedLocalazyContent = {};
330
+ const strapiContentTypesModels = await StrapiService.getModels();
311
331
  for (const [isoLocalazy, keys] of Object.entries(localazyContent)) {
312
332
  const isoStrapi = isoLocalazyToStrapi(isoLocalazy);
313
333
  if (!isoStrapi) {
@@ -322,21 +342,39 @@ module.exports = {
322
342
  const value = localazyEntry.value;
323
343
 
324
344
  const parsedKey = StrapiI18nService.parseLocalazyKey(key);
325
- const setKey = [
326
- isoStrapi,
327
- parsedKey.uid,
328
- parsedKey.id,
329
- ...parsedKey.rest,
330
- ];
331
-
332
- set(parsedLocalazyContent, setKey, value);
345
+
346
+ const modelContentTransferSetup = findSetupModelByCollectionUid(
347
+ contentTransferSetup,
348
+ strapiContentTypesModels,
349
+ parsedKey.uid
350
+ );
351
+
352
+ if (shouldSetDownloadedProperty(modelContentTransferSetup, parsedKey.rest)) {
353
+ const parsedKeyRestWithoutComponents = parsedKey.rest.map((segment) => {
354
+ const semicolonIndex = segment.indexOf(";");
355
+
356
+ if (semicolonIndex === -1) {
357
+ return segment;
358
+ }
359
+
360
+ return segment.substring(0, semicolonIndex);
361
+ });
362
+
363
+ const setKey = [
364
+ isoStrapi,
365
+ parsedKey.uid,
366
+ parsedKey.id,
367
+ ...parsedKeyRestWithoutComponents,
368
+ ];
369
+
370
+ set(parsedLocalazyContent, setKey, value);
371
+ }
333
372
  }
334
373
  }
335
374
 
336
375
  /**
337
376
  * Iterate over parsed Localazy content and insert/update content in Strapi
338
377
  */
339
- const strapiContentTypesModels = await StrapiService.getModels();
340
378
  for (const [isoStrapi, contentTypes] of Object.entries(
341
379
  parsedLocalazyContent
342
380
  )) {
@@ -359,14 +397,9 @@ module.exports = {
359
397
  /**
360
398
  * Get original source language entry
361
399
  */
362
- const populate = await StrapiService.getPopulateObject(uid);
363
- const baseEntryDeep = await strapi.entityService.findOne(uid, id, {
364
- populate,
365
- });
366
- let baseEntry = await strapi.entityService.findOne(uid, id, {
367
- populate: "*",
400
+ const baseEntry = await strapi.entityService.findOne(uid, id, {
401
+ populate: "deep",
368
402
  });
369
- baseEntry = merge(baseEntry, baseEntryDeep);
370
403
 
371
404
  if (isEmpty(baseEntry)) {
372
405
  const message = `Source language entry ${uid}[${id}] does not exist anymore, skipping...`;
@@ -392,20 +425,15 @@ module.exports = {
392
425
  if (!baseEntryCurrentLanguageLocalizationInfo) {
393
426
  // create new entry
394
427
  try {
395
- const createEntry = parsedLocalazyEntryToCreateEntry(
428
+ const createdEntry = await strapiLocalazyI18nService.createEntry(
429
+ ctx,
430
+ uid,
396
431
  strapiContentTypesModels,
397
432
  translatedModel,
398
433
  baseEntry,
399
- uid,
400
- isoStrapi
434
+ isoStrapi,
401
435
  );
402
- const createdEntry =
403
- await StrapiI18nService.createLocalizationForAnExistingEntry(
404
- ctx,
405
- uid,
406
- baseEntry,
407
- createEntry
408
- );
436
+
409
437
  messageReport.push(
410
438
  `Created new entry ${uid}[${createdEntry.id}] in language ${isoStrapi}`
411
439
  );
@@ -421,29 +449,16 @@ module.exports = {
421
449
  try {
422
450
  const localizedEntryId =
423
451
  baseEntryCurrentLanguageLocalizationInfo.id;
424
- const populate = await StrapiService.getPopulateObject(uid);
425
- const localizedEntry = await strapi.entityService.findOne(
452
+
453
+ const updatedEntry = await strapiLocalazyI18nService.updateEntry(
426
454
  uid,
427
455
  localizedEntryId,
428
- {
429
- populate,
430
- }
431
- );
432
-
433
- const updateEntry = parsedLocalazyEntryToUpdateEntry(
434
456
  strapiContentTypesModels,
435
457
  translatedModel,
436
- localizedEntry,
437
458
  baseEntry,
438
- uid
459
+ isoStrapi,
439
460
  );
440
461
 
441
- const updatedEntry =
442
- await StrapiI18nService.updateLocalizationForAnExistingEntry(
443
- uid,
444
- localizedEntryId,
445
- updateEntry
446
- );
447
462
  messageReport.push(
448
463
  `Updated ${uid}[${updatedEntry.id}] (${isoStrapi})`
449
464
  );
@@ -0,0 +1,61 @@
1
+ const get = require("lodash/get");
2
+
3
+ const getDynamicZoneKeySegment = (parsedKey) => {
4
+ return parsedKey.find((segment) => segment.includes(";"));
5
+ };
6
+
7
+ const isDynamicZone = (parsedKey) => {
8
+ return !!getDynamicZoneKeySegment(parsedKey);
9
+ };
10
+
11
+ const getComponentNameFromDynamicZoneKeySegment = (dynamicZoneKeySegment) => {
12
+ return dynamicZoneKeySegment.split(";")[1];
13
+ };
14
+
15
+ const getDynamicZoneKeySegmentIndex = (parsedKey) => {
16
+ return parsedKey.findIndex((segment) => segment.includes(";"));
17
+ }
18
+
19
+ const getDynamicZonePropertyName = (parsedKey) => {
20
+ const dynamicZoneKeySegmentIndex = getDynamicZoneKeySegmentIndex(parsedKey);
21
+
22
+ if (dynamicZoneKeySegmentIndex === -1) {
23
+ return undefined;
24
+ }
25
+
26
+ return parsedKey[dynamicZoneKeySegmentIndex - 1];
27
+ };
28
+
29
+ const shouldSetDownloadedProperty = (
30
+ modelContentTransferSetup,
31
+ parsedKeyRest,
32
+ ) => {
33
+ if (!modelContentTransferSetup.__model__) {
34
+ return false;
35
+ }
36
+
37
+ const dynamicZoneKeySegment = getDynamicZoneKeySegment(parsedKeyRest);
38
+ if (!!dynamicZoneKeySegment) {
39
+ const dynamicZonePropertyName = getDynamicZonePropertyName(parsedKeyRest);
40
+ const componentName = getComponentNameFromDynamicZoneKeySegment(dynamicZoneKeySegment);
41
+
42
+ const dzContentTransferSetupModel = get(modelContentTransferSetup, dynamicZonePropertyName);
43
+ const dzContentTransferSetupComponentModel = dzContentTransferSetupModel.find((c) => c.__component__ === componentName);
44
+
45
+ if (!dzContentTransferSetupComponentModel) {
46
+ return false;
47
+ }
48
+
49
+ const dynamicZoneKeySegmentIndex = getDynamicZoneKeySegmentIndex(parsedKeyRest);
50
+ const slicedParsedKeyRest = parsedKeyRest.slice(dynamicZoneKeySegmentIndex + 1);
51
+ const filteredSlicedParsedKeyRest = slicedParsedKeyRest.filter((segment) => isNaN(parseInt(segment)));
52
+
53
+ return !!get(dzContentTransferSetupComponentModel, filteredSlicedParsedKeyRest);
54
+ } else {
55
+ const filteredParsedKeyRest = parsedKeyRest
56
+ .filter((partialKey) => isNaN(parseInt(partialKey)));
57
+ return !!get(modelContentTransferSetup, filteredParsedKeyRest);
58
+ }
59
+ };
60
+
61
+ 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 }) => ({
@@ -38,7 +39,7 @@ module.exports = ({ strapi }) => ({
38
39
  }
39
40
  },
40
41
  parseLocalazyKey(key) {
41
- const split = key.split(/\.|\[|\]/);
42
+ const split = key.split(/\.(?![^[]*])|\[|\]/);
42
43
  const filteredSplit = split.filter((item) => item !== "");
43
44
 
44
45
  return {
@@ -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
+ });