Init copy locale logic and move utils from CM to the helper plugin

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2021-03-17 11:54:59 +01:00
parent 3c21cbb23e
commit 0291649c1f
12 changed files with 350 additions and 24 deletions

View File

@ -1,3 +1,4 @@
import { getType, getOtherInfos } from './utils/getAttributeInfos';
// Assets
export { default as colors } from './assets/styles/colors';
export { default as sizes } from './assets/styles/sizes';
@ -126,6 +127,7 @@ export { default as cleanData } from './utils/cleanData';
export { default as difference } from './utils/difference';
export { default as dateFormats } from './utils/dateFormats';
export { default as dateToUtcTime } from './utils/dateToUtcTime';
export { default as formatComponentData } from './utils/formatComponentData';
export { default as hasPermissions } from './utils/hasPermissions';
export { findMatchingPermissions } from './utils/hasPermissions';
export { default as translatedErrors } from './utils/translatedErrors';
@ -139,11 +141,14 @@ export { default as Manager } from './utils/Manager';
export { default as request } from './utils/request';
export { default as storeData } from './utils/storeData';
export { default as templateObject } from './utils/templateObject';
export { getType };
export { getOtherInfos };
export { default as getYupInnerErrors } from './utils/getYupInnerErrors';
export { default as generateFiltersFromSearch } from './utils/generateFiltersFromSearch';
export { default as generateSearchFromFilters } from './utils/generateSearchFromFilters';
export { default as generateSearchFromObject } from './utils/generateSearchFromObject';
export { default as prefixFileUrlWithBackendUrl } from './utils/prefixFileUrlWithBackendUrl';
export { default as removeFieldsFromClonedData } from './utils/removeFieldsFromClonedData';
// SVGS
export { default as LayoutIcon } from './svgs/Layout';

View File

@ -0,0 +1,305 @@
const testData = {
contentType: {
uid: 'application::test.test',
apiID: 'test',
attributes: {
created_at: { type: 'timestamp' },
dz: { type: 'dynamiczone', components: ['compos.test-compo', 'compos.sub-compo'] },
id: { type: 'integer' },
name: { type: 'string' },
notrepeatable: {
type: 'component',
repeatable: false,
component: 'compos.test-compo',
},
password: { type: 'password' },
repeatable: { type: 'component', repeatable: true, component: 'compos.test-compo' },
updated_at: { type: 'timestamp' },
},
},
components: {
'compos.sub-compo': {
uid: 'compos.sub-compo',
category: 'compos',
attributes: {
id: { type: 'integer' },
name: { type: 'string' },
password: { type: 'password' },
},
},
'compos.test-compo': {
uid: 'compos.test-compo',
category: 'compos',
attributes: {
id: { type: 'integer' },
name: { type: 'string' },
password: { type: 'password' },
subcomponotrepeatable: {
type: 'component',
repeatable: false,
component: 'compos.sub-compo',
},
subrepeatable: {
type: 'component',
repeatable: true,
component: 'compos.sub-compo',
},
},
},
},
modifiedData: {
created_at: '2020-04-28T13:22:13.033Z',
dz: [
{ __component: 'compos.sub-compo', id: 7, name: 'name', password: 'password' },
{
id: 4,
name: 'name',
password: 'password',
subcomponotrepeatable: null,
subrepeatable: [],
__component: 'compos.test-compo',
},
{
id: 5,
name: 'name',
password: 'password',
subcomponotrepeatable: { id: 9, name: 'name', password: 'password' },
subrepeatable: [{ id: 8, name: 'name', password: 'password' }],
__component: 'compos.test-compo',
},
{
id: 6,
name: null,
password: null,
subcomponotrepeatable: null,
subrepeatable: [],
__component: 'compos.test-compo',
},
],
id: 1,
name: 'name',
notrepeatable: {
id: 1,
name: 'name',
password: 'password',
subcomponotrepeatable: { id: 4, name: 'name', password: 'password' },
subrepeatable: [
{ id: 1, name: 'name', password: 'password' },
{ id: 2, name: 'name', password: 'password' },
{ id: 3, name: 'name', password: 'password' },
],
},
password: 'password',
repeatable: [
{
id: 2,
name: 'name',
password: 'password',
subrepeatable: [{ id: 5, name: 'name', password: 'password' }],
subcomponotrepeatable: { id: 6, name: 'name', password: 'password' },
},
{
id: 3,
name: 'name',
password: 'password',
subrepeatable: [],
subcomponotrepeatable: null,
},
],
updated_at: '2020-04-28T13:22:13.033Z',
},
expectedModifiedData: {
created_at: '2020-04-28T13:22:13.033Z',
dz: [
{ __component: 'compos.sub-compo', id: 7, name: 'name' },
{
id: 4,
name: 'name',
subcomponotrepeatable: null,
subrepeatable: [],
__component: 'compos.test-compo',
},
{
id: 5,
name: 'name',
subcomponotrepeatable: { id: 9, name: 'name' },
subrepeatable: [{ id: 8, name: 'name' }],
__component: 'compos.test-compo',
},
{
id: 6,
name: null,
subcomponotrepeatable: null,
subrepeatable: [],
__component: 'compos.test-compo',
},
],
id: 1,
name: 'name',
notrepeatable: {
id: 1,
name: 'name',
subcomponotrepeatable: { id: 4, name: 'name' },
subrepeatable: [
{ id: 1, name: 'name' },
{ id: 2, name: 'name' },
{ id: 3, name: 'name' },
],
},
repeatable: [
{
id: 2,
name: 'name',
subrepeatable: [{ id: 5, name: 'name' }],
subcomponotrepeatable: { id: 6, name: 'name' },
},
{
id: 3,
name: 'name',
subrepeatable: [],
subcomponotrepeatable: null,
},
],
updated_at: '2020-04-28T13:22:13.033Z',
},
expectedNoFieldsModifiedData: {
dz: [
{ __component: 'compos.sub-compo', name: 'name', password: 'password' },
{
name: 'name',
password: 'password',
subcomponotrepeatable: null,
subrepeatable: [],
__component: 'compos.test-compo',
},
{
name: 'name',
password: 'password',
subcomponotrepeatable: { name: 'name', password: 'password' },
subrepeatable: [{ name: 'name', password: 'password' }],
__component: 'compos.test-compo',
},
{
name: null,
password: null,
subcomponotrepeatable: null,
subrepeatable: [],
__component: 'compos.test-compo',
},
],
name: 'name',
notrepeatable: {
name: 'name',
password: 'password',
subcomponotrepeatable: { name: 'name', password: 'password' },
subrepeatable: [
{ name: 'name', password: 'password' },
{ name: 'name', password: 'password' },
{ name: 'name', password: 'password' },
],
},
password: 'password',
repeatable: [
{
name: 'name',
password: 'password',
subrepeatable: [{ name: 'name', password: 'password' }],
subcomponotrepeatable: { name: 'name', password: 'password' },
},
{
name: 'name',
password: 'password',
subrepeatable: [],
subcomponotrepeatable: null,
},
],
},
};
const permissions = [
{
id: 11,
action: 'plugins::content-manager.explorer.read',
subject: 'application::article.article',
properties: {
fields: ['name', 'description'],
},
conditions: ['admin::is-creator'],
},
{
id: 12,
action: 'plugins::content-manager.explorer.update',
subject: 'application::article.article',
properties: {
fields: ['name', 'description'],
},
conditions: ['admin::is-creator'],
},
{
id: 22,
action: 'plugins::content-manager.explorer.read',
subject: 'plugins::users-permissions.user',
properties: {
fields: [
'username',
'email',
'provider',
'password',
'resetPasswordToken',
'confirmed',
'blocked',
'role',
],
},
conditions: [],
},
{
id: 24,
action: 'plugins::content-manager.explorer.update',
subject: 'plugins::users-permissions.user',
properties: {
fields: [
'username',
'email',
'provider',
'password',
'resetPasswordToken',
'confirmed',
'blocked',
'role',
],
},
conditions: [],
},
{
id: 28,
action: 'plugins::upload.read',
subject: null,
properties: {
fields: null,
},
conditions: [],
},
{
id: 39,
action: 'plugins::users-permissions.roles.update',
subject: null,
properties: {
fields: null,
},
conditions: [],
},
{
id: 63,
action: 'plugins::content-manager.explorer.read',
subject: 'application::article.article',
properties: {
fields: ['name', 'description', 'test'],
},
conditions: [],
},
];
export default testData;
export { permissions };

View File

@ -1,7 +1,7 @@
// NOTE: this function is for adding a __temp_key__ key to each object of a repeatable component
// in order to have a unique identifier for the DnD
import { get } from 'lodash';
import get from 'lodash/get';
import { getType, getOtherInfos } from './getAttributeInfos';
const formatComponentData = (data, ct, composSchema) => {

View File

@ -1,4 +1,4 @@
import { get } from 'lodash';
import get from 'lodash/get';
const getType = (schema, attrName) => get(schema, ['attributes', attrName, 'type'], '');
const getOtherInfos = (schema, arr) => get(schema, ['attributes', ...arr], '');

View File

@ -1,9 +1,9 @@
import { testData } from '../../testUtils';
import testData from '../../testUtils/testData';
import formatComponentData from '../formatComponentData';
const { contentType, components, modifiedData } = testData;
describe('CONTENT MANAGER | utils | formatComponentData', () => {
describe('STRAPI_HELPER_PLUGIN | utils | formatComponentData', () => {
it('should add the __temp_key__ property to each repeatable component object', () => {
const expected = {
created_at: '2020-04-28T13:22:13.033Z',

View File

@ -1,7 +1,7 @@
import { testData } from '../../testUtils';
import testData from '../../testUtils/testData';
import removeFieldsFromClonedData from '../removeFieldsFromClonedData';
describe('CONTENT MANAGER | containers | EditViewDataManager | utils', () => {
describe('STRAPI_HELPER_PLUGIN | utils', () => {
describe('removeFieldsFromClonedData', () => {
it('should return an empty object', () => {
const { components, contentType } = testData;

View File

@ -1,16 +1,16 @@
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { get } from 'lodash';
import { request, useGlobalContext, useQueryParams } from 'strapi-helper-plugin';
import {
request,
useGlobalContext,
useQueryParams,
formatComponentData,
removeFieldsFromClonedData,
} from 'strapi-helper-plugin';
import { useSelector, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import {
createDefaultForm,
formatComponentData,
getTrad,
removePasswordFieldsFromData,
removeFieldsFromClonedData,
} from '../../utils';
import { createDefaultForm, getTrad, removePasswordFieldsFromData } from '../../utils';
import pluginId from '../../pluginId';
import {
getData,

View File

@ -1,15 +1,10 @@
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { get } from 'lodash';
import { request, useGlobalContext } from 'strapi-helper-plugin';
import { request, useGlobalContext, formatComponentData } from 'strapi-helper-plugin';
import { useSelector, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import {
createDefaultForm,
formatComponentData,
getTrad,
removePasswordFieldsFromData,
} from '../../utils';
import { createDefaultForm, getTrad, removePasswordFieldsFromData } from '../../utils';
import {
getData,
getDataSucceeded,

View File

@ -1,7 +1,6 @@
export { default as checkIfAttributeIsDisplayable } from './checkIfAttributeIsDisplayable';
export { default as createDefaultForm } from './createDefaultForm';
export { default as dateFormats } from './dateFormats';
export { default as formatComponentData } from './formatComponentData';
export { default as formatFiltersFromQuery } from './formatFiltersFromQuery';
export { default as formatFiltersToQuery } from './formatFiltersToQuery';
export { default as formatLayoutToApi } from './formatLayoutToApi';
@ -16,4 +15,3 @@ export { default as ItemTypes } from './ItemTypes';
export { default as mergeMetasWithSchema } from './mergeMetasWithSchema';
export { default as removeKeyInObject } from './removeKeyInObject';
export { default as removePasswordFieldsFromData } from './removePasswordFieldsFromData';
export { default as removeFieldsFromClonedData } from './removeFieldsFromClonedData';

View File

@ -1,5 +1,5 @@
import { get } from 'lodash';
import { getType, getOtherInfos } from './getAttributeInfos';
import { getType, getOtherInfos } from 'strapi-helper-plugin';
const removePasswordFieldsFromData = (data, contentTypeSchema, componentSchema) => {
const recursiveCleanData = (data, schema) => {

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { Duplicate } from '@buffetjs/icons';
import { Label, Padded, Text } from '@buffetjs/core';
import Select from 'react-select';
import { useDispatch } from 'react-redux';
import { useTheme } from 'styled-components';
import { useIntl } from 'react-intl';
import {
@ -10,15 +11,36 @@ import {
ModalConfirm,
selectStyles,
DropdownIndicator,
useContentManagerEditViewDataManager,
request,
} from 'strapi-helper-plugin';
import { getTrad } from '../../utils';
const CMEditViewCopyLocale = ({ appLocales, currentLocale, localizations }) => {
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const { slug } = useContentManagerEditViewDataManager();
const [isOpen, setIsOpen] = useState(false);
const [value, setValue] = useState(null);
const theme = useTheme();
const handleConfirmCopyLocale = async () => {
if (!value) {
handleToggle();
return;
}
const requestURL = `/content-manager/collection-types/${slug}/${value.value}`;
try {
const response = await request(requestURL, { method: 'GET' });
console.log({ response });
} catch (err) {
console.log(err);
}
};
const handleChange = value => {
setValue(value);
};
@ -73,6 +95,7 @@ const CMEditViewCopyLocale = ({ appLocales, currentLocale, localizations }) => {
'Your current content will be erased and filled by the content of the selected locale:',
}}
isOpen={isOpen}
onConfirm={handleConfirmCopyLocale}
title={{ id: 'CMEditViewCopyLocale.ModalConfirm.title', defaultMessage: 'Select Locale' }}
toggle={handleToggle}
type="success"