Temp commit before layout refacto

Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
soupette 2020-11-03 17:07:56 +01:00
parent 5c11e0aeb8
commit b834aea0c9
9 changed files with 244 additions and 281 deletions

View File

@ -124,6 +124,7 @@ module.exports = {
'react/destructuring-assignment': 0,
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
'react/forbid-prop-types': 0,
'react/no-unused-prop-types': 2,
'react/jsx-props-no-spreading': 0,
'react/jsx-one-expression-per-line': 0,
'react/state-in-constructor': 0,

View File

@ -8,17 +8,17 @@ const EditSettingsView = lazy(() => import('../EditSettingsView'));
const ListView = lazy(() => import('../ListView'));
const ListSettingsView = lazy(() => import('../ListSettingsView'));
const CollectionTypeRecursivePath = props => {
const CollectionTypeRecursivePath = () => {
const { url } = useRouteMatch();
const { slug } = useParams();
const renderRoute = (routeProps, Component) => {
return <Component {...props} {...routeProps} slug={slug} />;
return <Component {...routeProps} slug={slug} />;
};
const renderPermissionsRoute = (routeProps, Component) => {
return (
<CheckPagePermissions permissions={pluginPermissions.collectionTypesConfigurations}>
<Component {...props} {...routeProps} slug={slug} />
<Component {...routeProps} slug={slug} />
</CheckPagePermissions>
);
};

View File

@ -11,6 +11,7 @@ import {
generateFiltersFromSearch,
request,
CheckPermissions,
useGlobalContext,
useUserPermissions,
useQuery,
} from 'strapi-helper-plugin';
@ -26,11 +27,12 @@ import {
import DisplayedFieldsDropdown from '../../components/DisplayedFieldsDropdown';
import Container from '../../components/Container';
import CustomTable from '../../components/CustomTable';
import FilterPicker from '../../components/FilterPicker';
// import FilterPicker from '../../components/FilterPicker';
import Search from '../../components/Search';
import State from '../../components/State';
import ListViewProvider from '../ListViewProvider';
import { onChangeListLabels, resetListLabels } from '../Main/actions';
// import { onChangeListLabels, resetListLabels } from '../Main/actions';
import { AddFilterCta, FilterIcon, Wrapper } from './components';
import Filter from './Filter';
import Footer from './Footer';
@ -52,11 +54,15 @@ import makeSelectListView from './selectors';
/* eslint-disable react/no-array-index-key */
const FilterPicker = () => <div>FILTER</div>;
const onChangeListLabels = () => console.log('todo');
const resetListLabels = () => console.log('todo');
function ListView({
count,
data,
didDeleteData,
emitEvent,
// emitEvent,
entriesToDelete,
isLoading,
location: { pathname },
@ -80,6 +86,7 @@ function ListView({
toggleModalDelete,
toggleModalDeleteAll,
}) {
const { emitEvent } = useGlobalContext();
const viewPermissions = useMemo(() => generatePermissionsObject(slug), [slug]);
const {
isLoading: isLoadingForPermissions,
@ -656,7 +663,7 @@ ListView.propTypes = {
count: PropTypes.number.isRequired,
data: PropTypes.array.isRequired,
didDeleteData: PropTypes.bool.isRequired,
emitEvent: PropTypes.func.isRequired,
// emitEvent: PropTypes.func.isRequired,
entriesToDelete: PropTypes.array.isRequired,
isLoading: PropTypes.bool.isRequired,
layouts: PropTypes.object,
@ -664,7 +671,7 @@ ListView.propTypes = {
pathname: PropTypes.string.isRequired,
search: PropTypes.string.isRequired,
}).isRequired,
models: PropTypes.array.isRequired,
// models: PropTypes.array.isRequired,
getData: PropTypes.func.isRequired,
getDataSucceeded: PropTypes.func.isRequired,
history: PropTypes.shape({

View File

@ -1,61 +1,75 @@
import {
DELETE_LAYOUT,
DELETE_LAYOUTS,
// DELETE_LAYOUT,
// DELETE_LAYOUTS,
GET_DATA,
GET_DATA_SUCCEEDED,
GET_LAYOUT_SUCCEEDED,
ON_CHANGE_LIST_LABELS,
RESET_LIST_LABELS,
// GET_LAYOUT_SUCCEEDED,
// ON_CHANGE_LIST_LABELS,
// RESET_LIST_LABELS,
RESET_PROPS,
} from './constants';
export function deleteLayout(uid) {
return {
type: DELETE_LAYOUT,
uid,
};
}
// export function deleteLayout(uid) {
// return {
// type: DELETE_LAYOUT,
// uid,
// };
// }
export function deleteLayouts() {
return {
type: DELETE_LAYOUTS,
};
}
// export function deleteLayouts() {
// return {
// type: DELETE_LAYOUTS,
// };
// }
export function getDataSucceeded(components, models, mainFields) {
return {
type: GET_DATA_SUCCEEDED,
components,
models: models.filter(model => model.isDisplayed === true),
mainFields,
};
}
// export function getDataSucceeded(components, models, mainFields) {
// return {
// type: GET_DATA_SUCCEEDED,
// components,
// models: models.filter(model => model.isDisplayed === true),
// mainFields,
// };
// }
export function getLayoutSucceeded(layout, uid) {
return {
type: GET_LAYOUT_SUCCEEDED,
layout,
uid,
};
}
// export function getLayoutSucceeded(layout, uid) {
// return {
// type: GET_LAYOUT_SUCCEEDED,
// layout,
// uid,
// };
// }
export function onChangeListLabels({ target: { name, slug, value } }) {
return {
type: ON_CHANGE_LIST_LABELS,
name,
slug,
value,
};
}
// export function onChangeListLabels({ target: { name, slug, value } }) {
// return {
// type: ON_CHANGE_LIST_LABELS,
// name,
// slug,
// value,
// };
// }
export function resetListLabels(slug) {
return {
type: RESET_LIST_LABELS,
slug,
};
}
// export function resetListLabels(slug) {
// return {
// type: RESET_LIST_LABELS,
// slug,
// };
// }
export function resetProps() {
return {
type: RESET_PROPS,
};
}
// export function resetProps() {
// return {
// type: RESET_PROPS,
// };
// }
//
export const getData = () => ({
type: GET_DATA,
});
export const getDataSucceeded = (models, components) => ({
type: GET_DATA_SUCCEEDED,
components,
models,
});
export const resetProps = () => ({ type: RESET_PROPS });

View File

@ -1,7 +1,9 @@
export const DELETE_LAYOUT = 'ContentManager/Main/DELETE_LAYOUT';
export const DELETE_LAYOUTS = 'ContentManager/Main/DELETE_LAYOUTS';
export const GET_DATA = 'ContentManager/Main/GET_DATA';
export const GET_DATA_SUCCEEDED = 'ContentManager/Main/GET_DATA_SUCCEEDED';
export const GET_LAYOUT_SUCCEEDED = 'ContentManager/Main/GET_LAYOUT_SUCCEEDED';
export const ON_CHANGE_LIST_LABELS = 'ContentManager/Main/ON_CHANGE_LIST_LABELS';
export const RESET_LIST_LABELS = 'ContentManager/Main/RESET_LIST_LABELS';
export const RESET_PROPS = 'ContentManager/Main/RESET_PROPS';
// export const DELETE_LAYOUT = 'ContentManager/Main/DELETE_LAYOUT';
// export const DELETE_LAYOUTS = 'ContentManager/Main/DELETE_LAYOUTS';
// export const GET_LAYOUT_SUCCEEDED = 'ContentManager/Main/GET_LAYOUT_SUCCEEDED';
// export const ON_CHANGE_LIST_LABELS = 'ContentManager/Main/ON_CHANGE_LIST_LABELS';
// export const RESET_LIST_LABELS = 'ContentManager/Main/RESET_LIST_LABELS';

View File

@ -1,186 +1,105 @@
import React, { Suspense, lazy, useEffect, useRef } from 'react';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux';
import { Switch, Route, useRouteMatch } from 'react-router-dom';
import {
LoadingIndicatorPage,
useGlobalContext,
request,
CheckPagePermissions,
} from 'strapi-helper-plugin';
import { Switch, Route } from 'react-router-dom';
import { LoadingIndicatorPage, request, CheckPagePermissions } from 'strapi-helper-plugin';
import { DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import pluginId from '../../pluginId';
import pluginPermissions from '../../permissions';
import DragLayer from '../../components/DragLayer';
import getRequestUrl from '../../utils/getRequestUrl';
import createPossibleMainFieldsForModelsAndComponents from './utils/createPossibleMainFieldsForModelsAndComponents';
import {
deleteLayout,
deleteLayouts,
getDataSucceeded,
getLayoutSucceeded,
resetProps,
} from './actions';
import CollectionTypeRecursivePath from '../CollectionTypeRecursivePath';
import EditSettingsView from '../EditSettingsView';
import SingleTypeRecursivePath from '../SingleTypeRecursivePath';
// import createPossibleMainFieldsForModelsAndComponents from './utils/createPossibleMainFieldsForModelsAndComponents';
import { getData, getDataSucceeded, resetProps } from './actions';
import makeSelectMain from './selectors';
const EditSettingsView = lazy(() => import('../EditSettingsView'));
const CollectionTypeRecursivePath = lazy(() => import('../CollectionTypeRecursivePath'));
const SingleTypeRecursivePath = lazy(() => import('../SingleTypeRecursivePath'));
function Main({
deleteLayout,
deleteLayouts,
getDataSucceeded,
getLayoutSucceeded,
components,
componentsAndModelsMainPossibleMainFields,
isLoading,
layouts,
location: { pathname },
global: { currentEnvironment, plugins },
models,
resetProps,
}) {
const { emitEvent } = useGlobalContext();
const {
params: { slug },
} = useRouteMatch('/plugins/content-manager/:contentType/:slug');
const getDataRef = useRef();
const getLayoutRef = useRef();
const resetPropsRef = useRef();
getDataRef.current = async () => {
try {
const [{ data: components }, { data: models }] = await Promise.all(
['components', 'content-types'].map(endPoint =>
request(getRequestUrl(endPoint), { method: 'GET' })
)
);
getDataSucceeded(components, models, {
...createPossibleMainFieldsForModelsAndComponents(components),
...createPossibleMainFieldsForModelsAndComponents(models),
});
} catch (err) {
strapi.notification.error('notification.error');
}
};
getLayoutRef.current = async uid => {
try {
const { data: layout } = await request(getRequestUrl(`content-types/${uid}`), {
method: 'GET',
});
getLayoutSucceeded(layout, uid);
} catch (err) {
strapi.notification.error('notification.error');
}
};
resetPropsRef.current = resetProps;
// TODO change the layouts logic
const shouldShowLoader = !pathname.includes('ctm-configurations/') && layouts[slug] === undefined;
// const EditSettingsView = lazy(() => import('../EditSettingsView'));
// const CollectionTypeRecursivePath = lazy(() => import('../CollectionTypeRecursivePath'));
// const SingleTypeRecursivePath = lazy(() => import('../SingleTypeRecursivePath'));
function Main({ getData, getDataSucceeded, isLoading, resetProps }) {
useEffect(() => {
getDataRef.current();
const abortController = new AbortController();
const { signal } = abortController;
const fetchData = async signal => {
getData();
console.log('up');
try {
const [{ data: components }, { data: models }] = await Promise.all(
['components', 'content-types'].map(endPoint =>
request(getRequestUrl(endPoint), { method: 'GET', signal })
)
);
getDataSucceeded(models, components);
} catch (err) {
console.error('CM/main', err);
// TODO: new notif API
strapi.notification.error('notification.error');
}
};
fetchData(signal);
return () => {
resetPropsRef.current();
abortController.abort();
resetProps();
};
}, [getDataRef]);
}, [getData, getDataSucceeded, resetProps]);
// This effect is fetching the layout of each content type, however the logic of fetching a specific
// ct has been re introduced in the EditView with the useFetchContentType hook this causes, sometimes, the layout to be fetched twice
// I am leaving this legacy for now and will redo the logic when the back-end when the endpoints for the single types and the collection types will be split
useEffect(() => {
if (shouldShowLoader) {
getLayoutRef.current(slug);
}
}, [getLayoutRef, shouldShowLoader, slug]);
if (isLoading || shouldShowLoader) {
if (isLoading) {
return <LoadingIndicatorPage />;
}
const renderRoute = (props, Component) => (
<Component
currentEnvironment={currentEnvironment}
deleteLayout={deleteLayout}
deleteLayouts={deleteLayouts}
emitEvent={emitEvent}
components={components}
componentsAndModelsMainPossibleMainFields={componentsAndModelsMainPossibleMainFields}
layouts={layouts}
models={models}
plugins={plugins}
{...props}
/>
);
const routes = [
{ path: 'singleType/:slug', comp: SingleTypeRecursivePath },
{ path: 'collectionType/:slug', comp: CollectionTypeRecursivePath },
].map(({ path, comp }) => (
<Route
key={path}
path={`/plugins/${pluginId}/${path}`}
render={props => renderRoute(props, comp)}
/>
<Route key={path} path={`/plugins/${pluginId}/${path}`} component={comp} />
));
return (
<DndProvider backend={HTML5Backend}>
<DragLayer />
<Suspense fallback={<LoadingIndicatorPage />}>
<Switch>
<Route
path={`/plugins/${pluginId}/ctm-configurations/edit-settings/:type/:componentSlug`}
render={routeProps => (
<CheckPagePermissions permissions={pluginPermissions.componentsConfigurations}>
<EditSettingsView
currentEnvironment={currentEnvironment}
deleteLayout={deleteLayout}
deleteLayouts={deleteLayouts}
emitEvent={emitEvent}
components={components}
componentsAndModelsMainPossibleMainFields={
componentsAndModelsMainPossibleMainFields
}
layouts={layouts}
models={models}
plugins={plugins}
{...routeProps}
/>
</CheckPagePermissions>
)}
/>
{routes}
</Switch>
</Suspense>
<Switch>
<Route
path={`/plugins/${pluginId}/ctm-configurations/edit-settings/:type/:componentSlug`}
render={routeProps => (
<CheckPagePermissions permissions={pluginPermissions.componentsConfigurations}>
<EditSettingsView
// currentEnvironment={currentEnvironment}
// deleteLayout={deleteLayout}
// deleteLayouts={deleteLayouts}
// emitEvent={emitEvent}
// components={components}
// componentsAndModelsMainPossibleMainFields={
// componentsAndModelsMainPossibleMainFields
// }
// layouts={layouts}
// models={models}
// plugins={plugins}
{...routeProps}
/>
</CheckPagePermissions>
)}
/>
{routes}
</Switch>
</DndProvider>
);
}
Main.propTypes = {
deleteLayout: PropTypes.func.isRequired,
deleteLayouts: PropTypes.func.isRequired,
getData: PropTypes.func.isRequired,
getDataSucceeded: PropTypes.func.isRequired,
getLayoutSucceeded: PropTypes.func.isRequired,
global: PropTypes.shape({
currentEnvironment: PropTypes.string.isRequired,
plugins: PropTypes.object,
}).isRequired,
components: PropTypes.array.isRequired,
componentsAndModelsMainPossibleMainFields: PropTypes.object.isRequired,
isLoading: PropTypes.bool.isRequired,
layouts: PropTypes.object.isRequired,
location: PropTypes.shape({
pathname: PropTypes.string.isRequired,
search: PropTypes.string,
}).isRequired,
models: PropTypes.array.isRequired,
resetProps: PropTypes.func.isRequired,
};
@ -189,10 +108,8 @@ const mapStateToProps = makeSelectMain();
export function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
deleteLayout,
deleteLayouts,
getData,
getDataSucceeded,
getLayoutSucceeded,
resetProps,
},
dispatch

View File

@ -2,68 +2,97 @@
*
* main reducer
*/
import { fromJS } from 'immutable';
/* eslint-disable consistent-return */
import produce from 'immer';
import {
DELETE_LAYOUT,
DELETE_LAYOUTS,
// DELETE_LAYOUT,
// DELETE_LAYOUTS,
GET_DATA,
GET_DATA_SUCCEEDED,
GET_LAYOUT_SUCCEEDED,
ON_CHANGE_LIST_LABELS,
RESET_LIST_LABELS,
// GET_LAYOUT_SUCCEEDED,
// ON_CHANGE_LIST_LABELS,
// RESET_LIST_LABELS,
RESET_PROPS,
} from './constants';
// import { fromJS } from 'immutable';
export const initialState = fromJS({
componentsAndModelsMainPossibleMainFields: {},
const initialState = {
// TODO!
// componentsAndModelsMainPossibleMainFields: {},
// TODO!
components: [],
initialLayouts: {},
isLoading: true,
layouts: {},
models: [],
});
};
function mainReducer(state = initialState, action) {
switch (action.type) {
case DELETE_LAYOUT:
return state.removeIn(['layouts', action.uid]);
case DELETE_LAYOUTS:
return state.update('layouts', () => fromJS({}));
case GET_DATA_SUCCEEDED:
return state
.update('components', () => fromJS(action.components))
.update('models', () => fromJS(action.models))
.update('componentsAndModelsMainPossibleMainFields', () =>
fromJS(action.mainFields)
)
.update('isLoading', () => false);
case GET_LAYOUT_SUCCEEDED:
return state
.updateIn(['layouts', action.uid], () => fromJS(action.layout))
.updateIn(['initialLayouts', action.uid], () => fromJS(action.layout));
case ON_CHANGE_LIST_LABELS: {
const { name, slug, value } = action;
return state.updateIn(
['layouts', slug, 'contentType', 'layouts', 'list'],
list => {
if (value) {
return list.push(name);
}
return list.filter(l => l !== name);
}
);
const mainReducer = (state = initialState, action) =>
produce(state, draftState => {
switch (action.type) {
case GET_DATA: {
draftState.isLoading = true;
break;
}
case GET_DATA_SUCCEEDED: {
draftState.isLoading = false;
draftState.components = action.components;
draftState.models = action.models;
break;
}
case RESET_PROPS: {
draftState = initialState;
break;
}
default:
return draftState;
}
case RESET_LIST_LABELS:
return state.updateIn(['layouts', action.slug], () =>
state.getIn(['initialLayouts', action.slug])
);
case RESET_PROPS:
return initialState;
default:
return state;
}
}
});
// export const initialState = fromJS({
// componentsAndModelsMainPossibleMainFields: {},
// components: [],
// initialLayouts: {},
// isLoading: true,
// layouts: {},
// models: [],
// });
// function mainReducer(state = initialState, action) {
// switch (action.type) {
// case DELETE_LAYOUT:
// return state.removeIn(['layouts', action.uid]);
// case DELETE_LAYOUTS:
// return state.update('layouts', () => fromJS({}));
// case GET_DATA_SUCCEEDED:
// return state
// .update('components', () => fromJS(action.components))
// .update('models', () => fromJS(action.models))
// .update('componentsAndModelsMainPossibleMainFields', () => fromJS(action.mainFields))
// .update('isLoading', () => false);
// case GET_LAYOUT_SUCCEEDED:
// return state
// .updateIn(['layouts', action.uid], () => fromJS(action.layout))
// .updateIn(['initialLayouts', action.uid], () => fromJS(action.layout));
// case ON_CHANGE_LIST_LABELS: {
// const { name, slug, value } = action;
// return state.updateIn(['layouts', slug, 'contentType', 'layouts', 'list'], list => {
// if (value) {
// return list.push(name);
// }
// return list.filter(l => l !== name);
// });
// }
// case RESET_LIST_LABELS:
// return state.updateIn(['layouts', action.slug], () =>
// state.getIn(['initialLayouts', action.slug])
// );
// case RESET_PROPS:
// return initialState;
// default:
// return state;
// }
// }
export default mainReducer;
export { initialState };

View File

@ -2,29 +2,20 @@ import { createSelector } from 'reselect';
import pluginId from '../../pluginId';
import { initialState } from './reducer';
/**
* Direct selector to the main state domain
*/
const selectMainDomain = () => state => state.get(`${pluginId}_main`) || initialState;
/**
* Other specific selectors
*/
/**
* Default selector used by Main
*/
const selectMainDomain = () => state => {
return state.get(`${pluginId}_main`) || initialState;
};
const makeSelectMain = () =>
createSelector(selectMainDomain(), substate => {
return substate.toJS();
return substate;
});
const makeSelectModels = () =>
createSelector(selectMainDomain(), substate => {
const allModels = substate.get('models').toJS();
const { models } = substate;
return allModels.filter(model => model.isDisplayed === true).map(({ uid }) => uid);
return models.filter(model => model.isDisplayed === true).map(({ uid }) => uid);
});
export default makeSelectMain;

View File

@ -1,3 +1,5 @@
// TODO
import { get } from 'lodash';
const createPossibleMainFieldsForModelsAndComponents = array => {