mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-04-26 03:24:08 +01:00
Async and await implemented for loadEntities
This commit is contained in:
parent
046e6eb5a4
commit
b7cb0b55a6
@ -535,11 +535,11 @@ input::-webkit-inner-spin-button {
|
||||
}
|
||||
|
||||
.query-document-detail-list {
|
||||
overflow-x: hidden;
|
||||
// overflow-x: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
.query-table-clause-container {
|
||||
max-height: 80px;
|
||||
max-height: 150px;
|
||||
overflow: scroll;
|
||||
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 {
|
||||
// }
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { IDropdownOption, Image, Label, Stack, Text, TextField } from "@fluentui/react";
|
||||
import { useBoolean } from "@fluentui/react-hooks";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as _ from "underscore";
|
||||
import AddPropertyIcon from "../../../../images/Add-property.svg";
|
||||
import RevertBackIcon from "../../../../images/RevertBack.svg";
|
||||
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
|
||||
import { TableEntity } from "../../../Common/TableEntity";
|
||||
import { useSidePanel } from "../../../hooks/useSidePanel";
|
||||
import { userContext } from "../../../UserContext";
|
||||
@ -11,6 +13,7 @@ import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities";
|
||||
import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel";
|
||||
import * as Entities from "../../Tables/Entities";
|
||||
import { CassandraAPIDataClient, CassandraTableKey, TableDataClient } from "../../Tables/TableDataClient";
|
||||
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
|
||||
import * as Utilities from "../../Tables/Utilities";
|
||||
import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
@ -115,10 +118,62 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
|
||||
|
||||
setIsExecuting(true);
|
||||
const entity: Entities.ITableEntity = entityFromAttributes(entities);
|
||||
await tableDataClient.createDocument(queryTablesTab.collection, entity);
|
||||
// await tableEntityListViewModel.addEntityToCache(newEntity);
|
||||
reloadEntities();
|
||||
closeSidePanel();
|
||||
const newEntity: Entities.ITableEntity = await tableDataClient.createDocument(queryTablesTab.collection, entity);
|
||||
try {
|
||||
await tableEntityListViewModel.addEntityToCache(newEntity);
|
||||
// if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
|
||||
// tableEntityListViewModel.redrawTableThrottled();
|
||||
reloadEntities();
|
||||
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 */
|
||||
|
@ -4,10 +4,12 @@ import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as _ from "underscore";
|
||||
import AddPropertyIcon from "../../../../images/Add-property.svg";
|
||||
import RevertBackIcon from "../../../../images/RevertBack.svg";
|
||||
import { getErrorMessage, handleError } from "../../../Common/ErrorHandlingUtils";
|
||||
import { TableEntity } from "../../../Common/TableEntity";
|
||||
import { useSidePanel } from "../../../hooks/useSidePanel";
|
||||
import { userContext } from "../../../UserContext";
|
||||
import * as TableConstants from "../../Tables/Constants";
|
||||
import * as DataTableUtilities from "../../Tables/DataTable/DataTableUtilities";
|
||||
import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel";
|
||||
import * as Entities from "../../Tables/Entities";
|
||||
import { CassandraAPIDataClient, TableDataClient } from "../../Tables/TableDataClient";
|
||||
@ -213,9 +215,59 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
|
||||
const entity: Entities.ITableEntity = entityFromAttributes(entities);
|
||||
const newTableDataClient = userContext.apiType === "Cassandra" ? cassandraApiClient : tableDataClient;
|
||||
const originalDocumentData = userContext.apiType === "Cassandra" ? originalDocument[0] : originalDocument;
|
||||
await newTableDataClient.updateDocument(queryTablesTab.collection, originalDocumentData, entity);
|
||||
reloadEntities();
|
||||
closeSidePanel();
|
||||
// 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();
|
||||
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
|
||||
|
@ -170,6 +170,10 @@ abstract class DataTableViewModel {
|
||||
}
|
||||
|
||||
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 renderData = this.cache.data.slice(startIndex, endIndex);
|
||||
|
||||
|
@ -148,6 +148,97 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
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.
|
||||
* 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.
|
||||
* 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 columnSortOrder: any;
|
||||
// Threshold(pages) for triggering cache prefetch.
|
||||
// If number remaining pages in cache falls below prefetchThreshold prefetch will be triggered.
|
||||
var prefetchThreshold = 10;
|
||||
@ -169,12 +260,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
// Check if prefetch needed.
|
||||
if (this.tablePageStartIndex + tablePageSize <= this.cache.length || this.allDownloaded) {
|
||||
prefetchNeeded = false;
|
||||
// if (columnSortOrder && (!this.cache.sortOrder || !_.isEqual(this.cache.sortOrder, columnSortOrder))) {
|
||||
// this.sortColumns(columnSortOrder, oSettings);
|
||||
// }
|
||||
this.tablePageStartIndex = 0;
|
||||
this.renderPage(this.tablePageStartIndex, tablePageSize);
|
||||
// this.renderPage(0, 100);
|
||||
this.renderPage(this.tablePageStartIndex, this.cache.length);
|
||||
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
|
||||
@ -191,24 +278,17 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
|
||||
if (prefetchNeeded) {
|
||||
var downloadSize = tableQuery.top || this.downloadSize;
|
||||
this.prefetchAndRender(
|
||||
tableQuery,
|
||||
this.tablePageStartIndex,
|
||||
tablePageSize,
|
||||
downloadSize
|
||||
// draw,
|
||||
// oSettings,
|
||||
// columnSortOrder
|
||||
);
|
||||
return await this.prefetchAndRender(tableQuery, 0, tablePageSize, downloadSize);
|
||||
} else {
|
||||
return this.cache.data;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
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.
|
||||
if (this.cache.serverCallInProgress) {
|
||||
return Utilities.delay(this.pollingInterval).then(() => {
|
||||
return this.updateCachedEntity(entity);
|
||||
Utilities.delay(this.pollingInterval).then(() => {
|
||||
this.updateCachedEntity(entity);
|
||||
});
|
||||
}
|
||||
|
||||
@ -224,8 +304,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
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.
|
||||
if (this.cache.serverCallInProgress) {
|
||||
return Utilities.delay(this.pollingInterval).then(() => {
|
||||
return this.updateCachedEntity(entity);
|
||||
Utilities.delay(this.pollingInterval).then(() => {
|
||||
this.updateCachedEntity(entity);
|
||||
});
|
||||
}
|
||||
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.
|
||||
if (this.cache.serverCallInProgress) {
|
||||
return Utilities.delay(this.pollingInterval).then(() => {
|
||||
return this.removeEntitiesFromCache(entities);
|
||||
Utilities.delay(this.pollingInterval).then(() => {
|
||||
this.removeEntitiesFromCache(entities);
|
||||
});
|
||||
}
|
||||
|
||||
@ -354,87 +434,89 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
});
|
||||
}
|
||||
|
||||
private prefetchAndRender(
|
||||
private async prefetchAndRender(
|
||||
tableQuery: Entities.ITableQuery,
|
||||
tablePageStartIndex: number,
|
||||
tablePageSize: number,
|
||||
downloadSize: number
|
||||
// draw: number,/
|
||||
// oSettings: any,
|
||||
// columnSortOrder: any
|
||||
): void {
|
||||
): Promise<Entities.ITableEntity[]> {
|
||||
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 366 ~ TableEntityListViewModel ~ prefetchAndRender");
|
||||
this.queryErrorMessage(null);
|
||||
if (this.cache.serverCallInProgress) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
this.prefetchData(tableQuery, downloadSize, /* currentRetry */ 0)
|
||||
.then((result: IListTableEntitiesSegmentedResult) => {
|
||||
if (!result) {
|
||||
return;
|
||||
try {
|
||||
const result = await this.prefetchData(tableQuery, downloadSize, /* currentRetry */ 0);
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
// Cache is assigned using prefetchData
|
||||
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)) {
|
||||
(<CassandraAPIDataClient>this.queryTablesTab.container.tableDataClient)
|
||||
.getTableSchema(this.queryTablesTab.collection)
|
||||
.then((headers: CassandraTableKey[]) => {
|
||||
console.log(
|
||||
"🚀 ~ file: TableEntityListViewModel.ts ~ line 438 ~ TableEntityListViewModel ~ .then ~ headers",
|
||||
headers
|
||||
);
|
||||
this.updateHeaders(
|
||||
headers.map((header) => header.property),
|
||||
true
|
||||
);
|
||||
});
|
||||
console.log(
|
||||
"🚀 ~ file: TableEntityListViewModel.ts ~ line 430 ~ TableEntityListViewModel ~ .then ~ entities inside",
|
||||
entities
|
||||
);
|
||||
} else {
|
||||
var selectedHeadersUnion: string[] = DataTableUtilities.getPropertyIntersectionFromTableEntities(
|
||||
entities,
|
||||
userContext.apiType === "Cassandra"
|
||||
);
|
||||
var newHeaders: string[] = _.difference(selectedHeadersUnion, this.headers);
|
||||
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.
|
||||
this.updateHeaders(newHeaders, /* notifyColumnChanges */ true);
|
||||
}
|
||||
}
|
||||
this.renderPage(tablePageStartIndex, entities.length);
|
||||
|
||||
var entities = this.cache.data;
|
||||
if (userContext.apiType === "Cassandra" && DataTableUtilities.checkForDefaultHeader(this.headers)) {
|
||||
(<CassandraAPIDataClient>this.queryTablesTab.container.tableDataClient)
|
||||
.getTableSchema(this.queryTablesTab.collection)
|
||||
.then((headers: CassandraTableKey[]) => {
|
||||
this.updateHeaders(
|
||||
headers.map((header) => header.property),
|
||||
true
|
||||
);
|
||||
});
|
||||
} else {
|
||||
var selectedHeadersUnion: string[] = DataTableUtilities.getPropertyIntersectionFromTableEntities(
|
||||
entities,
|
||||
userContext.apiType === "Cassandra"
|
||||
);
|
||||
var newHeaders: string[] = _.difference(selectedHeadersUnion, this.headers);
|
||||
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.
|
||||
this.updateHeaders(newHeaders, /* notifyColumnChanges */ true);
|
||||
} else {
|
||||
if (columnSortOrder) {
|
||||
this.sortColumns(columnSortOrder, oSettings);
|
||||
}
|
||||
// this.renderPage(renderCallBack, draw, tablePageStartIndex, tablePageSize, oSettings);
|
||||
}
|
||||
this.renderPage(0, 100);
|
||||
}
|
||||
|
||||
if (result.ExceedMaximumRetries) {
|
||||
var message: string = "We are having trouble getting your data. Please try again."; // localize
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
const parsedErrors = parseError(error);
|
||||
var errors = parsedErrors.map((error) => {
|
||||
return <ViewModels.QueryError>{
|
||||
message: error.message,
|
||||
start: error.location ? error.location.start : undefined,
|
||||
end: error.location ? error.location.end : undefined,
|
||||
code: error.code,
|
||||
severity: error.severity,
|
||||
};
|
||||
});
|
||||
this.queryErrorMessage(errors[0].message);
|
||||
if (this.queryTablesTab.onLoadStartKey != null && this.queryTablesTab.onLoadStartKey != undefined) {
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.Tab,
|
||||
{
|
||||
databaseName: this.queryTablesTab.collection.databaseId,
|
||||
collectionName: this.queryTablesTab.collection.id(),
|
||||
dataExplorerArea: Areas.Tab,
|
||||
tabTitle: this.queryTablesTab.tabTitle(),
|
||||
error: error,
|
||||
},
|
||||
this.queryTablesTab.onLoadStartKey
|
||||
);
|
||||
this.queryTablesTab.onLoadStartKey = null;
|
||||
}
|
||||
DataTableUtilities.turnOffProgressIndicator();
|
||||
return result;
|
||||
} catch (error) {
|
||||
const parsedErrors = parseError(error);
|
||||
var errors = parsedErrors.map((error) => {
|
||||
return <ViewModels.QueryError>{
|
||||
message: error.message,
|
||||
start: error.location ? error.location.start : undefined,
|
||||
end: error.location ? error.location.end : undefined,
|
||||
code: error.code,
|
||||
severity: error.severity,
|
||||
};
|
||||
});
|
||||
this.queryErrorMessage(errors[0].message);
|
||||
if (this.queryTablesTab.onLoadStartKey != null && this.queryTablesTab.onLoadStartKey != undefined) {
|
||||
TelemetryProcessor.traceFailure(
|
||||
Action.Tab,
|
||||
{
|
||||
databaseName: this.queryTablesTab.collection.databaseId,
|
||||
collectionName: this.queryTablesTab.collection.id(),
|
||||
dataExplorerArea: Areas.Tab,
|
||||
tabTitle: this.queryTablesTab.tabTitle(),
|
||||
error: error,
|
||||
},
|
||||
this.queryTablesTab.onLoadStartKey
|
||||
);
|
||||
this.queryTablesTab.onLoadStartKey = null;
|
||||
}
|
||||
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.
|
||||
* See Microsoft Azure API Documentation at: https://msdn.microsoft.com/en-us/library/azure/dd135718.aspx
|
||||
*/
|
||||
private prefetchData(
|
||||
|
||||
private async prefetchData(
|
||||
tableQuery: Entities.ITableQuery,
|
||||
downloadSize: number,
|
||||
currentRetry: number = 0
|
||||
): Q.Promise<any> {
|
||||
): Promise<any> {
|
||||
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 456 ~ TableEntityListViewModel ~ prefetchData");
|
||||
var entities: any;
|
||||
if (!this.cache.serverCallInProgress) {
|
||||
this.cache.serverCallInProgress = true;
|
||||
this.allDownloaded = false;
|
||||
this.lastPrefetchTime = new Date().getTime();
|
||||
var time = this.lastPrefetchTime;
|
||||
|
||||
var promise: Q.Promise<IListTableEntitiesSegmentedResult>;
|
||||
if (this._documentIterator && this.continuationToken) {
|
||||
// TODO handle Cassandra case
|
||||
|
||||
promise = Q(this._documentIterator.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 Q.resolve(finalEntities);
|
||||
}
|
||||
);
|
||||
} else if (this.continuationToken && userContext.apiType === "Cassandra") {
|
||||
promise = Q(
|
||||
this.queryTablesTab.container.tableDataClient.queryDocuments(
|
||||
var promise: Promise<IListTableEntitiesSegmentedResult>;
|
||||
try {
|
||||
if (this._documentIterator && this.continuationToken) {
|
||||
// TODO handle Cassandra case
|
||||
const fetchNext = await this._documentIterator.fetchNext();
|
||||
let fetchNextEntities: Entities.ITableEntity[] = TableEntityProcessor.convertDocumentsToEntities(
|
||||
fetchNext.resources
|
||||
);
|
||||
let finalEntities: IListTableEntitiesSegmentedResult = <IListTableEntitiesSegmentedResult>{
|
||||
Results: fetchNextEntities,
|
||||
ContinuationToken: this._documentIterator.hasMoreResults(),
|
||||
};
|
||||
entities = finalEntities;
|
||||
} else if (this.continuationToken && userContext.apiType === "Cassandra") {
|
||||
entities = this.queryTablesTab.container.tableDataClient.queryDocuments(
|
||||
this.queryTablesTab.collection,
|
||||
this.cqlQuery(),
|
||||
true,
|
||||
this.continuationToken
|
||||
)
|
||||
);
|
||||
} else {
|
||||
let query = this.sqlQuery();
|
||||
if (userContext.apiType === "Cassandra") {
|
||||
query = this.cqlQuery();
|
||||
);
|
||||
} else {
|
||||
let query = this.sqlQuery();
|
||||
if (userContext.apiType === "Cassandra") {
|
||||
query = this.cqlQuery();
|
||||
}
|
||||
entities = await this.queryTablesTab.container.tableDataClient.queryDocuments(
|
||||
this.queryTablesTab.collection,
|
||||
query,
|
||||
true
|
||||
);
|
||||
}
|
||||
promise = Q(
|
||||
this.queryTablesTab.container.tableDataClient.queryDocuments(this.queryTablesTab.collection, query, true)
|
||||
);
|
||||
}
|
||||
return promise
|
||||
.then((result: IListTableEntitiesSegmentedResult) => {
|
||||
|
||||
const result = entities;
|
||||
if (result) {
|
||||
if (!this._documentIterator) {
|
||||
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.
|
||||
// Thus, end the prefetch.
|
||||
if (this.lastPrefetchTime !== time) {
|
||||
return Q.resolve(null);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
var entities = result.Results;
|
||||
actualDownloadSize = entities.length;
|
||||
|
||||
// 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) {
|
||||
this.allDownloaded = true;
|
||||
@ -519,9 +603,23 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
if (this.isCacheValid(tableQuery)) {
|
||||
// Append to cache.
|
||||
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 {
|
||||
// Create cache.
|
||||
this.cache.data = entities;
|
||||
console.log(
|
||||
"🚀 ~ file: TableEntityListViewModel.ts ~ line 671 ~ TableEntityListViewModel ~ .then ~ this.cache.data",
|
||||
this.cache.data
|
||||
);
|
||||
}
|
||||
|
||||
this.cache.tableQuery = tableQuery;
|
||||
@ -532,30 +630,20 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
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) {
|
||||
return Q.resolve(result);
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
if (currentRetry >= TableEntityListViewModel._maximumNumberOfPrefetchRetries) {
|
||||
result.ExceedMaximumRetries = true;
|
||||
return Q.resolve(result);
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
return this.prefetchData(tableQuery, nextDownloadSize, currentRetry + 1);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
this.cache.serverCallInProgress = false;
|
||||
return Q.reject(error);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.cache.serverCallInProgress = false;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,10 @@ export default class QueryViewModel {
|
||||
this._tableEntityListViewModel.oDataQuery(filter);
|
||||
this._tableEntityListViewModel.sqlQuery(this.setSqlFilter(queryTableRows));
|
||||
this._tableEntityListViewModel.cqlQuery(filter);
|
||||
console.log(
|
||||
"🚀 ~ file: QueryViewModel.tsx ~ line 165 ~ QueryViewModel ~ this._tableEntityListViewModel.sqlQuery()",
|
||||
this._tableEntityListViewModel.sqlQuery()
|
||||
);
|
||||
|
||||
return userContext.apiType !== "Cassandra"
|
||||
? this._tableEntityListViewModel.sqlQuery()
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -63,7 +63,7 @@ export interface Button {
|
||||
isSelected?: boolean;
|
||||
}
|
||||
|
||||
const PAGESIZE = 10;
|
||||
const PAGESIZE = 100;
|
||||
|
||||
class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, IQueryTablesTabComponentStates> {
|
||||
public collection: ViewModels.Collection;
|
||||
@ -100,12 +100,6 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
this.tableDataClient = this.container.tableDataClient;
|
||||
this.tableEntityListViewModel2(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 = {
|
||||
tableEntityListViewModel,
|
||||
@ -201,7 +195,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.loadEntities(true);
|
||||
this.loadEntities(true, false);
|
||||
}
|
||||
|
||||
public createSelection = (): Selection => {
|
||||
@ -294,33 +288,77 @@ 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;
|
||||
// tableEntityListViewModel.renderNextPageAndupdateCache();
|
||||
let headers: string[] = [];
|
||||
//eslint-disable-next-line
|
||||
let documents: any = {};
|
||||
try {
|
||||
if (userContext.apiType === "Cassandra") {
|
||||
documents = await this.props.queryTablesTab.container.tableDataClient.queryDocuments(
|
||||
this.props.queryTablesTab.collection,
|
||||
selectedQueryText,
|
||||
true
|
||||
);
|
||||
headers = this.getFormattedHeaders(documents.Results);
|
||||
this.setupIntialEntities(documents.Results, headers, isInitialLoad);
|
||||
} else {
|
||||
const { collection } = this.props;
|
||||
documents = await this.getDocuments(collection, selectedQueryText);
|
||||
headers = this.getFormattedHeaders(documents.Results);
|
||||
this.setupIntialEntities(documents.Results, headers, isInitialLoad);
|
||||
// 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,
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
queryErrorMessage: "",
|
||||
hasQueryError: false,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.responseText) {
|
||||
} else {
|
||||
try {
|
||||
if (userContext.apiType === "Cassandra") {
|
||||
documents = await this.props.queryTablesTab.container.tableDataClient.queryDocuments(
|
||||
this.props.queryTablesTab.collection,
|
||||
selectedQueryText,
|
||||
true
|
||||
);
|
||||
headers = this.getFormattedHeaders(documents.Results);
|
||||
this.setupIntialEntities(headers, documents.Results, isInitialLoad);
|
||||
} else {
|
||||
const { collection } = this.props;
|
||||
documents = await this.getDocuments(collection, selectedQueryText);
|
||||
headers = this.getFormattedHeaders(documents.Results);
|
||||
this.setupIntialEntities(headers, documents.Results, isInitialLoad);
|
||||
}
|
||||
this.setState({
|
||||
queryErrorMessage: "",
|
||||
hasQueryError: false,
|
||||
});
|
||||
} catch (error) {
|
||||
this.setState({
|
||||
queryErrorMessage: error.responseText,
|
||||
hasQueryError: true,
|
||||
@ -331,17 +369,35 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
}
|
||||
|
||||
private setupIntialEntities = (
|
||||
entities: Entities.ITableEntity[],
|
||||
headers: string[],
|
||||
isInitialLoad: boolean
|
||||
entities?: Entities.ITableEntity[],
|
||||
isInitialLoad?: boolean
|
||||
): void => {
|
||||
let minWidth: number;
|
||||
let maxWidth: number;
|
||||
let documentItems: IDocument[] = [];
|
||||
let filteredItems: IDocument[] = [];
|
||||
this.columns = [];
|
||||
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({
|
||||
key: header,
|
||||
name: header,
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
minWidth: minWidth,
|
||||
maxWidth: maxWidth,
|
||||
data: "string",
|
||||
fieldName: header,
|
||||
isResizable: true,
|
||||
@ -350,12 +406,14 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
sortAscendingAriaLabel: "Sorted A to Z",
|
||||
sortDescendingAriaLabel: "Sorted Z to A",
|
||||
onColumnClick: this.onColumnClick,
|
||||
// onRender: (item: Entities.ITableEntity) => {
|
||||
// return <div className={!item[header] ? "noData" : ""}>{item[header] ? item[header] : " "}</div>;
|
||||
// },
|
||||
});
|
||||
});
|
||||
|
||||
const documentItems = this.generateDetailsList(entities);
|
||||
|
||||
const filteredItems = documentItems.slice(0, PAGESIZE);
|
||||
documentItems = this.generateDetailsList(entities);
|
||||
filteredItems = documentItems.slice(0, PAGESIZE);
|
||||
|
||||
this.setState(
|
||||
{
|
||||
@ -369,6 +427,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
queryText: this.state.queryViewModel.queryText(),
|
||||
fromDocument: 0,
|
||||
toDocument: PAGESIZE,
|
||||
currentStartIndex: PAGESIZE,
|
||||
},
|
||||
() => {
|
||||
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 => {
|
||||
const { columns, items } = this.state;
|
||||
const newColumns: IColumn[] = columns.slice();
|
||||
@ -444,6 +533,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
//eslint-disable-next-line
|
||||
let obj: any;
|
||||
documents.map((item) => {
|
||||
obj = {};
|
||||
this.columns.map((col) => {
|
||||
if (item[col.name]) {
|
||||
obj = { ...obj, ...{ [col.name]: item[col.name]._ } };
|
||||
@ -458,7 +548,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
this.loadEntities(false);
|
||||
this.loadEntities(false, false);
|
||||
}
|
||||
|
||||
public onAddEntityClick = (): void => {
|
||||
@ -472,7 +562,8 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
tableEntityListViewModel={this.state.tableEntityListViewModel}
|
||||
cassandraApiClient={new CassandraAPIDataClient()}
|
||||
reloadEntities={() => this.reloadEntities()}
|
||||
/>
|
||||
/>,
|
||||
"700px"
|
||||
);
|
||||
};
|
||||
|
||||
@ -492,7 +583,8 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
cassandraApiClient={new CassandraAPIDataClient()}
|
||||
selectedEntity={this.state.selectedItems}
|
||||
reloadEntities={() => this.reloadEntities()}
|
||||
/>
|
||||
/>,
|
||||
"700px"
|
||||
);
|
||||
};
|
||||
|
||||
@ -511,10 +603,12 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
.deleteDocuments(this.state.tableEntityListViewModel.queryTablesTab.collection, entitiesToDelete)
|
||||
//eslint-disable-next-line
|
||||
.then((results: any) => {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
return this.state.tableEntityListViewModel.removeEntitiesFromCache(entitiesToDelete).then(() => {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
this.loadEntities(false, false);
|
||||
});
|
||||
this.loadEntities(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -525,7 +619,11 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
selectedQueryText: this.state.queryViewModel.runQuery(queryTableRows),
|
||||
});
|
||||
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);
|
||||
this.setState({
|
||||
queryText: this.state.queryViewModel.queryText(),
|
||||
@ -1005,7 +1103,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
</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.items.length > 0 && !this.state.isLoading && (
|
||||
<DetailsList
|
||||
@ -1018,6 +1116,7 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
|
||||
selection={this.state.selection}
|
||||
selectionPreservedOnEmptyClick={true}
|
||||
checkboxVisibility={CheckboxVisibility.always}
|
||||
onShouldVirtualize={() => false}
|
||||
/>
|
||||
)}
|
||||
{this.state.items.length === 0 && !this.state.isLoading && (
|
||||
|
Loading…
x
Reference in New Issue
Block a user