Code clean up round 2

This commit is contained in:
vaidankarswapnil 2021-08-16 18:36:22 +05:30
parent 884f06a729
commit 27e99d7f2f
13 changed files with 67 additions and 937 deletions

View File

@ -107,8 +107,8 @@ src/Explorer/Tables/DataTable/CacheBase.ts
src/Explorer/Tables/DataTable/DataTableBindingManager.ts
src/Explorer/Tables/DataTable/DataTableBuilder.ts
src/Explorer/Tables/DataTable/DataTableContextMenu.ts
src/Explorer/Tables/DataTable/DataTableOperationManager.ts
src/Explorer/Tables/DataTable/DataTableOperations.ts
# src/Explorer/Tables/DataTable/DataTableOperationManager.ts
# src/Explorer/Tables/DataTable/DataTableOperations.ts
src/Explorer/Tables/DataTable/DataTableViewModel.ts
src/Explorer/Tables/DataTable/TableCommands.ts
src/Explorer/Tables/DataTable/TableEntityCache.ts

View File

@ -94,12 +94,13 @@
overflow: hidden;
.flex-display();
.flex-direction();
position: relative;
}
.tablesQueryTab {
padding-left: @MediumSpace;
width: 100%;
margin-bottom: 100px;
margin-bottom: 60px;
position: relative;
height: 100%;
}
@ -535,7 +536,6 @@ input::-webkit-inner-spin-button {
}
.query-document-detail-list {
// overflow-x: hidden;
height: 100%;
}
.query-table-clause-container {
@ -545,14 +545,19 @@ input::-webkit-inner-spin-button {
}
.query-tab-document-pagination {
display: flex;
flex-direction: column;
flex-direction: row;
position: absolute;
bottom: 0;
padding-left: @MediumSpace;
padding-bottom: 45px;
padding-left: 12px;
justify-content: space-between;
width: 100%;
align-items: center;
height: 60px;
}
.pagination {
margin: 15px 0 !important;
order: 2;
padding-right: 15px;
li > .item-link {
position: relative;
float: left;
@ -577,8 +582,6 @@ input::-webkit-inner-spin-button {
height: 100%;
width: 100%;
}
// .pagination > li > div {
// }
/*
@media only screen and (max-width: 1200px) {

View File

@ -1,7 +1,6 @@
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";
@ -13,7 +12,6 @@ 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";
@ -123,11 +121,8 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
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);
@ -136,46 +131,6 @@ export const AddTableEntityPanel: FunctionComponent<AddTableEntityPanelProps> =
} 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 */

View File

@ -9,7 +9,6 @@ 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";
@ -215,7 +214,6 @@ 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);
try {
const newEntity: Entities.ITableEntity = await newTableDataClient.updateDocument(
@ -224,11 +222,8 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
entity
);
await tableEntityListViewModel.updateCachedEntity(newEntity);
// if (!tryInsertNewHeaders(tableEntityListViewModel, newEntity)) {
// tableEntityListViewModel.redrawTableThrottled();
reloadEntities();
closeSidePanel();
// }
tableEntityListViewModel.selected.removeAll();
tableEntityListViewModel.selected.push(newEntity);
} catch (error) {
@ -238,36 +233,6 @@ export const EditTableEntityPanel: FunctionComponent<EditTableEntityPanelProps>
} 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

View File

@ -1,52 +0,0 @@
import * as Utilities from "../Utilities";
/**
* Wrapper function for creating data tables. Call this method, not the
* data tables constructor when you want to create a data table. This
* function makes sure that content without a render function is properly
* encoded to prevent XSS.
* @param{$dataTableElem} JQuery data table element
* @param{$settings} Settings to use when creating the data table
*/
export function createDataTable($dataTableElem: JQuery, settings: any): DataTables.DataTable {
return $dataTableElem.DataTable(applyDefaultRendering(settings));
}
/**
* Go through the settings for a data table and apply a simple HTML encode to any column
* without a render function to prevent XSS.
* @param{settings} The settings to check
* @return The given settings with all columns having a rendering function
*/
function applyDefaultRendering(settings: any): DataTables.SettingsLegacy {
var tableColumns: DataTables.ColumnLegacy[] = null;
if (settings.aoColumns) {
tableColumns = settings.aoColumns;
} else if (settings.aoColumnDefs) {
// for tables we use aoColumnDefs instead of aoColumns
tableColumns = settings.aoColumnDefs;
}
// either the settings had no columns defined, or they were called
// by a property name which we have not used before
if (!tableColumns) {
return settings;
}
for (var i = 0; i < tableColumns.length; i++) {
// the column does not have a render function
if (!tableColumns[i].mRender) {
tableColumns[i].mRender = defaultDataRender;
}
}
return settings;
}
/**
* Default data render function, whatever is done to data in here
* will be done to any data which we do not specify a render for.
*/
function defaultDataRender(data: any, type: string, full: any) {
return Utilities.htmlEncode(data);
}

View File

@ -1,300 +0,0 @@
import ko from "knockout";
import * as DataTableOperations from "./DataTableOperations";
import * as Constants from "../Constants";
import TableCommands from "./TableCommands";
import TableEntityListViewModel from "./TableEntityListViewModel";
import * as Utilities from "../Utilities";
import * as Entities from "../Entities";
/*
* Base class for data table row selection.
*/
export default class DataTableOperationManager {
private _tableEntityListViewModel: TableEntityListViewModel;
private _tableCommands: TableCommands;
private dataTable: JQuery;
constructor(table: JQuery, viewModel: TableEntityListViewModel, tableCommands: TableCommands) {
this.dataTable = table;
this._tableEntityListViewModel = viewModel;
this._tableCommands = tableCommands;
this.bind();
this._tableEntityListViewModel.bind(this);
}
private click = (event: JQueryEventObject) => {
var elem: JQuery = $(event.currentTarget);
this.updateLastSelectedItem(elem, event.shiftKey);
if (Utilities.isEnvironmentCtrlPressed(event)) {
this.applyCtrlSelection(elem);
} else if (event.shiftKey) {
this.applyShiftSelection(elem);
} else {
this.applySingleSelection(elem);
}
};
private doubleClick = (event: JQueryEventObject) => {
this.tryOpenEditor();
};
private keyDown = (event: JQueryEventObject): boolean => {
var isUpArrowKey: boolean = event.keyCode === Constants.keyCodes.UpArrow,
isDownArrowKey: boolean = event.keyCode === Constants.keyCodes.DownArrow,
handled: boolean = false;
if (isUpArrowKey || isDownArrowKey) {
var lastSelectedItem: Entities.ITableEntity = this._tableEntityListViewModel.lastSelectedItem;
var dataTableRows: JQuery = $(Constants.htmlSelectors.dataTableAllRowsSelector);
var maximumIndex = dataTableRows.length - 1;
// If can't find an index for lastSelectedItem, then either no item is previously selected or it goes across page.
// Simply select the first item in this case.
var lastSelectedItemIndex = lastSelectedItem
? this._tableEntityListViewModel.getItemIndexFromCurrentPage(
this._tableEntityListViewModel.getTableEntityKeys(lastSelectedItem.RowKey._)
)
: -1;
var nextIndex: number = isUpArrowKey ? lastSelectedItemIndex - 1 : lastSelectedItemIndex + 1;
var safeIndex: number = Utilities.ensureBetweenBounds(nextIndex, 0, maximumIndex);
var selectedRowElement: JQuery = dataTableRows.eq(safeIndex);
if (selectedRowElement) {
if (event.shiftKey) {
this.applyShiftSelection(selectedRowElement);
} else {
this.applySingleSelection(selectedRowElement);
}
this.updateLastSelectedItem(selectedRowElement, event.shiftKey);
handled = true;
DataTableOperations.scrollToRowIfNeeded(dataTableRows, safeIndex, isUpArrowKey);
}
} else if (
Utilities.isEnvironmentCtrlPressed(event) &&
!Utilities.isEnvironmentShiftPressed(event) &&
!Utilities.isEnvironmentAltPressed(event) &&
event.keyCode === Constants.keyCodes.A
) {
this.applySelectAll();
handled = true;
}
return !handled;
};
// Note: There is one key up event each time a key is pressed;
// in contrast, there may be more than one key down and key
// pressed events.
private keyUp = (event: JQueryEventObject): boolean => {
var handled: boolean = false;
switch (event.keyCode) {
case Constants.keyCodes.Enter:
handled = this.tryOpenEditor();
break;
case Constants.keyCodes.Delete:
handled = this.tryHandleDeleteSelected();
break;
}
return !handled;
};
private itemDropped = (event: JQueryEventObject): boolean => {
var handled: boolean = false;
var items = (<any>event.originalEvent).dataTransfer.items;
if (!items) {
// On browsers outside of Chromium
// we can't discern between dirs and files
// so we will disable drag & drop for now
return null;
}
for (var i = 0; i < items.length; i++) {
var item = items[i];
var entry = item.webkitGetAsEntry();
if (entry.isFile) {
// TODO: parse the file and insert content as entities
}
}
return !handled;
};
private tryOpenEditor(): boolean {
return this._tableCommands.tryOpenEntityEditor(this._tableEntityListViewModel);
}
private tryHandleDeleteSelected(): boolean {
var selectedEntities: Entities.ITableEntity[] = this._tableEntityListViewModel.selected();
var handled: boolean = false;
if (selectedEntities && selectedEntities.length) {
this._tableCommands.deleteEntitiesCommand(this._tableEntityListViewModel);
handled = true;
}
return handled;
}
private getEntityIdentity($elem: JQuery): Entities.ITableEntityIdentity {
return {
RowKey: $elem.attr(Constants.htmlAttributeNames.dataTableRowKeyAttr),
};
}
private updateLastSelectedItem($elem: JQuery, isShiftSelect: boolean) {
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var entity = this._tableEntityListViewModel.getItemFromCurrentPage(
this._tableEntityListViewModel.getTableEntityKeys(entityIdentity.RowKey)
);
this._tableEntityListViewModel.lastSelectedItem = entity;
if (!isShiftSelect) {
this._tableEntityListViewModel.lastSelectedAnchorItem = entity;
}
}
private applySingleSelection($elem: JQuery) {
if ($elem) {
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
this._tableEntityListViewModel.clearSelection();
this.addToSelection(entityIdentity.RowKey);
}
}
private applySelectAll() {
this._tableEntityListViewModel.clearSelection();
ko.utils.arrayPushAll<Entities.ITableEntity>(
this._tableEntityListViewModel.selected,
this._tableEntityListViewModel.getAllItemsInCurrentPage()
);
}
private applyCtrlSelection($elem: JQuery): void {
var koSelected: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
? this._tableEntityListViewModel.selected
: null;
if (koSelected) {
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
if (
!this._tableEntityListViewModel.isItemSelected(
this._tableEntityListViewModel.getTableEntityKeys(entityIdentity.RowKey)
)
) {
// Adding item not previously in selection
this.addToSelection(entityIdentity.RowKey);
} else {
koSelected.remove((item: Entities.ITableEntity) => item.RowKey._ === entityIdentity.RowKey);
}
}
}
private applyShiftSelection($elem: JQuery): void {
var anchorItem = this._tableEntityListViewModel.lastSelectedAnchorItem;
// If anchor item doesn't exist, use the first available item of current page instead
if (!anchorItem && this._tableEntityListViewModel.items().length > 0) {
anchorItem = this._tableEntityListViewModel.items()[0];
}
if (anchorItem) {
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var elementIndex = this._tableEntityListViewModel.getItemIndexFromAllPages(
this._tableEntityListViewModel.getTableEntityKeys(entityIdentity.RowKey)
);
var anchorIndex = this._tableEntityListViewModel.getItemIndexFromAllPages(
this._tableEntityListViewModel.getTableEntityKeys(anchorItem.RowKey._)
);
var startIndex = Math.min(elementIndex, anchorIndex);
var endIndex = Math.max(elementIndex, anchorIndex);
this._tableEntityListViewModel.clearSelection();
ko.utils.arrayPushAll<Entities.ITableEntity>(
this._tableEntityListViewModel.selected,
this._tableEntityListViewModel.getItemsFromAllPagesWithinRange(startIndex, endIndex + 1)
);
}
}
private applyContextMenuSelection($elem: JQuery) {
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
if (
!this._tableEntityListViewModel.isItemSelected(
this._tableEntityListViewModel.getTableEntityKeys(entityIdentity.RowKey)
)
) {
if (this._tableEntityListViewModel.selected().length) {
this._tableEntityListViewModel.clearSelection();
}
this.addToSelection(entityIdentity.RowKey);
}
}
private addToSelection(rowKey: string) {
var selectedEntity: Entities.ITableEntity = this._tableEntityListViewModel.getItemFromCurrentPage(
this._tableEntityListViewModel.getTableEntityKeys(rowKey)
);
if (selectedEntity != null) {
this._tableEntityListViewModel.selected.push(selectedEntity);
}
}
// Selecting first row if the selection is empty.
public selectFirstIfNeeded(): void {
var koSelected: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
? this._tableEntityListViewModel.selected
: null;
var koEntities: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
? this._tableEntityListViewModel.items
: null;
if (!koSelected().length && koEntities().length) {
var firstEntity: Entities.ITableEntity = koEntities()[0];
// Clear last selection: lastSelectedItem and lastSelectedAnchorItem
this._tableEntityListViewModel.clearLastSelected();
this.addToSelection(firstEntity.RowKey._);
// Update last selection
this._tableEntityListViewModel.lastSelectedItem = firstEntity;
// Finally, make sure first row is visible
DataTableOperations.scrollToTopIfNeeded();
}
}
public bind() {
this.dataTable.on("click", "tr", this.click);
this.dataTable.on("dblclick", "tr", this.doubleClick);
this.dataTable.on("keydown", "td", this.keyDown);
this.dataTable.on("keyup", "td", this.keyUp);
// Keyboard navigation - selecting first row if the selection is empty when the table gains focus.
this.dataTable.on("focus", () => {
this.selectFirstIfNeeded();
return true;
});
// Bind drag & drop behavior
$("body").on("drop", this.itemDropped);
}
public focusTable(): void {
this.dataTable.focus();
}
}

View File

@ -1,192 +0,0 @@
import _ from "underscore";
import Q from "q";
import * as Entities from "../Entities";
import * as QueryBuilderConstants from "../Constants";
import * as Utilities from "../Utilities";
export function getRowSelector(selectorSchema: Entities.IProperty[]): string {
var selector: string = "";
selectorSchema &&
selectorSchema.forEach((p: Entities.IProperty) => {
selector += "[" + p.key + '="' + Utilities.jQuerySelectorEscape(p.value) + '"]';
});
return QueryBuilderConstants.htmlSelectors.dataTableAllRowsSelector + selector;
}
export function isRowVisible(dataTableScrollBodyQuery: JQuery, element: HTMLElement): boolean {
var isVisible = false;
if (dataTableScrollBodyQuery.length && element) {
var elementRect: ClientRect = element.getBoundingClientRect(),
dataTableScrollBodyRect: ClientRect = dataTableScrollBodyQuery.get(0).getBoundingClientRect();
isVisible = elementRect.bottom <= dataTableScrollBodyRect.bottom && dataTableScrollBodyRect.top <= elementRect.top;
}
return isVisible;
}
export function scrollToRowIfNeeded(dataTableRows: JQuery, currentIndex: number, isScrollUp: boolean): void {
if (dataTableRows.length) {
var dataTableScrollBodyQuery: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector),
selectedRowElement: HTMLElement = dataTableRows.get(currentIndex);
if (dataTableScrollBodyQuery.length && selectedRowElement) {
var isVisible: boolean = isRowVisible(dataTableScrollBodyQuery, selectedRowElement);
if (!isVisible) {
var selectedRowQuery: JQuery = $(selectedRowElement),
scrollPosition: number = dataTableScrollBodyQuery.scrollTop(),
selectedElementPosition: number = selectedRowQuery.position().top,
newScrollPosition: number = 0;
if (isScrollUp) {
newScrollPosition = scrollPosition + selectedElementPosition;
} else {
newScrollPosition =
scrollPosition + (selectedElementPosition + selectedRowQuery.height() - dataTableScrollBodyQuery.height());
}
dataTableScrollBodyQuery.scrollTop(newScrollPosition);
}
}
}
}
export function scrollToTopIfNeeded(): void {
var $dataTableRows: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableAllRowsSelector),
$dataTableScrollBody: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector);
if ($dataTableRows.length && $dataTableScrollBody.length) {
$dataTableScrollBody.scrollTop(0);
}
}
export function setPaginationButtonEventHandlers(): void {
$(QueryBuilderConstants.htmlSelectors.dataTablePaginationButtonSelector)
.on("mousedown", (event: JQueryEventObject) => {
// Prevents the table contents from briefly jumping when clicking on "Load more"
event.preventDefault();
})
.attr("role", "button");
}
export function filterColumns(table: DataTables.DataTable, settings: boolean[]): void {
settings &&
settings.forEach((value: boolean, index: number) => {
table.column(index).visible(value, false);
});
table.columns.adjust().draw(false);
}
/**
* Reorder columns based on current order.
* If no current order is specified, reorder the columns based on intial order.
*/
export function reorderColumns(
table: DataTables.DataTable,
targetOrder: number[],
currentOrder?: number[]
): Q.Promise<any> {
var columnsCount: number = targetOrder.length;
var isCurrentOrderPassedIn: boolean = !!currentOrder;
if (!isCurrentOrderPassedIn) {
currentOrder = getInitialOrder(columnsCount);
}
var isSameOrder: boolean = Utilities.isEqual(currentOrder, targetOrder);
// if the targetOrder is the same as current order, do nothing.
if (!isSameOrder) {
// Otherwise, calculate the transformation order.
// If current order not specified, then it'll be set to initial order,
// i.e., either no reorder happened before or reordering to its initial order,
// Then the transformation order will be the same as target order.
// If current order is specified, then a transformation order is calculated.
// Refer to calculateTransformationOrder for details about transformation order.
var transformationOrder: number[] = isCurrentOrderPassedIn
? calculateTransformationOrder(currentOrder, targetOrder)
: targetOrder;
try {
$.fn.dataTable.ColReorder(table).fnOrder(transformationOrder);
} catch (err) {
return Q.reject(err);
}
}
return Q.resolve(null);
}
export function resetColumns(table: DataTables.DataTable): void {
$.fn.dataTable.ColReorder(table).fnReset();
}
/**
* A table's initial order is described in the form of a natural ascending order.
* E.g., for a table with 9 columns, the initial order will be: [0, 1, 2, 3, 4, 5, 6, 7, 8]
*/
export function getInitialOrder(columnsCount: number): number[] {
return _.range(columnsCount);
}
/**
* Get current table's column order which is described based on initial table. E.g.,
* Initial order: I = [0, 1, 2, 3, 4, 5, 6, 7, 8] <----> {prop0, prop1, prop2, prop3, prop4, prop5, prop6, prop7, prop8}
* Current order: C = [0, 1, 2, 6, 7, 3, 4, 5, 8] <----> {prop0, prop1, prop2, prop6, prop7, prop3, prop4, prop5, prop8}
*/
export function getCurrentOrder(table: DataTables.DataTable): number[] {
return $.fn.dataTable.ColReorder(table).fnOrder();
}
/**
* Switch the index and value for each element of an array. e.g.,
* InputArray: [0, 1, 2, 6, 7, 3, 4, 5, 8]
* Result: [0, 1, 2, 5, 6, 7, 3, 4, 8]
*/
export function invertIndexValues(inputArray: number[]): number[] {
var invertedArray: number[] = [];
if (inputArray) {
inputArray.forEach((value: number, index: number) => {
invertedArray[inputArray[index]] = index;
});
}
return invertedArray;
}
/**
* DataTable fnOrder API is based on the current table. So we need to map the order targeting original table to targeting current table.
* An detailed example for this. Assume the table has 9 columns.
* Initial order (order of the initial table): I = [0, 1, 2, 3, 4, 5, 6, 7, 8] <----> {prop0, prop1, prop2, prop3, prop4, prop5, prop6, prop7, prop8}
* Current order (order of the current table): C = [0, 1, 2, 6, 7, 3, 4, 5, 8] <----> {prop0, prop1, prop2, prop6, prop7, prop3, prop4, prop5, prop8}
* Target order (order of the targeting table): T = [0, 1, 2, 5, 6, 7, 8, 3, 4] <----> {prop0, prop1, prop2, prop5, prop6, prop7, prop8, prop3, prop4}
* Transformation order: an order passed to fnOrder API that transforms table from current order to target order.
* When the table is constructed, it has the intial order. After an reordering with current order array, now the table is shown in current order, e.g.,
* column 3 in the current table is actually column C[3]=6 in the intial table, both indicate the column with header prop6.
* Now we want to continue to do another reorder to make the target table in the target order. Directly invoking API with the new order won't work as
* the API only do reorder based on the current table like the first time we invoke the API. So an order based on the current table needs to be calulated.
* Here is an example of how to calculate the transformation order:
* In target table, column 3 should be column T[3]=5 in the intial table with header prop5, while in current table, column with header prop5 is column 7 as C[7]=5.
* As a result, in transformation order, column 3 in the target table should be column 7 in the current table, Trans[3] = 7. In the same manner, we can get the
* transformation order: Trans = [0, 1, 2, 7, 3, 4, 8, 5, 6]
*/
export function calculateTransformationOrder(currentOrder: number[], targetOrder: number[]): number[] {
var transformationOrder: number[] = [];
if (currentOrder && targetOrder && currentOrder.length === targetOrder.length) {
var invertedCurrentOrder: number[] = invertIndexValues(currentOrder);
transformationOrder = targetOrder.map((value: number) => invertedCurrentOrder[value]);
}
return transformationOrder;
}
export function getDataTableHeaders(table: DataTables.DataTable): string[] {
var columns: DataTables.ColumnsMethods = table.columns();
var headers: string[] = [];
if (columns) {
// table.columns() return ColumnsMethods which is an array of arrays
var columnIndexes: number[] = (<any>columns)[0];
if (columnIndexes) {
headers = columnIndexes.map((value: number) => $(table.columns(value).header()).html());
}
}
return headers;
}

View File

@ -123,10 +123,3 @@ export function checkForDefaultHeader(headers: string[]): boolean {
export function forceRecalculateTableSize(): void {
$("body").trigger("resize");
}
/**
* Turns off the spinning progress indicator on the data table.
*/
export function turnOffProgressIndicator(): void {
$("div.dataTables_processing").hide();
}

View File

@ -5,7 +5,6 @@ import * as CommonConstants from "../../../Common/Constants";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab";
import * as Constants from "../Constants";
import * as Entities from "../Entities";
import CacheBase from "./CacheBase";
@ -46,19 +45,11 @@ abstract class DataTableViewModel {
private pendingRedraw = false;
private lastRedrawTime = new Date().getTime();
private dataTableOperationManager: IDataTableOperation;
public queryTablesTab: NewQueryTablesTab;
constructor() {
this.items([]);
this.selected([]);
// Late bound
this.dataTableOperationManager = null;
}
public bind(dataTableOperationManager: IDataTableOperation): void {
this.dataTableOperationManager = dataTableOperationManager;
}
public clearLastSelected(): void {
@ -100,10 +91,6 @@ abstract class DataTableViewModel {
}
}
public focusDataTable(): void {
this.dataTableOperationManager.focusTable();
}
public getItemFromSelectedItems(itemKeys: Entities.IProperty[]): Entities.ITableEntity {
return _.find(this.selected(), (item: Entities.ITableEntity) => {
return this.matchesKeys(item, itemKeys);
@ -170,10 +157,6 @@ 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);
@ -208,27 +191,6 @@ abstract class DataTableViewModel {
protected stringCompare(s1: string, s2: string): boolean {
return s1 === s2;
}
private updatePaginationControls(oSettings: any) {
var pageInfo = this.table.page.info();
var pageSize = pageInfo.length;
var paginateElement = $(oSettings.nTableWrapper).find(Constants.htmlSelectors.paginateSelector);
if (this.allDownloaded) {
if (this.cache.length <= pageSize) {
// Hide pagination controls if everything fits in one page!.
paginateElement.hide();
} else {
// Enable pagination controls.
paginateElement.show();
oSettings.oLanguage.oPaginate.sLast = DataTableViewModel.lastPageLabel;
}
} else {
// Enable pagination controls and show load more button.
paginateElement.show();
oSettings.oLanguage.oPaginate.sLast = DataTableViewModel.loadMoreLabel;
}
}
}
interface IDataTableOperation {

View File

@ -94,8 +94,4 @@ export default class TableCommands {
return null;
}
public resetColumns(viewModel: TableEntityListViewModel): void {
viewModel.reloadTable();
}
}

View File

@ -132,113 +132,10 @@ export default class TableEntityListViewModel extends DataTableViewModel {
return [{ key: Constants.EntityKeyNames.RowKey, value: rowKey }];
}
public reloadTable(useSetting: boolean = true, resetHeaders: boolean = true): DataTables.DataTable {
this.clearCache();
this.clearSelection();
this.isCancelled = false;
this.useSetting = useSetting;
if (resetHeaders) {
this.updateHeaders([Constants.defaultHeader]);
}
return this.table.ajax.reload();
}
public updateHeaders(newHeaders: string[], notifyColumnChanges: boolean = false, enablePrompt: boolean = true): void {
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.
@ -440,7 +337,6 @@ export default class TableEntityListViewModel extends DataTableViewModel {
tablePageSize: number,
downloadSize: number
): Promise<Entities.ITableEntity[]> {
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 366 ~ TableEntityListViewModel ~ prefetchAndRender");
this.queryErrorMessage(null);
if (this.cache.serverCallInProgress) {
return undefined;
@ -452,27 +348,15 @@ export default class TableEntityListViewModel extends DataTableViewModel {
}
// 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,
@ -514,9 +398,8 @@ export default class TableEntityListViewModel extends DataTableViewModel {
);
this.queryTablesTab.onLoadStartKey = null;
}
DataTableUtilities.turnOffProgressIndicator();
}
// return undefined;
return undefined;
}
/**
@ -536,7 +419,6 @@ export default class TableEntityListViewModel extends DataTableViewModel {
downloadSize: number,
currentRetry: number = 0
): Promise<any> {
console.log("🚀 ~ file: TableEntityListViewModel.ts ~ line 456 ~ TableEntityListViewModel ~ prefetchData");
var entities: any;
if (!this.cache.serverCallInProgress) {
this.cache.serverCallInProgress = true;
@ -544,7 +426,6 @@ export default class TableEntityListViewModel extends DataTableViewModel {
this.lastPrefetchTime = new Date().getTime();
var time = this.lastPrefetchTime;
var promise: Promise<IListTableEntitiesSegmentedResult>;
try {
if (this._documentIterator && this.continuationToken) {
// TODO handle Cassandra case
@ -558,7 +439,7 @@ export default class TableEntityListViewModel extends DataTableViewModel {
};
entities = finalEntities;
} else if (this.continuationToken && userContext.apiType === "Cassandra") {
entities = this.queryTablesTab.container.tableDataClient.queryDocuments(
entities = await this.queryTablesTab.container.tableDataClient.queryDocuments(
this.queryTablesTab.collection,
this.cqlQuery(),
true,
@ -603,10 +484,6 @@ 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);
@ -616,10 +493,6 @@ export default class TableEntityListViewModel extends DataTableViewModel {
} 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;

View File

@ -170,17 +170,13 @@ 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()
: this._tableEntityListViewModel.cqlQuery();
};
public clearQuery = (): DataTables.DataTable => {
public clearQuery = (): void => {
this.queryText();
this.topValue();
this.selectText();
@ -198,7 +194,6 @@ export default class QueryViewModel {
this.queryTablesTab.collection.id()
)}`
);
return this._tableEntityListViewModel.reloadTable(false);
};
public selectQueryOptions(headers: string[], getSelectMessage: (selectMessage: string) => void): void {

View File

@ -243,7 +243,6 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
public loadFilterExample(): void {
const { queryTableRows, headers, entities } = this.state;
const queryTableRowsClone = [...queryTableRows];
// queryTableRowsClone[0].fieldOptions = getformattedOptions(headers);
this.setState({
operators: this.state.queryViewModel.queryBuilderViewModel().operators(),
queryTableRows: queryTableRowsClone,
@ -291,48 +290,16 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
let headers: string[] = [];
//eslint-disable-next-line
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 = documents.Results?.length
? this.getFormattedHeaders(documents.Results)
: ["userid", "name", "email"];
this.setupIntialEntities(headers, documents.Results, isInitialLoad);
headers = documents?.length ? this.getFormattedHeaders(documents) : ["userid", "name", "email"];
this.setupIntialEntities(headers, documents, isInitialLoad);
} else {
// console.log(
// "🚀 ~ file: QueryTablesTabComponent.tsx ~ line 311 ~ QueryTablesTabComponent ~ loadEntities ~ data",
// documents
// );
headers = documents.Results?.length
? this.getFormattedHeaders(documents.Results)
: ["RowKey", "PartitionKey", "Timestamp"];
headers = documents?.length ? this.getFormattedHeaders(documents) : ["RowKey", "PartitionKey", "Timestamp"];
this.setupIntialEntities(headers, documents, isInitialLoad);
}
// this.isEntitiesAvailable(isInitialLoad, data);
} catch (error) {
this.setState({
queryErrorMessage: error.responseText,
@ -415,9 +382,6 @@ 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>;
// },
});
});
@ -455,36 +419,6 @@ 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();
@ -640,10 +574,6 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
selectedQueryText: this.state.queryViewModel.runQuery(queryTableRows),
});
setTimeout(() => {
// console.log(
// "🚀 ~ file: QueryTablesTabComponent.tsx ~ line 651 ~ QueryTablesTabComponent ~ runQuery ~ selectedQueryText",
// this.state.selectedQueryText
// );
this.loadEntities(false, queryTableRows.length > 0 ? true : false);
}, 2000);
this.setState({
@ -1147,53 +1077,55 @@ class QueryTablesTabComponent extends Component<IQueryTablesTabComponentProps, I
<div className="query-tab-document-pagination">
{this.state.items.length > 0 && !this.state.isLoading && (
<>
<ul className="pagination ">
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("FIRST", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
First
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination(
"PREVIOUS",
this.state.originalItems,
this.state.currentStartIndex,
PAGESIZE
)
}
>
Previous
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("NEXT", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
Next
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("LAST", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
Last
</div>
</li>
</ul>
{this.state.originalItems.length > PAGESIZE && (
<ul className="pagination ">
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("FIRST", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
First
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination(
"PREVIOUS",
this.state.originalItems,
this.state.currentStartIndex,
PAGESIZE
)
}
>
Previous
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("NEXT", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
Next
</div>
</li>
<li>
<div
className="item-link"
onClick={() =>
this.handlePagination("LAST", this.state.originalItems, this.state.currentStartIndex, PAGESIZE)
}
>
Last
</div>
</li>
</ul>
)}
<Text variant="medium">
Results {this.state.fromDocument + 1} -{" "}
{this.state.originalItems.length >= this.state.toDocument