DetailsList implemented

This commit is contained in:
vaidankarswapnil 2021-07-29 12:15:21 +05:30
parent 754f0b392c
commit 4f632b234f
4 changed files with 255 additions and 140 deletions

View File

@ -25,6 +25,7 @@ abstract class DataTableViewModel {
/* Observables */
public items = ko.observableArray<Entities.ITableEntity>();
public items1: Entities.ITableEntity[];
public selected = ko.observableArray<Entities.ITableEntity>();
public table: DataTables.DataTable;
@ -54,6 +55,7 @@ abstract class DataTableViewModel {
constructor() {
this.items([]);
this.items1 = [];
this.selected([]);
// Late bound
this.dataTableOperationManager = null;
@ -172,36 +174,38 @@ abstract class DataTableViewModel {
}
protected renderPage(
renderCallBack: any,
draw: number,
// renderCallBack: any,
// draw: number,
startIndex: number,
pageSize: number,
oSettings: any,
postRenderTasks: (startIndex: number, pageSize: number) => Promise<void> = null
pageSize: number
// oSettings: any,
// postRenderTasks: (startIndex: number, pageSize: number) => Promise<void> = null
) {
this.updatePaginationControls(oSettings);
// this.updatePaginationControls(oSettings);
// pageSize < 0 means to show all data
var endIndex = pageSize < 0 ? this.cache.length : startIndex + pageSize;
var renderData = this.cache.data.slice(startIndex, endIndex);
this.items(renderData);
this.items1 = renderData;
console.log("🚀 ~ file: DataTableViewModel.ts ~ line 191 ~ DataTableViewModel ~ renderData", renderData);
console.log("🚀 ~ file: DataTableViewModel.ts ~ line 192 ~ DataTableViewModel ~ this.items", this.items());
var render: IDataTableRenderData = {
draw: draw,
aaData: renderData,
recordsTotal: this.cache.length,
recordsFiltered: this.cache.length,
};
console.log("🚀 ~ file: DataTableViewModel.ts ~ line 192 ~ DataTableViewModel ~ this.items1", this.items1);
// var render: IDataTableRenderData = {
// draw: draw,
// aaData: renderData,
// recordsTotal: this.cache.length,
// recordsFiltered: this.cache.length,
// };
if (!!postRenderTasks) {
postRenderTasks(startIndex, pageSize).then(() => {
this.table.rows().invalidate();
});
}
renderCallBack(render);
// if (!!postRenderTasks) {
// postRenderTasks(startIndex, pageSize).then(() => {
// this.table.rows().invalidate();
// });
// }
// renderCallBack(render);
if (this.queryTablesTab.onLoadStartKey != null && this.queryTablesTab.onLoadStartKey != undefined) {
TelemetryProcessor.traceSuccess(
Action.Tab,

View File

@ -149,10 +149,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
public updateHeaders(newHeaders: string[], notifyColumnChanges: boolean = false, enablePrompt: boolean = true): void {
this.headers = newHeaders;
if (notifyColumnChanges) {
this.clearSelection();
this.notifyColumnChanges(enablePrompt, this.queryTablesTab);
}
// if (notifyColumnChanges) {
// this.clearSelection();
// this.notifyColumnChanges(enablePrompt, this.queryTablesTab);
// }
}
/**
@ -162,7 +162,7 @@ export default class TableEntityListViewModel extends DataTableViewModel {
* fnCallback - is the render callback with data to render.
* oSetting: current settings used for table initialization.
*/
public renderNextPageAndupdateCache(sSource: any, aoData: any, fnCallback: any, oSettings: any) {
public renderNextPageAndupdateCache(sSource?: any, aoData?: any, fnCallback?: any, oSettings?: any): Promise<void> {
var tablePageSize: number;
var draw: number;
var prefetchNeeded = true;
@ -172,21 +172,21 @@ export default class TableEntityListViewModel extends DataTableViewModel {
var prefetchThreshold = 10;
var tableQuery = this.tableQuery;
for (var index in aoData) {
var data = aoData[index];
if (data.name === "length") {
tablePageSize = data.value;
}
if (data.name === "start") {
this.tablePageStartIndex = data.value;
}
if (data.name === "draw") {
draw = data.value;
}
if (data.name === "order") {
columnSortOrder = data.value;
}
}
// for (var index in aoData) {
// var data = aoData[index];
// if (data.name === "length") {
// tablePageSize = data.value;
// }
// if (data.name === "start") {
// this.tablePageStartIndex = data.value;
// }
// if (data.name === "draw") {
// draw = data.value;
// }
// if (data.name === "order") {
// columnSortOrder = data.value;
// }
// }
// Try cache if valid.
if (this.isCacheValid(tableQuery)) {
// Check if prefetch needed.
@ -195,7 +195,7 @@ export default class TableEntityListViewModel extends DataTableViewModel {
if (columnSortOrder && (!this.cache.sortOrder || !_.isEqual(this.cache.sortOrder, columnSortOrder))) {
this.sortColumns(columnSortOrder, oSettings);
}
this.renderPage(fnCallback, draw, this.tablePageStartIndex, tablePageSize, oSettings);
this.renderPage(this.tablePageStartIndex, tablePageSize);
if (
!this.allDownloaded &&
this.tablePageStartIndex > 0 && // This is a case now that we can hit this as we re-construct table when we update column
@ -218,11 +218,11 @@ export default class TableEntityListViewModel extends DataTableViewModel {
tablePageSize,
downloadSize,
draw,
fnCallback,
oSettings,
columnSortOrder
);
}
return undefined;
}
public addEntityToCache(entity: Entities.ITableEntity): Q.Promise<any> {
@ -402,7 +402,7 @@ export default class TableEntityListViewModel extends DataTableViewModel {
tablePageSize: number,
downloadSize: number,
draw: number,
renderCallBack: Function,
// renderCallBack: Function,
oSettings: any,
columnSortOrder: any
): void {
@ -432,6 +432,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
userContext.apiType === "Cassandra"
);
var newHeaders: string[] = _.difference(selectedHeadersUnion, this.headers);
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 435 ~ TableEntityListViewModel ~ .then ~ newHeaders",
newHeaders
);
if (newHeaders.length > 0) {
// Any new columns found will be added into headers array, which will trigger a re-render of the DataTable.
// So there is no need to call it here.
@ -440,8 +444,9 @@ export default class TableEntityListViewModel extends DataTableViewModel {
if (columnSortOrder) {
this.sortColumns(columnSortOrder, oSettings);
}
this.renderPage(renderCallBack, draw, tablePageStartIndex, tablePageSize, oSettings);
// this.renderPage(renderCallBack, draw, tablePageStartIndex, tablePageSize, oSettings);
}
this.renderPage(0, 100);
}
if (result.ExceedMaximumRetries) {
@ -449,6 +454,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
}
})
.catch((error: any) => {
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 452 ~ TableEntityListViewModel ~ //constructor ~ error",
error
);
const parsedErrors = parseError(error);
var errors = parsedErrors.map((error) => {
return <ViewModels.QueryError>{
@ -562,6 +571,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
} else {
// Create cache.
this.cache.data = entities;
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 569 ~ TableEntityListViewModel ~ .then ~ this.cache.data",
this.cache.data
);
}
this.cache.tableQuery = tableQuery;

View File

@ -160,7 +160,7 @@ export default class QueryViewModel {
notify: "always",
});
public runQuery = (): DataTables.DataTable => {
public runQuery = (): void => {
let filter = this.setFilter();
if (filter && userContext.apiType !== "Cassandra") {
filter = filter.replace(/"/g, "'");
@ -175,7 +175,7 @@ export default class QueryViewModel {
this._tableEntityListViewModel.sqlQuery(this.setSqlFilter());
this._tableEntityListViewModel.cqlQuery(filter);
return this._tableEntityListViewModel.reloadTable(/*useSetting*/ false, /*resetHeaders*/ false);
// return this._tableEntityListViewModel.reloadTable(/*useSetting*/ false, /*resetHeaders*/ false);
};
public clearQuery = (): DataTables.DataTable => {

View File

@ -1,3 +1,4 @@
import { DetailsList, DetailsListLayoutMode, IColumn, SelectionMode } from "@fluentui/react";
import * as ko from "knockout";
import React, { Component } from "react";
import QueryInformation from "../../../../images//QueryBuilder/QueryInformation_16x.png";
@ -33,7 +34,11 @@ export interface Button {
enabled: boolean;
isSelected?: boolean;
}
export interface IDocument {
partitionKey: string;
rowKey: string;
timeStamp: string;
}
export interface IQueryTablesTabComponentProps {
tabKind: ViewModels.CollectionTabKind;
title: string;
@ -58,6 +63,9 @@ interface IQueryTablesTabComponentStates {
editEntityButton: Button;
deleteEntityButton: Button;
isHelperActive: boolean;
columns: IColumn[];
items: IDocument[];
isExpanded: boolean;
}
class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, IQueryTablesTabComponentStates> {
@ -86,9 +94,38 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
public valueLabel: string;
public tableEntityListViewModel1: TableEntityListViewModel;
public tableEntityListViewModel2 = ko.observable<TableEntityListViewModel>();
public allItems: IDocument[];
// public columns: IColumn[];
constructor(props: IQueryTablesTabComponentProps) {
super(props);
// this.columns = [];
const columns: IColumn[] = [
{
key: "column1",
name: "PartitionKey",
minWidth: 100,
maxWidth: 200,
data: String,
fieldName: "partitionKey",
// onRender: this.onRenderColumnItem,
},
{
key: "column2",
name: "RowKey",
minWidth: 100,
maxWidth: 200,
data: String,
fieldName: "rowKey",
},
{
key: "column3",
name: "Timestamp",
minWidth: 200,
maxWidth: 200,
data: String,
fieldName: "timeStamp",
},
];
this.container = props.collection && props.collection.container;
this.tableCommands = new TableCommands(this.container);
this.tableDataClient = this.container.tableDataClient;
@ -146,6 +183,9 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
visible: true,
isSelected: false,
},
columns: columns,
items: [],
isExpanded: false,
};
this.state.tableEntityListViewModel.queryTablesTab = this.props.queryTablesTab;
// console.log(
@ -174,27 +214,73 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.valueLabel = this.state.queryViewModel.queryBuilderViewModel().valueLabel;
useCommandBar.getState().setContextButtons(this.getTabsButtons());
this.state.tableEntityListViewModel.items.subscribe(() => {
console.log(
"🚀 ~ file: QueryTablesTab.tsx ~ line 54 ~ QueryTablesTab ~ sampleQuerySubscription ~ this.tableEntityListViewModel().items().length",
this.state.tableEntityListViewModel.items()
);
if (this.state.tableEntityListViewModel.items().length > 0 && userContext.apiType === "Tables") {
// this.state.queryViewModel.queryBuilderViewModel.setExample();
// console.log(
// "🚀 ~ file: QueryTablesTab.tsx ~ line 55 ~ QueryTablesTab ~ sampleQuerySubscription ~ this.queryViewModel().queryBuilderViewModel().setExample()",
// this.state.queryViewModel.queryBuilderViewModel.setExample()
// );
}
});
this.props.queryTablesTab.container.tableDataClient.queryDocuments(
this.props.queryTablesTab.collection,
"SELECT * FROM c",
true
);
// this.state.tableEntityListViewModel.items.subscribe(() => {
// console.log(
// "🚀 ~ file: QueryTablesTab.tsx ~ line 54 ~ QueryTablesTab ~ sampleQuerySubscription ~ this.tableEntityListViewModel().items().length",
// this.state.tableEntityListViewModel.items()
// );
// if (this.state.tableEntityListViewModel.items().length > 0 && userContext.apiType === "Tables") {
// // this.state.queryViewModel.queryBuilderViewModel.setExample();
// // console.log(
// // "🚀 ~ file: QueryTablesTab.tsx ~ line 55 ~ QueryTablesTab ~ sampleQuerySubscription ~ this.queryViewModel().queryBuilderViewModel().setExample()",
// // this.state.queryViewModel.queryBuilderViewModel.setExample()
// // );
// }
// });
// this.test();
// this.state.tableEntityListViewModel.renderNextPageAndupdateCache();
// setTimeout(() => {
// console.log("items > ", this.state.tableEntityListViewModel.cache.data);
// console.log("items > ", this.state.tableEntityListViewModel.items());
// console.log("items1 > ", this.state.tableEntityListViewModel.items1);
// console.log("items1 > simple > ", this.tableEntityListViewModel1.items1);
// this.allItems = this.generateDetailsList();
// this.setState({
// items: this.allItems,
// });
// // this.state = {
// // items: this.generateDetailsList()
// // }
// }, 10000);
// this.props.queryTablesTab.container.tableDataClient.queryDocuments(
// this.props.queryTablesTab.collection,
// "SELECT * FROM c",
// true
// );
this.buildCommandBarOptions();
}
async componentDidMount(): Promise<void> {
const abc = await this.state.tableEntityListViewModel.renderNextPageAndupdateCache();
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 249 ~ QueryTablesTabComponent ~ componentDidMount ~ abc",
abc
);
setTimeout(() => {
console.log("items > ", this.state.tableEntityListViewModel.cache.data);
console.log("items > ", this.state.tableEntityListViewModel.items());
console.log("items1 > ", this.state.tableEntityListViewModel.headers);
console.log("items1 > simple > ", this.tableEntityListViewModel1.items1);
// this.state.tableEntityListViewModel.headers.map(header => {
// })
this.allItems = this.generateDetailsList();
this.setState({
items: this.allItems,
});
// this.state = {
// items: this.generateDetailsList()
// }
}, 10000);
}
// public async test(): Promise<void> {
// await this.state.tableEntityListViewModel.renderNextPageAndupdateCache().then(() => {
// console.log("inside > ", this.state.tableEntityListViewModel.items());
// });
// console.log("items > ", this.state.tableEntityListViewModel.items());
// }
public onAddEntityClick = (): void => {
useSidePanel
.getState()
@ -315,6 +401,32 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.props.tabsBaseInstance.updateNavbarWithTabsButtons();
}
public generateDetailsList(): IDocument[] {
const items: IDocument[] = [];
this.state.tableEntityListViewModel.items().map((item) => {
console.log("generateDetailsList > ", item["PartitionKey"]._);
items.push({
partitionKey: item["PartitionKey"]._,
rowKey: item["RowKey"]._,
timeStamp: item["Timestamp"]._,
});
});
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 383 ~ QueryTablesTabComponent ~ this.state.tableEntityListViewModel.items ~ items",
items
);
return items;
}
toggleAdvancedOptions(): void {
// console.log("toggleAdvancedOptions!");
this.setState({
isExpanded: !this.state.isExpanded,
});
this.state.queryViewModel.toggleAdvancedOptions();
}
render(): JSX.Element {
useCommandBar.getState().setContextButtons(this.getTabsButtons());
@ -411,96 +523,82 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
</div>
)}
<div className="advanced-options-panel">
<div className="advanced-heading">
<div className="advanced-heading" onClick={() => this.toggleAdvancedOptions()}>
<span
className="advanced-title"
role="button"
aria-expanded={this.state.isExpanded}
// onKeyDown = {() => this.state.queryViewModel.ontoggleAdvancedOptionsKeyDown}
// data-bind="click:toggleAdvancedOptions, event: { keydown: ontoggleAdvancedOptionsKeyDown }, attr:{ 'aria-expanded': isExpanded() ? 'true' : 'false' }"
tabIndex={0}
>
<div
className="themed-images"
// type="text/html"
id="ExpandChevronRight"
// data-bind="hasFocus: focusExpandIcon"
>
<img
className="imgiconwidth expand-triangle expand-triangle-right"
src={TriangleRight}
alt="toggle"
/>
</div>
<div
className="themed-images"
// type="text/html"
id="ExpandChevronDown"
>
<img className="imgiconwidth expand-triangle" src={TriangleDown} alt="toggle" />
</div>
{!this.state.isExpanded && (
<div className="themed-images" id="ExpandChevronRight">
<img
className="imgiconwidth expand-triangle expand-triangle-right"
src={TriangleRight}
alt="toggle"
/>
</div>
)}
{this.state.queryViewModel.isExpanded() && (
<div className="themed-images" id="ExpandChevronDown">
<img className="imgiconwidth expand-triangle" src={TriangleDown} alt="toggle" />
</div>
)}
<span>Advanced Options</span>
</span>
</div>
<div
className="advanced-options"
// data-bind="visible: isExpanded"
>
<div className="top">
<span>Show top results:</span>
<input
className="top-input"
type="number"
// data-bind="hasFocus: focusTopResult, textInput: topValue, attr: { title: topValueLimitMessage }"
role="textbox"
aria-label="Show top results"
/>
<div
role="alert"
aria-atomic="true"
className="inline-div"
// data-bind="visible: isExceedingLimit"
>
<img className="advanced-options-icon" src={StatusWraning} />
<span data-bind="text: topValueLimitMessage"></span>
</div>
</div>
<div className="select">
<span> Select fields for query: </span>
<div
// data-bind="visible: isSelected"
>
<img className="advanced-options-icon" src={QueryInformation} />
<span
className="select-options-text"
// data-bind="text: selectMessage"
{this.state.isExpanded && (
<div className="advanced-options">
<div className="top">
<span>Show top results:</span>
<input
className="top-input"
type="number"
title={this.state.queryViewModel.topValueLimitMessage}
// data-bind="hasFocus: focusTopResult, textInput: topValue, attr: { title: topValueLimitMessage }"
role="textbox"
aria-label="Show top results"
/>
{this.state.queryViewModel.isExceedingLimit() && (
<div role="alert" aria-atomic="true" className="inline-div">
<img className="advanced-options-icon" src={StatusWraning} />
<span>{this.state.queryViewModel.topValueLimitMessage}</span>
</div>
)}
</div>
<div className="select">
<span> Select fields for query: </span>
{this.state.queryViewModel.isSelected() && (
<div>
<img className="advanced-options-icon" src={QueryInformation} />
<span className="select-options-text">{this.state.queryViewModel.selectMessage()}</span>
</div>
)}
<a
className="select-options-link"
// data-bind="click: selectQueryOptions, event: { keydown: onselectQueryOptionsKeyDown }"
tabIndex={0}
role="link"
onClick={() => this.state.queryViewModel.selectQueryOptions()}
>
<span>Choose Columns... </span>
</a>
</div>
<a
className="select-options-link"
// data-bind="click: selectQueryOptions, event: { keydown: onselectQueryOptionsKeyDown }"
tabIndex={0}
role="link"
>
<span>Choose Columns... </span>
</a>
</div>
</div>
)}
</div>
</div>
{this.state.tableEntityListViewModel.items().map((item, index) => (
<label key={index}>{item}</label>
))}
<div
className="tablesQueryTab tableContainer"
data-bind="with: tableEntityListViewModel, attr: {
id: tableEntityListViewModel.id
}"
>
<table
id="storageTable"
className="storage azure-table show-gridlines"
tabIndex={0}
data-bind="tableSource: items, tableSelection: selected"
></table>
<div className="tablesQueryTab tableContainer">
<DetailsList
items={this.state.items}
columns={this.state.columns}
selectionMode={SelectionMode.none}
layoutMode={DetailsListLayoutMode.justified}
compact={true}
/>
</div>
</div>
);