Skip to content

Commit c76f516

Browse files
committed
(CISC-1585) Select all with pagination, new icons, check all empty state bug fix, table actions
1 parent 3a731b8 commit c76f516

File tree

7 files changed

+416
-25
lines changed

7 files changed

+416
-25
lines changed

packages/data-grid/src/__test__/__snapshots__/Table.test.jsx.snap

+4-4
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ exports[`Snapshot test Check component matches previous HTML snapshot 1`] = `
7878
fixed={false}
7979
fixedColumn={false}
8080
headerCheckState={false}
81-
headerIndeterminateState={true}
81+
headerIndeterminateState={false}
8282
horizontalScroll={false}
8383
loading={false}
8484
loadingMessage="Loading"
@@ -126,7 +126,7 @@ exports[`Snapshot test Check component matches previous HTML snapshot 1`] = `
126126
},
127127
]
128128
}
129-
headerIndeterminateState={true}
129+
headerIndeterminateState={false}
130130
loading={false}
131131
loadingMessage="Loading"
132132
onSelectAll={[Function]}
@@ -443,7 +443,7 @@ exports[`Snapshot test Check component matches previous HTML snapshot 2`] = `
443443
fixed={false}
444444
fixedColumn={false}
445445
headerCheckState={false}
446-
headerIndeterminateState={true}
446+
headerIndeterminateState={false}
447447
horizontalScroll={false}
448448
loading={false}
449449
loadingMessage="Loading"
@@ -491,7 +491,7 @@ exports[`Snapshot test Check component matches previous HTML snapshot 2`] = `
491491
},
492492
]
493493
}
494-
headerIndeterminateState={true}
494+
headerIndeterminateState={false}
495495
loading={false}
496496
loadingMessage="Loading"
497497
onSelectAll={[Function]}

packages/data-grid/src/table/README.md

+247-4
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ The Data Grid package was developed to aid in the structuring of data. By using
44

55
To add the Data Grid package to your library run
66

7-
```sh
7+
```markdown
88
npm install @puppet/data-grid
99
```
1010

1111
In your .js file which will be rendering the Data Grid Table component you can reference your node modules instance with the following command:
1212

13-
```jsx
13+
```markdown
1414
import { Table } from '@puppet/data-grid';
1515
```
1616

1717
In your app level index.scss add the command below to import the Data Grids styles
1818

19-
```jsx
20-
@import '~@puppet/data-grid/dist/index';
19+
```markdown
20+
import '~@puppet/data-grid/dist/index';
2121
```
2222

2323
### Basic use
@@ -984,3 +984,246 @@ const columns = [
984984

985985
<Table data={data} columns={columns} />;
986986
```
987+
988+
### Selection and Pagination
989+
990+
Once we start adding multiple patterns together it is very easy to start confusing the end user. Thats why in the data grid when selecting and paginating together we treat each page header click as page specific and use additional badges in the header for cross pagination selecting and clearing. It's important to remember that a column header checkbox is used to show the state of the page visible. Intermediate and check all states on one page should not be shown on the next.
991+
992+
```jsx
993+
import { Link, Heading } from '@puppet/react-components';
994+
import { TablePageSelector, TableFooter } from '../index';
995+
996+
const data = [
997+
{
998+
eventType: 'Application Control',
999+
affectedDevices: 0,
1000+
detections: 1000,
1001+
sorted: 'asc',
1002+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1003+
unique: 6,
1004+
},
1005+
{
1006+
eventType: 'Virus/Malware',
1007+
affectedDevices: 20,
1008+
detections: 634,
1009+
unique: 1,
1010+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1011+
},
1012+
{
1013+
eventType: 'Spyware/Grayware',
1014+
affectedDevices: 20,
1015+
detections: 634,
1016+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1017+
unique: 2,
1018+
},
1019+
{
1020+
eventType: 'URL Filtering',
1021+
affectedDevices: 16,
1022+
detections: 599,
1023+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1024+
unique: 3,
1025+
},
1026+
{
1027+
eventType: 'Web Reputation',
1028+
affectedDevices: 15,
1029+
detections: 598,
1030+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1031+
unique: 4,
1032+
},
1033+
{
1034+
eventType: 'Network Virus',
1035+
affectedDevices: 15,
1036+
detections: 497,
1037+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1038+
unique: 5,
1039+
},
1040+
1041+
{
1042+
eventType: 'Application Controls',
1043+
affectedDevices: 0,
1044+
detections: 0,
1045+
Link: <Link href="https://puppet.com/">Help to fix</Link>,
1046+
unique: 7,
1047+
},
1048+
];
1049+
1050+
const columns = [
1051+
{
1052+
label: 'Event Type1',
1053+
dataKey: 'eventType',
1054+
},
1055+
{ label: 'Affected Devices', dataKey: 'affectedDevices' },
1056+
1057+
{ label: 'Detections', dataKey: 'detections' },
1058+
{ label: 'Linked field', dataKey: 'Link' },
1059+
];
1060+
1061+
class StatefulParent extends React.Component {
1062+
constructor() {
1063+
super();
1064+
this.state = { CurrentPage: 1, checkAll: false, data, indeterminateState: false, showSelectAllBadge: false, Pages: {arrayOfArrays: []}, nodesPerPage: 5 };
1065+
this.pageSelectFunc = this.pageSelectFunc.bind(this);
1066+
this.breakIntoMultiplePages = this.breakIntoMultiplePages.bind(this);
1067+
this.onRowSelected = this.onRowSelected.bind(this);
1068+
this.onHeaderSelected = this.onHeaderSelected.bind(this);
1069+
this.onSelectAllBadgeClick = this.onSelectAllBadgeClick.bind(this);
1070+
this.onClearAllBadgeClick = this.onClearAllBadgeClick.bind(this);
1071+
}
1072+
1073+
componentWillMount() {
1074+
const dataToPages = this.breakIntoMultiplePages(data, 5)
1075+
this.setState({Pages: dataToPages})
1076+
}
1077+
1078+
pageSelectFunc(newPage) {
1079+
const { CurrentPage, Pages } = this.state;
1080+
this.checkIfIndeterminateState(Pages)
1081+
this.setState({ CurrentPage: newPage });
1082+
}
1083+
1084+
breakIntoMultiplePages(originalArray, pageSize) {
1085+
const arrayOfArrays = [];
1086+
for (let i = 0; i < originalArray.length; i += pageSize) {
1087+
arrayOfArrays.push(originalArray.slice(i, i + pageSize));
1088+
}
1089+
return { arrayOfArrays };
1090+
}
1091+
1092+
checkIfIndeterminateState(Pages) {
1093+
const { data, indeterminateState, checkAll, CurrentPage } = this.state;
1094+
1095+
let selectedOnCurrentPage = Pages.arrayOfArrays[CurrentPage -1].filter(e => e.selected === true);
1096+
let currentPageLength = Pages.arrayOfArrays[CurrentPage -1].length
1097+
1098+
if (selectedOnCurrentPage.length > 0 && indeterminateState === false && checkAll === false) {
1099+
this.setState({ indeterminateState: true });
1100+
} else if (
1101+
(selectedOnCurrentPage.length === 0 && indeterminateState === true) ||
1102+
(selectedOnCurrentPage.length === 0 && checkAll === true)
1103+
) {
1104+
this.setState({ indeterminateState: false, checkAll: false });
1105+
}
1106+
if (selectedOnCurrentPage.length === currentPageLength && checkAll === false) {
1107+
this.setState({ indeterminateState: false, checkAll: true });
1108+
}
1109+
}
1110+
1111+
onHeaderSelected(checked) {
1112+
const { data: stateData, indeterminateState, show, showSelectAllBadge, CurrentPage, Pages } = this.state;
1113+
1114+
this.setState({ indeterminateState: false, checkAll: checked });
1115+
1116+
const x = Pages.arrayOfArrays[CurrentPage - 1]
1117+
let newObj = stateData;
1118+
1119+
x.forEach((row) => {
1120+
const y = stateData.findIndex((stateRow) => stateRow.unique === row.unique )
1121+
const updatedObj = { ...stateData[y], selected: checked };
1122+
newObj.splice(y,1, updatedObj);
1123+
})
1124+
1125+
this.setState({data: newObj})
1126+
1127+
}
1128+
1129+
1130+
onRowSelected(checked, row) {
1131+
const { data: stateData, checkAll, Pages } = this.state;
1132+
1133+
if (checkAll) {
1134+
this.setState({ checkAll: false });
1135+
}
1136+
// find the index of object from array that you want to update
1137+
const objIndex = stateData.findIndex(obj => obj.unique === row.unique);
1138+
// make new object of updated object.
1139+
const updatedObj = { ...stateData[objIndex], selected: checked };
1140+
// make final new array of objects by combining updated object.
1141+
const updatedData = [
1142+
...stateData.slice(0, objIndex),
1143+
updatedObj,
1144+
...stateData.slice(objIndex + 1),
1145+
];
1146+
1147+
this.checkIfIndeterminateState(Pages)
1148+
1149+
this.setState({ data: updatedData });
1150+
}
1151+
1152+
onSelectAllBadgeClick(){
1153+
const { data } = this.state;
1154+
const x = data
1155+
for (let i = 0; i < x.length; i += 1) {
1156+
x[i].selected = true;
1157+
}
1158+
this.setState({data: x})
1159+
}
1160+
1161+
onClearAllBadgeClick(){
1162+
const { data } = this.state;
1163+
const x = data
1164+
for (let i = 0; i < x.length; i += 1) {
1165+
x[i].selected = false;
1166+
}
1167+
this.setState({data: x})
1168+
}
1169+
1170+
render() {
1171+
const {
1172+
CurrentPage,
1173+
data:stateData,
1174+
indeterminateState,
1175+
checkAll: headerCheckboxState,
1176+
nodesPerPage
1177+
} = this.state;
1178+
1179+
const Pages = this.breakIntoMultiplePages(stateData, 5)
1180+
const PageLength = Pages.arrayOfArrays[CurrentPage -1].length
1181+
const PageCount = Pages.arrayOfArrays.length;
1182+
const renderPages = CurrentPage - 1;
1183+
const currentNode = `${nodesPerPage * CurrentPage}`;
1184+
const tableFooterText = `${currentNode -
1185+
PageLength +
1186+
1} - ${currentNode} of ${stateData.length} nodes`;
1187+
const selectAllBadgeText = `Select all ${stateData.length} nodes`
1188+
1189+
this.checkIfIndeterminateState(Pages);
1190+
const selectedCount = stateData.filter(obj => obj.selected === true).length
1191+
1192+
let rowCountText = `${stateData.length} nodes`
1193+
if( selectedCount > 0 ){
1194+
rowCountText = `${selectedCount} of ${stateData.length} nodes selected`
1195+
}
1196+
1197+
return (
1198+
<div>
1199+
<Table.TableHeader
1200+
showSelectAllBadge={selectedCount > 0 && selectedCount !== stateData.length }
1201+
rowCountText={rowCountText}
1202+
onSelectAllBadgeClick={this.onSelectAllBadgeClick}
1203+
showClearAllBadge={selectedCount === stateData.length}
1204+
onClearAllBadgeClick={this.onClearAllBadgeClick}
1205+
selectAllBadgeText={selectAllBadgeText}/>
1206+
<Table
1207+
data={Pages.arrayOfArrays[renderPages]}
1208+
columns={columns}
1209+
selectable
1210+
onRowChecked={this.onRowSelected}
1211+
headerIndeterminateState={indeterminateState}
1212+
checkIfIndeterminateState={this.checkIfIndeterminateState}
1213+
headerCheckState={headerCheckboxState}
1214+
onHeaderChecked={this.onHeaderSelected}
1215+
/>
1216+
<TableFooter>
1217+
<TablePageSelector
1218+
paginationCountText={tableFooterText}
1219+
currentPage={CurrentPage}
1220+
pageCount={PageCount}
1221+
updatePage={ this.pageSelectFunc}
1222+
/>
1223+
</TableFooter>
1224+
</div>
1225+
);
1226+
}
1227+
}
1228+
<StatefulParent/>;
1229+
```

packages/data-grid/src/table/Table.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ const defaultProps = {
106106
onHeaderChecked: () => {},
107107
onRowClick: () => {},
108108
headerCheckState: false,
109-
headerIndeterminateState: true,
109+
headerIndeterminateState: false,
110110
};
111111

112112
const defaultColumnDefs = {

0 commit comments

Comments
 (0)