Async and await implemented for loadEntities

This commit is contained in:
vaidankarswapnil 2021-08-16 13:27:30 +05:30
parent 046e6eb5a4
commit b7cb0b55a6
8 changed files with 508 additions and 483 deletions

View File

@ -535,11 +535,11 @@ input::-webkit-inner-spin-button {
} }
.query-document-detail-list { .query-document-detail-list {
overflow-x: hidden; // overflow-x: hidden;
height: 100%; height: 100%;
} }
.query-table-clause-container { .query-table-clause-container {
max-height: 80px; max-height: 150px;
overflow: scroll; overflow: scroll;
overflow-x: hidden; overflow-x: hidden;
} }
@ -569,6 +569,14 @@ input::-webkit-inner-spin-button {
} }
} }
} }
.noData {
background-color: #e3e2e6;
color: #e3e2e6;
padding-top: 1px;
height: 100%;
width: 100%;
}
// .pagination > li > div { // .pagination > li > div {
// } // }

View File

@ -1,8 +1,10 @@
import { IDropdownOption, Image, Label, Stack, Text, TextField } from "@fluentui/react"; import { IDropdownOption, Image, Label, Stack, Text, TextField } from "@fluentui/react";
import { useBoolean } from "@fluentui/react-hooks"; import { useBoolean } from "@fluentui/react-hooks";
import React, { FunctionComponent, useEffect, useState } from "react"; import React, { FunctionComponent, useEffect, useState } from "react";
import * as _ from "underscore";
import AddPropertyIcon from "../../../../images/Add-property.svg"; import AddPropertyIcon from "../../../../images/Add-property.svg";
import RevertBackIcon from "../../../../images/RevertBack.svg"; import RevertBackIcon from "../../../../images/RevertBack.svg";
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
import { TableEntity } from "../../../Common/TableEntity"; import { TableEntity } from "../../../Common/TableEntity";
import { useSidePanel } from "../../../hooks/useSidePanel"; import { useSidePanel } from "../../../hooks/useSidePanel";
import { userContext } from "../../../UserContext"; import { userContext } from "../../../UserContext";
@ -11,6 +13,7 @@ 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, CassandraTableKey, TableDataClient } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient, CassandraTableKey, TableDataClient } from "../../Tables/TableDataClient";
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
import * as Utilities from "../../Tables/Utilities"; import * as Utilities from "../../Tables/Utilities";
import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab"; import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
@ -115,10 +118,62 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
setIsExecuting(true); setIsExecuting(true);
const entity: Entities.ITableEntity = entityFromAttributes(entities); const entity: Entities.ITableEntity = entityFromAttributes(entities);
await tableDataClient.createDocument(queryTablesTab.collection, entity); const newEntity: Entities.ITableEntity = await tableDataClient.createDocument(queryTablesTab.collection, entity);
// await tableEntityListViewModel.addEntityToCache(newEntity); try {
await tableEntityListViewModel.addEntityToCache(newEntity);
// if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
// tableEntityListViewModel.redrawTableThrottled();
reloadEntities(); reloadEntities();
closeSidePanel(); setFormError("");
// }
} catch (error) {
const errorMessage = getErrorMessage(error);
setFormError(errorMessage);
handleError(errorMessage, "AddTableRow");
throw error;
} finally {
setIsExecuting(false);
}
// try {
// await tableDataClient.createDocument(queryTablesTab.collection, entity);
// reloadEntities();
// setFormError("");
// closeSidePanel();
// } catch (error) {
// const errorMessage = getErrorMessage(error);
// setFormError(errorMessage);
// handleError(errorMessage, "AddTableRow");
// } finally {
// setIsExecuting(false);
// }
};
const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => {
let newHeaders: string[] = [];
const keys = Object.keys(newEntity);
keys &&
keys.forEach((key: string) => {
if (
!_.contains(viewModel.headers, key) &&
key !== TableEntityProcessor.keyProperties.attachments &&
key !== TableEntityProcessor.keyProperties.etag &&
key !== TableEntityProcessor.keyProperties.resourceId &&
key !== TableEntityProcessor.keyProperties.self &&
(!(userContext.apiType === "Cassandra") || key !== TableConstants.EntityKeyNames.RowKey)
) {
newHeaders.push(key);
}
});
let newHeadersInserted = false;
if (newHeaders.length) {
if (!DataTableUtilities.checkForDefaultHeader(viewModel.headers)) {
newHeaders = viewModel.headers.concat(newHeaders);
}
viewModel.updateHeaders(newHeaders, /* notifyColumnChanges */ true, /* enablePrompt */ false);
newHeadersInserted = true;
}
return newHeadersInserted;
}; };
/* Add new entity row */ /* Add new entity row */

View File

@ -4,10 +4,12 @@ import React, { FunctionComponent, useEffect, useState } from "react";
import * as _ from "underscore"; import * as _ from "underscore";
import AddPropertyIcon from "../../../../images/Add-property.svg"; import AddPropertyIcon from "../../../../images/Add-property.svg";
import RevertBackIcon from "../../../../images/RevertBack.svg"; import RevertBackIcon from "../../../../images/RevertBack.svg";
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
import { TableEntity } from "../../../Common/TableEntity"; 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 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";
@ -213,9 +215,59 @@ 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;
await newTableDataClient.updateDocument(queryTablesTab.collection, originalDocumentData, entity); // await newTableDataClient.updateDocument(queryTablesTab.collection, originalDocumentData, entity);
try {
const newEntity: Entities.ITableEntity = await newTableDataClient.updateDocument(
queryTablesTab.collection,
originalDocumentData,
entity
);
await tableEntityListViewModel.updateCachedEntity(newEntity);
// if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
// tableEntityListViewModel.redrawTableThrottled();
reloadEntities(); reloadEntities();
closeSidePanel(); closeSidePanel();
// }
tableEntityListViewModel.selected.removeAll();
tableEntityListViewModel.selected.push(newEntity);
} catch (error) {
const errorMessage = getErrorMessage(error);
handleError(errorMessage, "EditTableRow");
throw error;
} finally {
setIsExecuting(false);
}
// reloadEntities();
// closeSidePanel();
};
const tryInsertNewHeaders = (viewModel: TableEntityListViewModel, newEntity: Entities.ITableEntity): boolean => {
let newHeaders: string[] = [];
const keys = Object.keys(newEntity);
keys &&
keys.forEach((key: string) => {
if (
!_.contains(viewModel.headers, key) &&
key !== TableEntityProcessor.keyProperties.attachments &&
key !== TableEntityProcessor.keyProperties.etag &&
key !== TableEntityProcessor.keyProperties.resourceId &&
key !== TableEntityProcessor.keyProperties.self &&
(!(userContext.apiType === "Cassandra") || key !== TableConstants.EntityKeyNames.RowKey)
) {
newHeaders.push(key);
}
});
let newHeadersInserted = false;
if (newHeaders.length) {
if (!DataTableUtilities.checkForDefaultHeader(viewModel.headers)) {
newHeaders = viewModel.headers.concat(newHeaders);
}
viewModel.updateHeaders(newHeaders, /* notifyColumnChanges */ true, /* enablePrompt */ false);
newHeadersInserted = true;
}
return newHeadersInserted;
}; };
// Add new entity row // Add new entity row

View File

@ -170,6 +170,10 @@ abstract class DataTableViewModel {
} }
protected renderPage(startIndex: number, pageSize: number) { protected renderPage(startIndex: number, pageSize: number) {
console.log(
"🚀 ~ file: DataTableViewModel.ts ~ line 179 ~ DataTableViewModel ~ renderPage ~ this.cache.data",
this.cache.data
);
var endIndex = pageSize < 0 ? this.cache.length : startIndex + pageSize; var endIndex = pageSize < 0 ? this.cache.length : startIndex + pageSize;
var renderData = this.cache.data.slice(startIndex, endIndex); var renderData = this.cache.data.slice(startIndex, endIndex);

View File

@ -148,6 +148,97 @@ export default class TableEntityListViewModel extends DataTableViewModel {
this.headers = newHeaders; this.headers = newHeaders;
} }
public async a(): Promise<Entities.ITableEntity[]> {
const a = await this.b();
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 153 ~ TableEntityListViewModel ~ a ~ a", a);
return a;
}
public async b(): Promise<Entities.ITableEntity[]> {
const b = await this.c();
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 157 ~ TableEntityListViewModel ~ b ~ b", b);
return b;
}
public async c(tableQuery?: Entities.ITableQuery, downloadSize?: number): Promise<any> {
var c: any;
var d: any;
if (this._documentIterator && this.continuationToken) {
// TODO handle Cassandra case
d = await this._documentIterator.fetchNext();
let entities: Entities.ITableEntity[] = TableEntityProcessor.convertDocumentsToEntities(d.resources);
let finalEntities: IListTableEntitiesSegmentedResult = <IListTableEntitiesSegmentedResult>{
Results: entities,
ContinuationToken: this._documentIterator.hasMoreResults(),
};
c = finalEntities;
// .fetchNext()
// .then((response) => response.resources)
// .then((documents: any[]) => {
// let entities: Entities.ITableEntity[] = TableEntityProcessor.convertDocumentsToEntities(documents);
// let finalEntities: IListTableEntitiesSegmentedResult = <IListTableEntitiesSegmentedResult>{
// Results: entities,
// ContinuationToken: this._documentIterator.hasMoreResults(),
// };
// return Promise.resolve(finalEntities);
// });
} else {
c = await this.queryTablesTab.container.tableDataClient.queryDocuments(
this.queryTablesTab.collection,
this.sqlQuery(),
true
);
}
// const c = await this.queryTablesTab.container.tableDataClient.queryDocuments(
// this.queryTablesTab.collection,
// this.sqlQuery(),
// true
// );
const result = c;
if (result) {
if (!this._documentIterator) {
this._documentIterator = result.iterator;
}
var actualDownloadSize: number = 0;
var entities = result.Results;
actualDownloadSize = entities.length;
this.continuationToken = this.isCancelled ? null : result.ContinuationToken;
if (!this.continuationToken) {
this.allDownloaded = true;
}
if (this.isCacheValid(this.tableQuery)) {
// Append to cache.
this.cache.data = this.cache.data.concat(entities.slice(0));
} else {
// Create cache.
this.cache.data = entities;
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 797 ~ TableEntityListViewModel ~ .then ~ this.cache.data",
this.cache.data
);
}
this.cache.tableQuery = this.tableQuery;
this.cache.serverCallInProgress = false;
var nextDownloadSize: number = this.downloadSize - actualDownloadSize;
if (nextDownloadSize === 0 && this.tableQuery.top) {
this.allDownloaded = true;
}
if (this.allDownloaded || nextDownloadSize === 0) {
return Promise.resolve(this.cache.data);
}
return this.c(this.tableQuery, nextDownloadSize);
}
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 161 ~ TableEntityListViewModel ~ c ~ data", c);
return this.cache.data;
}
/** /**
* This callback function called by datatable to fetch the next page of data and render. * This callback function called by datatable to fetch the next page of data and render.
* sSource - ajax URL of data source, ignored in our case as we are not using ajax. * sSource - ajax URL of data source, ignored in our case as we are not using ajax.
@ -155,10 +246,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
* fnCallback - is the render callback with data to render. * fnCallback - is the render callback with data to render.
* oSetting: current settings used for table initialization. * oSetting: current settings used for table initialization.
*/ */
public renderNextPageAndupdateCache(sSource?: any, aoData?: any, fnCallback?: any): Promise<void> {
var tablePageSize: number = 100; public async renderNextPageAndupdateCache(): Promise<Entities.ITableEntity[]> {
var tablePageSize: number;
var prefetchNeeded = true; var prefetchNeeded = true;
// var columnSortOrder: any;
// Threshold(pages) for triggering cache prefetch. // Threshold(pages) for triggering cache prefetch.
// If number remaining pages in cache falls below prefetchThreshold prefetch will be triggered. // If number remaining pages in cache falls below prefetchThreshold prefetch will be triggered.
var prefetchThreshold = 10; var prefetchThreshold = 10;
@ -169,12 +260,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
// Check if prefetch needed. // Check if prefetch needed.
if (this.tablePageStartIndex + tablePageSize <= this.cache.length || this.allDownloaded) { if (this.tablePageStartIndex + tablePageSize <= this.cache.length || this.allDownloaded) {
prefetchNeeded = false; prefetchNeeded = false;
// if (columnSortOrder && (!this.cache.sortOrder || !_.isEqual(this.cache.sortOrder, columnSortOrder))) {
// this.sortColumns(columnSortOrder, oSettings);
// }
this.tablePageStartIndex = 0; this.tablePageStartIndex = 0;
this.renderPage(this.tablePageStartIndex, tablePageSize); this.renderPage(this.tablePageStartIndex, this.cache.length);
// this.renderPage(0, 100);
if ( if (
!this.allDownloaded && !this.allDownloaded &&
this.tablePageStartIndex > 0 && // This is a case now that we can hit this as we re-construct table when we update column this.tablePageStartIndex > 0 && // This is a case now that we can hit this as we re-construct table when we update column
@ -191,24 +278,17 @@ export default class TableEntityListViewModel extends DataTableViewModel {
if (prefetchNeeded) { if (prefetchNeeded) {
var downloadSize = tableQuery.top || this.downloadSize; var downloadSize = tableQuery.top || this.downloadSize;
this.prefetchAndRender( return await this.prefetchAndRender(tableQuery, 0, tablePageSize, downloadSize);
tableQuery, } else {
this.tablePageStartIndex, return this.cache.data;
tablePageSize,
downloadSize
// draw,
// oSettings,
// columnSortOrder
);
} }
return undefined;
} }
public addEntityToCache(entity: Entities.ITableEntity): Q.Promise<any> { public addEntityToCache(entity: Entities.ITableEntity): Q.Promise<any> {
// Delay the add operation if we are fetching data from server, so as to avoid race condition. // Delay the add operation if we are fetching data from server, so as to avoid race condition.
if (this.cache.serverCallInProgress) { if (this.cache.serverCallInProgress) {
return Utilities.delay(this.pollingInterval).then(() => { Utilities.delay(this.pollingInterval).then(() => {
return this.updateCachedEntity(entity); this.updateCachedEntity(entity);
}); });
} }
@ -224,8 +304,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
public updateCachedEntity(entity: Entities.ITableEntity): Q.Promise<any> { public updateCachedEntity(entity: Entities.ITableEntity): Q.Promise<any> {
// Delay the add operation if we are fetching data from server, so as to avoid race condition. // Delay the add operation if we are fetching data from server, so as to avoid race condition.
if (this.cache.serverCallInProgress) { if (this.cache.serverCallInProgress) {
return Utilities.delay(this.pollingInterval).then(() => { Utilities.delay(this.pollingInterval).then(() => {
return this.updateCachedEntity(entity); this.updateCachedEntity(entity);
}); });
} }
var oldEntityIndex: number = _.findIndex( var oldEntityIndex: number = _.findIndex(
@ -245,8 +325,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
// Delay the remove operation if we are fetching data from server, so as to avoid race condition. // Delay the remove operation if we are fetching data from server, so as to avoid race condition.
if (this.cache.serverCallInProgress) { if (this.cache.serverCallInProgress) {
return Utilities.delay(this.pollingInterval).then(() => { Utilities.delay(this.pollingInterval).then(() => {
return this.removeEntitiesFromCache(entities); this.removeEntitiesFromCache(entities);
}); });
} }
@ -354,36 +434,45 @@ export default class TableEntityListViewModel extends DataTableViewModel {
}); });
} }
private prefetchAndRender( private async prefetchAndRender(
tableQuery: Entities.ITableQuery, tableQuery: Entities.ITableQuery,
tablePageStartIndex: number, tablePageStartIndex: number,
tablePageSize: number, tablePageSize: number,
downloadSize: number downloadSize: number
// draw: number,/ ): Promise<Entities.ITableEntity[]> {
// oSettings: any,
// columnSortOrder: any
): void {
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 366 ~ TableEntityListViewModel ~ prefetchAndRender"); console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 366 ~ TableEntityListViewModel ~ prefetchAndRender");
this.queryErrorMessage(null); this.queryErrorMessage(null);
if (this.cache.serverCallInProgress) { if (this.cache.serverCallInProgress) {
return; return undefined;
} }
this.prefetchData(tableQuery, downloadSize, /* currentRetry */ 0) try {
.then((result: IListTableEntitiesSegmentedResult) => { const result = await this.prefetchData(tableQuery, downloadSize, /* currentRetry */ 0);
if (!result) { if (!result) {
return; return undefined;
} }
// Cache is assigned using prefetchData
var entities = this.cache.data; var entities = this.cache.data;
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 430 ~ TableEntityListViewModel ~ .then ~ entities outside",
entities
);
if (userContext.apiType === "Cassandra" && DataTableUtilities.checkForDefaultHeader(this.headers)) { if (userContext.apiType === "Cassandra" && DataTableUtilities.checkForDefaultHeader(this.headers)) {
(<CassandraAPIDataClient>this.queryTablesTab.container.tableDataClient) (<CassandraAPIDataClient>this.queryTablesTab.container.tableDataClient)
.getTableSchema(this.queryTablesTab.collection) .getTableSchema(this.queryTablesTab.collection)
.then((headers: CassandraTableKey[]) => { .then((headers: CassandraTableKey[]) => {
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 438 ~ TableEntityListViewModel ~ .then ~ headers",
headers
);
this.updateHeaders( this.updateHeaders(
headers.map((header) => header.property), headers.map((header) => header.property),
true true
); );
}); });
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 430 ~ TableEntityListViewModel ~ .then ~ entities inside",
entities
);
} else { } else {
var selectedHeadersUnion: string[] = DataTableUtilities.getPropertyIntersectionFromTableEntities( var selectedHeadersUnion: string[] = DataTableUtilities.getPropertyIntersectionFromTableEntities(
entities, entities,
@ -394,20 +483,12 @@ export default class TableEntityListViewModel extends DataTableViewModel {
// Any new columns found will be added into headers array, which will trigger a re-render of the DataTable. // 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. // So there is no need to call it here.
this.updateHeaders(newHeaders, /* notifyColumnChanges */ true); this.updateHeaders(newHeaders, /* notifyColumnChanges */ true);
} else {
if (columnSortOrder) {
this.sortColumns(columnSortOrder, oSettings);
} }
// this.renderPage(renderCallBack, draw, tablePageStartIndex, tablePageSize, oSettings);
}
this.renderPage(0, 100);
} }
this.renderPage(tablePageStartIndex, entities.length);
if (result.ExceedMaximumRetries) { return result;
var message: string = "We are having trouble getting your data. Please try again."; // localize } catch (error) {
}
})
.catch((error: any) => {
const parsedErrors = parseError(error); const parsedErrors = parseError(error);
var errors = parsedErrors.map((error) => { var errors = parsedErrors.map((error) => {
return <ViewModels.QueryError>{ return <ViewModels.QueryError>{
@ -434,7 +515,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
this.queryTablesTab.onLoadStartKey = null; this.queryTablesTab.onLoadStartKey = null;
} }
DataTableUtilities.turnOffProgressIndicator(); DataTableUtilities.turnOffProgressIndicator();
}); }
// return undefined;
} }
/** /**
@ -448,52 +530,54 @@ export default class TableEntityListViewModel extends DataTableViewModel {
* Note that this also means that we can get less entities than the requested download size in a successful call. * Note that this also means that we can get less entities than the requested download size in a successful call.
* See Microsoft Azure API Documentation at: https://msdn.microsoft.com/en-us/library/azure/dd135718.aspx * See Microsoft Azure API Documentation at: https://msdn.microsoft.com/en-us/library/azure/dd135718.aspx
*/ */
private prefetchData(
private async prefetchData(
tableQuery: Entities.ITableQuery, tableQuery: Entities.ITableQuery,
downloadSize: number, downloadSize: number,
currentRetry: number = 0 currentRetry: number = 0
): Q.Promise<any> { ): Promise<any> {
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 456 ~ TableEntityListViewModel ~ prefetchData"); console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 456 ~ TableEntityListViewModel ~ prefetchData");
var entities: any;
if (!this.cache.serverCallInProgress) { if (!this.cache.serverCallInProgress) {
this.cache.serverCallInProgress = true; this.cache.serverCallInProgress = true;
this.allDownloaded = false; this.allDownloaded = false;
this.lastPrefetchTime = new Date().getTime(); this.lastPrefetchTime = new Date().getTime();
var time = this.lastPrefetchTime; var time = this.lastPrefetchTime;
var promise: Q.Promise<IListTableEntitiesSegmentedResult>; var promise: Promise<IListTableEntitiesSegmentedResult>;
try {
if (this._documentIterator && this.continuationToken) { if (this._documentIterator && this.continuationToken) {
// TODO handle Cassandra case // TODO handle Cassandra case
const fetchNext = await this._documentIterator.fetchNext();
promise = Q(this._documentIterator.fetchNext().then((response) => response.resources)).then( let fetchNextEntities: Entities.ITableEntity[] = TableEntityProcessor.convertDocumentsToEntities(
(documents: any[]) => { fetchNext.resources
let entities: Entities.ITableEntity[] = TableEntityProcessor.convertDocumentsToEntities(documents); );
let finalEntities: IListTableEntitiesSegmentedResult = <IListTableEntitiesSegmentedResult>{ let finalEntities: IListTableEntitiesSegmentedResult = <IListTableEntitiesSegmentedResult>{
Results: entities, Results: fetchNextEntities,
ContinuationToken: this._documentIterator.hasMoreResults(), ContinuationToken: this._documentIterator.hasMoreResults(),
}; };
return Q.resolve(finalEntities); entities = finalEntities;
}
);
} else if (this.continuationToken && userContext.apiType === "Cassandra") { } else if (this.continuationToken && userContext.apiType === "Cassandra") {
promise = Q( entities = this.queryTablesTab.container.tableDataClient.queryDocuments(
this.queryTablesTab.container.tableDataClient.queryDocuments(
this.queryTablesTab.collection, this.queryTablesTab.collection,
this.cqlQuery(), this.cqlQuery(),
true, true,
this.continuationToken this.continuationToken
)
); );
} else { } else {
let query = this.sqlQuery(); let query = this.sqlQuery();
if (userContext.apiType === "Cassandra") { if (userContext.apiType === "Cassandra") {
query = this.cqlQuery(); query = this.cqlQuery();
} }
promise = Q( entities = await this.queryTablesTab.container.tableDataClient.queryDocuments(
this.queryTablesTab.container.tableDataClient.queryDocuments(this.queryTablesTab.collection, query, true) this.queryTablesTab.collection,
query,
true
); );
} }
return promise
.then((result: IListTableEntitiesSegmentedResult) => { const result = entities;
if (result) {
if (!this._documentIterator) { if (!this._documentIterator) {
this._documentIterator = result.iterator; this._documentIterator = result.iterator;
} }
@ -503,14 +587,14 @@ export default class TableEntityListViewModel extends DataTableViewModel {
// And as another service call is during process, we don't set serverCallInProgress to false here. // And as another service call is during process, we don't set serverCallInProgress to false here.
// Thus, end the prefetch. // Thus, end the prefetch.
if (this.lastPrefetchTime !== time) { if (this.lastPrefetchTime !== time) {
return Q.resolve(null); return Promise.resolve(undefined);
} }
var entities = result.Results; var entities = result.Results;
actualDownloadSize = entities.length; actualDownloadSize = entities.length;
// Queries can fetch no results and still return a continuation header. See prefetchAndRender() method. // Queries can fetch no results and still return a continuation header. See prefetchAndRender() method.
this.continuationToken = this.isCancelled ? null : result.ContinuationToken; this.continuationToken = this.isCancelled ? undefined : result.ContinuationToken;
if (!this.continuationToken) { if (!this.continuationToken) {
this.allDownloaded = true; this.allDownloaded = true;
@ -519,9 +603,23 @@ export default class TableEntityListViewModel extends DataTableViewModel {
if (this.isCacheValid(tableQuery)) { if (this.isCacheValid(tableQuery)) {
// Append to cache. // Append to cache.
this.cache.data = this.cache.data.concat(entities.slice(0)); this.cache.data = this.cache.data.concat(entities.slice(0));
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 667 ~ TableEntityListViewModel ~ .then ~ this.cache.data",
this.cache.data
);
var p = new Promise<Entities.ITableEntity[]>((resolve) => {
if (this.cache.data) {
resolve(this.cache.data);
}
});
return p;
} else { } else {
// Create cache. // Create cache.
this.cache.data = entities; this.cache.data = entities;
console.log(
"🚀 ~ file: TableEntityListViewModel.ts ~ line 671 ~ TableEntityListViewModel ~ .then ~ this.cache.data",
this.cache.data
);
} }
this.cache.tableQuery = tableQuery; this.cache.tableQuery = tableQuery;
@ -532,30 +630,20 @@ export default class TableEntityListViewModel extends DataTableViewModel {
this.allDownloaded = true; this.allDownloaded = true;
} }
// There are three possible results for a prefetch:
// 1. Continuation token is null or fetched items' size reaches predefined.
// 2. Continuation token is not null and fetched items' size hasn't reach predefined.
// 2.1 Retry times has reached predefined maximum.
// 2.2 Retry times hasn't reached predefined maximum.
// Correspondingly,
// For #1, end prefetch.
// For #2.1, set prefetch exceeds maximum retry number and end prefetch.
// For #2.2, go to next round prefetch.
if (this.allDownloaded || nextDownloadSize === 0) { if (this.allDownloaded || nextDownloadSize === 0) {
return Q.resolve(result); return Promise.resolve(result);
} }
if (currentRetry >= TableEntityListViewModel._maximumNumberOfPrefetchRetries) { if (currentRetry >= TableEntityListViewModel._maximumNumberOfPrefetchRetries) {
result.ExceedMaximumRetries = true; result.ExceedMaximumRetries = true;
return Q.resolve(result); return Promise.resolve(result);
} }
return this.prefetchData(tableQuery, nextDownloadSize, currentRetry + 1); return this.prefetchData(tableQuery, nextDownloadSize, currentRetry + 1);
}) }
.catch((error: Error) => { } catch (error) {
this.cache.serverCallInProgress = false; this.cache.serverCallInProgress = false;
return Q.reject(error); return Promise.reject(error);
}); }
} }
return null;
} }
} }

View File

@ -170,6 +170,10 @@ export default class QueryViewModel {
this._tableEntityListViewModel.oDataQuery(filter); this._tableEntityListViewModel.oDataQuery(filter);
this._tableEntityListViewModel.sqlQuery(this.setSqlFilter(queryTableRows)); this._tableEntityListViewModel.sqlQuery(this.setSqlFilter(queryTableRows));
this._tableEntityListViewModel.cqlQuery(filter); this._tableEntityListViewModel.cqlQuery(filter);
console.log(
"🚀 ~ file: QueryViewModel.tsx ~ line 165 ~ QueryViewModel ~ this._tableEntityListViewModel.sqlQuery()",
this._tableEntityListViewModel.sqlQuery()
);
return userContext.apiType !== "Cassandra" return userContext.apiType !== "Cassandra"
? this._tableEntityListViewModel.sqlQuery() ? this._tableEntityListViewModel.sqlQuery()

View File

@ -1,285 +0,0 @@
import * as ko from "knockout";
import React from "react";
import AddEntityIcon from "../../../images/AddEntity.svg";
import DeleteEntitiesIcon from "../../../images/DeleteEntities.svg";
import EditEntityIcon from "../../../images/Edit-entity.svg";
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
import QueryBuilderIcon from "../../../images/Query-Builder.svg";
import QueryTextIcon from "../../../images/Query-Text.svg";
import * as ViewModels from "../../Contracts/ViewModels";
import { useSidePanel } from "../../hooks/useSidePanel";
import { userContext } from "../../UserContext";
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
import Explorer from "../Explorer";
import { AddTableEntityPanel } from "../Panes/Tables/AddTableEntityPanel";
import { EditTableEntityPanel } from "../Panes/Tables/EditTableEntityPanel";
import TableCommands from "../Tables/DataTable/TableCommands";
import TableEntityListViewModel from "../Tables/DataTable/TableEntityListViewModel";
import QueryViewModel from "../Tables/QueryBuilder/QueryViewModel";
import { CassandraAPIDataClient, TableDataClient } from "../Tables/TableDataClient";
import template from "./QueryTablesTab.html";
import TabsBase from "./TabsBase";
// Will act as table explorer class
export default class QueryTablesTab extends TabsBase {
public readonly html = template;
public collection: ViewModels.Collection;
public tableEntityListViewModel = ko.observable<TableEntityListViewModel>();
public queryViewModel = ko.observable<QueryViewModel>();
public tableCommands: TableCommands;
public tableDataClient: TableDataClient;
public queryText = ko.observable("PartitionKey eq 'partitionKey1'"); // Start out with an example they can modify
public selectedQueryText = ko.observable("").extend({ notify: "always" });
public executeQueryButton: ViewModels.Button;
public addEntityButton: ViewModels.Button;
public editEntityButton: ViewModels.Button;
public deleteEntityButton: ViewModels.Button;
public queryBuilderButton: ViewModels.Button;
public queryTextButton: ViewModels.Button;
public container: Explorer;
constructor(options: ViewModels.TabOptions) {
super(options);
this.container = options.collection && options.collection.container;
this.tableCommands = new TableCommands(this.container);
this.tableDataClient = this.container.tableDataClient;
this.tableEntityListViewModel(new TableEntityListViewModel(this.tableCommands, this));
this.tableEntityListViewModel().queryTablesTab = this;
this.queryViewModel(new QueryViewModel(this));
const sampleQuerySubscription = this.tableEntityListViewModel().items.subscribe(() => {
if (this.tableEntityListViewModel().items().length > 0 && userContext.apiType === "Tables") {
this.queryViewModel().queryBuilderViewModel().setExample();
}
sampleQuerySubscription.dispose();
});
this.executeQueryButton = {
enabled: ko.computed<boolean>(() => {
return true;
}),
visible: ko.computed<boolean>(() => {
return true;
}),
};
this.queryBuilderButton = {
enabled: ko.computed<boolean>(() => {
return true;
}),
visible: ko.computed<boolean>(() => {
return true;
}),
isSelected: ko.computed<boolean>(() => {
return this.queryViewModel() ? this.queryViewModel().isHelperActive() : false;
}),
};
this.queryTextButton = {
enabled: ko.computed<boolean>(() => {
return true;
}),
visible: ko.computed<boolean>(() => {
return true;
}),
isSelected: ko.computed<boolean>(() => {
return this.queryViewModel() ? this.queryViewModel().isEditorActive() : false;
}),
};
this.addEntityButton = {
enabled: ko.computed<boolean>(() => {
return true;
}),
visible: ko.computed<boolean>(() => {
return true;
}),
};
this.editEntityButton = {
enabled: ko.computed<boolean>(() => {
return this.tableCommands.isEnabled(
TableCommands.editEntityCommand,
this.tableEntityListViewModel().selected()
);
}),
visible: ko.computed<boolean>(() => {
return true;
}),
};
this.deleteEntityButton = {
enabled: ko.computed<boolean>(() => {
return this.tableCommands.isEnabled(
TableCommands.deleteEntitiesCommand,
this.tableEntityListViewModel().selected()
);
}),
visible: ko.computed<boolean>(() => {
return true;
}),
};
this.buildCommandBarOptions();
}
public onAddEntityClick = (): void => {
useSidePanel
.getState()
.openSidePanel(
"Add Table Row",
<AddTableEntityPanel
tableDataClient={this.tableDataClient}
queryTablesTab={this}
tableEntityListViewModel={this.tableEntityListViewModel()}
cassandraApiClient={new CassandraAPIDataClient()}
/>,
"700px"
);
};
public onEditEntityClick = (): void => {
useSidePanel
.getState()
.openSidePanel(
"Edit Table Entity",
<EditTableEntityPanel
tableDataClient={this.tableDataClient}
queryTablesTab={this}
tableEntityListViewModel={this.tableEntityListViewModel()}
cassandraApiClient={new CassandraAPIDataClient()}
/>,
"700px"
);
};
public onDeleteEntityClick = (): void => {
this.tableCommands.deleteEntitiesCommand(this.tableEntityListViewModel());
};
public onActivate(): void {
super.onActivate();
const columns =
!!this.tableEntityListViewModel() &&
!!this.tableEntityListViewModel().table &&
this.tableEntityListViewModel().table.columns;
if (columns) {
columns.adjust();
$(window).resize();
}
}
protected getTabsButtons(): CommandButtonComponentProps[] {
const buttons: CommandButtonComponentProps[] = [];
if (this.queryBuilderButton.visible()) {
const label = userContext.apiType === "Cassandra" ? "CQL Query Builder" : "Query Builder";
buttons.push({
iconSrc: QueryBuilderIcon,
iconAlt: label,
onCommandClick: () => this.queryViewModel().selectHelper(),
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled: !this.queryBuilderButton.enabled(),
isSelected: this.queryBuilderButton.isSelected(),
});
}
if (this.queryTextButton.visible()) {
const label = userContext.apiType === "Cassandra" ? "CQL Query Text" : "Query Text";
buttons.push({
iconSrc: QueryTextIcon,
iconAlt: label,
onCommandClick: () => this.queryViewModel().selectEditor(),
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled: !this.queryTextButton.enabled(),
isSelected: this.queryTextButton.isSelected(),
});
}
if (this.executeQueryButton.visible()) {
const label = "Run Query";
buttons.push({
iconSrc: ExecuteQueryIcon,
iconAlt: label,
onCommandClick: () => this.queryViewModel().runQuery(),
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled: !this.executeQueryButton.enabled(),
});
}
if (this.addEntityButton.visible()) {
const label = userContext.apiType === "Cassandra" ? "Add Row" : "Add Entity";
buttons.push({
iconSrc: AddEntityIcon,
iconAlt: label,
onCommandClick: this.onAddEntityClick,
commandButtonLabel: label,
ariaLabel: label,
hasPopup: true,
disabled: !this.addEntityButton.enabled(),
});
}
if (this.editEntityButton.visible()) {
const label = userContext.apiType === "Cassandra" ? "Edit Row" : "Edit Entity";
buttons.push({
iconSrc: EditEntityIcon,
iconAlt: label,
onCommandClick: this.onEditEntityClick,
commandButtonLabel: label,
ariaLabel: label,
hasPopup: true,
disabled: !this.editEntityButton.enabled(),
});
}
if (this.deleteEntityButton.visible()) {
const label = userContext.apiType === "Cassandra" ? "Delete Rows" : "Delete Entities";
buttons.push({
iconSrc: DeleteEntitiesIcon,
iconAlt: label,
onCommandClick: this.onDeleteEntityClick,
commandButtonLabel: label,
ariaLabel: label,
hasPopup: true,
disabled: !this.deleteEntityButton.enabled(),
});
}
return buttons;
}
protected buildCommandBarOptions(): void {
ko.computed(() =>
ko.toJSON([
this.queryBuilderButton.visible,
this.queryBuilderButton.enabled,
this.queryTextButton.visible,
this.queryTextButton.enabled,
this.executeQueryButton.visible,
this.executeQueryButton.enabled,
this.addEntityButton.visible,
this.addEntityButton.enabled,
this.editEntityButton.visible,
this.editEntityButton.enabled,
this.deleteEntityButton.visible,
this.deleteEntityButton.enabled,
])
).subscribe(() => this.updateNavbarWithTabsButtons());
this.updateNavbarWithTabsButtons();
}
}

View File

@ -63,7 +63,7 @@ export interface Button {
isSelected?: boolean; isSelected?: boolean;
} }
const PAGESIZE = 10; const PAGESIZE = 100;
class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, IQueryTablesTabComponentStates> { class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, IQueryTablesTabComponentStates> {
public collection: ViewModels.Collection; public collection: ViewModels.Collection;
@ -100,12 +100,6 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.tableDataClient = this.container.tableDataClient; this.tableDataClient = this.container.tableDataClient;
this.tableEntityListViewModel2(new TableEntityListViewModel(this.tableCommands, props.queryTablesTab)); this.tableEntityListViewModel2(new TableEntityListViewModel(this.tableCommands, props.queryTablesTab));
const tableEntityListViewModel = new TableEntityListViewModel(this.tableCommands, props.queryTablesTab); const tableEntityListViewModel = new TableEntityListViewModel(this.tableCommands, props.queryTablesTab);
// const queryBuilderViewModel = new QueryViewModel(this.props.queryTablesTab).queryBuilderViewModel();
// const entityTypeOptions = queryBuilderViewModel.edmTypes();
// const timestampOptions = queryBuilderViewModel.timeOptions();
// const operatorsOptions = queryBuilderViewModel.operators();
// const operationOptions = queryBuilderViewModel.clauseRules();
this.state = { this.state = {
tableEntityListViewModel, tableEntityListViewModel,
@ -201,7 +195,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
} }
componentDidMount(): void { componentDidMount(): void {
this.loadEntities(true); this.loadEntities(true, false);
} }
public createSelection = (): Selection => { public createSelection = (): Selection => {
@ -294,12 +288,57 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
}); });
} }
public async loadEntities(isInitialLoad: boolean): Promise<void> { public async loadEntities(isInitialLoad: boolean, isRunQuery?: boolean): Promise<void> {
const { tableEntityListViewModel, selectedQueryText } = this.state; const { tableEntityListViewModel, selectedQueryText } = this.state;
// tableEntityListViewModel.renderNextPageAndupdateCache();
let headers: string[] = []; let headers: string[] = [];
//eslint-disable-next-line //eslint-disable-next-line
let documents: any = {}; let documents: any = {};
// const data = await tableEntityListViewModel.a();
// console.log(
// "🚀 ~ file: QueryTablesTabComponent.tsx ~ line 311 ~ QueryTablesTabComponent ~ loadEntities ~ data",
// data
// );
// setTimeout(() => {
// console.log("Items > ", this.state.tableEntityListViewModel.items());
// }, 10000);
// await tableEntityListViewModel.renderNextPageAndupdateCache(selectedQueryText);
// setTimeout(() => {
// // console.log("Processing...");
// this.isEntitiesAvailable(isInitialLoad);
// }, 0);
if (!isRunQuery) {
try {
documents = await tableEntityListViewModel.renderNextPageAndupdateCache();
// setTimeout(() => {
// // console.log("Processing...");
// this.isEntitiesAvailable(isInitialLoad);
// }, 0);
// const data = await tableEntityListViewModel.a();
if (userContext.apiType === "Cassandra") {
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 311 ~ QueryTablesTabComponent ~ loadEntities ~ data",
documents.Results
);
headers = this.getFormattedHeaders(documents.Results);
this.setupIntialEntities(headers, documents.Results, isInitialLoad);
} else {
console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 311 ~ QueryTablesTabComponent ~ loadEntities ~ data",
documents
);
headers = this.getFormattedHeaders(documents);
this.setupIntialEntities(headers, documents, isInitialLoad);
}
// this.isEntitiesAvailable(isInitialLoad, data);
} catch (error) {
this.setState({
queryErrorMessage: error.responseText,
hasQueryError: true,
isLoading: false,
});
}
} else {
try { try {
if (userContext.apiType === "Cassandra") { if (userContext.apiType === "Cassandra") {
documents = await this.props.queryTablesTab.container.tableDataClient.queryDocuments( documents = await this.props.queryTablesTab.container.tableDataClient.queryDocuments(
@ -308,19 +347,18 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
true true
); );
headers = this.getFormattedHeaders(documents.Results); headers = this.getFormattedHeaders(documents.Results);
this.setupIntialEntities(documents.Results, headers, isInitialLoad); this.setupIntialEntities(headers, documents.Results, isInitialLoad);
} else { } else {
const { collection } = this.props; const { collection } = this.props;
documents = await this.getDocuments(collection, selectedQueryText); documents = await this.getDocuments(collection, selectedQueryText);
headers = this.getFormattedHeaders(documents.Results); headers = this.getFormattedHeaders(documents.Results);
this.setupIntialEntities(documents.Results, headers, isInitialLoad); this.setupIntialEntities(headers, documents.Results, isInitialLoad);
} }
this.setState({ this.setState({
queryErrorMessage: "", queryErrorMessage: "",
hasQueryError: false, hasQueryError: false,
}); });
} catch (error) { } catch (error) {
if (error.responseText) {
this.setState({ this.setState({
queryErrorMessage: error.responseText, queryErrorMessage: error.responseText,
hasQueryError: true, hasQueryError: true,
@ -331,17 +369,35 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
} }
private setupIntialEntities = ( private setupIntialEntities = (
entities: Entities.ITableEntity[],
headers: string[], headers: string[],
isInitialLoad: boolean entities?: Entities.ITableEntity[],
isInitialLoad?: boolean
): void => { ): void => {
let minWidth: number;
let maxWidth: number;
let documentItems: IDocument[] = [];
let filteredItems: IDocument[] = [];
this.columns = []; this.columns = [];
headers.map((header) => { headers.map((header) => {
switch (header) {
case "PartitionKey":
case "RowKey":
minWidth = 50;
maxWidth = 100;
break;
case "Timestamp":
minWidth = 200;
maxWidth = 200;
break;
default:
minWidth = 30;
maxWidth = 50;
}
this.columns.push({ this.columns.push({
key: header, key: header,
name: header, name: header,
minWidth: 100, minWidth: minWidth,
maxWidth: 200, maxWidth: maxWidth,
data: "string", data: "string",
fieldName: header, fieldName: header,
isResizable: true, isResizable: true,
@ -350,12 +406,14 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
sortAscendingAriaLabel: "Sorted A to Z", sortAscendingAriaLabel: "Sorted A to Z",
sortDescendingAriaLabel: "Sorted Z to A", sortDescendingAriaLabel: "Sorted Z to A",
onColumnClick: this.onColumnClick, onColumnClick: this.onColumnClick,
// onRender: (item: Entities.ITableEntity) => {
// return <div className={!item[header] ? "noData" : ""}>{item[header] ? item[header] : " "}</div>;
// },
}); });
}); });
const documentItems = this.generateDetailsList(entities); documentItems = this.generateDetailsList(entities);
filteredItems = documentItems.slice(0, PAGESIZE);
const filteredItems = documentItems.slice(0, PAGESIZE);
this.setState( this.setState(
{ {
@ -369,6 +427,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
queryText: this.state.queryViewModel.queryText(), queryText: this.state.queryViewModel.queryText(),
fromDocument: 0, fromDocument: 0,
toDocument: PAGESIZE, toDocument: PAGESIZE,
currentStartIndex: PAGESIZE,
}, },
() => { () => {
if (isInitialLoad && headers.length > 0) { if (isInitialLoad && headers.length > 0) {
@ -379,6 +438,36 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
); );
}; };
// public isEntitiesAvailable(isInitialLoad: boolean, data?: Entities.ITableEntity[]): void {
// let headers: string[] = [];
// headers = this.getFormattedHeaders(data);
// this.setupIntialEntities(false, headers);
// const documentItems = this.generateDetailsList(data);
// const filteredItems = documentItems.slice(0, PAGESIZE);
// this.setState(
// {
// columns: this.columns,
// headers,
// operators: this.state.queryViewModel.queryBuilderViewModel().operators(),
// isLoading: false,
// items: filteredItems,
// entities: data,
// originalItems: documentItems,
// queryText: this.state.queryViewModel.queryText(),
// fromDocument: 0,
// toDocument: PAGESIZE,
// },
// () => {
// if (isInitialLoad && headers.length > 0) {
// this.loadFilterExample();
// this.onItemsSelectionChanged(true);
// }
// }
// );
// }
private onColumnClick = (ev: React.MouseEvent<HTMLElement>, column: IColumn): void => { private onColumnClick = (ev: React.MouseEvent<HTMLElement>, column: IColumn): void => {
const { columns, items } = this.state; const { columns, items } = this.state;
const newColumns: IColumn[] = columns.slice(); const newColumns: IColumn[] = columns.slice();
@ -444,6 +533,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
//eslint-disable-next-line //eslint-disable-next-line
let obj: any; let obj: any;
documents.map((item) => { documents.map((item) => {
obj = {};
this.columns.map((col) => { this.columns.map((col) => {
if (item[col.name]) { if (item[col.name]) {
obj = { ...obj, ...{ [col.name]: item[col.name]._ } }; obj = { ...obj, ...{ [col.name]: item[col.name]._ } };
@ -458,7 +548,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
this.setState({ this.setState({
isLoading: true, isLoading: true,
}); });
this.loadEntities(false); this.loadEntities(false, false);
} }
public onAddEntityClick = (): void => { public onAddEntityClick = (): void => {
@ -472,7 +562,8 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
tableEntityListViewModel={this.state.tableEntityListViewModel} tableEntityListViewModel={this.state.tableEntityListViewModel}
cassandraApiClient={new CassandraAPIDataClient()} cassandraApiClient={new CassandraAPIDataClient()}
reloadEntities={() => this.reloadEntities()} reloadEntities={() => this.reloadEntities()}
/> />,
"700px"
); );
}; };
@ -492,7 +583,8 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
cassandraApiClient={new CassandraAPIDataClient()} cassandraApiClient={new CassandraAPIDataClient()}
selectedEntity={this.state.selectedItems} selectedEntity={this.state.selectedItems}
reloadEntities={() => this.reloadEntities()} reloadEntities={() => this.reloadEntities()}
/> />,
"700px"
); );
}; };
@ -511,10 +603,12 @@ 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, false);
});
}); });
} }
}; };
@ -525,7 +619,11 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
selectedQueryText: this.state.queryViewModel.runQuery(queryTableRows), selectedQueryText: this.state.queryViewModel.runQuery(queryTableRows),
}); });
setTimeout(() => { setTimeout(() => {
this.loadEntities(false); console.log(
"🚀 ~ file: QueryTablesTabComponent.tsx ~ line 651 ~ QueryTablesTabComponent ~ runQuery ~ selectedQueryText",
this.state.selectedQueryText
);
this.loadEntities(false, queryTableRows.length > 0 ? true : false);
}, 2000); }, 2000);
this.setState({ this.setState({
queryText: this.state.queryViewModel.queryText(), queryText: this.state.queryViewModel.queryText(),
@ -1005,7 +1103,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
</div> </div>
</div> </div>
<div className="tablesQueryTab tableContainer"> <div className="tablesQueryTab tableContainer" data-is-scrollable="true">
{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
@ -1018,6 +1116,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
selection={this.state.selection} selection={this.state.selection}
selectionPreservedOnEmptyClick={true} selectionPreservedOnEmptyClick={true}
checkboxVisibility={CheckboxVisibility.always} checkboxVisibility={CheckboxVisibility.always}
onShouldVirtualize={() => false}
/> />
)} )}
{this.state.items.length === 0 && !this.state.isLoading && ( {this.state.items.length === 0 && !this.state.isLoading && (