Compare commits

..

4 Commits

Author SHA1 Message Date
vaidankarswapnil
e55e2b9fe3 Removed comment from eslintignore file 2021-10-18 16:08:01 +05:30
vaidankarswapnil
0c1f6d2a80 Fix eslint issues for NotebookContentLient and other files 2021-10-18 13:39:56 +05:30
victor-meng
55837db65b Revert "Fix keyboard focus does not retain on 'New Database' button a… (#1139)
* Revert "Fix keyboard focus does not retain on 'New Database' button after closing the 'New Database' blade via ESC key (#1109)"

This reverts commit f7e7240010.

* Revert "Fix ally database panel open issue (#1120)"

This reverts commit ed1ffb692f.
2021-10-15 17:36:48 -07:00
victor-meng
9f27cb95b9 Only use the SET keyword once in the update query (#1138) 2021-10-15 12:33:59 -07:00
11 changed files with 111 additions and 123 deletions

View File

@@ -42,8 +42,6 @@ src/Explorer/Controls/Editor/EditorComponent.ts
src/Explorer/Controls/JsonEditor/JsonEditorComponent.ts
src/Explorer/DataSamples/ContainerSampleGenerator.test.ts
src/Explorer/DataSamples/ContainerSampleGenerator.ts
src/Explorer/DataSamples/DataSamplesUtil.test.ts
src/Explorer/DataSamples/DataSamplesUtil.ts
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts
@@ -54,8 +52,6 @@ src/Explorer/Graph/GraphExplorerComponent/GraphData.ts
src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts
src/Explorer/Graph/GraphExplorerComponent/GremlinClient.ts
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.test.ts
src/Explorer/Graph/GraphExplorerComponent/GremlinSimpleClient.ts
src/Explorer/Menus/ContextMenu.ts
src/Explorer/MostRecentActivity/MostRecentActivity.ts
src/Explorer/Notebook/NotebookClientV2.ts
src/Explorer/Notebook/NotebookComponent/NotebookContentProvider.ts
@@ -64,16 +60,18 @@ src/Explorer/Notebook/NotebookComponent/actions.ts
src/Explorer/Notebook/NotebookComponent/epics.test.ts
src/Explorer/Notebook/NotebookComponent/epics.ts
src/Explorer/Notebook/NotebookComponent/loadTransform.ts
src/Explorer/Notebook/NotebookComponent/reducers.ts
src/Explorer/Notebook/NotebookComponent/store.ts
src/Explorer/Notebook/NotebookComponent/types.ts
src/Explorer/Notebook/NotebookContainerClient.ts
src/Explorer/Notebook/NotebookContentItem.ts
src/Explorer/Notebook/NotebookUtil.ts
src/Explorer/OpenActionsStubs.ts
src/Explorer/Panes/Tables/Validators/EntityPropertyNameValidator.ts
src/Explorer/Panes/Tables/Validators/EntityPropertyValidationCommon.ts
src/Explorer/Panes/Tables/Validators/EntityPropertyValueValidator.ts
src/Explorer/SplashScreen/SplashScreen.test.ts
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/DataTableViewModel.ts

View File

@@ -19,7 +19,7 @@ describe("DataSampleUtils", () => {
const explorer = {} as Explorer;
useDatabases.getState().addDatabases([database]);
const dataSamplesUtil = new DataSamplesUtil(explorer);
//eslint-disable-next-line
const fakeGenerator = sinon.createStubInstance<ContainerSampleGenerator>(ContainerSampleGenerator as any);
fakeGenerator.getCollectionId.returns(sampleCollectionId);
fakeGenerator.getDatabaseId.returns(sampleDatabaseId);

View File

@@ -18,6 +18,7 @@ export interface GremlinSimpleClientParameters {
export interface Result {
requestId: string; // Can be null
//eslint-disable-next-line
data: any;
requestCharge: number; // RU cost
}
@@ -30,6 +31,7 @@ export interface GremlinRequestMessage {
args:
| {
gremlin: string;
//eslint-disable-next-line
bindings: {};
language: string;
}
@@ -54,6 +56,7 @@ export interface GremlinResponseMessage {
message: string;
};
result: {
//eslint-disable-next-line
data: any;
};
}
@@ -74,7 +77,7 @@ export class GremlinSimpleClient {
this.requestsToSend = {};
}
public connect() {
public connect(): void {
if (this.ws) {
if (this.ws.readyState === WebSocket.CONNECTING) {
// Wait until it connects to execute all requests
@@ -106,9 +109,10 @@ export class GremlinSimpleClient {
return new WebSocket(endpoint);
}
public close() {
public close(): void {
if (this.ws && this.ws.readyState !== WebSocket.CLOSING && this.ws.readyState !== WebSocket.CLOSED) {
const msg = `Disconnecting from ${this.params.endpoint} as ${this.params.user}`;
//eslint-disable-next-line
console.log(msg);
if (this.params.infoCallback) {
this.params.infoCallback(msg);
@@ -143,7 +147,7 @@ export class GremlinSimpleClient {
}
}
public onMessage(msg: MessageEvent) {
public onMessage(msg: MessageEvent): void {
if (!msg) {
if (this.params.failureCallback) {
this.params.failureCallback(null, "onMessage called with no message");
@@ -194,8 +198,10 @@ export class GremlinSimpleClient {
}
break;
case 407: // Request authentication
const challengeResponse = this.buildChallengeResponse(this.pendingRequests[requestId]);
this.sendGremlinMessage(challengeResponse);
{
const challengeResponse = this.buildChallengeResponse(this.pendingRequests[requestId]);
this.sendGremlinMessage(challengeResponse);
}
break;
case 401: // Unauthorized
delete this.pendingRequests[requestId];
@@ -267,7 +273,7 @@ export class GremlinSimpleClient {
}
public buildChallengeResponse(request: GremlinRequestMessage): GremlinRequestMessage {
var args = {
const args = {
SASL: GremlinSimpleClient.utf8ToB64("\0" + this.params.user + "\0" + this.params.password),
};
return {
@@ -278,9 +284,9 @@ export class GremlinSimpleClient {
};
}
public static utf8ToB64(utf8Str: string) {
public static utf8ToB64(utf8Str: string): string {
return btoa(
encodeURIComponent(utf8Str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
encodeURIComponent(utf8Str).replace(/%([0-9A-F]{2})/g, (match, p1) => {
return String.fromCharCode(parseInt(p1, 16));
})
);
@@ -291,12 +297,13 @@ export class GremlinSimpleClient {
* mimeLength + mimeType + serialized message
* @param requestMessage
*/
//eslint-disable-next-line
public static buildGremlinMessage(requestMessage: {}): Uint8Array {
const mimeType = "application/json";
let serializedMessage = mimeType + JSON.stringify(requestMessage);
const serializedMessage = mimeType + JSON.stringify(requestMessage);
const encodedMessage = new TextEncoder().encode(serializedMessage);
let binaryMessage = new Uint8Array(1 + encodedMessage.length);
const binaryMessage = new Uint8Array(1 + encodedMessage.length);
binaryMessage[0] = mimeType.length;
for (let i = 0; i < encodedMessage.length; i++) {
@@ -305,19 +312,19 @@ export class GremlinSimpleClient {
return binaryMessage;
}
private onOpen(event: any) {
private onOpen() {
this.executeRequestsToSend();
}
private executeRequestsToSend() {
for (let requestId in this.requestsToSend) {
for (const requestId in this.requestsToSend) {
const request = this.requestsToSend[requestId];
this.sendGremlinMessage(request);
this.pendingRequests[request.requestId] = request;
delete this.requestsToSend[request.requestId];
}
}
//eslint-disable-next-line
private onError(err: any) {
if (this.params.failureCallback) {
this.params.failureCallback(null, err);
@@ -339,9 +346,9 @@ export class GremlinSimpleClient {
* RFC4122 version 4 compliant UUID
*/
private static uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0,
v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}

View File

@@ -307,18 +307,11 @@ function createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonCo
function createNewDatabase(container: Explorer): CommandButtonComponentProps {
const label = "New " + getDatabaseName();
const newDatabaseButton = document.activeElement as HTMLElement;
return {
iconSrc: AddDatabaseIcon,
iconAlt: label,
onCommandClick: () =>
useSidePanel
.getState()
.openSidePanel(
"New " + getDatabaseName(),
<AddDatabasePanel explorer={container} buttonElement={newDatabaseButton} />
),
useSidePanel.getState().openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={container} />),
commandButtonLabel: label,
ariaLabel: label,
hasPopup: true,

View File

@@ -50,6 +50,7 @@ export const coreReducer = (state: CoreRecord, action: Action) => {
.setIn(path.concat("language"), kernelspecs.language);
}
default:
//eslint-disable-next-line
return nteractReducers.core(state as any, action as any);
}
};

View File

@@ -12,7 +12,6 @@ import { NotebookContentItem, NotebookContentItemType } from "./NotebookContentI
// Must match rx-jupyter' FileType
export type FileType = "directory" | "file" | "notebook";
// Utilities for notebooks
//eslint-disable-next-line
export class NotebookUtil {
public static UntrustedNotebookRunHint = "Please trust notebook first before running any code cells";
@@ -191,7 +190,6 @@ export class NotebookUtil {
subSnapshots: SnapshotFragment[],
downloadFilename?: string
): Promise<{ imageSrc: string | undefined }> => {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
try {
// target.scrollIntoView();
@@ -260,7 +258,6 @@ export class NotebookUtil {
subSnapshots: SnapshotFragment[],
downloadFilename?: string
): Promise<{ imageSrc?: string }> => {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
// target.scrollIntoView();
try {

View File

@@ -23,12 +23,10 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
export interface AddDatabasePaneProps {
explorer: Explorer;
buttonElement?: HTMLElement;
}
export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
explorer: container,
buttonElement,
}: AddDatabasePaneProps) => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
let throughput: number;
@@ -79,7 +77,6 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
dataExplorerArea: Constants.Areas.ContextualPane,
};
TelemetryProcessor.trace(Action.CreateDatabase, ActionModifiers.Open, addDatabasePaneOpenMessage);
buttonElement.focus();
}, []);
const onSubmit = () => {

View File

@@ -307,23 +307,16 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
iconSrc: AddDatabaseIcon,
title: "New " + getDatabaseName(),
description: undefined,
onClick: () => this.openAddDatabasePanel(),
onClick: () =>
useSidePanel
.getState()
.openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={this.container} />),
});
}
return items;
}
private openAddDatabasePanel() {
const newDatabaseButton = document.activeElement as HTMLElement;
useSidePanel
.getState()
.openSidePanel(
"New " + getDatabaseName(),
<AddDatabasePanel explorer={this.container} buttonElement={newDatabaseButton} />
);
}
private decorateOpenCollectionActivity({ databaseId, collectionId }: MostRecentActivity.OpenCollectionItem) {
return {
iconSrc: NotebookIcon,

View File

@@ -1,18 +1,20 @@
import * as ko from "knockout";
import * as _ from "underscore";
import QueryTablesTab from "../../Tabs/QueryTablesTab";
import * as Constants from "../Constants";
import * as Entities from "../Entities";
import * as Utilities from "../Utilities";
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
*/
const tableEntityListViewModelMap: {
var tableEntityListViewModelMap: {
[key: string]: {
tableViewModel: TableEntityListViewModel;
operationManager: DataTableOperationManager;
@@ -20,13 +22,12 @@ const tableEntityListViewModelMap: {
};
} = {};
//eslint-disable-next-line
function bindDataTable(element: any, bindingContext: any) {
const tableEntityListViewModel = bindingContext.$data;
function bindDataTable(element: any, valueAccessor: any, allBindings: any, viewModel: any, bindingContext: any) {
var tableEntityListViewModel = bindingContext.$data;
tableEntityListViewModel.notifyColumnChanges = onTableColumnChange;
const $dataTable = $(element);
const queryTablesTab = bindingContext.$parent;
const operationManager = new DataTableOperationManager(
var $dataTable = $(element);
var queryTablesTab = bindingContext.$parent;
var operationManager = new DataTableOperationManager(
$dataTable,
tableEntityListViewModel,
queryTablesTab.tableCommands
@@ -43,9 +44,9 @@ function bindDataTable(element: any, bindingContext: any) {
operationManager.focusTable(); // Also selects the first row if needed.
}
function onTableColumnChange(queryTablesTab: QueryTablesTab) {
const columnsFilter: boolean[] = null;
const tableEntityListViewModel = tableEntityListViewModelMap[queryTablesTab.tabId].tableViewModel;
function onTableColumnChange(enablePrompt: boolean = true, queryTablesTab: QueryTablesTab) {
var columnsFilter: boolean[] = null;
var tableEntityListViewModel = tableEntityListViewModelMap[queryTablesTab.tabId].tableViewModel;
if (queryTablesTab.queryViewModel()) {
queryTablesTab.queryViewModel().queryBuilderViewModel().updateColumnOptions();
}
@@ -62,36 +63,35 @@ function createDataTable(
startIndex: number,
tableEntityListViewModel: TableEntityListViewModel,
queryTablesTab: QueryTablesTab,
destroy = false,
destroy: boolean = false,
columnsFilter: boolean[] = null
): void {
const $dataTable = tableEntityListViewModelMap[queryTablesTab.tabId].$dataTable;
var $dataTable = tableEntityListViewModelMap[queryTablesTab.tabId].$dataTable;
if (destroy) {
// Find currently displayed columns.
const currentColumns: string[] = tableEntityListViewModel.headers;
var currentColumns: string[] = tableEntityListViewModel.headers;
// Calculate how many more columns need to added to the current table.
const columnsToAdd: number = _.difference(tableEntityListViewModel.headers, currentColumns).length;
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 (let i = 0; i < columnsToAdd; i++) {
for (var i = 0; i < columnsToAdd; i++) {
$(".dataTables_scrollHead table thead tr th").eq(0).after("<th></th>");
}
tableEntityListViewModel.table.destroy();
$dataTable.empty();
}
const jsonColTable = [];
var jsonColTable = [];
for (let i = 0; i < tableEntityListViewModel.headers.length; i++) {
for (var i = 0; i < tableEntityListViewModel.headers.length; i++) {
jsonColTable.push({
sTitle: tableEntityListViewModel.headers[i],
data: tableEntityListViewModel.headers[i],
aTargets: [i],
mRender: bindColumn,
// eslint-disable-next-line no-extra-boolean-cast
visible: !!columnsFilter ? columnsFilter[i] : true,
});
}
@@ -154,10 +154,9 @@ function createDataTable(
table.setAttribute("summary", `Results for container ${tableEntityListViewModel.queryTablesTab.collection.id()}`);
});
}
//eslint-disable-next-line
function bindColumn(data: any) {
//eslint-disable-next-line
let displayedValue: any = null;
function bindColumn(data: any, type: string, full: any) {
var displayedValue: any = null;
if (data) {
displayedValue = data._;
@@ -174,7 +173,7 @@ function bindColumn(data: any) {
}
return displayedValue;
}
//eslint-disable-next-line
function getServerData(sSource: any, aoData: any, fnCallback: any, oSettings: any) {
tableEntityListViewModelMap[oSettings.ajax].tableViewModel.renderNextPageAndupdateCache(
sSource,
@@ -192,15 +191,15 @@ function bindClientId(nRow: Node, aData: Entities.ITableEntity) {
$(nRow).attr(Constants.htmlAttributeNames.dataTableRowKeyAttr, aData.RowKey._);
return nRow;
}
//eslint-disable-next-line
function selectionChanged(bindingContext: any) {
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) => {
const sel = DataTableOperations.getRowSelector([
var sel = DataTableOperations.getRowSelector([
{
key: Constants.htmlAttributeNames.dataTableRowKeyAttr,
value: b.RowKey && b.RowKey._ && b.RowKey._.toString(),
@@ -212,7 +211,7 @@ function selectionChanged(bindingContext: any) {
//selected = bindingContext.$data.selected();
}
function dataChanged() {
function dataChanged(element: any, valueAccessor: any, allBindings: any, viewModel: any, bindingContext: any) {
// do nothing for now
}
@@ -230,21 +229,20 @@ function updateTableScrollableRegionMetrics(): void {
* 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((index, tabElement) => {
$(".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.
const dataTablePaddingBottom = 10;
const bodyHeight = $(window).height();
const dataTablesScrollBodyPosY = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector).offset()
.top;
const dataTablesInfoElem = $(tabElement).find(".dataTables_info");
const dataTablesPaginateElem = $(tabElement).find(".dataTables_paginate");
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 **/
let scrollHeight =
var scrollHeight =
bodyHeight -
dataTablesScrollBodyPosY -
dataTablesPaginateElem.outerHeight(true) -
@@ -259,10 +257,10 @@ function updateTableScrollableRegionHeight(): void {
// 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);
const element = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector)[0];
const style = getComputedStyle(element);
const actualHeight = parseInt(style.height);
const change = element.offsetHeight - 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);
@@ -273,15 +271,15 @@ function updateTableScrollableRegionHeight(): void {
* Update the table's scrollable region width to make efficient use of the remaining space.
*/
function updateTableScrollableRegionWidth(): void {
$(".tab-pane").each((index, tabElement) => {
$(".tab-pane").each(function (index, tabElement) {
if (!$(tabElement).hasClass("tableContainer")) {
return;
}
const bodyWidth = $(window).width();
const dataTablesScrollBodyPosLeft = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector).offset()
var bodyWidth = $(window).width();
var dataTablesScrollBodyPosLeft = $(tabElement).find(Constants.htmlSelectors.dataTableScrollBodySelector).offset()
.left;
const scrollWidth = bodyWidth - dataTablesScrollBodyPosLeft;
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.
@@ -290,9 +288,9 @@ function updateTableScrollableRegionWidth(): void {
}
function initializeEventHandlers(): void {
const $headers: JQuery = $(Constants.htmlSelectors.dataTableHeaderTypeSelector);
const $firstHeader: JQuery = $headers.first();
const firstIndex: string = $firstHeader.attr(Constants.htmlAttributeNames.dataTableHeaderIndex);
var $headers: JQuery = $(Constants.htmlSelectors.dataTableHeaderTypeSelector);
var $firstHeader: JQuery = $headers.first();
var firstIndex: string = $firstHeader.attr(Constants.htmlAttributeNames.dataTableHeaderIndex);
$headers
.on("keydown", (event: JQueryEventObject) => {
@@ -304,7 +302,7 @@ function initializeEventHandlers(): void {
Utilities.onTab(
event,
($sourceElement: JQuery) => {
const sourceIndex: string = $sourceElement.attr(Constants.htmlAttributeNames.dataTableHeaderIndex);
var sourceIndex: string = $sourceElement.attr(Constants.htmlAttributeNames.dataTableHeaderIndex);
if (sourceIndex === firstIndex) {
event.preventDefault();
@@ -326,14 +324,14 @@ function initializeEventHandlers(): void {
});
});
}
//eslint-disable-next-line
function updateSelectionStatus(oSettings: any): void {
const $dataTableRows: JQuery = $(Constants.htmlSelectors.dataTableAllRowsSelector);
var $dataTableRows: JQuery = $(Constants.htmlSelectors.dataTableAllRowsSelector);
if ($dataTableRows) {
for (let i = 0; i < $dataTableRows.length; i++) {
const $row: JQuery = $dataTableRows.eq(i);
const rowKey: string = $row.attr(Constants.htmlAttributeNames.dataTableRowKeyAttr);
const table = tableEntityListViewModelMap[oSettings.ajax].tableViewModel;
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");
}
@@ -348,10 +346,10 @@ function updateSelectionStatus(oSettings: any): void {
// 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 {
const $activeElement: JQuery = $(document.activeElement);
const isFocusLost: boolean = $activeElement.is("body"); // When focus is lost, "body" becomes the active element.
const storageExplorerFrameHasFocus: boolean = document.hasFocus();
const operationManager = tableEntityListViewModelMap[queryTablesTabId].operationManager;
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
@@ -373,20 +371,19 @@ function updateDataTableFocus(queryTablesTabId: string): void {
}
}
}
//eslint-disable-next-line
(<any>ko.bindingHandlers).tableSource = {
init: bindDataTable,
update: dataChanged,
};
//eslint-disable-next-line
(<any>ko.bindingHandlers).tableSelection = {
update: selectionChanged,
};
//eslint-disable-next-line
(<any>ko.bindingHandlers).readOnly = {
//eslint-disable-next-line
update: (element: any, valueAccessor: any) => {
const value = ko.utils.unwrapObservable(valueAccessor());
update: function (element: any, valueAccessor: any) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (value) {
element.setAttribute("readOnly", true);
} else {

View File

@@ -8,7 +8,7 @@ import * as Utilities from "../Utilities";
* @param{$dataTableElem} JQuery data table element
* @param{$settings} Settings to use when creating the data table
*/
export function createDataTable($dataTableElem: JQuery, settings: DataTables.Settings): DataTables.DataTable {
export function createDataTable($dataTableElem: JQuery, settings: any): DataTables.DataTable {
return $dataTableElem.DataTable(applyDefaultRendering(settings));
}
@@ -18,9 +18,8 @@ export function createDataTable($dataTableElem: JQuery, settings: DataTables.Set
* @param{settings} The settings to check
* @return The given settings with all columns having a rendering function
*/
//eslint-disable-next-line
function applyDefaultRendering(settings: any): DataTables.SettingsLegacy {
let tableColumns: DataTables.ColumnLegacy[] = null;
var tableColumns: DataTables.ColumnLegacy[] = null;
if (settings.aoColumns) {
tableColumns = settings.aoColumns;
@@ -35,7 +34,7 @@ function applyDefaultRendering(settings: any): DataTables.SettingsLegacy {
return settings;
}
for (let i = 0; i < tableColumns.length; i++) {
for (var i = 0; i < tableColumns.length; i++) {
// the column does not have a render function
if (!tableColumns[i].mRender) {
tableColumns[i].mRender = defaultDataRender;
@@ -48,7 +47,6 @@ function applyDefaultRendering(settings: any): DataTables.SettingsLegacy {
* 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.
*/
//eslint-disable-next-line
function defaultDataRender(data: any) {
function defaultDataRender(data: any, type: string, full: any) {
return Utilities.htmlEncode(data);
}

View File

@@ -202,14 +202,21 @@ export class CassandraAPIDataClient extends TableDataClient {
let updateQuery = `UPDATE ${collection.databaseId}.${collection.id()}`;
let isPropertyUpdated = false;
let isFirstPropertyToUpdate = true;
for (let property in newEntity) {
if (
!originalDocument[property] ||
newEntity[property]._.toString() !== originalDocument[property]._.toString()
) {
updateQuery += this.isStringType(newEntity[property].$)
? ` SET ${property} = '${newEntity[property]._}',`
: ` SET ${property} = ${newEntity[property]._},`;
let propertyQuerySegment = this.isStringType(newEntity[property].$)
? `${property} = '${newEntity[property]._}',`
: `${property} = ${newEntity[property]._},`;
// Only add the "SET" keyword once
if (isFirstPropertyToUpdate) {
propertyQuerySegment = " SET " + propertyQuerySegment;
isFirstPropertyToUpdate = false;
}
updateQuery += propertyQuerySegment;
isPropertyUpdated = true;
}
}