Implemented pagination

This commit is contained in:
vaidankarswapnil 2021-08-11 12:48:54 +05:30
commit d7963b3ef4
5 changed files with 230 additions and 81 deletions

View File

@ -99,7 +99,7 @@
.tablesQueryTab { .tablesQueryTab {
padding-left: @MediumSpace; padding-left: @MediumSpace;
width: 100%; width: 100%;
margin-bottom: @LargeSpace; margin-bottom: 100px;
position: relative; position: relative;
height: 100%; height: 100%;
} }
@ -534,6 +534,44 @@ input::-webkit-inner-spin-button {
margin-bottom: 5px; margin-bottom: 5px;
} }
.query-document-detail-list {
overflow-x: hidden;
height: 100%;
}
.query-table-clause-container {
max-height: 80px;
overflow: scroll;
overflow-x: hidden;
}
.query-tab-document-pagination {
display: flex;
flex-direction: column;
position: absolute;
bottom: 0;
padding-left: @MediumSpace;
padding-bottom: 45px;
}
.pagination {
margin: 15px 0 !important;
li > .item-link {
position: relative;
float: left;
padding: 6px 12px;
margin-left: -1px;
line-height: 1.42857143;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd;
cursor: pointer;
&:hover {
font-weight: bold;
background: #eef7ff;
}
}
}
// .pagination > li > div {
// }
/* /*
@media only screen and (max-width: 1200px) { @media only screen and (max-width: 1200px) {
.clause-table { .clause-table {

View File

@ -107,7 +107,7 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
event.preventDefault(); event.preventDefault();
const entity: Entities.ITableEntity = entityFromAttributes(entities); const entity: Entities.ITableEntity = entityFromAttributes(entities);
const newEntity: Entities.ITableEntity = await tableDataClient.createDocument(queryTablesTab.collection, entity); await tableDataClient.createDocument(queryTablesTab.collection, entity);
// await tableEntityListViewModel.addEntityToCache(newEntity); // await tableEntityListViewModel.addEntityToCache(newEntity);
reloadEntities(); reloadEntities();
closeSidePanel(); closeSidePanel();

View File

@ -8,7 +8,7 @@ import { TableEntity } from "../../../Common/TableEntity";
import { useSidePanel } from "../../../hooks/useSidePanel"; import { useSidePanel } from "../../../hooks/useSidePanel";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
import * as TableConstants from "../../Tables/Constants"; import * as TableConstants from "../../Tables/Constants";
import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities"; // import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities";
import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel"; import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel";
import * as Entities from "../../Tables/Entities"; import * as Entities from "../../Tables/Entities";
import { CassandraAPIDataClient, TableDataClient } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient, TableDataClient } from "../../Tables/TableDataClient";
@ -204,48 +204,44 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
const entity: Entities.ITableEntity = entityFromAttributes(entities); const entity: Entities.ITableEntity = entityFromAttributes(entities);
const newTableDataClient = userContext.apiType === "Cassandra" ? cassandraApiClient : tableDataClient; const newTableDataClient = userContext.apiType === "Cassandra" ? cassandraApiClient : tableDataClient;
const originalDocumentData = userContext.apiType === "Cassandra" ? originalDocument[0] : originalDocument; const originalDocumentData = userContext.apiType === "Cassandra" ? originalDocument[0] : originalDocument;
const newEntity: Entities.ITableEntity = await newTableDataClient.updateDocument( await newTableDataClient.updateDocument(queryTablesTab.collection, originalDocumentData, entity);
queryTablesTab.collection, // await tableEntityListViewModel.updateCachedEntity(newEntity);
originalDocumentData, // if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
entity // tableEntityListViewModel.redrawTableThrottled();
); reloadEntities();
await tableEntityListViewModel.updateCachedEntity(newEntity); // }
if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) { // tableEntityListViewModel.selected.removeAll();
// tableEntityListViewModel.redrawTableThrottled(); // tableEntityListViewModel.selected.push(newEntity);
reloadEntities();
}
tableEntityListViewModel.selected.removeAll();
tableEntityListViewModel.selected.push(newEntity);
closeSidePanel(); closeSidePanel();
}; };
const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => { // const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => {
let newHeaders: string[] = []; // let newHeaders: string[] = [];
const keys = Object.keys(newEntity); // const keys = Object.keys(newEntity);
keys && // keys &&
keys.forEach((key: string) => { // keys.forEach((key: string) => {
if ( // if (
!_.contains(viewModel.headers, key) && // !_.contains(viewModel.headers, key) &&
key !== TableEntityProcessor.keyProperties.attachments && // key !== TableEntityProcessor.keyProperties.attachments &&
key !== TableEntityProcessor.keyProperties.etag && // key !== TableEntityProcessor.keyProperties.etag &&
key !== TableEntityProcessor.keyProperties.resourceId && // key !== TableEntityProcessor.keyProperties.resourceId &&
key !== TableEntityProcessor.keyProperties.self && // key !== TableEntityProcessor.keyProperties.self &&
(!(userContext.apiType === "Cassandra") || key !== TableConstants.EntityKeyNames.RowKey) // (!(userContext.apiType === "Cassandra") || key !== TableConstants.EntityKeyNames.RowKey)
) { // ) {
newHeaders.push(key); // newHeaders.push(key);
} // }
}); // });
let newHeadersInserted = false; // let newHeadersInserted = false;
if (newHeaders.length) { // if (newHeaders.length) {
if (!DataTableUtilities.checkForDefaultHeader(viewModel.headers)) { // if (!DataTableUtilities.checkForDefaultHeader(viewModel.headers)) {
newHeaders = viewModel.headers.concat(newHeaders); // newHeaders = viewModel.headers.concat(newHeaders);
} // }
viewModel.updateHeaders(newHeaders, /* notifyColumnChanges */ true, /* enablePrompt */ false); // viewModel.updateHeaders(newHeaders, /* notifyColumnChanges */ true, /* enablePrompt */ false);
newHeadersInserted = true; // newHeadersInserted = true;
} // }
return newHeadersInserted; // return newHeadersInserted;
}; // };
// Add new entity row // Add new entity row
const addNewEntity = (): void => { const addNewEntity = (): void => {

View File

@ -66,6 +66,10 @@ export interface IQueryTablesTabComponentStates {
isLoading: boolean; isLoading: boolean;
queryErrorMessage: string; queryErrorMessage: string;
hasQueryError: boolean; hasQueryError: boolean;
currentPage: number;
currentStartIndex: number;
fromDocument: number;
toDocument: number;
} }
export interface IQueryTableRowsType { export interface IQueryTableRowsType {

View File

@ -63,6 +63,8 @@ export interface Button {
isSelected?: boolean; isSelected?: boolean;
} }
const PAGESIZE = 10;
class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, IQueryTablesTabComponentStates> { class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, IQueryTablesTabComponentStates> {
public collection: ViewModels.Collection; public collection: ViewModels.Collection;
public _queryViewModel: QueryViewModel; public _queryViewModel: QueryViewModel;
@ -163,34 +165,13 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
entities: [], entities: [],
headers: [], headers: [],
queryTableRows: [], queryTableRows: [],
// queryTableRows: [
// {
// isQueryTableEntityChecked: false,
// selectedOperator: "=",
// id: "1",
// selectedField: userContext.apiType === "Cassandra" ? "email" : "PartitionKey",
// selectedOperation: "",
// entityValue: "",
// selectedEntityType: "String",
// isTimeStampSelected: false,
// selectedTimestamp: "Last hour",
// operatorOptions: getformattedOptions(operatorsOptions),
// fieldOptions: getformattedOptions(tableEntityListViewModel.headers),
// entityTypeOptions: getformattedOptions(entityTypeOptions),
// operationOptions: getformattedOptions(operationOptions),
// timestampOptions: getformattedOptions(timestampOptions),
// clauseGroup: queryBuilderViewModel.queryClauses,
// isValue: true,
// isLocal: false,
// isTimestamp: false,
// isCustomRangeTimestamp: false,
// customTimeValue: "",
// timeValue: "",
// },
// ],
isLoading: true, isLoading: true,
queryErrorMessage: "", queryErrorMessage: "",
hasQueryError: false, hasQueryError: false,
currentPage: 0,
currentStartIndex: PAGESIZE,
fromDocument: 0,
toDocument: PAGESIZE,
}; };
this.state.tableEntityListViewModel.queryTablesTab = this.props.queryTablesTab; this.state.tableEntityListViewModel.queryTablesTab = this.props.queryTablesTab;
@ -243,6 +224,10 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
let selectedItems: Entities.ITableEntity[]; let selectedItems: Entities.ITableEntity[];
const { selection } = this.state; const { selection } = this.state;
isFirstItemSelected && selection.setIndexSelected(0, true, false); isFirstItemSelected && selection.setIndexSelected(0, true, false);
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 254 ~ QueryTablesTabComponent ~ selection.getSelection().length",
selection.getSelection().length
);
if (selection.getSelection().length > 0) { if (selection.getSelection().length > 0) {
Object.keys(this.state.selection.getSelection()[0]).map((key, index) => { Object.keys(this.state.selection.getSelection()[0]).map((key, index) => {
if (key === documentKey) { if (key === documentKey) {
@ -254,6 +239,11 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
selectedItems: selectedItems, selectedItems: selectedItems,
rowSelected: true, rowSelected: true,
}); });
} else {
this.setState({
selectedItems: [],
rowSelected: false,
});
} }
return selectedItems; return selectedItems;
}; };
@ -364,10 +354,8 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
}); });
const documentItems = this.generateDetailsList(entities); const documentItems = this.generateDetailsList(entities);
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 367 ~ QueryTablesTabComponent ~ documentItems", const filteredItems = documentItems.slice(0, PAGESIZE);
documentItems
);
this.setState( this.setState(
{ {
@ -375,11 +363,12 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
headers, headers,
operators: this.state.queryViewModel.queryBuilderViewModel().operators(), operators: this.state.queryViewModel.queryBuilderViewModel().operators(),
isLoading: false, isLoading: false,
items: documentItems, items: filteredItems,
entities: entities, entities: entities,
originalItems: documentItems, originalItems: documentItems,
queryText: this.state.queryViewModel.queryText(), queryText: this.state.queryViewModel.queryText(),
// queryTableRows: headers.length === 0 ? [] : this.state.queryTableRows, fromDocument: 0,
toDocument: PAGESIZE,
}, },
() => { () => {
if (isInitialLoad && headers.length > 0) { if (isInitialLoad && headers.length > 0) {
@ -488,6 +477,10 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
}; };
public onEditEntityClick = (): void => { public onEditEntityClick = (): void => {
if (!this.state.rowSelected) {
window.alert("Please select entity to edit");
return undefined;
}
useSidePanel useSidePanel
.getState() .getState()
.openSidePanel( .openSidePanel(
@ -504,7 +497,8 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
}; };
public onDeleteEntityClick = (): void => { public onDeleteEntityClick = (): void => {
if (!this.state.selectedItems) { if (!this.state.rowSelected) {
window.alert("Please select entity to delete");
return undefined; return undefined;
} }
const entitiesToDelete: Entities.ITableEntity[] = this.state.selectedItems; const entitiesToDelete: Entities.ITableEntity[] = this.state.selectedItems;
@ -517,12 +511,10 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
.deleteDocuments(this.state.tableEntityListViewModel.queryTablesTab.collection, entitiesToDelete) .deleteDocuments(this.state.tableEntityListViewModel.queryTablesTab.collection, entitiesToDelete)
//eslint-disable-next-line //eslint-disable-next-line
.then((results: any) => { .then((results: any) => {
return this.state.tableEntityListViewModel.removeEntitiesFromCache(entitiesToDelete).then(() => { this.setState({
this.setState({ isLoading: true,
isLoading: true,
});
this.loadEntities(false);
}); });
this.loadEntities(false);
}); });
} }
}; };
@ -748,7 +740,6 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
}; };
public onAddNewClauseKeyDown(event: React.KeyboardEvent<HTMLDivElement>): void { public onAddNewClauseKeyDown(event: React.KeyboardEvent<HTMLDivElement>): void {
console.log("🚀 ~ file: QueryTablesTabComponent.tsx ~ line 723 ~ QueryTablesTabComponent ~ event", event);
if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) { if (event.key === NormalizedEventKey.Space || event.key === NormalizedEventKey.Enter) {
this.state.queryViewModel.queryBuilderViewModel().onAddNewClauseKeyDown(event); this.state.queryViewModel.queryBuilderViewModel().onAddNewClauseKeyDown(event);
this.onAddNewClause(); this.onAddNewClause();
@ -763,6 +754,65 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.setState({ queryTableRows: cloneQueryTableRows }); this.setState({ queryTableRows: cloneQueryTableRows });
}; };
private handlePagination = (action: string, items: IDocument[], startIndex: number, pageSize: number): void => {
let currentStartIndex: number;
let fromDocument: number;
let toDocument: number;
let filteredItems: IDocument[];
// eslint-disable-next-line no-console
switch (action) {
case "NEXT":
fromDocument = this.state.currentStartIndex;
toDocument = fromDocument + pageSize;
currentStartIndex = toDocument;
if (toDocument <= items.length) {
filteredItems = items.slice(fromDocument, toDocument);
} else {
filteredItems = items.slice(fromDocument, items.length);
toDocument = items.length;
}
break;
case "PREVIOUS":
fromDocument = this.state.currentStartIndex - pageSize * 2;
toDocument = fromDocument + pageSize;
currentStartIndex = toDocument;
if (fromDocument >= 0) {
filteredItems = items.slice(fromDocument, toDocument);
} else {
filteredItems = items.slice(0, toDocument);
fromDocument = 0;
}
break;
case "FIRST":
fromDocument = 0;
toDocument = fromDocument + pageSize;
currentStartIndex = toDocument;
filteredItems = items.slice(fromDocument, toDocument);
break;
case "LAST":
if (items.length % pageSize === 0) {
fromDocument = items.length - pageSize;
} else {
fromDocument = items.length - (items.length % pageSize);
}
toDocument = items.length;
currentStartIndex = fromDocument + pageSize;
filteredItems = items.slice(fromDocument, toDocument);
break;
}
if (filteredItems.length > 0) {
this.setState({
currentStartIndex: currentStartIndex,
fromDocument: fromDocument,
toDocument: toDocument,
items: filteredItems,
});
}
};
render(): JSX.Element { render(): JSX.Element {
useCommandBar.getState().setContextButtons(this.getTabsButtons()); useCommandBar.getState().setContextButtons(this.getTabsButtons());
const { queryTableRows } = this.state; const { queryTableRows } = this.state;
@ -830,7 +880,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
</thead> </thead>
</table> </table>
</div> </div>
<> <div className="query-table-clause-container">
{queryTableRows.map((queryTableRow, index) => ( {queryTableRows.map((queryTableRow, index) => (
<QueryTableEntityClause <QueryTableEntityClause
index={index} index={index}
@ -863,7 +913,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
} }
/> />
))} ))}
</> </div>
<div <div
className="addClause" className="addClause"
role="button" role="button"
@ -959,6 +1009,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
{this.state.isLoading && <Spinner size={SpinnerSize.large} className="spinner" />} {this.state.isLoading && <Spinner size={SpinnerSize.large} className="spinner" />}
{this.state.items.length > 0 && !this.state.isLoading && ( {this.state.items.length > 0 && !this.state.isLoading && (
<DetailsList <DetailsList
className="query-document-detail-list"
items={this.state.items} items={this.state.items}
columns={this.state.columns} columns={this.state.columns}
selectionMode={SelectionMode.single} selectionMode={SelectionMode.single}
@ -973,6 +1024,66 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
<Text variant="mediumPlus">No data available in table</Text> <Text variant="mediumPlus">No data available in table</Text>
)} )}
</div> </div>
<div className="query-tab-document-pagination">
{this.state.items.length > 0 && !this.state.isLoading && (
<>
<ul className="pagination ">
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("FIRST", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
First
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination(
"PREVIOUS",
this.state.originalItems,
this.state.currentStartIndex,
PAGESIZE
)
}
>
Previous
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("NEXT", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
Next
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("LAST", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
Last
</div>
</li>
</ul>
<Text variant="medium">
Results {this.state.fromDocument + 1} -{" "}
{this.state.originalItems.length >= this.state.toDocument
? this.state.toDocument
: this.state.items.length}{" "}
of {this.state.originalItems.length}
</Text>
</>
)}
</div>
</div> </div>
); );
} }