@blaze-cms/plugin-data-ui 0.140.3 → 0.141.0-alpha.1
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/CHANGELOG.md +27 -0
- package/lib/components/EntityManager/Entity/Entity.js +9 -1
- package/lib/components/EntityManager/Entity/Entity.js.map +1 -1
- package/lib/components/EntityManager/Entity/EntityHeader/EntityHeader.js +18 -4
- package/lib/components/EntityManager/Entity/EntityHeader/EntityHeader.js.map +1 -1
- package/lib/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js +1 -1
- package/lib/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js.map +1 -1
- package/lib/components/InfoBoxes/helpers/build-dynamic-query.js +1 -1
- package/lib/components/InfoBoxes/helpers/build-dynamic-query.js.map +1 -1
- package/lib/components/InfoBoxes/presentational/InfoBox.js +2 -1
- package/lib/components/InfoBoxes/presentational/InfoBox.js.map +1 -1
- package/lib/components/ListingTable/ListingTable.js +116 -120
- package/lib/components/ListingTable/ListingTable.js.map +1 -1
- package/lib/components/ListingTable/ListingTableContent/ListingTableContent.js +18 -19
- package/lib/components/ListingTable/ListingTableContent/ListingTableContent.js.map +1 -1
- package/lib/components/ListingTable/mappers/populate-rows.js +3 -2
- package/lib/components/ListingTable/mappers/populate-rows.js.map +1 -1
- package/lib/components/ListingTable/service/index.js +11 -2
- package/lib/components/ListingTable/service/index.js.map +1 -1
- package/lib/components/hooks/useCallbackDebounce.js +22 -0
- package/lib/components/hooks/useCallbackDebounce.js.map +1 -0
- package/lib/utils/build-listing-query.js +1 -1
- package/lib/utils/build-listing-query.js.map +1 -1
- package/lib/utils/get-default-query-params.js +1 -1
- package/lib/utils/get-default-query-params.js.map +1 -1
- package/lib-es/components/EntityManager/Entity/Entity.js +12 -1
- package/lib-es/components/EntityManager/Entity/Entity.js.map +1 -1
- package/lib-es/components/EntityManager/Entity/EntityHeader/EntityHeader.js +18 -4
- package/lib-es/components/EntityManager/Entity/EntityHeader/EntityHeader.js.map +1 -1
- package/lib-es/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js +1 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js.map +1 -1
- package/lib-es/components/InfoBoxes/helpers/build-dynamic-query.js +1 -0
- package/lib-es/components/InfoBoxes/helpers/build-dynamic-query.js.map +1 -1
- package/lib-es/components/InfoBoxes/presentational/InfoBox.js +2 -1
- package/lib-es/components/InfoBoxes/presentational/InfoBox.js.map +1 -1
- package/lib-es/components/ListingTable/ListingTable.js +58 -57
- package/lib-es/components/ListingTable/ListingTable.js.map +1 -1
- package/lib-es/components/ListingTable/ListingTableContent/ListingTableContent.js +18 -19
- package/lib-es/components/ListingTable/ListingTableContent/ListingTableContent.js.map +1 -1
- package/lib-es/components/ListingTable/mappers/populate-rows.js +20 -17
- package/lib-es/components/ListingTable/mappers/populate-rows.js.map +1 -1
- package/lib-es/components/ListingTable/service/index.js +7 -1
- package/lib-es/components/ListingTable/service/index.js.map +1 -1
- package/lib-es/components/hooks/useCallbackDebounce.js +12 -0
- package/lib-es/components/hooks/useCallbackDebounce.js.map +1 -0
- package/lib-es/utils/build-listing-query.js +1 -0
- package/lib-es/utils/build-listing-query.js.map +1 -1
- package/lib-es/utils/get-default-query-params.js +1 -1
- package/lib-es/utils/get-default-query-params.js.map +1 -1
- package/package.json +8 -7
- package/src/components/EntityManager/Entity/Entity.js +18 -0
- package/src/components/EntityManager/Entity/EntityHeader/EntityHeader.js +24 -11
- package/src/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js +1 -0
- package/src/components/InfoBoxes/helpers/build-dynamic-query.js +1 -0
- package/src/components/InfoBoxes/presentational/InfoBox.js +2 -2
- package/src/components/ListingTable/ListingTable.js +86 -93
- package/src/components/ListingTable/ListingTableContent/ListingTableContent.js +20 -18
- package/src/components/ListingTable/mappers/populate-rows.js +19 -16
- package/src/components/ListingTable/service/index.js +13 -2
- package/src/components/hooks/useCallbackDebounce.js +15 -0
- package/src/utils/build-listing-query.js +1 -0
- package/src/utils/get-default-query-params.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blaze-cms/plugin-data-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.141.0-alpha.1",
|
|
4
4
|
"description": "Blaze plugin data ui",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib-es/index.js",
|
|
@@ -27,18 +27,19 @@
|
|
|
27
27
|
},
|
|
28
28
|
"license": "GPL-3.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@blaze-cms/admin-ui-utils": "
|
|
30
|
+
"@blaze-cms/admin-ui-utils": "0.141.0-alpha.0",
|
|
31
31
|
"@blaze-cms/core-errors": "^0.140.3",
|
|
32
32
|
"@blaze-cms/plugin-render-hooks-ui": "^0.140.3",
|
|
33
|
-
"@blaze-cms/react-form-builder": "
|
|
34
|
-
"@blaze-cms/react-page-builder": "
|
|
33
|
+
"@blaze-cms/react-form-builder": "0.141.0-alpha.1",
|
|
34
|
+
"@blaze-cms/react-page-builder": "0.141.0-alpha.1",
|
|
35
35
|
"@blaze-cms/setup-ui": "^0.140.3",
|
|
36
36
|
"@blaze-cms/versioning-ui": "^0.140.3",
|
|
37
37
|
"@blaze-react/button": "0.5.19",
|
|
38
38
|
"@blaze-react/more": "0.5.19",
|
|
39
|
-
"@blaze-react/multiselect": "0.
|
|
39
|
+
"@blaze-react/multiselect": "0.8.0-alpha.78",
|
|
40
|
+
"@blaze-react/pagination": "0.8.0-alpha.76",
|
|
40
41
|
"@blaze-react/select": "0.8.0-alpha.64",
|
|
41
|
-
"@blaze-react/table": "0.
|
|
42
|
+
"@blaze-react/table": "0.8.0-alpha.74",
|
|
42
43
|
"@blaze-react/toaster": "0.5.17",
|
|
43
44
|
"@blaze-react/utils": "0.5.15",
|
|
44
45
|
"core-js": "^3.2.1",
|
|
@@ -66,5 +67,5 @@
|
|
|
66
67
|
"lib/*",
|
|
67
68
|
"lib-es/*"
|
|
68
69
|
],
|
|
69
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "511c3db4259e32fc0e45b4072254189b9d64764c"
|
|
70
71
|
}
|
|
@@ -14,6 +14,7 @@ import isFormEmpty from '../utils/is-form-empty';
|
|
|
14
14
|
import availableActions from './actions-handlers';
|
|
15
15
|
import SideBarRelations from './SideBarRelations';
|
|
16
16
|
import Tabs from '../../Tabs';
|
|
17
|
+
import useCallbackDebounce from '../../hooks/useCallbackDebounce';
|
|
17
18
|
|
|
18
19
|
import {
|
|
19
20
|
ENTITY_PUBLISHED,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
UNPUBLISHED_WARNING
|
|
28
29
|
} from '../../../constants';
|
|
29
30
|
import EntityHeader from './EntityHeader';
|
|
31
|
+
|
|
30
32
|
import {
|
|
31
33
|
validateSideBarRelations,
|
|
32
34
|
canViewPage,
|
|
@@ -84,6 +86,20 @@ const Entity = ({
|
|
|
84
86
|
|
|
85
87
|
// Here's how we'll keep track of our component's mounted state
|
|
86
88
|
const componentIsMounted = useRef(true);
|
|
89
|
+
|
|
90
|
+
const {
|
|
91
|
+
displayProperties: { saveOnChange = false }
|
|
92
|
+
} = schema;
|
|
93
|
+
|
|
94
|
+
useCallbackDebounce(
|
|
95
|
+
() => {
|
|
96
|
+
isSaveButtonAvailable && onSubmit();
|
|
97
|
+
},
|
|
98
|
+
500,
|
|
99
|
+
[isSaveButtonAvailable],
|
|
100
|
+
!saveOnChange
|
|
101
|
+
);
|
|
102
|
+
|
|
87
103
|
useEffect(
|
|
88
104
|
() => () => {
|
|
89
105
|
componentIsMounted.current = false;
|
|
@@ -424,6 +440,8 @@ const Entity = ({
|
|
|
424
440
|
formData={formData}
|
|
425
441
|
onViewUrl={onViewUrlHandler}
|
|
426
442
|
saveButtonText={saveButtonText}
|
|
443
|
+
saveOnChange={saveOnChange}
|
|
444
|
+
entitySchema={entitySchema}
|
|
427
445
|
/>
|
|
428
446
|
<div className="page-wrapper__content">
|
|
429
447
|
<div className="tabs-wrapper tabs-wrapper__tab">
|
|
@@ -9,6 +9,7 @@ import { SAVE_BUTTON_TEXTS } from '../../../../constants';
|
|
|
9
9
|
const EntityHeader = ({
|
|
10
10
|
saveButtonText,
|
|
11
11
|
entityData,
|
|
12
|
+
entitySchema,
|
|
12
13
|
entityIdentifier,
|
|
13
14
|
pageTitle,
|
|
14
15
|
onSubmit,
|
|
@@ -20,18 +21,29 @@ const EntityHeader = ({
|
|
|
20
21
|
toggleModal,
|
|
21
22
|
formData,
|
|
22
23
|
pageName,
|
|
23
|
-
onViewUrl
|
|
24
|
+
onViewUrl,
|
|
25
|
+
saveOnChange
|
|
24
26
|
}) => {
|
|
25
27
|
const SaveButtonModifiers = isSaveButtonAvailable ? ['small'] : ['small', 'disabled'];
|
|
26
28
|
const showPreviewButton = isEnablePreviewButton && entityIdentifier && entityData.id;
|
|
27
29
|
const shouldDisableMoreMenu = saveButtonText === SAVE_BUTTON_TEXTS.saving;
|
|
28
30
|
|
|
31
|
+
const {
|
|
32
|
+
displayProperties: { adminCrudActions: { delete: deleteAction = { active: true } } = {} } = {}
|
|
33
|
+
} =
|
|
34
|
+
entitySchema || {};
|
|
35
|
+
|
|
36
|
+
const showDeleteButton =
|
|
37
|
+
deleteAction.active && formData && Object.keys(formData.values).length !== 0;
|
|
38
|
+
|
|
29
39
|
return (
|
|
30
40
|
<PageHeader title={pageTitle} pageName={pageName} onViewUrl={onViewUrl}>
|
|
31
41
|
<PageHeader.Actions>
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
|
|
42
|
+
{!saveOnChange && (
|
|
43
|
+
<Button onClick={onSubmit} modifiers={SaveButtonModifiers} data-testid="button-save">
|
|
44
|
+
{saveButtonText}
|
|
45
|
+
</Button>
|
|
46
|
+
)}
|
|
35
47
|
<More disabled={shouldDisableMoreMenu}>
|
|
36
48
|
<More.Avatar data-testid={`entity-header-${pageName}`} isMoreMenu>
|
|
37
49
|
<span className="material-icons">more_vert</span>
|
|
@@ -58,12 +70,11 @@ const EntityHeader = ({
|
|
|
58
70
|
View
|
|
59
71
|
</Button>
|
|
60
72
|
)}
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
)}
|
|
73
|
+
{showDeleteButton && (
|
|
74
|
+
<Button className="more-menu__link" onClick={toggleModal}>
|
|
75
|
+
Delete
|
|
76
|
+
</Button>
|
|
77
|
+
)}
|
|
67
78
|
</More.Content>
|
|
68
79
|
</More>
|
|
69
80
|
</PageHeader.Actions>
|
|
@@ -74,6 +85,7 @@ const EntityHeader = ({
|
|
|
74
85
|
EntityHeader.propTypes = {
|
|
75
86
|
entityData: PropTypes.object,
|
|
76
87
|
entityIdentifier: PropTypes.string,
|
|
88
|
+
entitySchema: PropTypes.object.isRequired,
|
|
77
89
|
pageTitle: PropTypes.string.isRequired,
|
|
78
90
|
pageName: PropTypes.string,
|
|
79
91
|
onSubmit: PropTypes.func.isRequired,
|
|
@@ -85,7 +97,8 @@ EntityHeader.propTypes = {
|
|
|
85
97
|
toggleModal: PropTypes.func.isRequired,
|
|
86
98
|
formData: PropTypes.object,
|
|
87
99
|
onViewUrl: PropTypes.func.isRequired,
|
|
88
|
-
saveButtonText: PropTypes.string
|
|
100
|
+
saveButtonText: PropTypes.string,
|
|
101
|
+
saveOnChange: PropTypes.bool.isRequired
|
|
89
102
|
};
|
|
90
103
|
|
|
91
104
|
EntityHeader.defaultProps = {
|
|
@@ -8,10 +8,10 @@ const InfoBox = ({ items, infoBoxKey }) => {
|
|
|
8
8
|
Object.values(item)
|
|
9
9
|
.map(info => {
|
|
10
10
|
if (!info.label || !info.value) return null;
|
|
11
|
-
|
|
11
|
+
const label = info.showLabel === false ? '' : `${info.label}: `;
|
|
12
12
|
return (
|
|
13
13
|
<div className="info-box--item" key={`${infoBoxKey}-${info.label.toLowerCase()}`}>
|
|
14
|
-
<div className="info-box--label">{
|
|
14
|
+
<div className="info-box--label">{label}</div>
|
|
15
15
|
<div className="info-box--value">{info.value}</div>
|
|
16
16
|
</div>
|
|
17
17
|
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useApolloClient } from '@apollo/client';
|
|
2
1
|
import React, { useEffect, useState, Fragment } from 'react';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
|
-
import { withRouter, Link } from 'react-router-dom';
|
|
5
3
|
import More from '@blaze-react/more';
|
|
4
|
+
import { useApolloClient } from '@apollo/client';
|
|
5
|
+
import { withRouter, Link, useLocation } from 'react-router-dom';
|
|
6
6
|
import { PageHeader, DeleteAction, CardPrompt } from '@blaze-cms/admin';
|
|
7
7
|
import { useToasts } from '@blaze-react/toaster';
|
|
8
8
|
import { RenderHook } from '@blaze-cms/plugin-render-hooks-ui';
|
|
@@ -12,20 +12,20 @@ import { fetchData } from './service';
|
|
|
12
12
|
import { populateRows, formatRows, getParsedRowData } from './mappers/populate-rows';
|
|
13
13
|
import { getDefaultQueryParams } from '../../utils/get-default-query-params';
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const ListingTable = ({ match, entitySchema }) => {
|
|
15
|
+
const ListingTable = ({ match, entitySchema, history }) => {
|
|
18
16
|
const [tableData, setTableData] = useState({});
|
|
19
17
|
const [modalStatus, setModalStatus] = useState(false);
|
|
20
18
|
const [itemToDelete, setItemToDelete] = useState({});
|
|
21
19
|
const [previousSchema, setPreviousSchema] = useState({ id: null });
|
|
22
|
-
const [
|
|
23
|
-
const [verifiedRanges, setVerifiedRanges] = useState([]);
|
|
20
|
+
const [totalItems, setTotalItems] = useState(0);
|
|
24
21
|
const queryParamsDefault = getDefaultQueryParams(entitySchema);
|
|
25
22
|
const [queryParams, setQueryParams] = useState(queryParamsDefault);
|
|
26
23
|
const [listFilters, setListFilters] = useState([]);
|
|
27
24
|
const client = useApolloClient();
|
|
28
25
|
const { addToast } = useToasts();
|
|
26
|
+
const location = useLocation();
|
|
27
|
+
const searchParams = new URLSearchParams(location.search);
|
|
28
|
+
const currentPage = Number(searchParams.get('page')) || 1;
|
|
29
29
|
|
|
30
30
|
useEffect(
|
|
31
31
|
() => {
|
|
@@ -42,12 +42,12 @@ const ListingTable = ({ match, entitySchema }) => {
|
|
|
42
42
|
[client, entitySchema, match.url, previousSchema.id, queryParams] // eslint-disable-line react-hooks/exhaustive-deps
|
|
43
43
|
);
|
|
44
44
|
|
|
45
|
-
const doQuery = async (filters = listFilters) => {
|
|
46
|
-
const
|
|
45
|
+
const doQuery = async (filters = listFilters, params = queryParamsDefault) => {
|
|
46
|
+
const { listingData, totalRecords } = await fetchData({
|
|
47
47
|
client,
|
|
48
48
|
querySettings: {
|
|
49
49
|
entitySchema,
|
|
50
|
-
queryParams:
|
|
50
|
+
queryParams: params
|
|
51
51
|
},
|
|
52
52
|
listFilters: filters
|
|
53
53
|
});
|
|
@@ -56,10 +56,23 @@ const ListingTable = ({ match, entitySchema }) => {
|
|
|
56
56
|
toggleModal,
|
|
57
57
|
url: match.url,
|
|
58
58
|
entitySchema,
|
|
59
|
-
rows:
|
|
59
|
+
rows: listingData
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
setTableData(populatedTable);
|
|
63
|
+
setTotalItems(totalRecords);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const handleOnPageChange = async ({ pageNumber, offset: _offset }) => {
|
|
67
|
+
const updatedQueryParams = {
|
|
68
|
+
...queryParams,
|
|
69
|
+
offset: _offset
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
await doQuery(listFilters, updatedQueryParams);
|
|
73
|
+
|
|
74
|
+
history.push(`?page=${pageNumber}`);
|
|
75
|
+
document.getElementsByClassName('page')[0].scrollTo(0, 0);
|
|
63
76
|
};
|
|
64
77
|
|
|
65
78
|
const updateListingFilters = async filters => {
|
|
@@ -100,11 +113,9 @@ const ListingTable = ({ match, entitySchema }) => {
|
|
|
100
113
|
...queryParamsDefault,
|
|
101
114
|
sort: [{ property, direction }]
|
|
102
115
|
};
|
|
103
|
-
setScrollToIndex(0);
|
|
104
|
-
setVerifiedRanges([]);
|
|
105
116
|
setQueryParams(sortQueryParams);
|
|
106
117
|
|
|
107
|
-
const
|
|
118
|
+
const { listingData } = await fetchData({
|
|
108
119
|
client,
|
|
109
120
|
querySettings: {
|
|
110
121
|
entitySchema,
|
|
@@ -119,85 +130,62 @@ const ListingTable = ({ match, entitySchema }) => {
|
|
|
119
130
|
...tableData,
|
|
120
131
|
appliedSort: { [property]: direction },
|
|
121
132
|
rows: formatRows({
|
|
122
|
-
rows: getParsedRowData(
|
|
133
|
+
rows: getParsedRowData(listingData),
|
|
123
134
|
url: match.url,
|
|
124
135
|
toggleModal,
|
|
125
136
|
firstColumn,
|
|
126
137
|
isEnquiry
|
|
127
138
|
})
|
|
128
139
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const handleRenderedItems = async params => {
|
|
132
|
-
const { startIndex } = params;
|
|
133
|
-
const rowsLength = tableData.rows.length;
|
|
134
|
-
const loadIndex = Math.floor(rowsLength / 3) - OVER_SCAN_BUFFER;
|
|
135
|
-
if (loadIndex > 0 && loadIndex < startIndex && !verifiedRanges.includes(loadIndex)) {
|
|
136
|
-
const updatedQueryParams = {
|
|
137
|
-
...queryParams,
|
|
138
|
-
offset: rowsLength
|
|
139
|
-
};
|
|
140
|
-
const data = await fetchData({
|
|
141
|
-
client,
|
|
142
|
-
querySettings: {
|
|
143
|
-
entitySchema,
|
|
144
|
-
queryParams: updatedQueryParams
|
|
145
|
-
},
|
|
146
|
-
listFilters
|
|
147
|
-
});
|
|
148
|
-
const updatedRows = [
|
|
149
|
-
...tableData.rows,
|
|
150
|
-
...formatRows({
|
|
151
|
-
rows: getParsedRowData(data),
|
|
152
|
-
url: match.url,
|
|
153
|
-
toggleModal,
|
|
154
|
-
isEnquiry: tableData.isEnquiry
|
|
155
|
-
})
|
|
156
|
-
];
|
|
157
|
-
|
|
158
|
-
setVerifiedRanges([...verifiedRanges, loadIndex]);
|
|
159
|
-
setQueryParams(updatedQueryParams);
|
|
160
|
-
setTableData({
|
|
161
|
-
...tableData,
|
|
162
|
-
rows: updatedRows
|
|
163
|
-
});
|
|
164
|
-
setScrollToIndex(startIndex + OVER_SCAN_BUFFER);
|
|
165
|
-
}
|
|
140
|
+
history.push('?page=1');
|
|
166
141
|
};
|
|
167
142
|
|
|
168
143
|
if (!tableData || !tableData.rows) return 'loading';
|
|
169
|
-
|
|
144
|
+
|
|
145
|
+
const {
|
|
146
|
+
displayProperties: {
|
|
147
|
+
adminCrudActions: {
|
|
148
|
+
create: createAction = { active: true },
|
|
149
|
+
delete: _deleteAction = { active: true }
|
|
150
|
+
} = {}
|
|
151
|
+
} = {}
|
|
152
|
+
} = entitySchema;
|
|
153
|
+
|
|
154
|
+
const showAddButton = !tableData.rows.length && listFilters.length === 0;
|
|
170
155
|
|
|
171
156
|
return (
|
|
172
157
|
<div className="page">
|
|
173
|
-
{modalStatus &&
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
{showAddButton && (
|
|
182
|
-
<Fragment>
|
|
183
|
-
<Link
|
|
184
|
-
data-testid="addEntity"
|
|
185
|
-
className="button button--small"
|
|
186
|
-
to={`${match.url}/create`}>
|
|
187
|
-
Add
|
|
188
|
-
</Link>
|
|
189
|
-
<PageHeader.Actions>
|
|
190
|
-
<More>
|
|
191
|
-
<More.Avatar isMoreMenu>
|
|
192
|
-
<span className="material-icons">more_vert</span>
|
|
193
|
-
</More.Avatar>
|
|
194
|
-
<More.Content isMoreMenu />
|
|
195
|
-
</More>
|
|
196
|
-
</PageHeader.Actions>
|
|
197
|
-
</Fragment>
|
|
158
|
+
{modalStatus &&
|
|
159
|
+
_deleteAction.active && (
|
|
160
|
+
<DeleteAction
|
|
161
|
+
data-testid="deleteEntity"
|
|
162
|
+
onClose={toggleModal}
|
|
163
|
+
deleteAction={deleteAction}
|
|
164
|
+
itemName={itemToDelete.name}
|
|
165
|
+
/>
|
|
198
166
|
)}
|
|
167
|
+
<PageHeader title={entitySchema.displayName} subtitle="">
|
|
168
|
+
{createAction.active &&
|
|
169
|
+
!showAddButton && (
|
|
170
|
+
<Fragment>
|
|
171
|
+
<Link
|
|
172
|
+
data-testid="addEntity"
|
|
173
|
+
className="button button--small"
|
|
174
|
+
to={`${match.url}/create`}>
|
|
175
|
+
Add
|
|
176
|
+
</Link>
|
|
177
|
+
<PageHeader.Actions>
|
|
178
|
+
<More>
|
|
179
|
+
<More.Avatar isMoreMenu>
|
|
180
|
+
<span className="material-icons">more_vert</span>
|
|
181
|
+
</More.Avatar>
|
|
182
|
+
<More.Content isMoreMenu />
|
|
183
|
+
</More>
|
|
184
|
+
</PageHeader.Actions>
|
|
185
|
+
</Fragment>
|
|
186
|
+
)}
|
|
199
187
|
</PageHeader>
|
|
200
|
-
{
|
|
188
|
+
{showAddButton ? (
|
|
201
189
|
<CardPrompt>
|
|
202
190
|
<Link
|
|
203
191
|
className="button button--rounded button--cta"
|
|
@@ -206,26 +194,31 @@ const ListingTable = ({ match, entitySchema }) => {
|
|
|
206
194
|
Add
|
|
207
195
|
</Link>
|
|
208
196
|
</CardPrompt>
|
|
197
|
+
) : (
|
|
198
|
+
<>
|
|
199
|
+
<RenderHook
|
|
200
|
+
hookKey="entity:listing:main:top"
|
|
201
|
+
schema={entitySchema}
|
|
202
|
+
listFilters={listFilters}
|
|
203
|
+
setListFilters={updateListingFilters}
|
|
204
|
+
/>
|
|
205
|
+
<ListingTableContent
|
|
206
|
+
totalItems={totalItems}
|
|
207
|
+
currentPage={currentPage}
|
|
208
|
+
onSort={handleSort}
|
|
209
|
+
handleOnPageChange={handleOnPageChange}
|
|
210
|
+
tableData={tableData}
|
|
211
|
+
onCloseCardPrompt={onCloseCardPrompt}
|
|
212
|
+
/>
|
|
213
|
+
</>
|
|
209
214
|
)}
|
|
210
|
-
<RenderHook
|
|
211
|
-
hookKey="entity:listing:main:top"
|
|
212
|
-
schema={entitySchema}
|
|
213
|
-
setListFilters={updateListingFilters}
|
|
214
|
-
/>
|
|
215
|
-
<ListingTableContent
|
|
216
|
-
overScanBuffer={OVER_SCAN_BUFFER}
|
|
217
|
-
onSort={handleSort}
|
|
218
|
-
onRenderItems={handleRenderedItems}
|
|
219
|
-
tableData={tableData}
|
|
220
|
-
onCloseCardPrompt={onCloseCardPrompt}
|
|
221
|
-
scrollToIndex={scrollToIndex}
|
|
222
|
-
/>
|
|
223
215
|
</div>
|
|
224
216
|
);
|
|
225
217
|
};
|
|
226
218
|
ListingTable.propTypes = {
|
|
227
219
|
entitySchema: PropTypes.object.isRequired,
|
|
228
|
-
match: PropTypes.object.isRequired
|
|
220
|
+
match: PropTypes.object.isRequired,
|
|
221
|
+
history: PropTypes.object.isRequired
|
|
229
222
|
};
|
|
230
223
|
|
|
231
224
|
export default withRouter(ListingTable);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Table from '@blaze-react/table';
|
|
3
|
+
import Pagination from '@blaze-react/pagination';
|
|
4
|
+
|
|
3
5
|
import PropTypes from 'prop-types';
|
|
4
6
|
import { withRouter } from 'react-router-dom';
|
|
5
7
|
|
|
@@ -7,10 +9,9 @@ const ListingTableContent = ({
|
|
|
7
9
|
tableData,
|
|
8
10
|
handleSelect,
|
|
9
11
|
onSort,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
scrollToIndex
|
|
12
|
+
handleOnPageChange,
|
|
13
|
+
currentPage,
|
|
14
|
+
totalItems
|
|
14
15
|
}) => {
|
|
15
16
|
const displayTable = tableData && tableData.rows && !!tableData.rows.length;
|
|
16
17
|
const { isEnquiry } = tableData;
|
|
@@ -18,22 +19,28 @@ const ListingTableContent = ({
|
|
|
18
19
|
|
|
19
20
|
return (
|
|
20
21
|
<>
|
|
21
|
-
{displayTable
|
|
22
|
+
{displayTable ? (
|
|
22
23
|
<>
|
|
23
24
|
<div className={className}>
|
|
24
25
|
<Table
|
|
25
|
-
scrollToIndex={scrollToIndex}
|
|
26
26
|
onSort={onSort}
|
|
27
|
-
onClickRow={onClickRow}
|
|
28
|
-
overScanBuffer={overScanBuffer}
|
|
29
|
-
onRenderItems={onRenderItems}
|
|
30
27
|
data={tableData}
|
|
31
28
|
checkboxes={!isEnquiry}
|
|
32
29
|
onSelect={handleSelect}
|
|
33
30
|
data-testid="listing-table-content"
|
|
34
31
|
/>
|
|
32
|
+
<Pagination
|
|
33
|
+
visiblePages={10}
|
|
34
|
+
totalItems={totalItems}
|
|
35
|
+
currentPage={currentPage}
|
|
36
|
+
onPageChange={handleOnPageChange}
|
|
37
|
+
/>
|
|
35
38
|
</div>
|
|
36
39
|
</>
|
|
40
|
+
) : (
|
|
41
|
+
<span className="table-no-results" data-testid="no-results">
|
|
42
|
+
No results
|
|
43
|
+
</span>
|
|
37
44
|
)}
|
|
38
45
|
</>
|
|
39
46
|
);
|
|
@@ -46,20 +53,15 @@ ListingTableContent.propTypes = {
|
|
|
46
53
|
}).isRequired,
|
|
47
54
|
handleSelect: PropTypes.func,
|
|
48
55
|
onSort: PropTypes.func,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
onRenderItems: PropTypes.func
|
|
56
|
+
handleOnPageChange: PropTypes.func,
|
|
57
|
+
currentPage: PropTypes.number.isRequired,
|
|
58
|
+
totalItems: PropTypes.number.isRequired
|
|
53
59
|
};
|
|
54
60
|
|
|
55
61
|
ListingTableContent.defaultProps = {
|
|
56
62
|
handleSelect: () => {},
|
|
57
63
|
onSort: () => {},
|
|
58
|
-
|
|
59
|
-
overScanBuffer: 0,
|
|
60
|
-
scrollToIndex: 0,
|
|
61
|
-
onRenderItems: () => {},
|
|
62
|
-
selectedMenuItem: null
|
|
64
|
+
handleOnPageChange: () => {}
|
|
63
65
|
};
|
|
64
66
|
|
|
65
67
|
export default withRouter(ListingTableContent);
|
|
@@ -34,22 +34,25 @@ const getSanitizedColumnLabel = columnProp => {
|
|
|
34
34
|
|
|
35
35
|
const buildArrayRowContent = rowData => (
|
|
36
36
|
<div className="table-row-list">
|
|
37
|
-
{rowData.map(rowGroup =>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
{rowData.map(rowGroup => {
|
|
38
|
+
if (!rowGroup.length) return null;
|
|
39
|
+
return (
|
|
40
|
+
<div className="table-row-list__group">
|
|
41
|
+
{rowGroup.map(({ label, value, url }) => (
|
|
42
|
+
<div className="table-row-list__group__item">
|
|
43
|
+
<span className="table-row-list__group__item__label"> {label}:</span>
|
|
44
|
+
{url && value ? (
|
|
45
|
+
<Link to={url} role="button" className="table-row-list__group__item__value">
|
|
46
|
+
{value}
|
|
47
|
+
</Link>
|
|
48
|
+
) : (
|
|
49
|
+
value && <span className="table-row-list__group__item__value"> {value}</span>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
))}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
})}
|
|
53
56
|
</div>
|
|
54
57
|
);
|
|
55
58
|
|
|
@@ -41,9 +41,20 @@ const fetchData = async ({ client, querySettings: { entitySchema, queryParams },
|
|
|
41
41
|
const isSearchQuery = source === 'search';
|
|
42
42
|
const query = buildListingQuery(entitySchema, isSearchQuery);
|
|
43
43
|
const variables = buildVariables({ entitySchema, listFilters, queryParams, isSearchQuery });
|
|
44
|
-
const { data = {} } = await client.query({ query, variables, fetchPolicy: 'network-only' });
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
const { data = {} } = await client.query({
|
|
46
|
+
query,
|
|
47
|
+
variables,
|
|
48
|
+
fetchPolicy: 'network-only'
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (data.searchResults) {
|
|
52
|
+
return {
|
|
53
|
+
listingData: data.searchResults.results,
|
|
54
|
+
totalRecords: data.searchResults.total
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return data;
|
|
47
58
|
};
|
|
48
59
|
|
|
49
60
|
export { fetchData };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
function useCallbackDebounce(callback, delay, dependencies, skip) {
|
|
4
|
+
useEffect(
|
|
5
|
+
() => {
|
|
6
|
+
if (skip) return;
|
|
7
|
+
const timer = setTimeout(callback, delay);
|
|
8
|
+
return () => clearTimeout(timer);
|
|
9
|
+
},
|
|
10
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11
|
+
dependencies
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default useCallbackDebounce;
|