Compare commits

..

1 Commits

Author SHA1 Message Date
sunilyadav840
2ff5efcea4 Fixed eslint issue of githuvClient and NotebookRenderer files 2021-10-05 13:29:21 +05:30
43 changed files with 463 additions and 482 deletions

View File

@@ -81,12 +81,21 @@ src/Explorer/Tables/DataTable/DataTableBindingManager.ts
src/Explorer/Tables/DataTable/DataTableBuilder.ts src/Explorer/Tables/DataTable/DataTableBuilder.ts
src/Explorer/Tables/DataTable/DataTableContextMenu.ts src/Explorer/Tables/DataTable/DataTableContextMenu.ts
src/Explorer/Tables/DataTable/DataTableOperationManager.ts src/Explorer/Tables/DataTable/DataTableOperationManager.ts
src/Explorer/Tables/DataTable/DataTableOperations.ts
src/Explorer/Tables/DataTable/DataTableViewModel.ts src/Explorer/Tables/DataTable/DataTableViewModel.ts
src/Explorer/Tables/DataTable/TableCommands.ts
src/Explorer/Tables/DataTable/TableEntityCache.ts
src/Explorer/Tables/DataTable/TableEntityListViewModel.ts src/Explorer/Tables/DataTable/TableEntityListViewModel.ts
src/Explorer/Tables/Entities.ts
src/Explorer/Tables/QueryBuilder/ClauseGroup.ts
src/Explorer/Tables/QueryBuilder/ClauseGroupViewModel.ts
src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts src/Explorer/Tables/QueryBuilder/CustomTimestampHelper.ts
src/Explorer/Tables/QueryBuilder/QueryBuilderViewModel.ts
src/Explorer/Tables/QueryBuilder/QueryClauseViewModel.ts
src/Explorer/Tables/TableDataClient.ts src/Explorer/Tables/TableDataClient.ts
src/Explorer/Tables/TableEntityProcessor.ts src/Explorer/Tables/TableEntityProcessor.ts
src/Explorer/Tables/Utilities.ts src/Explorer/Tables/Utilities.ts
src/Explorer/Tabs/ConflictsTab.ts
src/Explorer/Tabs/DatabaseSettingsTab.ts src/Explorer/Tabs/DatabaseSettingsTab.ts
src/Explorer/Tabs/DocumentsTab.test.ts src/Explorer/Tabs/DocumentsTab.test.ts
src/Explorer/Tabs/DocumentsTab.ts src/Explorer/Tabs/DocumentsTab.ts
@@ -97,7 +106,6 @@ src/Explorer/Tabs/ScriptTabBase.ts
src/Explorer/Tabs/TabComponents.ts src/Explorer/Tabs/TabComponents.ts
src/Explorer/Tabs/TabsBase.ts src/Explorer/Tabs/TabsBase.ts
src/Explorer/Tabs/TriggerTab.ts src/Explorer/Tabs/TriggerTab.ts
src/Explorer/Tabs/UserDefinedFunctionTab.ts
src/Explorer/Tree/AccessibleVerticalList.ts src/Explorer/Tree/AccessibleVerticalList.ts
src/Explorer/Tree/Collection.ts src/Explorer/Tree/Collection.ts
src/Explorer/Tree/ConflictId.ts src/Explorer/Tree/ConflictId.ts
@@ -106,12 +114,15 @@ src/Explorer/Tree/ObjectId.ts
src/Explorer/Tree/ResourceTokenCollection.ts src/Explorer/Tree/ResourceTokenCollection.ts
src/Explorer/Tree/StoredProcedure.ts src/Explorer/Tree/StoredProcedure.ts
src/Explorer/Tree/TreeComponents.ts src/Explorer/Tree/TreeComponents.ts
src/Explorer/Tree/Trigger.ts
src/Explorer/WaitsForTemplateViewModel.ts src/Explorer/WaitsForTemplateViewModel.ts
src/GitHub/GitHubClient.test.ts src/GitHub/GitHubClient.test.ts
src/GitHub/GitHubClient.ts src/GitHub/GitHubConnector.ts
src/GitHub/GitHubOAuthService.ts
src/Index.ts src/Index.ts
src/Juno/JunoClient.test.ts
src/Juno/JunoClient.ts
src/Platform/Hosted/Authorization.ts src/Platform/Hosted/Authorization.ts
src/ReactDevTools.ts
src/Shared/Constants.ts src/Shared/Constants.ts
src/Shared/DefaultExperienceUtility.test.ts src/Shared/DefaultExperienceUtility.test.ts
src/Shared/DefaultExperienceUtility.ts src/Shared/DefaultExperienceUtility.ts
@@ -129,14 +140,20 @@ src/Explorer/Controls/Notebook/NotebookTerminalComponent.tsx
src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx
src/Explorer/Controls/TreeComponent/TreeComponent.tsx src/Explorer/Controls/TreeComponent/TreeComponent.tsx
src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.test.tsx
src/Explorer/Graph/GraphExplorerComponent/GraphExplorer.tsx
src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx
src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx
src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.test.tsx
src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx src/Explorer/Graph/GraphExplorerComponent/NodePropertiesComponent.tsx
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.tsx src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.tsx
src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.tsx
src/Explorer/Menus/CommandBar/CommandBarUtil.tsx src/Explorer/Menus/CommandBar/CommandBarUtil.tsx
src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx src/Explorer/Notebook/NotebookComponent/NotebookComponentAdapter.tsx
src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx
src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx src/Explorer/Notebook/NotebookComponent/VirtualCommandBarComponent.tsx
src/Explorer/Notebook/NotebookComponent/contents/index.tsx src/Explorer/Notebook/NotebookComponent/contents/index.tsx
src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx
src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx src/Explorer/Notebook/NotebookRenderer/decorators/draggable/index.tsx
src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx src/Explorer/Notebook/NotebookRenderer/decorators/hijack-scroll/index.tsx
src/Explorer/Notebook/NotebookRenderer/decorators/kbd-shortcuts/index.tsx src/Explorer/Notebook/NotebookRenderer/decorators/kbd-shortcuts/index.tsx

View File

@@ -39,6 +39,7 @@ module.exports = {
"@typescript-eslint/switch-exhaustiveness-check": "error", "@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-extraneous-class": "error", "@typescript-eslint/no-extraneous-class": "error",
"no-null/no-null": "error",
"@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-explicit-any": "error",
"prefer-arrow/prefer-arrow-functions": ["error", { allowStandaloneDeclarations: true }], "prefer-arrow/prefer-arrow-functions": ["error", { allowStandaloneDeclarations: true }],
eqeqeq: "error", eqeqeq: "error",

View File

@@ -22,6 +22,5 @@
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": true, "source.fixAll.eslint": true,
"source.organizeImports": true "source.organizeImports": true
}, }
"typescript.preferences.importModuleSpecifier": "non-relative"
} }

View File

@@ -37,8 +37,8 @@ module.exports = {
global: { global: {
branches: 25, branches: 25,
functions: 25, functions: 25,
lines: 29, lines: 29.5,
statements: 29, statements: 29.5,
}, },
}, },
@@ -129,8 +129,6 @@ module.exports = {
// The test environment that will be used for testing // The test environment that will be used for testing
// testEnvironment: "jest-environment-jsdom", // testEnvironment: "jest-environment-jsdom",
modulePaths: ["node_modules", "<rootDir>/src"],
// Options that will be passed to the testEnvironment // Options that will be passed to the testEnvironment
// testEnvironmentOptions: {}, // testEnvironmentOptions: {},

View File

@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { FeedOptions, ItemDefinition, QueryIterator, Resource } from "@azure/cosmos"; import { FeedOptions, ItemDefinition, QueryIterator, Resource } from "@azure/cosmos";
import * as Q from "q"; import * as Q from "q";
import * as React from "react"; import * as React from "react";
@@ -296,6 +294,8 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
this.setGremlinParams(); this.setGremlinParams();
} }
const selectedNode = this.state.highlightedNode;
props.onGraphAccessorCreated({ props.onGraphAccessorCreated({
applyFilter: this.submitQuery.bind(this), applyFilter: this.submitQuery.bind(this),
addVertex: this.addVertex.bind(this), addVertex: this.addVertex.bind(this),
@@ -303,7 +303,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
}); });
} // constructor } // constructor
public shareIGraphConfig(igraphConfig: IGraphConfig): void { public shareIGraphConfig(igraphConfig: IGraphConfig) {
this.setState({ this.setState({
igraphConfig: { ...igraphConfig }, igraphConfig: { ...igraphConfig },
}); });
@@ -330,10 +330,10 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
const partitionKeyProperty = this.props.collectionPartitionKeyProperty; const partitionKeyProperty = this.props.collectionPartitionKeyProperty;
// aggregate all the properties, remove dropped ones // aggregate all the properties, remove dropped ones
const finalProperties = editedProperties.existingProperties.concat(editedProperties.addedProperties); let finalProperties = editedProperties.existingProperties.concat(editedProperties.addedProperties);
// Compose the query // Compose the query
const pkId = editedProperties.pkId; let pkId = editedProperties.pkId;
let updateQueryFragment = ""; let updateQueryFragment = "";
finalProperties.forEach((p) => { finalProperties.forEach((p) => {
@@ -422,7 +422,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* Called from ko binding * Called from ko binding
* @param id * @param id
*/ */
public selectNode(id: string): void { public selectNode(id: string) {
if (!this.d3ForceGraph) { if (!this.d3ForceGraph) {
console.warn("Attempting to select node, but d3ForceGraph not initialized, yet."); console.warn("Attempting to select node, but d3ForceGraph not initialized, yet.");
return; return;
@@ -431,7 +431,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
this.d3ForceGraph.selectNode(id); this.d3ForceGraph.selectNode(id);
} }
public deleteHighlightedNode(): void { public deleteHighlightedNode() {
if (!this.state.highlightedNode) { if (!this.state.highlightedNode) {
GraphExplorer.reportToConsole(ConsoleDataType.Error, "No highlighted node to remove."); GraphExplorer.reportToConsole(ConsoleDataType.Error, "No highlighted node to remove.");
return; return;
@@ -467,23 +467,23 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* Is of type: {e: GremlinEdge, v: GremlinVertex}[] * Is of type: {e: GremlinEdge, v: GremlinVertex}[]
* @param data * @param data
*/ */
public static isEdgeVertexPairArray(data: any): boolean { public static isEdgeVertexPairArray(data: any) {
if (!(data instanceof Array)) { if (!(data instanceof Array)) {
GraphExplorer.reportToConsole(ConsoleDataType.Info, "Query result not an array", data); GraphExplorer.reportToConsole(ConsoleDataType.Info, "Query result not an array", data);
return false; return false;
} }
const pairs: any[] = data; let pairs: any[] = data;
for (let i = 0; i < pairs.length; i++) { for (let i = 0; i < pairs.length; i++) {
const item = pairs[i]; const item = pairs[i];
if ( if (
!Object.prototype.hasOwnProperty.call(item, "e") || !item.hasOwnProperty("e") ||
!Object.prototype.hasOwnProperty.call(item, "v") || !item.hasOwnProperty("v") ||
!Object.prototype.hasOwnProperty.call(item["e"], "id") || !item["e"].hasOwnProperty("id") ||
!Object.prototype.hasOwnProperty.call(item["e"], "type") || !item["e"].hasOwnProperty("type") ||
item["e"].type !== "edge" || item["e"].type !== "edge" ||
!Object.prototype.hasOwnProperty.call(item["v"], "id") || !item["v"].hasOwnProperty("id") ||
!Object.prototype.hasOwnProperty.call(item["e"], "type") || !item["v"].hasOwnProperty("type") ||
item["v"].type !== "vertex" item["v"].type !== "vertex"
) { ) {
return false; return false;
@@ -514,7 +514,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
// Try hitting cache first // Try hitting cache first
const cache = outE ? this.outECache : this.inECache; const cache = outE ? this.outECache : this.inECache;
const pairs = cache.retrieve(vertex.id, startIndex, pageSize); const pairs = cache.retrieve(vertex.id, startIndex, pageSize);
if (pairs !== null && pairs.length === pageSize) { if (pairs != null && pairs.length === pageSize) {
const msg = `Retrieved ${pairs.length} ${outE ? "outE" : "inE"} edges from cache for vertex id: ${vertex.id}`; const msg = `Retrieved ${pairs.length} ${outE ? "outE" : "inE"} edges from cache for vertex id: ${vertex.id}`;
GraphExplorer.reportToConsole(ConsoleDataType.Info, msg); GraphExplorer.reportToConsole(ConsoleDataType.Info, msg);
return Q.resolve(pairs); return Q.resolve(pairs);
@@ -588,6 +588,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
vertex._outEAllLoaded && vertex._outEAllLoaded &&
vertex._inEAllLoaded vertex._inEAllLoaded
) { ) {
console.info("No more edges to load for vertex " + vertex.id);
updateGraphData(); updateGraphData();
return Q.resolve(graphData); return Q.resolve(graphData);
} }
@@ -667,7 +668,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
} }
); );
return promise.then(() => { return promise.then((nbPairsFetched: number) => {
if (offsetIndex >= GraphExplorer.LOAD_PAGE_SIZE || !vertex._outEAllLoaded || !vertex._inEAllLoaded) { if (offsetIndex >= GraphExplorer.LOAD_PAGE_SIZE || !vertex._outEAllLoaded || !vertex._inEAllLoaded) {
vertex._pagination = { vertex._pagination = {
total: total:
@@ -753,7 +754,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* Create a new edge in docdb and update graph * Create a new edge in docdb and update graph
* @param e * @param e
*/ */
public createNewEdge(e: GraphNewEdgeData): Q.Promise<unknown> { public createNewEdge(e: GraphNewEdgeData): Q.Promise<any> {
const q = `g.V('${GraphUtil.escapeSingleQuotes(e.inputOutV)}').addE('${GraphUtil.escapeSingleQuotes( const q = `g.V('${GraphUtil.escapeSingleQuotes(e.inputOutV)}').addE('${GraphUtil.escapeSingleQuotes(
e.label e.label
)}').To(g.V('${GraphUtil.escapeSingleQuotes(e.inputInV)}'))`; )}').To(g.V('${GraphUtil.escapeSingleQuotes(e.inputInV)}'))`;
@@ -771,8 +772,8 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
return; return;
} }
const edge = edges[0]; let edge = edges[0];
const graphData = this.originalGraphData; let graphData = this.originalGraphData;
graphData.addEdge(edge); graphData.addEdge(edge);
// Allow loadNeighbors to load list new edge // Allow loadNeighbors to load list new edge
@@ -799,10 +800,10 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* Manually update in-memory graph. * Manually update in-memory graph.
* @param edgeId * @param edgeId
*/ */
public removeEdge(edgeId: string): Q.Promise<unknown> { public removeEdge(edgeId: string): Q.Promise<any> {
return this.submitToBackend(`g.E('${GraphUtil.escapeSingleQuotes(edgeId)}').drop()`).then( return this.submitToBackend(`g.E('${GraphUtil.escapeSingleQuotes(edgeId)}').drop()`).then(
() => { () => {
const graphData = this.originalGraphData; let graphData = this.originalGraphData;
graphData.removeEdge(edgeId, false); graphData.removeEdge(edgeId, false);
this.updateGraphData(graphData, this.state.igraphConfig); this.updateGraphData(graphData, this.state.igraphConfig);
}, },
@@ -825,14 +826,10 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
return false; return false;
} }
const vertices: any[] = data; let vertices: any[] = data;
if (vertices.length > 0) { if (vertices.length > 0) {
const v0 = vertices[0]; let v0 = vertices[0];
if ( if (!v0.hasOwnProperty("id") || !v0.hasOwnProperty("type") || v0.type !== "vertex") {
!Object.prototype.hasOwnProperty.call(v0, "id") ||
!Object.prototype.hasOwnProperty.call(v0, "type") ||
v0.type !== "vertex"
) {
return false; return false;
} }
} }
@@ -840,7 +837,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
} }
public processGremlinQueryResults(result: GremlinClient.GremlinRequestResult): void { public processGremlinQueryResults(result: GremlinClient.GremlinRequestResult): void {
const data = result.data as GraphData.GremlinVertex[]; const data = result.data as any;
this.setFilterQueryStatus(FilterQueryStatus.GraphEmptyResult); this.setFilterQueryStatus(FilterQueryStatus.GraphEmptyResult);
if (data === null) { if (data === null) {
@@ -930,13 +927,13 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
throw { title: err }; throw { title: err };
} }
if (vertices === null || vertices.length < 1) { if (vertices == null || vertices.length < 1) {
const err = "Failed to create vertex (no vertex in response)"; const err = "Failed to create vertex (no vertex in response)";
GraphExplorer.reportToConsole(ConsoleDataType.Error, err, vertices); GraphExplorer.reportToConsole(ConsoleDataType.Error, err, vertices);
throw { title: err }; throw { title: err };
} }
const vertex = vertices[0]; let vertex = vertices[0];
const graphData = this.originalGraphData; const graphData = this.originalGraphData;
graphData.addVertex(vertex); graphData.addVertex(vertex);
this.updateGraphData(graphData, this.state.igraphConfig); this.updateGraphData(graphData, this.state.igraphConfig);
@@ -1025,7 +1022,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
this.gremlinClient.destroy(); this.gremlinClient.destroy();
} }
public componentDidMount(): void { public componentDidMount(): void {
if (this.props.onLoadStartKey !== null && this.props.onLoadStartKey !== undefined) { if (this.props.onLoadStartKey != null && this.props.onLoadStartKey != undefined) {
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(
Action.Tab, Action.Tab,
{ {
@@ -1085,7 +1082,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
public static reportToConsole(type: ConsoleDataType.Info, msg: string, ...errorData: any[]): void; public static reportToConsole(type: ConsoleDataType.Info, msg: string, ...errorData: any[]): void;
public static reportToConsole(type: ConsoleDataType.Error, msg: string, ...errorData: any[]): void; public static reportToConsole(type: ConsoleDataType.Error, msg: string, ...errorData: any[]): void;
public static reportToConsole(type: ConsoleDataType, msg: string, ...errorData: any[]): void | (() => void) { public static reportToConsole(type: ConsoleDataType, msg: string, ...errorData: any[]): void | (() => void) {
let errorDataStr = ""; let errorDataStr: string = "";
if (errorData && errorData.length > 0) { if (errorData && errorData.length > 0) {
console.error(msg, errorData); console.error(msg, errorData);
errorDataStr = ": " + JSON.stringify(errorData); errorDataStr = ": " + JSON.stringify(errorData);
@@ -1164,15 +1161,12 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
)}"` )}"`
).then( ).then(
(documents: DataModels.DocumentId[]) => { (documents: DataModels.DocumentId[]) => {
$.each( $.each(documents, (index: number, doc: any) => {
documents,
(index: number, doc: { _graph_icon_property_value: string; icon: string; format: string }) => {
newIconsMap[doc["_graph_icon_property_value"]] = { newIconsMap[doc["_graph_icon_property_value"]] = {
data: doc["icon"], data: doc["icon"],
format: doc["format"], format: doc["format"],
}; };
} });
);
// Update graph configuration // Update graph configuration
this.setState({ this.setState({
@@ -1229,8 +1223,8 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
const key = this.state.igraphConfig.nodeCaption; const key = this.state.igraphConfig.nodeCaption;
return $.map( return $.map(
this.state.rootMap, this.state.rootMap,
(value: any): LeftPane.CaptionId => { (value: any, index: number): LeftPane.CaptionId => {
const result = GraphData.GraphData.getNodePropValue(value, key); let result = GraphData.GraphData.getNodePropValue(value, key);
return { return {
caption: result !== undefined ? result : value.id, caption: result !== undefined ? result : value.id,
id: value.id, id: value.id,
@@ -1243,7 +1237,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* Selecting a root node means * Selecting a root node means
* @param node * @param node
*/ */
private selectRootNode(id: string): Q.Promise<unknown> { private selectRootNode(id: string): Q.Promise<any> {
if (!this.d3ForceGraph) { if (!this.d3ForceGraph) {
console.warn("Attempting to reset zoom, but d3ForceGraph not initialized, yet."); console.warn("Attempting to reset zoom, but d3ForceGraph not initialized, yet.");
} else { } else {
@@ -1288,7 +1282,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
this.collectNodeProperties(this.originalGraphData.vertices); this.collectNodeProperties(this.originalGraphData.vertices);
this.updatePropertiesPane(id); this.updatePropertiesPane(id);
}, },
(reason: string) => { (reason: any) => {
GraphExplorer.reportToConsole(ConsoleDataType.Error, `Failed to select root node. Reason:${reason}`); GraphExplorer.reportToConsole(ConsoleDataType.Error, `Failed to select root node. Reason:${reason}`);
} }
); );
@@ -1355,10 +1349,10 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
private getPkIdFromVertex(v: GraphData.GremlinVertex): string { private getPkIdFromVertex(v: GraphData.GremlinVertex): string {
if ( if (
this.props.collectionPartitionKeyProperty && this.props.collectionPartitionKeyProperty &&
Object.prototype.hasOwnProperty.call(v, "properties") && v.hasOwnProperty("properties") &&
Object.prototype.hasOwnProperty.call(v.properties, this.props.collectionPartitionKeyProperty) && v.properties.hasOwnProperty(this.props.collectionPartitionKeyProperty) &&
v.properties[this.props.collectionPartitionKeyProperty].length > 0 && v.properties[this.props.collectionPartitionKeyProperty].length > 0 &&
Object.prototype.hasOwnProperty.call(v.properties[this.props.collectionPartitionKeyProperty][0], "value") v.properties[this.props.collectionPartitionKeyProperty][0].hasOwnProperty("value")
) { ) {
const pk = v.properties[this.props.collectionPartitionKeyProperty][0].value; const pk = v.properties[this.props.collectionPartitionKeyProperty][0].value;
return GraphExplorer.generatePkIdPair(pk, v.id); return GraphExplorer.generatePkIdPair(pk, v.id);
@@ -1376,8 +1370,8 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
private getPkIdFromNodeData(v: GraphHighlightedNodeData): string { private getPkIdFromNodeData(v: GraphHighlightedNodeData): string {
if ( if (
this.props.collectionPartitionKeyProperty && this.props.collectionPartitionKeyProperty &&
Object.prototype.hasOwnProperty.call(v, "properties") && v.hasOwnProperty("properties") &&
Object.prototype.hasOwnProperty.call(v.properties, this.props.collectionPartitionKeyProperty) v.properties.hasOwnProperty(this.props.collectionPartitionKeyProperty)
) { ) {
const pk = v.properties[this.props.collectionPartitionKeyProperty]; const pk = v.properties[this.props.collectionPartitionKeyProperty];
return GraphExplorer.generatePkIdPair(pk[0] as PartitionKeyValueType, v.id); return GraphExplorer.generatePkIdPair(pk[0] as PartitionKeyValueType, v.id);
@@ -1394,14 +1388,14 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* @return id * @return id
*/ */
public static getPkIdFromDocumentId(d: DataModels.DocumentId, collectionPartitionKeyProperty: string): string { public static getPkIdFromDocumentId(d: DataModels.DocumentId, collectionPartitionKeyProperty: string): string {
const { id } = d; let { id } = d;
if (typeof id !== "string") { if (typeof id !== "string") {
const error = `Vertex id is not a string: ${JSON.stringify(id)}.`; const error = `Vertex id is not a string: ${JSON.stringify(id)}.`;
logConsoleError(error); logConsoleError(error);
throw new Error(error); throw new Error(error);
} }
if (collectionPartitionKeyProperty && Object.prototype.hasOwnProperty.call(d, collectionPartitionKeyProperty)) { if (collectionPartitionKeyProperty && d.hasOwnProperty(collectionPartitionKeyProperty)) {
let pk = (d as any)[collectionPartitionKeyProperty]; let pk = (d as any)[collectionPartitionKeyProperty];
if (typeof pk !== "string" && typeof pk !== "number" && typeof pk !== "boolean") { if (typeof pk !== "string" && typeof pk !== "number" && typeof pk !== "boolean") {
if (Array.isArray(pk) && pk.length > 0) { if (Array.isArray(pk) && pk.length > 0) {
@@ -1431,7 +1425,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
}"] AS p FROM c WHERE NOT IS_DEFINED(c._isEdge)`; }"] AS p FROM c WHERE NOT IS_DEFINED(c._isEdge)`;
return this.executeNonPagedDocDbQuery(q).then( return this.executeNonPagedDocDbQuery(q).then(
(documents: DataModels.DocumentId[]) => { (documents: DataModels.DocumentId[]) => {
const possibleVertices = [] as PossibleVertex[]; let possibleVertices = [] as PossibleVertex[];
$.each(documents, (index: number, item: any) => { $.each(documents, (index: number, item: any) => {
if (highlightedNodeId && item.id === highlightedNodeId) { if (highlightedNodeId && item.id === highlightedNodeId) {
// Exclude highlighed node in the list // Exclude highlighed node in the list
@@ -1445,7 +1439,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
caption: item.p, caption: item.p,
}); });
} else { } else {
if (Object.prototype.hasOwnProperty.call(item, "p")) { if (item.hasOwnProperty("p")) {
possibleVertices.push({ possibleVertices.push({
value: item.id, value: item.id,
caption: item.p[0]["_value"], caption: item.p[0]["_value"],
@@ -1468,17 +1462,17 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
* @param addedEdges * @param addedEdges
* @return promise when done * @return promise when done
*/ */
private editGraphEdges(editedEdges: EditedEdges): Q.Promise<unknown> { private editGraphEdges(editedEdges: EditedEdges): Q.Promise<any> {
const promises = []; let promises = [];
// Drop edges // Drop edges
for (let i = 0; i < editedEdges.droppedIds.length; i++) { for (let i = 0; i < editedEdges.droppedIds.length; i++) {
const id = editedEdges.droppedIds[i]; let id = editedEdges.droppedIds[i];
promises.push(this.removeEdge(id)); promises.push(this.removeEdge(id));
} }
// Add edges // Add edges
for (let i = 0; i < editedEdges.addedEdges.length; i++) { for (let i = 0; i < editedEdges.addedEdges.length; i++) {
const e = editedEdges.addedEdges[i]; let e = editedEdges.addedEdges[i];
promises.push( promises.push(
this.createNewEdge(e).then(() => { this.createNewEdge(e).then(() => {
// Reload neighbors in case we linked to a vertex that isn't loaded in the graph // Reload neighbors in case we linked to a vertex that isn't loaded in the graph
@@ -1531,9 +1525,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
/** /**
* For unit testing purposes * For unit testing purposes
*/ */
public onGraphUpdated(timestamp: number): void {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public onGraphUpdated(_timestamp: number): void {}
/** /**
* Get node properties for styling purposes. Result is the union of all properties of all nodes. * Get node properties for styling purposes. Result is the union of all properties of all nodes.
@@ -1541,17 +1533,17 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
private collectNodeProperties(vertices: GraphData.GremlinVertex[]) { private collectNodeProperties(vertices: GraphData.GremlinVertex[]) {
const props = {} as any; // Hashset const props = {} as any; // Hashset
$.each(vertices, (index: number, item: GraphData.GremlinVertex) => { $.each(vertices, (index: number, item: GraphData.GremlinVertex) => {
for (const p in item) { for (var p in item) {
// DocDB: Exclude type because it's always 'vertex' // DocDB: Exclude type because it's always 'vertex'
if (p !== "type" && typeof (item as any)[p] === "string") { if (p !== "type" && typeof (item as any)[p] === "string") {
props[p] = true; props[p] = true;
} }
} }
// Inspect properties // Inspect properties
if (Object.prototype.hasOwnProperty.call(item, "properties")) { if (item.hasOwnProperty("properties")) {
// TODO This is DocDB-graph specific // TODO This is DocDB-graph specific
// Assume each property value is [{value:... }] // Assume each property value is [{value:... }]
for (const f in item.properties) { for (var f in item.properties) {
props[f] = true; props[f] = true;
} }
} }
@@ -1578,21 +1570,21 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
return; return;
} }
const data = this.originalGraphData.getVertexById(id); let data = this.originalGraphData.getVertexById(id);
// A bit of translation to make it easier to display // A bit of translation to make it easier to display
const props: { [id: string]: ViewModels.GremlinPropertyValueType[] } = {}; let props: { [id: string]: ViewModels.GremlinPropertyValueType[] } = {};
for (const p in data.properties) { for (let p in data.properties) {
props[p] = data.properties[p].map((gremlinProperty) => gremlinProperty.value); props[p] = data.properties[p].map((gremlinProperty) => gremlinProperty.value);
} }
// update neighbors // update neighbors
const sources: NeighborVertexBasicInfo[] = []; let sources: NeighborVertexBasicInfo[] = [];
const targets: NeighborVertexBasicInfo[] = []; let targets: NeighborVertexBasicInfo[] = [];
this.props.onResetDefaultGraphConfigValues(); this.props.onResetDefaultGraphConfigValues();
const nodeCaption = this.state.igraphConfigUiData.nodeCaptionChoice; let nodeCaption = this.state.igraphConfigUiData.nodeCaptionChoice;
this.updateSelectedNodeNeighbors(data.id, nodeCaption, sources, targets); this.updateSelectedNodeNeighbors(data.id, nodeCaption, sources, targets);
const sData: GraphHighlightedNodeData = { let sData: GraphHighlightedNodeData = {
id: data.id, id: data.id,
label: data.label, label: data.label,
properties: props, properties: props,
@@ -1619,16 +1611,16 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
targets: NeighborVertexBasicInfo[] targets: NeighborVertexBasicInfo[]
): void { ): void {
// update neighbors // update neighbors
const gd = this.originalGraphData; let gd = this.originalGraphData;
const v = gd.getVertexById(id); let v = gd.getVertexById(id);
// Clear the array while keeping the references // Clear the array while keeping the references
sources.length = 0; sources.length = 0;
targets.length = 0; targets.length = 0;
const possibleEdgeLabels = {} as any; // Collect all edge labels in a hashset let possibleEdgeLabels = {} as any; // Collect all edge labels in a hashset
for (const p in v.inE) { for (let p in v.inE) {
possibleEdgeLabels[p] = true; possibleEdgeLabels[p] = true;
const edges = v.inE[p]; const edges = v.inE[p];
$.each(edges, (index: number, edge: GraphData.GremlinShortInEdge) => { $.each(edges, (index: number, edge: GraphData.GremlinShortInEdge) => {
@@ -1637,7 +1629,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
// If id not known, it must be an edge node whose neighbor hasn't been loaded into the graph, yet // If id not known, it must be an edge node whose neighbor hasn't been loaded into the graph, yet
return; return;
} }
const caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string; let caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string;
sources.push({ sources.push({
name: caption, name: caption,
id: neighborId, id: neighborId,
@@ -1647,7 +1639,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
}); });
} }
for (const p in v.outE) { for (let p in v.outE) {
possibleEdgeLabels[p] = true; possibleEdgeLabels[p] = true;
const edges = v.outE[p]; const edges = v.outE[p];
$.each(edges, (index: number, edge: GraphData.GremlinShortOutEdge) => { $.each(edges, (index: number, edge: GraphData.GremlinShortOutEdge) => {
@@ -1656,7 +1648,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
// If id not known, it must be an edge node whose neighbor hasn't been loaded into the graph, yet // If id not known, it must be an edge node whose neighbor hasn't been loaded into the graph, yet
return; return;
} }
const caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string; let caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string;
targets.push({ targets.push({
name: caption, name: caption,
id: neighborId, id: neighborId,
@@ -1668,7 +1660,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
this.setState({ this.setState({
possibleEdgeLabels: Object.keys(possibleEdgeLabels).map( possibleEdgeLabels: Object.keys(possibleEdgeLabels).map(
(value: string): InputTypeaheadComponent.Item => { (value: string, index: number, array: string[]): InputTypeaheadComponent.Item => {
return { caption: value, value: value }; return { caption: value, value: value };
} }
), ),
@@ -1689,20 +1681,20 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
return; return;
} }
const updatedVertex = vertices[0]; let updatedVertex = vertices[0];
if (this.originalGraphData.hasVertexId(updatedVertex.id)) { if (this.originalGraphData.hasVertexId(updatedVertex.id)) {
const currentVertex = this.originalGraphData.getVertexById(updatedVertex.id); let currentVertex = this.originalGraphData.getVertexById(updatedVertex.id);
// Copy updated properties // Copy updated properties
if (Object.prototype.hasOwnProperty.call(currentVertex, "properties")) { if (currentVertex.hasOwnProperty("properties")) {
delete currentVertex["properties"]; delete currentVertex["properties"];
} }
for (const p in updatedVertex) { for (var p in updatedVertex) {
(currentVertex as any)[p] = updatedVertex[p]; (currentVertex as any)[p] = updatedVertex[p];
} }
} }
// TODO This kind of assumes saveVertexProperty is done from property panes. // TODO This kind of assumes saveVertexProperty is done from property panes.
const hn = this.state.highlightedNode; let hn = this.state.highlightedNode;
if (hn && hn.id === updatedVertex.id) { if (hn && hn.id === updatedVertex.id) {
this.updatePropertiesPane(hn.id); this.updatePropertiesPane(hn.id);
} }
@@ -1716,7 +1708,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
igraphConfig?: IGraphConfig igraphConfig?: IGraphConfig
) { ) {
this.originalGraphData = graphData; this.originalGraphData = graphData;
const gd = JSON.parse(JSON.stringify(this.originalGraphData)); let gd = JSON.parse(JSON.stringify(this.originalGraphData));
if (!this.d3ForceGraph) { if (!this.d3ForceGraph) {
console.warn("Attempting to update graph, but d3ForceGraph not initialized, yet."); console.warn("Attempting to update graph, but d3ForceGraph not initialized, yet.");
return; return;
@@ -1881,7 +1873,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
promise promise
.then((result: GremlinClient.GremlinRequestResult) => this.processGremlinQueryResults(result)) .then((result: GremlinClient.GremlinRequestResult) => this.processGremlinQueryResults(result))
.catch((error: Error) => { .catch((error: any) => {
const errorMsg = `Failed to process query result: ${getErrorMessage(error)}`; const errorMsg = `Failed to process query result: ${getErrorMessage(error)}`;
GraphExplorer.reportToConsole(ConsoleDataType.Error, errorMsg); GraphExplorer.reportToConsole(ConsoleDataType.Error, errorMsg);
this.setState({ this.setState({

View File

@@ -58,7 +58,7 @@ export class LeftPaneComponent extends React.Component<LeftPaneComponentProps> {
className={className} className={className}
as="tr" as="tr"
aria-label={node.caption} aria-label={node.caption}
onActivated={() => this.props.onRootNodeSelected(node.id)} onActivated={(e) => this.props.onRootNodeSelected(node.id)}
key={node.id} key={node.id}
> >
<td className="resultItem"> <td className="resultItem">

View File

@@ -1,8 +1,8 @@
import React from "react";
import { mount, ReactWrapper } from "enzyme"; import { mount, ReactWrapper } from "enzyme";
import * as Q from "q"; import * as Q from "q";
import React from "react"; import { NodePropertiesComponent, NodePropertiesComponentProps, Mode } from "./NodePropertiesComponent";
import { GraphHighlightedNodeData, PossibleVertex } from "./GraphExplorer"; import { GraphHighlightedNodeData, EditedProperties, EditedEdges, PossibleVertex } from "./GraphExplorer";
import { Mode, NodePropertiesComponent, NodePropertiesComponentProps } from "./NodePropertiesComponent";
describe("Property pane", () => { describe("Property pane", () => {
const title = "My Title"; const title = "My Title";
@@ -37,18 +37,17 @@ describe("Property pane", () => {
return { return {
expandedTitle: title, expandedTitle: title,
isCollapsed: false, isCollapsed: false,
onCollapsedChanged: jest.fn(), onCollapsedChanged: (newValue: boolean): void => {},
node: highlightedNode, node: highlightedNode,
getPkIdFromNodeData: (): string => undefined, getPkIdFromNodeData: (v: GraphHighlightedNodeData): string => null,
collectionPartitionKeyProperty: undefined, collectionPartitionKeyProperty: null,
updateVertexProperties: (): Q.Promise<void> => Q.resolve(), updateVertexProperties: (editedProperties: EditedProperties): Q.Promise<void> => Q.resolve(),
selectNode: jest.fn(), selectNode: (id: string): void => {},
updatePossibleVertices: (): Q.Promise<PossibleVertex[]> => Q.resolve(undefined), updatePossibleVertices: (): Q.Promise<PossibleVertex[]> => Q.resolve(null),
possibleEdgeLabels: undefined, possibleEdgeLabels: null,
//eslint-disable-next-line editGraphEdges: (editedEdges: EditedEdges): Q.Promise<any> => Q.resolve(),
editGraphEdges: (): Q.Promise<any> => Q.resolve(), deleteHighlightedNode: (): void => {},
deleteHighlightedNode: jest.fn(), onModeChanged: (newMode: Mode): void => {},
onModeChanged: jest.fn(),
viewMode: Mode.READONLY_PROP, viewMode: Mode.READONLY_PROP,
}; };
}; };

View File

@@ -72,7 +72,7 @@ export class NodePropertiesComponent extends React.Component<
super(props); super(props);
this.state = { this.state = {
editedProperties: { editedProperties: {
pkId: undefined, pkId: null,
readOnlyProperties: [], readOnlyProperties: [],
existingProperties: [], existingProperties: [],
addedProperties: [], addedProperties: [],
@@ -98,12 +98,15 @@ export class NodePropertiesComponent extends React.Component<
}; };
} }
public static getDerivedStateFromProps(props: NodePropertiesComponentProps): Partial<NodePropertiesComponentState> { public static getDerivedStateFromProps(
props: NodePropertiesComponentProps,
state: NodePropertiesComponentState
): Partial<NodePropertiesComponentState> {
if (props.viewMode !== Mode.READONLY_PROP) { if (props.viewMode !== Mode.READONLY_PROP) {
return { isDeleteConfirm: false }; return { isDeleteConfirm: false };
} }
return undefined; return null;
} }
public render(): JSX.Element { public render(): JSX.Element {
@@ -135,10 +138,10 @@ export class NodePropertiesComponent extends React.Component<
* @param value * @param value
*/ */
private static getTypeOption(value: any): ViewModels.InputPropertyValueTypeString { private static getTypeOption(value: any): ViewModels.InputPropertyValueTypeString {
if (value === undefined) { if (value == null) {
return "null"; return "null";
} }
const type = typeof value; let type = typeof value;
switch (type) { switch (type) {
case "number": case "number":
case "boolean": case "boolean":
@@ -169,9 +172,10 @@ export class NodePropertiesComponent extends React.Component<
]; ];
const existingProps: ViewModels.InputProperty[] = []; const existingProps: ViewModels.InputProperty[] = [];
if (this.props.node.hasOwnProperty("properties")) { if (this.props.node.hasOwnProperty("properties")) {
const hProps = this.props.node["properties"]; const hProps = this.props.node["properties"];
for (const p in hProps) { for (let p in hProps) {
const propValues = hProps[p]; const propValues = hProps[p];
(p === partitionKeyProperty ? readOnlyProps : existingProps).push({ (p === partitionKeyProperty ? readOnlyProps : existingProps).push({
key: p, key: p,
@@ -433,7 +437,7 @@ export class NodePropertiesComponent extends React.Component<
</div> </div>
); );
} else { } else {
return undefined; return null;
} }
} }

View File

@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { CellId, CellType, ImmutableNotebook } from "@nteract/commutable"; import { CellId, CellType, ImmutableNotebook } from "@nteract/commutable";
// Vendor modules // Vendor modules
import { import {
@@ -31,19 +30,6 @@ export interface NotebookComponentBootstrapperOptions {
contentRef: ContentRef; contentRef: ContentRef;
} }
interface IWrapModel {
name: string;
path: string;
last_modified: Date;
created: string;
content: unknown;
format: string;
mimetype: unknown;
size: number;
writeable: boolean;
type: string;
}
export class NotebookComponentBootstrapper { export class NotebookComponentBootstrapper {
public contentRef: ContentRef; public contentRef: ContentRef;
protected renderExtraComponent: () => JSX.Element; protected renderExtraComponent: () => JSX.Element;
@@ -55,7 +41,7 @@ export class NotebookComponentBootstrapper {
this.contentRef = options.contentRef; this.contentRef = options.contentRef;
} }
protected static wrapModelIntoContent(name: string, path: string, content: unknown): IWrapModel { protected static wrapModelIntoContent(name: string, path: string, content: any) {
return { return {
name, name,
path, path,
@@ -63,7 +49,7 @@ export class NotebookComponentBootstrapper {
created: "", created: "",
content, content,
format: "json", format: "json",
mimetype: undefined, mimetype: null as any,
size: 0, size: 0,
writeable: false, writeable: false,
type: "notebook", type: "notebook",
@@ -99,7 +85,7 @@ export class NotebookComponentBootstrapper {
}; };
} }
public setContent(name: string, content: unknown): void { public setContent(name: string, content: any): void {
this.getStore().dispatch( this.getStore().dispatch(
actions.fetchContentFulfilled({ actions.fetchContentFulfilled({
filepath: undefined, filepath: undefined,
@@ -284,6 +270,7 @@ export class NotebookComponentBootstrapper {
public isContentDirty(): boolean { public isContentDirty(): boolean {
const content = selectors.content(this.getStore().getState(), { contentRef: this.contentRef }); const content = selectors.content(this.getStore().getState(), { contentRef: this.contentRef });
if (!content) { if (!content) {
console.log("No error");
return false; return false;
} }

View File

@@ -16,10 +16,9 @@ import "./NotebookReadOnlyRenderer.less";
import SandboxOutputs from "./outputs/SandboxOutputs"; import SandboxOutputs from "./outputs/SandboxOutputs";
export interface NotebookRendererProps { export interface NotebookRendererProps {
contentRef: ContentRef; contentRef: any;
hideInputs?: boolean; hideInputs?: boolean;
hidePrompts?: boolean; hidePrompts?: boolean;
addTransform: (component: React.ComponentType & { MIMETYPE: string }) => void;
} }
/** /**
@@ -28,7 +27,7 @@ export interface NotebookRendererProps {
class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> { class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
componentDidMount() { componentDidMount() {
if (!userContext.features.sandboxNotebookOutputs) { if (!userContext.features.sandboxNotebookOutputs) {
loadTransform(this.props as NotebookRendererProps); loadTransform(this.props as any);
} }
} }
@@ -60,7 +59,7 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
<div className="NotebookReadOnlyRender"> <div className="NotebookReadOnlyRender">
<Cells contentRef={this.props.contentRef}> <Cells contentRef={this.props.contentRef}>
{{ {{
code: ({ id, contentRef }: { id: string; contentRef: ContentRef }) => ( code: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => (
<CodeCell id={id} contentRef={contentRef}> <CodeCell id={id} contentRef={contentRef}>
{{ {{
prompt: (props: { id: string; contentRef: string }) => this.renderPrompt(props.id, props.contentRef), prompt: (props: { id: string; contentRef: string }) => this.renderPrompt(props.id, props.contentRef),
@@ -74,14 +73,14 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
}} }}
</CodeCell> </CodeCell>
), ),
markdown: ({ id, contentRef }: { id: string; contentRef: ContentRef }) => ( markdown: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => (
<MarkdownCell id={id} contentRef={contentRef} cell_type="markdown"> <MarkdownCell id={id} contentRef={contentRef} cell_type="markdown">
{{ {{
editor: {}, editor: {},
}} }}
</MarkdownCell> </MarkdownCell>
), ),
raw: ({ id, contentRef }: { id: string; contentRef: ContentRef }) => ( raw: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => (
<RawCell id={id} contentRef={contentRef} cell_type="raw"> <RawCell id={id} contentRef={contentRef} cell_type="raw">
{{ {{
editor: { editor: {
@@ -99,7 +98,6 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
} }
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: NotebookRendererProps) => { const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: NotebookRendererProps) => {
const mapDispatchToProps = (dispatch: Dispatch) => { const mapDispatchToProps = (dispatch: Dispatch) => {
return { return {
@@ -116,4 +114,4 @@ const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: Noteboo
return mapDispatchToProps; return mapDispatchToProps;
}; };
export default connect(undefined, makeMapDispatchToProps)(NotebookReadOnlyRenderer); export default connect(null, makeMapDispatchToProps)(NotebookReadOnlyRenderer);

View File

@@ -31,12 +31,13 @@ import StatusBar from "./StatusBar";
import CellToolbar from "./Toolbar"; import CellToolbar from "./Toolbar";
export interface NotebookRendererBaseProps { export interface NotebookRendererBaseProps {
contentRef: any; contentRef: ContentRef;
} }
interface NotebookRendererDispatchProps { interface NotebookRendererDispatchProps {
storeNotebookSnapshot: (imageSrc: string, requestId: string) => void; storeNotebookSnapshot: (imageSrc: string, requestId: string) => void;
notebookSnapshotError: (error: string) => void; notebookSnapshotError: (error: string) => void;
addTransform: (transform: React.ComponentType & { MIMETYPE: string }) => void;
} }
interface StateProps { interface StateProps {
@@ -73,7 +74,7 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
componentDidMount() { componentDidMount() {
if (!userContext.features.sandboxNotebookOutputs) { if (!userContext.features.sandboxNotebookOutputs) {
loadTransform(this.props as any); loadTransform(this.props as NotebookRendererProps);
} }
} }
@@ -138,7 +139,7 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
}} }}
</CodeCell> </CodeCell>
), ),
markdown: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => markdown: ({ id, contentRef }: { id: CellId; contentRef: ContentRef }) =>
decorate( decorate(
id, id,
contentRef, contentRef,
@@ -155,7 +156,7 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
</MarkdownCell> </MarkdownCell>
), ),
raw: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => raw: ({ id, contentRef }: { id: CellId; contentRef: ContentRef }) =>
decorate( decorate(
id, id,
contentRef, contentRef,
@@ -202,7 +203,8 @@ export const makeMapStateToProps = (
return mapStateToProps; return mapStateToProps;
}; };
const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: NotebookRendererBaseProps) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars
const makeMapDispatchToProps = (_initialDispatch: Dispatch, _initialProps: NotebookRendererBaseProps) => {
const mapDispatchToProps = (dispatch: Dispatch) => { const mapDispatchToProps = (dispatch: Dispatch) => {
return { return {
addTransform: (transform: React.ComponentType & { MIMETYPE: string }) => addTransform: (transform: React.ComponentType & { MIMETYPE: string }) =>

View File

@@ -4,8 +4,6 @@ import * as React from "react";
import { useFullScreenURLs } from "../hooks/useFullScreenURLs"; import { useFullScreenURLs } from "../hooks/useFullScreenURLs";
export const OpenFullScreen: React.FunctionComponent = () => { export const OpenFullScreen: React.FunctionComponent = () => {
const [isReadUrlCopy, setIsReadUrlCopy] = React.useState<boolean>(false);
const [isReadWriteUrlCopy, setIsReadWriteUrlCopy] = React.useState<boolean>(false);
const result = useFullScreenURLs(); const result = useFullScreenURLs();
if (!result) { if (!result) {
return <Spinner label="Generating URLs..." ariaLive="assertive" labelPosition="right" />; return <Spinner label="Generating URLs..." ariaLive="assertive" labelPosition="right" />;
@@ -27,9 +25,8 @@ export const OpenFullScreen: React.FunctionComponent = () => {
<DefaultButton <DefaultButton
onClick={() => { onClick={() => {
copyToClipboard(readWriteUrl); copyToClipboard(readWriteUrl);
setIsReadWriteUrlCopy(true);
}} }}
text={isReadWriteUrlCopy ? "Copied" : "Copy"} text="Copy"
iconProps={{ iconName: "Copy" }} iconProps={{ iconName: "Copy" }}
/> />
<PrimaryButton <PrimaryButton
@@ -44,10 +41,9 @@ export const OpenFullScreen: React.FunctionComponent = () => {
<Stack horizontal tokens={{ childrenGap: 10 }}> <Stack horizontal tokens={{ childrenGap: 10 }}>
<DefaultButton <DefaultButton
onClick={() => { onClick={() => {
setIsReadUrlCopy(true);
copyToClipboard(readUrl); copyToClipboard(readUrl);
}} }}
text={isReadUrlCopy ? "Copied" : "Copy"} text="Copy"
iconProps={{ iconName: "Copy" }} iconProps={{ iconName: "Copy" }}
/> />
<PrimaryButton <PrimaryButton

View File

@@ -13,21 +13,21 @@ import {
Text, Text,
TooltipHost, TooltipHost,
} from "@fluentui/react"; } from "@fluentui/react";
import * as Constants from "Common/Constants";
import { createCollection } from "Common/dataAccess/createCollection";
import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import { configContext, Platform } from "ConfigContext";
import * as DataModels from "Contracts/DataModels";
import { SubscriptionType } from "Contracts/SubscriptionType";
import { useSidePanel } from "hooks/useSidePanel";
import React from "react"; import React from "react";
import { CollectionCreation } from "Shared/Constants"; import * as Constants from "../../Common/Constants";
import { Action } from "Shared/Telemetry/TelemetryConstants"; import { createCollection } from "../../Common/dataAccess/createCollection";
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import { userContext } from "UserContext"; import { configContext, Platform } from "../../ConfigContext";
import { getCollectionName } from "Utils/APITypeUtils"; import * as DataModels from "../../Contracts/DataModels";
import { isCapabilityEnabled, isServerlessAccount } from "Utils/CapabilityUtils"; import { SubscriptionType } from "../../Contracts/SubscriptionType";
import { getUpsellMessage } from "Utils/PricingUtils"; import { useSidePanel } from "../../hooks/useSidePanel";
import { CollectionCreation } from "../../Shared/Constants";
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../UserContext";
import { getCollectionName } from "../../Utils/APITypeUtils";
import { isCapabilityEnabled, isServerlessAccount } from "../../Utils/CapabilityUtils";
import { getUpsellMessage } from "../../Utils/PricingUtils";
import { CollapsibleSectionComponent } from "../Controls/CollapsiblePanel/CollapsibleSectionComponent"; import { CollapsibleSectionComponent } from "../Controls/CollapsiblePanel/CollapsibleSectionComponent";
import { ThroughputInput } from "../Controls/ThroughputInput/ThroughputInput"; import { ThroughputInput } from "../Controls/ThroughputInput/ThroughputInput";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
@@ -999,7 +999,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
const collectionId: string = this.state.collectionId.trim(); const collectionId: string = this.state.collectionId.trim();
let databaseId = this.state.createNewDatabase ? this.state.newDatabaseId.trim() : this.state.selectedDatabaseId; let databaseId = this.state.createNewDatabase ? this.state.newDatabaseId.trim() : this.state.selectedDatabaseId;
let partitionKeyString = this.state.isSharded ? this.state.partitionKey.trim() : undefined; let partitionKeyString = this.state.partitionKey.trim();
if (userContext.apiType === "Tables") { if (userContext.apiType === "Tables") {
// Table require fixed Database: TablesDB, and fixed Partition Key: /'$pk' // Table require fixed Database: TablesDB, and fixed Partition Key: /'$pk'

View File

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

View File

@@ -1,14 +1,14 @@
import { Checkbox, Dropdown, IDropdownOption, Link, Stack, Text, TextField } from "@fluentui/react"; import { Checkbox, Dropdown, IDropdownOption, Link, Stack, Text, TextField } from "@fluentui/react";
import * as Constants from "Common/Constants";
import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import { InfoTooltip } from "Common/Tooltip/InfoTooltip";
import { useSidePanel } from "hooks/useSidePanel";
import React, { FunctionComponent, useState } from "react"; import React, { FunctionComponent, useState } from "react";
import * as SharedConstants from "Shared/Constants"; import * as Constants from "../../../Common/Constants";
import { Action } from "Shared/Telemetry/TelemetryConstants"; import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor"; import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
import { userContext } from "UserContext"; import { useSidePanel } from "../../../hooks/useSidePanel";
import { isServerlessAccount } from "Utils/CapabilityUtils"; import * as SharedConstants from "../../../Shared/Constants";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../../UserContext";
import { isServerlessAccount } from "../../../Utils/CapabilityUtils";
import { ThroughputInput } from "../../Controls/ThroughputInput/ThroughputInput"; import { ThroughputInput } from "../../Controls/ThroughputInput/ThroughputInput";
import Explorer from "../../Explorer"; import Explorer from "../../Explorer";
import { CassandraAPIDataClient } from "../../Tables/TableDataClient"; import { CassandraAPIDataClient } from "../../Tables/TableDataClient";

View File

@@ -1,18 +1,18 @@
import { Text, TextField } from "@fluentui/react"; import { Text, TextField } from "@fluentui/react";
import { Areas } from "Common/Constants";
import { deleteCollection } from "Common/dataAccess/deleteCollection";
import DeleteFeedback from "Common/DeleteFeedback";
import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import { Collection } from "Contracts/ViewModels";
import { useSidePanel } from "hooks/useSidePanel";
import { useTabs } from "hooks/useTabs";
import React, { FunctionComponent, useState } from "react"; import React, { FunctionComponent, useState } from "react";
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility"; import { Areas } from "../../../Common/Constants";
import { Action, ActionModifiers } from "Shared/Telemetry/TelemetryConstants"; import { deleteCollection } from "../../../Common/dataAccess/deleteCollection";
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor"; import DeleteFeedback from "../../../Common/DeleteFeedback";
import { userContext } from "UserContext"; import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
import { getCollectionName } from "Utils/APITypeUtils"; import { Collection } from "../../../Contracts/ViewModels";
import * as NotificationConsoleUtils from "Utils/NotificationConsoleUtils"; import { useSidePanel } from "../../../hooks/useSidePanel";
import { useTabs } from "../../../hooks/useTabs";
import { DefaultExperienceUtility } from "../../../Shared/DefaultExperienceUtility";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../../UserContext";
import { getCollectionName } from "../../../Utils/APITypeUtils";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import { useDatabases } from "../../useDatabases"; import { useDatabases } from "../../useDatabases";
import { useSelectedNode } from "../../useSelectedNode"; import { useSelectedNode } from "../../useSelectedNode";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";

View File

@@ -1,18 +1,18 @@
import { Text, TextField } from "@fluentui/react"; import { Text, TextField } from "@fluentui/react";
import { useBoolean } from "@fluentui/react-hooks"; import { useBoolean } from "@fluentui/react-hooks";
import { Areas } from "Common/Constants";
import { deleteDatabase } from "Common/dataAccess/deleteDatabase";
import DeleteFeedback from "Common/DeleteFeedback";
import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import { Collection, Database } from "Contracts/ViewModels";
import { useSidePanel } from "hooks/useSidePanel";
import { useTabs } from "hooks/useTabs";
import React, { FunctionComponent, useState } from "react"; import React, { FunctionComponent, useState } from "react";
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility"; import { Areas } from "../../Common/Constants";
import { Action, ActionModifiers } from "Shared/Telemetry/TelemetryConstants"; import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor"; import DeleteFeedback from "../../Common/DeleteFeedback";
import { userContext } from "UserContext"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import { logConsoleError } from "Utils/NotificationConsoleUtils"; import { Collection, Database } from "../../Contracts/ViewModels";
import { useSidePanel } from "../../hooks/useSidePanel";
import { useTabs } from "../../hooks/useTabs";
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../UserContext";
import { logConsoleError } from "../../Utils/NotificationConsoleUtils";
import { useDatabases } from "../useDatabases"; import { useDatabases } from "../useDatabases";
import { useSelectedNode } from "../useSelectedNode"; import { useSelectedNode } from "../useSelectedNode";
import { PanelInfoErrorComponent, PanelInfoErrorProps } from "./PanelInfoErrorComponent"; import { PanelInfoErrorComponent, PanelInfoErrorProps } from "./PanelInfoErrorComponent";

View File

@@ -1,13 +1,13 @@
import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton } from "@fluentui/react"; import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton } from "@fluentui/react";
import * as Constants from "Common/Constants";
import { InfoTooltip } from "Common/Tooltip/InfoTooltip";
import { configContext } from "ConfigContext";
import { useSidePanel } from "hooks/useSidePanel";
import React, { FunctionComponent, MouseEvent, useState } from "react"; import React, { FunctionComponent, MouseEvent, useState } from "react";
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility"; import * as Constants from "../../../Common/Constants";
import * as StringUtility from "Shared/StringUtility"; import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
import { userContext } from "UserContext"; import { configContext } from "../../../ConfigContext";
import { logConsoleInfo } from "Utils/NotificationConsoleUtils"; import { useSidePanel } from "../../../hooks/useSidePanel";
import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
import * as StringUtility from "../../../Shared/StringUtility";
import { userContext } from "../../../UserContext";
import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
export const SettingsPane: FunctionComponent = () => { export const SettingsPane: FunctionComponent = () => {

View File

@@ -1,8 +1,8 @@
import { TextField } from "@fluentui/react"; import { TextField } from "@fluentui/react";
import * as ViewModels from "Contracts/ViewModels";
import { useTabs } from "hooks/useTabs";
import React, { FormEvent, FunctionComponent, useState } from "react"; import React, { FormEvent, FunctionComponent, useState } from "react";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "Utils/NotificationConsoleUtils"; import * as ViewModels from "../../../Contracts/ViewModels";
import { useTabs } from "../../../hooks/useTabs";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
import * as FileSystemUtil from "../../Notebook/FileSystemUtil"; import * as FileSystemUtil from "../../Notebook/FileSystemUtil";
import { NotebookContentItem } from "../../Notebook/NotebookContentItem"; import { NotebookContentItem } from "../../Notebook/NotebookContentItem";
import NotebookV2Tab from "../../Tabs/NotebookV2Tab"; import NotebookV2Tab from "../../Tabs/NotebookV2Tab";

View File

@@ -1,7 +1,7 @@
import { Upload } from "Common/Upload/Upload";
import { useSidePanel } from "hooks/useSidePanel";
import React, { ChangeEvent, FunctionComponent, useState } from "react"; import React, { ChangeEvent, FunctionComponent, useState } from "react";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "Utils/NotificationConsoleUtils"; import { Upload } from "../../../Common/Upload/Upload";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
import { NotebookContentItem } from "../../Notebook/NotebookContentItem"; import { NotebookContentItem } from "../../Notebook/NotebookContentItem";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";

View File

@@ -1,8 +1,8 @@
import { DetailsList, DetailsListLayoutMode, IColumn, SelectionMode } from "@fluentui/react"; import { DetailsList, DetailsListLayoutMode, IColumn, SelectionMode } from "@fluentui/react";
import { Upload } from "Common/Upload/Upload";
import { UploadDetailsRecord } from "Contracts/ViewModels";
import React, { ChangeEvent, FunctionComponent, useState } from "react"; import React, { ChangeEvent, FunctionComponent, useState } from "react";
import { logConsoleError } from "Utils/NotificationConsoleUtils"; import { Upload } from "../../../Common/Upload/Upload";
import { UploadDetailsRecord } from "../../../Contracts/ViewModels";
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
import { getErrorMessage } from "../../Tables/Utilities"; import { getErrorMessage } from "../../Tables/Utilities";
import { useSelectedNode } from "../../useSelectedNode"; import { useSelectedNode } from "../../useSelectedNode";
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";

View File

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

View File

@@ -1,11 +1,12 @@
import Q from "q";
import _ from "underscore"; import _ from "underscore";
import * as QueryBuilderConstants from "../Constants"; import Q from "q";
import * as Entities from "../Entities"; import * as Entities from "../Entities";
import * as QueryBuilderConstants from "../Constants";
import * as Utilities from "../Utilities"; import * as Utilities from "../Utilities";
export function getRowSelector(selectorSchema: Entities.IProperty[]): string { export function getRowSelector(selectorSchema: Entities.IProperty[]): string {
let selector = ""; var selector: string = "";
selectorSchema && selectorSchema &&
selectorSchema.forEach((p: Entities.IProperty) => { selectorSchema.forEach((p: Entities.IProperty) => {
selector += "[" + p.key + '="' + Utilities.jQuerySelectorEscape(p.value) + '"]'; selector += "[" + p.key + '="' + Utilities.jQuerySelectorEscape(p.value) + '"]';
@@ -14,10 +15,10 @@ export function getRowSelector(selectorSchema: Entities.IProperty[]): string {
} }
export function isRowVisible(dataTableScrollBodyQuery: JQuery, element: HTMLElement): boolean { export function isRowVisible(dataTableScrollBodyQuery: JQuery, element: HTMLElement): boolean {
let isVisible = false; var isVisible = false;
if (dataTableScrollBodyQuery.length && element) { if (dataTableScrollBodyQuery.length && element) {
const elementRect: ClientRect = element.getBoundingClientRect(), var elementRect: ClientRect = element.getBoundingClientRect(),
dataTableScrollBodyRect: ClientRect = dataTableScrollBodyQuery.get(0).getBoundingClientRect(); dataTableScrollBodyRect: ClientRect = dataTableScrollBodyQuery.get(0).getBoundingClientRect();
isVisible = elementRect.bottom <= dataTableScrollBodyRect.bottom && dataTableScrollBodyRect.top <= elementRect.top; isVisible = elementRect.bottom <= dataTableScrollBodyRect.bottom && dataTableScrollBodyRect.top <= elementRect.top;
@@ -28,17 +29,17 @@ export function isRowVisible(dataTableScrollBodyQuery: JQuery, element: HTMLElem
export function scrollToRowIfNeeded(dataTableRows: JQuery, currentIndex: number, isScrollUp: boolean): void { export function scrollToRowIfNeeded(dataTableRows: JQuery, currentIndex: number, isScrollUp: boolean): void {
if (dataTableRows.length) { if (dataTableRows.length) {
const dataTableScrollBodyQuery: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector), var dataTableScrollBodyQuery: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector),
selectedRowElement: HTMLElement = dataTableRows.get(currentIndex); selectedRowElement: HTMLElement = dataTableRows.get(currentIndex);
if (dataTableScrollBodyQuery.length && selectedRowElement) { if (dataTableScrollBodyQuery.length && selectedRowElement) {
const isVisible: boolean = isRowVisible(dataTableScrollBodyQuery, selectedRowElement); var isVisible: boolean = isRowVisible(dataTableScrollBodyQuery, selectedRowElement);
if (!isVisible) { if (!isVisible) {
const selectedRowQuery: JQuery = $(selectedRowElement), var selectedRowQuery: JQuery = $(selectedRowElement),
scrollPosition: number = dataTableScrollBodyQuery.scrollTop(), scrollPosition: number = dataTableScrollBodyQuery.scrollTop(),
selectedElementPosition: number = selectedRowQuery.position().top; selectedElementPosition: number = selectedRowQuery.position().top,
let newScrollPosition = 0; newScrollPosition: number = 0;
if (isScrollUp) { if (isScrollUp) {
newScrollPosition = scrollPosition + selectedElementPosition; newScrollPosition = scrollPosition + selectedElementPosition;
@@ -54,7 +55,7 @@ export function scrollToRowIfNeeded(dataTableRows: JQuery, currentIndex: number,
} }
export function scrollToTopIfNeeded(): void { export function scrollToTopIfNeeded(): void {
const $dataTableRows: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableAllRowsSelector), var $dataTableRows: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableAllRowsSelector),
$dataTableScrollBody: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector); $dataTableScrollBody: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector);
if ($dataTableRows.length && $dataTableScrollBody.length) { if ($dataTableRows.length && $dataTableScrollBody.length) {
@@ -87,14 +88,13 @@ export function reorderColumns(
table: DataTables.DataTable, table: DataTables.DataTable,
targetOrder: number[], targetOrder: number[],
currentOrder?: number[] currentOrder?: number[]
//eslint-disable-next-line
): Q.Promise<any> { ): Q.Promise<any> {
const columnsCount: number = targetOrder.length; var columnsCount: number = targetOrder.length;
const isCurrentOrderPassedIn = !!currentOrder; var isCurrentOrderPassedIn: boolean = !!currentOrder;
if (!isCurrentOrderPassedIn) { if (!isCurrentOrderPassedIn) {
currentOrder = getInitialOrder(columnsCount); currentOrder = getInitialOrder(columnsCount);
} }
const isSameOrder: boolean = Utilities.isEqual(currentOrder, targetOrder); var isSameOrder: boolean = Utilities.isEqual(currentOrder, targetOrder);
// if the targetOrder is the same as current order, do nothing. // if the targetOrder is the same as current order, do nothing.
if (!isSameOrder) { if (!isSameOrder) {
@@ -104,7 +104,7 @@ export function reorderColumns(
// Then the transformation order will be the same as target order. // Then the transformation order will be the same as target order.
// If current order is specified, then a transformation order is calculated. // If current order is specified, then a transformation order is calculated.
// Refer to calculateTransformationOrder for details about transformation order. // Refer to calculateTransformationOrder for details about transformation order.
const transformationOrder: number[] = isCurrentOrderPassedIn var transformationOrder: number[] = isCurrentOrderPassedIn
? calculateTransformationOrder(currentOrder, targetOrder) ? calculateTransformationOrder(currentOrder, targetOrder)
: targetOrder; : targetOrder;
try { try {
@@ -143,7 +143,7 @@ export function getCurrentOrder(table: DataTables.DataTable): number[] {
* Result: [0, 1, 2, 5, 6, 7, 3, 4, 8] * Result: [0, 1, 2, 5, 6, 7, 3, 4, 8]
*/ */
export function invertIndexValues(inputArray: number[]): number[] { export function invertIndexValues(inputArray: number[]): number[] {
const invertedArray: number[] = []; var invertedArray: number[] = [];
if (inputArray) { if (inputArray) {
inputArray.forEach((value: number, index: number) => { inputArray.forEach((value: number, index: number) => {
invertedArray[inputArray[index]] = index; invertedArray[inputArray[index]] = index;
@@ -170,21 +170,20 @@ export function invertIndexValues(inputArray: number[]): number[] {
* transformation order: Trans = [0, 1, 2, 7, 3, 4, 8, 5, 6] * transformation order: Trans = [0, 1, 2, 7, 3, 4, 8, 5, 6]
*/ */
export function calculateTransformationOrder(currentOrder: number[], targetOrder: number[]): number[] { export function calculateTransformationOrder(currentOrder: number[], targetOrder: number[]): number[] {
let transformationOrder: number[] = []; var transformationOrder: number[] = [];
if (currentOrder && targetOrder && currentOrder.length === targetOrder.length) { if (currentOrder && targetOrder && currentOrder.length === targetOrder.length) {
const invertedCurrentOrder: number[] = invertIndexValues(currentOrder); var invertedCurrentOrder: number[] = invertIndexValues(currentOrder);
transformationOrder = targetOrder.map((value: number) => invertedCurrentOrder[value]); transformationOrder = targetOrder.map((value: number) => invertedCurrentOrder[value]);
} }
return transformationOrder; return transformationOrder;
} }
export function getDataTableHeaders(table: DataTables.DataTable): string[] { export function getDataTableHeaders(table: DataTables.DataTable): string[] {
const columns: DataTables.ColumnsMethods = table.columns(); var columns: DataTables.ColumnsMethods = table.columns();
let headers: string[] = []; var headers: string[] = [];
if (columns) { if (columns) {
// table.columns() return ColumnsMethods which is an array of arrays // table.columns() return ColumnsMethods which is an array of arrays
//eslint-disable-next-line var columnIndexes: number[] = (<any>columns)[0];
const columnIndexes: number[] = (<any>columns)[0];
if (columnIndexes) { if (columnIndexes) {
headers = columnIndexes.map((value: number) => $(table.columns(value).header()).html()); headers = columnIndexes.map((value: number) => $(table.columns(value).header()).html());
} }

View File

@@ -8,11 +8,11 @@ import TableEntityListViewModel from "./TableEntityListViewModel";
export default class TableCommands { export default class TableCommands {
// Command Ids // Command Ids
public static editEntityCommand = "edit"; public static editEntityCommand: string = "edit";
public static deleteEntitiesCommand = "delete"; public static deleteEntitiesCommand: string = "delete";
public static reorderColumnsCommand = "reorder"; public static reorderColumnsCommand: string = "reorder";
public static resetColumnsCommand = "reset"; public static resetColumnsCommand: string = "reset";
public static customizeColumnsCommand = "customizeColumns"; public static customizeColumnsCommand: string = "customizeColumns";
private _container: Explorer; private _container: Explorer;
@@ -21,8 +21,8 @@ export default class TableCommands {
} }
public isEnabled(commandName: string, selectedEntites: Entities.ITableEntity[]): boolean { public isEnabled(commandName: string, selectedEntites: Entities.ITableEntity[]): boolean {
const singleItemSelected = DataTableUtilities.containSingleItem(selectedEntites); var singleItemSelected: boolean = DataTableUtilities.containSingleItem(selectedEntites);
const atLeastOneItemSelected = DataTableUtilities.containItems(selectedEntites); var atLeastOneItemSelected: boolean = DataTableUtilities.containItems(selectedEntites);
switch (commandName) { switch (commandName) {
case TableCommands.editEntityCommand: case TableCommands.editEntityCommand:
return singleItemSelected; return singleItemSelected;
@@ -47,7 +47,6 @@ export default class TableCommands {
/** /**
* Edit entity * Edit entity
*/ */
//eslint-disable-next-line
public editEntityCommand(viewModel: TableEntityListViewModel): Q.Promise<any> { public editEntityCommand(viewModel: TableEntityListViewModel): Q.Promise<any> {
if (!viewModel) { if (!viewModel) {
return null; // Error return null; // Error
@@ -57,9 +56,12 @@ export default class TableCommands {
return null; // Erorr return null; // Erorr
} }
var entityToUpdate: Entities.ITableEntity = viewModel.selected()[0];
var originalNumberOfProperties = entityToUpdate ? 0 : Object.keys(entityToUpdate).length - 1; // .metadata is always a property for etag
return null; return null;
} }
//eslint-disable-next-line
public deleteEntitiesCommand(viewModel: TableEntityListViewModel): Q.Promise<any> { public deleteEntitiesCommand(viewModel: TableEntityListViewModel): Q.Promise<any> {
if (!viewModel) { if (!viewModel) {
return null; // Error return null; // Error
@@ -67,7 +69,7 @@ export default class TableCommands {
if (!DataTableUtilities.containItems(viewModel.selected())) { if (!DataTableUtilities.containItems(viewModel.selected())) {
return null; // Error return null; // Error
} }
const entitiesToDelete: Entities.ITableEntity[] = viewModel.selected(); var entitiesToDelete: Entities.ITableEntity[] = viewModel.selected();
const deleteMessage: string = const deleteMessage: string =
userContext.apiType === "Cassandra" userContext.apiType === "Cassandra"
? "Are you sure you want to delete the selected rows?" ? "Are you sure you want to delete the selected rows?"
@@ -80,7 +82,7 @@ export default class TableCommands {
() => { () => {
viewModel.queryTablesTab.container.tableDataClient viewModel.queryTablesTab.container.tableDataClient
.deleteDocuments(viewModel.queryTablesTab.collection, entitiesToDelete) .deleteDocuments(viewModel.queryTablesTab.collection, entitiesToDelete)
.then(() => { .then((results: any) => {
return viewModel.removeEntitiesFromCache(entitiesToDelete).then(() => { return viewModel.removeEntitiesFromCache(entitiesToDelete).then(() => {
viewModel.redrawTableThrottled(); viewModel.redrawTableThrottled();
}); });

View File

@@ -1,5 +1,5 @@
import * as Entities from "../Entities";
import * as Utilities from "../Utilities"; import * as Utilities from "../Utilities";
import * as Entities from "../Entities";
import CacheBase from "./CacheBase"; import CacheBase from "./CacheBase";
export default class TableEntityCache extends CacheBase<Entities.ITableEntity> { export default class TableEntityCache extends CacheBase<Entities.ITableEntity> {
@@ -21,7 +21,7 @@ export default class TableEntityCache extends CacheBase<Entities.ITableEntity> {
this._tableQuery = Utilities.copyTableQuery(tableQuery); this._tableQuery = Utilities.copyTableQuery(tableQuery);
} }
public preClear(): void { public preClear() {
this.tableQuery = null; this.tableQuery = null;
} }
} }

View File

@@ -1,4 +1,4 @@
import { ItemDefinition, QueryIterator, Resource } from "@azure/cosmos"; import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
export interface ITableEntity { export interface ITableEntity {
[property: string]: ITableEntityAttribute; [property: string]: ITableEntityAttribute;
@@ -17,7 +17,6 @@ export interface ITableEntityAttribute {
export interface IListTableEntitiesResult { export interface IListTableEntitiesResult {
Results: ITableEntity[]; Results: ITableEntity[];
//eslint-disable-next-line
ContinuationToken: any; ContinuationToken: any;
iterator?: QueryIterator<ItemDefinition & Resource>; iterator?: QueryIterator<ItemDefinition & Resource>;
} }

View File

@@ -1,9 +1,8 @@
import * as Utilities from "../Utilities";
import QueryClauseViewModel from "./QueryClauseViewModel"; import QueryClauseViewModel from "./QueryClauseViewModel";
import * as Utilities from "../Utilities";
export default class ClauseGroup { export default class ClauseGroup {
public isRootGroup: boolean; public isRootGroup: boolean;
//eslint-disable-next-line
public children = new Array(); public children = new Array();
public parentGroup: ClauseGroup; public parentGroup: ClauseGroup;
private _id: string; private _id: string;
@@ -18,7 +17,7 @@ export default class ClauseGroup {
* Flattens the clause tree into an array, depth-first, left to right. * Flattens the clause tree into an array, depth-first, left to right.
*/ */
public flattenClauses(targetArray: ko.ObservableArray<QueryClauseViewModel>): void { public flattenClauses(targetArray: ko.ObservableArray<QueryClauseViewModel>): void {
const tempArray = new Array<QueryClauseViewModel>(); var tempArray = new Array<QueryClauseViewModel>();
this.flattenClausesImpl(this, tempArray); this.flattenClausesImpl(this, tempArray);
targetArray.removeAll(); targetArray.removeAll();
@@ -32,10 +31,10 @@ export default class ClauseGroup {
newClause.clauseGroup = this; newClause.clauseGroup = this;
this.children.push(newClause); this.children.push(newClause);
} else { } else {
const targetGroup = insertBefore.clauseGroup; var targetGroup = insertBefore.clauseGroup;
if (targetGroup) { if (targetGroup) {
const insertBeforeIndex = targetGroup.children.indexOf(insertBefore); var insertBeforeIndex = targetGroup.children.indexOf(insertBefore);
newClause.clauseGroup = targetGroup; newClause.clauseGroup = targetGroup;
targetGroup.children.splice(insertBeforeIndex, 0, newClause); targetGroup.children.splice(insertBeforeIndex, 0, newClause);
} }
@@ -43,19 +42,19 @@ export default class ClauseGroup {
} }
public deleteClause(clause: QueryClauseViewModel): void { public deleteClause(clause: QueryClauseViewModel): void {
const targetGroup = clause.clauseGroup; var targetGroup = clause.clauseGroup;
if (targetGroup) { if (targetGroup) {
const index = targetGroup.children.indexOf(clause); var index = targetGroup.children.indexOf(clause);
targetGroup.children.splice(index, 1); targetGroup.children.splice(index, 1);
clause.dispose(); clause.dispose();
if (targetGroup.children.length <= 1 && !targetGroup.isRootGroup) { if (targetGroup.children.length <= 1 && !targetGroup.isRootGroup) {
const parent = targetGroup.parentGroup; var parent = targetGroup.parentGroup;
const targetGroupIndex = parent.children.indexOf(targetGroup); var targetGroupIndex = parent.children.indexOf(targetGroup);
if (targetGroup.children.length === 1) { if (targetGroup.children.length === 1) {
const orphan = targetGroup.children.shift(); var orphan = targetGroup.children.shift();
if (orphan instanceof QueryClauseViewModel) { if (orphan instanceof QueryClauseViewModel) {
(<QueryClauseViewModel>orphan).clauseGroup = parent; (<QueryClauseViewModel>orphan).clauseGroup = parent;
@@ -72,14 +71,14 @@ export default class ClauseGroup {
} }
public removeAll(): void { public removeAll(): void {
const allClauses: QueryClauseViewModel[] = new Array<QueryClauseViewModel>(); var allClauses: QueryClauseViewModel[] = new Array<QueryClauseViewModel>();
this.flattenClausesImpl(this, allClauses); this.flattenClausesImpl(this, allClauses);
while (allClauses.length > 0) { while (allClauses.length > 0) {
allClauses.shift().dispose(); allClauses.shift().dispose();
} }
//eslint-disable-next-line
this.children = new Array<any>(); this.children = new Array<any>();
} }
@@ -88,12 +87,12 @@ export default class ClauseGroup {
*/ */
public groupSelectedItems(): boolean { public groupSelectedItems(): boolean {
// Find the selection start & end, also check for gaps between selected items (if found, cannot proceed). // Find the selection start & end, also check for gaps between selected items (if found, cannot proceed).
const selection = this.getCheckedItemsInfo(); var selection = this.getCheckedItemsInfo();
if (selection.canGroup) { if (selection.canGroup) {
const newGroup = new ClauseGroup(false, this); var newGroup = new ClauseGroup(false, this);
// Replace the selected items with the new group, and then move the selected items into the new group. // Replace the selected items with the new group, and then move the selected items into the new group.
const groupedItems = this.children.splice(selection.begin, selection.end - selection.begin + 1, newGroup); var groupedItems = this.children.splice(selection.begin, selection.end - selection.begin + 1, newGroup);
groupedItems && groupedItems &&
groupedItems.forEach((element) => { groupedItems.forEach((element) => {
@@ -119,13 +118,13 @@ export default class ClauseGroup {
return; return;
} }
const parentGroup = this.parentGroup; var parentGroup = this.parentGroup;
let index = parentGroup.children.indexOf(this); var index = parentGroup.children.indexOf(this);
if (index >= 0) { if (index >= 0) {
parentGroup.children.splice(index, 1); parentGroup.children.splice(index, 1);
const toPromote = this.children.splice(0, this.children.length); var toPromote = this.children.splice(0, this.children.length);
// Move all children one level up. // Move all children one level up.
toPromote && toPromote &&
@@ -147,16 +146,16 @@ export default class ClauseGroup {
} }
public findDeepestGroupInChildren(skipIndex?: number): ClauseGroup { public findDeepestGroupInChildren(skipIndex?: number): ClauseGroup {
let deepest = <ClauseGroup>this; var deepest: ClauseGroup = this;
let level = 0; var level: number = 0;
const func = (currentGroup: ClauseGroup): void => { var func = (currentGroup: ClauseGroup): void => {
level++; level++;
if (currentGroup.getCurrentGroupDepth() > deepest.getCurrentGroupDepth()) { if (currentGroup.getCurrentGroupDepth() > deepest.getCurrentGroupDepth()) {
deepest = currentGroup; deepest = currentGroup;
} }
for (let i = 0; i < currentGroup.children.length; i++) { for (var i = 0; i < currentGroup.children.length; i++) {
const currentItem = currentGroup.children[i]; var currentItem = currentGroup.children[i];
if ((i !== skipIndex || level > 1) && currentItem instanceof ClauseGroup) { if ((i !== skipIndex || level > 1) && currentItem instanceof ClauseGroup) {
func(currentItem); func(currentItem);
@@ -171,16 +170,16 @@ export default class ClauseGroup {
} }
private getCheckedItemsInfo(): { canGroup: boolean; begin: number; end: number } { private getCheckedItemsInfo(): { canGroup: boolean; begin: number; end: number } {
let beginIndex = -1; var beginIndex = -1;
let endIndex = -1; var endIndex = -1;
// In order to perform group, all selected items must be next to each other. // In order to perform group, all selected items must be next to each other.
// If one or more items are not selected between the first and the last selected item, the gapFlag will be set to True, meaning cannot perform group. // If one or more items are not selected between the first and the last selected item, the gapFlag will be set to True, meaning cannot perform group.
let gapFlag = false; var gapFlag = false;
let count = 0; var count = 0;
for (let i = 0; i < this.children.length; i++) { for (var i = 0; i < this.children.length; i++) {
const currentItem = this.children[i]; var currentItem = this.children[i];
let subGroupSelectionState: { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean }; var subGroupSelectionState: { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean };
if (currentItem instanceof ClauseGroup) { if (currentItem instanceof ClauseGroup) {
subGroupSelectionState = (<ClauseGroup>currentItem).getSelectionState(); subGroupSelectionState = (<ClauseGroup>currentItem).getSelectionState();
@@ -236,10 +235,10 @@ export default class ClauseGroup {
} }
private getSelectionState(): { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean } { private getSelectionState(): { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean } {
let selectedCount = 0; var selectedCount = 0;
for (let i = 0; i < this.children.length; i++) { for (var i = 0; i < this.children.length; i++) {
const currentItem = this.children[i]; var currentItem = this.children[i];
if (currentItem instanceof ClauseGroup && (<ClauseGroup>currentItem).getSelectionState().allSelected) { if (currentItem instanceof ClauseGroup && (<ClauseGroup>currentItem).getSelectionState().allSelected) {
selectedCount++; selectedCount++;
@@ -261,8 +260,8 @@ export default class ClauseGroup {
} }
private unselectAll(): void { private unselectAll(): void {
for (let i = 0; i < this.children.length; i++) { for (var i = 0; i < this.children.length; i++) {
const currentItem = this.children[i]; var currentItem = this.children[i];
if (currentItem instanceof ClauseGroup) { if (currentItem instanceof ClauseGroup) {
(<ClauseGroup>currentItem).unselectAll(); (<ClauseGroup>currentItem).unselectAll();
@@ -279,8 +278,8 @@ export default class ClauseGroup {
targetArray.splice(0, targetArray.length); targetArray.splice(0, targetArray.length);
} }
for (let i = 0; i < queryGroup.children.length; i++) { for (var i = 0; i < queryGroup.children.length; i++) {
const currentItem = queryGroup.children[i]; var currentItem = queryGroup.children[i];
if (currentItem instanceof ClauseGroup) { if (currentItem instanceof ClauseGroup) {
this.flattenClausesImpl(currentItem, targetArray); this.flattenClausesImpl(currentItem, targetArray);
@@ -293,13 +292,13 @@ export default class ClauseGroup {
} }
public getTreeDepth(): number { public getTreeDepth(): number {
let currentDepth = this.getCurrentGroupDepth(); var currentDepth = this.getCurrentGroupDepth();
for (let i = 0; i < this.children.length; i++) { for (var i = 0; i < this.children.length; i++) {
const currentItem = this.children[i]; var currentItem = this.children[i];
if (currentItem instanceof ClauseGroup) { if (currentItem instanceof ClauseGroup) {
const newDepth = (<ClauseGroup>currentItem).getTreeDepth(); var newDepth = (<ClauseGroup>currentItem).getTreeDepth();
if (newDepth > currentDepth) { if (newDepth > currentDepth) {
currentDepth = newDepth; currentDepth = newDepth;
@@ -311,8 +310,8 @@ export default class ClauseGroup {
} }
public getCurrentGroupDepth(): number { public getCurrentGroupDepth(): number {
let group = <ClauseGroup>this; var group = <ClauseGroup>this;
let depth = 0; var depth = 0;
while (!group.isRootGroup) { while (!group.isRootGroup) {
depth++; depth++;

View File

@@ -1,7 +1,7 @@
import * as ko from "knockout"; import * as ko from "knockout";
import * as Constants from "../Constants";
import ClauseGroup from "./ClauseGroup"; import ClauseGroup from "./ClauseGroup";
import QueryBuilderViewModel from "./QueryBuilderViewModel"; import QueryBuilderViewModel from "./QueryBuilderViewModel";
import * as Constants from "../Constants";
/** /**
* View model for showing group indicators on UI, contains information such as group color and border styles. * View model for showing group indicators on UI, contains information such as group color and border styles.
@@ -38,7 +38,7 @@ export default class ClauseGroupViewModel {
}; };
private getGroupBackgroundColor(group: ClauseGroup): string { private getGroupBackgroundColor(group: ClauseGroup): string {
const colorCount = Constants.clauseGroupColors.length; var colorCount = Constants.clauseGroupColors.length;
if (group.isRootGroup) { if (group.isRootGroup) {
return Constants.transparentColor; return Constants.transparentColor;

View File

@@ -29,7 +29,7 @@ export default class QueryBuilderViewModel {
public removeThisFilterLine = "Remove this filter line"; // localize public removeThisFilterLine = "Remove this filter line"; // localize
public groupSelectedClauses = "Group selected clauses"; // localize public groupSelectedClauses = "Group selected clauses"; // localize
public clauseArray = ko.observableArray<QueryClauseViewModel>(); // This is for storing the clauses in flattened form queryClauses for easier UI data binding. public clauseArray = ko.observableArray<QueryClauseViewModel>(); // This is for storing the clauses in flattened form queryClauses for easier UI data binding.
public queryClauses = new ClauseGroup(true, undefined); // The actual data structure containing the clause information. public queryClauses = new ClauseGroup(true, null); // The actual data structure containing the clause information.
public columnOptions: ko.ObservableArray<string>; public columnOptions: ko.ObservableArray<string>;
public canGroupClauses = ko.observable<boolean>(false); public canGroupClauses = ko.observable<boolean>(false);
@@ -107,7 +107,7 @@ export default class QueryBuilderViewModel {
} }
public setExample() { public setExample() {
const example1 = new QueryClauseViewModel( var example1 = new QueryClauseViewModel(
this, this,
"", "",
"PartitionKey", "PartitionKey",
@@ -121,7 +121,7 @@ export default class QueryBuilderViewModel {
//null, //null,
true true
); );
const example2 = new QueryClauseViewModel( var example2 = new QueryClauseViewModel(
this, this,
"And", "And",
"RowKey", "RowKey",
@@ -140,13 +140,13 @@ export default class QueryBuilderViewModel {
} }
public getODataFilterFromClauses = (): string => { public getODataFilterFromClauses = (): string => {
let filterString = ""; var filterString: string = "";
const treeTraversal = (group: ClauseGroup): void => { var treeTraversal = (group: ClauseGroup): void => {
for (let i = 0; i < group.children.length; i++) { for (var i = 0; i < group.children.length; i++) {
const currentItem = group.children[i]; var currentItem = group.children[i];
if (currentItem instanceof QueryClauseViewModel) { if (currentItem instanceof QueryClauseViewModel) {
const clause = <QueryClauseViewModel>currentItem; var clause = <QueryClauseViewModel>currentItem;
this.timestampToValue(clause); this.timestampToValue(clause);
filterString = filterString.concat( filterString = filterString.concat(
this.constructODataClause( this.constructODataClause(
@@ -173,7 +173,7 @@ export default class QueryBuilderViewModel {
}; };
public getSqlFilterFromClauses = (): string => { public getSqlFilterFromClauses = (): string => {
let filterString = "SELECT * FROM c"; var filterString: string = "SELECT * FROM c";
if (this._queryViewModel.selectText() && this._queryViewModel.selectText().length > 0) { if (this._queryViewModel.selectText() && this._queryViewModel.selectText().length > 0) {
filterString = "SELECT"; filterString = "SELECT";
const selectText = this._queryViewModel && this._queryViewModel.selectText && this._queryViewModel.selectText(); const selectText = this._queryViewModel && this._queryViewModel.selectText && this._queryViewModel.selectText();
@@ -199,15 +199,15 @@ export default class QueryBuilderViewModel {
return filterString; return filterString;
} }
filterString = filterString.concat(" WHERE"); filterString = filterString.concat(" WHERE");
let first = true; var first = true;
const treeTraversal = (group: ClauseGroup): void => { var treeTraversal = (group: ClauseGroup): void => {
for (let i = 0; i < group.children.length; i++) { for (var i = 0; i < group.children.length; i++) {
const currentItem = group.children[i]; var currentItem = group.children[i];
if (currentItem instanceof QueryClauseViewModel) { if (currentItem instanceof QueryClauseViewModel) {
const clause = <QueryClauseViewModel>currentItem; var clause = <QueryClauseViewModel>currentItem;
const timeStampValue: string = this.timestampToSqlValue(clause); let timeStampValue: string = this.timestampToSqlValue(clause);
let value = clause.value(); var value = clause.value();
if (!clause.isValue()) { if (!clause.isValue()) {
value = timeStampValue; value = timeStampValue;
} }
@@ -240,7 +240,7 @@ export default class QueryBuilderViewModel {
const databaseId = this._queryViewModel.queryTablesTab.collection.databaseId; const databaseId = this._queryViewModel.queryTablesTab.collection.databaseId;
const collectionId = this._queryViewModel.queryTablesTab.collection.id(); const collectionId = this._queryViewModel.queryTablesTab.collection.id();
const tableToQuery = `${getQuotedCqlIdentifier(databaseId)}.${getQuotedCqlIdentifier(collectionId)}`; const tableToQuery = `${getQuotedCqlIdentifier(databaseId)}.${getQuotedCqlIdentifier(collectionId)}`;
let filterString = `SELECT * FROM ${tableToQuery}`; var filterString: string = `SELECT * FROM ${tableToQuery}`;
if (this._queryViewModel.selectText() && this._queryViewModel.selectText().length > 0) { if (this._queryViewModel.selectText() && this._queryViewModel.selectText().length > 0) {
filterString = "SELECT"; filterString = "SELECT";
const selectText = this._queryViewModel && this._queryViewModel.selectText && this._queryViewModel.selectText(); const selectText = this._queryViewModel && this._queryViewModel.selectText && this._queryViewModel.selectText();
@@ -255,15 +255,15 @@ export default class QueryBuilderViewModel {
return filterString; return filterString;
} }
filterString = filterString.concat(" WHERE"); filterString = filterString.concat(" WHERE");
let first = true; var first = true;
const treeTraversal = (group: ClauseGroup): void => { var treeTraversal = (group: ClauseGroup): void => {
for (let i = 0; i < group.children.length; i++) { for (var i = 0; i < group.children.length; i++) {
const currentItem = group.children[i]; var currentItem = group.children[i];
if (currentItem instanceof QueryClauseViewModel) { if (currentItem instanceof QueryClauseViewModel) {
const clause = <QueryClauseViewModel>currentItem; var clause = <QueryClauseViewModel>currentItem;
const timeStampValue = this.timestampToSqlValue(clause); let timeStampValue: string = this.timestampToSqlValue(clause);
let value = clause.value(); var value = clause.value();
if (!clause.isValue()) { if (!clause.isValue()) {
value = timeStampValue; value = timeStampValue;
} }
@@ -293,13 +293,13 @@ export default class QueryBuilderViewModel {
}; };
public updateColumnOptions = (): void => { public updateColumnOptions = (): void => {
// let originalHeaders = this.columnOptions(); let originalHeaders = this.columnOptions();
const newHeaders = this.tableEntityListViewModel.headers; let newHeaders = this.tableEntityListViewModel.headers;
this.columnOptions(newHeaders.sort(DataTableUtilities.compareTableColumns)); this.columnOptions(newHeaders.sort(DataTableUtilities.compareTableColumns));
}; };
private generateLeftParentheses(clause: QueryClauseViewModel): string { private generateLeftParentheses(clause: QueryClauseViewModel): string {
let result = ""; var result = "";
if (clause.clauseGroup.isRootGroup || clause.clauseGroup.children.indexOf(clause) !== 0) { if (clause.clauseGroup.isRootGroup || clause.clauseGroup.children.indexOf(clause) !== 0) {
return result; return result;
@@ -307,7 +307,7 @@ export default class QueryBuilderViewModel {
result = result.concat("("); result = result.concat("(");
} }
let currentGroup: ClauseGroup = clause.clauseGroup; var currentGroup: ClauseGroup = clause.clauseGroup;
while ( while (
!currentGroup.isRootGroup && !currentGroup.isRootGroup &&
@@ -322,7 +322,7 @@ export default class QueryBuilderViewModel {
} }
private generateRightParentheses(clause: QueryClauseViewModel): string { private generateRightParentheses(clause: QueryClauseViewModel): string {
let result = ""; var result = "";
if ( if (
clause.clauseGroup.isRootGroup || clause.clauseGroup.isRootGroup ||
@@ -333,7 +333,7 @@ export default class QueryBuilderViewModel {
result = result.concat(")"); result = result.concat(")");
} }
let currentGroup: ClauseGroup = clause.clauseGroup; var currentGroup: ClauseGroup = clause.clauseGroup;
while ( while (
!currentGroup.isRootGroup && !currentGroup.isRootGroup &&
@@ -364,17 +364,14 @@ export default class QueryBuilderViewModel {
case Constants.TableType.String: case Constants.TableType.String:
return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter( return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter(
operator operator
// eslint-disable-next-line no-useless-escape
)} \'${value}\'${rightParentheses}`; )} \'${value}\'${rightParentheses}`;
case Constants.TableType.Guid: case Constants.TableType.Guid:
return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter( return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter(
operator operator
// eslint-disable-next-line no-useless-escape
)} guid\'${value}\'${rightParentheses}`; )} guid\'${value}\'${rightParentheses}`;
case Constants.TableType.Binary: case Constants.TableType.Binary:
return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter( return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter(
operator operator
// eslint-disable-next-line no-useless-escape
)} binary\'${value}\'${rightParentheses}`; )} binary\'${value}\'${rightParentheses}`;
default: default:
return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter( return ` ${clauseRule.toLowerCase()} ${leftParentheses}${propertyName} ${this.operatorConverter(
@@ -394,11 +391,9 @@ export default class QueryBuilderViewModel {
): string => { ): string => {
if (propertyName === Constants.EntityKeyNames.PartitionKey) { if (propertyName === Constants.EntityKeyNames.PartitionKey) {
propertyName = TableEntityProcessor.keyProperties.PartitionKey; propertyName = TableEntityProcessor.keyProperties.PartitionKey;
// eslint-disable-next-line no-useless-escape
return ` ${clauseRule.toLowerCase()} ${leftParentheses}c["${propertyName}"] ${operator} \'${value}\'${rightParentheses}`; return ` ${clauseRule.toLowerCase()} ${leftParentheses}c["${propertyName}"] ${operator} \'${value}\'${rightParentheses}`;
} else if (propertyName === Constants.EntityKeyNames.RowKey) { } else if (propertyName === Constants.EntityKeyNames.RowKey) {
propertyName = TableEntityProcessor.keyProperties.Id; propertyName = TableEntityProcessor.keyProperties.Id;
// eslint-disable-next-line no-useless-escape
return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName} ${operator} \'${value}\'${rightParentheses}`; return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName} ${operator} \'${value}\'${rightParentheses}`;
} else if (propertyName === Constants.EntityKeyNames.Timestamp) { } else if (propertyName === Constants.EntityKeyNames.Timestamp) {
propertyName = TableEntityProcessor.keyProperties.Timestamp; propertyName = TableEntityProcessor.keyProperties.Timestamp;
@@ -408,21 +403,16 @@ export default class QueryBuilderViewModel {
} }
switch (type) { switch (type) {
case Constants.TableType.DateTime: case Constants.TableType.DateTime:
// eslint-disable-next-line no-useless-escape
return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} \'${DateTimeUtilities.convertJSDateToTicksWithPadding( return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} \'${DateTimeUtilities.convertJSDateToTicksWithPadding(
value value
// eslint-disable-next-line no-useless-escape
)}\'${rightParentheses}`; )}\'${rightParentheses}`;
case Constants.TableType.Int64: case Constants.TableType.Int64:
// eslint-disable-next-line no-useless-escape
return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} \'${Utilities.padLongWithZeros( return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} \'${Utilities.padLongWithZeros(
value value
// eslint-disable-next-line no-useless-escape
)}\'${rightParentheses}`; )}\'${rightParentheses}`;
case Constants.TableType.String: case Constants.TableType.String:
case Constants.TableType.Guid: case Constants.TableType.Guid:
case Constants.TableType.Binary: case Constants.TableType.Binary:
// eslint-disable-next-line no-useless-escape
return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} \'${value}\'${rightParentheses}`; return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} \'${value}\'${rightParentheses}`;
default: default:
return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} ${value}${rightParentheses}`; return ` ${clauseRule.toLowerCase()} ${leftParentheses}c.${propertyName}["$v"] ${operator} ${value}${rightParentheses}`;
@@ -444,7 +434,6 @@ export default class QueryBuilderViewModel {
type === Constants.CassandraType.Ascii || type === Constants.CassandraType.Ascii ||
type === Constants.CassandraType.Varchar type === Constants.CassandraType.Varchar
) { ) {
// eslint-disable-next-line no-useless-escape
return ` ${clauseRule.toLowerCase()} ${leftParentheses} ${propertyName} ${operator} \'${value}\'${rightParentheses}`; return ` ${clauseRule.toLowerCase()} ${leftParentheses} ${propertyName} ${operator} \'${value}\'${rightParentheses}`;
} }
return ` ${clauseRule.toLowerCase()} ${leftParentheses} ${propertyName} ${operator} ${value}${rightParentheses}`; return ` ${clauseRule.toLowerCase()} ${leftParentheses} ${propertyName} ${operator} ${value}${rightParentheses}`;
@@ -465,7 +454,7 @@ export default class QueryBuilderViewModel {
case Constants.Operator.NotEqualTo: case Constants.Operator.NotEqualTo:
return Constants.ODataOperator.NotEqualTo; return Constants.ODataOperator.NotEqualTo;
} }
return undefined; return null;
}; };
public groupClauses = (): void => { public groupClauses = (): void => {
@@ -474,11 +463,11 @@ export default class QueryBuilderViewModel {
this.updateCanGroupClauses(); this.updateCanGroupClauses();
}; };
public addClauseIndex = (index: number): void => { public addClauseIndex = (index: number, data: any): void => {
if (index < 0) { if (index < 0) {
index = 0; index = 0;
} }
const newClause = new QueryClauseViewModel( var newClause = new QueryClauseViewModel(
this, this,
"And", "And",
"", "",
@@ -503,28 +492,28 @@ export default class QueryBuilderViewModel {
// adds a new clause to the end of the array // adds a new clause to the end of the array
public addNewClause = (): void => { public addNewClause = (): void => {
this.addClauseIndex(this.clauseArray().length); this.addClauseIndex(this.clauseArray().length, null);
}; };
public onAddClauseKeyDown = (index: number, event: KeyboardEvent): boolean => { public onAddClauseKeyDown = (index: number, data: any, event: KeyboardEvent, source: any): boolean => {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.addClauseIndex(index); this.addClauseIndex(index, data);
event.stopPropagation(); event.stopPropagation();
return false; return false;
} }
return true; return true;
}; };
public onAddNewClauseKeyDown = (event: KeyboardEvent): boolean => { public onAddNewClauseKeyDown = (source: any, event: KeyboardEvent): boolean => {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.addClauseIndex(this.clauseArray().length - 1); this.addClauseIndex(this.clauseArray().length - 1, null);
event.stopPropagation(); event.stopPropagation();
return false; return false;
} }
return true; return true;
}; };
public deleteClause = (index: number): void => { public deleteClause = (index: number, data: any): void => {
this.deleteClauseImpl(index); this.deleteClauseImpl(index);
if (this.clauseArray().length !== 0) { if (this.clauseArray().length !== 0) {
this.clauseArray()[0].and_or(""); this.clauseArray()[0].and_or("");
@@ -534,9 +523,9 @@ export default class QueryBuilderViewModel {
$(window).resize(); $(window).resize();
}; };
public onDeleteClauseKeyDown = (index: number, event: KeyboardEvent): boolean => { public onDeleteClauseKeyDown = (index: number, data: any, event: KeyboardEvent, source: any): boolean => {
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) { if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
this.deleteClause(index); this.deleteClause(index, data);
event.stopPropagation(); event.stopPropagation();
return false; return false;
} }
@@ -550,26 +539,25 @@ export default class QueryBuilderViewModel {
* (transparent) or its parent group view models. * (transparent) or its parent group view models.
*/ */
public getClauseGroupViewModels = (clause: QueryClauseViewModel): ClauseGroupViewModel[] => { public getClauseGroupViewModels = (clause: QueryClauseViewModel): ClauseGroupViewModel[] => {
const placeHolderGroupViewModel = new ClauseGroupViewModel(this.queryClauses, false, this); var placeHolderGroupViewModel = new ClauseGroupViewModel(this.queryClauses, false, this);
const treeDepth = this.queryClauses.getTreeDepth(); var treeDepth = this.queryClauses.getTreeDepth();
const groupViewModels = new Array<ClauseGroupViewModel>(treeDepth); var groupViewModels = new Array<ClauseGroupViewModel>(treeDepth);
// Prefill the arry with placeholders. // Prefill the arry with placeholders.
for (let i = 0; i < groupViewModels.length; i++) { for (var i = 0; i < groupViewModels.length; i++) {
groupViewModels[i] = placeHolderGroupViewModel; groupViewModels[i] = placeHolderGroupViewModel;
} }
let currentGroup = clause.clauseGroup; var currentGroup = clause.clauseGroup;
// This function determines whether the path from clause to the current group is on the left most. // This function determines whether the path from clause to the current group is on the left most.
const isLeftMostPath = (): boolean => { var isLeftMostPath = (): boolean => {
let group = clause.clauseGroup; var group = clause.clauseGroup;
if (group.children.indexOf(clause) !== 0) { if (group.children.indexOf(clause) !== 0) {
return false; return false;
} }
// eslint-disable-next-line no-constant-condition
while (true) { while (true) {
if (group.getId() === currentGroup.getId()) { if (group.getId() === currentGroup.getId()) {
break; break;
@@ -585,14 +573,13 @@ export default class QueryBuilderViewModel {
}; };
// This function determines whether the path from clause to the current group is on the right most. // This function determines whether the path from clause to the current group is on the right most.
const isRightMostPath = (): boolean => { var isRightMostPath = (): boolean => {
let group = clause.clauseGroup; var group = clause.clauseGroup;
if (group.children.indexOf(clause) !== group.children.length - 1) { if (group.children.indexOf(clause) !== group.children.length - 1) {
return false; return false;
} }
// eslint-disable-next-line no-constant-condition
while (true) { while (true) {
if (group.getId() === currentGroup.getId()) { if (group.getId() === currentGroup.getId()) {
break; break;
@@ -607,26 +594,26 @@ export default class QueryBuilderViewModel {
return true; return true;
}; };
let vmIndex = groupViewModels.length - 1; var vmIndex = groupViewModels.length - 1;
let skipIndex = -1; var skipIndex = -1;
let lastDepth = clause.groupDepth; var lastDepth = clause.groupDepth;
while (!currentGroup.isRootGroup) { while (!currentGroup.isRootGroup) {
// The current group will be rendered at least once, and if there are any sibling groups deeper // The current group will be rendered at least once, and if there are any sibling groups deeper
// than the current group, we will repeat rendering the current group to fill up the gap between // than the current group, we will repeat rendering the current group to fill up the gap between
// current & deepest sibling. // current & deepest sibling.
const deepestInSiblings = currentGroup.findDeepestGroupInChildren(skipIndex).getCurrentGroupDepth(); var deepestInSiblings = currentGroup.findDeepestGroupInChildren(skipIndex).getCurrentGroupDepth();
// Find out the depth difference between the deepest group under the siblings of currentGroup and // Find out the depth difference between the deepest group under the siblings of currentGroup and
// the deepest group under currentGroup. If the result n is a positive number, it means there are // the deepest group under currentGroup. If the result n is a positive number, it means there are
// deeper groups in siblings and we need to draw n + 1 group blocks on UI to fill up the depth // deeper groups in siblings and we need to draw n + 1 group blocks on UI to fill up the depth
// differences. If the result n is a negative number, it means current group contains the deepest // differences. If the result n is a negative number, it means current group contains the deepest
// sub-group, we only need to draw the group block once. // sub-group, we only need to draw the group block once.
const repeatCount = Math.max(deepestInSiblings - lastDepth, 0); var repeatCount = Math.max(deepestInSiblings - lastDepth, 0);
for (let i = 0; i <= repeatCount; i++) { for (var i = 0; i <= repeatCount; i++) {
const isLeftMost = isLeftMostPath(); var isLeftMost = isLeftMostPath();
const isRightMost = isRightMostPath(); var isRightMost = isRightMostPath();
const groupViewModel = new ClauseGroupViewModel(currentGroup, i === 0 && isLeftMost, this); var groupViewModel = new ClauseGroupViewModel(currentGroup, i === 0 && isLeftMost, this);
groupViewModel.showTopBorder(isLeftMost); groupViewModel.showTopBorder(isLeftMost);
groupViewModel.showBottomBorder(isRightMost); groupViewModel.showBottomBorder(isRightMost);
@@ -648,9 +635,9 @@ export default class QueryBuilderViewModel {
}; };
public addCustomRange(timestamp: CustomTimestampHelper.ITimestampQuery, clauseToAdd: QueryClauseViewModel): void { public addCustomRange(timestamp: CustomTimestampHelper.ITimestampQuery, clauseToAdd: QueryClauseViewModel): void {
const index = this.clauseArray.peek().indexOf(clauseToAdd); var index = this.clauseArray.peek().indexOf(clauseToAdd);
const newClause = new QueryClauseViewModel( var newClause = new QueryClauseViewModel(
this, this,
//this._tableEntityListViewModel.tableExplorerContext.hostProxy, //this._tableEntityListViewModel.tableExplorerContext.hostProxy,
"And", "And",
@@ -675,10 +662,10 @@ export default class QueryBuilderViewModel {
} }
private scrollToBottom(): void { private scrollToBottom(): void {
const scrollBox = document.getElementById("scroll"); var scrollBox = document.getElementById("scroll");
if (!this.scrollEventListener) { if (!this.scrollEventListener) {
scrollBox.addEventListener("scroll", function () { scrollBox.addEventListener("scroll", function () {
const translate = "translate(0," + this.scrollTop + "px)"; var translate = "translate(0," + this.scrollTop + "px)";
const allTh = <NodeListOf<HTMLElement>>this.querySelectorAll("thead td"); const allTh = <NodeListOf<HTMLElement>>this.querySelectorAll("thead td");
for (let i = 0; i < allTh.length; i++) { for (let i = 0; i < allTh.length; i++) {
allTh[i].style.transform = translate; allTh[i].style.transform = translate;
@@ -686,7 +673,7 @@ export default class QueryBuilderViewModel {
}); });
this.scrollEventListener = true; this.scrollEventListener = true;
} }
const isScrolledToBottom = scrollBox.scrollHeight - scrollBox.clientHeight <= scrollBox.scrollHeight + 1; var isScrolledToBottom = scrollBox.scrollHeight - scrollBox.clientHeight <= scrollBox.scrollHeight + 1;
if (isScrolledToBottom) { if (isScrolledToBottom) {
scrollBox.scrollTop = scrollBox.scrollHeight - scrollBox.clientHeight; scrollBox.scrollTop = scrollBox.scrollHeight - scrollBox.clientHeight;
} }
@@ -698,8 +685,8 @@ export default class QueryBuilderViewModel {
} }
private deleteClauseImpl(index: number): void { private deleteClauseImpl(index: number): void {
const clause = this.clauseArray()[index]; var clause = this.clauseArray()[index];
const previousClause = index === 0 ? 0 : index - 1; var previousClause = index === 0 ? 0 : index - 1;
this.queryClauses.deleteClause(clause); this.queryClauses.deleteClause(clause);
this.updateClauseArray(); this.updateClauseArray();
if (this.clauseArray()[previousClause]) { if (this.clauseArray()[previousClause]) {
@@ -744,7 +731,7 @@ export default class QueryBuilderViewModel {
private timestampToSqlValue(clause: QueryClauseViewModel): string { private timestampToSqlValue(clause: QueryClauseViewModel): string {
if (clause.isValue()) { if (clause.isValue()) {
return undefined; return null;
} else if (clause.isTimestamp()) { } else if (clause.isTimestamp()) {
return this.getTimeStampToSqlQuery(clause); return this.getTimeStampToSqlQuery(clause);
// } else if (clause.isCustomLastTimestamp()) { // } else if (clause.isCustomLastTimestamp()) {
@@ -756,7 +743,7 @@ export default class QueryBuilderViewModel {
return clause.customTimeValue(); return clause.customTimeValue();
} }
} }
return undefined; return null;
} }
private getTimeStampToQuery(clause: QueryClauseViewModel): void { private getTimeStampToQuery(clause: QueryClauseViewModel): void {
@@ -802,7 +789,7 @@ export default class QueryBuilderViewModel {
case Constants.timeOptions.currentYear: case Constants.timeOptions.currentYear:
return CustomTimestampHelper._queryCurrentYearLocal(); return CustomTimestampHelper._queryCurrentYearLocal();
} }
return undefined; return null;
} }
public checkIfClauseChanged(): void { public checkIfClauseChanged(): void {

View File

@@ -14,7 +14,7 @@ export default class QueryClauseViewModel {
public field: ko.Observable<string>; public field: ko.Observable<string>;
public type: ko.Observable<string>; public type: ko.Observable<string>;
public operator: ko.Observable<string>; public operator: ko.Observable<string>;
public value: ko.Observable<string>; public value: ko.Observable<any>;
public timeValue: ko.Observable<string>; public timeValue: ko.Observable<string>;
public customTimeValue: ko.Observable<string>; public customTimeValue: ko.Observable<string>;
public canAnd: ko.Observable<boolean>; public canAnd: ko.Observable<boolean>;
@@ -39,7 +39,7 @@ export default class QueryClauseViewModel {
field: string, field: string,
type: string, type: string,
operator: string, operator: string,
value: string, value: any,
canAnd: boolean, canAnd: boolean,
timeValue: string, timeValue: string,
customTimeValue: string, customTimeValue: string,
@@ -88,30 +88,30 @@ export default class QueryClauseViewModel {
userContext.apiType !== "Cassandra" userContext.apiType !== "Cassandra"
); );
this.and_or.subscribe(() => { this.and_or.subscribe((value) => {
this._queryBuilderViewModel.checkIfClauseChanged(); this._queryBuilderViewModel.checkIfClauseChanged();
}); });
this.field.subscribe(() => { this.field.subscribe((value) => {
this.changeField(); this.changeField();
}); });
this.type.subscribe(() => { this.type.subscribe((value) => {
this.changeType(); this.changeType();
}); });
this.timeValue.subscribe(() => { this.timeValue.subscribe((value) => {
// if (this.timeValue() === QueryBuilderConstants.timeOptions.custom) { // if (this.timeValue() === QueryBuilderConstants.timeOptions.custom) {
// this.customTimestampDialog(); // this.customTimestampDialog();
// } // }
}); });
this.customTimeValue.subscribe(() => { this.customTimeValue.subscribe((value) => {
this._queryBuilderViewModel.checkIfClauseChanged(); this._queryBuilderViewModel.checkIfClauseChanged();
}); });
this.value.subscribe(() => { this.value.subscribe((value) => {
this._queryBuilderViewModel.checkIfClauseChanged(); this._queryBuilderViewModel.checkIfClauseChanged();
}); });
this.operator.subscribe(() => { this.operator.subscribe((value) => {
this._queryBuilderViewModel.checkIfClauseChanged(); this._queryBuilderViewModel.checkIfClauseChanged();
}); });
this._groupCheckSubscription = this.checkedForGrouping.subscribe(() => { this._groupCheckSubscription = this.checkedForGrouping.subscribe((value) => {
this._queryBuilderViewModel.updateCanGroupClauses(); this._queryBuilderViewModel.updateCanGroupClauses();
}); });
this.isAndOrFocused = ko.observable<boolean>(false); this.isAndOrFocused = ko.observable<boolean>(false);
@@ -280,7 +280,7 @@ export default class QueryClauseViewModel {
this._groupCheckSubscription.dispose(); this._groupCheckSubscription.dispose();
} }
this.clauseGroup = undefined; this.clauseGroup = null;
this._queryBuilderViewModel = undefined; this._queryBuilderViewModel = null;
} }
} }

View File

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

View File

@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/switch-exhaustiveness-check */
import { ConflictDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos"; import { ConflictDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos";
import * as ko from "knockout"; import * as ko from "knockout";
import Q from "q"; import Q from "q";
@@ -71,13 +69,13 @@ export default class ConflictsTab extends TabsBase {
ViewModels.DocumentExplorerState.noDocumentSelected ViewModels.DocumentExplorerState.noDocumentSelected
); );
this.selectedConflictId = ko.observable<ConflictId>(); this.selectedConflictId = ko.observable<ConflictId>();
this.selectedConflictContent = editable.observable<string>(""); this.selectedConflictContent = editable.observable<any>("");
this.selectedConflictCurrent = editable.observable<string>(""); this.selectedConflictCurrent = editable.observable<any>("");
this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey); this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey);
this.conflictIds = options.conflictIds; this.conflictIds = options.conflictIds;
this.partitionKeyPropertyHeader = this.partitionKeyPropertyHeader =
(this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader(); (this.collection && this.collection.partitionKeyPropertyHeader) || this._getPartitionKeyPropertyHeader();
this.partitionKeyProperty = this.partitionKeyPropertyHeader this.partitionKeyProperty = !!this.partitionKeyPropertyHeader
? this.partitionKeyPropertyHeader.replace(/[/]+/g, ".").substr(1).replace(/[']+/g, "") ? this.partitionKeyPropertyHeader.replace(/[/]+/g, ".").substr(1).replace(/[']+/g, "")
: null; : null;
@@ -189,7 +187,7 @@ export default class ConflictsTab extends TabsBase {
this.buildCommandBarOptions(); this.buildCommandBarOptions();
this.shouldShowDiffEditor = ko.pureComputed<boolean>(() => { this.shouldShowDiffEditor = ko.pureComputed<boolean>(() => {
const documentHasContent: boolean = const documentHasContent: boolean =
this.selectedConflictContent() !== null && this.selectedConflictContent().length > 0; this.selectedConflictContent() != null && this.selectedConflictContent().length > 0;
const operationIsReplace: boolean = this.conflictOperation() === Constants.ConflictOperationType.Replace; const operationIsReplace: boolean = this.conflictOperation() === Constants.ConflictOperationType.Replace;
const isLoadingData: boolean = this.loadingConflictData(); const isLoadingData: boolean = this.loadingConflictData();
return documentHasContent && operationIsReplace && !isLoadingData; return documentHasContent && operationIsReplace && !isLoadingData;
@@ -197,7 +195,7 @@ export default class ConflictsTab extends TabsBase {
this.shouldShowEditor = ko.pureComputed<boolean>(() => { this.shouldShowEditor = ko.pureComputed<boolean>(() => {
const documentHasContent: boolean = const documentHasContent: boolean =
this.selectedConflictContent() !== null && this.selectedConflictContent().length > 0; this.selectedConflictContent() != null && this.selectedConflictContent().length > 0;
const operationIsInsert: boolean = this.conflictOperation() === Constants.ConflictOperationType.Create; const operationIsInsert: boolean = this.conflictOperation() === Constants.ConflictOperationType.Create;
const operationIsDelete: boolean = this.conflictOperation() === Constants.ConflictOperationType.Delete; const operationIsDelete: boolean = this.conflictOperation() === Constants.ConflictOperationType.Delete;
const isLoadingData: boolean = this.loadingConflictData(); const isLoadingData: boolean = this.loadingConflictData();
@@ -244,7 +242,7 @@ export default class ConflictsTab extends TabsBase {
return true; return true;
}; };
public onConflictIdClick(): Q.Promise<unknown> { public onConflictIdClick(clickedDocumentId: ConflictId): Q.Promise<any> {
if (this.editorState() !== ViewModels.DocumentExplorerState.noDocumentSelected) { if (this.editorState() !== ViewModels.DocumentExplorerState.noDocumentSelected) {
return Q(); return Q();
} }
@@ -407,19 +405,19 @@ export default class ConflictsTab extends TabsBase {
} }
}; };
public onDiscardClick = (): Q.Promise<unknown> => { public onDiscardClick = (): Q.Promise<any> => {
this.selectedConflictContent(this.selectedConflictContent.getEditableOriginalValue()); this.selectedConflictContent(this.selectedConflictContent.getEditableOriginalValue());
this.editorState(ViewModels.DocumentExplorerState.exisitingDocumentNoEdits); this.editorState(ViewModels.DocumentExplorerState.exisitingDocumentNoEdits);
return Q(); return Q();
}; };
public onValidDocumentEdit(): Q.Promise<unknown> { public onValidDocumentEdit(): Q.Promise<any> {
this.editorState(ViewModels.DocumentExplorerState.exisitingDocumentDirtyValid); this.editorState(ViewModels.DocumentExplorerState.exisitingDocumentDirtyValid);
return Q(); return Q();
} }
public onInvalidDocumentEdit(): Q.Promise<unknown> { public onInvalidDocumentEdit(): Q.Promise<any> {
if ( if (
this.editorState() === ViewModels.DocumentExplorerState.exisitingDocumentNoEdits || this.editorState() === ViewModels.DocumentExplorerState.exisitingDocumentNoEdits ||
this.editorState() === ViewModels.DocumentExplorerState.exisitingDocumentDirtyValid this.editorState() === ViewModels.DocumentExplorerState.exisitingDocumentDirtyValid
@@ -444,7 +442,7 @@ export default class ConflictsTab extends TabsBase {
this._documentsIterator = await this.createIterator(); this._documentsIterator = await this.createIterator();
await this.loadNextPage(); await this.loadNextPage();
} catch (error) { } catch (error) {
if (this.onLoadStartKey !== null && this.onLoadStartKey !== undefined) { if (this.onLoadStartKey != null && this.onLoadStartKey != undefined) {
TelemetryProcessor.traceFailure( TelemetryProcessor.traceFailure(
Action.Tab, Action.Tab,
{ {
@@ -473,7 +471,7 @@ export default class ConflictsTab extends TabsBase {
return queryConflicts(this.collection.databaseId, this.collection.id(), query, options as FeedOptions); return queryConflicts(this.collection.databaseId, this.collection.id(), query, options as FeedOptions);
} }
public loadNextPage(): Q.Promise<unknown> { public loadNextPage(): Q.Promise<any> {
this.isExecuting(true); this.isExecuting(true);
this.isExecutionError(false); this.isExecutionError(false);
return this._loadNextPageInternal() return this._loadNextPageInternal()
@@ -493,7 +491,7 @@ export default class ConflictsTab extends TabsBase {
const merged = currentConflicts.concat(nextConflictIds); const merged = currentConflicts.concat(nextConflictIds);
this.conflictIds(merged); this.conflictIds(merged);
if (this.onLoadStartKey !== null && this.onLoadStartKey !== undefined) { if (this.onLoadStartKey != null && this.onLoadStartKey != undefined) {
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(
Action.Tab, Action.Tab,
{ {
@@ -510,7 +508,7 @@ export default class ConflictsTab extends TabsBase {
}, },
(error) => { (error) => {
this.isExecutionError(true); this.isExecutionError(true);
if (this.onLoadStartKey !== null && this.onLoadStartKey !== undefined) { if (this.onLoadStartKey != null && this.onLoadStartKey != undefined) {
TelemetryProcessor.traceFailure( TelemetryProcessor.traceFailure(
Action.Tab, Action.Tab,
{ {
@@ -543,18 +541,18 @@ export default class ConflictsTab extends TabsBase {
return Q(this._documentsIterator.fetchNext().then((response) => response.resources)); return Q(this._documentsIterator.fetchNext().then((response) => response.resources));
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars protected _onEditorContentChange(newContent: string) {
protected _onEditorContentChange(_newContent: string) {
try { try {
const parsed: any = JSON.parse(newContent);
this.onValidDocumentEdit(); this.onValidDocumentEdit();
} catch (e) { } catch (e) {
this.onInvalidDocumentEdit(); this.onInvalidDocumentEdit();
} }
} }
public initDocumentEditorForCreate(documentId: ConflictId, documentToInsert: any): Q.Promise<unknown> { public initDocumentEditorForCreate(documentId: ConflictId, documentToInsert: any): Q.Promise<any> {
if (documentId) { if (documentId) {
const parsedConflictContent: any = JSON.parse(documentToInsert); let parsedConflictContent: any = JSON.parse(documentToInsert);
const renderedConflictContent: string = this.renderObjectForEditor(parsedConflictContent, null, 4); const renderedConflictContent: string = this.renderObjectForEditor(parsedConflictContent, null, 4);
this.selectedConflictContent.setBaseline(renderedConflictContent); this.selectedConflictContent.setBaseline(renderedConflictContent);
this.editorState(ViewModels.DocumentExplorerState.exisitingDocumentNoEdits); this.editorState(ViewModels.DocumentExplorerState.exisitingDocumentNoEdits);
@@ -567,7 +565,7 @@ export default class ConflictsTab extends TabsBase {
documentId: ConflictId, documentId: ConflictId,
conflictContent: any, conflictContent: any,
currentContent: any currentContent: any
): Q.Promise<unknown> { ): Q.Promise<any> {
if (documentId) { if (documentId) {
currentContent = ConflictsTab.removeSystemProperties(currentContent); currentContent = ConflictsTab.removeSystemProperties(currentContent);
const renderedCurrentContent: string = this.renderObjectForEditor(currentContent, null, 4); const renderedCurrentContent: string = this.renderObjectForEditor(currentContent, null, 4);
@@ -584,7 +582,7 @@ export default class ConflictsTab extends TabsBase {
return Q(); return Q();
} }
public initDocumentEditorForDelete(documentId: ConflictId, documentToDelete: any): Q.Promise<unknown> { public initDocumentEditorForDelete(documentId: ConflictId, documentToDelete: any): Q.Promise<any> {
if (documentId) { if (documentId) {
let parsedDocumentToDelete: any = JSON.parse(documentToDelete); let parsedDocumentToDelete: any = JSON.parse(documentToDelete);
parsedDocumentToDelete = ConflictsTab.removeSystemProperties(parsedDocumentToDelete); parsedDocumentToDelete = ConflictsTab.removeSystemProperties(parsedDocumentToDelete);
@@ -596,8 +594,7 @@ export default class ConflictsTab extends TabsBase {
return Q(); return Q();
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars public initDocumentEditorForNoOp(documentId: ConflictId): Q.Promise<any> {
public initDocumentEditorForNoOp(_documentId: ConflictId): Q.Promise<unknown> {
this.selectedConflictContent(null); this.selectedConflictContent(null);
this.selectedConflictCurrent(null); this.selectedConflictCurrent(null);
this.editorState(ViewModels.DocumentExplorerState.noDocumentSelected); this.editorState(ViewModels.DocumentExplorerState.noDocumentSelected);

View File

@@ -118,7 +118,7 @@ export default class NotebookTabV2 extends NotebookTabBase {
const saveButtonChildren = []; const saveButtonChildren = [];
if (this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) { if (this.container.notebookManager?.gitHubOAuthService.isLoggedIn()) {
saveButtonChildren.push({ saveButtonChildren.push({
iconName: copyToLabel, iconName: "Copy",
onCommandClick: () => this.copyNotebook(), onCommandClick: () => this.copyNotebook(),
commandButtonLabel: copyToLabel, commandButtonLabel: copyToLabel,
hasPopup: false, hasPopup: false,

View File

@@ -22,7 +22,6 @@ export default class Trigger {
public triggerType: ko.Observable<string>; public triggerType: ko.Observable<string>;
public triggerOperation: ko.Observable<string>; public triggerOperation: ko.Observable<string>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(container: Explorer, collection: ViewModels.Collection, data: any) { constructor(container: Explorer, collection: ViewModels.Collection, data: any) {
this.nodeKind = "Trigger"; this.nodeKind = "Trigger";
this.container = container; this.container = container;
@@ -35,7 +34,7 @@ export default class Trigger {
this.triggerType = ko.observable(data.triggerType); this.triggerType = ko.observable(data.triggerType);
} }
public select(): void { public select() {
useSelectedNode.getState().setSelectedNode(this); useSelectedNode.getState().setSelectedNode(this);
TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, { TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, {
description: "Trigger node", description: "Trigger node",
@@ -44,8 +43,7 @@ export default class Trigger {
}); });
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars public static create(source: ViewModels.Collection, event: MouseEvent) {
public static create(source: ViewModels.Collection, _event: MouseEvent): void {
const id = useTabs.getState().getTabs(ViewModels.CollectionTabKind.Triggers).length + 1; const id = useTabs.getState().getTabs(ViewModels.CollectionTabKind.Triggers).length + 1;
const trigger = <StoredProcedureDefinition>{ const trigger = <StoredProcedureDefinition>{
id: "", id: "",
@@ -101,7 +99,7 @@ export default class Trigger {
} }
}; };
public delete(): void { public delete() {
useDialog.getState().showOkCancelModalDialog( useDialog.getState().showOkCancelModalDialog(
"Confirm delete", "Confirm delete",
"Are you sure you want to delete the trigger?", "Are you sure you want to delete the trigger?",
@@ -112,8 +110,7 @@ export default class Trigger {
useTabs.getState().closeTabsByComparator((tab) => tab.node && tab.node.rid === this.rid); useTabs.getState().closeTabsByComparator((tab) => tab.node && tab.node.rid === this.rid);
this.collection.children.remove(this); this.collection.children.remove(this);
}, },
// eslint-disable-next-line @typescript-eslint/no-empty-function (reason) => {}
() => {}
); );
}, },
"Cancel", "Cancel",

View File

@@ -1,9 +1,9 @@
import { Octokit } from "@octokit/rest"; import { Octokit } from "@octokit/rest";
import { HttpStatusCodes } from "../Common/Constants"; import { HttpStatusCodes } from "../Common/Constants";
import { getErrorMessage } from "../Common/ErrorHandlingUtils";
import * as Logger from "../Common/Logger"; import * as Logger from "../Common/Logger";
import * as UrlUtility from "../Common/UrlUtility"; import * as UrlUtility from "../Common/UrlUtility";
import { NotebookUtil } from "../Explorer/Notebook/NotebookUtil"; import { NotebookUtil } from "../Explorer/Notebook/NotebookUtil";
import { getErrorMessage } from "../Common/ErrorHandlingUtils";
export interface IGitHubPageInfo { export interface IGitHubPageInfo {
endCursor: string; endCursor: string;
@@ -225,7 +225,7 @@ export class GitHubClient {
private static readonly SelfErrorCode = 599; private static readonly SelfErrorCode = 599;
private ocktokit: Octokit; private ocktokit: Octokit;
constructor(private errorCallback: (error: any) => void) { constructor(private errorCallback: (error: Error) => void) {
this.initOctokit(); this.initOctokit();
} }
@@ -501,10 +501,11 @@ export class GitHubClient {
this.ocktokit = new Octokit({ this.ocktokit = new Octokit({
auth: token, auth: token,
log: { log: {
// eslint-disable-next-line @typescript-eslint/no-empty-function
debug: () => {}, debug: () => {},
info: (message?: any) => GitHubClient.log(Logger.logInfo, message), info: (message?: string) => GitHubClient.log(Logger.logInfo, message),
warn: (message?: any) => GitHubClient.log(Logger.logWarning, message), warn: (message?: string) => GitHubClient.log(Logger.logWarning, message),
error: (error?: any) => Logger.logError(getErrorMessage(error), "GitHubClient.Octokit"), error: (error?: Error) => Logger.logError(getErrorMessage(error), "GitHubClient.Octokit"),
}, },
}); });
@@ -514,7 +515,7 @@ export class GitHubClient {
}); });
} }
private static log(logger: (message: string, area: string) => void, message?: any) { private static log(logger: (message: string, area: string) => void, message?: string) {
if (message) { if (message) {
message = typeof message === "string" ? message : JSON.stringify(message); message = typeof message === "string" ? message : JSON.stringify(message);
logger(message, "GitHubClient.Octokit"); logger(message, "GitHubClient.Octokit");

View File

@@ -64,7 +64,7 @@ export class GitHubOAuthService {
return params.state; return params.state;
} }
public async finishOAuth(params: IGitHubConnectorParams): Promise<void> { public async finishOAuth(params: IGitHubConnectorParams) {
try { try {
this.validateState(params.state); this.validateState(params.state);
const response = await this.junoClient.getGitHubToken(params.code); const response = await this.junoClient.getGitHubToken(params.code);
@@ -113,7 +113,7 @@ export class GitHubOAuthService {
return this.state; return this.state;
} }
public resetToken(): void { public resetToken() {
this.token(undefined); this.token(undefined);
} }

View File

@@ -50,8 +50,7 @@ describe("Pinned repos", () => {
}); });
it("updatePinnedRepos invokes pinned repos subscribers", async () => { it("updatePinnedRepos invokes pinned repos subscribers", async () => {
// eslint-disable-next-line @typescript-eslint/no-empty-function const callback = jest.fn().mockImplementation((pinnedRepos: IPinnedRepo[]) => {});
const callback = jest.fn().mockImplementation(() => {});
junoClient.subscribeToPinnedRepos(callback); junoClient.subscribeToPinnedRepos(callback);
const response = await junoClient.updatePinnedRepos(samplePinnedRepos); const response = await junoClient.updatePinnedRepos(samplePinnedRepos);
@@ -61,8 +60,7 @@ describe("Pinned repos", () => {
}); });
it("getPinnedRepos invokes pinned repos subscribers", async () => { it("getPinnedRepos invokes pinned repos subscribers", async () => {
// eslint-disable-next-line @typescript-eslint/no-empty-function const callback = jest.fn().mockImplementation((pinnedRepos: IPinnedRepo[]) => {});
const callback = jest.fn().mockImplementation(() => {});
junoClient.subscribeToPinnedRepos(callback); junoClient.subscribeToPinnedRepos(callback);
const response = await junoClient.getPinnedRepos("scope"); const response = await junoClient.getPinnedRepos("scope");
@@ -155,7 +153,7 @@ describe("Gallery", () => {
it("getSampleNotebooks", async () => { it("getSampleNotebooks", async () => {
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.getSampleNotebooks(); const response = await junoClient.getSampleNotebooks();
@@ -167,7 +165,7 @@ describe("Gallery", () => {
it("getPublicNotebooks", async () => { it("getPublicNotebooks", async () => {
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.getPublicNotebooks(); const response = await junoClient.getPublicNotebooks();
@@ -180,7 +178,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.getNotebookInfo(id); const response = await junoClient.getNotebookInfo(id);
@@ -193,7 +191,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
text: () => undefined as undefined, text: () => undefined as any,
}); });
const response = await junoClient.getNotebookContent(id); const response = await junoClient.getNotebookContent(id);
@@ -206,7 +204,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.increaseNotebookViews(id); const response = await junoClient.increaseNotebookViews(id);
@@ -220,7 +218,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.increaseNotebookDownloadCount(id); const response = await junoClient.increaseNotebookDownloadCount(id);
@@ -245,7 +243,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.favoriteNotebook(id); const response = await junoClient.favoriteNotebook(id);
@@ -270,7 +268,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.unfavoriteNotebook(id); const response = await junoClient.unfavoriteNotebook(id);
@@ -294,7 +292,7 @@ describe("Gallery", () => {
it("getFavoriteNotebooks", async () => { it("getFavoriteNotebooks", async () => {
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.getFavoriteNotebooks(); const response = await junoClient.getFavoriteNotebooks();
@@ -317,7 +315,7 @@ describe("Gallery", () => {
it("getPublishedNotebooks", async () => { it("getPublishedNotebooks", async () => {
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.getPublishedNotebooks(); const response = await junoClient.getPublishedNotebooks();
@@ -341,7 +339,7 @@ describe("Gallery", () => {
const id = "id"; const id = "id";
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.deleteNotebook(id); const response = await junoClient.deleteNotebook(id);
@@ -371,7 +369,7 @@ describe("Gallery", () => {
const addLinkToNotebookViewer = true; const addLinkToNotebookViewer = true;
window.fetch = jest.fn().mockReturnValue({ window.fetch = jest.fn().mockReturnValue({
status: HttpStatusCodes.OK, status: HttpStatusCodes.OK,
json: () => undefined as undefined, json: () => undefined as any,
}); });
const response = await junoClient.publishNotebook(name, description, tags, thumbnailUrl, content); const response = await junoClient.publishNotebook(name, description, tags, thumbnailUrl, content);

View File

@@ -62,7 +62,7 @@ export interface IPublishNotebookRequest {
description: string; description: string;
tags: string[]; tags: string[];
thumbnailUrl: string; thumbnailUrl: string;
content: unknown; content: any;
addLinkToNotebookViewer: boolean; addLinkToNotebookViewer: boolean;
} }

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
if (window.parent !== window) { if (window.parent !== window) {
(window as any).__REACT_DEVTOOLS_GLOBAL_HOOK__ = (window.parent as any).__REACT_DEVTOOLS_GLOBAL_HOOK__; (window as any).__REACT_DEVTOOLS_GLOBAL_HOOK__ = (window.parent as any).__REACT_DEVTOOLS_GLOBAL_HOOK__;
} }

View File

@@ -30,7 +30,7 @@ describe("GalleryUtils", () => {
}); });
it("downloadItem shows dialog in data explorer", () => { it("downloadItem shows dialog in data explorer", () => {
const container = new Explorer(); const container = {} as Explorer;
GalleryUtils.downloadItem(container, undefined, galleryItem, undefined); GalleryUtils.downloadItem(container, undefined, galleryItem, undefined);
expect(useDialog.getState().visible).toBe(true); expect(useDialog.getState().visible).toBe(true);

View File

@@ -69,11 +69,7 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
if (tab.tabId === activeTab.tabId && tabIndex !== -1) { if (tab.tabId === activeTab.tabId && tabIndex !== -1) {
const tabToTheRight = updatedTabs[tabIndex]; const tabToTheRight = updatedTabs[tabIndex];
const lastOpenTab = updatedTabs[updatedTabs.length - 1]; const lastOpenTab = updatedTabs[updatedTabs.length - 1];
const newActiveTab = tabToTheRight ?? lastOpenTab; set({ activeTab: tabToTheRight || lastOpenTab });
set({ activeTab: newActiveTab });
if (newActiveTab) {
newActiveTab.onActivate();
}
} }
set({ openedTabs: updatedTabs }); set({ openedTabs: updatedTabs });

View File

@@ -15,13 +15,18 @@
"target": "es2017", "target": "es2017",
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"lib": ["es5", "es6", "dom"], "lib": [
"es5",
"es6",
"dom"
],
"jsx": "react", "jsx": "react",
"moduleResolution": "node", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"noEmit": true, "noEmit": true,
"types": ["jest"], "types": [
"baseUrl": "src" "jest"
]
}, },
"typedocOptions": { "typedocOptions": {
"entryPoints": [ "entryPoints": [
@@ -37,6 +42,11 @@
"includes": "./src/SelfServe/Documentation", "includes": "./src/SelfServe/Documentation",
"disableSources": true "disableSources": true
}, },
"include": ["src", "./src/**/*", "./utils/**/*"], "include": [
"exclude": ["./src/**/__mocks__/**/*"] "./src/**/*",
"./utils/**/*"
],
"exclude": [
"./src/**/__mocks__/**/*"
]
} }

View File

@@ -227,7 +227,6 @@ module.exports = function (_env = {}, argv = {}) {
rules, rules,
}, },
resolve: { resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"],
alias: { alias: {
process: "process/browser", process: "process/browser",
}, },