@@ -300,9 +298,9 @@ export const Default = {
-
Opened and with immutable items :
-
-
+
Opened and with plain object items :
+
),
diff --git a/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.container.js b/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.container.js
index c1907aafce6..1491d849fd3 100644
--- a/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.container.js
+++ b/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.container.js
@@ -1,16 +1,12 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
-import Immutable from 'immutable';
export function addPathsToCollection(index, collection, paths, jsonpath) {
- return collection.set(index, paths.push(jsonpath));
+ return { ...collection, [index]: [...paths, jsonpath] };
}
export function removePathsFromCollection(index, collection, paths, jsonpath) {
- return collection.set(
- index,
- paths.filter(path => path !== jsonpath),
- );
+ return { ...collection, [index]: paths.filter(path => path !== jsonpath) };
}
/**
@@ -51,23 +47,23 @@ export default class TreeManager extends Component {
this.state = {
isAllExpanded: props.isAllExpanded || false,
- collapsedNodes: props.collapsedNodes || Immutable.Map(),
- expandedNodes: props.expandedNodes || Immutable.Map().set(0, Immutable.List(['$'])),
+ collapsedNodes: props.collapsedNodes || {},
+ expandedNodes: props.expandedNodes || { 0: ['$'] },
};
}
onExpandAll = () => {
- this.setState(oldState => ({
+ this.setState({
isAllExpanded: true,
- collapsedNodes: oldState.collapsedNodes.clear(),
- }));
+ collapsedNodes: {},
+ });
};
onCollapseAll = () => {
- this.setState(oldState => ({
+ this.setState({
isAllExpanded: false,
- expandedNodes: oldState.expandedNodes.clear(),
- }));
+ expandedNodes: {},
+ });
};
onToggle = (event, options, index) => {
@@ -88,7 +84,7 @@ export default class TreeManager extends Component {
index,
collection,
isAllExpanded,
- collection.get(index, Immutable.List()),
+ collection[index] ?? [],
options,
),
});
@@ -98,7 +94,7 @@ export default class TreeManager extends Component {
index,
collection,
isAllExpanded,
- collection.get(index, Immutable.List()),
+ collection[index] ?? [],
options,
),
});
@@ -115,7 +111,7 @@ export default class TreeManager extends Component {
onToggle: this.onToggle,
onCollapseAll: this.onCollapseAll,
onExpandAll: this.onExpandAll,
- paths: isAllExpanded ? this.state.collapsedNodes.toJS() : this.state.expandedNodes.toJS(),
+ paths: isAllExpanded ? this.state.collapsedNodes : this.state.expandedNodes,
highlighted: this.props.highlighted,
isAllExpanded,
};
diff --git a/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.test.jsx b/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.test.jsx
index a9d4ce332ca..d483b56576d 100644
--- a/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.test.jsx
+++ b/packages/components/src/DataViewer/Managers/TreeManager/TreeManager.test.jsx
@@ -1,7 +1,5 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import Immutable from 'immutable';
-
import TreeManager, {
addPathsToCollection,
removePathsFromCollection,
@@ -9,19 +7,19 @@ import TreeManager, {
describe('addPathsToCollection', () => {
it('should add the jsonpath to the paths collection', () => {
- const myMap = Immutable.Map();
- const myList = Immutable.List();
+ const myMap = {};
+ const myList = [];
const newMap = addPathsToCollection(0, myMap, myList, 'jsonpath');
- expect(newMap.get(0).toJS()).toEqual(['jsonpath']);
+ expect(newMap[0]).toEqual(['jsonpath']);
});
});
describe('removePathsFromCollection', () => {
it('should remove the jsonpath to the paths collection', () => {
- const myList = Immutable.List(['jsonpath', 'somestuff']);
- const myMap = Immutable.Map({ 0: myList });
+ const myList = ['jsonpath', 'somestuff'];
+ const myMap = { 0: myList };
const newCollection = removePathsFromCollection(0, myMap, myList, 'jsonpath');
- expect(newCollection.get(0).toJS()).toEqual(['somestuff']);
+ expect(newCollection[0]).toEqual(['somestuff']);
});
});
diff --git a/packages/components/src/HeaderBar/HeaderBar.stories.jsx b/packages/components/src/HeaderBar/HeaderBar.stories.jsx
index a314d23c18f..b75d94664de 100644
--- a/packages/components/src/HeaderBar/HeaderBar.stories.jsx
+++ b/packages/components/src/HeaderBar/HeaderBar.stories.jsx
@@ -1,5 +1,4 @@
/* eslint-disable no-console */
-import Immutable from 'immutable';
import assetsApi from '@talend/assets-api';
import tokens from '@talend/design-tokens';
import AppSwitcher from '../AppSwitcher';
@@ -102,7 +101,7 @@ export default meta;
export const Default = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
return
;
},
parameters: { info: { styles: infoStyle } },
@@ -110,7 +109,7 @@ export const Default = {
export const WithFullLogo = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.logo.isFull = true;
return
;
},
@@ -119,10 +118,10 @@ export const WithFullLogo = {
export const WithoutProducts = {
render: () => {
- const headerProps = Immutable.fromJS({
+ const headerProps = structuredClone({
...props,
products: null,
- }).toJS();
+ });
headerProps.logo.isFull = true;
return
;
},
@@ -131,13 +130,13 @@ export const WithoutProducts = {
export const WithBrandIcon = {
render: () => {
- const headerProps = Immutable.fromJS({
+ const headerProps = structuredClone({
...props,
brand: {
...props.brand,
icon: 'talend-tmc-negative',
},
- }).toJS();
+ });
return
;
},
parameters: { info: { styles: infoStyle } },
@@ -145,13 +144,13 @@ export const WithBrandIcon = {
export const WithBrandIconUrl = {
render: () => {
- const headerProps = Immutable.fromJS({
+ const headerProps = structuredClone({
...props,
brand: {
...props.brand,
iconUrl: assetsApi.getURL('/src/svg/products/tmc-negative.svg', '@talend/icons'),
},
- }).toJS();
+ });
return
;
},
parameters: { info: { styles: infoStyle } },
@@ -159,7 +158,7 @@ export const WithBrandIconUrl = {
export const WithEnvironmentDropdown = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.env = {
id: 'header-environment',
items: [
@@ -177,7 +176,7 @@ export const WithEnvironmentDropdown = {
export const WithUnreadNotifications = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.notification = {
hasUnread: true,
};
@@ -188,7 +187,7 @@ export const WithUnreadNotifications = {
export const WithReadNotifications = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.notification = {
hasUnread: false,
};
@@ -199,7 +198,7 @@ export const WithReadNotifications = {
export const WithHelpSplitDropdown = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.help.items = [
{
icon: 'talend-board',
@@ -219,7 +218,7 @@ export const WithHelpSplitDropdown = {
export const WithCallToAction = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.callToAction = {
bsStyle: 'info',
className: 'btn-inverse',
@@ -234,7 +233,7 @@ export const WithCallToAction = {
export const WithGenericAction = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.genericAction = {
bsStyle: 'link',
id: 'header-generic-action',
@@ -249,7 +248,7 @@ export const WithGenericAction = {
export const WithoutUserAndWithInformation = {
render: () => {
- const headerProps = Immutable.fromJS(props).toJS();
+ const headerProps = structuredClone(props);
headerProps.user = null;
headerProps.information = {
id: 'header-info',
diff --git a/packages/components/src/test-setup.js b/packages/components/src/test-setup.js
index 330c81b7444..3051abaa1c6 100644
--- a/packages/components/src/test-setup.js
+++ b/packages/components/src/test-setup.js
@@ -21,6 +21,16 @@ vi.mock('@talend/utils', async () => {
globalThis.jest = vi;
globalThis.xit = it.skip;
+// Node v25+ declares `localStorage` on globalThis, which prevents vitest/jsdom from
+// overriding it with jsdom's Storage. Use the JSDOM instance directly to fix this.
+const jsdomLocalStorage = globalThis.jsdom?.window?.localStorage;
+if (jsdomLocalStorage) {
+ Object.defineProperty(globalThis, 'localStorage', {
+ configurable: true,
+ value: jsdomLocalStorage,
+ });
+}
+
// Suppress React warnings in tests, as they are not relevant to the test results and can clutter the output.
const originalConsoleError = console.error;
vi.spyOn(console, 'error').mockImplementation((...args) => {
diff --git a/packages/containers/.storybook/cmfModule/index.js b/packages/containers/.storybook/cmfModule/index.js
index 080161a2cb6..2998b5065a2 100644
--- a/packages/containers/.storybook/cmfModule/index.js
+++ b/packages/containers/.storybook/cmfModule/index.js
@@ -1,4 +1,3 @@
-import { fromJS } from 'immutable';
import actionCreators from './actionCreators';
import components from './components';
import expressions from './expressions';
@@ -15,7 +14,7 @@ const cmfModule = {
modules: [containersModule],
preloadedState: {
cmf: {
- collections: fromJS({
+ collections: {
with: {
data: [
{
@@ -122,7 +121,7 @@ const cmfModule = {
},
],
},
- }),
+ },
},
},
};
diff --git a/packages/containers/package.json b/packages/containers/package.json
index 8b0f12847aa..2a1c5de5461 100644
--- a/packages/containers/package.json
+++ b/packages/containers/package.json
@@ -51,11 +51,9 @@
"@talend/react-forms": "^16.1.1",
"@talend/utils": "^3.7.1",
"classnames": "^2.5.1",
- "immutable": "^3.8.2",
"invariant": "^2.2.4",
"lodash": "^4.17.23",
"memoize-one": "^6.0.0",
- "react-immutable-proptypes": "^2.2.0",
"redux-saga": "^1.4.2",
"reselect": "^2.5.4"
},
diff --git a/packages/containers/src/AboutDialog/AboutDialog.container.jsx b/packages/containers/src/AboutDialog/AboutDialog.container.jsx
index 589390db39b..568ceb1c276 100644
--- a/packages/containers/src/AboutDialog/AboutDialog.container.jsx
+++ b/packages/containers/src/AboutDialog/AboutDialog.container.jsx
@@ -1,14 +1,13 @@
import { Component as RComponent } from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
-import { Map } from 'immutable';
import { cmfConnect } from '@talend/react-cmf';
import Component from '@talend/react-components/lib/AboutDialog';
import Constants from './AboutDialog.constant';
-export const DEFAULT_STATE = new Map({
+export const DEFAULT_STATE = {
expanded: false,
-});
+};
class AboutDialog extends RComponent {
static displayName = 'Container(AboutDialog)';
@@ -26,7 +25,7 @@ class AboutDialog extends RComponent {
}
toggle() {
- this.props.setState(({ state }) => ({ expanded: !state.get('expanded') }));
+ this.props.setState(({ state }) => ({ expanded: !state?.expanded }));
}
hide() {
@@ -39,9 +38,9 @@ class AboutDialog extends RComponent {
);
diff --git a/packages/containers/src/AboutDialog/AboutDialog.test.js b/packages/containers/src/AboutDialog/AboutDialog.test.js
index 3ace64157b7..56a49584ad7 100644
--- a/packages/containers/src/AboutDialog/AboutDialog.test.js
+++ b/packages/containers/src/AboutDialog/AboutDialog.test.js
@@ -1,6 +1,5 @@
-import { Map, List } from 'immutable';
-
import Container from './AboutDialog.container';
+
import Connected, { mapStateToProps } from './AboutDialog.connect';
import Constants from './AboutDialog.constant';
@@ -13,11 +12,7 @@ describe('Connected AboutDialog', () => {
it('should mapStateToProps with an empty list of products', () => {
const state = {
cmf: {
- collections: new Map({
- AboutDialog: {
- [Constants.COLLECTION_ID]: new List(),
- },
- }),
+ collections: {},
},
};
const ownProps = {};
diff --git a/packages/containers/src/ActionDropdown/ActionDropdown.connect.jsx b/packages/containers/src/ActionDropdown/ActionDropdown.connect.jsx
index 14e8bdd992c..7e9c11bf6cf 100644
--- a/packages/containers/src/ActionDropdown/ActionDropdown.connect.jsx
+++ b/packages/containers/src/ActionDropdown/ActionDropdown.connect.jsx
@@ -1,5 +1,4 @@
import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
import cmf, { cmfConnect } from '@talend/react-cmf';
import { ActionDropdown } from '@talend/react-components/lib/Actions';
import omit from 'lodash/omit';
@@ -50,7 +49,7 @@ export function ContainerActionDropdown({ items, ...props }) {
ContainerActionDropdown.displayName = 'Container(ActionDropdown)';
ContainerActionDropdown.propTypes = {
- items: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), ImmutablePropTypes.list]),
+ items: PropTypes.arrayOf(PropTypes.object),
noCaret: PropTypes.bool,
pullRight: PropTypes.bool,
hideLabel: PropTypes.bool,
diff --git a/packages/containers/src/ActionDropdown/ActionDropdown.stories.jsx b/packages/containers/src/ActionDropdown/ActionDropdown.stories.jsx
index 7acc636b1da..4df59b65ab2 100644
--- a/packages/containers/src/ActionDropdown/ActionDropdown.stories.jsx
+++ b/packages/containers/src/ActionDropdown/ActionDropdown.stories.jsx
@@ -1,5 +1,4 @@
/* eslint-disable react/prop-types */
-import Immutable from 'immutable';
import { action } from 'storybook/actions';
import ActionDropdown from '.';
@@ -45,7 +44,7 @@ export function Default({ onSelect }) {
displayMode: 'dropdown',
label: 'my immutable items',
onSelect,
- items: Immutable.fromJS([
+ items: [
{
id: 'item1',
label: 'First immutable label',
@@ -54,7 +53,7 @@ export function Default({ onSelect }) {
id: 'item2',
label: '2nd immutable',
},
- ]),
+ ],
};
return (
diff --git a/packages/containers/src/AppLoader/AppLoader.connect.jsx b/packages/containers/src/AppLoader/AppLoader.connect.jsx
index 23b2a2c8569..43796e71fd5 100644
--- a/packages/containers/src/AppLoader/AppLoader.connect.jsx
+++ b/packages/containers/src/AppLoader/AppLoader.connect.jsx
@@ -51,8 +51,8 @@ AppLoaderContainer.propTypes = {
*/
export function mapStateToProps(state, ownProps) {
return {
- loading: !get(ownProps, 'hasCollections', []).every(collectionName =>
- state.cmf.collections.has(collectionName),
+ loading: !get(ownProps, 'hasCollections', []).every(
+ collectionName => collectionName in state.cmf.collections,
),
};
}
diff --git a/packages/containers/src/AppLoader/AppLoader.connect.test.js b/packages/containers/src/AppLoader/AppLoader.connect.test.js
index f2feea27f5a..c8aac1d2a0c 100644
--- a/packages/containers/src/AppLoader/AppLoader.connect.test.js
+++ b/packages/containers/src/AppLoader/AppLoader.connect.test.js
@@ -1,4 +1,3 @@
-import Immutable from 'immutable';
import { render, screen } from '@testing-library/react';
import { AppLoaderContainer, mapStateToProps } from './AppLoader.connect';
@@ -27,7 +26,7 @@ describe('AppLoader container', () => {
describe('mapStateToProps', () => {
it('should return loading to false if we have nothing to wait', () => {
// given
- const state = { cmf: { collections: Immutable.Map() } };
+ const state = { cmf: { collections: {} } };
const ownProps = {};
// when
const result = mapStateToProps(state, ownProps);
@@ -37,7 +36,7 @@ describe('AppLoader container', () => {
it('should return loading to true if there is something to wait', () => {
// given
- const state = { cmf: { collections: Immutable.Map({ test2: Immutable.Map() }) } };
+ const state = { cmf: { collections: { test2: null } } };
const ownProps = { hasCollections: ['test', 'test2'] };
// when
const result = mapStateToProps(state, ownProps);
@@ -49,7 +48,7 @@ describe('AppLoader container', () => {
// given
const state = {
cmf: {
- collections: Immutable.Map({ test2: Immutable.Map(), test: Immutable.Map() }),
+ collections: { test2: null, test: null },
},
};
const ownProps = { hasCollections: ['test', 'test2'] };
diff --git a/packages/containers/src/Breadcrumbs/Breadcrumbs.connect.jsx b/packages/containers/src/Breadcrumbs/Breadcrumbs.connect.jsx
index 33c006c34e0..d8b6013dbe6 100644
--- a/packages/containers/src/Breadcrumbs/Breadcrumbs.connect.jsx
+++ b/packages/containers/src/Breadcrumbs/Breadcrumbs.connect.jsx
@@ -1,11 +1,10 @@
import { cmfConnect } from '@talend/react-cmf';
-import { Map } from 'immutable';
import Breadcrumbs from '@talend/react-components/lib/Breadcrumbs';
-const DEFAULT_STATE = Map();
+const DEFAULT_STATE = {};
export function ContainerBreadcrumbs({ state = DEFAULT_STATE, dispatchActionCreator, ...props }) {
- const items = state.get('items', props.items);
+ const items = state?.items ?? props.items;
const newProps = {
...props,
items:
@@ -14,8 +13,8 @@ export function ContainerBreadcrumbs({ state = DEFAULT_STATE, dispatchActionCrea
...item,
onClick: (event, data) => dispatchActionCreator(item.actionCreator, event, data),
})),
- loading: state.get('loading', props.loading),
- maxItems: state.get('maxItems', props.maxItems),
+ loading: state?.loading ?? props.loading,
+ maxItems: state?.maxItems ?? props.maxItems,
};
return
;
@@ -28,7 +27,7 @@ ContainerBreadcrumbs.propTypes = {
};
export default cmfConnect({
- defaultState: Map({ items: [], maxItems: 10 }),
+ defaultState: { items: [], maxItems: 10 },
omitCMFProps: true,
withComponentRegistry: true,
withDispatchActionCreator: true,
diff --git a/packages/containers/src/Breadcrumbs/Breadcrumbs.stories.jsx b/packages/containers/src/Breadcrumbs/Breadcrumbs.stories.jsx
index 9eb97fb4039..a84c24c91da 100644
--- a/packages/containers/src/Breadcrumbs/Breadcrumbs.stories.jsx
+++ b/packages/containers/src/Breadcrumbs/Breadcrumbs.stories.jsx
@@ -1,7 +1,6 @@
-import { Map } from 'immutable';
import Breadcrumbs from '.';
-const initialState = new Map({
+const initialState = {
items: [
{ text: 'Text A', title: 'Text title A', actionCreator: 'breadcrumb:folder:openA' },
{ text: 'Text B', title: 'Text title B', actionCreator: 'breadcrumb:folder:openB' },
@@ -12,7 +11,7 @@ const initialState = new Map({
},
],
maxItems: 3,
-});
+};
export default {
title: 'Breadcrumb',
diff --git a/packages/containers/src/ComponentForm/ComponentForm.component.jsx b/packages/containers/src/ComponentForm/ComponentForm.component.jsx
index 02c01815e5b..7af449e4e26 100644
--- a/packages/containers/src/ComponentForm/ComponentForm.component.jsx
+++ b/packages/containers/src/ComponentForm/ComponentForm.component.jsx
@@ -4,7 +4,6 @@ import cmf, { cmfConnect } from '@talend/react-cmf';
import Form from '@talend/react-forms';
import omit from 'lodash/omit';
import get from 'lodash/get';
-import { Map } from 'immutable';
import memoizeOne from 'memoize-one';
import kit from './kit';
import tcompFieldsWidgets from './fields';
@@ -20,19 +19,19 @@ const TO_OMIT = [
...cmfConnect.INJECTED_PROPS,
];
-export const DEFAULT_STATE = new Map({
+export const DEFAULT_STATE = {
dirty: false,
- initialState: new Map(),
-});
+ initialState: {},
+};
/**
- * Convert immutable object to js object
+ * Returns object or null
*/
-export function toJS(immutableObject) {
- if (!immutableObject) {
+export function toJS(object) {
+ if (!object) {
return null;
}
- return immutableObject.toJS();
+ return object;
}
/**
@@ -102,9 +101,9 @@ export class TCompForm extends Component {
}
componentDidUpdate(prevProps) {
- const nextProperties = this.props.state.get('properties');
- if (prevProps.state.get('properties') !== nextProperties) {
- this.setState({ properties: nextProperties?.toJS() || {} });
+ const nextProperties = this.props.state.properties;
+ if (prevProps.state.properties !== nextProperties) {
+ this.setState({ properties: nextProperties || {} });
}
if (
@@ -123,7 +122,7 @@ export class TCompForm extends Component {
}
onChange(_, payload) {
- if (!this.props.state.get('dirty')) {
+ if (!this.props.state.dirty) {
this.props.setState({ dirty: true });
}
@@ -184,15 +183,15 @@ export class TCompForm extends Component {
}
onReset() {
- this.props.setState(prev =>
- prev.state
- .set('jsonSchema', this.props.state.getIn(['initialState', 'jsonSchema']))
- .set('uiSchema', this.props.state.getIn(['initialState', 'uiSchema']))
- .set('properties', this.props.state.getIn(['initialState', 'properties']))
- .set('dirty', false),
- );
+ const { initialState } = this.props.state;
+ this.props.setState({
+ jsonSchema: initialState?.jsonSchema,
+ uiSchema: initialState?.uiSchema,
+ properties: initialState?.properties,
+ dirty: false,
+ });
this.setState({
- properties: this.props.state.getIn(['initialState', 'properties']).toJS(),
+ properties: initialState?.properties || {},
});
}
@@ -213,8 +212,8 @@ export class TCompForm extends Component {
getUISpec() {
return {
properties: this.state.properties,
- jsonSchema: this.getMemoizedJsonSchema(this.props.state.get('jsonSchema')),
- uiSchema: this.getMemoizedUiSchema(this.props.state.get('uiSchema')),
+ jsonSchema: this.getMemoizedJsonSchema(this.props.state.jsonSchema),
+ uiSchema: this.getMemoizedUiSchema(this.props.state.uiSchema),
};
}
@@ -222,9 +221,9 @@ export class TCompForm extends Component {
const uiSpecs = this.getUISpec();
if (!uiSpecs.jsonSchema) {
- const response = this.props.state.get('response');
+ const response = this.props.state.response;
if (response) {
- return
{response.get('statusText')}
;
+ return
{response.statusText}
;
}
return
;
}
@@ -232,7 +231,7 @@ export class TCompForm extends Component {
const props = {
...omit(this.props, TO_OMIT),
data: uiSpecs,
- initialData: this.getMemoizedInitialState(this.props.state.get('initialState')),
+ initialData: this.getMemoizedInitialState(this.props.state.initialState),
onTrigger: this.onTrigger,
onChange: this.onChange,
onSubmit: this.onSubmit,
diff --git a/packages/containers/src/ComponentForm/ComponentForm.saga.test.js b/packages/containers/src/ComponentForm/ComponentForm.saga.test.js
index 7af55f47d89..69ca2a5a9b9 100644
--- a/packages/containers/src/ComponentForm/ComponentForm.saga.test.js
+++ b/packages/containers/src/ComponentForm/ComponentForm.saga.test.js
@@ -1,9 +1,8 @@
import { call, select, put } from 'redux-saga/effects';
-import { fromJS, Map } from 'immutable';
import cmf from '@talend/react-cmf';
import * as sagas from './ComponentForm.sagas';
-import ConnectedTCompForm, { TCompForm } from './ComponentForm.component';
+import { TCompForm } from './ComponentForm.component';
describe('ComponentForm saga', () => {
describe('*checkFormComponentId', () => {
@@ -72,14 +71,14 @@ describe('ComponentForm saga', () => {
const selector = selectJsonSchema.payload.selector;
const jsonSchemaSelection = selector({
cmf: {
- components: fromJS({
+ components: {
[TCompForm.displayName]: { [props.componentId]: { jsonSchema } },
- }),
+ },
},
});
// then
- expect(jsonSchemaSelection.toJS()).toEqual(jsonSchema);
+ expect(jsonSchemaSelection).toEqual(jsonSchema);
});
it('should NOT fetch uiSpec when it is already fetched', () => {
@@ -174,9 +173,9 @@ describe('ComponentForm saga', () => {
function getReduxStore() {
return {
cmf: {
- components: fromJS({
+ components: {
[TCompForm.displayName]: { [componentId]: {} },
- }),
+ },
},
};
}
@@ -231,19 +230,19 @@ describe('ComponentForm saga', () => {
const errorStep = gen.next({ response }).value;
expect(errorStep.payload).toBeDefined();
expect(errorStep.type).toBe('PUT');
- const setStateAction = errorStep.payload.action(null, getReduxStore);
+ const setStateAction = errorStep.payload.action;
// then
expect(setStateAction).toEqual({
cmf: {
componentState: {
componentName: 'ComponentForm',
- componentState: new Map({
+ componentState: {
jsonSchema: undefined,
uiSchema: undefined,
response,
dirty: false,
- }),
+ },
key: 'MyComponentId',
type: 'REACT_CMF.COMPONENT_MERGE_STATE',
},
@@ -348,15 +347,15 @@ describe('ComponentForm saga', () => {
describe('onFormSubmit', () => {
const componentId = 'form';
const prevState = {
- cmf: { components: fromJS({ [TCompForm.displayName]: { [componentId]: {} } }) },
+ cmf: { components: { [TCompForm.displayName]: { [componentId]: {} } } },
};
const mergeStatePayload = {
cmf: {
componentState: {
componentName: 'ComponentForm',
- componentState: fromJS({
+ componentState: {
initialState: { jsonSchema: undefined, uiSchema: undefined, properties: 'prop' },
- }),
+ },
key: 'form',
type: 'REACT_CMF.COMPONENT_MERGE_STATE',
},
@@ -441,15 +440,14 @@ describe('ComponentForm saga', () => {
// when
const gen = sagas.handleSetDirtyState({ componentId, dirty });
// then
- expect(gen.next().value).toEqual(select(ConnectedTCompForm.getState, componentId));
- expect(gen.next(Map({})).value).toEqual(
+ expect(gen.next().value).toEqual(
put({
cmf: {
componentState: {
componentName: 'ComponentForm',
- componentState: Map({
+ componentState: {
dirty: true,
- }),
+ },
key: 'myId',
type: 'REACT_CMF.COMPONENT_MERGE_STATE',
},
diff --git a/packages/containers/src/ComponentForm/ComponentForm.sagas.js b/packages/containers/src/ComponentForm/ComponentForm.sagas.js
index eab521a4e2c..d258d2e4960 100644
--- a/packages/containers/src/ComponentForm/ComponentForm.sagas.js
+++ b/packages/containers/src/ComponentForm/ComponentForm.sagas.js
@@ -1,6 +1,5 @@
import { call, put, select, take, takeEvery, takeLatest } from 'redux-saga/effects';
import cmf from '@talend/react-cmf';
-import { fromJS } from 'immutable';
import get from 'lodash/get';
import Component from './ComponentForm.component';
import { COMPONENT_FORM_SET_DIRTY } from './ComponentForm.actions';
@@ -13,8 +12,7 @@ export function* fetchDefinition(action) {
if (!response.ok) {
yield put(
Component.setStateAction(
- prev =>
- prev.set('jsonSchema').set('uiSchema').set('response', response).set('dirty', false),
+ { jsonSchema: undefined, uiSchema: undefined, response, dirty: false },
action.componentId,
),
);
@@ -45,9 +43,7 @@ export function* onDidMount({
uiSpecPath,
data,
}) {
- const jsonSchema = yield select(state =>
- Component.getState(state, componentId).get('jsonSchema'),
- );
+ const jsonSchema = yield select(state => Component.getState(state, componentId)?.jsonSchema);
if (!jsonSchema) {
if (definition) {
yield put(
@@ -74,11 +70,15 @@ export function* onFormSubmit(componentId, submitURL, action) {
}
yield put(
Component.setStateAction(
- prev =>
- prev
- .setIn(['initialState', 'jsonSchema'], prev.get('jsonSchema'))
- .setIn(['initialState', 'uiSchema'], prev.get('uiSchema'))
- .setIn(['initialState', 'properties'], fromJS(action.properties)),
+ prev => ({
+ ...prev,
+ initialState: {
+ ...(prev.initialState ?? {}),
+ jsonSchema: prev.jsonSchema,
+ uiSchema: prev.uiSchema,
+ properties: action.properties,
+ },
+ }),
componentId,
)(undefined, getReduxState),
);
@@ -111,8 +111,7 @@ export function checkFormComponentId(componentId, actionType) {
* @param {object} reduxAction with a componentId (string) & the dirtyState (boolean) to apply
*/
export function* handleSetDirtyState({ componentId, dirty }) {
- const componentFormState = yield select(Component.getState, componentId);
- yield put(Component.setStateAction(componentFormState.set('dirty', !!dirty), componentId));
+ yield put(Component.setStateAction({ dirty: !!dirty }, componentId));
}
export function* handle(props) {
diff --git a/packages/containers/src/ComponentForm/ComponentForm.selectors.js b/packages/containers/src/ComponentForm/ComponentForm.selectors.js
index fe4120b1073..9c36cdede70 100644
--- a/packages/containers/src/ComponentForm/ComponentForm.selectors.js
+++ b/packages/containers/src/ComponentForm/ComponentForm.selectors.js
@@ -1,7 +1,7 @@
import ConnectedComponentForm from './ComponentForm.component';
export function isComponentFormDirty(state, componentName) {
- return ConnectedComponentForm.getState(state, componentName).get('dirty', false);
+ return ConnectedComponentForm.getState(state, componentName)?.dirty ?? false;
}
export default isComponentFormDirty;
diff --git a/packages/containers/src/ComponentForm/ComponentForm.selectors.test.js b/packages/containers/src/ComponentForm/ComponentForm.selectors.test.js
index a96d2fa17b6..2f530b5ee30 100644
--- a/packages/containers/src/ComponentForm/ComponentForm.selectors.test.js
+++ b/packages/containers/src/ComponentForm/ComponentForm.selectors.test.js
@@ -1,4 +1,3 @@
-import Immutable from 'immutable';
import { isComponentFormDirty } from './ComponentForm.selectors';
import { TCompForm } from './ComponentForm.component';
@@ -9,11 +8,9 @@ describe('ComponentForm selectors', () => {
// given
const state = {
cmf: {
- components: Immutable.fromJS({
- [TCompForm.displayName]: {
- [componentName]: {},
- },
- }),
+ components: {
+ [TCompForm.displayName]: { [componentName]: {} },
+ },
},
};
// when
@@ -26,11 +23,9 @@ describe('ComponentForm selectors', () => {
// given
const state = {
cmf: {
- components: Immutable.fromJS({
- [TCompForm.displayName]: {
- [componentName]: { dirty: false },
- },
- }),
+ components: {
+ [TCompForm.displayName]: { [componentName]: { dirty: false } },
+ },
},
};
// when
@@ -43,11 +38,9 @@ describe('ComponentForm selectors', () => {
// given
const state = {
cmf: {
- components: Immutable.fromJS({
- [TCompForm.displayName]: {
- [componentName]: { dirty: true },
- },
- }),
+ components: {
+ [TCompForm.displayName]: { [componentName]: { dirty: true } },
+ },
},
};
// when
diff --git a/packages/containers/src/ComponentForm/ComponentForm.test.js b/packages/containers/src/ComponentForm/ComponentForm.test.js
index c928fff7cdf..3c18e0da754 100644
--- a/packages/containers/src/ComponentForm/ComponentForm.test.js
+++ b/packages/containers/src/ComponentForm/ComponentForm.test.js
@@ -1,5 +1,4 @@
import { render, screen } from '@testing-library/react';
-import { fromJS, Map } from 'immutable';
import cmf, { mock } from '@talend/react-cmf';
@@ -47,10 +46,10 @@ describe('ComponentForm', () => {
it('should return js object', () => {
// given
- const immutableObject = new Map({ a: 1, b: 2 });
+ const anObject = { a: 1, b: 2 };
// when
- const result = toJS(immutableObject);
+ const result = toJS(anObject);
// then
expect(result).toEqual({ a: 1, b: 2 });
@@ -313,7 +312,7 @@ describe('ComponentForm', () => {
describe('#render', () => {
it("should render a CircularProgress when we don't have the schema", () => {
// given
- const state = new Map({});
+ const state = {};
// when
render(
@@ -334,7 +333,7 @@ describe('ComponentForm', () => {
it('should render a response status', () => {
// given
- const state = fromJS({ response: { statusText: 'we had an error' } });
+ const state = { response: { statusText: 'we had an error' } };
// when
render(
@@ -353,7 +352,7 @@ describe('ComponentForm', () => {
it('should render a UIForm', () => {
// given
- const state = fromJS(addSchemaMock.ui);
+ const state = { ...addSchemaMock.ui };
// when
const { container } = render(
@@ -374,7 +373,7 @@ describe('ComponentForm', () => {
describe('#security', () => {
it('should pass security props to createTrigger', () => {
- const state = fromJS(addSchemaMock.ui);
+ const state = { ...addSchemaMock.ui };
const instance = new TCompForm({
state,
triggerURL: 'http://trigger',
@@ -391,7 +390,7 @@ describe('ComponentForm', () => {
describe('#update', () => {
it('should recreate trigger if triggerURL or customTriggers props change', () => {
// given
- const state = fromJS(addSchemaMock.ui);
+ const state = { ...addSchemaMock.ui };
const oldTriggerURL = 'http://old';
const newTriggerURL = 'http://new';
const oldCustomTriggers = { oldCustomReload: () => {} };
@@ -433,7 +432,7 @@ describe('ComponentForm', () => {
it('should dispatch new definitionURL props', () => {
// given
- const state = fromJS(addSchemaMock.ui);
+ const state = { ...addSchemaMock.ui };
const dispatch = jest.fn();
const oldUrl = 'http://old';
const newUrl = 'http://new';
@@ -460,7 +459,7 @@ describe('ComponentForm', () => {
});
describe('events', () => {
- const state = fromJS({ ...addSchemaMock.ui, initialState: addSchemaMock.ui });
+ const state = { ...addSchemaMock.ui, initialState: addSchemaMock.ui };
// extract type field schema
const typeSchema = {
@@ -501,10 +500,7 @@ describe('ComponentForm', () => {
it('should NOT dispatch dirty state if it is already dirty', () => {
// given
- const dirtyState = fromJS({
- ...addSchemaMock.ui,
- dirty: true,
- });
+ const dirtyState = { ...addSchemaMock.ui, dirty: true };
const setState = jest.fn();
const instance = new TCompForm({
state: dirtyState,
diff --git a/packages/containers/src/ConfirmDialog/ConfirmDialog.connect.js b/packages/containers/src/ConfirmDialog/ConfirmDialog.connect.js
index 4bf305a6e8e..54d973731ee 100644
--- a/packages/containers/src/ConfirmDialog/ConfirmDialog.connect.js
+++ b/packages/containers/src/ConfirmDialog/ConfirmDialog.connect.js
@@ -9,9 +9,9 @@ export function mapStateToProps(state, props, cmfProps) {
getState: () => state,
},
};
- const validateAction = cmfProps.state ? cmfProps.state.get('validateAction') : undefined;
- const cancelAction = cmfProps.state ? cmfProps.state.get('cancelAction') : undefined;
- const model = cmfProps.state ? cmfProps.state.get('model') : cmfProps.model;
+ const validateAction = cmfProps.state?.validateAction;
+ const cancelAction = cmfProps.state?.cancelAction;
+ const model = cmfProps.state?.model ?? cmfProps.model;
return {
validateAction: getActionsProps(context, validateAction, model),
cancelAction: getActionsProps(context, cancelAction, model),
diff --git a/packages/containers/src/ConfirmDialog/ConfirmDialog.container.jsx b/packages/containers/src/ConfirmDialog/ConfirmDialog.container.jsx
index 1752a20072c..8b61a03a67e 100644
--- a/packages/containers/src/ConfirmDialog/ConfirmDialog.container.jsx
+++ b/packages/containers/src/ConfirmDialog/ConfirmDialog.container.jsx
@@ -1,18 +1,17 @@
-import { Map } from 'immutable';
import omit from 'lodash/omit';
import Component from '@talend/react-components/lib/ConfirmDialog';
import { cmfConnect, useCMFContext } from '@talend/react-cmf';
import { getActionsProps } from '../actionAPI';
-export const DEFAULT_STATE = new Map({
+export const DEFAULT_STATE = {
show: false,
-});
+};
// eslint-disable-next-line react/prefer-stateless-function
function ConfirmDialog(props) {
const context = useCMFContext();
- const state = (props.state || DEFAULT_STATE).toJS();
+ const state = props.state || DEFAULT_STATE;
if (!state.validateAction || !state.cancelAction) {
return null;
}
diff --git a/packages/containers/src/ConfirmDialog/ConfirmDialog.stories.jsx b/packages/containers/src/ConfirmDialog/ConfirmDialog.stories.jsx
index 1ee0f3f3eb8..4a2687b1641 100644
--- a/packages/containers/src/ConfirmDialog/ConfirmDialog.stories.jsx
+++ b/packages/containers/src/ConfirmDialog/ConfirmDialog.stories.jsx
@@ -1,14 +1,13 @@
-import { Map } from 'immutable';
import ConfirmDialog from '.';
-const initialState = new Map({
+const initialState = {
size: 'small',
header: 'DO SOMETHING',
show: true,
children: 'Confirm this !',
validateAction: 'confirm-dialog:validate',
cancelAction: 'confirm-dialog:cancel',
-});
+};
export default {
title: 'ConfirmDialog',
diff --git a/packages/containers/src/ConfirmDialog/ConfirmDialog.test.jsx b/packages/containers/src/ConfirmDialog/ConfirmDialog.test.jsx
index 46ac3c92b66..bc2cd1c9c8f 100644
--- a/packages/containers/src/ConfirmDialog/ConfirmDialog.test.jsx
+++ b/packages/containers/src/ConfirmDialog/ConfirmDialog.test.jsx
@@ -1,6 +1,5 @@
/* eslint-disable react/prop-types */
/* eslint-disable react/display-name */
-import { fromJS, Map } from 'immutable';
import cmf, { mock } from '@talend/react-cmf';
import { render } from '@testing-library/react';
@@ -37,12 +36,12 @@ describe('Container ConfirmDialog', () => {
App = config.App;
});
it('should not render', () => {
- const state = new Map({
+ const state = {
size: 'small',
header: 'DO SOMETHING',
show: true,
children: 'Confirm this !',
- });
+ };
const { container } = render(
@@ -51,7 +50,7 @@ describe('Container ConfirmDialog', () => {
expect(container).toBeEmptyDOMElement();
});
it('should render', () => {
- const state = new Map({
+ const state = {
size: 'small',
header: 'DO SOMETHING',
show: true,
@@ -59,7 +58,7 @@ describe('Container ConfirmDialog', () => {
validateAction: 'menu:demo',
cancelAction: 'menu:demo',
model: { foo: 'bar' },
- });
+ };
const { container } = render(
@@ -77,14 +76,14 @@ describe('Connected ConfirmDialog', () => {
});
it('should set validateAction and cancelAction', () => {
- const cmfState = new Map({
+ const cmfState = {
size: 'small',
header: 'DO SOMETHING',
show: true,
children: 'Confirm this !',
validateAction: 'object:validate',
cancelAction: 'object:cancel',
- });
+ };
const state = mock.store.state();
state.cmf.settings.actions['object:validate'] = { name: 'foo' };
state.cmf.settings.actions['object:cancel'] = { name: 'foo1' };
@@ -98,15 +97,15 @@ describe('Connected ConfirmDialog', () => {
describe('ConfirmDialog.show/hide', () => {
it('should change the visibility to true in the state', () => {
const state = mock.store.state();
- state.cmf.components = fromJS({
+ state.cmf.components = {
ConfirmDialog: {
ConfirmDialog: {
show: false,
},
},
- });
+ };
- const dialog = new Map({
+ const dialog = {
size: 'small',
header: 'REMOVE SEMANTIC TYPE',
children: 'Are you sure you want to remove the semantic type ?',
@@ -114,7 +113,7 @@ describe('ConfirmDialog.show/hide', () => {
// these two actions are contained in show:remove:semantic action payload
validateAction: '',
cancelAction: '',
- });
+ };
const action = {
confirmDialogConf: dialog,
@@ -123,31 +122,25 @@ describe('ConfirmDialog.show/hide', () => {
const newState = showConfirmDialog(state, action);
expect(newState).not.toBe(state);
- const confirmDialoVisibility = newState.cmf.components.getIn([
- 'CMFContainer(ConfirmDialog)',
- 'ConfirmDialog',
- 'show',
- ]);
+ const confirmDialoVisibility =
+ newState.cmf.components?.['CMFContainer(ConfirmDialog)']?.['ConfirmDialog']?.show;
expect(confirmDialoVisibility).toBeTruthy();
});
it('should change the visibility to false in the state', () => {
const state = mock.store.state();
- state.cmf.components = fromJS({
+ state.cmf.components = {
ConfirmDialog: {
ConfirmDialog: {
show: true,
},
},
- });
+ };
const newState = hideConfirmDialog(state);
expect(newState).not.toBe(state);
- const confirmDialogVisibility = newState.cmf.components.getIn([
- 'CMFContainer(ConfirmDialog)',
- 'ConfirmDialog',
- 'show',
- ]);
+ const confirmDialogVisibility =
+ newState.cmf.components?.['CMFContainer(ConfirmDialog)']?.['ConfirmDialog']?.show;
expect(confirmDialogVisibility).toBeFalsy();
});
});
diff --git a/packages/containers/src/ConfirmDialog/showHideConfirmDialog.js b/packages/containers/src/ConfirmDialog/showHideConfirmDialog.js
index 01d92a4b6ff..51935094269 100644
--- a/packages/containers/src/ConfirmDialog/showHideConfirmDialog.js
+++ b/packages/containers/src/ConfirmDialog/showHideConfirmDialog.js
@@ -1,18 +1,40 @@
export function showConfirmDialog(state, action) {
// adding conf and showing modal
const path = ['CMFContainer(ConfirmDialog)', 'ConfirmDialog'];
- const newState = { ...state };
- newState.cmf.components = state.cmf.components.setIn(
- path,
- action.confirmDialogConf.set('show', true),
- );
- return newState;
+ const [containerName, dialogKey] = path;
+ return {
+ ...state,
+ cmf: {
+ ...state.cmf,
+ components: {
+ ...state.cmf.components,
+ [containerName]: {
+ ...(state.cmf.components[containerName] ?? {}),
+ [dialogKey]: { ...action.confirmDialogConf, show: true },
+ },
+ },
+ },
+ };
}
export function hideConfirmDialog(state) {
// hiding the modal
- const path = ['CMFContainer(ConfirmDialog)', 'ConfirmDialog', 'show'];
- const newState = { ...state };
- newState.cmf.components = state.cmf.components.setIn(path, false);
- return newState;
+ const containerName = 'CMFContainer(ConfirmDialog)';
+ const dialogKey = 'ConfirmDialog';
+ return {
+ ...state,
+ cmf: {
+ ...state.cmf,
+ components: {
+ ...state.cmf.components,
+ [containerName]: {
+ ...(state.cmf.components[containerName] ?? {}),
+ [dialogKey]: {
+ ...(state.cmf.components[containerName]?.[dialogKey] ?? {}),
+ show: false,
+ },
+ },
+ },
+ },
+ };
}
diff --git a/packages/containers/src/DeleteResource/DeleteResource.connect.js b/packages/containers/src/DeleteResource/DeleteResource.connect.js
index 6f3970497e1..03355cb5ca3 100644
--- a/packages/containers/src/DeleteResource/DeleteResource.connect.js
+++ b/packages/containers/src/DeleteResource/DeleteResource.connect.js
@@ -1,5 +1,4 @@
-import { cmfConnect } from '@talend/react-cmf';
-import Immutable from 'immutable';
+import cmf, { cmfConnect } from '@talend/react-cmf';
import get from 'lodash/get';
import Container from './DeleteResource.container';
@@ -16,9 +15,7 @@ export function mapStateToProps(state, ownProps) {
} else {
const collectionId = ownProps.collectionId || ownProps.resourceType;
if (collectionId) {
- props.resource = state.cmf.collections
- .get(collectionId, new Immutable.Map())
- .find(currentResource => currentResource.get('id') === resourceId);
+ props.resource = cmf.selectors.collections.getCollectionItem(state, collectionId, resourceId);
}
}
diff --git a/packages/containers/src/DeleteResource/DeleteResource.container.jsx b/packages/containers/src/DeleteResource/DeleteResource.container.jsx
index 0738759d131..946f37dd127 100644
--- a/packages/containers/src/DeleteResource/DeleteResource.container.jsx
+++ b/packages/containers/src/DeleteResource/DeleteResource.container.jsx
@@ -14,7 +14,7 @@ import CONSTANTS from './constants';
*/
function getLabel(resource) {
if (resource) {
- return resource.get('label') || resource.get('name') || '';
+ return resource.label || resource.name || '';
}
return '';
}
diff --git a/packages/containers/src/DeleteResource/DeleteResource.test.js b/packages/containers/src/DeleteResource/DeleteResource.test.js
index e57643bbf4b..2935e6a3758 100644
--- a/packages/containers/src/DeleteResource/DeleteResource.test.js
+++ b/packages/containers/src/DeleteResource/DeleteResource.test.js
@@ -1,18 +1,14 @@
import { render, screen } from '@testing-library/react';
import cmf, { mock } from '@talend/react-cmf';
-import Immutable from 'immutable';
import { DeleteResource } from './DeleteResource.container';
import Connected, { mapStateToProps } from './DeleteResource.connect';
const state = mock.store.state();
const settings = {};
-state.cmf = {
- settings,
-};
-state.cmf.collections = new Immutable.Map({
- foo: new Immutable.List([new Immutable.Map({ id: '123' })]),
-});
+state.cmf = { settings };
+const fooItem = { id: '123' };
+state.cmf.collections = { foo: [fooItem] };
describe('Container DeleteResource', () => {
let App;
@@ -27,7 +23,7 @@ describe('Container DeleteResource', () => {
const props = {
uri: '/myEndpoint',
resourceType: 'myResourceType',
- resource: new Immutable.Map({ label: 'myLabel' }),
+ resource: { label: 'myLabel' },
header: 'My header title',
params: { id: 'myResourceID' },
resourceTypeLabel: 'resourceLabel',
@@ -79,12 +75,12 @@ describe('Connected DeleteResource', () => {
});
it('should return the props.resource corresponding to resourceId', () => {
expect(mapStateToProps(state, { resourceType: 'foo', resourceId: '123' }).resource).toBe(
- state.cmf.collections.get('foo').get(0),
+ fooItem,
);
});
it('should return the props.resource corresponding to routeParams.id', () => {
expect(mapStateToProps(state, { resourceType: 'foo', params: { id: '123' } }).resource).toBe(
- state.cmf.collections.get('foo').get(0),
+ fooItem,
);
});
diff --git a/packages/containers/src/DeleteResource/sagas.js b/packages/containers/src/DeleteResource/sagas.js
index 87c96e0c760..b2b7ba0989d 100644
--- a/packages/containers/src/DeleteResource/sagas.js
+++ b/packages/containers/src/DeleteResource/sagas.js
@@ -85,7 +85,7 @@ export function* deleteResourceValidate(
model: {
...get(action, 'data.model', {}),
id: safeId,
- labelResource: resource.get('label') || resource.get('name', ''),
+ labelResource: resource.label || resource.name || '',
},
});
yield call(redirect, get(action, 'data.model.redirectUrl'));
diff --git a/packages/containers/src/DeleteResource/sagas.test.js b/packages/containers/src/DeleteResource/sagas.test.js
index 0e988b34d9d..6eff040cad0 100644
--- a/packages/containers/src/DeleteResource/sagas.test.js
+++ b/packages/containers/src/DeleteResource/sagas.test.js
@@ -1,5 +1,4 @@
// import SagaTester from 'redux-saga-tester';
-import { Map } from 'immutable';
import cmf from '@talend/react-cmf';
import { take, put } from 'redux-saga/effects';
import CONSTANTS from './constants';
@@ -54,7 +53,7 @@ describe('internals', () => {
},
},
};
- const resource = new Map({ id: '123', label: 'Foo' });
+ const resource = { id: '123', label: 'Foo' };
const gen = internals.deleteResourceValidate();
let effect = gen.next().value;
@@ -97,7 +96,11 @@ describe('internals', () => {
},
};
- const resource = new Map({ id: 'profileId', type: 'advanced', name: 'deleteThisRunProfile' });
+ const resource = {
+ id: 'profileId',
+ type: 'advanced',
+ name: 'deleteThisRunProfile',
+ };
const gen = internals.deleteResourceValidate();
gen.next();
@@ -122,11 +125,11 @@ describe('internals', () => {
},
},
};
- const resource = new Map({
+ const resource = {
id: 'profileId',
type: 'advanced',
name: 'deleteThisRunProfile',
- });
+ };
const gen = internals.deleteResourceValidate();
gen.next();
diff --git a/packages/containers/src/EditableText/EditableText.container.jsx b/packages/containers/src/EditableText/EditableText.container.jsx
index 7a46fb2a420..c84356bbdd2 100644
--- a/packages/containers/src/EditableText/EditableText.container.jsx
+++ b/packages/containers/src/EditableText/EditableText.container.jsx
@@ -1,14 +1,13 @@
import { Component as RComponent } from 'react';
import PropTypes from 'prop-types';
import Component from '@talend/react-components/lib/EditableText';
-import Immutable from 'immutable';
import omit from 'lodash/omit';
import { cmfConnect } from '@talend/react-cmf';
export const DISPLAY_NAME = 'Container(EditableText)';
-export const DEFAULT_STATE = new Immutable.Map({
+export const DEFAULT_STATE = {
editMode: false,
-});
+};
class EditableText extends RComponent {
static displayName = DISPLAY_NAME;
@@ -91,7 +90,7 @@ class EditableText extends RComponent {
onCancel: this.onCancel,
onSubmit: this.onSubmit,
onChange: this.onChange,
- ...state.toJS(),
+ ...state,
};
return ;
}
diff --git a/packages/containers/src/EditableText/EditableText.selectors.js b/packages/containers/src/EditableText/EditableText.selectors.js
index d8337be26ad..4a04f19cd86 100644
--- a/packages/containers/src/EditableText/EditableText.selectors.js
+++ b/packages/containers/src/EditableText/EditableText.selectors.js
@@ -6,5 +6,5 @@ import EditableText from './EditableText.connect';
* @param {string} idComponent
*/
export function getEditMode(state, idComponent) {
- return EditableText.getState(state, idComponent).get('editMode', false);
+ return EditableText.getState(state, idComponent)?.editMode ?? false;
}
diff --git a/packages/containers/src/EditableText/EditableText.test.js b/packages/containers/src/EditableText/EditableText.test.js
index 09a50864909..9fb6cc26642 100644
--- a/packages/containers/src/EditableText/EditableText.test.js
+++ b/packages/containers/src/EditableText/EditableText.test.js
@@ -1,6 +1,5 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import { Map } from 'immutable';
import cmf, { mock } from '@talend/react-cmf';
@@ -35,7 +34,7 @@ describe('EditableText container', () => {
it('should setState when submit event trigger', async () => {
let state;
const props = {
- state: Map({ editMode: true }),
+ state: { editMode: true },
setState: jest.fn(fn => {
state = fn;
}),
@@ -53,11 +52,10 @@ describe('EditableText container', () => {
});
});
it('should call ActionCreatorSubmit when submit event trigger', async () => {
- const event = {};
const props = {
actionCreatorSubmit: 'mySubmitActionCreator',
dispatchActionCreator: jest.fn(),
- state: Map({ editMode: true }),
+ state: { editMode: true },
setState: jest.fn(),
text: 'my text',
};
@@ -78,7 +76,7 @@ describe('EditableText container', () => {
it('should setState when cancel event trigger', async () => {
let state;
const props = {
- state: Map({ editMode: true }),
+ state: { editMode: true },
setState: jest.fn(fn => {
state = fn;
}),
@@ -93,7 +91,7 @@ describe('EditableText container', () => {
it('should call onCancel when cancel event trigger', async () => {
const props = {
setState: jest.fn(),
- state: Map({ editMode: true }),
+ state: { editMode: true },
onCancel: jest.fn(),
text: 'my text',
};
@@ -104,7 +102,7 @@ describe('EditableText container', () => {
it('should call actionCreatorCancel when cancel event trigger', async () => {
const props = {
setState: jest.fn(),
- state: Map({ editMode: true }),
+ state: { editMode: true },
actionCreatorCancel: 'myCancelActionCreator',
dispatchActionCreator: jest.fn(),
text: 'my text',
@@ -122,7 +120,7 @@ describe('EditableText container', () => {
it('should call setState when edit event trigger', async () => {
let state;
const props = {
- state: Map({ editMode: false }),
+ state: { editMode: false },
setState: jest.fn(fn => {
state = fn;
}),
@@ -137,7 +135,7 @@ describe('EditableText container', () => {
it('should call onEdit when edit event trigger', async () => {
const props = {
setState: jest.fn(),
- state: Map({ editMode: false }),
+ state: { editMode: false },
onEdit: jest.fn(),
text: 'my text',
};
@@ -145,10 +143,10 @@ describe('EditableText container', () => {
await userEvent.click(screen.getByLabelText('Rename'));
expect(props.onEdit).toHaveBeenCalledWith(expect.anything());
});
- it('should call onEdit when edit event trigger', async () => {
+ it('should call actionCreatorEdit via dispatchActionCreator when edit event trigger', async () => {
const props = {
setState: jest.fn(),
- state: Map({ editMode: false }),
+ state: { editMode: false },
dispatchActionCreator: jest.fn(),
actionCreatorEdit: 'myEditActionCreator',
text: 'my text',
@@ -168,7 +166,7 @@ describe('EditableText container', () => {
const props = {
setState: jest.fn(),
- state: Map({ editMode: true }),
+ state: { editMode: true },
onChange: jest.fn(),
text: 'my text',
};
@@ -184,7 +182,7 @@ describe('EditableText container', () => {
const props = {
setState: jest.fn(),
- state: Map({ editMode: true }),
+ state: { editMode: true },
dispatchActionCreator: jest.fn(),
actionCreatorChange: 'myChangeActionCreator',
text: 'my text',
@@ -207,11 +205,11 @@ describe('EditableText container', () => {
describe('EditableText selectors', () => {
let mockState;
- const componentState = Map({ editMode: true });
+ const componentState = { editMode: true };
beforeEach(() => {
mockState = {
cmf: {
- components: Map({ [DISPLAY_NAME]: Map({ myEditableText: componentState }) }),
+ components: { [DISPLAY_NAME]: { myEditableText: componentState } },
},
};
});
diff --git a/packages/containers/src/FilterBar/FilterBar.container.jsx b/packages/containers/src/FilterBar/FilterBar.container.jsx
index 34f1d6d4e03..03d4087afc0 100644
--- a/packages/containers/src/FilterBar/FilterBar.container.jsx
+++ b/packages/containers/src/FilterBar/FilterBar.container.jsx
@@ -2,14 +2,13 @@ import { cmfConnect } from '@talend/react-cmf';
import { Component as RComponent } from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
-import Immutable from 'immutable';
import Component from '@talend/react-components/lib/FilterBar';
export const QUERY_ATTR = 'query';
-export const DEFAULT_STATE = new Immutable.Map({
+export const DEFAULT_STATE = {
[QUERY_ATTR]: '',
docked: true,
-});
+};
export const DISPLAY_NAME = 'Container(FilterBar)';
@@ -49,13 +48,9 @@ class FilterBar extends RComponent {
}
onToggle(event) {
- this.props.setState(prevState => {
- let state = prevState.state;
- if (this.props.dockable) {
- state = state.set('docked', !this.props.state.get('docked'));
- }
- return state;
- });
+ if (this.props.dockable) {
+ this.props.setState({ docked: !this.props.state?.docked });
+ }
if (this.props.onToggle) {
this.props.onToggle(event);
}
@@ -65,8 +60,8 @@ class FilterBar extends RComponent {
const state = this.props.state || DEFAULT_STATE;
const props = {
...omit(this.props, cmfConnect.INJECTED_PROPS),
- docked: this.props.docked != null ? this.props.docked : state.get(DOCKED_ATTR),
- value: this.props.value ? this.props.value : state.get(QUERY_ATTR, ''),
+ docked: this.props.docked != null ? this.props.docked : state?.[DOCKED_ATTR],
+ value: this.props.value ? this.props.value : (state?.[QUERY_ATTR] ?? ''),
onToggle: this.onToggle,
onFilter: this.onFilter,
};
diff --git a/packages/containers/src/FilterBar/FilterBar.selectors.js b/packages/containers/src/FilterBar/FilterBar.selectors.js
index 5e2d915456f..e6b5a1a55f1 100644
--- a/packages/containers/src/FilterBar/FilterBar.selectors.js
+++ b/packages/containers/src/FilterBar/FilterBar.selectors.js
@@ -6,10 +6,7 @@ import { DEFAULT_STATE, DISPLAY_NAME } from './FilterBar.container';
* @param {string} idComponent
*/
export function getComponentState(state, idComponent) {
- if (state.cmf.components.hasIn([DISPLAY_NAME, idComponent])) {
- return state.cmf.components.getIn([DISPLAY_NAME, idComponent]);
- }
- return DEFAULT_STATE;
+ return state.cmf.components?.[DISPLAY_NAME]?.[idComponent] ?? DEFAULT_STATE;
}
/**
@@ -18,5 +15,5 @@ export function getComponentState(state, idComponent) {
* @param {string} idComponent
*/
export function getQuery(state, idComponent) {
- return getComponentState(state, idComponent).get('query', '');
+ return getComponentState(state, idComponent).query ?? '';
}
diff --git a/packages/containers/src/FilterBar/FilterBar.test.js b/packages/containers/src/FilterBar/FilterBar.test.js
index 56d44e56ad8..98259eb7892 100644
--- a/packages/containers/src/FilterBar/FilterBar.test.js
+++ b/packages/containers/src/FilterBar/FilterBar.test.js
@@ -1,5 +1,5 @@
-import { Map } from 'immutable';
-import { screen, render, fireEvent } from '@testing-library/react';
+import { fireEvent, render } from '@testing-library/react';
+import { screen } from '@testing-library/react';
import Container, { DEFAULT_STATE, DISPLAY_NAME } from './FilterBar.container';
import Connected from './FilterBar.connect';
import { getComponentState, getQuery } from './FilterBar.selectors';
@@ -29,7 +29,7 @@ describe('Filter container', () => {
const props = {
onFilter: jest.fn(),
setState: jest.fn(),
- state: Map({ docked: false }),
+ state: { docked: false },
};
render();
const query = 'foo';
@@ -40,7 +40,7 @@ describe('Filter container', () => {
const props = {
onFilter: jest.fn(),
setState: jest.fn(),
- state: Map({ docked: false }),
+ state: { docked: false },
};
const query = 'foo';
render();
@@ -58,7 +58,7 @@ describe('Filter container', () => {
const props = {
onBlur: jest.fn(),
setState: jest.fn(),
- state: Map({ docked: false }),
+ state: { docked: false },
};
render();
fireEvent.blur(document.querySelector('input'));
@@ -68,7 +68,7 @@ describe('Filter container', () => {
const props = {
onBlur: jest.fn(),
setState: jest.fn(),
- state: Map({ docked: false }),
+ state: { docked: false },
onFocus: jest.fn(),
};
render();
@@ -76,13 +76,9 @@ describe('Filter container', () => {
expect(props.onFocus).toHaveBeenCalled();
});
it('should call setState when onToggle event trigger', () => {
- const state = Map({ docked: false });
- const prevState = { state };
- const setState = jest.fn(fn => {
- prevState.state = fn(prevState);
- });
+ const state = { docked: false };
const props = {
- setState,
+ setState: jest.fn(),
state,
dockable: true,
onToggle: jest.fn(),
@@ -90,21 +86,20 @@ describe('Filter container', () => {
render();
fireEvent.blur(document.querySelector('input'));
expect(props.setState).toHaveBeenCalled();
- expect(prevState.state).not.toBe(state);
- expect(prevState.state.get('docked')).toBe(true);
+ expect(props.setState).toHaveBeenCalledWith({ docked: true });
expect(props.onToggle).toHaveBeenCalled();
});
});
describe('Filter Selectors', () => {
it('should return the filter component state', () => {
- const componentState = Map({
+ const componentState = {
query: 'Toto was here',
docked: true,
- });
+ };
const state = {
cmf: {
- components: Map({ [DISPLAY_NAME]: Map({ myFilterComponent: componentState }) }),
+ components: { [DISPLAY_NAME]: { myFilterComponent: componentState } },
},
};
expect(getComponentState(state, 'myFilterComponent')).toEqual(componentState);
@@ -112,19 +107,19 @@ describe('Filter Selectors', () => {
it('should return the default filter component state', () => {
const state = {
cmf: {
- components: Map(),
+ components: {},
},
};
expect(getComponentState(state, 'myFilterComponent')).toEqual(DEFAULT_STATE);
});
it('should return the query', () => {
- const componentState = Map({
+ const componentState = {
query: 'Hello world',
docked: true,
- });
+ };
const state = {
cmf: {
- components: Map({ [DISPLAY_NAME]: Map({ myFilterComponent: componentState }) }),
+ components: { [DISPLAY_NAME]: { myFilterComponent: componentState } },
},
};
expect(getQuery(state, 'myFilterComponent')).toEqual('Hello world');
diff --git a/packages/containers/src/Form/Form.container.jsx b/packages/containers/src/Form/Form.container.jsx
index a3d5747e35f..daa47b92f87 100644
--- a/packages/containers/src/Form/Form.container.jsx
+++ b/packages/containers/src/Form/Form.container.jsx
@@ -1,6 +1,5 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
-import Immutable from 'immutable';
import { cmfConnect } from '@talend/react-cmf';
import BaseForm from '@talend/react-forms';
import classnames from 'classnames';
@@ -10,7 +9,7 @@ if (process.env.FORM_MOZ) {
DefaultArrayFieldTemplate = BaseForm.deprecated.templates.ArrayFieldTemplate;
}
-export const DEFAULT_STATE = new Immutable.Map({});
+export const DEFAULT_STATE = {};
/**
* Because we don't want to loose form input
@@ -42,7 +41,7 @@ class Form extends Component {
* @return {[type]} [description]
*/
static getFormData(state, formId) {
- return state.cmf.components.getIn(['Container(Form)', formId, 'data'], new Immutable.Map());
+ return state.cmf.components?.['Container(Form)']?.[formId]?.data ?? {};
}
static getDerivedStateFromProps(nextProps, prevState) {
@@ -62,7 +61,7 @@ class Form extends Component {
constructor(props) {
super(props);
- this.state = DEFAULT_STATE.toJS();
+ this.state = { ...DEFAULT_STATE };
this.formActions = this.formActions.bind(this);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
@@ -105,7 +104,7 @@ class Form extends Component {
}
jsonSchema() {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
if (typeof this.props.jsonSchema === 'function') {
return this.props.jsonSchema(state.data);
}
@@ -113,7 +112,7 @@ class Form extends Component {
}
uiSchema() {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
if (typeof this.props.uiSchema === 'function') {
return this.props.uiSchema(state.data);
}
@@ -121,7 +120,7 @@ class Form extends Component {
}
data() {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
if (typeof this.props.data === 'function') {
return this.props.data(state.data);
}
@@ -129,7 +128,7 @@ class Form extends Component {
}
errors() {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
if (typeof this.props.errors === 'function') {
return this.props.errors(state.errors);
}
@@ -138,14 +137,14 @@ class Form extends Component {
formActions() {
if (typeof this.props.actions === 'function') {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
return this.props.actions(state.data || this.props.data);
}
return this.props.actions;
}
render() {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
const props = {
data: {
jsonSchema: this.jsonSchema(),
diff --git a/packages/containers/src/Form/Form.test.js b/packages/containers/src/Form/Form.test.js
index 5ca8c98b793..ea576ed1a2f 100644
--- a/packages/containers/src/Form/Form.test.js
+++ b/packages/containers/src/Form/Form.test.js
@@ -1,5 +1,4 @@
import { render } from '@testing-library/react';
-import { fromJS } from 'immutable';
import Connected from './Form.connect';
import Container from './Form.container';
@@ -45,7 +44,7 @@ describe('Container(Form)', () => {
const setState = jest.fn();
const event = { target: 'test' };
const form = new Container({
- state: fromJS({ data: { schema: true } }),
+ state: { data: { schema: true } },
onErrors,
setState,
});
@@ -59,7 +58,7 @@ describe('Container(Form)', () => {
const dispatchActionCreator = jest.fn();
const setState = jest.fn();
const form = new Container({
- state: fromJS({ data: { schema: true } }),
+ state: { data: { schema: true } },
setState,
onSubmitActionCreator: 'myaction',
onSubmit,
@@ -70,7 +69,7 @@ describe('Container(Form)', () => {
expect(dispatchActionCreator.mock.calls[0][0]).toBe('myaction');
expect(dispatchActionCreator.mock.calls[0][1]).toBe(null);
expect(dispatchActionCreator.mock.calls[0][2].formData).toEqual({ foo: 'bar' });
- expect(dispatchActionCreator.mock.calls[0][2].props.state.size).toBe(1);
+ expect(dispatchActionCreator.mock.calls[0][2].props.state).toEqual({ data: { schema: true } });
expect(setState.mock.calls.length).toBe(0);
});
@@ -79,7 +78,7 @@ describe('Container(Form)', () => {
const setState = jest.fn();
const event = { target: 'test' };
const form = new Container({
- state: fromJS({ data: { schema: true } }),
+ state: { data: { schema: true } },
onChange,
setState,
});
@@ -93,17 +92,17 @@ describe('Container(Form)', () => {
const formId = 'my-form';
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(Form)': {
[formId]: {
data: { foo: 'bar' },
},
},
- }),
+ },
},
};
const formData = Container.getFormData(state, formId);
- expect(formData.get('foo')).toBe('bar');
+ expect(formData.foo).toBe('bar');
});
it('should formActions return props.action', () => {
diff --git a/packages/containers/src/GuidedTour/GuidedTour.connect.js b/packages/containers/src/GuidedTour/GuidedTour.connect.js
index 8d56e8ce315..d253f8a72d2 100644
--- a/packages/containers/src/GuidedTour/GuidedTour.connect.js
+++ b/packages/containers/src/GuidedTour/GuidedTour.connect.js
@@ -1,9 +1,8 @@
-import { Map } from 'immutable';
import { cmfConnect } from '@talend/react-cmf';
import GuidedTourContainer from './GuidedTour.container';
-export const DEFAULT_STATE = Map({});
+export const DEFAULT_STATE = {};
export default cmfConnect({
componentId: ownProps => ownProps.componentId || ownProps.id,
diff --git a/packages/containers/src/GuidedTour/GuidedTour.container.jsx b/packages/containers/src/GuidedTour/GuidedTour.container.jsx
index 50dcdd876a1..cb06f4c664c 100644
--- a/packages/containers/src/GuidedTour/GuidedTour.container.jsx
+++ b/packages/containers/src/GuidedTour/GuidedTour.container.jsx
@@ -59,7 +59,7 @@ class GuidedTourContainer extends Component {
const { controls } = this.state;
return (
b.label ? 1 : -1;
@@ -40,7 +39,7 @@ class HeaderBar extends RComponent {
// products URL has changed or products have not been loaded yet
const hasProductsUrlChanged = this.props.productsUrl !== prevProps.productsUrl;
const hasProductsNotBeenLoaded =
- this.props.state.get('productsFetchState') === Constants.PRODUCTS_NOT_LOADED;
+ this.props.state?.productsFetchState === Constants.PRODUCTS_NOT_LOADED;
if (this.props.productsUrl && (hasProductsNotBeenLoaded || hasProductsUrlChanged)) {
this.props.dispatch(fetchProducts(this.props.productsUrl));
@@ -56,7 +55,7 @@ class HeaderBar extends RComponent {
} = this.props;
const hasFetchedProducts =
- this.props.state.get('productsFetchState') === Constants.FETCH_PRODUCTS_SUCCESS;
+ this.props.state?.productsFetchState === Constants.FETCH_PRODUCTS_SUCCESS;
const productsProps = {};
diff --git a/packages/containers/src/HeaderBar/HeaderBar.test.js b/packages/containers/src/HeaderBar/HeaderBar.test.js
index c15484d3479..c90d98fc26a 100644
--- a/packages/containers/src/HeaderBar/HeaderBar.test.js
+++ b/packages/containers/src/HeaderBar/HeaderBar.test.js
@@ -1,8 +1,8 @@
-import { Map, List } from 'immutable';
import { render, screen } from '@testing-library/react';
// eslint-disable-next-line @talend/import-depth
import { prepareCMF } from '@talend/react-cmf/lib/mock/rtl';
+
import Container, { DEFAULT_STATE } from './HeaderBar.container';
import Connected, { mapStateToProps } from './HeaderBar.connect';
import Constants from './HeaderBar.constant';
@@ -28,9 +28,9 @@ describe('Container HeaderBar', () => {
url: 'http://foo.bar',
},
],
- state: new Map({
+ state: {
productsFetchState: Constants.FETCH_PRODUCTS_SUCCESS,
- }),
+ },
};
render(await prepareCMF());
@@ -65,9 +65,9 @@ describe('Container HeaderBar', () => {
},
],
},
- state: new Map({
+ state: {
productsFetchState: Constants.FETCH_PRODUCTS_SUCCESS,
- }),
+ },
};
render(await prepareCMF());
expect(screen.getAllByRole('menuitem')).toHaveLength(3);
@@ -90,9 +90,9 @@ describe('Container HeaderBar', () => {
prepareProducts: jest.fn(products =>
products.map(product => ({ ...product, label: `${product.label} and bar` })),
),
- state: new Map({
+ state: {
productsFetchState: Constants.FETCH_PRODUCTS_SUCCESS,
- }),
+ },
};
render();
@@ -103,9 +103,9 @@ describe('Container HeaderBar', () => {
it('should render HeaderBar container while fetching items', async () => {
const props = {
...containerProps,
- state: new Map({
+ state: {
productsFetchState: Constants.FETCHING_PRODUCTS,
- }),
+ },
};
render(await prepareCMF());
@@ -124,11 +124,7 @@ describe('Connected HeaderBar', () => {
it('should mapStateToProps with an empty list of products', () => {
const state = {
cmf: {
- collections: new Map({
- HeaderBar: {
- [Constants.COLLECTION_ID]: new List(),
- },
- }),
+ collections: {},
},
};
const ownProps = {};
@@ -146,9 +142,7 @@ describe('Connected HeaderBar', () => {
const apps = [{ url: 'foobar' }];
const state = {
cmf: {
- collections: new Map({
- [Constants.COLLECTION_ID]: new List(apps),
- }),
+ collections: { [Constants.COLLECTION_ID]: apps },
},
};
const ownProps = {};
diff --git a/packages/containers/src/HomeListView/HomeListView.connect.test.js b/packages/containers/src/HomeListView/HomeListView.connect.test.js
index 8c0d68fe22e..fe6482c4436 100644
--- a/packages/containers/src/HomeListView/HomeListView.connect.test.js
+++ b/packages/containers/src/HomeListView/HomeListView.connect.test.js
@@ -1,6 +1,5 @@
// rewrite tests using react-testing-library
import { screen, render } from '@testing-library/react';
-import { fromJS } from 'immutable';
// eslint-disable-next-line @talend/import-depth
import { prepareCMF } from '@talend/react-cmf/lib/mock/rtl';
@@ -36,7 +35,7 @@ const toolbar = {
},
};
-const items = fromJS([
+const items = [
{
id: 1,
label: 'Title with actions',
@@ -47,7 +46,7 @@ const items = fromJS([
display: 'text',
className: 'item-0-class',
},
-]);
+];
const listProps = {
list,
diff --git a/packages/containers/src/HomeListView/HomeListView.stories.jsx b/packages/containers/src/HomeListView/HomeListView.stories.jsx
index 472c69b8f7e..63003aff52d 100644
--- a/packages/containers/src/HomeListView/HomeListView.stories.jsx
+++ b/packages/containers/src/HomeListView/HomeListView.stories.jsx
@@ -1,6 +1,5 @@
import { Drawer } from '@talend/react-components';
import { action } from 'storybook/actions';
-import Immutable from 'immutable';
import HomeListView from '.';
@@ -128,7 +127,7 @@ const toolbar = {
},
};
-const items = Immutable.fromJS([
+const items = [
{
id: 1,
label: 'Title with actions',
@@ -156,7 +155,7 @@ const items = Immutable.fromJS([
modified: '2016-09-22',
author: 'Jean-Pierre DUPONT with super long name',
},
-]);
+];
const listProps = {
list,
diff --git a/packages/containers/src/List/List.connect.js b/packages/containers/src/List/List.connect.js
index c05069134d7..f6a43dab964 100644
--- a/packages/containers/src/List/List.connect.js
+++ b/packages/containers/src/List/List.connect.js
@@ -1,5 +1,4 @@
import get from 'lodash/get';
-import { List } from 'immutable';
import { cmfConnect } from '@talend/react-cmf';
import Container, { DEFAULT_STATE } from './List.container';
import {
@@ -48,7 +47,7 @@ export function mapStateToProps(state, ownProps, cmfProps) {
props.items = getItems(state, config);
- const totalResults = props.items.size;
+ const totalResults = props.items.length;
if (get(ownProps, ['toolbar', 'pagination'])) {
props.items = getPagedItems(state, config, props.items);
@@ -56,12 +55,18 @@ export function mapStateToProps(state, ownProps, cmfProps) {
const cmfState = get(cmfProps, 'state');
if (cmfState) {
- props.state = cmfState.setIn(['totalResults'], totalResults);
- if (props.state.has('toolbar')) {
- props.state = props.state.mergeIn(
- ['toolbar', 'pagination'],
- configureGetPagination(state, config),
- );
+ props.state = { ...cmfState, totalResults };
+ if (props.state.toolbar !== undefined) {
+ props.state = {
+ ...props.state,
+ toolbar: {
+ ...props.state.toolbar,
+ pagination: {
+ ...props.state.toolbar?.pagination,
+ ...configureGetPagination(state, config),
+ },
+ },
+ };
}
}
@@ -81,7 +86,7 @@ export default cmfConnect({
defaultProps: {
saga: 'List#root',
- listItems: new List(),
+ listItems: [],
},
componentId,
diff --git a/packages/containers/src/List/List.container.jsx b/packages/containers/src/List/List.container.jsx
index f0d715322ae..cf2125b3297 100644
--- a/packages/containers/src/List/List.container.jsx
+++ b/packages/containers/src/List/List.container.jsx
@@ -1,6 +1,4 @@
import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import { Map, List as ImmutableList } from 'immutable';
import Component from '@talend/react-components/lib/List';
import VirtualizedList from '@talend/react-components/lib/VirtualizedList';
import get from 'lodash/get';
@@ -44,9 +42,9 @@ export const connectedCellDictionary = {
},
};
-export const DEFAULT_STATE = new Map({
+export const DEFAULT_STATE = {
displayMode: 'table',
- selectedItems: new ImmutableList(),
+ selectedItems: [],
searchQuery: '',
itemsPerPage: 10,
startIndex: 1,
@@ -54,7 +52,7 @@ export const DEFAULT_STATE = new Map({
sortOn: 'name',
sortAsc: true,
filterDocked: true,
-});
+};
/**
* merge props.items with actions
@@ -63,7 +61,7 @@ export const DEFAULT_STATE = new Map({
* @return {Array} [description]
*/
export function getItems(context, props) {
- return props.items.toJS().map(item => {
+ return props.items.map(item => {
const actionsItems = get(props, 'actions.items', []);
let actions = [];
if (
@@ -89,7 +87,7 @@ export function getItems(context, props) {
function List(props) {
const context = useCMFContext();
- const state = props.state.toJS();
+ const state = props.state;
function onChangePage(startIndex, itemsPerPage) {
props.setState({ startIndex, itemsPerPage });
@@ -100,7 +98,7 @@ function List(props) {
}
function getSelectedItems() {
- return props.state.get('selectedItems', new ImmutableList());
+ return props.state?.selectedItems ?? [];
}
function onToggleMultiSelection(event, data) {
@@ -108,11 +106,11 @@ function List(props) {
const dataIndex = selectedItems.indexOf(data[props.idKey]);
if (dataIndex > -1) {
props.setState({
- selectedItems: selectedItems.splice(dataIndex, 1),
+ selectedItems: selectedItems.filter((_, i) => i !== dataIndex),
});
} else {
props.setState({
- selectedItems: selectedItems.push(data[props.idKey]),
+ selectedItems: [...selectedItems, data[props.idKey]],
});
}
}
@@ -120,13 +118,13 @@ function List(props) {
function onToggleAllMultiSelection() {
const selectedItems = getSelectedItems();
const items = props.items;
- if (selectedItems.size !== items.size) {
+ if (selectedItems.length !== items.length) {
props.setState({
- selectedItems: items.map(item => item.get(props.idKey)),
+ selectedItems: items.map(item => item[props.idKey]),
});
} else {
props.setState({
- selectedItems: new ImmutableList([]),
+ selectedItems: [],
});
}
}
@@ -268,7 +266,7 @@ function List(props) {
newProps.list.itemProps.onToggle = onToggleMultiSelection;
newProps.list.itemProps.onToggleAll = onToggleAllMultiSelection;
newProps.list.itemProps.isSelected = isSelected;
- newProps.toolbar.actionBar.selected = getSelectedItems().size;
+ newProps.toolbar.actionBar.selected = getSelectedItems().length;
}
const actions = newProps.actions;
@@ -353,7 +351,7 @@ List.propTypes = {
}),
cellDictionary: PropTypes.object,
displayMode: PropTypes.string,
- items: ImmutablePropTypes.list.isRequired,
+ items: PropTypes.array.isRequired,
state: cmfConnect.propTypes.state,
...cmfConnect.propTypes,
};
diff --git a/packages/containers/src/List/List.sagas.test.js b/packages/containers/src/List/List.sagas.test.js
index 4aa9a5fb8cf..4e567bfc001 100644
--- a/packages/containers/src/List/List.sagas.test.js
+++ b/packages/containers/src/List/List.sagas.test.js
@@ -1,12 +1,11 @@
import { put } from 'redux-saga/effects';
-import { fromJS } from 'immutable';
import { mock } from '@talend/react-cmf';
import { onToggleFilter, onFilterChange, onChangeSortChange } from './List.sagas';
import Connected from './List.connect';
const localConfig = {
collectionId: 'default',
- items: fromJS([
+ items: [
{
id: 'id1',
value: 'value1',
@@ -17,7 +16,7 @@ const localConfig = {
value: 'value2',
text: 'text',
},
- ]),
+ ],
list: {
columns: [
{ key: 'id', name: 'ID' },
@@ -27,7 +26,7 @@ const localConfig = {
};
const state = mock.store.state();
-state.cmf.collections = fromJS({
+state.cmf.collections = {
default: {
columns: [
{ key: 'id', name: 'ID' },
@@ -35,7 +34,7 @@ state.cmf.collections = fromJS({
],
items: localConfig.items,
},
-});
+};
const context = mock.store.context();
const event = { type: 'click' };
@@ -47,14 +46,14 @@ const data = {
props: { config: localConfig },
};
-state.cmf.components = fromJS({
+state.cmf.components = {
'Container(List)': {
default: {
itemsPerPage: 1,
startIndex: 1,
},
},
-});
+};
describe('List sagas', () => {
it('should check onToggleFilter action', () => {
diff --git a/packages/containers/src/List/List.stories.jsx b/packages/containers/src/List/List.stories.jsx
index bd3f759b262..55819b708c1 100644
--- a/packages/containers/src/List/List.stories.jsx
+++ b/packages/containers/src/List/List.stories.jsx
@@ -1,7 +1,6 @@
import PropTypes from 'prop-types';
import api from '@talend/react-cmf';
-import Immutable from 'immutable';
import cloneDeep from 'lodash/cloneDeep';
import List from '.';
@@ -115,16 +114,16 @@ const customHeight = {
table: 100,
};
-const defaultListState = new Immutable.Map({
+const defaultListState = {
displayMode: 'large',
-});
+};
-const defaultSortedListState = new Immutable.Map({
+const defaultSortedListState = {
sortOn: 'modified',
sortAsc: false,
-});
+};
-const items = Immutable.fromJS([
+const items = [
{
id: 'id1',
label: 'Title with actions',
@@ -179,7 +178,7 @@ const items = Immutable.fromJS([
modified: '2016-09-22',
author: 'Jean-Pierre DUPONT',
},
-]);
+];
const referenceDatetime = Date.now();
const minusThreeHours = referenceDatetime - 3600 * 3 * 1000;
@@ -189,7 +188,7 @@ const minusThreeMin = referenceDatetime - 60 * 3 * 1000;
const oneDay = 24 * 3600 * 1000;
-const itemsWithTimestamp = Immutable.fromJS([
+const itemsWithTimestamp = [
{
id: 'id0',
label: 'Title with actions but first',
@@ -227,7 +226,7 @@ const itemsWithTimestamp = Immutable.fromJS([
modified: minusOneHours,
author: 'Jean-Pierre DUPONT with super long name',
},
-]);
+];
const sortUpdatedAsc = {
field: 'modified',
@@ -258,73 +257,72 @@ export const WithSeparatorActions = () => (
);
export const Pagination = () => {
const propsPg = cloneDeep(props);
- const itemsPg = items.concat(
- Immutable.fromJS([
- {
- id: 'id4',
- label: 'Title with actions',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT',
- },
- {
- id: 'ID5',
- label: 'Title in input mode',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT',
- },
- {
- id: 'iD6',
- label: 'Super long title to trigger overflow on some rendering',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT with super long name',
- },
- {
- id: 'id7',
- label: 'Title with actions',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT',
- },
- {
- id: 'ID8',
- label: 'Title in input mode',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT',
- },
- {
- id: 'iD9',
- label: 'Super long title to trigger overflow on some rendering',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT with super long name',
- },
- {
- id: 'id10',
- label: 'Title with actions',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT',
- },
- {
- id: 'ID11',
- label: 'Title in input mode',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT',
- },
- {
- id: 'iD12',
- label: 'Super long title to trigger overflow on some rendering',
- created: '2016-09-22',
- modified: '2016-09-22',
- author: 'Jean-Pierre DUPONT with super long name',
- },
- ]),
- );
+ const itemsPg = [
+ ...items,
+ {
+ id: 'id4',
+ label: 'Title with actions',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT',
+ },
+ {
+ id: 'ID5',
+ label: 'Title in input mode',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT',
+ },
+ {
+ id: 'iD6',
+ label: 'Super long title to trigger overflow on some rendering',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT with super long name',
+ },
+ {
+ id: 'id7',
+ label: 'Title with actions',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT',
+ },
+ {
+ id: 'ID8',
+ label: 'Title in input mode',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT',
+ },
+ {
+ id: 'iD9',
+ label: 'Super long title to trigger overflow on some rendering',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT with super long name',
+ },
+ {
+ id: 'id10',
+ label: 'Title with actions',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT',
+ },
+ {
+ id: 'ID11',
+ label: 'Title in input mode',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT',
+ },
+ {
+ id: 'iD12',
+ label: 'Super long title to trigger overflow on some rendering',
+ created: '2016-09-22',
+ modified: '2016-09-22',
+ author: 'Jean-Pierre DUPONT with super long name',
+ },
+ ];
propsPg.toolbar.pagination = {};
return (
diff --git a/packages/containers/src/List/List.test.jsx b/packages/containers/src/List/List.test.jsx
index aa29224a643..f324f61549d 100644
--- a/packages/containers/src/List/List.test.jsx
+++ b/packages/containers/src/List/List.test.jsx
@@ -2,7 +2,6 @@
/* eslint-disable react/display-name */
import { fireEvent, render, screen } from '@testing-library/react';
-import { fromJS, List as ImmutableList, Map } from 'immutable';
import cloneDeep from 'lodash/cloneDeep';
// eslint-disable-next-line @talend/import-depth
@@ -70,7 +69,7 @@ const settings = {
actions,
};
-const items = fromJS([
+const items = [
{
id: 1,
name: 'Title with actions',
@@ -98,7 +97,7 @@ const items = fromJS([
modified: '2016-09-22',
author: 'Jean-Pierre DUPONT with super long name',
},
-]);
+];
vi.mock('@talend/react-components/lib/List', () => ({
default: ({ getProps, ...props }) => (
@@ -144,7 +143,7 @@ describe('Container List', () => {
,
{ cmfModule },
@@ -172,7 +171,7 @@ describe('Container List', () => {
,
{ cmfModule },
@@ -492,7 +491,7 @@ describe('Container List', () => {
left: ['object:remove'],
};
multiSelectionSetting.setState = jest.fn();
- const state = fromJS({ selectedItems: [] });
+ const state = { selectedItems: [] };
multiSelectionSetting.state = state;
render(
await prepareCMF(
@@ -505,8 +504,8 @@ describe('Container List', () => {
const props = getProps.mock.calls[0][0];
props.list.itemProps.onToggle({}, { id: 1 });
// then
- expect(multiSelectionSetting.setState.mock.calls[0][0]).toMatchObject({
- selectedItems: expect.any(ImmutableList),
+ expect(multiSelectionSetting.setState.mock.calls[0][0]).toEqual({
+ selectedItems: [1],
});
});
@@ -519,7 +518,7 @@ describe('Container List', () => {
left: ['object:remove'],
};
multiSelectionSetting.setState = jest.fn();
- const state = fromJS({ selectedItems: [1] });
+ const state = { selectedItems: [1] };
multiSelectionSetting.state = state;
render(
await prepareCMF(
@@ -533,7 +532,7 @@ describe('Container List', () => {
props.list.itemProps.onToggle({}, { id: 1 });
// then
expect(multiSelectionSetting.setState.mock.calls[0][0]).toEqual({
- selectedItems: new ImmutableList([]),
+ selectedItems: [],
});
});
it('should select all items', async () => {
@@ -546,7 +545,7 @@ describe('Container List', () => {
left: ['object:remove'],
};
multiSelectionSetting.setState = jest.fn();
- const state = fromJS({ selectedItems: [] });
+ const state = { selectedItems: [] };
multiSelectionSetting.state = state;
render(
await prepareCMF(
@@ -559,9 +558,8 @@ describe('Container List', () => {
const props = getProps.mock.calls[0][0];
props.list.itemProps.onToggleAll();
// then
-
expect(multiSelectionSetting.setState.mock.calls[0][0]).toEqual({
- selectedItems: new ImmutableList([1, 2, 3]),
+ selectedItems: [1, 2, 3],
});
});
@@ -574,7 +572,7 @@ describe('Container List', () => {
left: ['object:remove'],
};
multiSelectionSetting.setState = jest.fn();
- const state = fromJS({ selectedItems: [1, 2, 3] });
+ const state = { selectedItems: [1, 2, 3] };
multiSelectionSetting.state = state;
render(
await prepareCMF(
@@ -588,7 +586,7 @@ describe('Container List', () => {
props.list.itemProps.onToggleAll();
// then
expect(multiSelectionSetting.setState.mock.calls[0][0]).toEqual({
- selectedItems: new ImmutableList([]),
+ selectedItems: [],
});
});
@@ -601,7 +599,7 @@ describe('Container List', () => {
left: ['object:remove'],
};
multiSelectionSetting.setState = jest.fn();
- const state = fromJS({ selectedItems: [1, 2, 3] });
+ const state = { selectedItems: [1, 2, 3] };
multiSelectionSetting.state = state;
// when
@@ -629,14 +627,14 @@ describe('Connected List', () => {
// given
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(List)': {
- cid: DEFAULT_STATE.toJS(),
+ cid: DEFAULT_STATE,
},
- }),
- collections: fromJS({
+ },
+ collections: {
cid: items,
- }),
+ },
},
};
@@ -651,18 +649,18 @@ describe('Connected List', () => {
// given
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(List)': {
- default: DEFAULT_STATE.toJS(),
+ default: DEFAULT_STATE,
},
- }),
- collections: new Map(),
+ },
+ collections: {},
},
};
// when : no collectionId defined
const props = mapStateToProps(state, {
- items: fromJS(items),
+ items: items,
});
// then
@@ -673,10 +671,10 @@ describe('Connected List', () => {
// given
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(List)': {
cid: {
- ...DEFAULT_STATE.toJS(),
+ ...DEFAULT_STATE,
toolbar: {
pagination: {
onChange: 'pagination:change',
@@ -684,8 +682,8 @@ describe('Connected List', () => {
},
},
},
- }),
- collections: fromJS({
+ },
+ collections: {
cid: {
pagination: {
totalResults: 36,
@@ -694,7 +692,7 @@ describe('Connected List', () => {
},
items,
},
- }),
+ },
},
};
@@ -709,7 +707,7 @@ describe('Connected List', () => {
// given
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(List)': {
default: {
displayMode: 'large',
@@ -721,25 +719,25 @@ describe('Connected List', () => {
filterDocked: true,
},
},
- }),
- collections: new Map(),
+ },
+ collections: {},
},
};
const initalSettings = cloneDeep(settings);
- initalSettings.items = fromJS(items);
+ initalSettings.items = items;
initalSettings.toolbar.filter.defaultFiltering = false;
// when : no collectionId defined
const props = mapStateToProps(state, initalSettings);
// then
- expect(props.items.size).toBe(items.size);
+ expect(props.items.length).toBe(items.length);
});
it('should disable sorting when defaultSorting is set to false', () => {
// given
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(List)': {
default: {
displayMode: 'large',
@@ -751,25 +749,25 @@ describe('Connected List', () => {
filterDocked: true,
},
},
- }),
- collections: new Map(),
+ },
+ collections: {},
},
};
const initalSettings = cloneDeep(settings);
- initalSettings.items = fromJS(items);
+ initalSettings.items = items;
initalSettings.toolbar.sort.defaultSorting = false;
// when : no collectionId defined
const props = mapStateToProps(state, initalSettings);
// then
- expect(props.items.toJS()[0].id).toBe(1);
+ expect(props.items[0].id).toBe(1);
});
it('should disable paging when defaultPaging is set to false', () => {
// given
const state = {
cmf: {
- components: fromJS({
+ components: {
'Container(List)': {
default: {
displayMode: 'large',
@@ -781,17 +779,17 @@ describe('Connected List', () => {
filterDocked: true,
},
},
- }),
- collections: new Map(),
+ },
+ collections: {},
},
};
const initalSettings = cloneDeep(settings);
- initalSettings.items = fromJS(items);
+ initalSettings.items = items;
initalSettings.toolbar.pagination.defaultPaging = false;
// when : no collectionId defined
const props = mapStateToProps(state, initalSettings);
// then
- expect(props.items.size).toBe(items.size);
+ expect(props.items.length).toBe(items.length);
});
});
diff --git a/packages/containers/src/List/__snapshots__/List.test.jsx.snap b/packages/containers/src/List/__snapshots__/List.test.jsx.snap
index 05d987def17..bb561f1e429 100644
--- a/packages/containers/src/List/__snapshots__/List.test.jsx.snap
+++ b/packages/containers/src/List/__snapshots__/List.test.jsx.snap
@@ -2,33 +2,33 @@
exports[`Connected List > should map items to props from collection List 1`] = `
{
- "items": Immutable.List [
- Immutable.Map {
- "id": 3,
- "name": "Super long title to trigger overflow on some rendering",
- "created": "2016-09-22",
- "modified": "2016-09-22",
+ "items": [
+ {
"author": "Jean-Pierre DUPONT with super long name",
- },
- Immutable.Map {
- "id": 2,
- "name": "Title in input mode",
"created": "2016-09-22",
+ "id": 3,
"modified": "2016-09-22",
+ "name": "Super long title to trigger overflow on some rendering",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-pdf-o",
- "display": "input",
"className": "item-1-class",
- },
- Immutable.Map {
- "id": 1,
- "name": "Title with actions",
"created": "2016-09-22",
+ "display": "input",
+ "icon": "fa fa-file-pdf-o",
+ "id": 2,
"modified": "2016-09-22",
+ "name": "Title in input mode",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-excel-o",
- "display": "text",
"className": "item-0-class",
+ "created": "2016-09-22",
+ "display": "text",
+ "icon": "fa fa-file-excel-o",
+ "id": 1,
+ "modified": "2016-09-22",
+ "name": "Title with actions",
},
],
}
@@ -36,33 +36,33 @@ exports[`Connected List > should map items to props from collection List 1`] = `
exports[`Connected List > should map items to props from collection Map 1`] = `
{
- "items": Immutable.List [
- Immutable.Map {
- "id": 3,
- "name": "Super long title to trigger overflow on some rendering",
- "created": "2016-09-22",
- "modified": "2016-09-22",
+ "items": [
+ {
"author": "Jean-Pierre DUPONT with super long name",
- },
- Immutable.Map {
- "id": 2,
- "name": "Title in input mode",
"created": "2016-09-22",
+ "id": 3,
"modified": "2016-09-22",
+ "name": "Super long title to trigger overflow on some rendering",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-pdf-o",
- "display": "input",
"className": "item-1-class",
- },
- Immutable.Map {
- "id": 1,
- "name": "Title with actions",
"created": "2016-09-22",
+ "display": "input",
+ "icon": "fa fa-file-pdf-o",
+ "id": 2,
"modified": "2016-09-22",
+ "name": "Title in input mode",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-excel-o",
- "display": "text",
"className": "item-0-class",
+ "created": "2016-09-22",
+ "display": "text",
+ "icon": "fa fa-file-excel-o",
+ "id": 1,
+ "modified": "2016-09-22",
+ "name": "Title with actions",
},
],
}
@@ -70,33 +70,33 @@ exports[`Connected List > should map items to props from collection Map 1`] = `
exports[`Connected List > should map items to props from default collection List 1`] = `
{
- "items": Immutable.List [
- Immutable.Map {
- "id": 3,
- "name": "Super long title to trigger overflow on some rendering",
- "created": "2016-09-22",
- "modified": "2016-09-22",
+ "items": [
+ {
"author": "Jean-Pierre DUPONT with super long name",
- },
- Immutable.Map {
- "id": 2,
- "name": "Title in input mode",
"created": "2016-09-22",
+ "id": 3,
"modified": "2016-09-22",
+ "name": "Super long title to trigger overflow on some rendering",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-pdf-o",
- "display": "input",
"className": "item-1-class",
- },
- Immutable.Map {
- "id": 1,
- "name": "Title with actions",
"created": "2016-09-22",
+ "display": "input",
+ "icon": "fa fa-file-pdf-o",
+ "id": 2,
"modified": "2016-09-22",
+ "name": "Title in input mode",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-excel-o",
- "display": "text",
"className": "item-0-class",
+ "created": "2016-09-22",
+ "display": "text",
+ "icon": "fa fa-file-excel-o",
+ "id": 1,
+ "modified": "2016-09-22",
+ "name": "Title with actions",
},
],
}
@@ -110,33 +110,33 @@ exports[`Container List > should put default props 1`] = `
"title": "object:open",
},
"displayMode": "table",
- "items": Immutable.List [
- Immutable.Map {
- "id": 1,
- "name": "Title with actions",
- "created": "2016-09-22",
- "modified": "2016-09-22",
+ "items": [
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-excel-o",
- "display": "text",
"className": "item-0-class",
- },
- Immutable.Map {
- "id": 2,
- "name": "Title in input mode",
"created": "2016-09-22",
+ "display": "text",
+ "icon": "fa fa-file-excel-o",
+ "id": 1,
"modified": "2016-09-22",
+ "name": "Title with actions",
+ },
+ {
"author": "Jean-Pierre DUPONT",
- "icon": "fa fa-file-pdf-o",
- "display": "input",
"className": "item-1-class",
- },
- Immutable.Map {
- "id": 3,
- "name": "Super long title to trigger overflow on some rendering",
"created": "2016-09-22",
+ "display": "input",
+ "icon": "fa fa-file-pdf-o",
+ "id": 2,
"modified": "2016-09-22",
+ "name": "Title in input mode",
+ },
+ {
"author": "Jean-Pierre DUPONT with super long name",
+ "created": "2016-09-22",
+ "id": 3,
+ "modified": "2016-09-22",
+ "name": "Super long title to trigger overflow on some rendering",
},
],
"list": {
diff --git a/packages/containers/src/List/selector.js b/packages/containers/src/List/selector.js
index 578e2cbd89f..56996fcd179 100644
--- a/packages/containers/src/List/selector.js
+++ b/packages/containers/src/List/selector.js
@@ -2,29 +2,25 @@ import cmf from '@talend/react-cmf';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import { createSelector } from 'reselect';
-import { Map, List } from 'immutable';
function contains(listItem, query, columns) {
- let item = listItem;
- if (Map.isMap(listItem)) {
- item = listItem.toJS();
- }
return columns.some(
column =>
- typeof item[column.key] === 'string' &&
- item[column.key].toLowerCase().indexOf(query.toLowerCase()) !== -1,
+ typeof listItem[column.key] === 'string' &&
+ listItem[column.key].toLowerCase().indexOf(query.toLowerCase()) !== -1,
);
}
function getCollection(state, collectionId) {
- return state.cmf.collections.get(collectionId);
+ if (collectionId == null) return undefined;
+ return cmf.selectors.collections.get(state, collectionId);
}
export function getCollectionItems(state, collectionId) {
const collection = getCollection(state, collectionId);
- if (Map.isMap(collection)) {
- return collection.get('items');
+ if (collection != null && !Array.isArray(collection) && typeof collection === 'object') {
+ return collection.items !== undefined ? collection.items : collection;
}
return collection;
}
@@ -32,15 +28,18 @@ export function getCollectionItems(state, collectionId) {
export function configureGetPagination(state, { collectionId }) {
const collection = getCollection(state, collectionId);
- if (Map.isMap(collection)) {
- return collection.get('pagination');
+ if (collection != null && !Array.isArray(collection) && typeof collection === 'object') {
+ return typeof collection.get === 'function'
+ ? collection.get('pagination')
+ : collection.pagination;
}
return null;
}
function getComponentState(collectionId) {
- return state => state.cmf.components.getIn(['Container(List)', collectionId || 'default']);
+ return state =>
+ cmf.selectors.components.getComponentState(state, 'Container(List)', collectionId || 'default');
}
export function configureGetFilteredItems(configure) {
@@ -51,7 +50,7 @@ export function configureGetFilteredItems(configure) {
componentState => {
let results = localConfig.items;
if (componentState) {
- const searchQuery = componentState.get('searchQuery');
+ const searchQuery = componentState?.searchQuery;
if (searchQuery && results) {
results = results.filter(item => contains(item, searchQuery, localConfig.columns));
}
@@ -60,13 +59,16 @@ export function configureGetFilteredItems(configure) {
},
);
- return createSelector([getFilteredList, getComponentState], items => items);
+ return createSelector(
+ [getFilteredList, getComponentState(localConfig.collectionId)],
+ items => items,
+ );
}
export function compare(sortBy) {
return (a, b) => {
- let aValue = a.get(sortBy);
- let bValue = b.get(sortBy);
+ let aValue = typeof a.get === 'function' ? a.get(sortBy) : a[sortBy];
+ let bValue = typeof b.get === 'function' ? b.get(sortBy) : b[sortBy];
if (typeof aValue === 'string' && typeof bValue === 'string') {
aValue = aValue.toLowerCase();
@@ -93,22 +95,22 @@ export function compare(sortBy) {
}
export function getSortedResults(componentState, config, listItems) {
- if (!List.isList(listItems)) {
- return new List();
+ if (listItems == null || typeof listItems.filter !== 'function') {
+ return [];
}
let results = listItems;
if (!isEmpty(componentState)) {
- const sortBy = componentState.get('sortOn');
- const sortAsc = componentState.get('sortAsc');
+ const sortBy = componentState.sortOn;
+ const sortAsc = componentState.sortAsc;
const sortedColumn = get(config, 'columns', []).find(column => column.key === sortBy);
if (get(sortedColumn, 'sortFunction')) {
// Immutable sort method returns sorted array
- results = results.sort(
+ results = [...results].sort(
cmf.registry.getFromRegistry(sortedColumn.sortFunction)(sortBy, sortAsc),
);
} else {
- results = results.sort(compare(sortBy));
+ results = [...results].sort(compare(sortBy));
}
if (!sortAsc) {
@@ -123,25 +125,25 @@ export function configureGetSortedItems(config, listItems) {
getSortedResults(componentState, config, listItems),
);
- return createSelector([getSortedList, getComponentState], items => items);
+ return createSelector([getSortedList, getComponentState(config.collectionId)], items => items);
}
export function configureGetPagedItems(configure, listItems) {
const getPagedList = createSelector(getComponentState(configure.collectionId), componentState => {
let results = listItems;
if (componentState) {
- const startIndex = componentState.get('startIndex');
- const itemsPerPage = componentState.get('itemsPerPage');
+ const startIndex = componentState.startIndex;
+ const itemsPerPage = componentState.itemsPerPage;
if (itemsPerPage > 0 && startIndex > 0) {
results = results.slice(
startIndex - 1,
- Math.min(startIndex + itemsPerPage - 1, results.size),
+ Math.min(startIndex + itemsPerPage - 1, results.size ?? results.length),
);
}
}
return results;
});
- return createSelector([getPagedList, getComponentState], items => items);
+ return createSelector([getPagedList, getComponentState(configure.collectionId)], items => items);
}
diff --git a/packages/containers/src/List/selector.test.js b/packages/containers/src/List/selector.test.js
index b9525d7d579..8ba0eb4dfdb 100644
--- a/packages/containers/src/List/selector.test.js
+++ b/packages/containers/src/List/selector.test.js
@@ -1,5 +1,4 @@
import cmf, { mock } from '@talend/react-cmf';
-import { fromJS, List } from 'immutable';
import { mapStateToProps } from './List.connect';
import { compare, getSortedResults } from './selector';
@@ -26,7 +25,7 @@ const localConfig = {
};
const state = mock.store.state();
-state.cmf.collections = fromJS({
+state.cmf.collections = {
default: {
columns: [
{ key: 'id', name: 'ID' },
@@ -34,11 +33,11 @@ state.cmf.collections = fromJS({
],
items: localConfig.items,
},
-});
+};
describe('List Selector tests', () => {
it('should not filter the list when there is no search query', () => {
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(List)': {
default: {
displayMode: 'large',
@@ -50,14 +49,14 @@ describe('List Selector tests', () => {
filterDocked: true,
},
},
- });
+ };
const props = mapStateToProps(state, localConfig);
- expect(props.items.size).toBe(localConfig.items.length);
+ expect(props.items.length).toBe(localConfig.items.length);
});
it('should filter the list when filter on visible column', () => {
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(List)': {
default: {
displayMode: 'large',
@@ -69,14 +68,14 @@ describe('List Selector tests', () => {
filterDocked: true,
},
},
- });
+ };
const props = mapStateToProps(state, localConfig);
- expect(props.items.size).toBe(1);
+ expect(props.items.length).toBe(1);
});
it('should return no elements when search on non visible column', () => {
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(List)': {
default: {
displayMode: 'large',
@@ -88,85 +87,76 @@ describe('List Selector tests', () => {
filterDocked: true,
},
},
- });
+ };
const props = mapStateToProps(state, localConfig);
- expect(props.items.size).toBe(0);
+ expect(props.items.length).toBe(0);
});
it('should return items in a page when pagination applied', () => {
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(List)': {
default: {
itemsPerPage: 1,
startIndex: 1,
},
},
- });
+ };
const props = mapStateToProps(state, { ...localConfig, toolbar: { pagination: {} } });
- expect(props.items.size).toBe(1);
+ expect(props.items.length).toBe(1);
});
it('should sort a different column type correctly', () => {
expect(
- fromJS([{ stringID: '1' }, { stringID: '11' }, { stringID: '12' }, { stringID: '2' }]).sort(
+ [{ stringID: '1' }, { stringID: '11' }, { stringID: '12' }, { stringID: '2' }].sort(
compare('stringID'),
),
- ).toEqual(
- fromJS([{ stringID: '1' }, { stringID: '11' }, { stringID: '12' }, { stringID: '2' }]),
- );
+ ).toEqual([{ stringID: '1' }, { stringID: '11' }, { stringID: '12' }, { stringID: '2' }]);
expect(
- fromJS([
+ [
{ stringName: 'Uzbekistan' },
{ stringName: 'American Samoa' },
{ stringName: 'Djibouti' },
{ stringName: 'Luxembourg' },
- ]).sort(compare('stringName')),
- ).toEqual(
- fromJS([
- { stringName: 'American Samoa' },
- { stringName: 'Djibouti' },
- { stringName: 'Luxembourg' },
- { stringName: 'Uzbekistan' },
- ]),
- );
+ ].sort(compare('stringName')),
+ ).toEqual([
+ { stringName: 'American Samoa' },
+ { stringName: 'Djibouti' },
+ { stringName: 'Luxembourg' },
+ { stringName: 'Uzbekistan' },
+ ]);
expect(
- fromJS([{ intID: 1 }, { intID: 11 }, { intID: 12 }, { intID: 2 }]).sort(compare('intID')),
- ).toEqual(fromJS([{ intID: 1 }, { intID: 2 }, { intID: 11 }, { intID: 12 }]));
+ [{ intID: 1 }, { intID: 11 }, { intID: 12 }, { intID: 2 }].sort(compare('intID')),
+ ).toEqual([{ intID: 1 }, { intID: 2 }, { intID: 11 }, { intID: 12 }]);
expect(
- fromJS([{ mixedID: '1' }, { mixedID: '11' }, { mixedID: '-' }, { mixedID: '2' }]).sort(
+ [{ mixedID: '1' }, { mixedID: '11' }, { mixedID: '-' }, { mixedID: '2' }].sort(
compare('mixedID'),
),
- ).toEqual(fromJS([{ mixedID: '-' }, { mixedID: '1' }, { mixedID: '11' }, { mixedID: '2' }]));
+ ).toEqual([{ mixedID: '-' }, { mixedID: '1' }, { mixedID: '11' }, { mixedID: '2' }]);
expect(
- fromJS([
- { mixedString: 'a' },
- { mixedString: 'b' },
- { mixedString: 'C' },
- { mixedString: 'D' },
- ]).sort(compare('mixedString')),
- ).toEqual(
- fromJS([
- { mixedString: 'a' },
- { mixedString: 'b' },
- { mixedString: 'C' },
- { mixedString: 'D' },
- ]),
- );
+ [{ mixedString: 'a' }, { mixedString: 'b' }, { mixedString: 'C' }, { mixedString: 'D' }].sort(
+ compare('mixedString'),
+ ),
+ ).toEqual([
+ { mixedString: 'a' },
+ { mixedString: 'b' },
+ { mixedString: 'C' },
+ { mixedString: 'D' },
+ ]);
});
it('should test the getSortedResults method', () => {
cmf.registry.addToRegistry('myCustomSortFn', (sortBy, sortAsc) => (a, b) => {
if (sortAsc) {
- return a.get(sortBy) > b.get(sortBy) ? -1 : 1;
+ return a[sortBy] > b[sortBy] ? -1 : 1;
}
return 0;
});
- const componentState = fromJS({
+ const componentState = {
sortOn: 'data',
sortAsc: true,
- });
+ };
const config = {
columns: [
{
@@ -178,41 +168,40 @@ describe('List Selector tests', () => {
// Sorting the list
expect(
- getSortedResults(
- componentState,
- config,
- fromJS([{ data: 0 }, { data: 4 }, { data: 2 }, { data: 11 }, { data: 1 }, { data: 23 }]),
- ),
- ).toEqual(
- fromJS([{ data: 0 }, { data: 1 }, { data: 2 }, { data: 4 }, { data: 11 }, { data: 23 }]),
- );
+ getSortedResults(componentState, config, [
+ { data: 0 },
+ { data: 4 },
+ { data: 2 },
+ { data: 11 },
+ { data: 1 },
+ { data: 23 },
+ ]),
+ ).toEqual([{ data: 0 }, { data: 1 }, { data: 2 }, { data: 4 }, { data: 11 }, { data: 23 }]);
// Sorting by column and custom sort function
expect(
getSortedResults(
- fromJS({ sortOn: 'a', sortAsc: true }),
+ { sortOn: 'a', sortAsc: true },
{ columns: [{ key: 'a', sortFunction: 'myCustomSortFn' }] },
- fromJS([{ a: 1 }, { a: 3 }, { a: 2 }]),
+ [{ a: 1 }, { a: 3 }, { a: 2 }],
),
- ).toEqual(fromJS([{ a: 3 }, { a: 2 }, { a: 1 }]));
+ ).toEqual([{ a: 3 }, { a: 2 }, { a: 1 }]);
// Desc sort
expect(
- getSortedResults(
- fromJS({ sortOn: 'key', sortAsc: false }),
- config,
- fromJS([{ key: 1 }, { key: 3 }, { key: 2 }]),
- ),
- ).toEqual(fromJS([{ key: 3 }, { key: 2 }, { key: 1 }]));
+ getSortedResults({ sortOn: 'key', sortAsc: false }, config, [
+ { key: 1 },
+ { key: 3 },
+ { key: 2 },
+ ]),
+ ).toEqual([{ key: 3 }, { key: 2 }, { key: 1 }]);
// Edge cases
[null, undefined, 1, true, false, [], {}].forEach(val =>
- expect(getSortedResults(val, val, fromJS([{ item: 'one' }]))).toEqual(
- fromJS([{ item: 'one' }]),
- ),
+ expect(getSortedResults(val, val, [{ item: 'one' }])).toEqual([{ item: 'one' }]),
);
// With no items
- expect(getSortedResults(componentState, config, null)).toEqual(new List());
+ expect(getSortedResults(componentState, config, null)).toEqual([]);
});
});
diff --git a/packages/containers/src/Notification/Notification.connect.js b/packages/containers/src/Notification/Notification.connect.js
index 76e3105003b..a057cc47ad8 100644
--- a/packages/containers/src/Notification/Notification.connect.js
+++ b/packages/containers/src/Notification/Notification.connect.js
@@ -7,11 +7,11 @@ export function componentId(ownProps) {
export function deleteNotification(indexNotification) {
return function mutator(prevStateProps) {
- const notifications = prevStateProps.state.get('notifications');
+ const notifications = prevStateProps.state.notifications;
const index = notifications.indexOf(indexNotification);
if (index > -1) {
- const newNotif = notifications.delete(index);
- return prevStateProps.state.set('notifications', newNotif);
+ const newNotif = [...notifications.slice(0, index), ...notifications.slice(index + 1)];
+ return { ...prevStateProps.state, notifications: newNotif };
}
return prevStateProps.state;
};
diff --git a/packages/containers/src/Notification/Notification.container.jsx b/packages/containers/src/Notification/Notification.container.jsx
index cc5cdf5ad2e..42736f8472b 100644
--- a/packages/containers/src/Notification/Notification.container.jsx
+++ b/packages/containers/src/Notification/Notification.container.jsx
@@ -1,14 +1,13 @@
import PropTypes from 'prop-types';
-import { List, Map } from 'immutable';
import Component from '@talend/react-components/lib/Notification';
import { cmfConnect } from '@talend/react-cmf';
-export const DEFAULT_STATE = new Map({
- notifications: new List(),
-});
+export const DEFAULT_STATE = {
+ notifications: [],
+};
function Notification(props) {
- const state = (props.state || DEFAULT_STATE).toJS();
+ const state = props.state || DEFAULT_STATE;
return (
props.deleteNotification(i)}
diff --git a/packages/containers/src/Notification/Notification.sagas.js b/packages/containers/src/Notification/Notification.sagas.js
index ee0b8e3ba1b..97208d6e2d1 100644
--- a/packages/containers/src/Notification/Notification.sagas.js
+++ b/packages/containers/src/Notification/Notification.sagas.js
@@ -12,12 +12,16 @@ const DEFAULT_COMPONENT_ID = 'Notification';
export function* onPushNotification(action) {
const componentState = yield select(state => Notification.getState(state, DEFAULT_COMPONENT_ID));
- const newComponentState = componentState.updateIn(['notifications'], notifications =>
- notifications.push({
- id: randomUUID(),
- ...action.notification,
- }),
- );
+ const newComponentState = {
+ ...componentState,
+ notifications: [
+ ...(componentState?.notifications ?? []),
+ {
+ id: randomUUID(),
+ ...action.notification,
+ },
+ ],
+ };
const updateStateAction = Notification.setStateAction(newComponentState, DEFAULT_COMPONENT_ID);
yield put(updateStateAction);
diff --git a/packages/containers/src/Notification/Notification.sagas.test.js b/packages/containers/src/Notification/Notification.sagas.test.js
index e26a0a4db47..745303fec8d 100644
--- a/packages/containers/src/Notification/Notification.sagas.test.js
+++ b/packages/containers/src/Notification/Notification.sagas.test.js
@@ -1,4 +1,3 @@
-import Immutable from 'immutable';
import { runSaga } from 'redux-saga';
import { onPushNotification } from './Notification.sagas';
@@ -18,13 +17,13 @@ describe('Notification sagas', () => {
dispatch: a => dispatched.push(a),
getState: () => ({
cmf: {
- components: Immutable.fromJS({
+ components: {
'Container(Notification)': {
Notification: {
notifications: [],
},
},
- }),
+ },
},
}),
},
@@ -32,8 +31,7 @@ describe('Notification sagas', () => {
onPushNotificationAction,
).done;
- // Convert first, the half immutable payload to a full one then back to a full js one
- const actions = Immutable.fromJS(dispatched).toJS();
+ const actions = dispatched;
expect(actions[0]).toEqual({
type: 'Container(Notification).setState',
diff --git a/packages/containers/src/Notification/Notification.stories.jsx b/packages/containers/src/Notification/Notification.stories.jsx
index 85f74f523b4..3d9e2bc4fa1 100644
--- a/packages/containers/src/Notification/Notification.stories.jsx
+++ b/packages/containers/src/Notification/Notification.stories.jsx
@@ -1,8 +1,7 @@
-import { List, Map } from 'immutable';
import Notification from '.';
-const initialState = new Map({
- notifications: new List([
+const initialState = {
+ notifications: [
{
id: 'story-1',
message: 'This is a feedback of your operation1, This is a feedback of your operation1',
@@ -20,8 +19,8 @@ const initialState = new Map({
type: 'warning',
message: ['This is a feedback of your operation3', 'details'],
},
- ]),
-});
+ ],
+};
export default {
title: 'Notification',
diff --git a/packages/containers/src/Notification/Notification.test.jsx b/packages/containers/src/Notification/Notification.test.jsx
index c38ad6f2e6b..61030d533c8 100644
--- a/packages/containers/src/Notification/Notification.test.jsx
+++ b/packages/containers/src/Notification/Notification.test.jsx
@@ -3,7 +3,6 @@
/* eslint-disable react/display-name */
import { render } from '@testing-library/react';
import { mock } from '@talend/react-cmf';
-import Immutable, { fromJS } from 'immutable';
// eslint-disable-next-line @talend/import-depth
import { prepareCMF } from '@talend/react-cmf/lib/mock/rtl';
import Container from './Notification.container';
@@ -30,7 +29,7 @@ describe('Connected Notification', () => {
it('mergeProps should merge the props', () => {
const message = { message: 'hello world' };
const stateProps = {
- state: fromJS({ notifications: [message] }),
+ state: { notifications: [message] },
};
const dispatchProps = {
setState: jest.fn(),
@@ -38,7 +37,7 @@ describe('Connected Notification', () => {
const ownProps = { foo: 'bar' };
const props = mergeProps(stateProps, dispatchProps, ownProps);
expect(props.foo).toBe('bar');
- expect(props.state.get('notifications').size).toBe(1);
+ expect(props.state.notifications.length).toBe(1);
expect(typeof props.setState).toBe('function');
expect(typeof props.deleteNotification).toBe('function');
props.deleteNotification(message);
@@ -46,20 +45,20 @@ describe('Connected Notification', () => {
});
it('deleteNotification should delete notification', () => {
- const message = fromJS({ message: 'hello world' });
+ const message = { message: 'hello world' };
const stateProps = {
- state: fromJS({ notifications: [message] }),
+ state: { notifications: [message] },
};
- expect(deleteNotification(message)(stateProps).toJS()).toEqual({
+ expect(deleteNotification(message)(stateProps)).toEqual({
notifications: [],
});
});
it('deleteNotification should do nothing if the notification does not exist', () => {
- const ok = fromJS({ message: 'ahah' });
- const ko = fromJS({ message: 'hello world' });
+ const ok = { message: 'ahah' };
+ const ko = { message: 'hello world' };
const stateProps = {
- state: fromJS({ notifications: [ok] }),
+ state: { notifications: [ok] },
};
expect(deleteNotification(ko)(stateProps)).toEqual(stateProps.state);
});
@@ -68,74 +67,65 @@ describe('Connected Notification', () => {
describe('Notification.pushNotification', () => {
it('should add a Notification in the state', () => {
const state = mock.store.state();
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(Notification)': {
Notification: {
notifications: [],
},
},
- });
+ };
const notification = { message: 'hello world' };
const newState = pushNotification(state, notification);
expect(newState).not.toBe(state);
- const notifications = newState.cmf.components.getIn([
- 'Container(Notification)',
- 'Notification',
- 'notifications',
- ]);
- expect(notifications.size).toBe(1);
- expect(notifications.get(0).message).toBe('hello world');
+ const notifications =
+ newState.cmf.components['Container(Notification)'].Notification.notifications;
+ expect(notifications.length).toBe(1);
+ expect(notifications[0].message).toBe('hello world');
});
it('should add a Notification in the state even if the state slot is not yet available', () => {
const state = mock.store.state();
- state.cmf.components = new Immutable.Map();
+ state.cmf.components = {};
const notification = { message: 'hello world' };
const newState = pushNotification(state, notification);
- const notifications = newState.cmf.components.getIn([
- 'Container(Notification)',
- 'Notification',
- 'notifications',
- ]);
- expect(notifications.size).toBe(1);
- expect(notifications.get(0).message).toBe('hello world');
+ const notifications =
+ newState.cmf.components['Container(Notification)'].Notification.notifications;
+ expect(notifications.length).toBe(1);
+ expect(notifications[0].message).toBe('hello world');
});
it('should delete all Notification in the state', () => {
const state = mock.store.state();
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(Notification)': {
Notification: {
notifications: [{ message: 'hello world' }, { message: 'hello world2' }],
},
},
- });
+ };
const newState = clearNotifications(state);
expect(newState).not.toBe(state);
- const notifications = newState.cmf.components.getIn([
- 'Container(Notification)',
- 'Notification',
- 'notifications',
- ]);
- expect(notifications.size).toBe(0);
+ const notifications =
+ newState.cmf.components['Container(Notification)'].Notification.notifications;
+ expect(notifications.length).toBe(0);
});
it('should not change the state if no notification', () => {
const state = mock.store.state();
- state.cmf.components = fromJS({
+ state.cmf.components = {
'Container(Notification)': {
Notification: {
notifications: [],
},
},
- });
+ };
const newState = pushNotification(state);
expect(newState).toBe(state);
});
it('should not change the state if notification state is not yet availbale', () => {
const state = mock.store.state();
- state.cmf.components = fromJS({});
+ state.cmf.components = {};
const newState = pushNotification(state);
expect(newState).toBe(state);
});
diff --git a/packages/containers/src/Notification/clearNotifications.js b/packages/containers/src/Notification/clearNotifications.js
index 4c6abd0b661..44d375f5c0a 100644
--- a/packages/containers/src/Notification/clearNotifications.js
+++ b/packages/containers/src/Notification/clearNotifications.js
@@ -1,13 +1,31 @@
+import cmf from '@talend/react-cmf';
+
export default function clearNotifications(state) {
- const path = ['Container(Notification)', 'Notification', 'notifications'];
- let notifs = state.cmf.components.getIn(path);
+ const notifs = cmf.selectors.components.getComponentStateProperty(
+ state,
+ 'Container(Notification)',
+ 'Notification',
+ 'notifications',
+ );
if (!notifs) {
return state;
}
- notifs = notifs.clear();
- const newState = { ...state };
- newState.cmf.components = state.cmf.components.setIn(path, notifs);
- return newState;
+ return {
+ ...state,
+ cmf: {
+ ...state.cmf,
+ components: {
+ ...state.cmf.components,
+ 'Container(Notification)': {
+ ...state.cmf.components?.['Container(Notification)'],
+ Notification: {
+ ...state.cmf.components?.['Container(Notification)']?.Notification,
+ notifications: [],
+ },
+ },
+ },
+ },
+ };
}
diff --git a/packages/containers/src/Notification/pushNotification.js b/packages/containers/src/Notification/pushNotification.js
index 3e8e51ca99c..831983a4dd9 100644
--- a/packages/containers/src/Notification/pushNotification.js
+++ b/packages/containers/src/Notification/pushNotification.js
@@ -1,5 +1,5 @@
import get from 'lodash/get';
-import Immutable from 'immutable';
+import cmf from '@talend/react-cmf';
import { randomUUID } from '@talend/utils';
/**
@@ -13,13 +13,29 @@ export default function pushNotification(state, notification) {
if (!get(notification, 'message')) {
return state;
}
- const path = ['Container(Notification)', 'Notification', 'notifications'];
- let notifs = state.cmf.components.getIn(path, new Immutable.List());
- notifs = notifs.push({
- id: randomUUID(),
- ...notification,
- });
- const newState = { ...state };
- newState.cmf.components = state.cmf.components.setIn(path, notifs);
+ const notifs =
+ cmf.selectors.components.getComponentStateProperty(
+ state,
+ 'Container(Notification)',
+ 'Notification',
+ 'notifications',
+ ) || [];
+ const newNotifs = [...notifs, { id: randomUUID(), ...notification }];
+ const newState = {
+ ...state,
+ cmf: {
+ ...state.cmf,
+ components: {
+ ...state.cmf.components,
+ 'Container(Notification)': {
+ ...state.cmf.components?.['Container(Notification)'],
+ Notification: {
+ ...state.cmf.components?.['Container(Notification)']?.Notification,
+ notifications: newNotifs,
+ },
+ },
+ },
+ },
+ };
return newState;
}
diff --git a/packages/containers/src/ObjectViewer/ObjectViewer.container.jsx b/packages/containers/src/ObjectViewer/ObjectViewer.container.jsx
index 43c5ac9482e..b34899439f1 100644
--- a/packages/containers/src/ObjectViewer/ObjectViewer.container.jsx
+++ b/packages/containers/src/ObjectViewer/ObjectViewer.container.jsx
@@ -1,37 +1,35 @@
import PropTypes from 'prop-types';
import { Component as RComponent } from 'react';
-import { List, Map } from 'immutable';
import get from 'lodash/get';
import Component from '@talend/react-components/lib/ObjectViewer';
import { cmfConnect } from '@talend/react-cmf';
-export const DEFAULT_STATE = new Map({
- edited: new List(), // Array of JSONPath
- opened: new List(), // Array of JSONPath
+export const DEFAULT_STATE = {
+ edited: [], // Array of JSONPath
+ opened: [], // Array of JSONPath
selectedJsonpath: '', // Selected JSONPath
- modified: new Map(), // Store the onChange
-});
+ modified: {}, // Store the onChange
+};
export function open(path, state) {
- return state.set('opened', state.get('opened').push(path));
+ return { opened: [...(state.opened ?? []), path] };
}
export function select(path, state) {
- return state.set('selectedJsonpath', path);
+ return { selectedJsonpath: path };
}
export function close(path, state) {
- const opened = state.get('opened');
- return state.set('opened', opened.delete(opened.indexOf(path)));
+ return { opened: (state.opened ?? []).filter(p => p !== path) };
}
export function edit(path, state) {
- return state.set('edited', state.get('edited').push(path));
+ return { edited: [...(state.edited ?? []), path] };
}
export function change(path, state, value) {
- return state.set('modified', state.get('modified').set(path, value));
+ return { modified: { ...(state.modified ?? {}), [path]: value } };
}
export function toggleState(prevState, data) {
@@ -42,21 +40,16 @@ export function toggleState(prevState, data) {
return open(data.jsonpath, prevState.state);
}
- return prevState;
+ return {};
}
export function openAllState(prevState, siblings) {
- let openedIds = prevState.state.get('opened');
-
- siblings
+ const openedIds = prevState.state?.opened ?? [];
+ const newIds = siblings
.filter(({ data }) => typeof data === 'object')
- .forEach(({ jsonpath }) => {
- if (!openedIds.includes(jsonpath)) {
- openedIds = openedIds.push(jsonpath);
- }
- });
-
- return prevState.state.set('opened', openedIds);
+ .map(({ jsonpath }) => jsonpath)
+ .filter(id => !openedIds.includes(id));
+ return { opened: [...openedIds, ...newIds] };
}
export function selectWrapper(prevState, data) {
@@ -68,7 +61,7 @@ export function editWrapper(prevState, data) {
return edit(data.jsonpath, prevState.state);
}
- return prevState;
+ return {};
}
class ObjectViewer extends RComponent {
@@ -112,7 +105,7 @@ class ObjectViewer extends RComponent {
}
render() {
- const state = (this.props.state || DEFAULT_STATE).toJS();
+ const state = this.props.state || DEFAULT_STATE;
return (
);
}
diff --git a/packages/containers/src/ObjectViewer/ObjectViewer.test.jsx b/packages/containers/src/ObjectViewer/ObjectViewer.test.jsx
index 12112325c00..63aa0cea999 100644
--- a/packages/containers/src/ObjectViewer/ObjectViewer.test.jsx
+++ b/packages/containers/src/ObjectViewer/ObjectViewer.test.jsx
@@ -118,14 +118,14 @@ describe('editValue', () => {
};
prevState.state = editWrapper(prevState, someData);
- expect(prevState.state.get('edited').size).toBe(1);
+ expect(prevState.state.edited.length).toBe(1);
});
it('should change', () => {
const prevState = { state: DEFAULT_STATE };
prevState.state = change(path, prevState.state, 'new label');
- expect(prevState.state.get('modified').size).toBe(1);
+ expect(Object.keys(prevState.state.modified).length).toBe(1);
});
});
@@ -133,18 +133,18 @@ describe('toggleState', () => {
const prevState = { state: DEFAULT_STATE };
it('should open', () => {
const newState = toggleState(prevState, { isOpened: false, jsonpath: path });
- expect(newState.get('opened').size).toBe(1);
- expect(newState.get('opened').first()).toEqual(path);
+ expect(newState.opened.length).toBe(1);
+ expect(newState.opened[0]).toEqual(path);
});
it(' should close', () => {
- prevState.state = prevState.state.set('opened', prevState.state.get('opened').push(path));
+ prevState.state = { ...prevState.state, opened: [...(prevState.state.opened ?? []), path] };
- expect(prevState.state.get('opened').size).toBe(1);
- expect(prevState.state.get('opened').first()).toEqual(path);
+ expect(prevState.state.opened.length).toBe(1);
+ expect(prevState.state.opened[0]).toEqual(path);
const newState = toggleState(prevState, { isOpened: true, jsonpath: path });
- expect(newState.get('opened').size).toBe(0);
+ expect(newState.opened.length).toBe(0);
});
});
@@ -153,6 +153,6 @@ describe('select', () => {
const prevState = { state: DEFAULT_STATE };
prevState.state = selectWrapper(prevState, { jsonpath: path });
- expect(prevState.state.get('selectedJsonpath')).toEqual(path);
+ expect(prevState.state.selectedJsonpath).toEqual(path);
});
});
diff --git a/packages/containers/src/PieChartButton/PieChartButton.connect.jsx b/packages/containers/src/PieChartButton/PieChartButton.connect.jsx
index 2d908461d60..018edf6ecf4 100644
--- a/packages/containers/src/PieChartButton/PieChartButton.connect.jsx
+++ b/packages/containers/src/PieChartButton/PieChartButton.connect.jsx
@@ -1,10 +1,9 @@
import PropTypes from 'prop-types';
-import Immutable from 'immutable';
import omit from 'lodash/omit';
import { cmfConnect, Inject } from '@talend/react-cmf';
import PieChart from '@talend/react-components/lib/PieChart';
-export const DEFAULT_STATE = new Immutable.Map({});
+export const DEFAULT_STATE = {};
export function ContainerPieChartButton(props) {
let overlayComponent = null;
@@ -30,14 +29,14 @@ export function ContainerPieChartButton(props) {
}
const state = props.state || DEFAULT_STATE;
- const model = state.has('model') ? state.get('model').toJS() : props.model;
+ const model = 'model' in state ? state.model : props.model;
const newProps = {
...omit(props, cmfConnect.INJECTED_PROPS.concat(['getComponent', 'initialState'])),
model,
- inProgress: state.get('inProgress', props.inProgress),
- loading: state.get('loading', props.loading),
- available: state.get('available', props.available),
+ inProgress: state?.inProgress ?? props.inProgress,
+ loading: state?.loading ?? props.loading,
+ available: state?.available ?? props.available,
overlayComponent,
onClick,
};
diff --git a/packages/containers/src/PieChartButton/PieChartButton.test.js b/packages/containers/src/PieChartButton/PieChartButton.test.js
index f2e7d72dc0d..76e60a354a7 100644
--- a/packages/containers/src/PieChartButton/PieChartButton.test.js
+++ b/packages/containers/src/PieChartButton/PieChartButton.test.js
@@ -1,4 +1,3 @@
-import Immutable from 'immutable';
import { screen, render } from '@testing-library/react';
import Connected, { ContainerPieChartButton } from './PieChartButton.connect';
@@ -11,7 +10,7 @@ describe('PieChartButton connected', () => {
describe('PieChartButton container', () => {
it('should render', () => {
- const initialState = Immutable.fromJS({
+ const initialState = {
model: [
{ percentage: 10, color: 'rio-grande' },
{ percentage: 15, color: 'chestnut-rose' },
@@ -19,13 +18,13 @@ describe('PieChartButton container', () => {
{ percentage: 20, color: 'dove-gray' },
{ percentage: 15, color: 'silver-chalice' },
],
- });
+ };
const { container } = render();
expect(container.firstChild).toMatchSnapshot();
});
it('should render not available pie chart button', () => {
- const initialState = Immutable.fromJS({
+ const initialState = {
model: [
{ percentage: 10, color: 'rio-grande' },
{ percentage: 15, color: 'chestnut-rose' },
@@ -34,13 +33,13 @@ describe('PieChartButton container', () => {
{ percentage: 15, color: 'silver-chalice' },
],
available: false,
- });
+ };
const { container } = render();
expect(container).toBeEmptyDOMElement();
});
it('should render loading pie chart button', () => {
- const initialState = Immutable.fromJS({
+ const initialState = {
model: [
{ percentage: 10, color: 'rio-grande' },
{ percentage: 15, color: 'chestnut-rose' },
@@ -49,7 +48,7 @@ describe('PieChartButton container', () => {
{ percentage: 15, color: 'silver-chalice' },
],
loading: true,
- });
+ };
render();
expect(screen.getByLabelText('Loading chart')).toBeVisible();
expect(screen.getByLabelText('Loading chart')).toHaveAttribute('aria-busy', 'true');
diff --git a/packages/containers/src/SelectObject/SelectObject.component.jsx b/packages/containers/src/SelectObject/SelectObject.component.jsx
index acd7c66d523..f6fc3177756 100644
--- a/packages/containers/src/SelectObject/SelectObject.component.jsx
+++ b/packages/containers/src/SelectObject/SelectObject.component.jsx
@@ -1,5 +1,3 @@
-import ImmutablePropTypes from 'react-immutable-proptypes';
-
import classNames from 'classnames';
import PropTypes from 'prop-types';
@@ -55,12 +53,12 @@ function SelectObject({
{filteredData.map(data => (
results.onClick(event, data)}
>
- {data.get(nameAttr)}
- {data.get('currentPosition')}
+ {data[nameAttr]}
+ {data.currentPosition}
))}
@@ -80,12 +78,12 @@ SelectObject.propTypes = {
list: PropTypes.object,
filter: PropTypes.object,
schema: PropTypes.object,
- filteredData: ImmutablePropTypes.List,
+ filteredData: PropTypes.array,
results: PropTypes.shape({
selectedId: PropTypes.string,
onClick: PropTypes.func,
}),
- sourceData: ImmutablePropTypes.List,
+ sourceData: PropTypes.array,
selected: PropTypes.object,
};
diff --git a/packages/containers/src/SelectObject/SelectObject.component.test.js b/packages/containers/src/SelectObject/SelectObject.component.test.js
index 3a7421577e8..7c8c6172dc2 100644
--- a/packages/containers/src/SelectObject/SelectObject.component.test.js
+++ b/packages/containers/src/SelectObject/SelectObject.component.test.js
@@ -1,13 +1,12 @@
import { render } from '@testing-library/react';
import { mock } from '@talend/react-cmf';
-import Immutable from 'immutable';
import Component from './SelectObject.component';
describe('Component SelectObject', () => {
it('should render', () => {
const context = mock.store.context();
- const item = new Immutable.Map({ id: '1', name: 'foo' });
+ const item = { id: '1', name: 'foo', get: k => ({ id: '1', name: 'foo' })[k] };
const props = {
id: 'my-tree',
schema: {
@@ -21,7 +20,7 @@ describe('Component SelectObject', () => {
},
},
},
- sourceData: new Immutable.List([item]),
+ sourceData: Object.assign([item], { toJS: () => [{ id: '1', name: 'foo' }] }),
filter: {
className: 'my-custom-filter',
},
diff --git a/packages/containers/src/SelectObject/SelectObject.connect.js b/packages/containers/src/SelectObject/SelectObject.connect.js
index b4391ac49ff..57fdfe5a7ce 100644
--- a/packages/containers/src/SelectObject/SelectObject.connect.js
+++ b/packages/containers/src/SelectObject/SelectObject.connect.js
@@ -1,4 +1,4 @@
-import { cmfConnect } from '@talend/react-cmf';
+import cmf, { cmfConnect } from '@talend/react-cmf';
import Container, { DEFAULT_STATE } from './SelectObject.container';
import { DISPLAY_NAME as FILTER_NAME, QUERY_ATTR } from '../FilterBar/FilterBar.container';
@@ -7,7 +7,7 @@ import { DISPLAY_NAME as TREE_NAME } from '../TreeView/TreeView.container';
export function mapStateToProps(state, ownProps) {
const props = {};
if (ownProps.source) {
- props.sourceData = state.cmf.collections.getIn(ownProps.source.split('.'));
+ props.sourceData = cmf.selectors.collections.get(state, ownProps.source.split('.'));
}
if (ownProps.nameAttr && ownProps.tree) {
props.tree = {
@@ -15,15 +15,11 @@ export function mapStateToProps(state, ownProps) {
...ownProps.tree,
};
}
- const filterState = state.cmf.components.getIn([FILTER_NAME, ownProps.id]);
- if (filterState) {
- props.query = filterState.get(QUERY_ATTR, '');
- } else {
- props.query = '';
- }
- const treeState = state.cmf.components.getIn([TREE_NAME, ownProps.id]);
+ const filterState = state.cmf.components?.[FILTER_NAME]?.[ownProps.id];
+ props.query = filterState?.[QUERY_ATTR] ?? '';
+ const treeState = state.cmf.components?.[TREE_NAME]?.[ownProps.id];
if (treeState) {
- props.selectedId = treeState.get('selectedId');
+ props.selectedId = treeState.selectedId;
}
return props;
}
diff --git a/packages/containers/src/SelectObject/SelectObject.connect.test.js b/packages/containers/src/SelectObject/SelectObject.connect.test.js
index 46cc330f9e3..763f4cf91a0 100644
--- a/packages/containers/src/SelectObject/SelectObject.connect.test.js
+++ b/packages/containers/src/SelectObject/SelectObject.connect.test.js
@@ -1,5 +1,4 @@
import { mock } from '@talend/react-cmf';
-import Immutable from 'immutable';
import Container from './SelectObject.container';
import Connected, { mapStateToProps } from './SelectObject.connect';
@@ -11,21 +10,12 @@ describe('Connected SelectObject', () => {
});
it('should map state to props', () => {
const state = mock.store.state();
- const data = new Immutable.List([
- new Immutable.Map({ label: 'foo' }),
- new Immutable.Map({ label: 'bar' }),
- ]);
- state.cmf.collections = new Immutable.Map({
- width: new Immutable.Map({ data }),
- });
- state.cmf.components = new Immutable.Map({
- 'Container(FilterBar)': new Immutable.Map({
- test: new Immutable.Map({ query: 'foo' }),
- }),
- 'Container(Tree)': new Immutable.Map({
- test: new Immutable.Map({ selectedId: '27' }),
- }),
- });
+ const data = [{ label: 'foo' }, { label: 'bar' }];
+ state.cmf.collections = { width: { data } };
+ state.cmf.components = {
+ 'Container(FilterBar)': { test: { query: 'foo' } },
+ 'Container(Tree)': { test: { selectedId: '27' } },
+ };
const props = mapStateToProps(state, {
id: 'test',
nameAttr: 'label',
diff --git a/packages/containers/src/SelectObject/SelectObject.container.jsx b/packages/containers/src/SelectObject/SelectObject.container.jsx
index d5d7c00e3f7..5ec936a6de4 100644
--- a/packages/containers/src/SelectObject/SelectObject.container.jsx
+++ b/packages/containers/src/SelectObject/SelectObject.container.jsx
@@ -2,12 +2,11 @@ import { Component as RComponent } from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import { cmfConnect } from '@talend/react-cmf';
-import Immutable, { List } from 'immutable';
import Component from './SelectObject.component';
export const DISPLAY_NAME = 'Container(SelectObject)';
-export const DEFAULT_STATE = new Immutable.Map({});
+export const DEFAULT_STATE = {};
function noop() {}
@@ -18,11 +17,11 @@ function noop() {}
*/
export function getById(items, id, { idAttr = 'id' } = {}) {
let found;
- items.forEach(item => {
- if (item.get(idAttr) === id) {
- found = item.toJS();
- } else if (!found && item.get('children', new List()).size > 0) {
- found = getById(item.get('children'), id, { idAttr });
+ (items || []).forEach(item => {
+ if (item[idAttr] === id) {
+ found = item;
+ } else if (!found && (item.children ?? []).length > 0) {
+ found = getById(item.children, id, { idAttr });
}
});
return found;
@@ -35,7 +34,7 @@ export function getById(items, id, { idAttr = 'id' } = {}) {
* @return {Boolean}
*/
function isLeafElement(item) {
- return item.get('children', new List()).size === 0;
+ return (item.children ?? []).length === 0;
}
/**
@@ -46,14 +45,14 @@ function isLeafElement(item) {
* @param {String} query the query element used to match
* @param {String} nameAttr the attribute of item on which should be matched
* @param {callback} onMatch callback to call if match happen
- * @param {List