Skip to content

Commit

Permalink
Feat add json fields support (#65)
Browse files Browse the repository at this point in the history
* 🚧 wip: add json to supported content types

* ✨ feat: add json fields support

* πŸ› fix: string array is split into letters

* ✨ feat(JSON fields): attempt to support DZs and components

* πŸ› fix(JSON): `null` values upload

* πŸ› fix: doubled backslashed in URL

---------

Co-authored-by: david-vaclavek <vaclavek.dvd@gmail.com>
  • Loading branch information
david-vaclavek and david-vaclavek authored Nov 14, 2024
1 parent 76a6996 commit 5ef1f08
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const SUPPORTED_CONTENT_TYPE_FIELDS = [
"text",
"richtext",
"email",
"json",
];

export default SUPPORTED_CONTENT_TYPE_FIELDS;
2 changes: 1 addition & 1 deletion admin/src/modules/@common/utils/get-nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Upload from "@strapi/icons/Upload";
import pluginId from "../../../pluginId";
import i18n from "../../../i18n";

const BASE_PATH = `${process.env.ADMIN_PATH}/plugins/${pluginId}`;
const BASE_PATH = `${process.env.ADMIN_PATH}plugins/${pluginId}`;
const t = i18n.t;
const gevNav = () => {
return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ export default (route) => {
return;
}

history.push(`${process.env.ADMIN_PATH}/plugins/${pluginId}/${route}`);
history.push(`${process.env.ADMIN_PATH}plugins/${pluginId}/${route}`);
};
8 changes: 4 additions & 4 deletions admin/src/pages/App/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function App() {
<>
{!isLoggedIn && (
<Switch>
<Route path={`${process.env.ADMIN_PATH}/plugins/${pluginId}/login`} exact>
<Route path={`${process.env.ADMIN_PATH}plugins/${pluginId}/login`} exact>
<Login
title={headerTitle}
subtitle={headerSubtitle}
Expand All @@ -121,19 +121,19 @@ function App() {

{isLoggedIn && (
<Switch>
<Route path={`${process.env.ADMIN_PATH}/plugins/${pluginId}/download`} exact>
<Route path={`${process.env.ADMIN_PATH}plugins/${pluginId}/download`} exact>
<Download
title={headerTitle}
subtitle={headerSubtitle}
/>
</Route>
<Route path={`${process.env.ADMIN_PATH}/plugins/${pluginId}/upload`} exact>
<Route path={`${process.env.ADMIN_PATH}plugins/${pluginId}/upload`} exact>
<Upload
title={headerTitle}
subtitle={headerSubtitle}
/>
</Route>
<Route path={`${process.env.ADMIN_PATH}/plugins/${pluginId}/settings`} exact>
<Route path={`${process.env.ADMIN_PATH}plugins/${pluginId}/settings`} exact>
<Settings
title={headerTitle}
subtitle={headerSubtitle}
Expand Down
37 changes: 35 additions & 2 deletions server/functions/should-set-downloaded-property.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ const getDynamicZonePropertyName = (parsedKey) => {
return parsedKey[dynamicZoneKeySegmentIndex - 1];
};

/**
*
* @param {*} modelContentTransferSetup
* @param {*} parsedKeyRest
* @returns "yes" | "no" | "json"
*/
const shouldSetDownloadedProperty = (
modelContentTransferSetup,
parsedKeyRest,
Expand All @@ -50,11 +56,38 @@ const shouldSetDownloadedProperty = (
const slicedParsedKeyRest = parsedKeyRest.slice(dynamicZoneKeySegmentIndex + 1);
const filteredSlicedParsedKeyRest = slicedParsedKeyRest.filter((segment) => isNaN(parseInt(segment)));

return !!get(dzContentTransferSetupComponentModel, filteredSlicedParsedKeyRest);
if(get(dzContentTransferSetupComponentModel, filteredSlicedParsedKeyRest) === true) {
return "yes";
}

// json fields
while(filteredSlicedParsedKeyRest.length > 0) {
// last segment out
filteredSlicedParsedKeyRest.pop();
if(get(dzContentTransferSetupComponentModel, filteredSlicedParsedKeyRest) === true) {
return "json";
}
}

return "no";
} else {
const filteredParsedKeyRest = parsedKeyRest
.filter((partialKey) => isNaN(parseInt(partialKey)));
return !!get(modelContentTransferSetup, filteredParsedKeyRest);

if(get(modelContentTransferSetup, filteredParsedKeyRest) === true) {
return "yes";
}

// json fields
while(filteredParsedKeyRest.length > 0) {
// last segment out
filteredParsedKeyRest.pop();
if(get(modelContentTransferSetup, filteredParsedKeyRest) === true) {
return "json";
}
}

return "no";
}
};

Expand Down
1 change: 1 addition & 0 deletions server/models/supported-content-type-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const SUPPORTED_CONTENT_TYPE_FIELDS = [
"text",
"richtext",
"email",
"json",
];

module.exports = SUPPORTED_CONTENT_TYPE_FIELDS;
79 changes: 70 additions & 9 deletions server/services/localazy-transfer-download-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
} = require("../utils/iso-locales-utils");
const shouldSetDownloadedProperty = require("../functions/should-set-downloaded-property");
const set = require("lodash/set");
const get = require("lodash/get");
const isEmpty = require("lodash/isEmpty");
const RequestInitiatorHelper = require('../utils/request-initiator-helper');
const PluginSettingsServiceHelper = require('../services/helpers/plugin-settings-service-helper');
Expand Down Expand Up @@ -223,6 +224,7 @@ module.exports = ({ strapi }) => ({
*/
const parsedLocalazyContent = {};
const strapiContentTypesModels = await StrapiService.getModels();
const jsonFields = [];
for (const [isoLocalazy, keys] of Object.entries(localazyContent)) {
const isoStrapi = isoLocalazyToStrapi(isoLocalazy);
if (!isoStrapi) {
Expand All @@ -244,20 +246,79 @@ module.exports = ({ strapi }) => ({
parsedKey.uid
);

if (typeof modelContentTransferSetup !== "undefined" && shouldSetDownloadedProperty(modelContentTransferSetup, parsedKey.rest)) {
const parsedKeyRestWithoutComponents = parsedKey.rest;
const setKey = [
isoStrapi,
parsedKey.uid,
parsedKey.id,
...parsedKeyRestWithoutComponents,
];
if (typeof modelContentTransferSetup !== "undefined") {
const shouldSetDownloadedPropertyResult = shouldSetDownloadedProperty(modelContentTransferSetup, parsedKey.rest);
if (shouldSetDownloadedPropertyResult === "no") {
continue;
}

let parsedKeyRestWithoutComponents = parsedKey.rest;
if (shouldSetDownloadedPropertyResult === "json") {
const setKey = [
isoStrapi,
parsedKey.uid,
parsedKey.id,
];

// handle dynamic zones and components here
let updatedParsedKeyRestWithoutComponents = parsedKeyRestWithoutComponents;
let segmentsToAdd = [];
for (const segment of parsedKeyRestWithoutComponents) {
const hasEntry = get(modelContentTransferSetup, [...segmentsToAdd, segment]);
const hasEntryNotFinal = hasEntry && typeof hasEntry !== "boolean";
// const isDZ = Array.isArray(hasEntry) && hasEntry.every((entry) => entry.__component__);
// processed till here in iterations and `segment` is numeric
const isComponent = parseInt(segment) > 0;

if (hasEntryNotFinal || (!hasEntry && isComponent)) {
segmentsToAdd.push(segment);
setKey.push(segment);
updatedParsedKeyRestWithoutComponents = updatedParsedKeyRestWithoutComponents.slice(1);
} else {
break;
}
}
parsedKeyRestWithoutComponents = updatedParsedKeyRestWithoutComponents;

let foundJsonFieldIndex = jsonFields.findIndex((jsonField) => {
return jsonField.setKey.join() === setKey.join();
});
if (foundJsonFieldIndex === -1) {
jsonFields.push({
setKey,
jsonKey: parsedKeyRestWithoutComponents[0],
jsonValue: {},
});
}

set(parsedLocalazyContent, setKey, value);
foundJsonFieldIndex = foundJsonFieldIndex === -1 ? jsonFields.length - 1 : foundJsonFieldIndex;
const foundJsonField = jsonFields[foundJsonFieldIndex];
// rest from index 1
const restSliced = parsedKeyRestWithoutComponents.slice(1);
set(foundJsonField, ['jsonValue', ...restSliced], value);
jsonFields[foundJsonFieldIndex] = foundJsonField;
}

if (shouldSetDownloadedPropertyResult === "yes") {
const setKey = [
isoStrapi,
parsedKey.uid,
parsedKey.id,
...parsedKeyRestWithoutComponents,
];
set(parsedLocalazyContent, setKey, value);
}
}
}
}

/**
* Set json fields if applicable
*/
for (const jsonField of jsonFields) {
set(parsedLocalazyContent, [...jsonField.setKey, jsonField.jsonKey], jsonField.jsonValue);
}

/**
* Iterate over parsed Localazy content and insert/update content in Strapi
*/
Expand Down
8 changes: 6 additions & 2 deletions server/utils/flatten-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
const flattenObject = (object, prefix = "") => {
const result = {};

if (typeof object === "string" || typeof object === "number" || typeof object === "boolean") {
return object;
}

for (const objectKey in object) {
if (objectKey === "id") {
continue;
Expand All @@ -22,9 +26,9 @@ const flattenObject = (object, prefix = "") => {
const flattenedArray = object[objectKey].reduce(
(accumulator, item, index) => {
// No id should use the index of the array item
let key = `${objectKey}[${item.id || index}]`;
let key = `${objectKey}[${item?.id || index}]`;
// is Dynamic Zone
if (item.id && item.__component) {
if (item?.id && item?.__component) {
key = `${objectKey}[${item.id};${item.__component}]`;
}

Expand Down
7 changes: 6 additions & 1 deletion server/utils/pick-entries.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ const pickEntries = (flatten, pickPaths) => {
if (isDynamicZoneKey(key)) {
filteredKey = filteredKey.replace(/\[\d+;[\w-]+\./g, `[`);
}
if (mappedPickPaths.includes(filteredKey)) {
// if (mappedPickPaths.includes(filteredKey)) {
if (
mappedPickPaths.includes(filteredKey) ||
// include JSON fields
mappedPickPaths.some((pickPath) => filteredKey.startsWith(`${pickPath}.`))
) {
pickedEntries[key] = flatten[key];
}
});
Expand Down

0 comments on commit 5ef1f08

Please sign in to comment.