@localazy/strapi-plugin 0.1.11-rc.0 → 0.1.11-rc.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.
Files changed (31) hide show
  1. package/admin/src/modules/plugin-settings/components/ContentTransferSetup/index.js +5 -0
  2. package/admin/src/modules/plugin-settings/components/Tree/index.js +21 -6
  3. package/admin/src/modules/plugin-settings/functions/build-content-transfer-setup-schema.js +1 -1
  4. package/admin/src/modules/plugin-settings/functions/has-model-changed.js +1 -1
  5. package/admin/src/modules/plugin-settings/locale/en.js +1 -1
  6. package/admin/src/modules/plugin-settings/utils/get-filtered-models-schemas.js +1 -7
  7. package/admin/src/modules/plugin-settings/utils/get-models-tree.js +19 -3
  8. package/package.json +4 -4
  9. package/server/controllers/localazy-transfer-controller.js +29 -8
  10. package/server/functions/should-set-downloaded-property.js +48 -3
  11. package/server/services/strapi-i18n-service.js +1 -1
  12. package/server/services/strapi-localazy-i18n-service.js +1 -1
  13. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-lesson-dz.js +392 -0
  14. package/server/tests/fixtures/parsed-localazy-entry-to-create-entry-sample-json-dz.js +4675 -0
  15. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-lesson-dz.js +309 -0
  16. package/server/tests/fixtures/populate-create-update-entry-with-base-entry-sample-json-dz.js +884 -0
  17. package/server/tests/fixtures/strapi-plugin-all-models.js +844 -37
  18. package/server/utils/__tests__/parsed-localazy-entry-to-create-entry.test.js +211 -62
  19. package/server/utils/__tests__/pick-entries.test.js +936 -56
  20. package/server/utils/__tests__/populate-create-update-entry-with-base-entry.test.js +287 -0
  21. package/server/utils/build-populate.js +5 -0
  22. package/server/utils/model-utils.js +5 -0
  23. package/server/utils/omit-deep.js +7 -0
  24. package/server/utils/parsed-localazy-entry-to-create-entry.js +58 -4
  25. package/server/utils/parsed-localazy-entry-to-update-entry.js +6 -1
  26. package/server/utils/pick-deep.js +22 -0
  27. package/server/utils/pick-entries.js +90 -5
  28. package/server/utils/populate-create-update-entry-with-base-entry.js +51 -3
  29. package/server/tests/fixtures/collection-flattened.js +0 -76
  30. package/server/tests/fixtures/restaurant-flattened.js +0 -46
  31. package/server/tests/fixtures/restaurants-pick-paths.js +0 -15
@@ -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,14 +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);
33
- const hasAllNullValue = Object.values(flattened).every(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);
34
44
 
35
- if (key === "__model__") {
45
+ const RESERVED_KEYS_TO_SKIP = ["__model__", "__component__"];
46
+
47
+ if (RESERVED_KEYS_TO_SKIP.includes(key)) {
36
48
  return false;
37
49
  }
38
50
  const passedKey = `${path}.${key}`;
@@ -51,7 +63,10 @@ function Tree(props) {
51
63
  indeterminate={hasTruthyValue && hasFalsyValue}
52
64
  onChange={() => onTreeItemClick(flattenedKeys, hasTruthyValue && !hasFalsyValue)}
53
65
  >
54
- {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>
55
70
  </Checkbox>)
56
71
  }
57
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
- import baseSupportedContentTypeFields from "../../@common/models/supported-content-type-fields";
2
-
3
- const SUPPORTED_CONTENT_TYPE_FIELDS = [
4
- ...baseSupportedContentTypeFields,
5
- "component",
6
- // "relation", // relation cannot be supported field type
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) {
@@ -28,9 +28,25 @@ const getModelsTree = (allModels, localizableModels = []) => {
28
28
  : isComponentAttributesObjectTranslatable
29
29
  ),
30
30
  };
31
- } else if (
32
- SUPPORTED_CONTENT_TYPE_FIELDS.includes(attributes[attribute].type)
33
- ) {
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)) {
34
50
  // field might not be localizable
35
51
  if (isComponentAttributes) {
36
52
  if (isComponentAttributesObjectTranslatable) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localazy/strapi-plugin",
3
- "version": "0.1.11-rc.0",
3
+ "version": "0.1.11-rc.2",
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",
@@ -17,6 +17,7 @@ const {
17
17
  const shouldSetDownloadedProperty = require("../functions/should-set-downloaded-property");
18
18
  const set = require("lodash/set");
19
19
  const isEmpty = require("lodash/isEmpty");
20
+ const omitDeep = require("../utils/omit-deep");
20
21
 
21
22
  module.exports = {
22
23
  async upload(ctx) {
@@ -86,7 +87,8 @@ module.exports = {
86
87
  }
87
88
 
88
89
  // get only enabled fields paths
89
- const pickPaths = getPickPaths(transferSetupModel[collectionName]);
90
+ const currentTransferSetupModel = transferSetupModel[collectionName];
91
+ const pickPaths = getPickPaths(currentTransferSetupModel);
90
92
  if (!pickPaths.length) {
91
93
  const message = `No fields for collection ${collectionName} transfer are enabled.`;
92
94
  messageReport.push(message);
@@ -97,11 +99,19 @@ module.exports = {
97
99
  (pickPath) => `${modelUid}.${pickPath}`
98
100
  );
99
101
 
100
- const populate = await StrapiService.getPopulateObject(modelUid);
101
-
102
102
  let entries = await strapi.entityService.findMany(modelUid, {
103
- populate,
103
+ populate: "deep",
104
104
  });
105
+ entries = omitDeep(entries, [
106
+ // "__component",
107
+ "locale",
108
+ "localizations",
109
+ "createdAt",
110
+ "createdBy",
111
+ "updatedAt",
112
+ "updatedBy",
113
+ "publishedAt",
114
+ ]);
105
115
 
106
116
  if (!entries) {
107
117
  strapi.log.info(`No entries found for model ${modelUid}`);
@@ -116,8 +126,8 @@ module.exports = {
116
126
  const flatten = flattenObject({
117
127
  [modelUid]: entry,
118
128
  });
119
- // get only enabled fields
120
- 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);
121
131
 
122
132
  flattenContent = {
123
133
  ...flattenContent,
@@ -301,10 +311,11 @@ module.exports = {
301
311
  );
302
312
  const localazyContent = {};
303
313
  for (const isoLocalazy of supportedLanguages) {
314
+ const isoStrapi = isoLocalazyToStrapi(isoLocalazy);
304
315
  const result = await LocalazyDownloadService.download({
305
316
  projectId: user.project.id,
306
317
  fileId: strapiFile.id,
307
- lang: isoLocalazy,
318
+ lang: isoStrapi,
308
319
  });
309
320
  if (!result.success) {
310
321
  messageReport.push(result.message);
@@ -340,11 +351,21 @@ module.exports = {
340
351
  );
341
352
 
342
353
  if (shouldSetDownloadedProperty(modelContentTransferSetup, parsedKey.rest)) {
354
+ const parsedKeyRestWithoutComponents = parsedKey.rest.map((segment) => {
355
+ const semicolonIndex = segment.indexOf(";");
356
+
357
+ if (semicolonIndex === -1) {
358
+ return segment;
359
+ }
360
+
361
+ return segment.substring(0, semicolonIndex);
362
+ });
363
+
343
364
  const setKey = [
344
365
  isoStrapi,
345
366
  parsedKey.uid,
346
367
  parsedKey.id,
347
- ...parsedKey.rest,
368
+ ...parsedKeyRestWithoutComponents,
348
369
  ];
349
370
 
350
371
  set(parsedLocalazyContent, setKey, value);
@@ -1,5 +1,31 @@
1
1
  const get = require("lodash/get");
2
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
+
3
29
  const shouldSetDownloadedProperty = (
4
30
  modelContentTransferSetup,
5
31
  parsedKeyRest,
@@ -8,9 +34,28 @@ const shouldSetDownloadedProperty = (
8
34
  return false;
9
35
  }
10
36
 
11
- const filteredParsedKeyRest = parsedKeyRest
12
- .filter((partialKey) => isNaN(parseInt(partialKey)));
13
- return !!get(modelContentTransferSetup, filteredParsedKeyRest);
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
+ }
14
59
  };
15
60
 
16
61
  module.exports = shouldSetDownloadedProperty;
@@ -39,7 +39,7 @@ module.exports = ({ strapi }) => ({
39
39
  }
40
40
  },
41
41
  parseLocalazyKey(key) {
42
- const split = key.split(/\.|\[|\]/);
42
+ const split = key.split(/\.(?![^[]*])|\[|\]/);
43
43
  const filteredSplit = split.filter((item) => item !== "");
44
44
 
45
45
  return {
@@ -20,7 +20,7 @@ module.exports = ({ strapi }) => ({
20
20
  .plugin("localazy")
21
21
  .service("strapiI18nService");
22
22
 
23
- const createEntry = parsedLocalazyEntryToCreateEntry(
23
+ const { createEntry } = parsedLocalazyEntryToCreateEntry(
24
24
  strapiContentTypesModels,
25
25
  translatedModel,
26
26
  baseEntry,