mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 02:44:55 +00:00
Merge pull request #10373 from strapi/cm/settings-reducer
Move listview settings reducer and add tests
This commit is contained in:
commit
2ac8a411f9
@ -32,7 +32,7 @@ const ListSettingsView = ({ layout, slug, updateLayout }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { emitEvent, updateMenu } = useGlobalContext();
|
||||
const toggleModalForm = () => setIsModalFormOpen(prevState => !prevState);
|
||||
const { labelForm, labelToEdit, initialData, modifiedData } = reducerState.toJS();
|
||||
const { labelForm, labelToEdit, initialData, modifiedData } = reducerState;
|
||||
const attributes = useMemo(() => {
|
||||
return get(modifiedData, ['attributes'], {});
|
||||
}, [modifiedData]);
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import { fromJS } from 'immutable';
|
||||
|
||||
const init = (initialState, layout) => {
|
||||
return fromJS({
|
||||
...initialState.toJS(),
|
||||
return {
|
||||
...initialState,
|
||||
initialData: layout,
|
||||
modifiedData: layout,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export default init;
|
||||
|
||||
@ -1,77 +1,95 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import produce, { current } from 'immer';
|
||||
import set from 'lodash/set';
|
||||
import get from 'lodash/get';
|
||||
|
||||
const initialState = fromJS({
|
||||
const initialState = {
|
||||
labelForm: {},
|
||||
labelToEdit: '',
|
||||
initialData: {},
|
||||
modifiedData: {},
|
||||
status: 'resolved',
|
||||
});
|
||||
|
||||
const reducer = (state, action) => {
|
||||
const layoutPath = ['modifiedData', 'layouts', 'list'];
|
||||
|
||||
switch (action.type) {
|
||||
case 'ADD_FIELD':
|
||||
return state.updateIn(layoutPath, list => list.push(action.item));
|
||||
|
||||
case 'MOVE_FIELD':
|
||||
return state.updateIn(['modifiedData', 'layouts', 'list'], list => {
|
||||
return list
|
||||
.delete(action.originalIndex)
|
||||
.insert(action.atIndex, list.get(action.originalIndex));
|
||||
});
|
||||
case 'ON_CHANGE':
|
||||
return state.updateIn(['modifiedData', ...action.keys.split('.')], () => action.value);
|
||||
case 'ON_CHANGE_LABEL_METAS':
|
||||
return state.updateIn(['labelForm', action.name], () => action.value);
|
||||
case 'ON_RESET':
|
||||
return state.update('modifiedData', () => state.get('initialData'));
|
||||
case 'REMOVE_FIELD': {
|
||||
const defaultSortByPath = ['modifiedData', 'settings', 'defaultSortBy'];
|
||||
const defaultSortBy = state.getIn(defaultSortByPath);
|
||||
const attrPath = ['modifiedData', 'layouts', 'list', action.index];
|
||||
const attrToBeRemoved = state.getIn(attrPath);
|
||||
|
||||
const firstAttr = state.getIn(['modifiedData', 'layouts', 'list', 1]);
|
||||
const firstAttrType = state.getIn(['modifiedData', 'attributes', firstAttr, 'type']);
|
||||
const attrToSelect =
|
||||
firstAttrType !== 'media' && firstAttrType !== 'richtext' ? firstAttr : 'id';
|
||||
|
||||
return state
|
||||
.removeIn(['modifiedData', 'layouts', 'list', action.index])
|
||||
.updateIn(defaultSortByPath, () => {
|
||||
if (attrToBeRemoved === defaultSortBy) {
|
||||
return attrToSelect;
|
||||
}
|
||||
|
||||
return defaultSortBy;
|
||||
});
|
||||
}
|
||||
case 'SET_LABEL_TO_EDIT':
|
||||
return state
|
||||
.update('labelToEdit', () => action.labelToEdit)
|
||||
.updateIn(['labelForm', 'label'], () =>
|
||||
state.getIn(['modifiedData', 'metadatas', action.labelToEdit, 'list', 'label'])
|
||||
)
|
||||
.updateIn(['labelForm', 'sortable'], () =>
|
||||
state.getIn(['modifiedData', 'metadatas', action.labelToEdit, 'list', 'sortable'])
|
||||
);
|
||||
case 'UNSET_LABEL_TO_EDIT':
|
||||
return state.update('labelToEdit', () => '').update('labelForm', () => fromJS({}));
|
||||
case 'SUBMIT_LABEL_FORM': {
|
||||
const metaPath = ['modifiedData', 'metadatas', state.get('labelToEdit'), 'list'];
|
||||
|
||||
return state
|
||||
.updateIn([...metaPath, 'label'], () => state.getIn(['labelForm', 'label']))
|
||||
.updateIn([...metaPath, 'sortable'], () => state.getIn(['labelForm', 'sortable']));
|
||||
}
|
||||
case 'SUBMIT_SUCCEEDED':
|
||||
return state.update('initialData', () => state.get('modifiedData'));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const reducer = (state = initialState, action) =>
|
||||
// eslint-disable-next-line consistent-return
|
||||
produce(state, draftState => {
|
||||
const layoutFieldListPath = ['modifiedData', 'layouts', 'list'];
|
||||
switch (action.type) {
|
||||
case 'ADD_FIELD': {
|
||||
const layoutFieldList = get(state, layoutFieldListPath, []);
|
||||
set(draftState, layoutFieldListPath, [...layoutFieldList, action.item]);
|
||||
break;
|
||||
}
|
||||
case 'MOVE_FIELD': {
|
||||
const layoutFieldList = get(state, layoutFieldListPath, []);
|
||||
const { originalIndex, atIndex } = action;
|
||||
|
||||
if (
|
||||
layoutFieldList.length > 1 &&
|
||||
originalIndex <= layoutFieldList.length &&
|
||||
atIndex <= layoutFieldList.length
|
||||
) {
|
||||
const item = layoutFieldList.splice(action.originalIndex, 1);
|
||||
layoutFieldList.splice(action.atIndex, 0, item[0]);
|
||||
set(draftState, layoutFieldListPath, layoutFieldList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'ON_CHANGE': {
|
||||
set(draftState, ['modifiedData', ...action.keys.split('.')], action.value);
|
||||
break;
|
||||
}
|
||||
case 'ON_CHANGE_LABEL_METAS': {
|
||||
set(draftState, ['labelForm', action.name], action.value);
|
||||
break;
|
||||
}
|
||||
case 'ON_RESET': {
|
||||
draftState.modifiedData = state.initialData;
|
||||
break;
|
||||
}
|
||||
case 'REMOVE_FIELD': {
|
||||
const layoutFieldList = get(state, layoutFieldListPath, []);
|
||||
set(
|
||||
draftState,
|
||||
layoutFieldListPath,
|
||||
layoutFieldList.filter((_, index) => action.index !== index)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'SET_LABEL_TO_EDIT': {
|
||||
const { labelToEdit } = action;
|
||||
draftState.labelToEdit = labelToEdit;
|
||||
draftState.labelForm.label = get(
|
||||
current(draftState),
|
||||
['modifiedData', 'metadatas', labelToEdit, 'list', 'label'],
|
||||
''
|
||||
);
|
||||
draftState.labelForm.sortable = get(
|
||||
current(draftState),
|
||||
['modifiedData', 'metadatas', labelToEdit, 'list', 'sortable'],
|
||||
''
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'UNSET_LABEL_TO_EDIT': {
|
||||
draftState.labelToEdit = '';
|
||||
draftState.labelForm = {};
|
||||
break;
|
||||
}
|
||||
case 'SUBMIT_LABEL_FORM': {
|
||||
const fieldMetadataPath = ['modifiedData', 'metadatas', state.labelToEdit, 'list'];
|
||||
set(draftState, [...fieldMetadataPath, 'label'], state.labelForm.label);
|
||||
set(draftState, [...fieldMetadataPath, 'sortable'], state.labelForm.sortable);
|
||||
break;
|
||||
}
|
||||
case 'SUBMIT_SUCCEEDED': {
|
||||
draftState.initialData = state.modifiedData;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return draftState;
|
||||
}
|
||||
});
|
||||
|
||||
export default reducer;
|
||||
export { initialState };
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import init from '../init';
|
||||
|
||||
describe('CONTENT MANAGER | containers | ListSettingsView | init', () => {
|
||||
@ -11,7 +10,7 @@ describe('CONTENT MANAGER | containers | ListSettingsView | init', () => {
|
||||
initialData: { foo: 'bar' },
|
||||
};
|
||||
|
||||
const result = init(fromJS(initialState), layout).toJS();
|
||||
const result = init(initialState, layout);
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
@ -0,0 +1,330 @@
|
||||
import reducer from '../reducer';
|
||||
|
||||
describe('CONTENT MANAGER | CONTAINERS | ListView | reducer', () => {
|
||||
let state;
|
||||
|
||||
beforeEach(() => {
|
||||
state = {
|
||||
labelForm: {},
|
||||
labelToEdit: '',
|
||||
initialData: {},
|
||||
modifiedData: {},
|
||||
status: 'resolved',
|
||||
};
|
||||
});
|
||||
|
||||
it('should handle the default action correctly', () => {
|
||||
const expected = state;
|
||||
|
||||
expect(reducer(state, {})).toEqual(expected);
|
||||
});
|
||||
|
||||
describe('ADD_FIELD', () => {
|
||||
it('should add a field to the layout correctly', () => {
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {
|
||||
layouts: {
|
||||
list: ['title'],
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'ADD_FIELD', item: 'title' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('MOVE_FIELD', () => {
|
||||
it('should replace the title by the description and vice-versa', () => {
|
||||
state.modifiedData = {
|
||||
layouts: {
|
||||
list: ['id', 'description', 'title'],
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {
|
||||
layouts: {
|
||||
list: ['id', 'title', 'description'],
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'MOVE_FIELD', atIndex: 1, originalIndex: 2 };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
it('should not change the field list if 1 item', () => {
|
||||
state.modifiedData = {
|
||||
layouts: {
|
||||
list: ['id'],
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {
|
||||
layouts: {
|
||||
list: ['id'],
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'MOVE_FIELD', atIndex: 1, originalIndex: 2 };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
it('should not change the field list if indices are wrong', () => {
|
||||
state.modifiedData = {
|
||||
layouts: {
|
||||
list: ['id', 'description', 'id'],
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {
|
||||
layouts: {
|
||||
list: ['id', 'description', 'id'],
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'MOVE_FIELD', atIndex: 5, originalIndex: 7 };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ON_CHANGE', () => {
|
||||
it('should set the value related to the passed keys', () => {
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {
|
||||
settings: {
|
||||
pageSize: 50,
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'ON_CHANGE', keys: 'settings.pageSize', value: 50 };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ON_CHANGE_LABEL_METAS', () => {
|
||||
it('should set the attribute metas label in the label form', () => {
|
||||
const expected = {
|
||||
...state,
|
||||
labelForm: {
|
||||
label: 'Cover',
|
||||
},
|
||||
};
|
||||
const action = { type: 'ON_CHANGE_LABEL_METAS', name: 'label', value: 'Cover' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ON_RESET', () => {
|
||||
it('should set the current modified data to the initial state', () => {
|
||||
state.modifiedData = {
|
||||
layouts: {
|
||||
list: ['id', 'description', 'title'],
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {},
|
||||
};
|
||||
const action = { type: 'ON_RESET' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('REMOVE_FIELD', () => {
|
||||
it('should remove the field', () => {
|
||||
state.modifiedData = {
|
||||
layouts: {
|
||||
list: ['id', 'description', 'title'],
|
||||
},
|
||||
settings: {
|
||||
defaultSortBy: 'id',
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
modifiedData: {
|
||||
layouts: {
|
||||
list: ['id', 'title'],
|
||||
},
|
||||
settings: {
|
||||
defaultSortBy: 'id',
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'REMOVE_FIELD', index: 1 };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SET_LABEL_TO_EDIT', () => {
|
||||
it('should set the label form data of the field to edit', () => {
|
||||
state.modifiedData = {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
labelToEdit: 'cover',
|
||||
labelForm: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
modifiedData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'SET_LABEL_TO_EDIT', labelToEdit: 'cover' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('UNSET_LABEL_TO_EDIT', () => {
|
||||
it('should unset the label to edit and clean the label form', () => {
|
||||
state = {
|
||||
...state,
|
||||
labelToEdit: 'cover',
|
||||
labelForm: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
modifiedData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
labelToEdit: '',
|
||||
labelForm: {},
|
||||
modifiedData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'UNSET_LABEL_TO_EDIT', labelToEdit: 'cover' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SUBMIT_LABEL_FORM', () => {
|
||||
it('should submit the label and the sortable value of the field to edit', () => {
|
||||
state = {
|
||||
...state,
|
||||
labelToEdit: 'cover',
|
||||
labelForm: {
|
||||
label: 'New Cover',
|
||||
sortable: true,
|
||||
},
|
||||
modifiedData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
labelToEdit: 'cover',
|
||||
labelForm: {
|
||||
label: 'New Cover',
|
||||
sortable: true,
|
||||
},
|
||||
modifiedData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'New Cover',
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'SUBMIT_LABEL_FORM', labelToEdit: 'cover' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SUBMIT_SUCCEEDED', () => {
|
||||
it('should submit the label and the sortable value of the field to edit', () => {
|
||||
state.modifiedData = {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const expected = {
|
||||
...state,
|
||||
initialData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
modifiedData: {
|
||||
metadatas: {
|
||||
cover: {
|
||||
list: {
|
||||
label: 'Cover',
|
||||
sortable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const action = { type: 'SUBMIT_SUCCEEDED' };
|
||||
|
||||
expect(reducer(state, action)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user