Skip to content

Commit

Permalink
Merge pull request #117 from Synicix/pageination
Browse files Browse the repository at this point in the history
Pageination rewrite
  • Loading branch information
guzman-raphael authored Mar 8, 2021
2 parents bbcd0a0 + 561d050 commit 5cc8803
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 222 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and

## [Unreleased]
### Added
- Added Case insensitive behavior to schema and table search box (#99) PR #102
- Added case insensitive behavior to schema and table search box (#99) PR #102
- CSS for making the primary keys look disabled/readonly for update mode PR #105
- Added number of tuples input box for fetch table viewing PR #117

### Fixed
- Fixed bug of delete with datetime in primarykey crashing PR #105
- Fixed issue where website crashes when opening a filter card for datetime. (#104) PR #106
- Fixed broken paging system for fetching records. Before it would fetched everything, now it only fetches only what is needed (#30) PR #117
- Fixed redundent data fetching when user switch between Table Content and Table Info PR #117
- Fixed redundent props to state copy in tableInfo component PR #117
- Fixed issue where website crashes when opening a filter card for datetime. (#104) PR #106

## [0.1.0-beta.1] - 2021-02-26
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,7 @@ class TableAttribute {
return(<option selected={currentValue === enumOptionString} key={enumOptionString} value={enumOptionString}>{enumOptionString}</option>);
})}
</select>
)
}
)}
}

// Handle number return types
Expand Down
4 changes: 2 additions & 2 deletions src/Components/MainTableView/Filter/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type FilterState = {
/**
* Filter component that is in charge of managing one to many FilterCards as well as the data store beind them
*/
class Filter extends React.Component<{tableAttributesInfo?: TableAttributesInfo, fetchTableContent: any}, FilterState> {
class Filter extends React.Component<{tableAttributesInfo?: TableAttributesInfo, setRestrictions: (restrictions: Array<Restriction>) => void}, FilterState> {
constructor(props: any) {
super(props);
this.state = {
Expand Down Expand Up @@ -114,7 +114,7 @@ class Filter extends React.Component<{tableAttributesInfo?: TableAttributesInfo,

// Call fetch content if there is at lesat one valid restriction
if (validRestrictions.length >= 0) {
this.props.fetchTableContent(validRestrictions);
this.props.setRestrictions(validRestrictions);
}
}, 1000);

Expand Down
10 changes: 10 additions & 0 deletions src/Components/MainTableView/TableContent.css
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,14 @@ input[type="checkbox"][disabled] {
.paginator .icon.disabled {
color: rgb(196, 196, 196);
cursor: not-allowed;
}

.number-of-rows-per-page-input {
display: flex;
flex-direction: row;
}

.number-of-rows-per-page-input input{
margin-left: 20px;
width: 40px;
}
186 changes: 70 additions & 116 deletions src/Components/MainTableView/TableContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import DeleteTuple from './DeleteTuple/DeleteTuple'
import TableAttributesInfo from './DataStorageClasses/TableAttributesInfo';
import TableAttribute from './DataStorageClasses/TableAttribute'
import TableAttributeType from './enums/TableAttributeType'
import Restriction from './DataStorageClasses/Restriction'

enum PaginationCommand {
FORWARD,
Expand All @@ -19,27 +20,23 @@ enum PaginationCommand {
}

enum TableActionType {
FILTER = 0,
INSERT = 1,
UPDATE = 2,
DELETE = 3
FILTER,
INSERT,
UPDATE,
DELETE
}

type TableContentStatus = {
currentSelectedTableActionMenu: TableActionType,
hideTableActionMenu: boolean,
pageIncrement: number,
paginatorState: Array<number>,
selectedTableIndex: number,
selectedTableEntry?: {}, // Has to be an object with each attribute name as key cause the way tuple_buffer is handle in the subcomponents
selectedTupleIndex: number,
selectedTuple?: {}, // Has to be an object with each attribute name as key cause the way tuple_buffer is handle in the subcomponents
showWarning: boolean, // text warning when duplicate selection is made for delete/update, most likely to be take out once disable checkbox feature is finished
isDisabledCheckbox: boolean, // tells the UI to disable any other checkboxes once there is already a selection in delete/update mode
headerWidth: number, // part of table column resizer feature
dragStart: number, // part of table column resizer feature
dragDistance: number, // part of table column resizer feature
resizeIndex: any, // part of table column resizer feature
atEndPage: boolean, // tells the UI to disable certain pagination icons if user is on the last page
atStartPage: boolean // tells the UI to disable certain pagination icons if user is on the first page
}

/**
Expand All @@ -59,38 +56,38 @@ class TableContent extends React.Component<{
selectedTableName: string,
selectedTableType: TableType,
contentData: Array<any>,
tableTotal: number,
tableAttributesInfo?: TableAttributesInfo,
fetchTableContent: any},
totalNumOfTuples: number,
currentPageNumber: number,
maxPageNumber: number,
tuplePerPage: number,
tableAttributesInfo?: TableAttributesInfo,
setPageNumber: any,
setNumberOfTuplesPerPage: any,
fetchTableContent: any,
setRestrictions: (restrictions: Array<Restriction>) => void},
TableContentStatus> {
constructor(props: any) {
super(props);
this.state = {
currentSelectedTableActionMenu: TableActionType.FILTER,
hideTableActionMenu: true,
pageIncrement: 25,
paginatorState: [0, 25],
selectedTableIndex: -1,
selectedTableEntry: undefined,
selectedTupleIndex: -1,
selectedTuple: undefined,
showWarning: false,
isDisabledCheckbox: false,
headerWidth: 0,
dragStart: 0,
dragDistance: 0,
resizeIndex: undefined,
atEndPage: false,
atStartPage: true
resizeIndex: undefined
}

this.getCurrentTableActionMenuComponent = this.getCurrentTableActionMenuComponent.bind(this);
this.getShowWarningComponent = this.getShowWarningComponent.bind(this);

// TODO: use effect to add reference for table column styling
// cellRef: React.RefObject<HTMLTableDataCellElement>;
// this.cellRef = createRef<HTMLTableDataCellElement>()
// const [colRefs, setColRefs] = React.useState([]);
// React.useEffect(() => {
// })
this.goToFirstPage = this.goToFirstPage.bind(this);
this.goToLastPage = this.goToLastPage.bind(this);
this.goForwardAPage = this.goForwardAPage.bind(this);
this.goBackwardAPage = this.goBackwardAPage.bind(this);
this.handleNumberOfTuplesPerPageChange = this.handleNumberOfTuplesPerPageChange.bind(this);
}

/**
Expand All @@ -99,31 +96,13 @@ class TableContent extends React.Component<{
* @param prevState
*/
componentDidUpdate(prevProps: any, prevState: any) {
// check to see if contentData updated, if so, check length to update page info
if (this.props.contentData !== prevProps.contentData) {
// Update paginator state if contentData is less than 25
if (this.props.contentData.length < 25 ) {
this.setState({paginatorState: [0, this.props.contentData.length]})
} else {
this.setState({paginatorState: [0, this.state.pageIncrement]}) // set to default increment of 25
}
}

// Break if the the selectedTable did not change
if (prevProps.selectedTableName === this.props.selectedTableName) {
return;
}

// Reset TableActionview
this.setState({currentSelectedTableActionMenu: TableActionType.FILTER, hideTableActionMenu: true, selectedTableEntry: undefined});

// TODO: part of reference for table column width update
// console.log('cellRef: ', this.cellRef)
// let cellStyle
// if (this.cellRef.current) {
// cellStyle = getComputedStyle(this.cellRef.current)
// console.log('width: ', cellStyle.width)
// }
this.setState({currentSelectedTableActionMenu: TableActionType.FILTER, hideTableActionMenu: true, selectedTuple: undefined});
}

/**
Expand All @@ -141,59 +120,25 @@ class TableContent extends React.Component<{
}
}

/**
* Function for paginating between data entries. Takes in forward/backward/start/end commands to set
* the page view state by increments (currently hardcoded on pageIncrement state) of 25 entries.
* @param cmd
*/
handlePagination(cmd: PaginationCommand) {
// check to see if paginator needs to even run for pages with small entries, if not, break
if (this.state.paginatorState[1] < this.state.pageIncrement) {
this.setState({atStartPage: true, atEndPage: true})
return;
goToFirstPage() {
this.props.setPageNumber(1);
}

goToLastPage() {
this.props.setPageNumber(this.props.maxPageNumber);
}

goForwardAPage() {
if (this.props.currentPageNumber != this.props.maxPageNumber) {
this.props.setPageNumber(this.props.currentPageNumber + 1);
}

// jump to beginning/end/next/previous page and update the page position and style status accordingly
if (cmd === PaginationCommand.START) {
this.setState({paginatorState: [0, this.state.pageIncrement], atStartPage: true, atEndPage: false})
}
else if (cmd === PaginationCommand.END) {
if (this.props.contentData.length % this.state.pageIncrement > 0) {
this.setState({paginatorState: [this.props.contentData.length - this.props.contentData.length % this.state.pageIncrement, this.props.contentData.length]})
}
else {
this.setState({paginatorState: [this.props.contentData.length - this.state.pageIncrement, this.props.contentData.length]})
}
this.setState({atStartPage: false, atEndPage: true})
}
else if (cmd === PaginationCommand.FORWARD) {
if (this.state.paginatorState[1] + this.state.pageIncrement < this.props.contentData.length) {
this.setState({paginatorState: [this.state.paginatorState[0] + this.state.pageIncrement, this.state.paginatorState[1] + this.state.pageIncrement],
atStartPage: false})
}
else if (this.props.contentData.length % this.state.pageIncrement > 0) {
this.setState({paginatorState: [this.props.contentData.length - this.props.contentData.length % this.state.pageIncrement, this.props.contentData.length],
atStartPage: false, atEndPage: true})
}
else {
this.setState({paginatorState: [this.props.contentData.length - this.state.pageIncrement, this.props.contentData.length],
atStartPage: false, atEndPage: true})
}
}

goBackwardAPage() {
if (this.props.currentPageNumber != 1) {
this.props.setPageNumber(this.props.currentPageNumber - 1);
}
else if (cmd === PaginationCommand.BACKWARD) {
if (this.state.paginatorState[0] - this.state.pageIncrement > 0) {
this.setState({paginatorState: [this.state.paginatorState[0] - this.state.pageIncrement, this.state.paginatorState[0]],
atEndPage: false})
}
else if (this.state.paginatorState[0] - this.state.pageIncrement === 0) {
this.setState({paginatorState: [this.state.paginatorState[0] - this.state.pageIncrement, this.state.paginatorState[0]],
atStartPage: true, atEndPage: false})
}
else {
this.setState({paginatorState: [0, this.state.pageIncrement],
atStartPage: true, atEndPage: false})
}
}
}

/**
Expand All @@ -204,7 +149,7 @@ class TableContent extends React.Component<{
return (<div className="actionMenuContainer">
<Filter
tableAttributesInfo={this.props.tableAttributesInfo}
fetchTableContent={this.props.fetchTableContent}
setRestrictions={this.props.setRestrictions}
/>
</div>)
}
Expand All @@ -217,7 +162,7 @@ class TableContent extends React.Component<{
tableAttributesInfo={this.props.tableAttributesInfo}
fetchTableContent={this.props.fetchTableContent}
clearEntrySelection={() => this.handleSelectionClearRequest()}
selectedTableEntry={this.state.selectedTableEntry}
selectedTableEntry={this.state.selectedTuple}
/>
</div>)
}
Expand All @@ -231,7 +176,7 @@ class TableContent extends React.Component<{
tableAttributesInfo={this.props.tableAttributesInfo}
fetchTableContent={this.props.fetchTableContent}
clearEntrySelection={() => this.handleSelectionClearRequest()}
selectedTableEntry={this.state.selectedTableEntry}
selectedTableEntry={this.state.selectedTuple}
/>
</div>)
}
Expand All @@ -246,7 +191,7 @@ class TableContent extends React.Component<{
tableAttributesInfo={this.props.tableAttributesInfo}
fetchTableContent={this.props.fetchTableContent}
clearEntrySelection={() => this.handleSelectionClearRequest()}
selectedTableEntry={this.state.selectedTableEntry}
selectedTableEntry={this.state.selectedTuple}
/>
</div>)
}
Expand All @@ -270,8 +215,8 @@ class TableContent extends React.Component<{
}

// If the tupleIndex is already selected, deselect it
if (tupleIndex === this.state.selectedTableIndex) {
this.setState({selectedTableIndex: -1, selectedTableEntry: undefined});
if (tupleIndex === this.state.selectedTupleIndex) {
this.setState({selectedTupleIndex: -1, selectedTuple: undefined});
return;
}

Expand Down Expand Up @@ -303,7 +248,11 @@ class TableContent extends React.Component<{

// Covert array into object

this.setState({selectedTableIndex: tupleIndex, selectedTableEntry: tupleBuffer});
this.setState({selectedTupleIndex: tupleIndex, selectedTuple: tupleBuffer});
}

handleNumberOfTuplesPerPageChange(event: any) {
this.props.setNumberOfTuplesPerPage(event.target.value)
}

/**
Expand All @@ -320,7 +269,7 @@ class TableContent extends React.Component<{
* Clears the staging once delete/update is successful and table content has been modified
*/
handleSelectionClearRequest() {
this.setState({selectedTableIndex: -1, selectedTableEntry: undefined});
this.setState({selectedTupleIndex: -1, selectedTuple: undefined});
}

/**
Expand Down Expand Up @@ -499,14 +448,14 @@ class TableContent extends React.Component<{
</tr>
</thead>
<tbody>
{this.props.contentData.slice(this.state.paginatorState[0], this.state.paginatorState[1]).map((entry: any, tupleIndex: number) => {
{this.props.contentData.map((entry: any, tupleIndex: number) => {
return (<tr key={entry} className="tableRow" onMouseMove={(event) => {this.cellResizeMouseMove(event)}} onMouseUp={(event) => {this.cellResizeMouseUp(event)}}>
<td colSpan={1}>
<input type="checkbox"
// disable multiple check for insert mode as well until multiple insert is supported.
disabled={this.state.selectedTableIndex > -1 && this.state.selectedTableIndex !== tupleIndex}
disabled={this.state.selectedTupleIndex > -1 && this.state.selectedTupleIndex !== tupleIndex}
onChange={(event) => this.handleCheckedEntry(event, tupleIndex)}
checked={this.state.selectedTableIndex === tupleIndex}/>
checked={this.state.selectedTupleIndex === tupleIndex}/>
</td>
{entry.map((column: any, index: number) => {
return (
Expand All @@ -520,16 +469,21 @@ class TableContent extends React.Component<{
</table>
</div>
<div className="paginator">
<p>Total Table Entries: {this.props.tableTotal}</p>
{ Object.entries(this.props.contentData).length ?
<div className="controls">
<FontAwesomeIcon className={!this.state.atStartPage ? "backAll icon" : "backAll icon disabled"} icon={faStepBackward} onClick={() => this.handlePagination(PaginationCommand.START)} />
<FontAwesomeIcon className={!this.state.atStartPage ? "backOne icon" : "backOne icon disabled"} icon={faChevronLeft} onClick={() => this.handlePagination(PaginationCommand.BACKWARD)} />
Currently viewing: {this.state.paginatorState[0] + 1} - {this.state.paginatorState[1]}
<FontAwesomeIcon className={!this.state.atEndPage ? "forwardOne icon" : "forwardOne icon disabled"} icon={faChevronRight} onClick={() => this.handlePagination(PaginationCommand.FORWARD)} />
<FontAwesomeIcon className={!this.state.atEndPage ? "forwardAll icon" : "forwardAll icon disabled"} icon={faStepForward} onClick={() => this.handlePagination(PaginationCommand.END)} />
<p>Total Table Entries: {this.props.totalNumOfTuples}</p>
<div className="number-of-rows-per-page-input">
<p>Number of row per page</p>
<input type='number' value={this.props.tuplePerPage} onChange={this.handleNumberOfTuplesPerPageChange}></input>
</div>
: '' }
{Object.entries(this.props.contentData).length ?
<div className="controls">
<FontAwesomeIcon className={true ? "backAll icon" : "backAll icon disabled"} icon={faStepBackward} onClick={() => this.goToFirstPage()} />
<FontAwesomeIcon className={true ? "backOne icon" : "backOne icon disabled"} icon={faChevronLeft} onClick={() => this.goBackwardAPage()} />
Page: ({this.props.currentPageNumber + ' / ' + this.props.maxPageNumber})
<FontAwesomeIcon className={true ? "forwardOne icon" : "forwardOne icon disabled"} icon={faChevronRight} onClick={() => this.goForwardAPage()} />
<FontAwesomeIcon className={true ? "forwardAll icon" : "forwardAll icon disabled"} icon={faStepForward} onClick={() => this.goToLastPage()} />
</div>
: ''
}
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 5cc8803

Please sign in to comment.