Compare commits

..

3 Commits

Author SHA1 Message Date
vaidankarswapnil
5b6a1b345f Fix eslint issues for D3ForceGraph and test file 2021-10-19 13:54:57 +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
9 changed files with 155 additions and 162 deletions

View File

@@ -46,8 +46,8 @@ 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
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts
# src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts
# src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts
src/Explorer/Graph/GraphExplorerComponent/EdgeInfoCache.ts
src/Explorer/Graph/GraphExplorerComponent/GraphData.test.ts
src/Explorer/Graph/GraphExplorerComponent/GraphData.ts
@@ -80,10 +80,10 @@ 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/DataTableOperationManager.ts
src/Explorer/Tables/DataTable/DataTableViewModel.ts
src/Explorer/Tables/DataTable/TableEntityListViewModel.ts
# src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts
src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts
src/Explorer/Tables/TableDataClient.ts
src/Explorer/Tables/TableEntityProcessor.ts
src/Explorer/Tables/Utilities.ts

View File

@@ -1,4 +1,5 @@
import * as sinon from "sinon";
/*eslint-disable jest/no-test-callback */
import * as sinon from "sinon";
import GraphTab from "../../Tabs/GraphTab";
import { D3Link, D3Node, GraphData } from "../GraphExplorerComponent/GraphData";
import { D3ForceGraph, D3GraphNodeData, LoadMoreDataAction } from "./D3ForceGraph";
@@ -70,6 +71,7 @@ describe("D3ForceGraph", () => {
forceGraph = new D3ForceGraph({
igraphConfig: GraphTab.createIGraphConfig(),
onHighlightedNode: sinon.spy(),
//eslint-disable-next-line
onLoadMoreData: (action: LoadMoreDataAction): void => {},
// parent to graph

View File

@@ -1,4 +1,6 @@
import { BaseType } from "d3";
/*eslint-disable @typescript-eslint/no-explicit-any*/
/*eslint-disable @typescript-eslint/no-this-alias*/
import { BaseType } from "d3";
import { map as d3Map } from "d3-collection";
import { D3DragEvent, drag } from "d3-drag";
import { forceCollide, forceLink, forceManyBody, forceSimulation } from "d3-force";
@@ -261,10 +263,10 @@ export class D3ForceGraph implements GraphRenderer {
return;
}
var self = this;
const self = this;
// Select this node id
selectAll(".node")
.filter(function (d: D3Node, i) {
.filter((d: D3Node) => {
return d.id === newVal;
})
.each(function (d: D3Node) {
@@ -277,15 +279,15 @@ export class D3ForceGraph implements GraphRenderer {
} // initialize
private updateUniqueValues(key: string) {
for (var i = 0; i < this.graphDataWrapper.vertices.length; i++) {
let vertex = this.graphDataWrapper.vertices[i];
for (let i = 0; i < this.graphDataWrapper.vertices.length; i++) {
const vertex = this.graphDataWrapper.vertices[i];
let props = D3ForceGraph.getNodeProperties(vertex);
const props = D3ForceGraph.getNodeProperties(vertex);
if (props.indexOf(key) === -1) {
// Vertex doesn't have the property
continue;
}
let val = GraphData.getNodePropValue(vertex, key);
const val = GraphData.getNodePropValue(vertex, key);
if (typeof val !== "string" && typeof val !== "number") {
// Not a type we can map
continue;
@@ -313,7 +315,7 @@ export class D3ForceGraph implements GraphRenderer {
*/
private static getNodeProperties(node: D3Node): string[] {
let props = ["id", "label"];
//eslint-disable-next-line
if (node.hasOwnProperty("properties")) {
props = props.concat(Object.keys(node.properties));
}
@@ -405,7 +407,7 @@ export class D3ForceGraph implements GraphRenderer {
// Remember nodes current position
const posMap = new Map<string, Point2D>();
this.simulation.nodes().forEach((d: D3Node) => {
if (d.x == undefined || d.y == undefined) {
if (d.x === undefined || d.y === undefined) {
return;
}
posMap.set(d.id, { x: d.x, y: d.y });
@@ -549,7 +551,7 @@ export class D3ForceGraph implements GraphRenderer {
.transition()
.delay(D3ForceGraph.TRANSITION_STEP3_MS - 100)
.duration(D3ForceGraph.TRANSITION_STEP3_MS)
.attrTween("fill", (t: any) => {
.attrTween("fill", () => {
const ic = interpolate("#ffffff", "#000000");
return (t: number) => {
return ic(t);
@@ -567,7 +569,7 @@ export class D3ForceGraph implements GraphRenderer {
// Distribute nodes initial position before simulation
const nodes = graph.vertices;
for (let i = 0; i < nodes.length; i++) {
let v = nodes[i];
const v = nodes[i];
if (v._isRoot) {
this.rootVertex = v;
@@ -611,6 +613,20 @@ export class D3ForceGraph implements GraphRenderer {
const self = this;
const ticked = () => {
self.linkSelection.select(".link").attr("d", (l: D3Link) => {
return self.positionLink(l);
});
if (!D3ForceGraph.useSvgMarkerEnd()) {
self.linkSelection.select(".markerEnd").attr("transform", (l: D3Link) => {
return self.positionLinkEnd(l);
});
}
self.nodeSelection.attr("transform", (d: D3Node) => {
return self.positionNode(d);
});
};
this.simulation.nodes(nodes).on("tick", ticked);
this.simulation.force<d3.ForceLink<D3Node, D3Link>>("link").links(graph.edges);
@@ -634,20 +650,6 @@ export class D3ForceGraph implements GraphRenderer {
this.simulation.alpha(1).restart();
this.params.onGraphUpdated(new Date().getTime());
});
function ticked() {
self.linkSelection.select(".link").attr("d", (l: D3Link) => {
return self.positionLink(l);
});
if (!D3ForceGraph.useSvgMarkerEnd()) {
self.linkSelection.select(".markerEnd").attr("transform", (l: D3Link) => {
return self.positionLinkEnd(l);
});
}
self.nodeSelection.attr("transform", (d: D3Node) => {
return self.positionNode(d);
});
}
}
private addNewLinks(): d3.Selection<Element, any, any, any> {
@@ -677,7 +679,7 @@ export class D3ForceGraph implements GraphRenderer {
}
private addNewNodes(): d3.Selection<Element, any, any, any> {
var self = this;
const self = this;
const newNodes = this.nodeSelection
.enter()
@@ -705,7 +707,7 @@ export class D3ForceGraph implements GraphRenderer {
this.highlightNode(this, d);
this.simulation.stop();
})
.on("mouseout", (_: MouseEvent, d: D3Node) => {
.on("mouseout", () => {
if (this.isHighlightDisabled || this.selectedNode || this.isDragging) {
return;
}
@@ -726,7 +728,7 @@ export class D3ForceGraph implements GraphRenderer {
.attr("class", "main")
.attr("r", this.igraphConfig.nodeSize);
var iconGroup = newNodes
const iconGroup = newNodes
.append("g")
.attr("class", "iconContainer")
.attr("tabindex", 0)
@@ -749,8 +751,8 @@ export class D3ForceGraph implements GraphRenderer {
self.onNodeClicked(this.parentNode, d);
}
});
var nodeSize = this.igraphConfig.nodeSize;
var bgsize = nodeSize + 1;
const nodeSize = this.igraphConfig.nodeSize;
const bgsize = nodeSize + 1;
iconGroup
.append("rect")
@@ -758,7 +760,7 @@ export class D3ForceGraph implements GraphRenderer {
.attr("y", -bgsize)
.attr("width", bgsize * 2)
.attr("height", bgsize * 2)
.attr("fill-opacity", (d: D3Node) => {
.attr("fill-opacity", () => {
return this.igraphConfig.nodeIconKey ? 1 : 0;
})
.attr("class", "icon-background");
@@ -830,10 +832,10 @@ export class D3ForceGraph implements GraphRenderer {
self.loadNeighbors(d, PAGE_ACTION.NEXT_PAGE);
}
}) as any)
.on("mouseover", ((e: MouseEvent, d: D3Node) => {
.on("mouseover", ((e: MouseEvent) => {
select(e.target as any).classed("active", true);
}) as any)
.on("mouseout", ((e: MouseEvent, d: D3Node) => {
.on("mouseout", ((e: MouseEvent) => {
select(e.target as any).classed("active", false);
}) as any)
.attr("visibility", (d: D3Node) => (!d._outEAllLoaded || !d._inEAllLoaded ? "visible" : "hidden"));
@@ -859,10 +861,10 @@ export class D3ForceGraph implements GraphRenderer {
self.loadNeighbors(d, PAGE_ACTION.PREVIOUS_PAGE);
}
}) as any)
.on("mouseover", ((e: MouseEvent, d: D3Node) => {
.on("mouseover", ((e: MouseEvent) => {
select(e.target as any).classed("active", true);
}) as any)
.on("mouseout", ((e: MouseEvent, d: D3Node) => {
.on("mouseout", ((e: MouseEvent) => {
select(e.target as any).classed("active", false);
}) as any)
.attr("visibility", (d: D3Node) =>
@@ -955,10 +957,10 @@ export class D3ForceGraph implements GraphRenderer {
self.loadNeighbors(d, PAGE_ACTION.FIRST_PAGE);
}
}) as any)
.on("mouseover", ((e: MouseEvent, d: D3Node) => {
.on("mouseover", ((e: MouseEvent) => {
select(e.target as any).classed("active", true);
}) as any)
.on("mouseout", ((e: MouseEvent, d: D3Node) => {
.on("mouseout", ((e: MouseEvent) => {
select(e.target as any).classed("active", false);
}) as any);
}
@@ -967,10 +969,9 @@ export class D3ForceGraph implements GraphRenderer {
* Remove LoadMore subassembly for existing nodes that show all their children in the graph
*/
private updateLoadMore(nodeSelection: d3.Selection<Element, any, any, any>) {
const self = this;
nodeSelection.selectAll(".loadmore").remove();
var nodeSize = this.igraphConfig.nodeSize;
const nodeSize = this.igraphConfig.nodeSize;
const rootSelectionG = nodeSelection
.filter((d: D3Node) => {
return !!d._isRoot && !!d._pagination;
@@ -1090,7 +1091,7 @@ export class D3ForceGraph implements GraphRenderer {
private fadeNonNeighbors(nodeId: string) {
this.g.selectAll(".node").classed("inactive", (d: D3Node) => {
var neighbors = ((showNeighborType) => {
const neighbors = ((showNeighborType) => {
switch (showNeighborType) {
case NeighborType.SOURCES_ONLY:
return this.graphDataWrapper.getSourcesForId(nodeId);
@@ -1151,7 +1152,7 @@ export class D3ForceGraph implements GraphRenderer {
}
private retrieveNodeCaption(d: D3Node) {
let key = this.igraphConfig.nodeCaption;
const key = this.igraphConfig.nodeCaption;
let value: string = d.id || d.label;
if (key) {
value = <string>GraphData.getNodePropValue(d, key) || "";
@@ -1202,14 +1203,14 @@ export class D3ForceGraph implements GraphRenderer {
y: (<D3Node>l.target).y,
};
const d1 = D3ForceGraph.calculateControlPoint(source, target);
var radius = this.igraphConfig.nodeSize + 3;
const radius = this.igraphConfig.nodeSize + 3;
// End
const dx = target.x - d1.x;
const dy = target.y - d1.y;
const angle = Math.atan2(dy, dx);
var ux = target.x - Math.cos(angle) * radius;
var uy = target.y - Math.sin(angle) * radius;
const ux = target.x - Math.cos(angle) * radius;
const uy = target.y - Math.sin(angle) * radius;
return `translate(${ux},${uy}) rotate(${(angle * 180) / Math.PI})`;
}
@@ -1224,21 +1225,21 @@ export class D3ForceGraph implements GraphRenderer {
y: (<D3Node>l.target).y,
};
const d1 = D3ForceGraph.calculateControlPoint(source, target);
var radius = this.igraphConfig.nodeSize + 3;
const radius = this.igraphConfig.nodeSize + 3;
// Start
var dx = d1.x - source.x;
var dy = d1.y - source.y;
var angle = Math.atan2(dy, dx);
var tx = source.x + Math.cos(angle) * radius;
var ty = source.y + Math.sin(angle) * radius;
let dx = d1.x - source.x;
let dy = d1.y - source.y;
let angle = Math.atan2(dy, dx);
const tx = source.x + Math.cos(angle) * radius;
const ty = source.y + Math.sin(angle) * radius;
// End
dx = target.x - d1.x;
dy = target.y - d1.y;
angle = Math.atan2(dy, dx);
var ux = target.x - Math.cos(angle) * radius;
var uy = target.y - Math.sin(angle) * radius;
const ux = target.x - Math.cos(angle) * radius;
const uy = target.y - Math.sin(angle) * radius;
return "M" + tx + "," + ty + "S" + d1.x + "," + d1.y + " " + ux + "," + uy;
}
@@ -1260,9 +1261,9 @@ export class D3ForceGraph implements GraphRenderer {
}
private static computeImageData(d: D3Node, config: IGraphConfig): string {
let propValue = <string>GraphData.getNodePropValue(d, config.nodeIconKey) || "";
const propValue = <string>GraphData.getNodePropValue(d, config.nodeIconKey) || "";
// Trim leading and trailing spaces to make comparison more forgiving.
let value = config.iconsMap[propValue.trim()];
const value = config.iconsMap[propValue.trim()];
if (!value) {
return undefined;
}
@@ -1288,7 +1289,7 @@ export class D3ForceGraph implements GraphRenderer {
// clear icons
this.g.selectAll(".node .icon").attr("xlink:href", undefined);
}
this.g.selectAll(".node .icon-background").attr("fill-opacity", (d: D3Node) => {
this.g.selectAll(".node .icon-background").attr("fill-opacity", () => {
return config.nodeIconKey ? 1 : 0;
});
this.g.selectAll(".node text.caption").text((d: D3Node) => {

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

@@ -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,10 +1,11 @@
import ko from "knockout";
import * as Constants from "../Constants";
import * as Entities from "../Entities";
import * as Utilities from "../Utilities";
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.
@@ -24,7 +25,7 @@ export default class DataTableOperationManager {
}
private click = (event: JQueryEventObject) => {
const elem: JQuery = $(event.currentTarget);
var elem: JQuery = $(event.currentTarget);
this.updateLastSelectedItem(elem, event.shiftKey);
if (Utilities.isEnvironmentCtrlPressed(event)) {
@@ -36,30 +37,30 @@ export default class DataTableOperationManager {
}
};
private doubleClick = () => {
private doubleClick = (event: JQueryEventObject) => {
this.tryOpenEditor();
};
private keyDown = (event: JQueryEventObject): boolean => {
const isUpArrowKey: boolean = event.keyCode === Constants.keyCodes.UpArrow,
isDownArrowKey: boolean = event.keyCode === Constants.keyCodes.DownArrow;
let handled = false;
var isUpArrowKey: boolean = event.keyCode === Constants.keyCodes.UpArrow,
isDownArrowKey: boolean = event.keyCode === Constants.keyCodes.DownArrow,
handled: boolean = false;
if (isUpArrowKey || isDownArrowKey) {
const lastSelectedItem: Entities.ITableEntity = this._tableEntityListViewModel.lastSelectedItem;
const dataTableRows: JQuery = $(Constants.htmlSelectors.dataTableAllRowsSelector);
const maximumIndex = dataTableRows.length - 1;
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.
const lastSelectedItemIndex = lastSelectedItem
var lastSelectedItemIndex = lastSelectedItem
? this._tableEntityListViewModel.getItemIndexFromCurrentPage(
this._tableEntityListViewModel.getTableEntityKeys(lastSelectedItem.RowKey._)
)
: -1;
const nextIndex: number = isUpArrowKey ? lastSelectedItemIndex - 1 : lastSelectedItemIndex + 1;
const safeIndex: number = Utilities.ensureBetweenBounds(nextIndex, 0, maximumIndex);
const selectedRowElement: JQuery = dataTableRows.eq(safeIndex);
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) {
@@ -89,7 +90,7 @@ export default class DataTableOperationManager {
// in contrast, there may be more than one key down and key
// pressed events.
private keyUp = (event: JQueryEventObject): boolean => {
let handled = false;
var handled: boolean = false;
switch (event.keyCode) {
case Constants.keyCodes.Enter:
@@ -104,9 +105,8 @@ export default class DataTableOperationManager {
};
private itemDropped = (event: JQueryEventObject): boolean => {
const handled = false;
//eslint-disable-next-line
const items = (<any>event.originalEvent).dataTransfer.items;
var handled: boolean = false;
var items = (<any>event.originalEvent).dataTransfer.items;
if (!items) {
// On browsers outside of Chromium
@@ -115,9 +115,9 @@ export default class DataTableOperationManager {
return null;
}
for (let i = 0; i < items.length; i++) {
const item = items[i];
const entry = item.webkitGetAsEntry();
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
@@ -132,8 +132,8 @@ export default class DataTableOperationManager {
}
private tryHandleDeleteSelected(): boolean {
const selectedEntities: Entities.ITableEntity[] = this._tableEntityListViewModel.selected();
let handled = false;
var selectedEntities: Entities.ITableEntity[] = this._tableEntityListViewModel.selected();
var handled: boolean = false;
if (selectedEntities && selectedEntities.length) {
this._tableCommands.deleteEntitiesCommand(this._tableEntityListViewModel);
@@ -150,8 +150,8 @@ export default class DataTableOperationManager {
}
private updateLastSelectedItem($elem: JQuery, isShiftSelect: boolean) {
const entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
const entity = this._tableEntityListViewModel.getItemFromCurrentPage(
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var entity = this._tableEntityListViewModel.getItemFromCurrentPage(
this._tableEntityListViewModel.getTableEntityKeys(entityIdentity.RowKey)
);
@@ -164,7 +164,7 @@ export default class DataTableOperationManager {
private applySingleSelection($elem: JQuery) {
if ($elem) {
const entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
this._tableEntityListViewModel.clearSelection();
this.addToSelection(entityIdentity.RowKey);
@@ -180,12 +180,12 @@ export default class DataTableOperationManager {
}
private applyCtrlSelection($elem: JQuery): void {
const koSelected: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
var koSelected: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
? this._tableEntityListViewModel.selected
: null;
if (koSelected) {
const entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
if (
!this._tableEntityListViewModel.isItemSelected(
@@ -201,7 +201,7 @@ export default class DataTableOperationManager {
}
private applyShiftSelection($elem: JQuery): void {
let anchorItem = this._tableEntityListViewModel.lastSelectedAnchorItem;
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) {
@@ -209,16 +209,16 @@ export default class DataTableOperationManager {
}
if (anchorItem) {
const entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
const elementIndex = this._tableEntityListViewModel.getItemIndexFromAllPages(
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var elementIndex = this._tableEntityListViewModel.getItemIndexFromAllPages(
this._tableEntityListViewModel.getTableEntityKeys(entityIdentity.RowKey)
);
const anchorIndex = this._tableEntityListViewModel.getItemIndexFromAllPages(
var anchorIndex = this._tableEntityListViewModel.getItemIndexFromAllPages(
this._tableEntityListViewModel.getTableEntityKeys(anchorItem.RowKey._)
);
const startIndex = Math.min(elementIndex, anchorIndex);
const endIndex = Math.max(elementIndex, anchorIndex);
var startIndex = Math.min(elementIndex, anchorIndex);
var endIndex = Math.max(elementIndex, anchorIndex);
this._tableEntityListViewModel.clearSelection();
ko.utils.arrayPushAll<Entities.ITableEntity>(
@@ -229,7 +229,7 @@ export default class DataTableOperationManager {
}
private applyContextMenuSelection($elem: JQuery) {
const entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
var entityIdentity: Entities.ITableEntityIdentity = this.getEntityIdentity($elem);
if (
!this._tableEntityListViewModel.isItemSelected(
@@ -244,26 +244,26 @@ export default class DataTableOperationManager {
}
private addToSelection(rowKey: string) {
const selectedEntity: Entities.ITableEntity = this._tableEntityListViewModel.getItemFromCurrentPage(
var selectedEntity: Entities.ITableEntity = this._tableEntityListViewModel.getItemFromCurrentPage(
this._tableEntityListViewModel.getTableEntityKeys(rowKey)
);
if (selectedEntity !== null) {
if (selectedEntity != null) {
this._tableEntityListViewModel.selected.push(selectedEntity);
}
}
// Selecting first row if the selection is empty.
public selectFirstIfNeeded(): void {
const koSelected: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
var koSelected: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
? this._tableEntityListViewModel.selected
: null;
const koEntities: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
var koEntities: ko.ObservableArray<Entities.ITableEntity> = this._tableEntityListViewModel
? this._tableEntityListViewModel.items
: null;
if (!koSelected().length && koEntities().length) {
const firstEntity: Entities.ITableEntity = koEntities()[0];
var firstEntity: Entities.ITableEntity = koEntities()[0];
// Clear last selection: lastSelectedItem and lastSelectedAnchorItem
this._tableEntityListViewModel.clearLastSelected();
@@ -278,7 +278,7 @@ export default class DataTableOperationManager {
}
}
public bind(): void {
public bind() {
this.dataTable.on("click", "tr", this.click);
this.dataTable.on("dblclick", "tr", this.doubleClick);
this.dataTable.on("keydown", "td", this.keyDown);

View File

@@ -1,12 +1,12 @@
import * as DateTimeUtilities from "./DateTimeUtilities";
import QueryBuilderViewModel from "./QueryBuilderViewModel";
import QueryClauseViewModel from "./QueryClauseViewModel";
import * as DateTimeUtilities from "./DateTimeUtilities";
/**
* Constants
*/
export const utc = "utc";
export const local = "local";
export var utc = "utc";
export var local = "local";
export interface ITimestampQuery {
queryType: string; // valid values are "last" and "range"
@@ -41,11 +41,11 @@ export function addRangeTimestamp(
queryBuilderViewModel.addCustomRange(timestamp, queryClauseViewModel);
}
export function getDefaultStart(localTime: boolean, durationHours = 24): string {
let startTimestamp: string;
export function getDefaultStart(localTime: boolean, durationHours: number = 24): string {
var startTimestamp: string;
const utcNowString: string = new Date().toISOString();
const yesterday: Date = new Date(utcNowString);
var utcNowString: string = new Date().toISOString();
var yesterday: Date = new Date(utcNowString);
yesterday.setHours(yesterday.getHours() - durationHours);
startTimestamp = yesterday.toISOString();
@@ -58,9 +58,9 @@ export function getDefaultStart(localTime: boolean, durationHours = 24): string
}
export function getDefaultEnd(localTime: boolean): string {
let endTimestamp: string;
var endTimestamp: string;
const utcNowString: string = new Date().toISOString();
var utcNowString: string = new Date().toISOString();
endTimestamp = utcNowString;
@@ -73,14 +73,14 @@ export function getDefaultEnd(localTime: boolean): string {
export function parseDate(dateString: string, isUTC: boolean): Date {
// TODO validate dateString
let date: Date = null;
var date: Date = null;
if (dateString) {
try {
// Date string is assumed to be UTC in Storage Explorer Standalone.
// Behavior may vary in other browsers.
// Here's an example of how the string looks like "2015-10-24T21:44:12"
const millisecondTime = Date.parse(dateString),
var millisecondTime = Date.parse(dateString),
parsed: Date = new Date(millisecondTime);
if (isUTC) {
@@ -89,7 +89,7 @@ export function parseDate(dateString: string, isUTC: boolean): Date {
// Since we parsed in UTC, accessors are flipped - we get local time from the getUTC* group
// Reinstating, the date is parsed above as UTC, and here we are creating a new date object
// in local time.
const year = parsed.getUTCFullYear(),
var year = parsed.getUTCFullYear(),
month = parsed.getUTCMonth(),
day = parsed.getUTCDate(),
hours = parsed.getUTCHours(),
@@ -109,8 +109,8 @@ export function parseDate(dateString: string, isUTC: boolean): Date {
export function utcFromLocalDateString(localDateString: string): string {
// TODO validate localDateString
const localDate = parseDate(localDateString, false);
let utcDateString: string = null;
var localDate = parseDate(localDateString, false),
utcDateString: string = null;
if (localDate) {
utcDateString = localDate.toISOString();
@@ -120,7 +120,7 @@ export function utcFromLocalDateString(localDateString: string): string {
}
function padIfNeeded(value: number): string {
let padded = String(value);
var padded: string = String(value);
if (0 <= value && value < 10) {
padded = "0" + padded;
@@ -130,7 +130,7 @@ function padIfNeeded(value: number): string {
}
function toLocalDateString(date: Date): string {
let localDateString: string = null;
var localDateString: string = null;
if (date) {
localDateString =
@@ -152,8 +152,8 @@ function toLocalDateString(date: Date): string {
export function localFromUtcDateString(utcDateString: string): string {
// TODO validate utcDateString
const utcDate: Date = parseDate(utcDateString, true);
let localDateString: string = null;
var utcDate: Date = parseDate(utcDateString, true),
localDateString: string = null;
if (utcDate) {
localDateString = toLocalDateString(utcDate);
@@ -164,8 +164,8 @@ export function localFromUtcDateString(utcDateString: string): string {
export function tryChangeTimestampTimeZone(koTimestamp: ko.Observable<string>, toUTC: boolean): void {
if (koTimestamp) {
const currentDateString: string = koTimestamp();
let newDateString: string;
var currentDateString: string = koTimestamp(),
newDateString: string;
if (currentDateString) {
if (toUTC) {
@@ -189,16 +189,16 @@ export function tryChangeTimestampTimeZone(koTimestamp: ko.Observable<string>, t
* Input validation helpers
*/
export const noTooltip = "",
export var noTooltip = "",
invalidStartTimeTooltip = "Please provide a valid start time.", // localize
invalidExpiryTimeRequiredTooltip = "Required field. Please provide a valid expiry time.", // localize
invalidExpiryTimeGreaterThanStartTimeTooltip = "The expiry time must be greater than the start time."; // localize
export function isDateString(dateString: string): boolean {
let success = false;
var success: boolean = false;
if (dateString) {
const date = Date.parse(dateString);
var date: number = Date.parse(dateString);
success = $.isNumeric(date);
}
@@ -308,10 +308,10 @@ function _getLocalIsoDateStringFromParts(
}
function _addDaysHours(time: Date, days: number, hours: number): Date {
const msPerHour = 1000 * 60 * 60;
const daysMs = days * msPerHour * 24;
const hoursMs = hours * msPerHour;
const newTimeMs = time.getTime() + daysMs + hoursMs;
var msPerHour = 1000 * 60 * 60;
var daysMs = days * msPerHour * 24;
var hoursMs = hours * msPerHour;
var newTimeMs = time.getTime() + daysMs + hoursMs;
return new Date(newTimeMs);
}
@@ -321,7 +321,7 @@ function _daysHoursBeforeNow(days: number, hours: number): Date {
export function _queryLastDaysHours(days: number, hours: number): string {
/* tslint:disable: no-unused-variable */
let daysHoursAgo = _getLocalIsoDateTimeString(_daysHoursBeforeNow(days, hours));
var daysHoursAgo = _getLocalIsoDateTimeString(_daysHoursBeforeNow(days, hours));
daysHoursAgo = DateTimeUtilities.getUTCDateTime(daysHoursAgo);
return daysHoursAgo;
@@ -329,21 +329,21 @@ export function _queryLastDaysHours(days: number, hours: number): string {
}
export function _queryCurrentMonthLocal(): string {
const now = new Date();
let start = _getLocalIsoDateStringFromParts(now.getFullYear(), now.getMonth(), 1);
var now = new Date();
var start = _getLocalIsoDateStringFromParts(now.getFullYear(), now.getMonth(), 1);
start = DateTimeUtilities.getUTCDateTime(start);
return start;
}
export function _queryCurrentYearLocal(): string {
const now = new Date();
let start = _getLocalIsoDateStringFromParts(now.getFullYear(), 0, 1); // Month is 0..11, date is 1..31
var now = new Date();
var start = _getLocalIsoDateStringFromParts(now.getFullYear(), 0, 1); // Month is 0..11, date is 1..31
start = DateTimeUtilities.getUTCDateTime(start);
return start;
}
function _addTime(time: Date, lastNumber: number, timeUnit: string): Date {
let timeMS: number;
var timeMS: number;
switch (TimeUnit[Number(timeUnit)]) {
case TimeUnit.Days.toString():
timeMS = lastNumber * 1000 * 60 * 60 * 24;
@@ -360,7 +360,7 @@ function _addTime(time: Date, lastNumber: number, timeUnit: string): Date {
default:
//throw new Errors.ArgumentOutOfRangeError(timeUnit);
}
const newTimeMS = time.getTime() + timeMS;
var newTimeMS = time.getTime() + timeMS;
return new Date(newTimeMS);
}
@@ -370,7 +370,7 @@ function _timeBeforeNow(lastNumber: number, timeUnit: string): Date {
export function _queryLastTime(lastNumber: number, timeUnit: string): string {
/* tslint:disable: no-unused-variable */
let daysHoursAgo = _getLocalIsoDateTimeString(_timeBeforeNow(lastNumber, timeUnit));
var daysHoursAgo = _getLocalIsoDateTimeString(_timeBeforeNow(lastNumber, timeUnit));
daysHoursAgo = DateTimeUtilities.getUTCDateTime(daysHoursAgo);
return daysHoursAgo;
/* tslint:enable: no-unused-variable */

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;
}
}