@localazy/strapi-plugin 0.1.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.
- package/.babelrc +7 -0
- package/.eslintrc +7 -0
- package/.github/workflows/.build.yml +39 -0
- package/.nvmrc +1 -0
- package/LICENSE +21 -0
- package/README.md +40 -0
- package/admin/src/.eslintrc +3 -0
- package/admin/src/components/Initializer/index.js +26 -0
- package/admin/src/components/PluginIcon/index.js +14 -0
- package/admin/src/i18n.js +37 -0
- package/admin/src/index.js +106 -0
- package/admin/src/modules/@common/components/Icons/Localazy/index.js +12 -0
- package/admin/src/modules/@common/components/SideNav/index.js +46 -0
- package/admin/src/modules/@common/components/TransferReport/index.js +54 -0
- package/admin/src/modules/@common/locale/en.js +13 -0
- package/admin/src/modules/@common/services/i18n-service.js +15 -0
- package/admin/src/modules/@common/services/project-service.js +15 -0
- package/admin/src/modules/@common/services/user-service.js +38 -0
- package/admin/src/modules/@common/utils/are-locales-compatible.js +42 -0
- package/admin/src/modules/@common/utils/functions/flatten-deep.js +23 -0
- package/admin/src/modules/@common/utils/get-default-locale.js +32 -0
- package/admin/src/modules/@common/utils/get-header-subtitle.js +21 -0
- package/admin/src/modules/@common/utils/get-header-title.js +24 -0
- package/admin/src/modules/@common/utils/get-nav.js +35 -0
- package/admin/src/modules/@common/utils/history.js +6 -0
- package/admin/src/modules/@common/utils/is-plugin-route.js +15 -0
- package/admin/src/modules/@common/utils/iso-locales-utils.js +15 -0
- package/admin/src/modules/@common/utils/redirect-to-plugin-route.js +22 -0
- package/admin/src/modules/@common/utils/sort-by-model-name.js +10 -0
- package/admin/src/modules/localazy-download/locale/en.js +20 -0
- package/admin/src/modules/localazy-download/services/localazy-download-service.js +16 -0
- package/admin/src/modules/localazy-upload/components/ReadDocsButton.js +21 -0
- package/admin/src/modules/localazy-upload/locale/en.js +18 -0
- package/admin/src/modules/localazy-upload/services/localazy-upload-service.js +16 -0
- package/admin/src/modules/login/components/LoginButton/index.js +56 -0
- package/admin/src/modules/login/components/LogoutButton/index.js +50 -0
- package/admin/src/modules/login/locale/en.js +7 -0
- package/admin/src/modules/login/services/localazy-login-service.js +29 -0
- package/admin/src/modules/plugin-settings/components/ContentTransferSetup/index.js +292 -0
- package/admin/src/modules/plugin-settings/components/Tree/index.js +120 -0
- package/admin/src/modules/plugin-settings/components/TreeItem/index.js +48 -0
- package/admin/src/modules/plugin-settings/functions/build-content-transfer-setup-schema.js +71 -0
- package/admin/src/modules/plugin-settings/functions/has-model-changed.js +85 -0
- package/admin/src/modules/plugin-settings/locale/en.js +19 -0
- package/admin/src/modules/plugin-settings/services/plugin-settings-service.js +32 -0
- package/admin/src/modules/plugin-settings/services/strapi-model-service.js +26 -0
- package/admin/src/modules/plugin-settings/utils/__tests__/get-models-tree.test.js +135 -0
- package/admin/src/modules/plugin-settings/utils/array-of-models-to-object.js +6 -0
- package/admin/src/modules/plugin-settings/utils/find-model-value-by-key.js +8 -0
- package/admin/src/modules/plugin-settings/utils/get-filtered-models-schemas.js +34 -0
- package/admin/src/modules/plugin-settings/utils/get-models-tree.js +73 -0
- package/admin/src/modules/settings/components/OverviewItem/index.js +44 -0
- package/admin/src/modules/settings/components/OverviewItemLink/index.js +34 -0
- package/admin/src/modules/settings/components/PrerequisitiesInfo/index.js +30 -0
- package/admin/src/modules/settings/locale/en.js +13 -0
- package/admin/src/modules/user/model/localazy-identity.js +14 -0
- package/admin/src/modules/user/services/localazy-user-service.js +38 -0
- package/admin/src/pages/App/index.js +152 -0
- package/admin/src/pages/Download/index.js +179 -0
- package/admin/src/pages/Index/index.js +8 -0
- package/admin/src/pages/Login/index.js +94 -0
- package/admin/src/pages/PluginSettings/index.js +42 -0
- package/admin/src/pages/Settings/index.js +120 -0
- package/admin/src/pages/Upload/index.js +187 -0
- package/admin/src/pluginId.js +5 -0
- package/admin/src/plugins/apolloClient.js +33 -0
- package/admin/src/state/localazy-identity.js +29 -0
- package/admin/src/tests/fixtures/all-models.js +877 -0
- package/admin/src/tests/fixtures/restaurant-model.js +230 -0
- package/admin/src/translations/en.json +4 -0
- package/admin/src/translations/fr.json +1 -0
- package/admin/src/utils/createAxiosInstance.js +52 -0
- package/admin/src/utils/getTrad.js +5 -0
- package/jest.config.js +0 -0
- package/package.json +60 -0
- package/server/bootstrap.js +5 -0
- package/server/config/development/index.js +15 -0
- package/server/config/example/index.js +15 -0
- package/server/config/index.js +15 -0
- package/server/config/production/index.js +16 -0
- package/server/config/schema.graphql.js +21 -0
- package/server/content-types/index.js +3 -0
- package/server/controllers/index.js +19 -0
- package/server/controllers/localazy-auth-controller.js +46 -0
- package/server/controllers/localazy-project-controller.js +21 -0
- package/server/controllers/localazy-transfer-controller.js +469 -0
- package/server/controllers/localazy-user-controller.js +24 -0
- package/server/controllers/my-controller.js +10 -0
- package/server/controllers/plugin-settings-controller.js +17 -0
- package/server/controllers/strapi-controller.js +16 -0
- package/server/db/model/content-transfer-setup.js +13 -0
- package/server/db/model/localazy-user.js +23 -0
- package/server/db/model/utils/get-strapi-store.js +9 -0
- package/server/destroy.js +5 -0
- package/server/index.js +25 -0
- package/server/middlewares/index.js +3 -0
- package/server/policies/index.js +3 -0
- package/server/register.js +5 -0
- package/server/routes/index.js +26 -0
- package/server/routes/localazy-auth.js +22 -0
- package/server/routes/localazy-project.js +14 -0
- package/server/routes/localazy-transfer.js +22 -0
- package/server/routes/localazy-user.js +30 -0
- package/server/routes/plugin-settings.js +22 -0
- package/server/routes/strapi.js +22 -0
- package/server/services/index.js +21 -0
- package/server/services/localazy-auth-service.js +38 -0
- package/server/services/localazy-download-service.js +54 -0
- package/server/services/localazy-pubapi-service.js +47 -0
- package/server/services/localazy-upload-service.js +95 -0
- package/server/services/localazy-user-service.js +29 -0
- package/server/services/plugin-settings-service.js +30 -0
- package/server/services/strapi-i18n-service.js +132 -0
- package/server/services/strapi-service.js +23 -0
- package/server/tests/fixtures/all-models-with-multimedia.js +1064 -0
- package/server/tests/fixtures/all-models.js +869 -0
- package/server/tests/fixtures/collection-flattened.js +76 -0
- package/server/tests/fixtures/restaurant-flattened.js +46 -0
- package/server/tests/fixtures/restaurant-model.js +230 -0
- package/server/tests/fixtures/restaurants-entries.js +152 -0
- package/server/tests/fixtures/restaurants-pick-paths.js +15 -0
- package/server/tests/fixtures/strapi-book-with-multimedia-components-cs.js +31 -0
- package/server/tests/fixtures/stringified-book-cs.js +3 -0
- package/server/tests/fixtures/stringified-book-with-multimedia-components-cs.js +3 -0
- package/server/tests/fixtures/stringified-restaurant-cs.js +3 -0
- package/server/tests/fixtures/stringified-restaurant-de.js +5 -0
- package/server/utils/__tests__/build-populate.test.js +85 -0
- package/server/utils/__tests__/flatten-object.test.js +171 -0
- package/server/utils/__tests__/get-models-tree.test.js +170 -0
- package/server/utils/__tests__/parsed-localazy-entry-to-create-entry.test.js +153 -0
- package/server/utils/__tests__/parsed-localazy-entry-to-update-entry.test.js +172 -0
- package/server/utils/__tests__/pick-entries.test.js +83 -0
- package/server/utils/build-populate.js +43 -0
- package/server/utils/delay.js +6 -0
- package/server/utils/flatten-object.js +52 -0
- package/server/utils/get-localazy-api.js +22 -0
- package/server/utils/get-main-keys-of-nested-array-objects.js +5 -0
- package/server/utils/get-models-tree.js +43 -0
- package/server/utils/intl-display-name.js +7 -0
- package/server/utils/is-generally-applicable-content-type.js +33 -0
- package/server/utils/is-localazy-applicable-content-type.js +36 -0
- package/server/utils/iso-locales-utils.js +22 -0
- package/server/utils/objectivise-entry.js +41 -0
- package/server/utils/omit-deep.js +17 -0
- package/server/utils/parsed-localazy-entry-to-create-entry.js +115 -0
- package/server/utils/parsed-localazy-entry-to-update-entry.js +31 -0
- package/server/utils/pick-entries.js +14 -0
- package/server/utils/transfer-setup-utils.js +39 -0
- package/strapi-admin.js +14 -0
- package/strapi-server.js +5 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const pickEntries = require("../pick-entries");
|
|
4
|
+
const restaurantFlattened = require("../../tests/fixtures/restaurant-flattened");
|
|
5
|
+
const collectionFlattened = require("../../tests/fixtures/collection-flattened");
|
|
6
|
+
const restaurantsPickPaths = require("../../tests/fixtures/restaurants-pick-paths");
|
|
7
|
+
|
|
8
|
+
describe("pick entries test suite", () => {
|
|
9
|
+
it("should return picked entries from 1 restaurant", () => {
|
|
10
|
+
// SETUP
|
|
11
|
+
const entry = restaurantFlattened;
|
|
12
|
+
const pickPaths = [
|
|
13
|
+
"api::restaurant.restaurant.title",
|
|
14
|
+
"api::restaurant.restaurant.description",
|
|
15
|
+
"api::restaurant.restaurant.street",
|
|
16
|
+
"api::restaurant.restaurant.city",
|
|
17
|
+
"api::restaurant.restaurant.country",
|
|
18
|
+
"api::restaurant.restaurant.id",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// EXECUTE
|
|
22
|
+
const result = pickEntries(entry, pickPaths);
|
|
23
|
+
|
|
24
|
+
// VERIFY
|
|
25
|
+
const expected = {
|
|
26
|
+
"api::restaurant.restaurant[3].city": "Testow",
|
|
27
|
+
"api::restaurant.restaurant[3].country": "Test Rep.",
|
|
28
|
+
"api::restaurant.restaurant[3].description":
|
|
29
|
+
"With some great description",
|
|
30
|
+
"api::restaurant.restaurant[3].street": "Testowa",
|
|
31
|
+
"api::restaurant.restaurant[3].title": "Full Restaurant",
|
|
32
|
+
};
|
|
33
|
+
expect(result).toEqual(expected);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should return picked entries from collection", () => {
|
|
37
|
+
// SETUP
|
|
38
|
+
const entry = collectionFlattened;
|
|
39
|
+
const pickPaths = restaurantsPickPaths("api::restaurant.restaurant");
|
|
40
|
+
|
|
41
|
+
// EXECUTE
|
|
42
|
+
const result = pickEntries(entry, pickPaths);
|
|
43
|
+
|
|
44
|
+
// VERIFY
|
|
45
|
+
const expected = {
|
|
46
|
+
"api::restaurant.restaurant[1].description": "Restaurant 1 description",
|
|
47
|
+
"api::restaurant.restaurant[1].descs[1].rich_description":
|
|
48
|
+
"restaurant 1 rich_desc",
|
|
49
|
+
"api::restaurant.restaurant[1].title": "Restaurant 1",
|
|
50
|
+
"api::restaurant.restaurant[2].description": "Restaurant 2 description",
|
|
51
|
+
"api::restaurant.restaurant[2].title": "Restaurant 2",
|
|
52
|
+
"api::restaurant.restaurant[3].city": "Testow",
|
|
53
|
+
"api::restaurant.restaurant[3].country": "Test Rep.",
|
|
54
|
+
"api::restaurant.restaurant[3].description":
|
|
55
|
+
"With some great description",
|
|
56
|
+
"api::restaurant.restaurant[3].descs[3].excerpt": "Est. 2022",
|
|
57
|
+
"api::restaurant.restaurant[3].descs[3].history":
|
|
58
|
+
"Est. 2022, based in NY, NY",
|
|
59
|
+
"api::restaurant.restaurant[3].descs[3].rich_description":
|
|
60
|
+
"Another restaurant desc",
|
|
61
|
+
"api::restaurant.restaurant[3].descs[3].test_variants[5].name":
|
|
62
|
+
"no such thing...",
|
|
63
|
+
"api::restaurant.restaurant[3].recipes[2].ingredients[4].name": "Beef",
|
|
64
|
+
"api::restaurant.restaurant[3].recipes[2].ingredients[5].name": "Water",
|
|
65
|
+
"api::restaurant.restaurant[3].recipes[2].name": "Beef Broth",
|
|
66
|
+
"api::restaurant.restaurant[3].recipes[3].ingredients[2].name": "Tomato",
|
|
67
|
+
"api::restaurant.restaurant[3].recipes[3].ingredients[3].name": "Soup",
|
|
68
|
+
"api::restaurant.restaurant[3].recipes[3].name": "Tomato Soup",
|
|
69
|
+
"api::restaurant.restaurant[3].recipes[3].variants[4].name":
|
|
70
|
+
"Red, yellow, green",
|
|
71
|
+
"api::restaurant.restaurant[3].recipes[4].ingredients[6].name":
|
|
72
|
+
"Beef meat",
|
|
73
|
+
"api::restaurant.restaurant[3].recipes[4].ingredients[7].name": "Pepper",
|
|
74
|
+
"api::restaurant.restaurant[3].recipes[4].ingredients[8].name":
|
|
75
|
+
"Pepper spices",
|
|
76
|
+
"api::restaurant.restaurant[3].recipes[4].ingredients[9].name": "Water",
|
|
77
|
+
"api::restaurant.restaurant[3].recipes[4].name": "Goulash",
|
|
78
|
+
"api::restaurant.restaurant[3].street": "Testowa",
|
|
79
|
+
"api::restaurant.restaurant[3].title": "Full Restaurant",
|
|
80
|
+
};
|
|
81
|
+
expect(result).toEqual(expected);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const set = require("lodash/set");
|
|
4
|
+
|
|
5
|
+
const getPopulateObject = (keys) => {
|
|
6
|
+
const populate = {};
|
|
7
|
+
for (const key of keys) {
|
|
8
|
+
set(populate, key, "*");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return populate;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const buildPopulate = (models, modelUid) => {
|
|
15
|
+
const buildPopulateStep = (models, modelUid, prefix = "") => {
|
|
16
|
+
const model = models.find((model) => model.uid === modelUid);
|
|
17
|
+
|
|
18
|
+
if (!model || !model.attributes) {
|
|
19
|
+
return getPopulateObject(keys);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (const [attributeName, attribute] of Object.entries(model.attributes)) {
|
|
23
|
+
if (attribute.type === "component") {
|
|
24
|
+
const key = prefix
|
|
25
|
+
? `${prefix}.${attributeName}.populate`
|
|
26
|
+
: `${attributeName}.populate`;
|
|
27
|
+
keys.push(key);
|
|
28
|
+
const newPrefix = prefix
|
|
29
|
+
? `${prefix}.${attributeName}`
|
|
30
|
+
: `${attributeName}`;
|
|
31
|
+
const innerModelUid = attribute.component;
|
|
32
|
+
buildPopulateStep(models, innerModelUid, newPrefix);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return getPopulateObject(keys);
|
|
37
|
+
};
|
|
38
|
+
const keys = ["populate"];
|
|
39
|
+
|
|
40
|
+
return buildPopulateStep(models, modelUid);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
module.exports = buildPopulate;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const flattenObject = (object, prefix = "") => {
|
|
4
|
+
const result = {};
|
|
5
|
+
|
|
6
|
+
for (const objectKey in object) {
|
|
7
|
+
if (objectKey === "id") {
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (typeof object[objectKey] !== "object") {
|
|
12
|
+
const key = prefix ? `${prefix}.${objectKey}` : objectKey;
|
|
13
|
+
// Simple leaf (e.g. string or number)
|
|
14
|
+
result[key] = object[objectKey];
|
|
15
|
+
} else {
|
|
16
|
+
// Recursive call down to flattened object
|
|
17
|
+
let flatObject;
|
|
18
|
+
|
|
19
|
+
// If it is an array then turn it into an object with the correct keys
|
|
20
|
+
if (Array.isArray(object[objectKey])) {
|
|
21
|
+
// Reduce each item into the right key
|
|
22
|
+
const flattenedArray = object[objectKey].reduce(
|
|
23
|
+
(accumulator, item, index) => {
|
|
24
|
+
// No id should use the index of the array item
|
|
25
|
+
accumulator[`${objectKey}[${item.id || index}]`] =
|
|
26
|
+
flattenObject(item);
|
|
27
|
+
return accumulator;
|
|
28
|
+
},
|
|
29
|
+
{}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Then flatten it
|
|
33
|
+
flatObject = flattenObject(flattenedArray);
|
|
34
|
+
} else {
|
|
35
|
+
// Otherwise it is a complex object so you want to flatten that
|
|
36
|
+
// but with the prefix of this current object key
|
|
37
|
+
const suffix = object[objectKey]?.id
|
|
38
|
+
? `${objectKey}[${object[objectKey].id}]`
|
|
39
|
+
: objectKey;
|
|
40
|
+
flatObject = flattenObject(object[objectKey], suffix);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const flatObjectKey in flatObject) {
|
|
44
|
+
const key = prefix ? `${prefix}.${flatObjectKey}` : flatObjectKey;
|
|
45
|
+
result[`${key}`] = flatObject[flatObjectKey];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
module.exports = flattenObject;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const LocalazyApi = require("@localazy/ts-api").default;
|
|
4
|
+
const { LOCALAZY_PUBLIC_API_URL } = require("../config").default;
|
|
5
|
+
|
|
6
|
+
module.exports = async () => {
|
|
7
|
+
const user = await strapi
|
|
8
|
+
.plugin("localazy")
|
|
9
|
+
.service("localazyUserService")
|
|
10
|
+
.getUser();
|
|
11
|
+
|
|
12
|
+
const { accessToken } = user;
|
|
13
|
+
if (!accessToken) {
|
|
14
|
+
throw new Error("Localazy user is not logged in.");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const api = LocalazyApi({
|
|
18
|
+
projectToken: accessToken,
|
|
19
|
+
baseUrl: LOCALAZY_PUBLIC_API_URL,
|
|
20
|
+
});
|
|
21
|
+
return api;
|
|
22
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const getModelTree = (attributes, models) => {
|
|
4
|
+
const currentModelTree = {};
|
|
5
|
+
for (const attribute in attributes) {
|
|
6
|
+
if (attributes[attribute].type === "component") {
|
|
7
|
+
const nestedModel = models.find(
|
|
8
|
+
(model) => model.uid === attributes[attribute].component
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
currentModelTree[attribute] = {
|
|
12
|
+
...getModelTree(nestedModel.__schema__.attributes, models),
|
|
13
|
+
};
|
|
14
|
+
} else if (
|
|
15
|
+
["string", "text", "richtext"].includes(attributes[attribute].type)
|
|
16
|
+
) {
|
|
17
|
+
currentModelTree[attribute] = false;
|
|
18
|
+
} else {
|
|
19
|
+
currentModelTree[attribute] = null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return currentModelTree;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Kinds of models ["collectionType", "singleType"] are expected by the function.
|
|
28
|
+
*/
|
|
29
|
+
const getModelsTree = (models) => {
|
|
30
|
+
const modelsTree = [];
|
|
31
|
+
for (const model of models) {
|
|
32
|
+
const modelTree = {
|
|
33
|
+
[model.__schema__.collectionName]: {
|
|
34
|
+
__model__: true,
|
|
35
|
+
...getModelTree(model.__schema__.attributes, models),
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
modelsTree.push(modelTree);
|
|
39
|
+
}
|
|
40
|
+
return modelsTree;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
module.exports = getModelsTree;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const { isoStrapiToLocalazy } = require("./iso-locales-utils.js");
|
|
2
|
+
|
|
3
|
+
module.exports = (isoCode) => {
|
|
4
|
+
const isoDashed = isoStrapiToLocalazy(isoCode);
|
|
5
|
+
let languageNames = new Intl.DisplayNames(["en"], { type: "language" });
|
|
6
|
+
return languageNames.of(isoDashed);
|
|
7
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const SUPPORTED_MODEL_TYPES = ["contentType", "component"];
|
|
4
|
+
const UNSUPPORTED_UID_PREFIXES = [
|
|
5
|
+
"strapi::core",
|
|
6
|
+
"plugin::users-permissions.user",
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
module.exports = (model) => {
|
|
10
|
+
for (const prefix of UNSUPPORTED_UID_PREFIXES) {
|
|
11
|
+
if (model.uid.includes(prefix)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!SUPPORTED_MODEL_TYPES.includes(model.modelType)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// is not applicable
|
|
21
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
22
|
+
if (!model.__schema__) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (model.pluginOptions) {
|
|
27
|
+
if (model.pluginOptions["content-type-builder"]) {
|
|
28
|
+
return model.pluginOptions["content-type-builder"].visible;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return true;
|
|
33
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const isGenerallyApplicableContentType = require("./is-generally-applicable-content-type");
|
|
4
|
+
|
|
5
|
+
module.exports = (model) => {
|
|
6
|
+
const isGenerallyApplicable = isGenerallyApplicableContentType(model);
|
|
7
|
+
if (!isGenerallyApplicable) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// cannot be translatable
|
|
12
|
+
if (!model.pluginOptions) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// cannot be translatable
|
|
17
|
+
if (!model.pluginOptions) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (model.pluginOptions) {
|
|
22
|
+
// cannot be translatable
|
|
23
|
+
if (!model.pluginOptions["i18n"]) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// decide whether it is translatable
|
|
28
|
+
if (model.pluginOptions["i18n"]) {
|
|
29
|
+
return model.pluginOptions["i18n"].localized
|
|
30
|
+
? model.pluginOptions["i18n"].localized
|
|
31
|
+
: false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return true;
|
|
36
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const isoStrapiToLocalazy = (isoStrapi) => {
|
|
4
|
+
if (!isoStrapi) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return isoStrapi.replace("_", "-");
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const isoLocalazyToStrapi = (isoLocalazy) => {
|
|
12
|
+
if (!isoLocalazy) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return isoLocalazy.replace("-", "_");
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
isoStrapiToLocalazy,
|
|
21
|
+
isoLocalazyToStrapi,
|
|
22
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const set = require("lodash/set");
|
|
4
|
+
|
|
5
|
+
const arrayToObject = (array, keyField) =>
|
|
6
|
+
array.reduce((obj, item) => {
|
|
7
|
+
obj[item[keyField]] = item;
|
|
8
|
+
return obj;
|
|
9
|
+
}, {});
|
|
10
|
+
|
|
11
|
+
const objectiviseEntry = (entry) => {
|
|
12
|
+
const objectivized = {};
|
|
13
|
+
|
|
14
|
+
const objectiviseEntryStep = (entryStep, prefix = "") => {
|
|
15
|
+
if (entryStep === null || typeof entryStep !== "object") {
|
|
16
|
+
set(objectivized, prefix, entryStep);
|
|
17
|
+
} else {
|
|
18
|
+
if (Array.isArray(entryStep)) {
|
|
19
|
+
const arrayedEntry = arrayToObject(entryStep, "id");
|
|
20
|
+
Object.keys(arrayedEntry).forEach((key) => {
|
|
21
|
+
objectiviseEntryStep(
|
|
22
|
+
arrayedEntry[key],
|
|
23
|
+
prefix ? `${prefix}.${key}` : key
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
} else {
|
|
27
|
+
Object.keys(entryStep).forEach((key) => {
|
|
28
|
+
objectiviseEntryStep(
|
|
29
|
+
entryStep[key],
|
|
30
|
+
prefix ? `${prefix}.${key}` : key
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
objectiviseEntryStep(entry);
|
|
37
|
+
|
|
38
|
+
return objectivized;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports = objectiviseEntry;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const cloneDeepWith = require("lodash/cloneDeepWith");
|
|
4
|
+
|
|
5
|
+
function omitDeep(collection, excludeKeys) {
|
|
6
|
+
function omitFn(value) {
|
|
7
|
+
if (value && typeof value === "object") {
|
|
8
|
+
excludeKeys.forEach((key) => {
|
|
9
|
+
delete value[key];
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return cloneDeepWith(collection, omitFn);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = omitDeep;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const set = require("lodash/set");
|
|
4
|
+
|
|
5
|
+
const getAttribute = (model, attribute) => {
|
|
6
|
+
const attributeObj = model.attributes[attribute];
|
|
7
|
+
return attributeObj;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const isComponent = (attributeObj) => {
|
|
11
|
+
return attributeObj.type === "component";
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const isRepeatable = (attributeObj) => {
|
|
15
|
+
return isComponent(attributeObj) && !!attributeObj.repeatable;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const findModel = (models, uid) => {
|
|
19
|
+
const model = models.find((model) => model.uid === uid);
|
|
20
|
+
return model;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const parsedLocalazyEntryToCreateEntry = (
|
|
24
|
+
models,
|
|
25
|
+
parsedLocalazyEntry,
|
|
26
|
+
uid,
|
|
27
|
+
locale = ""
|
|
28
|
+
) => {
|
|
29
|
+
const createEntry = {};
|
|
30
|
+
|
|
31
|
+
const toCreateEntry = (
|
|
32
|
+
entry,
|
|
33
|
+
model,
|
|
34
|
+
// eslint-disable-next-line no-unused-vars
|
|
35
|
+
key = "",
|
|
36
|
+
prefix = "",
|
|
37
|
+
component = "",
|
|
38
|
+
isRepeatableComponent = false
|
|
39
|
+
) => {
|
|
40
|
+
if (Array.isArray(entry)) {
|
|
41
|
+
// is array
|
|
42
|
+
let i = 0;
|
|
43
|
+
Object.entries(entry).forEach(([, value]) => {
|
|
44
|
+
if (value !== null) {
|
|
45
|
+
if (component && isRepeatableComponent) {
|
|
46
|
+
toCreateEntry(value, model, i, `${prefix}.${i}`, component);
|
|
47
|
+
i += 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (component && !isRepeatableComponent) {
|
|
51
|
+
toCreateEntry(value, model, `${prefix}`, `${prefix}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
// is object
|
|
57
|
+
Object.entries(entry).forEach(([objectKey, value]) => {
|
|
58
|
+
const attribute = getAttribute(model, objectKey);
|
|
59
|
+
if (attribute === undefined) {
|
|
60
|
+
// logicaly don't anything, skip...
|
|
61
|
+
} else if (isComponent(attribute)) {
|
|
62
|
+
// is component
|
|
63
|
+
const component = attribute.component;
|
|
64
|
+
const componentModel = findModel(models, component);
|
|
65
|
+
if (isRepeatable(attribute)) {
|
|
66
|
+
// is repeatable - array
|
|
67
|
+
const newPrefix = prefix
|
|
68
|
+
? `${prefix}.${objectKey}`
|
|
69
|
+
: `${objectKey}`;
|
|
70
|
+
toCreateEntry(
|
|
71
|
+
value,
|
|
72
|
+
componentModel,
|
|
73
|
+
objectKey,
|
|
74
|
+
newPrefix,
|
|
75
|
+
component,
|
|
76
|
+
true
|
|
77
|
+
);
|
|
78
|
+
} else {
|
|
79
|
+
// is no repeatable - object
|
|
80
|
+
const newPrefix = prefix
|
|
81
|
+
? `${prefix}.${objectKey}`
|
|
82
|
+
: `${objectKey}`;
|
|
83
|
+
set(createEntry, `${newPrefix}.__component`, component);
|
|
84
|
+
toCreateEntry(
|
|
85
|
+
value,
|
|
86
|
+
componentModel,
|
|
87
|
+
objectKey,
|
|
88
|
+
newPrefix,
|
|
89
|
+
component,
|
|
90
|
+
false
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
const newPrefix = prefix ? `${prefix}.${objectKey}` : `${objectKey}`;
|
|
95
|
+
set(createEntry, newPrefix, value);
|
|
96
|
+
|
|
97
|
+
if (component) {
|
|
98
|
+
set(createEntry, `${prefix}.__component`, component);
|
|
99
|
+
}
|
|
100
|
+
// is not component
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const model = findModel(models, uid);
|
|
107
|
+
toCreateEntry(parsedLocalazyEntry, model);
|
|
108
|
+
if (locale) {
|
|
109
|
+
createEntry.locale = locale;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return createEntry;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
module.exports = parsedLocalazyEntryToCreateEntry;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const merge = require("lodash/merge");
|
|
4
|
+
const parsedLocalazyEntryToCreateEntry = require("./parsed-localazy-entry-to-create-entry");
|
|
5
|
+
const omitDeep = require("./omit-deep");
|
|
6
|
+
|
|
7
|
+
const parsedLocalazyEntryToUpdateEntry = (
|
|
8
|
+
allModels,
|
|
9
|
+
localazyEntry,
|
|
10
|
+
currentEntry,
|
|
11
|
+
uid
|
|
12
|
+
) => {
|
|
13
|
+
const createEntry = parsedLocalazyEntryToCreateEntry(
|
|
14
|
+
allModels,
|
|
15
|
+
localazyEntry,
|
|
16
|
+
uid
|
|
17
|
+
);
|
|
18
|
+
let updateEntry = merge(currentEntry, createEntry);
|
|
19
|
+
updateEntry = omitDeep(updateEntry, [
|
|
20
|
+
"__component",
|
|
21
|
+
"locale",
|
|
22
|
+
"localizations",
|
|
23
|
+
"createdAt",
|
|
24
|
+
"updatedAt",
|
|
25
|
+
"publishedAt",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
return updateEntry;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = parsedLocalazyEntryToUpdateEntry;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const pickEntries = (flatten, pickPaths) => {
|
|
4
|
+
const pickedEntries = {};
|
|
5
|
+
Object.keys(flatten).forEach((key) => {
|
|
6
|
+
const filteredKey = key.replace(/\d|[[\]]+/g, "");
|
|
7
|
+
if (pickPaths.includes(filteredKey)) {
|
|
8
|
+
pickedEntries[key] = flatten[key];
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
return pickedEntries;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
module.exports = pickEntries;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const getMainKeysOfNestedArrayObjects = require("./get-main-keys-of-nested-array-objects");
|
|
2
|
+
const flattenObject = require("./flatten-object");
|
|
3
|
+
|
|
4
|
+
const findSetupModelByCollectionName = (models, collectionName) => {
|
|
5
|
+
return models.find((model) => Object.keys(model)[0] === collectionName);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const getCollectionsNames = (setup) => {
|
|
9
|
+
return getMainKeysOfNestedArrayObjects(setup);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const isCollectionTransferEnabled = (models, collectionName) => {
|
|
13
|
+
const model = findSetupModelByCollectionName(models, collectionName);
|
|
14
|
+
|
|
15
|
+
if (!model || !model[collectionName]) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return !!model[collectionName].__model__;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const getPickPaths = (transferSetupModelProps) => {
|
|
23
|
+
const flattenedObject = flattenObject(transferSetupModelProps);
|
|
24
|
+
const pickPaths = Object.keys(flattenedObject).filter(
|
|
25
|
+
(key) => flattenedObject[key] === true && key.indexOf("__model__") === -1
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// id needs to be always included
|
|
29
|
+
pickPaths.push("id");
|
|
30
|
+
|
|
31
|
+
return pickPaths;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
findSetupModelByCollectionName,
|
|
36
|
+
getCollectionsNames,
|
|
37
|
+
isCollectionTransferEnabled,
|
|
38
|
+
getPickPaths,
|
|
39
|
+
};
|
package/strapi-admin.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// TODO: resolve if possible
|
|
4
|
+
// https://medium.com/the-javascript-dojo/improving-code-readability-with-path-aliases-1a41143d7632
|
|
5
|
+
// const moduleAlias = require("module-alias");
|
|
6
|
+
|
|
7
|
+
// moduleAlias.addAliases({
|
|
8
|
+
// // eslint-disable-next-line node/no-path-concat
|
|
9
|
+
// "@admin": `${__dirname}/admin`,
|
|
10
|
+
// // eslint-disable-next-line node/no-path-concat
|
|
11
|
+
// "@src": `${__dirname}/admin/src`,
|
|
12
|
+
// });
|
|
13
|
+
|
|
14
|
+
module.exports = require("./admin/src").default;
|