diff --git a/src/Bindings/BindingHandlersRegisterer.ts b/src/Bindings/BindingHandlersRegisterer.ts index 45afc6732..363a33359 100644 --- a/src/Bindings/BindingHandlersRegisterer.ts +++ b/src/Bindings/BindingHandlersRegisterer.ts @@ -1,7 +1,5 @@ import * as ko from "knockout"; import * as ReactBindingHandler from "./ReactBindingHandler"; -import "../Explorer/Tables/DataTable/DataTableBindingManager"; - export class BindingHandlersRegisterer { public static registerBindingHandlers() { ko.bindingHandlers.setTemplateReady = { diff --git a/src/Explorer/Tables/DataTable/DataTableBindingManager.ts b/src/Explorer/Tables/DataTable/DataTableBindingManager.ts deleted file mode 100644 index 799bb1b70..000000000 --- a/src/Explorer/Tables/DataTable/DataTableBindingManager.ts +++ /dev/null @@ -1,393 +0,0 @@ -import * as ko from "knockout"; -import * as _ from "underscore"; - -import * as Constants from "../Constants"; -import * as ViewModels from "../../../Contracts/ViewModels"; -import * as DataTableBuilder from "./DataTableBuilder"; -import DataTableOperationManager from "./DataTableOperationManager"; -import * as DataTableOperations from "./DataTableOperations"; -import QueryTablesTab from "../../Tabs/QueryTablesTab"; -import TableEntityListViewModel from "./TableEntityListViewModel"; -import * as Utilities from "../Utilities"; -import * as Entities from "../Entities"; - -/** - * Custom binding manager of datatable - */ -var tableEntityListViewModelMap: { - [key: string]: { - tableViewModel: TableEntityListViewModel; - operationManager: DataTableOperationManager; - $dataTable: JQuery; - }; -} = {}; - -function bindDataTable(element: any, valueAccessor: any, allBindings: any, viewModel: any, bindingContext: any) { - var tableEntityListViewModel = bindingContext.$data; - tableEntityListViewModel.notifyColumnChanges = onTableColumnChange; - var $dataTable = $(element); - var queryTablesTab = bindingContext.$parent; - var operationManager = new DataTableOperationManager( - $dataTable, - tableEntityListViewModel, - queryTablesTab.tableCommands - ); - - tableEntityListViewModelMap[queryTablesTab.tabId] = { - tableViewModel: tableEntityListViewModel, - operationManager: operationManager, - $dataTable: $dataTable, - }; - - createDataTable(0, tableEntityListViewModel, queryTablesTab); // Fake a DataTable to start. - $(window).resize(updateTableScrollableRegionMetrics); - operationManager.focusTable(); // Also selects the first row if needed. -} - -function onTableColumnChange(enablePrompt: boolean = true, queryTablesTab: QueryTablesTab) { - var columnsFilter: boolean[] = null; - var tableEntityListViewModel = tableEntityListViewModelMap[queryTablesTab.tabId].tableViewModel; - if (queryTablesTab.queryViewModel()) { - queryTablesTab.queryViewModel().queryBuilderViewModel().updateColumnOptions(); - } - createDataTable( - tableEntityListViewModel.tablePageStartIndex, - tableEntityListViewModel, - queryTablesTab, - true, - columnsFilter - ); -} - -function createDataTable( - startIndex: number, - tableEntityListViewModel: TableEntityListViewModel, - queryTablesTab: QueryTablesTab, - destroy: boolean = false, - columnsFilter: boolean[] = null -): void { - var $dataTable = tableEntityListViewModelMap[queryTablesTab.tabId].$dataTable; - if (destroy) { - // Find currently displayed columns. - var currentColumns: string[] = tableEntityListViewModel.headers; - - // Calculate how many more columns need to added to the current table. - var columnsToAdd: number = _.difference(tableEntityListViewModel.headers, currentColumns).length; - - // This is needed as current solution of adding column is more like a workaround - // The official support for dynamically add column is not yet there - // Please track github issue https://github.com/DataTables/DataTables/issues/273 for its offical support - for (var i = 0; i < columnsToAdd; i++) { - $(".dataTables_scrollHead table thead tr th").eq(0).after(""); - } - tableEntityListViewModel.table.destroy(); - $dataTable.empty(); - } - - var jsonColTable = []; - - for (var i = 0; i < tableEntityListViewModel.headers.length; i++) { - jsonColTable.push({ - sTitle: tableEntityListViewModel.headers[i], - data: tableEntityListViewModel.headers[i], - aTargets: [i], - mRender: bindColumn, - visible: !!columnsFilter ? columnsFilter[i] : true, - }); - } - - tableEntityListViewModel.table = DataTableBuilder.createDataTable($dataTable, { - // WARNING!!! SECURITY: If you add new columns, make sure you encode them if they are user strings from Azure (see encodeText) - // so that they don't get interpreted as HTML in our page. - colReorder: true, - aoColumnDefs: jsonColTable, - stateSave: false, - dom: "RZlfrtip", - oColReorder: { - iFixedColumns: 1, - }, - displayStart: startIndex, - bPaginate: true, - pagingType: "full_numbers", - bProcessing: true, - oLanguage: { - sInfo: "Results _START_ - _END_ of _TOTAL_", - oPaginate: { - sFirst: "<<", - sNext: ">", - sPrevious: "<", - sLast: ">>", - }, - sProcessing: '', - oAria: { - sSortAscending: "", - sSortDescending: "", - }, - }, - destroy: destroy, - bInfo: true, - bLength: false, - bLengthChange: false, - scrollX: true, - scrollCollapse: true, - iDisplayLength: 100, - serverSide: true, - ajax: queryTablesTab.tabId, // Using this settings to make sure for getServerData we update the table based on the appropriate tab - fnServerData: getServerData, - fnRowCallback: bindClientId, - fnInitComplete: initializeTable, - fnDrawCallback: updateSelectionStatus, - }); - - (tableEntityListViewModel.table.table(0).container() as Element) - .querySelectorAll(Constants.htmlSelectors.dataTableHeaderTableSelector) - .forEach((table) => { - table.setAttribute( - "summary", - `Header for sorting results for container ${tableEntityListViewModel.queryTablesTab.collection.id()}` - ); - }); - - (tableEntityListViewModel.table.table(0).container() as Element) - .querySelectorAll(Constants.htmlSelectors.dataTableBodyTableSelector) - .forEach((table) => { - table.setAttribute("summary", `Results for container ${tableEntityListViewModel.queryTablesTab.collection.id()}`); - }); -} - -function bindColumn(data: any, type: string, full: any) { - var displayedValue: any = null; - if (data) { - displayedValue = data._; - - // SECURITY: Make sure we don't allow cross-site scripting by interpreting the values as HTML - displayedValue = Utilities.htmlEncode(displayedValue); - - // Css' empty psuedo class can only tell the difference of whether a cell has values. - // A cell has no values no matter it's empty or it has no such a property. - // To distinguish between an empty cell and a non-existing property cell, - // we add a whitespace to the empty cell so that css will treat it as a cell with values. - if (displayedValue === "" && data.$ === Constants.TableType.String) { - displayedValue = " "; - } - } - return displayedValue; -} - -function getServerData(sSource: any, aoData: any, fnCallback: any, oSettings: any) { - tableEntityListViewModelMap[oSettings.ajax].tableViewModel.renderNextPageAndupdateCache( - sSource, - aoData, - fnCallback, - oSettings - ); -} - -/** - * Bind table data information to row element so that we can track back to the table data - * from UI elements. - */ -function bindClientId(nRow: Node, aData: Entities.ITableEntity) { - $(nRow).attr(Constants.htmlAttributeNames.dataTableRowKeyAttr, aData.RowKey._); - return nRow; -} - -function selectionChanged(element: any, valueAccessor: any, allBindings: any, viewModel: any, bindingContext: any) { - $(".dataTable tr.selected").attr("tabindex", "-1").removeClass("selected"); - - const selected = - bindingContext && bindingContext.$data && bindingContext.$data.selected && bindingContext.$data.selected(); - selected && - selected.forEach((b: Entities.ITableEntity) => { - var sel = DataTableOperations.getRowSelector([ - { - key: Constants.htmlAttributeNames.dataTableRowKeyAttr, - value: b.RowKey && b.RowKey._ && b.RowKey._.toString(), - }, - ]); - - $(sel).attr("tabindex", "0").focus().addClass("selected"); - }); - //selected = bindingContext.$data.selected(); -} - -function dataChanged(element: any, valueAccessor: any, allBindings: any, viewModel: any, bindingContext: any) { - // do nothing for now -} - -function initializeTable(): void { - updateTableScrollableRegionMetrics(); - initializeEventHandlers(); -} - -function updateTableScrollableRegionMetrics(): void { - updateTableScrollableRegionHeight(); - updateTableScrollableRegionWidth(); -} - -/* - * Update the table's scrollable region height. So the pagination control is always shown at the bottom of the page. - */ -function updateTableScrollableRegionHeight(): void { - $(".tab-pane").each(function (index, tabElement) { - if (!$(tabElement).hasClass("tableContainer")) { - return; - } - - // Add some padding to the table so it doesn't get too close to the container border. - var dataTablePaddingBottom = 10; - var bodyHeight = $(window).height(); - var dataTablesScrollBodyPosY = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector).offset().top; - var dataTablesInfoElem = $(tabElement).find(".dataTables_info"); - var dataTablesPaginateElem = $(tabElement).find(".dataTables_paginate"); - const notificationConsoleHeight = 32; /** Header height **/ - - var scrollHeight = - bodyHeight - - dataTablesScrollBodyPosY - - dataTablesPaginateElem.outerHeight(true) - - dataTablePaddingBottom - - notificationConsoleHeight; - - //info and paginate control are stacked - if (dataTablesInfoElem.offset().top < dataTablesPaginateElem.offset().top) { - scrollHeight -= dataTablesInfoElem.outerHeight(true); - } - - // TODO This is a work around for setting the outerheight since we don't have access to the JQuery.outerheight(numberValue) - // in the current version of JQuery we are using. Ideally, we would upgrade JQuery and use this line instead: - // $(Constants.htmlSelectors.dataTableScrollBodySelector).outerHeight(scrollHeight); - var element = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector)[0]; - var style = getComputedStyle(element); - var actualHeight = parseInt(style.height); - var change = element.offsetHeight - scrollHeight; - $(tabElement) - .find(Constants.htmlSelectors.dataTableScrollBodySelector) - .height(actualHeight - change); - }); -} - -/* - * Update the table's scrollable region width to make efficient use of the remaining space. - */ -function updateTableScrollableRegionWidth(): void { - $(".tab-pane").each(function (index, tabElement) { - if (!$(tabElement).hasClass("tableContainer")) { - return; - } - - var bodyWidth = $(window).width(); - var dataTablesScrollBodyPosLeft = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector).offset() - .left; - var scrollWidth = bodyWidth - dataTablesScrollBodyPosLeft; - - // jquery datatables automatically sets width:100% to both the header and the body when we use it's column autoWidth feature. - // We work around that by setting the height for it's container instead. - $(tabElement).find(Constants.htmlSelectors.dataTableScrollContainerSelector).width(scrollWidth); - }); -} - -function initializeEventHandlers(): void { - var $headers: JQuery = $(Constants.htmlSelectors.dataTableHeaderTypeSelector); - var $firstHeader: JQuery = $headers.first(); - var firstIndex: string = $firstHeader.attr(Constants.htmlAttributeNames.dataTableHeaderIndex); - - $headers - .on("keydown", (event: JQueryEventObject) => { - Utilities.onEnter(event, ($sourceElement: JQuery) => { - $sourceElement.css("background-color", Constants.cssColors.commonControlsButtonActive); - }); - - // Bind shift+tab from first header back to search input field - Utilities.onTab( - event, - ($sourceElement: JQuery) => { - var sourceIndex: string = $sourceElement.attr(Constants.htmlAttributeNames.dataTableHeaderIndex); - - if (sourceIndex === firstIndex) { - event.preventDefault(); - } - }, - /* metaKey */ null, - /* shiftKey */ true, - /* altKey */ null - ); - - // Also reset color if [shift-] tabbing away from button while holding down 'enter' - Utilities.onTab(event, ($sourceElement: JQuery) => { - $sourceElement.css("background-color", ""); - }); - }) - .on("keyup", (event: JQueryEventObject) => { - Utilities.onEnter(event, ($sourceElement: JQuery) => { - $sourceElement.css("background-color", ""); - }); - }); -} - -function updateSelectionStatus(oSettings: any): void { - var $dataTableRows: JQuery = $(Constants.htmlSelectors.dataTableAllRowsSelector); - if ($dataTableRows) { - for (var i = 0; i < $dataTableRows.length; i++) { - var $row: JQuery = $dataTableRows.eq(i); - var rowKey: string = $row.attr(Constants.htmlAttributeNames.dataTableRowKeyAttr); - var table = tableEntityListViewModelMap[oSettings.ajax].tableViewModel; - if (table.isItemSelected(table.getTableEntityKeys(rowKey))) { - $row.attr("tabindex", "0"); - } - } - } - - updateDataTableFocus(oSettings.ajax); - - DataTableOperations.setPaginationButtonEventHandlers(); -} - -// TODO consider centralizing this "post-command" logic into some sort of Command Manager entity. -// See VSO:166520: "[Storage Explorer] Consider adding a 'command manager' to track command post-effects." -function updateDataTableFocus(queryTablesTabId: string): void { - var $activeElement: JQuery = $(document.activeElement); - var isFocusLost: boolean = $activeElement.is("body"); // When focus is lost, "body" becomes the active element. - var storageExplorerFrameHasFocus: boolean = document.hasFocus(); - var operationManager = tableEntityListViewModelMap[queryTablesTabId].operationManager; - if (operationManager) { - if (isFocusLost && storageExplorerFrameHasFocus) { - // We get here when no control is active, meaning that the table update was triggered - // from a dialog, the context menu or by clicking on a toolbar control or header. - // Note that giving focus to the table also selects the first row if needed. - // The document.hasFocus() ensures that the table will only get focus when the - // focus was lost (i.e. "body has the focus") within the Storage Explorer frame - // i.e. not when the focus is lost because it is in another frame - // e.g. a daytona dialog or in the Activity Log. - operationManager.focusTable(); - } - if ($activeElement.is(".sorting_asc") || $activeElement.is(".sorting_desc")) { - // If table header is selected, focus is shifted to the selected element as part of accessibility - $activeElement && $activeElement.focus(); - } else { - // If some control is active, we don't give focus back to the table, - // just select the first row if needed (empty selection). - operationManager.selectFirstIfNeeded(); - } - } -} - -(ko.bindingHandlers).tableSource = { - init: bindDataTable, - update: dataChanged, -}; - -(ko.bindingHandlers).tableSelection = { - update: selectionChanged, -}; - -(ko.bindingHandlers).readOnly = { - update: function (element: any, valueAccessor: any) { - var value = ko.utils.unwrapObservable(valueAccessor()); - if (value) { - element.setAttribute("readOnly", true); - } else { - element.removeAttribute("readOnly"); - } - }, -}; diff --git a/src/Explorer/Tables/DataTable/DataTableViewModel.ts b/src/Explorer/Tables/DataTable/DataTableViewModel.ts index 989c647cd..7f38ea536 100644 --- a/src/Explorer/Tables/DataTable/DataTableViewModel.ts +++ b/src/Explorer/Tables/DataTable/DataTableViewModel.ts @@ -3,7 +3,6 @@ import * as ko from "knockout"; import * as _ from "underscore"; import * as CommonConstants from "../../../Common/Constants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; -// import QueryTablesTab from "../../Tabs/QueryTablesTab"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab"; import * as Constants from "../Constants"; @@ -50,7 +49,6 @@ abstract class DataTableViewModel { private dataTableOperationManager: IDataTableOperation; - // public queryTablesTab: QueryTablesTab; public queryTablesTab: NewQueryTablesTab; constructor() { @@ -173,36 +171,13 @@ abstract class DataTableViewModel { this.cache.sortOrder = sortOrder; } - protected renderPage( - // renderCallBack: any, - // draw: number, - startIndex: number, - pageSize: number - // oSettings: any, - // postRenderTasks: (startIndex: number, pageSize: number) => Promise = null - ) { - // this.updatePaginationControls(oSettings); - - // pageSize < 0 means to show all data + protected renderPage(startIndex: number, pageSize: number) { var endIndex = pageSize < 0 ? this.cache.length : startIndex + pageSize; var renderData = this.cache.data.slice(startIndex, endIndex); this.items(renderData); this.items1 = renderData; - // var render: IDataTableRenderData = { - // draw: draw, - // aaData: renderData, - // recordsTotal: this.cache.length, - // recordsFiltered: this.cache.length, - // }; - - // if (!!postRenderTasks) { - // postRenderTasks(startIndex, pageSize).then(() => { - // this.table.rows().invalidate(); - // }); - // } - // renderCallBack(render); if (this.queryTablesTab.onLoadStartKey != null && this.queryTablesTab.onLoadStartKey != undefined) { TelemetryProcessor.traceSuccess( Action.Tab, @@ -221,16 +196,6 @@ abstract class DataTableViewModel { protected matchesKeys(item: Entities.ITableEntity, itemKeys: Entities.IProperty[]): boolean { return itemKeys.every((property: Entities.IProperty) => { var itemValue = item[property.key]; - - // if (itemValue && property.subkey) { - // itemValue = itemValue._[property.subkey]; - // if (!itemValue) { - // itemValue = ""; - // } - // } else if (property.subkey) { - // itemValue = ""; - // } - return this.stringCompare(itemValue._, property.value); }); } diff --git a/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts b/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts index f8a941350..ee0174168 100644 --- a/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts +++ b/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts @@ -6,7 +6,6 @@ import * as ViewModels from "../../../Contracts/ViewModels"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import { userContext } from "../../../UserContext"; -// import QueryTablesTab from "../../Tabs/QueryTablesTab"; import NewQueryTablesTab from "../../Tabs/QueryTablesTab/QueryTablesTab"; import * as Constants from "../Constants"; import { getQuotedCqlIdentifier } from "../CqlUtilities"; @@ -103,7 +102,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { //public tableExplorerContext: TableExplorerContext; public notifyColumnChanges: (enablePrompt: boolean, queryTablesTab: NewQueryTablesTab) => void; - // public notifyColumnChanges: (enablePrompt: boolean, queryTablesTab: QueryTablesTab) => void; public tablePageStartIndex: number; public tableQuery: Entities.ITableQuery = {}; @@ -115,7 +113,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { public queryErrorMessage: ko.Observable; public id: string; - // constructor(tableCommands: TableCommands, queryTablesTab: QueryTablesTab) { constructor(tableCommands: TableCommands, queryTablesTab: NewQueryTablesTab) { super(); this.cache = new TableEntityCache(); @@ -149,10 +146,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { public updateHeaders(newHeaders: string[], notifyColumnChanges: boolean = false, enablePrompt: boolean = true): void { this.headers = newHeaders; - // if (notifyColumnChanges) { - // this.clearSelection(); - // this.notifyColumnChanges(enablePrompt, this.queryTablesTab); - // } } /** @@ -172,21 +165,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { var prefetchThreshold = 10; var tableQuery = this.tableQuery; - // for (var index in aoData) { - // var data = aoData[index]; - // if (data.name === "length") { - // tablePageSize = data.value; - // } - // if (data.name === "start") { - // this.tablePageStartIndex = data.value; - // } - // if (data.name === "draw") { - // draw = data.value; - // } - // if (data.name === "order") { - // columnSortOrder = data.value; - // } - // } // Try cache if valid. if (this.isCacheValid(tableQuery)) { // Check if prefetch needed. @@ -234,19 +212,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { }); } - // Find the first item which is greater than the added entity. - // var oSettings: any = (this.table).context[0]; - // var index: number = _.findIndex(this.cache.data, (data: any) => { - // return this.dataComparer(data, entity, this.cache.sortOrder, oSettings) > 0; - // }); - - // If no such item, then insert at last. - // var insertIndex: number = Utilities.ensureBetweenBounds( - // index < 0 ? this.cache.length : index, - // 0, - // this.cache.length - // ); - this.cache.data.splice(this.cache.length, 0, entity); // Finally, select newly added entity @@ -297,14 +262,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { }); this.clearSelection(); - // Show last available page if there is not enough data - // var pageInfo = this.table.page.info(); - // if (this.cache.length <= pageInfo.start) { - // var availablePages = Math.ceil(this.cache.length / pageInfo.length); - // var pageToShow = availablePages > 0 ? availablePages - 1 : 0; - // this.table.page(pageToShow); - // } - return Q.resolve(null); } @@ -403,7 +360,6 @@ export default class TableEntityListViewModel extends DataTableViewModel { tablePageSize: number, downloadSize: number, draw: number, - // renderCallBack: Function, oSettings: any, columnSortOrder: any ): void { diff --git a/src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts b/src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts index 3089042d0..2a244c0fa 100644 --- a/src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts +++ b/src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts @@ -114,7 +114,6 @@ export default class QueryBuilderViewModel { "PartitionKey", this.edmTypes()[0], Constants.Operator.Equal, - // this.tableEntityListViewModel.items()[0].PartitionKey._, pk, false, "", @@ -129,7 +128,6 @@ export default class QueryBuilderViewModel { "RowKey", this.edmTypes()[0], Constants.Operator.Equal, - // this.tableEntityListViewModel.items()[0].RowKey._, rk, true, "", @@ -144,13 +142,10 @@ export default class QueryBuilderViewModel { public getODataFilterFromClauses = (queryClauses: IQueryTableRowsType[]): string => { var filterString: string = ""; - // var treeTraversal = (queryClauses: IQueryTableRowsType[]): void => { if (queryClauses != undefined) { for (var i = 0; i < queryClauses.length; i++) { var currentItem = queryClauses[i]; - // if (currentItem instanceof QueryClauseViewModel) { - // var clause = currentItem; this.timestampToValue(currentItem); filterString = filterString.concat( this.constructODataClause( @@ -163,16 +158,8 @@ export default class QueryBuilderViewModel { this.generateRightParentheses(currentItem) ) ); - // } - - // if (currentItem instanceof ClauseGroup) { - // treeTraversal(currentItem); - // } } } - // }; - - // treeTraversal(this.queryClauses); return filterString.trim(); }; @@ -205,12 +192,9 @@ export default class QueryBuilderViewModel { } filterString = filterString.concat(" WHERE"); var first = true; - // var treeTraversal = (group: ClauseGroup): void => { for (var i = 0; i < queryTableRows.length; i++) { var currentItem = queryTableRows[i]; - // if (currentItem instanceof QueryClauseViewModel) { - // var clause = currentItem; let timeStampValue: string = this.timestampToSqlValue(currentItem); var value = currentItem.entityValue; if (!currentItem.isValue) { @@ -228,17 +212,8 @@ export default class QueryBuilderViewModel { ) ); first = false; - // } - - // if (currentItem instanceof ClauseGroup) { - // treeTraversal(currentItem); - // } - // } } - // treeTraversal(this.queryClauses); - - console.log("🚀 ~ file: QueryBuilderViewModel.ts ~ line 250 ~ QueryBuilderViewModel ~ filterString", filterString); return filterString.trim(); }; @@ -262,12 +237,9 @@ export default class QueryBuilderViewModel { } filterString = filterString.concat(" WHERE"); var first = true; - // var treeTraversal = (group: ClauseGroup): void => { for (var i = 0; i < queryTableRows.length; i++) { var currentItem = queryTableRows[i]; - // if (currentItem instanceof QueryClauseViewModel) { - // var clause = currentItem; let timeStampValue: string = this.timestampToSqlValue(currentItem); var value = currentItem.entityValue; if (!currentItem.isValue) { @@ -285,15 +257,7 @@ export default class QueryBuilderViewModel { ) ); first = false; - // } - - if (currentItem instanceof ClauseGroup) { - // treeTraversal(currentItem); - } } - // }; - - // treeTraversal(this.queryClauses); return filterString.trim(); }; @@ -499,7 +463,6 @@ export default class QueryBuilderViewModel { // adds a new clause to the end of the array public addNewClause = (): void => { this.addClauseIndex(this.clauseArray().length, null); - // this.addClauseIndex(queryTableRows.length, null); }; public onAddClauseKeyDown = (index: number, data: any, event: KeyboardEvent, source: any): boolean => { @@ -637,16 +600,11 @@ export default class QueryBuilderViewModel { return groupViewModels; }; - public runQuery = (): DataTables.DataTable => { - return this._queryViewModel.runQuery(); - }; - public addCustomRange(timestamp: CustomTimestampHelper.ITimestampQuery, clauseToAdd: QueryClauseViewModel): void { var index = this.clauseArray.peek().indexOf(clauseToAdd); var newClause = new QueryClauseViewModel( this, - //this._tableEntityListViewModel.tableExplorerContext.hostProxy, "And", clauseToAdd.field(), "DateTime", diff --git a/src/Explorer/Tables/QueryBuilder/QueryViewModel.tsx b/src/Explorer/Tables/QueryBuilder/QueryViewModel.tsx index 834dff4ac..45a169de5 100644 --- a/src/Explorer/Tables/QueryBuilder/QueryViewModel.tsx +++ b/src/Explorer/Tables/QueryBuilder/QueryViewModel.tsx @@ -41,11 +41,9 @@ export default class QueryViewModel { public columnOptions: ko.ObservableArray; public queryTablesTab: NewQueryTablesTab; - // public queryTablesTab: QueryTablesTab; public id: string; private _tableEntityListViewModel: TableEntityListViewModel; - // constructor(queryTablesTab: QueryTablesTab) { constructor(queryTablesTab: NewQueryTablesTab) { this.queryTablesTab = queryTablesTab; this.id = `queryViewModel${this.queryTablesTab.tabId}`; @@ -106,7 +104,7 @@ export default class QueryViewModel { DataTableUtilities.forceRecalculateTableSize(); }; - public toggleAdvancedOptions = () => { + public toggleAdvancedOptions = (): void => { this.isExpanded(!this.isExpanded()); if (this.isExpanded()) { this.focusTopResult(true); @@ -129,7 +127,7 @@ export default class QueryViewModel { return this.selectText(); }; - private setFilter = (queryTableRows: IQueryTableRowsType[]): string => { + private setFilter = (queryTableRows?: IQueryTableRowsType[]): string => { const queryString = this.isEditorActive() ? this.queryText() : userContext.apiType === "Cassandra" @@ -144,10 +142,6 @@ export default class QueryViewModel { return this.queryBuilderViewModel().getSqlFilterFromClauses(queryTableRows); }; - // private setCqlFilter = (): string => { - // return this.queryBuilderViewModel().getCqlFilterFromClauses(); - // }; - public isHelperEnabled = ko .computed(() => { return ( @@ -162,15 +156,8 @@ export default class QueryViewModel { }); public runQuery = (queryTableRows: IQueryTableRowsType[]): string => { - console.log( - "🚀 ~ file: QueryViewModel.tsx ~ line 169 ~ QueryViewModel ~ //constructor ~ queryTableRows", - queryTableRows - ); let filter = this.setFilter(queryTableRows); - console.log( - "🚀 ~ file: QueryViewModel.tsx ~ line 171 ~ QueryViewModel ~ //constructor ~ userContext.apiType", - userContext.apiType - ); + if (filter && userContext.apiType !== "Cassandra") { filter = filter.replace(/"/g, "'"); } @@ -187,7 +174,6 @@ export default class QueryViewModel { return userContext.apiType !== "Cassandra" ? this._tableEntityListViewModel.sqlQuery() : this._tableEntityListViewModel.cqlQuery(); - // return this._tableEntityListViewModel.reloadTable(/*useSetting*/ false, /*resetHeaders*/ false); }; public clearQuery = (): DataTables.DataTable => { diff --git a/src/Explorer/Tabs/QueryTablesTab.html b/src/Explorer/Tabs/QueryTablesTab.html deleted file mode 100644 index 97bd77016..000000000 --- a/src/Explorer/Tabs/QueryTablesTab.html +++ /dev/null @@ -1,271 +0,0 @@ -
- -
- -
-
- - -
-
- - -
-
- -
-
- - -
-
-
- - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
-
-
-
- - Add new clause - - -
-
-
-
- - -
-
- - -
- toggle -
- - -
- toggle -
- - Advanced Options -
-
-
-
- Show top results: - - -
-
- Select fields for query: -
- - -
- - Choose Columns... - -
-
-
- -
- -
- -
-
-
- - - - - - diff --git a/src/Explorer/Tabs/QueryTablesTab.tsx b/src/Explorer/Tabs/QueryTablesTab.tsx deleted file mode 100644 index b48a6a10e..000000000 --- a/src/Explorer/Tabs/QueryTablesTab.tsx +++ /dev/null @@ -1,283 +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(); - public queryViewModel = ko.observable(); - 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(() => { - return true; - }), - - visible: ko.computed(() => { - return true; - }), - }; - - this.queryBuilderButton = { - enabled: ko.computed(() => { - return true; - }), - - visible: ko.computed(() => { - return true; - }), - - isSelected: ko.computed(() => { - return this.queryViewModel() ? this.queryViewModel().isHelperActive() : false; - }), - }; - - this.queryTextButton = { - enabled: ko.computed(() => { - return true; - }), - - visible: ko.computed(() => { - return true; - }), - - isSelected: ko.computed(() => { - return this.queryViewModel() ? this.queryViewModel().isEditorActive() : false; - }), - }; - - this.addEntityButton = { - enabled: ko.computed(() => { - return true; - }), - - visible: ko.computed(() => { - return true; - }), - }; - - this.editEntityButton = { - enabled: ko.computed(() => { - return this.tableCommands.isEnabled( - TableCommands.editEntityCommand, - this.tableEntityListViewModel().selected() - ); - }), - - visible: ko.computed(() => { - return true; - }), - }; - - this.deleteEntityButton = { - enabled: ko.computed(() => { - return this.tableCommands.isEnabled( - TableCommands.deleteEntitiesCommand, - this.tableEntityListViewModel().selected() - ); - }), - - visible: ko.computed(() => { - return true; - }), - }; - - this.buildCommandBarOptions(); - } - - public onAddEntityClick = (): void => { - useSidePanel - .getState() - .openSidePanel( - "Add Table Entity", - - ); - }; - - public onEditEntityClick = (): void => { - useSidePanel - .getState() - .openSidePanel( - "Edit Table Entity", - - ); - }; - - 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(); - } -} diff --git a/src/Explorer/Tabs/QueryTablesTab/QueryTablesTab.tsx b/src/Explorer/Tabs/QueryTablesTab/QueryTablesTab.tsx index fedc5226a..5c60664d9 100644 --- a/src/Explorer/Tabs/QueryTablesTab/QueryTablesTab.tsx +++ b/src/Explorer/Tabs/QueryTablesTab/QueryTablesTab.tsx @@ -4,7 +4,8 @@ import Explorer from "../../Explorer"; import TableCommands from "../../Tables/DataTable/TableCommands"; import TableEntityListViewModel from "../../Tables/DataTable/TableEntityListViewModel"; import TabsBase from "../TabsBase"; -import QueryTablesTabComponent, { IQueryTablesTabComponentProps } from "./QueryTablesTabComponent"; +import QueryTablesTabComponent from "./QueryTablesTabComponent"; +import { IQueryTablesTabComponentProps } from "./QueryTableTabUtils"; interface QueryTablesTabProps { container: Explorer; diff --git a/src/Explorer/Tabs/QueryTablesTab/QueryTablesTabComponent.tsx b/src/Explorer/Tabs/QueryTablesTab/QueryTablesTabComponent.tsx index 1d8446cbd..aaabeade8 100644 --- a/src/Explorer/Tabs/QueryTablesTab/QueryTablesTabComponent.tsx +++ b/src/Explorer/Tabs/QueryTablesTab/QueryTablesTabComponent.tsx @@ -521,7 +521,6 @@ class QueryTablesTabComponent extends Component