redux-paginator-immutable 17.0.16 → 17.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__tests__/createPaginator.spec.js +2 -2
- package/lib/__tests__/reducers.spec.js +2 -3
- package/lib/__tests__/selectors.spec.js +11 -13
- package/package.json +14 -7
- package/src/Info.tsx +29 -0
- package/src/LoadDataItem.tsx +84 -0
- package/src/{LoadPaginator.jsx → LoadPaginator.tsx} +77 -94
- package/src/LoadingButton.tsx +40 -0
- package/src/__tests__/createPaginator.spec.js +6 -6
- package/src/__tests__/reducers.spec.js +28 -28
- package/src/__tests__/selectors.spec.js +80 -81
- package/src/{actionTypes.js → actionTypes.ts} +0 -4
- package/src/actions.ts +157 -0
- package/src/agent.ts +62 -0
- package/src/createDataReducer.ts +98 -0
- package/src/{createItemReducer.js → createItemReducer.ts} +6 -12
- package/src/createPaginator.ts +107 -0
- package/src/{index.js → index.ts} +0 -13
- package/src/paginatorMiddleware.ts +93 -0
- package/src/reducerItemData.ts +74 -0
- package/src/reducerOperations.ts +101 -0
- package/src/{reducers.js → reducers.ts} +9 -18
- package/src/selectors.ts +113 -0
- package/src/types/{actions.js → actions.ts} +27 -39
- package/src/types/{index.js → index.ts} +3 -13
- package/src/types/{state.js → state.ts} +3 -6
- package/src/util.ts +51 -0
- package/src/{words.js → words.ts} +0 -2
- package/lib/Info.js +0 -41
- package/lib/LoadDataItem.js +0 -110
- package/lib/LoadPaginator.js +0 -216
- package/lib/LoadingButton.js +0 -75
- package/lib/actionTypes.js +0 -16
- package/lib/actions.js +0 -136
- package/lib/agent.js +0 -86
- package/lib/createDataReducer.js +0 -83
- package/lib/createItemReducer.js +0 -36
- package/lib/createPaginator.js +0 -141
- package/lib/index.js +0 -58
- package/lib/paginatorMiddleware.js +0 -102
- package/lib/reducerItemData.js +0 -63
- package/lib/reducerOperations.js +0 -114
- package/lib/reducers.js +0 -87
- package/lib/selectors.js +0 -129
- package/lib/types/actions.js +0 -1
- package/lib/types/index.js +0 -29
- package/lib/types/state.js +0 -1
- package/lib/util.js +0 -73
- package/lib/words.js +0 -15
- package/src/Info.jsx +0 -34
- package/src/LoadDataItem.jsx +0 -116
- package/src/LoadingButton.jsx +0 -55
- package/src/actions.js +0 -153
- package/src/agent.js +0 -55
- package/src/createDataReducer.js +0 -94
- package/src/createPaginator.js +0 -131
- package/src/paginatorMiddleware.js +0 -94
- package/src/reducerItemData.jsx +0 -64
- package/src/reducerOperations.jsx +0 -112
- package/src/selectors.js +0 -143
- package/src/util.js +0 -71
|
@@ -22,8 +22,8 @@ describe("createPaginator", function () {
|
|
|
22
22
|
idKey: "id_field",
|
|
23
23
|
resultsKey: "results",
|
|
24
24
|
totalKey: "count"
|
|
25
|
-
})
|
|
26
|
-
|
|
25
|
+
}),
|
|
26
|
+
action = paginator.requestPage(42, "foo=bar");
|
|
27
27
|
|
|
28
28
|
(0, _expect2.default)(action).toEqual(requestPage({
|
|
29
29
|
endpoint: "some/api/endpoint",
|
|
@@ -8,14 +8,14 @@ var _chaiImmutable = require("chai-immutable");
|
|
|
8
8
|
|
|
9
9
|
var _chaiImmutable2 = _interopRequireDefault(_chaiImmutable);
|
|
10
10
|
|
|
11
|
-
var _selectors = require("../selectors");
|
|
12
|
-
|
|
13
|
-
var _selectors2 = _interopRequireDefault(_selectors);
|
|
14
|
-
|
|
15
11
|
var _immutable = require("immutable");
|
|
16
12
|
|
|
17
13
|
var Immutable = _interopRequireWildcard(_immutable);
|
|
18
14
|
|
|
15
|
+
var _selectors = require("../selectors");
|
|
16
|
+
|
|
17
|
+
var _selectors2 = _interopRequireDefault(_selectors);
|
|
18
|
+
|
|
19
19
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
|
20
20
|
|
|
21
21
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -29,10 +29,8 @@ var getCurrentTotalResultsCount = _selectors2.default.getCurrentTotalResultsCoun
|
|
|
29
29
|
getResultsUpToPage = _selectors2.default.getResultsUpToPage,
|
|
30
30
|
isPageFetched = _selectors2.default.isPageFetched,
|
|
31
31
|
isPageFetching = _selectors2.default.isPageFetching,
|
|
32
|
-
getCurrentView = _selectors2.default.getCurrentView
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
var paginator = Immutable.Map({
|
|
32
|
+
getCurrentView = _selectors2.default.getCurrentView,
|
|
33
|
+
paginator = Immutable.Map({
|
|
36
34
|
"foo=bar": Immutable.Map({
|
|
37
35
|
page: 3,
|
|
38
36
|
token: "foo=bar",
|
|
@@ -51,9 +49,8 @@ var paginator = Immutable.Map({
|
|
|
51
49
|
total: 17,
|
|
52
50
|
view: 1
|
|
53
51
|
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
var items = Immutable.Map({
|
|
52
|
+
}),
|
|
53
|
+
items = Immutable.Map({
|
|
57
54
|
"1": Immutable.Map({
|
|
58
55
|
data: "foo1",
|
|
59
56
|
id: 1
|
|
@@ -92,9 +89,10 @@ var items = Immutable.Map({
|
|
|
92
89
|
})
|
|
93
90
|
});
|
|
94
91
|
|
|
92
|
+
|
|
95
93
|
describe("selectors", function () {
|
|
96
94
|
|
|
97
|
-
it("getAllResults
|
|
95
|
+
it("getAllResults should select all the items ids for pages with same params than the current page", function () {
|
|
98
96
|
(0, _chai.expect)(getAllResults(paginator, "foo=bar", items)).to.equal(Immutable.List([Immutable.Map({
|
|
99
97
|
data: "foo1",
|
|
100
98
|
id: 1
|
|
@@ -116,7 +114,7 @@ describe("selectors", function () {
|
|
|
116
114
|
})]));
|
|
117
115
|
});
|
|
118
116
|
|
|
119
|
-
it("getResultsUpToPage
|
|
117
|
+
it("getResultsUpToPage should select all the items ids for pages with same params than the current page", function () {
|
|
120
118
|
(0, _chai.expect)(getResultsUpToPage(paginator, "foo=bar", items, 2, 2)).to.equal(Immutable.List([Immutable.Map({
|
|
121
119
|
data: "foo1",
|
|
122
120
|
id: 1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redux-paginator-immutable",
|
|
3
|
-
"version": "17.0.
|
|
3
|
+
"version": "17.0.18",
|
|
4
4
|
"description": "redux-paginator-immutable helps you deal with paginated API by composing your existing reducers",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"babel": {
|
|
@@ -37,12 +37,13 @@
|
|
|
37
37
|
"build": "npm run build:lib",
|
|
38
38
|
"clean": "rimraf dist lib",
|
|
39
39
|
"check": "npm-check -u -i babel-jest -i jest --specials=bin,eslint,babel,webpack",
|
|
40
|
-
"eslint": "eslint --ext .jsx,.js src --fix",
|
|
41
|
-
"load": "npm run test && npm run eslint && npm run clean && npm run build && npm publish",
|
|
42
|
-
"test": "mocha
|
|
40
|
+
"eslint": "eslint --ext .jsx,.js,.ts,.tsx src --fix",
|
|
41
|
+
"load": "npm run test && npm run ts && npm run eslint && npm run clean && npm run build && npm publish",
|
|
42
|
+
"test": "ts-mocha src/__tests__/*.spec.js",
|
|
43
43
|
"test:watch": "npm test -- --watch",
|
|
44
44
|
"test:cov": "babel-node ./node_modules/isparta/bin/isparta cover ./node_modules/mocha/bin/_mocha -- --recursive \"src/**/__tests__/*\" --require src/__tests__/setup.js",
|
|
45
|
-
"test:codecov": "cat ./coverage/coverage.json | ./node_modules/.bin/codecov"
|
|
45
|
+
"test:codecov": "cat ./coverage/coverage.json | ./node_modules/.bin/codecov",
|
|
46
|
+
"ts": "tsc --build --clean"
|
|
46
47
|
},
|
|
47
48
|
"repository": {
|
|
48
49
|
"type": "git",
|
|
@@ -70,6 +71,9 @@
|
|
|
70
71
|
},
|
|
71
72
|
"homepage": "https://github.com/cristian-sima/redux-paginator-immutable#readme",
|
|
72
73
|
"devDependencies": {
|
|
74
|
+
"@types/superagent": "^4.1.15",
|
|
75
|
+
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
|
76
|
+
"@typescript-eslint/parser": "^5.10.2",
|
|
73
77
|
"babel-cli": "^6.26.0",
|
|
74
78
|
"babel-eslint": "^10.1.0",
|
|
75
79
|
"babel-plugin-transform-decorators-legacy": "^1.3.5",
|
|
@@ -83,19 +87,22 @@
|
|
|
83
87
|
"codecov": "^3.8.1",
|
|
84
88
|
"cross-env": "^6.0.3",
|
|
85
89
|
"es3ify": "^0.2.2",
|
|
86
|
-
"eslint": "^
|
|
90
|
+
"eslint": "^8.8.0",
|
|
91
|
+
"eslint-plugin-import": "^2.25.4",
|
|
87
92
|
"eslint-plugin-react": "^7.23.1",
|
|
88
93
|
"expect": "^24.9.0",
|
|
89
|
-
"flow-bin": "^0.148.0",
|
|
90
94
|
"flux-standard-action": "^2.1.1",
|
|
91
95
|
"glob": "^7.1.6",
|
|
92
96
|
"isparta": "^4.1.1",
|
|
93
97
|
"mocha": "^6.2.2",
|
|
94
98
|
"npm-check": "^5.9.2",
|
|
95
99
|
"rimraf": "^3.0.2",
|
|
100
|
+
"ts-mocha": "^9.0.2",
|
|
101
|
+
"typescript": "^4.5.5",
|
|
96
102
|
"webpack": "^4.41.2"
|
|
97
103
|
},
|
|
98
104
|
"dependencies": {
|
|
105
|
+
"create-subscription": "^17.0.0",
|
|
99
106
|
"depcheck": "^1.4.3",
|
|
100
107
|
"immutable": "*",
|
|
101
108
|
"query-string": "^7.1.0",
|
package/src/Info.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type InfoPropTypes = {
|
|
2
|
+
shown: number;
|
|
3
|
+
total: number;
|
|
4
|
+
one: string;
|
|
5
|
+
all: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { words as x25Words } from "x25/utility";
|
|
10
|
+
import words from "./words";
|
|
11
|
+
|
|
12
|
+
const
|
|
13
|
+
getNumberForm = (value: number, one: string, all: string): string => {
|
|
14
|
+
if (value === 1) {
|
|
15
|
+
return `1 ${one}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return `${x25Words.getNumberTense(value)} ${all}`;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
Info = ({ shown, total, one, all }: InfoPropTypes) => (
|
|
22
|
+
<div className="text-muted">
|
|
23
|
+
{`${words.Showing} `}
|
|
24
|
+
{shown === total ? `${words.All} - ` : `${shown} ${words.Of}`}
|
|
25
|
+
{` ${getNumberForm(total, one, all)}`}
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export default Info;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
type LoadDataItemPropTypes = {
|
|
4
|
+
isFetching: boolean;
|
|
5
|
+
fetched: boolean;
|
|
6
|
+
id: string;
|
|
7
|
+
hasError: boolean;
|
|
8
|
+
data: any;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
shouldFetch: any;
|
|
11
|
+
fetchItem: () => void;
|
|
12
|
+
};
|
|
13
|
+
type OwnProps = {
|
|
14
|
+
id: string;
|
|
15
|
+
settings: {
|
|
16
|
+
selectors: any;
|
|
17
|
+
dataItemURL: string;
|
|
18
|
+
endpoint: string;
|
|
19
|
+
manageEntity: any;
|
|
20
|
+
normalizeDataItem: any;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
import { connect } from "react-redux";
|
|
24
|
+
import { LargeErrorMessage, LoadingMessage } from "x25/Messages";
|
|
25
|
+
import { fetchItem as fetchItemAction } from "./actions";
|
|
26
|
+
import words from "./words";
|
|
27
|
+
|
|
28
|
+
const
|
|
29
|
+
mapStateToProps = (state: any, {
|
|
30
|
+
settings: {
|
|
31
|
+
selectors,
|
|
32
|
+
},
|
|
33
|
+
id,
|
|
34
|
+
}: OwnProps) => ({
|
|
35
|
+
data : selectors.getItem(state, id),
|
|
36
|
+
hasError : selectors.getItemHasError(state, id),
|
|
37
|
+
fetched : selectors.getItemIsFetched(state, id),
|
|
38
|
+
isFetching : selectors.getIsFetchingItemInfo(state, id),
|
|
39
|
+
shouldFetch : selectors.getShouldFetchItemInfo(state, id),
|
|
40
|
+
}),
|
|
41
|
+
mapDispatchToProps = (dispatch: any, {
|
|
42
|
+
id,
|
|
43
|
+
settings,
|
|
44
|
+
}: OwnProps) => ({
|
|
45
|
+
fetchItem () {
|
|
46
|
+
dispatch(fetchItemAction({
|
|
47
|
+
...settings,
|
|
48
|
+
id,
|
|
49
|
+
}));
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
|
|
53
|
+
LoadDataItem = (props: LoadDataItemPropTypes) : any => {
|
|
54
|
+
const {
|
|
55
|
+
children,
|
|
56
|
+
data,
|
|
57
|
+
isFetching,
|
|
58
|
+
shouldFetch,
|
|
59
|
+
hasError,
|
|
60
|
+
fetchItem,
|
|
61
|
+
} = props;
|
|
62
|
+
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (shouldFetch) {
|
|
65
|
+
fetchItem();
|
|
66
|
+
}
|
|
67
|
+
}, [shouldFetch, isFetching, hasError]);
|
|
68
|
+
|
|
69
|
+
if (isFetching) {
|
|
70
|
+
return <LoadingMessage message={words.LoadingData} />;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (hasError) {
|
|
74
|
+
return <LargeErrorMessage message={words.ThereWasAProblem} onRetry={fetchItem} />;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (data.size === 0) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return children;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default connect(mapStateToProps, mapDispatchToProps)(LoadDataItem);
|
|
@@ -1,72 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
|
|
2
|
+
import React, { Component } from "react";
|
|
3
|
+
import * as Immutable from "immutable";
|
|
4
|
+
import { connect } from "react-redux";
|
|
5
|
+
import { bindActionCreators } from "redux";
|
|
6
|
+
import { LargeErrorMessage, LoadingMessage } from "x25/Messages";
|
|
7
|
+
import selectors from "./selectors";
|
|
8
|
+
import LoadingButton from "./LoadingButton";
|
|
9
|
+
import words from "./words";
|
|
3
10
|
|
|
4
11
|
type Settings = {
|
|
5
12
|
key: string;
|
|
6
13
|
rowsPerLoad: number;
|
|
7
14
|
manipulateItems: (items: any) => void;
|
|
8
|
-
resetView: (data
|
|
15
|
+
resetView: (data: any) => void;
|
|
9
16
|
changeView: (data: any) => void;
|
|
10
|
-
requestPage: (page: string, token
|
|
11
|
-
}
|
|
12
|
-
|
|
17
|
+
requestPage: (page: string, token: string) => any;
|
|
18
|
+
};
|
|
13
19
|
type OwnProps = {
|
|
14
20
|
token: string;
|
|
15
21
|
settings: Settings;
|
|
16
22
|
};
|
|
17
|
-
|
|
18
23
|
type LoadPaginatorPropTypes = {
|
|
19
24
|
token: string;
|
|
20
25
|
children: any;
|
|
21
26
|
settings: Settings;
|
|
22
27
|
paginator: any;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
resetView: (token : string) => void;
|
|
35
|
-
|
|
36
|
-
loadData: (page : number) => void;
|
|
37
|
-
changeFilter: (filter : string) => (event : { target : { value : string } }) => void;
|
|
28
|
+
changeView: (info: {
|
|
29
|
+
token: string;
|
|
30
|
+
view: number;
|
|
31
|
+
}) => void;
|
|
32
|
+
resetView: (token: string) => void;
|
|
33
|
+
loadData: (page: number) => void;
|
|
34
|
+
changeFilter: (filter: string) => (event: {
|
|
35
|
+
target: {
|
|
36
|
+
value: string;
|
|
37
|
+
};
|
|
38
|
+
}) => void;
|
|
38
39
|
};
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
import { connect } from "react-redux";
|
|
43
|
-
import { bindActionCreators } from "redux";
|
|
44
|
-
|
|
45
|
-
import selectors from "./selectors";
|
|
46
|
-
|
|
47
|
-
import LoadingButton from "./LoadingButton";
|
|
48
|
-
|
|
49
|
-
import { LargeErrorMessage, LoadingMessage } from "x25/Messages";
|
|
50
|
-
import words from "./words";
|
|
51
|
-
|
|
52
|
-
const mapStateToProps = (state, { token, settings } : OwnProps) => {
|
|
53
|
-
|
|
54
|
-
const { list, entities } = selectors.getPaginators(state, settings.key);
|
|
55
|
-
|
|
41
|
+
const
|
|
42
|
+
mapStateToProps = (state : any, { token, settings }: OwnProps) => {
|
|
56
43
|
const
|
|
44
|
+
{ list, entities } = selectors.getPaginators(state, settings.key),
|
|
57
45
|
currentPage = selectors.getCurrentView(list, token),
|
|
58
46
|
isFetching = selectors.isPageFetching(list, token, currentPage),
|
|
59
47
|
isFetched = selectors.isPageFetched(list, token, currentPage),
|
|
60
48
|
isNextFetching = selectors.isPageFetching(list, token, currentPage + 1),
|
|
61
49
|
isNextFetched = selectors.isPageFetched(list, token, currentPage + 1),
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
),
|
|
50
|
+
// eslint-disable-next-line max-len
|
|
51
|
+
resultsUpTo = selectors.getResultsUpToPage(list, token, entities, currentPage, settings.rowsPerLoad),
|
|
65
52
|
items = settings.manipulateItems(resultsUpTo),
|
|
66
53
|
total = selectors.getCurrentTotalResultsCount(list, token),
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
54
|
+
// currentPage was previously given to the following function
|
|
55
|
+
hasProblems = selectors.hasPageProblems(list, token),
|
|
56
|
+
shouldLoadNext = !isNextFetched && !isNextFetching;
|
|
70
57
|
|
|
71
58
|
return {
|
|
72
59
|
paginator: Immutable.Map({
|
|
@@ -80,27 +67,59 @@ const mapStateToProps = (state, { token, settings } : OwnProps) => {
|
|
|
80
67
|
}),
|
|
81
68
|
};
|
|
82
69
|
},
|
|
83
|
-
mapDispatchToProps = (dispatch
|
|
70
|
+
mapDispatchToProps = (dispatch : any, {
|
|
71
|
+
token,
|
|
72
|
+
settings,
|
|
73
|
+
}: OwnProps) => ({
|
|
84
74
|
...bindActionCreators({
|
|
85
75
|
resetView : settings.resetView,
|
|
86
76
|
changeView : settings.changeView,
|
|
87
77
|
}, dispatch),
|
|
88
|
-
loadData (page) {
|
|
78
|
+
loadData (page : any) {
|
|
89
79
|
dispatch(settings.requestPage(page, token));
|
|
90
80
|
},
|
|
91
81
|
});
|
|
92
82
|
|
|
83
|
+
|
|
84
|
+
// new
|
|
85
|
+
|
|
86
|
+
/* eslint-disable */
|
|
93
87
|
class LoadPaginator extends Component<LoadPaginatorPropTypes> {
|
|
94
88
|
|
|
95
|
-
handleLoadMoreClick: () =>
|
|
89
|
+
handleLoadMoreClick: () => any;
|
|
90
|
+
|
|
91
|
+
componentDidMount () {
|
|
92
|
+
const
|
|
93
|
+
{ paginator, loadData } = this.props,
|
|
94
|
+
isFetched = paginator.get("isFetched"),
|
|
95
|
+
isFetching = paginator.get("isFetching"),
|
|
96
|
+
currentPage = paginator.get("currentPage"),
|
|
97
|
+
shouldFetch = !isFetched && !isFetching;
|
|
98
|
+
|
|
99
|
+
if (shouldFetch) {
|
|
100
|
+
loadData(currentPage);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
UNSAFE_componentWillReceiveProps (nextProps : LoadPaginatorPropTypes) {
|
|
105
|
+
const
|
|
106
|
+
{ loadData, paginator } = nextProps,
|
|
107
|
+
isFetched = paginator.get("isFetched"),
|
|
108
|
+
isFetching = paginator.get("isFetching"),
|
|
109
|
+
currentPage = paginator.get("currentPage"),
|
|
110
|
+
shouldFetch = !isFetched && !isFetching;
|
|
96
111
|
|
|
97
|
-
|
|
112
|
+
if (shouldFetch) {
|
|
113
|
+
loadData(currentPage);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
constructor (props: LoadPaginatorPropTypes) {
|
|
98
118
|
super(props);
|
|
99
119
|
|
|
100
120
|
this.handleLoadMoreClick = () => {
|
|
101
|
-
const { paginator, token, changeView, loadData } = this.props;
|
|
102
|
-
|
|
103
121
|
const
|
|
122
|
+
{ paginator, token, changeView, loadData } = this.props,
|
|
104
123
|
currentPage = paginator.get("currentPage"),
|
|
105
124
|
hasProblems = paginator.get("hasProblems"),
|
|
106
125
|
shouldLoadNext = paginator.get("shouldLoadNext");
|
|
@@ -120,40 +139,8 @@ class LoadPaginator extends Component<LoadPaginatorPropTypes> {
|
|
|
120
139
|
};
|
|
121
140
|
}
|
|
122
141
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
isFetched = paginator.get("isFetched"),
|
|
128
|
-
isFetching = paginator.get("isFetching"),
|
|
129
|
-
currentPage = paginator.get("currentPage");
|
|
130
|
-
|
|
131
|
-
const shouldFetch = !isFetched && !isFetching;
|
|
132
|
-
|
|
133
|
-
if (shouldFetch) {
|
|
134
|
-
loadData(currentPage);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
UNSAFE_componentWillReceiveProps (nextProps) {
|
|
139
|
-
const { loadData, paginator } = nextProps;
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
isFetched = paginator.get("isFetched"),
|
|
143
|
-
isFetching = paginator.get("isFetching"),
|
|
144
|
-
currentPage = paginator.get("currentPage");
|
|
145
|
-
|
|
146
|
-
const shouldFetch = !isFetched && !isFetching;
|
|
147
|
-
|
|
148
|
-
if (shouldFetch) {
|
|
149
|
-
loadData(currentPage);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
shouldComponentUpdate (nextProps : LoadPaginatorPropTypes) {
|
|
154
|
-
return (
|
|
155
|
-
this.props.paginator !== nextProps.paginator
|
|
156
|
-
);
|
|
142
|
+
shouldComponentUpdate (nextProps: LoadPaginatorPropTypes) {
|
|
143
|
+
return this.props.paginator !== nextProps.paginator;
|
|
157
144
|
}
|
|
158
145
|
|
|
159
146
|
componentWillUnmount () {
|
|
@@ -161,23 +148,18 @@ class LoadPaginator extends Component<LoadPaginatorPropTypes> {
|
|
|
161
148
|
}
|
|
162
149
|
|
|
163
150
|
render () {
|
|
164
|
-
const { paginator } = this.props;
|
|
165
|
-
|
|
166
151
|
const
|
|
152
|
+
{ paginator } = this.props,
|
|
167
153
|
items = paginator.get("items"),
|
|
168
154
|
hasProblems = paginator.get("hasProblems"),
|
|
169
155
|
currentPage = paginator.get("currentPage"),
|
|
170
156
|
isFetching = paginator.get("isFetching"),
|
|
171
|
-
total = paginator.get("total")
|
|
172
|
-
|
|
173
|
-
const
|
|
157
|
+
total = paginator.get("total"),
|
|
174
158
|
isEmpty = items.size === 0,
|
|
175
159
|
showLoading = total !== items.size;
|
|
176
160
|
|
|
177
161
|
if (isEmpty && isFetching) {
|
|
178
|
-
return
|
|
179
|
-
<LoadingMessage message={words.LoadingData} />
|
|
180
|
-
);
|
|
162
|
+
return <LoadingMessage message={words.LoadingData} />;
|
|
181
163
|
}
|
|
182
164
|
|
|
183
165
|
if (hasProblems && currentPage === 1) {
|
|
@@ -190,7 +172,7 @@ class LoadPaginator extends Component<LoadPaginatorPropTypes> {
|
|
|
190
172
|
}
|
|
191
173
|
|
|
192
174
|
return (
|
|
193
|
-
|
|
175
|
+
<>
|
|
194
176
|
{React.cloneElement(this.props.children, this.props)}
|
|
195
177
|
{
|
|
196
178
|
showLoading ? (
|
|
@@ -201,9 +183,10 @@ class LoadPaginator extends Component<LoadPaginatorPropTypes> {
|
|
|
201
183
|
/>
|
|
202
184
|
) : null
|
|
203
185
|
}
|
|
204
|
-
|
|
186
|
+
</>
|
|
205
187
|
);
|
|
206
188
|
}
|
|
189
|
+
|
|
207
190
|
}
|
|
208
191
|
|
|
209
192
|
export default connect(mapStateToProps, mapDispatchToProps)(LoadPaginator);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ErrorMessage, LoadingMessage } from "x25/Messages";
|
|
3
|
+
|
|
4
|
+
type LoadingButtonPropTypes = {
|
|
5
|
+
isFetching: boolean;
|
|
6
|
+
hasProblems: boolean;
|
|
7
|
+
onLoadMoreClick: () => void;
|
|
8
|
+
};
|
|
9
|
+
import words from "./words";
|
|
10
|
+
|
|
11
|
+
class LoadingButton extends React.Component<LoadingButtonPropTypes> {
|
|
12
|
+
|
|
13
|
+
shouldComponentUpdate (nextProps: LoadingButtonPropTypes) {
|
|
14
|
+
const { hasProblems, isFetching } = this.props;
|
|
15
|
+
|
|
16
|
+
return hasProblems !== nextProps.hasProblems || isFetching !== nextProps.isFetching;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
render () {
|
|
20
|
+
const { isFetching, hasProblems, onLoadMoreClick } = this.props;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className="text-center my-2">
|
|
24
|
+
{hasProblems ? <ErrorMessage message={words.ThereWasAProblem} /> : null}
|
|
25
|
+
{isFetching ? <LoadingMessage message={words.LoadingData} sm /> : (
|
|
26
|
+
<button
|
|
27
|
+
className="btn btn-outline-info d-print-none"
|
|
28
|
+
disabled={isFetching}
|
|
29
|
+
onClick={onLoadMoreClick}
|
|
30
|
+
type="button">
|
|
31
|
+
{isFetching ? words.LoadingData : words.LoadMore}
|
|
32
|
+
</button>
|
|
33
|
+
)}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default LoadingButton;
|
|
@@ -16,12 +16,12 @@ describe("createPaginator", () => {
|
|
|
16
16
|
|
|
17
17
|
it("should create correct request action creator", () => {
|
|
18
18
|
const paginator = createPaginator("some/api/endpoint", {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
pageArgName : "p",
|
|
20
|
+
idKey : "id_field",
|
|
21
|
+
resultsKey : "results",
|
|
22
|
+
totalKey : "count",
|
|
23
|
+
}),
|
|
24
|
+
action = paginator.requestPage(42, "foo=bar");
|
|
25
25
|
|
|
26
26
|
expect(action).
|
|
27
27
|
toEqual(requestPage({
|
|
@@ -20,33 +20,33 @@ import {
|
|
|
20
20
|
} from "../reducers";
|
|
21
21
|
|
|
22
22
|
const requestPageAction = requestPage({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
23
|
+
endpoint : "some/api/endpoint",
|
|
24
|
+
resultsKey : "results",
|
|
25
|
+
totalKey : "total",
|
|
26
|
+
pageArgName : "p",
|
|
27
|
+
idKey : "id",
|
|
28
|
+
page : 2,
|
|
29
|
+
token : "foo=bar",
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
receivePageAction = receivePage({
|
|
33
|
+
endpoint : "some/api/endpoint/",
|
|
34
|
+
pageArgName : "p",
|
|
35
|
+
idKey : "id",
|
|
36
|
+
page : 2,
|
|
37
|
+
token : "foo=bar",
|
|
38
|
+
items : [
|
|
39
|
+
{
|
|
40
|
+
id : "baz",
|
|
41
|
+
fooField : "bazValue",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id : "bar",
|
|
45
|
+
fooField : "barValue",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
total: 2,
|
|
49
|
+
});
|
|
50
50
|
|
|
51
51
|
describe("pages reducer", () => {
|
|
52
52
|
|
|
@@ -76,7 +76,7 @@ describe("pages reducer", () => {
|
|
|
76
76
|
view : 1,
|
|
77
77
|
fetched : false,
|
|
78
78
|
}),
|
|
79
|
-
})
|
|
79
|
+
}),
|
|
80
80
|
);
|
|
81
81
|
});
|
|
82
82
|
|