mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-03 19:36:20 +00:00 
			
		
		
		
	Features/i18n locale in filters (#9611)
This commit is contained in:
		
							parent
							
								
									068a31c3e5
								
							
						
					
					
						commit
						32a5e2becf
					
				@ -9,7 +9,7 @@ import { useFetchContentTypeLayout } from '../../hooks';
 | 
			
		||||
import { formatLayoutToApi } from '../../utils';
 | 
			
		||||
import EditView from '../EditView';
 | 
			
		||||
import EditSettingsView from '../EditSettingsView';
 | 
			
		||||
import ListView from '../ListView';
 | 
			
		||||
import ListViewLayout from '../ListView/ListViewLayout';
 | 
			
		||||
import ListSettingsView from '../ListSettingsView';
 | 
			
		||||
 | 
			
		||||
const CollectionTypeRecursivePath = ({
 | 
			
		||||
@ -75,7 +75,7 @@ const CollectionTypeRecursivePath = ({
 | 
			
		||||
  const routes = [
 | 
			
		||||
    { path: ':id/clone/:origin', comp: EditView },
 | 
			
		||||
    { path: ':id', comp: EditView },
 | 
			
		||||
    { path: '', comp: ListView },
 | 
			
		||||
    { path: '', comp: ListViewLayout },
 | 
			
		||||
  ].map(({ path, comp }) => (
 | 
			
		||||
    <Route key={path} path={`${url}/${path}`} render={props => renderRoute(props, comp)} />
 | 
			
		||||
  ));
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,48 @@
 | 
			
		||||
import React, { useEffect } from 'react';
 | 
			
		||||
import { useDispatch, useSelector } from 'react-redux';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import { setLayout } from './actions';
 | 
			
		||||
import ListView from '.';
 | 
			
		||||
import { useQueryParams } from '../../hooks';
 | 
			
		||||
 | 
			
		||||
const ListViewLayout = ({ layout, ...props }) => {
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const initialParams = useSelector(state => state.get('content-manager_listView').initialParams);
 | 
			
		||||
  const [, setQuery] = useQueryParams(initialParams);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    dispatch(setLayout(layout.contentType));
 | 
			
		||||
  }, [dispatch, layout]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (initialParams) {
 | 
			
		||||
      setQuery(initialParams);
 | 
			
		||||
    }
 | 
			
		||||
  }, [initialParams, setQuery]);
 | 
			
		||||
 | 
			
		||||
  if (!initialParams) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return <ListView {...props} layout={layout} />;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ListViewLayout.propTypes = {
 | 
			
		||||
  layout: PropTypes.exact({
 | 
			
		||||
    components: PropTypes.object.isRequired,
 | 
			
		||||
    contentType: PropTypes.shape({
 | 
			
		||||
      attributes: PropTypes.object.isRequired,
 | 
			
		||||
      metadatas: PropTypes.object.isRequired,
 | 
			
		||||
      info: PropTypes.shape({ label: PropTypes.string.isRequired }).isRequired,
 | 
			
		||||
      layouts: PropTypes.shape({
 | 
			
		||||
        list: PropTypes.array.isRequired,
 | 
			
		||||
        editRelations: PropTypes.array,
 | 
			
		||||
      }).isRequired,
 | 
			
		||||
      options: PropTypes.object.isRequired,
 | 
			
		||||
      settings: PropTypes.object.isRequired,
 | 
			
		||||
      pluginOptions: PropTypes.object,
 | 
			
		||||
    }).isRequired,
 | 
			
		||||
  }).isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default ListViewLayout;
 | 
			
		||||
@ -78,6 +78,23 @@ export function toggleModalDelete() {
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const setLayout = layout => ({ layout, type: SET_LIST_LAYOUT });
 | 
			
		||||
export const setLayout = contentType => {
 | 
			
		||||
  const { layouts, settings } = contentType;
 | 
			
		||||
  const defaultSort = `${settings.defaultSortBy}:${settings.defaultSortOrder}`;
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    contentType,
 | 
			
		||||
    displayedHeaders: layouts.list,
 | 
			
		||||
    type: SET_LIST_LAYOUT,
 | 
			
		||||
    // initParams needs to explicitly set in the action so that external
 | 
			
		||||
    // plugin can override this one.
 | 
			
		||||
    // For instance, the i18n plugin will catch this action in a middleware and enhance it with a "locale" key
 | 
			
		||||
    initialParams: {
 | 
			
		||||
      page: 1,
 | 
			
		||||
      pageSize: settings.pageSize,
 | 
			
		||||
      _sort: defaultSort,
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const onChangeListHeaders = target => ({ type: ON_CHANGE_LIST_HEADERS, target });
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,6 @@ import { useHistory, useLocation } from 'react-router-dom';
 | 
			
		||||
import { Header } from '@buffetjs/custom';
 | 
			
		||||
import { Flex, Padded } from '@buffetjs/core';
 | 
			
		||||
import isEqual from 'react-fast-compare';
 | 
			
		||||
import { stringify } from 'qs';
 | 
			
		||||
import {
 | 
			
		||||
  PopUpWarning,
 | 
			
		||||
  request,
 | 
			
		||||
@ -53,7 +52,7 @@ import {
 | 
			
		||||
} from './actions';
 | 
			
		||||
import makeSelectListView from './selectors';
 | 
			
		||||
 | 
			
		||||
import { getAllAllowedHeaders, getFirstSortableHeader } from './utils';
 | 
			
		||||
import { getAllAllowedHeaders, getFirstSortableHeader, buildQueryString } from './utils';
 | 
			
		||||
 | 
			
		||||
/* eslint-disable react/no-array-index-key */
 | 
			
		||||
function ListView({
 | 
			
		||||
@ -80,21 +79,14 @@ function ListView({
 | 
			
		||||
  onResetListHeaders,
 | 
			
		||||
  pagination: { total },
 | 
			
		||||
  resetProps,
 | 
			
		||||
  setLayout,
 | 
			
		||||
  slug,
 | 
			
		||||
  initialParams,
 | 
			
		||||
}) {
 | 
			
		||||
  const {
 | 
			
		||||
    contentType: {
 | 
			
		||||
      attributes,
 | 
			
		||||
      metadatas,
 | 
			
		||||
      settings: {
 | 
			
		||||
        defaultSortBy,
 | 
			
		||||
        defaultSortOrder,
 | 
			
		||||
        bulkable: isBulkable,
 | 
			
		||||
        filterable: isFilterable,
 | 
			
		||||
        searchable: isSearchable,
 | 
			
		||||
        pageSize: defaultPageSize,
 | 
			
		||||
      },
 | 
			
		||||
      settings: { bulkable: isBulkable, filterable: isFilterable, searchable: isSearchable },
 | 
			
		||||
    },
 | 
			
		||||
  } = layout;
 | 
			
		||||
 | 
			
		||||
@ -105,12 +97,9 @@ function ListView({
 | 
			
		||||
    isLoading: isLoadingForPermissions,
 | 
			
		||||
    allowedActions: { canCreate, canRead, canUpdate, canDelete },
 | 
			
		||||
  } = useUserPermissions(viewPermissions);
 | 
			
		||||
  const defaultSort = `${defaultSortBy}:${defaultSortOrder}`;
 | 
			
		||||
  const initParams = useMemo(() => ({ page: 1, pageSize: defaultPageSize, _sort: defaultSort }), [
 | 
			
		||||
    defaultPageSize,
 | 
			
		||||
    defaultSort,
 | 
			
		||||
  ]);
 | 
			
		||||
  const [{ query, rawQuery }, setQuery] = useQueryParams(initParams);
 | 
			
		||||
 | 
			
		||||
  const [{ query }, setQuery] = useQueryParams(initialParams);
 | 
			
		||||
  const params = buildQueryString(query);
 | 
			
		||||
 | 
			
		||||
  const { pathname } = useLocation();
 | 
			
		||||
  const { push } = useHistory();
 | 
			
		||||
@ -131,22 +120,17 @@ function ListView({
 | 
			
		||||
 | 
			
		||||
  const label = contentType.info.label;
 | 
			
		||||
 | 
			
		||||
  const params = useMemo(() => {
 | 
			
		||||
    return rawQuery || `?${stringify(initParams, { encode: false })}`;
 | 
			
		||||
  }, [initParams, rawQuery]);
 | 
			
		||||
 | 
			
		||||
  const firstSortableHeader = useMemo(() => getFirstSortableHeader(displayedHeaders), [
 | 
			
		||||
    displayedHeaders,
 | 
			
		||||
  ]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    setLayout(layout);
 | 
			
		||||
    setFilterPickerState(false);
 | 
			
		||||
 | 
			
		||||
    return () => {
 | 
			
		||||
      resetProps();
 | 
			
		||||
    };
 | 
			
		||||
  }, [layout, setLayout, resetProps]);
 | 
			
		||||
  }, [resetProps]);
 | 
			
		||||
 | 
			
		||||
  // Using a ref to avoid requests being fired multiple times on slug on change
 | 
			
		||||
  // We need it because the hook as mulitple dependencies so it may run before the permissions have checked
 | 
			
		||||
@ -528,6 +512,7 @@ ListView.propTypes = {
 | 
			
		||||
  toggleModalDelete: PropTypes.func.isRequired,
 | 
			
		||||
  toggleModalDeleteAll: PropTypes.func.isRequired,
 | 
			
		||||
  setLayout: PropTypes.func.isRequired,
 | 
			
		||||
  initialParams: PropTypes.shape({}).isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = makeSelectListView();
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ export const initialState = {
 | 
			
		||||
  pagination: {
 | 
			
		||||
    total: 0,
 | 
			
		||||
  },
 | 
			
		||||
  initialParams: null,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const listViewReducer = (state = initialState, action) =>
 | 
			
		||||
@ -47,6 +48,7 @@ const listViewReducer = (state = initialState, action) =>
 | 
			
		||||
          contentType: state.contentType,
 | 
			
		||||
          initialDisplayedHeaders: state.initialDisplayedHeaders,
 | 
			
		||||
          displayedHeaders: state.displayedHeaders,
 | 
			
		||||
          initialParams: state.initialParams,
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -166,11 +168,12 @@ const listViewReducer = (state = initialState, action) =>
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case SET_LIST_LAYOUT: {
 | 
			
		||||
        const { contentType } = action.layout;
 | 
			
		||||
        const { contentType, displayedHeaders, initialParams } = action;
 | 
			
		||||
 | 
			
		||||
        drafState.contentType = contentType;
 | 
			
		||||
        drafState.displayedHeaders = contentType.layouts.list;
 | 
			
		||||
        drafState.initialDisplayedHeaders = contentType.layouts.list;
 | 
			
		||||
        drafState.displayedHeaders = displayedHeaders;
 | 
			
		||||
        drafState.initialDisplayedHeaders = displayedHeaders;
 | 
			
		||||
        drafState.initialParams = initialParams;
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@ describe('CONTENT MANAGER | CONTAINERS | ListView | reducer', () => {
 | 
			
		||||
      contentType: {},
 | 
			
		||||
      initialDisplayedHeaders: [],
 | 
			
		||||
      displayedHeaders: [],
 | 
			
		||||
      initialParams: null,
 | 
			
		||||
      pagination: {
 | 
			
		||||
        total: 0,
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Accepts an object of plugins options like: { i18n: { locale: 'en' }, other: {some: "value"}  }
 | 
			
		||||
 * and transform it into an array looking like: [{ i18n: { locale: 'en' }  }, { other: {some: "value"} }]
 | 
			
		||||
 */
 | 
			
		||||
const arrayOfPluginOptions = (pluginOptions = {}) =>
 | 
			
		||||
  Object.keys(pluginOptions || {}).map(key => ({ [key]: pluginOptions[key] }));
 | 
			
		||||
 | 
			
		||||
export default arrayOfPluginOptions;
 | 
			
		||||
@ -0,0 +1,26 @@
 | 
			
		||||
import { stringify } from 'qs';
 | 
			
		||||
import arrayOfPluginOptions from './arrayOfPluginOptions';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a valid query string from an object of queryParams
 | 
			
		||||
 * This includes:
 | 
			
		||||
 * - a _where clause
 | 
			
		||||
 * - plugin options
 | 
			
		||||
 */
 | 
			
		||||
const buildQueryString = (queryParams = {}) => {
 | 
			
		||||
  const pluginOptionArray = arrayOfPluginOptions(queryParams.pluginOptions);
 | 
			
		||||
  const _where = queryParams._where || [];
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Extracting pluginOptions from the query since we don't want them to be part
 | 
			
		||||
   * of the url
 | 
			
		||||
   */
 | 
			
		||||
  const { pluginOptions: _, ...otherQueryParams } = {
 | 
			
		||||
    ...queryParams,
 | 
			
		||||
    _where: _where.concat(pluginOptionArray),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return `?${stringify(otherQueryParams, { encode: false })}`;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default buildQueryString;
 | 
			
		||||
@ -1,2 +1,4 @@
 | 
			
		||||
export { default as getAllAllowedHeaders } from './getAllAllowedHeaders';
 | 
			
		||||
export { default as getFirstSortableHeader } from './getFirstSortableHeader';
 | 
			
		||||
export { default as arrayOfPluginOptions } from './arrayOfPluginOptions';
 | 
			
		||||
export { default as buildQueryString } from './buildQueryString';
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,61 @@
 | 
			
		||||
import buildQueryString from '../buildQueryString';
 | 
			
		||||
 | 
			
		||||
describe('buildQueryString', () => {
 | 
			
		||||
  it('creates a valid query string with default params', () => {
 | 
			
		||||
    const queryParams = {
 | 
			
		||||
      page: '1',
 | 
			
		||||
      pageSize: '10',
 | 
			
		||||
      _sort: 'name:ASC',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const queryString = buildQueryString(queryParams);
 | 
			
		||||
 | 
			
		||||
    expect(queryString).toBe('?page=1&pageSize=10&_sort=name:ASC');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('creates a valid query string with default params & plugin options', () => {
 | 
			
		||||
    const queryParams = {
 | 
			
		||||
      page: '1',
 | 
			
		||||
      pageSize: '10',
 | 
			
		||||
      _sort: 'name:ASC',
 | 
			
		||||
      pluginOptions: {
 | 
			
		||||
        i18n: { locale: 'en' },
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const queryString = buildQueryString(queryParams);
 | 
			
		||||
 | 
			
		||||
    expect(queryString).toBe('?page=1&pageSize=10&_sort=name:ASC&_where[0][i18n][locale]=en');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('creates a valid query string with a _where clause', () => {
 | 
			
		||||
    const queryParams = {
 | 
			
		||||
      page: '1',
 | 
			
		||||
      pageSize: '10',
 | 
			
		||||
      _sort: 'name:ASC',
 | 
			
		||||
      _where: [{ name: 'hello world' }],
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const queryString = buildQueryString(queryParams);
 | 
			
		||||
 | 
			
		||||
    expect(queryString).toBe('?page=1&pageSize=10&_sort=name:ASC&_where[0][name]=hello world');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('creates a valid query string with a _where and plugin options', () => {
 | 
			
		||||
    const queryParams = {
 | 
			
		||||
      page: '1',
 | 
			
		||||
      pageSize: '10',
 | 
			
		||||
      _sort: 'name:ASC',
 | 
			
		||||
      _where: [{ name: 'hello world' }],
 | 
			
		||||
      pluginOptions: {
 | 
			
		||||
        i18n: { locale: 'en' },
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const queryString = buildQueryString(queryParams);
 | 
			
		||||
 | 
			
		||||
    expect(queryString).toBe(
 | 
			
		||||
      '?page=1&pageSize=10&_sort=name:ASC&_where[0][name]=hello world&_where[1][i18n][locale]=en'
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -14,6 +14,7 @@ const dtoFields = [
 | 
			
		||||
  'options',
 | 
			
		||||
  'pluginOptions',
 | 
			
		||||
  'attributes',
 | 
			
		||||
  'pluginOptions',
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ import { useSelector } from 'react-redux';
 | 
			
		||||
import { Picker, Padded, Text, Flex } from '@buffetjs/core';
 | 
			
		||||
import { Carret } from 'strapi-helper-plugin';
 | 
			
		||||
import styled from 'styled-components';
 | 
			
		||||
import get from 'lodash/get';
 | 
			
		||||
 | 
			
		||||
const List = styled.ul`
 | 
			
		||||
  list-style-type: none;
 | 
			
		||||
@ -33,10 +34,22 @@ const EllipsisParagraph = styled(Text)`
 | 
			
		||||
  text-align: left;
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
const selectContentManagerListViewPluginOptions = state =>
 | 
			
		||||
  state.get('content-manager_listView').contentType.pluginOptions;
 | 
			
		||||
 | 
			
		||||
const selectI18NLocales = state => state.get('i18n_locales').locales;
 | 
			
		||||
 | 
			
		||||
const LocalePicker = () => {
 | 
			
		||||
  const locales = useSelector(state => state.get('i18n_locales').locales);
 | 
			
		||||
  const pluginOptions = useSelector(selectContentManagerListViewPluginOptions);
 | 
			
		||||
  const locales = useSelector(selectI18NLocales);
 | 
			
		||||
  const [selected, setSelected] = useState(locales && locales[0]);
 | 
			
		||||
 | 
			
		||||
  const isFieldLocalized = get(pluginOptions, 'i18n.localized', false);
 | 
			
		||||
 | 
			
		||||
  if (!isFieldLocalized) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!locales || locales.length === 0) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,11 @@
 | 
			
		||||
import extendCTBInitialDataMiddleware from './extendCTBInitialDataMiddleware';
 | 
			
		||||
import extendCTBAttributeInitialDataMiddleware from './extendCTBAttributeInitialDataMiddleware';
 | 
			
		||||
import localeQueryParamsMiddleware from './localeQueryParamsMiddleware';
 | 
			
		||||
 | 
			
		||||
const middlewares = [extendCTBInitialDataMiddleware, extendCTBAttributeInitialDataMiddleware];
 | 
			
		||||
const middlewares = [
 | 
			
		||||
  extendCTBInitialDataMiddleware,
 | 
			
		||||
  extendCTBAttributeInitialDataMiddleware,
 | 
			
		||||
  localeQueryParamsMiddleware,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default middlewares;
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,25 @@
 | 
			
		||||
import get from 'lodash/get';
 | 
			
		||||
 | 
			
		||||
const localeQueryParamsMiddleware = () => () => next => action => {
 | 
			
		||||
  if (action.type !== 'ContentManager/ListView/SET_LIST_LAYOUT ') {
 | 
			
		||||
    return next(action);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const isFieldLocalized = get(action, 'contentType.pluginOptions.i18n.localized', false);
 | 
			
		||||
 | 
			
		||||
  if (!isFieldLocalized) {
 | 
			
		||||
    return next(action);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (action.initialParams.pluginOptions) {
 | 
			
		||||
    action.initialParams.pluginOptions.locale = 'en';
 | 
			
		||||
  } else {
 | 
			
		||||
    action.initialParams.pluginOptions = {
 | 
			
		||||
      locale: 'en',
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return next(action);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default localeQueryParamsMiddleware;
 | 
			
		||||
@ -0,0 +1,86 @@
 | 
			
		||||
import localeQueryParamsMiddleware from '../localeQueryParamsMiddleware';
 | 
			
		||||
 | 
			
		||||
describe('localeQueryParamsMiddleware', () => {
 | 
			
		||||
  it('does nothing on unknown actions', () => {
 | 
			
		||||
    const middleware = localeQueryParamsMiddleware()();
 | 
			
		||||
    const nextFn = jest.fn();
 | 
			
		||||
    const action = { type: 'UNKNOWN' };
 | 
			
		||||
 | 
			
		||||
    middleware(nextFn)(action);
 | 
			
		||||
 | 
			
		||||
    expect(nextFn).toBeCalledWith(action);
 | 
			
		||||
    expect(action).toEqual({
 | 
			
		||||
      type: 'UNKNOWN',
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('does nothing when there s no i18n.localized key in the action', () => {
 | 
			
		||||
    const middleware = localeQueryParamsMiddleware()();
 | 
			
		||||
    const nextFn = jest.fn();
 | 
			
		||||
    const action = {
 | 
			
		||||
      type: 'ContentManager/ListView/SET_LIST_LAYOUT ',
 | 
			
		||||
      contentType: { pluginOptions: {} },
 | 
			
		||||
 | 
			
		||||
      initialParams: {},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    middleware(nextFn)(action);
 | 
			
		||||
 | 
			
		||||
    expect(nextFn).toBeCalledWith(action);
 | 
			
		||||
    expect(action).toEqual({
 | 
			
		||||
      contentType: { pluginOptions: {} },
 | 
			
		||||
      initialParams: {},
 | 
			
		||||
      type: 'ContentManager/ListView/SET_LIST_LAYOUT ',
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('creates a pluginOptions key with a locale when initialParams does not have a pluginOptions key and the field is localized', () => {
 | 
			
		||||
    const middleware = localeQueryParamsMiddleware()();
 | 
			
		||||
    const nextFn = jest.fn();
 | 
			
		||||
    const action = {
 | 
			
		||||
      type: 'ContentManager/ListView/SET_LIST_LAYOUT ',
 | 
			
		||||
      contentType: {
 | 
			
		||||
        pluginOptions: {
 | 
			
		||||
          i18n: { localized: true },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      initialParams: {},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    middleware(nextFn)(action);
 | 
			
		||||
 | 
			
		||||
    expect(nextFn).toBeCalledWith(action);
 | 
			
		||||
    expect(action).toEqual({
 | 
			
		||||
      contentType: { pluginOptions: { i18n: { localized: true } } },
 | 
			
		||||
      initialParams: { pluginOptions: { locale: 'en' } },
 | 
			
		||||
      type: 'ContentManager/ListView/SET_LIST_LAYOUT ',
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('adds a key to pluginOptions with a locale when initialParams has a pluginOptions key and the field is localized', () => {
 | 
			
		||||
    const middleware = localeQueryParamsMiddleware()();
 | 
			
		||||
    const nextFn = jest.fn();
 | 
			
		||||
    const action = {
 | 
			
		||||
      type: 'ContentManager/ListView/SET_LIST_LAYOUT ',
 | 
			
		||||
      contentType: {
 | 
			
		||||
        pluginOptions: {
 | 
			
		||||
          i18n: { localized: true },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      initialParams: {
 | 
			
		||||
        pluginOptions: {
 | 
			
		||||
          hello: 'world',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    middleware(nextFn)(action);
 | 
			
		||||
 | 
			
		||||
    expect(nextFn).toBeCalledWith(action);
 | 
			
		||||
    expect(action).toEqual({
 | 
			
		||||
      contentType: { pluginOptions: { i18n: { localized: true } } },
 | 
			
		||||
      initialParams: { pluginOptions: { locale: 'en', hello: 'world' } },
 | 
			
		||||
      type: 'ContentManager/ListView/SET_LIST_LAYOUT ',
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user