Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFR] Migrate reducers to TypeScript #2857

Merged
merged 2 commits into from
Feb 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions packages/ra-core/src/actions/listActions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
export const CRUD_CHANGE_LIST_PARAMS = 'RA/CRUD_CHANGE_LIST_PARAMS';

interface Params {
sort: string;
order: string;
page: number;
perPage: number;
filter: any;
}

export interface ChangeListParamsAction {
readonly type: typeof CRUD_CHANGE_LIST_PARAMS;
readonly payload: any;
readonly payload: Params;
readonly meta: { resource: string };
}
export const changeListParams = (
resource: string,
params: any
params: Params
): ChangeListParamsAction => ({
type: CRUD_CHANGE_LIST_PARAMS,
payload: params,
Expand All @@ -16,15 +24,15 @@ export const changeListParams = (

export const SET_LIST_SELECTED_IDS = 'RA/SET_LIST_SELECTED_IDS';

export interface SetListLelectedIdsAction {
export interface SetListSelectedIdsAction {
readonly type: typeof SET_LIST_SELECTED_IDS;
readonly payload: [];
readonly meta: { resource: string };
}
export const setListSelectedIds = (
resource: string,
ids: []
): SetListLelectedIdsAction => ({
): SetListSelectedIdsAction => ({
type: SET_LIST_SELECTED_IDS,
payload: ids,
meta: { resource },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Reducer } from 'redux';
import { USER_LOGIN_SUCCESS, USER_LOGOUT } from '../../actions';

const initialState = { isLoggedIn: false };

export default (previousState = initialState, action) => {
interface State {
isLoggedIn: boolean;
}

const authReducer: Reducer<State> = (previousState = initialState, action) => {
switch (action.type) {
case USER_LOGIN_SUCCESS:
return { ...previousState, isLoggedIn: true };
Expand All @@ -14,3 +19,5 @@ export default (previousState = initialState, action) => {
};

export const isLoggedIn = state => state.isLoggedIn;

export default authReducer;
32 changes: 0 additions & 32 deletions packages/ra-core/src/reducer/admin/loading.spec.js

This file was deleted.

32 changes: 32 additions & 0 deletions packages/ra-core/src/reducer/admin/loading.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import expect from 'expect';
import {
FETCH_START,
FETCH_END,
FETCH_ERROR,
FETCH_CANCEL,
} from '../../actions/fetchActions';

import {
USER_LOGIN_LOADING,
USER_LOGIN_SUCCESS,
USER_LOGIN_FAILURE,
} from '../../actions/authActions';

import reducer from './loading';

describe('loading reducer', () => {
it('should return 0 by default', () => {
expect(reducer(undefined, { type: 'ANY' })).toEqual(0);
});
it('should increase with fetch or auth actions', () => {
expect(reducer(0, { type: FETCH_START })).toEqual(1);
expect(reducer(0, { type: USER_LOGIN_LOADING })).toEqual(1);
});
it('should decrease with fetch or auth actions success or failure', () => {
expect(reducer(1, { type: FETCH_END })).toEqual(0);
expect(reducer(1, { type: FETCH_ERROR })).toEqual(0);
expect(reducer(1, { type: FETCH_CANCEL })).toEqual(0);
expect(reducer(1, { type: USER_LOGIN_SUCCESS })).toEqual(0);
expect(reducer(1, { type: USER_LOGIN_FAILURE })).toEqual(0);
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Reducer } from 'redux';
import {
FETCH_START,
FETCH_END,
Expand All @@ -11,7 +12,9 @@ import {
USER_LOGIN_FAILURE,
} from '../../actions/authActions';

export default (previousState = 0, { type }) => {
type State = number;

const loadingReducer: Reducer<State> = (previousState = 0, { type }) => {
switch (type) {
case FETCH_START:
case USER_LOGIN_LOADING:
Expand All @@ -26,3 +29,5 @@ export default (previousState = 0, { type }) => {
return previousState;
}
};

export default loadingReducer;
23 changes: 0 additions & 23 deletions packages/ra-core/src/reducer/admin/record.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import assert from 'assert';
import expect from 'expect';
import { INITIALIZE_FORM, RESET_FORM } from '../../actions/formActions';
import reducer from './record';

describe('record reducer', () => {
it('should return an empty record by default', () => {
assert.deepEqual({}, reducer(undefined, {}));
expect(reducer(undefined, { type: 'OTHER_ACTION' })).toEqual({});
});

it('should return an empty record upon RESET_FORM', () => {
assert.deepEqual({}, reducer({ foo: 'bar' }, { type: RESET_FORM }));
expect(reducer({ foo: 'bar' }, { type: RESET_FORM })).toEqual({});
});

it('should return the current record with new fields upon INITIALIZE_FORM', () => {
assert.deepEqual(
{ foo: 'bar', bar: 'foo', deep: { very: { deep: 'gotme' } } },
expect(
reducer(
{ foo: 'bar' },
{
type: INITIALIZE_FORM,
payload: { bar: 'foo', 'deep.very.deep': 'gotme' },
}
)
);
).toEqual({
foo: 'bar',
bar: 'foo',
deep: { very: { deep: 'gotme' } },
});
});
});
42 changes: 42 additions & 0 deletions packages/ra-core/src/reducer/admin/record.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Reducer } from 'redux';
import {
INITIALIZE_FORM,
InitializeFormAction,
RESET_FORM,
ResetFormAction,
} from '../../actions/formActions';
import set from 'lodash/set';

const initialState = {};

interface State {
[key: string]: any;
}

type ActionTypes =
| InitializeFormAction
| ResetFormAction
| { type: 'OTHER_ACTION' };

const recordReducer: Reducer<State> = (
previousState = initialState,
action: ActionTypes
) => {
if (action.type === RESET_FORM) {
return initialState;
}

if (action.type === INITIALIZE_FORM) {
return Object.keys(action.payload).reduce(
(acc, key) => {
// Ensure we correctly set default values for path with dot notation
set(acc, key, action.payload[key]);
return acc;
},
{ ...previousState }
);
}
return previousState;
};

export default recordReducer;
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
import { CRUD_GET_MANY_REFERENCE_SUCCESS } from '../../../actions/dataActions';
import { Reducer } from 'redux';
import {
CRUD_GET_MANY_REFERENCE_SUCCESS,
CrudGetManyReferenceSuccessAction,
} from '../../../actions/dataActions';
import { Identifier, ReduxState } from '../../../types';

const initialState = {};

export default (previousState = initialState, { type, payload, meta }) => {
switch (type) {
interface State {
[relatedTo: string]: { ids: Identifier[]; total: number };
}

type ActionTypes =
| CrudGetManyReferenceSuccessAction
| { type: 'OTHER_ACTION'; payload: any; meta?: any };

const oneToManyReducer: Reducer<State> = (
previousState = initialState,
action: ActionTypes
) => {
switch (action.type) {
case CRUD_GET_MANY_REFERENCE_SUCCESS:
return {
...previousState,
[meta.relatedTo]: {
ids: payload.data.map(record => record.id),
total: payload.total,
[action.meta.relatedTo]: {
ids: action.payload.data.map(record => record.id),
total: action.payload.total,
},
};
default:
return previousState;
}
};

export const getIds = (state, relatedTo) =>
export const getIds = (state: ReduxState, relatedTo) =>
state.admin.references.oneToMany[relatedTo] &&
state.admin.references.oneToMany[relatedTo].ids;

export const getTotal = (state, relatedTo) =>
export const getTotal = (state: ReduxState, relatedTo) =>
state.admin.references.oneToMany[relatedTo] &&
state.admin.references.oneToMany[relatedTo].total;

export const getReferences = (state, reference, relatedTo) => {
export const getReferences = (state: ReduxState, reference, relatedTo) => {
const ids = getIds(state, relatedTo);
if (typeof ids === 'undefined') return undefined;
if (typeof ids === 'undefined') {
return undefined;
}

if (!state.admin.resources[reference]) {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -57,8 +75,10 @@ export const getReferences = (state, reference, relatedTo) => {
}, {});
};

export const getReferencesByIds = (state, reference, ids) => {
if (ids.length === 0) return {};
export const getReferencesByIds = (state: ReduxState, reference, ids) => {
if (ids.length === 0) {
return {};
}

if (!state.admin.resources[reference]) {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -100,3 +120,5 @@ export const nameRelatedTo = (reference, id, resource, target, filter = {}) => {
.map(key => `${key}=${JSON.stringify(filter[key])}`)
.join('&')}`;
};

export default oneToManyReducer;
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import { Reducer } from 'redux';
import {
CRUD_GET_MATCHING_SUCCESS,
CrudGetMatchingSuccessAction,
CRUD_GET_MATCHING_FAILURE,
CrudGetMatchingFailureAction,
} from '../../../actions/dataActions';
import { Identifier } from '../../../types';

const initialState = {};

export default (previousState = initialState, { type, payload, meta }) => {
switch (type) {
interface State {
[relatedTo: string]: { error?: string | object } | Identifier[];
}

type ActionTypes =
| CrudGetMatchingSuccessAction
| CrudGetMatchingFailureAction
| { type: 'OTHER_ACTION' };

const possibleValuesreducer: Reducer<State> = (
previousState = initialState,
action: ActionTypes
) => {
switch (action.type) {
case CRUD_GET_MATCHING_SUCCESS:
return {
...previousState,
[meta.relatedTo]: payload.data.map(record => record.id),
[action.meta.relatedTo]: action.payload.data.map(
record => record.id
),
};
case CRUD_GET_MATCHING_FAILURE:
return {
...previousState,
[meta.relatedTo]: { error: payload.error },
[action.meta.relatedTo]: { error: action.error },
};
default:
return previousState;
Expand All @@ -40,10 +58,12 @@ export const getPossibleReferences = (
possibleValues = Array.from(possibleValues);
selectedIds.forEach(
id =>
possibleValues.some(value => value == id) ||
possibleValues.some(value => value === id) ||
possibleValues.unshift(id)
);
return possibleValues
.map(id => referenceState.data[id])
.filter(r => typeof r !== 'undefined');
};

export default possibleValuesreducer;
Loading